leistungsbilanz-ts/src/domain/models/distribution-board-feeder-circuit-project-command.model.ts

132 lines
5 KiB
TypeScript

import {
assertCircuitInsertProjectCommand,
circuitInsertCommandType,
circuitStructureCommandSchemaVersion,
type CircuitSnapshot,
} from "./circuit-structure-project-command.model.js";
import {
assertDistributionBoardUpdateProjectCommand,
type DistributionBoardUpdateProjectCommand,
} from "./distribution-board-project-command.model.js";
import type { SerializedProjectCommand } from "./project-command.model.js";
export const distributionBoardCreateFeederCircuitCommandType =
"distribution-board.create-feeder-circuit" as const;
export const distributionBoardRemoveFeederCircuitCommandType =
"distribution-board.remove-feeder-circuit" as const;
export const distributionBoardFeederCircuitCommandSchemaVersion = 1 as const;
export interface DistributionBoardFeederCircuitCommandPayload {
circuit: CircuitSnapshot;
boardUpdate: DistributionBoardUpdateProjectCommand;
}
export interface DistributionBoardCreateFeederCircuitProjectCommand
extends SerializedProjectCommand<DistributionBoardFeederCircuitCommandPayload> {
schemaVersion: typeof distributionBoardFeederCircuitCommandSchemaVersion;
type: typeof distributionBoardCreateFeederCircuitCommandType;
}
export interface DistributionBoardRemoveFeederCircuitProjectCommand
extends SerializedProjectCommand<DistributionBoardFeederCircuitCommandPayload> {
schemaVersion: typeof distributionBoardFeederCircuitCommandSchemaVersion;
type: typeof distributionBoardRemoveFeederCircuitCommandType;
}
export type DistributionBoardFeederCircuitProjectCommand =
| DistributionBoardCreateFeederCircuitProjectCommand
| DistributionBoardRemoveFeederCircuitProjectCommand;
export function createDistributionBoardCreateFeederCircuitProjectCommand(
circuit: CircuitSnapshot,
boardUpdate: DistributionBoardUpdateProjectCommand
): DistributionBoardCreateFeederCircuitProjectCommand {
const command: DistributionBoardCreateFeederCircuitProjectCommand = {
schemaVersion: distributionBoardFeederCircuitCommandSchemaVersion,
type: distributionBoardCreateFeederCircuitCommandType,
payload: { circuit, boardUpdate },
};
assertDistributionBoardFeederCircuitProjectCommand(command);
return command;
}
export function createDistributionBoardRemoveFeederCircuitProjectCommand(
circuit: CircuitSnapshot,
boardUpdate: DistributionBoardUpdateProjectCommand
): DistributionBoardRemoveFeederCircuitProjectCommand {
const command: DistributionBoardRemoveFeederCircuitProjectCommand = {
schemaVersion: distributionBoardFeederCircuitCommandSchemaVersion,
type: distributionBoardRemoveFeederCircuitCommandType,
payload: { circuit, boardUpdate },
};
assertDistributionBoardFeederCircuitProjectCommand(command);
return command;
}
export function assertDistributionBoardFeederCircuitProjectCommand(
command: SerializedProjectCommand<unknown>
): asserts command is DistributionBoardFeederCircuitProjectCommand {
if (
command.schemaVersion !==
distributionBoardFeederCircuitCommandSchemaVersion ||
(command.type !== distributionBoardCreateFeederCircuitCommandType &&
command.type !== distributionBoardRemoveFeederCircuitCommandType) ||
!isPlainObject(command.payload)
) {
throw new Error("Unsupported distribution-board feeder-circuit command.");
}
const { circuit, boardUpdate } = command.payload;
if (!isPlainObject(boardUpdate)) {
throw new Error("Feeder-circuit command requires a board update.");
}
assertCircuitInsertProjectCommand({
schemaVersion: circuitStructureCommandSchemaVersion,
type: circuitInsertCommandType,
payload: { circuit },
});
const boardUpdateCommand =
boardUpdate as unknown as SerializedProjectCommand<unknown>;
assertDistributionBoardUpdateProjectCommand(boardUpdateCommand);
const typedCircuit = circuit as CircuitSnapshot;
const typedBoardUpdate: DistributionBoardUpdateProjectCommand =
boardUpdateCommand;
if (typedCircuit.deviceRows.length !== 0 || !typedCircuit.isReserve) {
throw new Error(
"A generated feeder circuit must be empty before the board load is linked."
);
}
const feedingBoard = getChangeValue(
typedBoardUpdate,
"feedingDistributionBoardId"
);
const feedingCircuit = getChangeValue(
typedBoardUpdate,
"feedingCircuitId"
);
if (feedingBoard === undefined || feedingCircuit === undefined) {
throw new Error(
"Feeder-circuit commands must update both logical feeding references."
);
}
if (
command.type === distributionBoardCreateFeederCircuitCommandType &&
(typeof feedingBoard !== "string" || feedingCircuit !== typedCircuit.id)
) {
throw new Error(
"The created feeder circuit must be linked by the distribution-board update."
);
}
}
function getChangeValue(
command: DistributionBoardUpdateProjectCommand,
field: "feedingDistributionBoardId" | "feedingCircuitId"
) {
return command.payload.changes.find((change) => change.field === field)?.value;
}
function isPlainObject(value: unknown): value is Record<string, unknown> {
return value !== null && typeof value === "object" && !Array.isArray(value);
}