Add logical distribution board feed links

This commit is contained in:
Julian Appel 2026-09-27 22:21:58 +02:00
parent b50c00c0ac
commit b893c72534
23 changed files with 3732 additions and 45 deletions

View file

@ -325,6 +325,16 @@ export class DistributionBoardStructureProjectCommandRepository
patch.supplyType
);
}
this.assertFeedingReference(database, input.projectId, current.id, {
feedingDistributionBoardId:
patch.feedingDistributionBoardId === undefined
? current.feedingDistributionBoardId
: patch.feedingDistributionBoardId,
feedingCircuitId:
patch.feedingCircuitId === undefined
? current.feedingCircuitId
: patch.feedingCircuitId,
});
const inversePatch = Object.fromEntries(
input.command.payload.changes.map((change) => [
change.field,
@ -333,7 +343,8 @@ export class DistributionBoardStructureProjectCommandRepository
) as DistributionBoardUpdatePatch;
const inverse = createDistributionBoardUpdateProjectCommand(
current.id,
inversePatch
inversePatch,
input.command.schemaVersion
);
const updated = database
.update(distributionBoards)
@ -352,6 +363,77 @@ export class DistributionBoardStructureProjectCommandRepository
}
return inverse;
}
private assertFeedingReference(
database: AppDatabase,
projectId: string,
distributionBoardId: string,
reference: {
feedingDistributionBoardId: string | null;
feedingCircuitId: string | null;
}
) {
const { feedingDistributionBoardId, feedingCircuitId } = reference;
if (feedingDistributionBoardId === null) {
if (feedingCircuitId !== null) {
throw new Error(
"Ein speisender Stromkreis erfordert eine speisende Verteilung."
);
}
return;
}
if (feedingDistributionBoardId === distributionBoardId) {
throw new Error("Eine Verteilung kann sich nicht selbst speisen.");
}
const projectBoards = database
.select({
id: distributionBoards.id,
feedingDistributionBoardId:
distributionBoards.feedingDistributionBoardId,
})
.from(distributionBoards)
.where(eq(distributionBoards.projectId, projectId))
.all();
const boardById = new Map(projectBoards.map((board) => [board.id, board]));
if (!boardById.has(feedingDistributionBoardId)) {
throw new Error(
"Die speisende Verteilung gehört nicht zum Projekt."
);
}
const visited = new Set<string>([distributionBoardId]);
let currentId: string | null = feedingDistributionBoardId;
while (currentId !== null) {
if (visited.has(currentId)) {
throw new Error("Die Einspeisungsverknüpfung würde einen Zyklus erzeugen.");
}
visited.add(currentId);
currentId = boardById.get(currentId)?.feedingDistributionBoardId ?? null;
}
if (feedingCircuitId === null) {
return;
}
const feedingCircuit = database
.select({
projectId: circuitLists.projectId,
distributionBoardId: circuitLists.distributionBoardId,
})
.from(circuits)
.innerJoin(
circuitLists,
eq(circuitLists.id, circuits.circuitListId)
)
.where(eq(circuits.id, feedingCircuitId))
.get();
if (
!feedingCircuit ||
feedingCircuit.projectId !== projectId ||
feedingCircuit.distributionBoardId !== feedingDistributionBoardId
) {
throw new Error(
"Der speisende Stromkreis gehört nicht zur gewählten Verteilung."
);
}
}
}
function assertSupplyTypeEnabled(
@ -392,11 +474,20 @@ function structureMatches(
location,
fedFrom,
remark,
feedingDistributionBoardId,
feedingCircuitId,
...actualDistributionBoard
} = actual.board;
if (
simultaneityFactor !== 1 ||
[boardNumber, location, fedFrom, remark].some((value) => value !== null) ||
[
boardNumber,
location,
fedFrom,
remark,
feedingDistributionBoardId,
feedingCircuitId,
].some((value) => value !== null) ||
!sameRecord(
expected.distributionBoard,
actualDistributionBoard