Create feeder circuits while linking boards

This commit is contained in:
Julian Appel 2026-09-28 22:14:30 +02:00
parent 552362bad1
commit ade21fe386
11 changed files with 960 additions and 40 deletions

View file

@ -1,4 +1,5 @@
import { and, asc, eq, inArray } from "drizzle-orm";
import { isDeepStrictEqual } from "node:util";
import {
assertDistributionBoardDeleteProjectCommand,
assertDistributionBoardInsertProjectCommand,
@ -17,6 +18,20 @@ import {
type DistributionBoardUpdateProjectCommand,
type DistributionBoardUpdateValues,
} from "../../domain/models/distribution-board-project-command.model.js";
import {
assertDistributionBoardFeederCircuitProjectCommand,
createDistributionBoardCreateFeederCircuitProjectCommand,
createDistributionBoardRemoveFeederCircuitProjectCommand,
distributionBoardCreateFeederCircuitCommandType,
distributionBoardRemoveFeederCircuitCommandType,
type DistributionBoardFeederCircuitProjectCommand,
} from "../../domain/models/distribution-board-feeder-circuit-project-command.model.js";
import {
circuitDeleteCommandType,
circuitInsertCommandType,
createCircuitDeleteProjectCommand,
createCircuitInsertProjectCommand,
} from "../../domain/models/circuit-structure-project-command.model.js";
import type {
DistributionBoardStructureProjectCommandStore,
ExecuteDistributionBoardStructureCommandInput,
@ -31,6 +46,7 @@ import { floors } from "../schema/floors.js";
import { projects } from "../schema/projects.js";
import { executeProjectCommandTransaction } from "./project-command-transaction.persistence.js";
import { assertBoardsAreNotReferencedAsFeeders } from "./distribution-board-feeding-deletion-guard.persistence.js";
import { CircuitStructureProjectCommandRepository } from "./circuit-structure-project-command.repository.js";
export class DistributionBoardStructureProjectCommandRepository
implements DistributionBoardStructureProjectCommandStore
@ -62,6 +78,30 @@ export class DistributionBoardStructureProjectCommandRepository
);
}
executeFeederCircuit(
input: Omit<
ExecuteDistributionBoardStructureCommandInput,
"command"
> & {
command: DistributionBoardFeederCircuitProjectCommand;
}
) {
assertDistributionBoardFeederCircuitProjectCommand(input.command);
if (
input.source === "user" &&
input.command.type === distributionBoardRemoveFeederCircuitCommandType
) {
throw new Error(
"Generated feeder circuits may only be removed through project history."
);
}
return executeProjectCommandTransaction(
this.database,
input,
(tx) => this.applyFeederCircuitCommand(tx, input)
);
}
private applyCommand(
database: AppDatabase,
projectId: string,
@ -367,6 +407,64 @@ export class DistributionBoardStructureProjectCommandRepository
return inverse;
}
private applyFeederCircuitCommand(
database: AppDatabase,
input: Omit<
ExecuteDistributionBoardStructureCommandInput,
"command"
> & {
command: DistributionBoardFeederCircuitProjectCommand;
}
): DistributionBoardFeederCircuitProjectCommand {
const circuitRepository =
new CircuitStructureProjectCommandRepository(database);
const { circuit, boardUpdate } = input.command.payload;
if (
input.command.type === distributionBoardCreateFeederCircuitCommandType
) {
const circuitInverse = circuitRepository.applyInTransaction(
database,
input.projectId,
input.source,
createCircuitInsertProjectCommand(circuit)
);
if (circuitInverse.type !== circuitDeleteCommandType) {
throw new Error("Created feeder circuit returned an invalid inverse.");
}
const boardInverse = this.update(database, {
...input,
command: boardUpdate,
});
return createDistributionBoardRemoveFeederCircuitProjectCommand(
circuit,
boardInverse
);
}
const boardInverse = this.update(database, {
...input,
command: boardUpdate,
});
const circuitInverse = circuitRepository.applyInTransaction(
database,
input.projectId,
input.source,
createCircuitDeleteProjectCommand(circuit.id, circuit.circuitListId)
);
if (
circuitInverse.type !== circuitInsertCommandType ||
!isDeepStrictEqual(circuitInverse.payload.circuit, circuit)
) {
throw new Error(
"Generated feeder circuit changed before history removal."
);
}
return createDistributionBoardCreateFeederCircuitProjectCommand(
circuit,
boardInverse
);
}
private assertFeedingReference(
database: AppDatabase,
projectId: string,