forked from jappel/leistungsbilanz-ts
Documentation
This commit is contained in:
parent
b1e19a88d5
commit
7580ad0ade
11 changed files with 584 additions and 1 deletions
|
|
@ -39,6 +39,7 @@ export class CircuitWriteService {
|
|||
this.numberingService = deps?.numberingService ?? new CircuitNumberingService();
|
||||
}
|
||||
|
||||
// Ensures writes never connect a section to the wrong circuit list.
|
||||
private async assertSectionInList(sectionId: string, circuitListId: string) {
|
||||
const section = await this.circuitSectionRepository.findById(sectionId);
|
||||
if (!section) {
|
||||
|
|
@ -50,6 +51,7 @@ export class CircuitWriteService {
|
|||
return section;
|
||||
}
|
||||
|
||||
// Enforces BMK uniqueness inside one circuit list.
|
||||
private async assertUniqueEquipmentIdentifier(
|
||||
circuitListId: string,
|
||||
equipmentIdentifier: string,
|
||||
|
|
@ -65,6 +67,7 @@ export class CircuitWriteService {
|
|||
}
|
||||
}
|
||||
|
||||
// Validates linked project-device id against owning project of the circuit list.
|
||||
private async assertValidLinkedProjectDevice(circuitId: string, linkedProjectDeviceId?: string) {
|
||||
if (!linkedProjectDeviceId) {
|
||||
return;
|
||||
|
|
@ -184,6 +187,7 @@ export class CircuitWriteService {
|
|||
overriddenFields: input.overriddenFields,
|
||||
});
|
||||
|
||||
// Reserve circuits become active as soon as at least one device row exists.
|
||||
if (Boolean(circuit.isReserve)) {
|
||||
await this.circuitRepository.update(circuit.id, {
|
||||
sectionId: circuit.sectionId,
|
||||
|
|
@ -247,6 +251,7 @@ export class CircuitWriteService {
|
|||
}
|
||||
await this.deviceRowRepository.delete(rowId);
|
||||
const remaining = await this.deviceRowRepository.countByCircuit(current.circuitId);
|
||||
// When last row is removed, keep circuit and mark it reserve instead of deleting it.
|
||||
if (remaining === 0) {
|
||||
await this.circuitRepository.update(circuit.id, {
|
||||
sectionId: circuit.sectionId,
|
||||
|
|
@ -287,6 +292,7 @@ export class CircuitWriteService {
|
|||
throw new Error("Invalid target circuit id.");
|
||||
}
|
||||
|
||||
// Placeholder-target move creates a new circuit explicitly; no implicit renumbering of others.
|
||||
if (!targetCircuit) {
|
||||
if (!input.targetSectionId || !input.createNewCircuit) {
|
||||
throw new Error("Invalid move target.");
|
||||
|
|
@ -321,6 +327,7 @@ export class CircuitWriteService {
|
|||
await this.deviceRowRepository.moveToCircuit(rowId, targetCircuit.id, (targetCount + 1) * 10);
|
||||
|
||||
const sourceRemaining = await this.deviceRowRepository.countByCircuit(sourceCircuit.id);
|
||||
// Source circuit becomes reserve when all rows are moved away.
|
||||
if (sourceRemaining === 0) {
|
||||
await this.circuitRepository.update(sourceCircuit.id, {
|
||||
sectionId: sourceCircuit.sectionId,
|
||||
|
|
@ -342,6 +349,7 @@ export class CircuitWriteService {
|
|||
});
|
||||
}
|
||||
|
||||
// Target circuit is no longer reserve once it receives moved rows.
|
||||
if (Boolean(targetCircuit.isReserve)) {
|
||||
await this.circuitRepository.update(targetCircuit.id, {
|
||||
sectionId: targetCircuit.sectionId,
|
||||
|
|
@ -367,6 +375,8 @@ export class CircuitWriteService {
|
|||
}
|
||||
|
||||
async moveDeviceRowsBulk(input: MoveCircuitDeviceRowsBulkInput) {
|
||||
// Bulk move keeps input order and resolves all source circuits first so undo can
|
||||
// restore per-source assignment deterministically.
|
||||
const uniqueRowIds = [...new Set(input.rowIds)];
|
||||
if (uniqueRowIds.length === 0) {
|
||||
throw new Error("No device rows provided.");
|
||||
|
|
@ -400,6 +410,7 @@ export class CircuitWriteService {
|
|||
throw new Error("Invalid target circuit id.");
|
||||
}
|
||||
|
||||
// Bulk placeholder move creates exactly one new circuit as common target.
|
||||
if (!targetCircuit) {
|
||||
if (!input.targetSectionId || !input.createNewCircuit) {
|
||||
throw new Error("Invalid move target.");
|
||||
|
|
@ -423,6 +434,7 @@ export class CircuitWriteService {
|
|||
}
|
||||
}
|
||||
|
||||
// Any source circuit emptied by bulk move is preserved as reserve circuit.
|
||||
for (const sourceCircuit of sourceCircuits.values()) {
|
||||
if (sourceCircuit.circuitListId !== targetCircuit.circuitListId) {
|
||||
throw new Error("All moved rows must belong to same circuit list as target.");
|
||||
|
|
@ -493,6 +505,8 @@ export class CircuitWriteService {
|
|||
}
|
||||
|
||||
async renumberSection(sectionId: string) {
|
||||
// Explicit renumber operation for one section only.
|
||||
// Never renumbers other sections and never runs implicitly during move/sort operations.
|
||||
const section = await this.circuitSectionRepository.findById(sectionId);
|
||||
if (!section) {
|
||||
throw new Error("Invalid section id.");
|
||||
|
|
@ -514,6 +528,7 @@ export class CircuitWriteService {
|
|||
finalAssignments.push({ id: circuit.id, equipmentIdentifier: candidate });
|
||||
index += 1;
|
||||
}
|
||||
// Uses safe two-phase identifier update to avoid UNIQUE collisions during swaps.
|
||||
await this.circuitRepository.updateEquipmentIdentifiersSafely(
|
||||
section.circuitListId,
|
||||
finalAssignments,
|
||||
|
|
@ -551,6 +566,7 @@ export class CircuitWriteService {
|
|||
}
|
||||
|
||||
async reorderCircuitsInSection(sectionId: string, input: ReorderSectionCircuitsInput) {
|
||||
// Reorder updates sortOrder only. BMKs remain unchanged; users may renumber explicitly later.
|
||||
const section = await this.circuitSectionRepository.findById(sectionId);
|
||||
if (!section) {
|
||||
throw new Error("Invalid section id.");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue