Create protected board defaults
This commit is contained in:
@@ -3,6 +3,15 @@ import {
|
||||
distributionBoardSupplyTypes,
|
||||
type DistributionBoardSupplyType,
|
||||
} from "../../shared/constants/distribution-board.js";
|
||||
import {
|
||||
defaultMainSwitchComponent,
|
||||
defaultSurgeProtectiveDeviceComponent,
|
||||
} from "../../shared/constants/distribution-board-component.js";
|
||||
import type { CircuitGroupCategory } from "../../shared/constants/circuit-group.js";
|
||||
import type {
|
||||
DistributionBoardComponentPlacement,
|
||||
DistributionBoardComponentRole,
|
||||
} from "../../shared/constants/distribution-board-component.js";
|
||||
import type { SerializedProjectCommand } from "./project-command.model.js";
|
||||
|
||||
export const distributionBoardInsertCommandType =
|
||||
@@ -10,9 +19,10 @@ export const distributionBoardInsertCommandType =
|
||||
export const distributionBoardDeleteCommandType =
|
||||
"distribution-board.delete" as const;
|
||||
export const legacyDistributionBoardStructureCommandSchemaVersion = 1 as const;
|
||||
export const distributionBoardStructureCommandSchemaVersion = 2 as const;
|
||||
export const previousDistributionBoardStructureCommandSchemaVersion = 2 as const;
|
||||
export const distributionBoardStructureCommandSchemaVersion = 3 as const;
|
||||
|
||||
export const defaultCircuitSectionDefinitions = [
|
||||
const legacyDefaultCircuitSectionDefinitions = [
|
||||
{
|
||||
key: "lighting",
|
||||
displayName: "Lighting",
|
||||
@@ -39,6 +49,33 @@ export const defaultCircuitSectionDefinitions = [
|
||||
},
|
||||
] as const;
|
||||
|
||||
export const defaultCircuitSectionDefinitions = [
|
||||
{
|
||||
key: "lighting",
|
||||
displayName: "Beleuchtung 1",
|
||||
prefix: "-1F1.",
|
||||
sortOrder: 10,
|
||||
category: "lighting",
|
||||
groupNumber: 1,
|
||||
},
|
||||
{
|
||||
key: "single_phase",
|
||||
displayName: "1-phasig 1",
|
||||
prefix: "-2F1.",
|
||||
sortOrder: 20,
|
||||
category: "single_phase",
|
||||
groupNumber: 1,
|
||||
},
|
||||
{
|
||||
key: "three_phase",
|
||||
displayName: "3-phasig 1",
|
||||
prefix: "-3F1.",
|
||||
sortOrder: 30,
|
||||
category: "three_phase",
|
||||
groupNumber: 1,
|
||||
},
|
||||
] as const;
|
||||
|
||||
interface LegacyDistributionBoardStructureSnapshot {
|
||||
distributionBoard: {
|
||||
id: string;
|
||||
@@ -46,7 +83,22 @@ interface LegacyDistributionBoardStructureSnapshot {
|
||||
name: string;
|
||||
};
|
||||
circuitList: DistributionBoardStructureSnapshot["circuitList"];
|
||||
sections: DistributionBoardStructureSnapshot["sections"];
|
||||
sections: LegacyCircuitSectionSnapshot[];
|
||||
}
|
||||
|
||||
interface PreviousDistributionBoardStructureSnapshot {
|
||||
distributionBoard: DistributionBoardStructureSnapshot["distributionBoard"];
|
||||
circuitList: DistributionBoardStructureSnapshot["circuitList"];
|
||||
sections: LegacyCircuitSectionSnapshot[];
|
||||
}
|
||||
|
||||
interface LegacyCircuitSectionSnapshot {
|
||||
id: string;
|
||||
circuitListId: string;
|
||||
key: string;
|
||||
displayName: string;
|
||||
prefix: string;
|
||||
sortOrder: number;
|
||||
}
|
||||
|
||||
export interface DistributionBoardStructureSnapshot {
|
||||
@@ -70,7 +122,31 @@ export interface DistributionBoardStructureSnapshot {
|
||||
displayName: string;
|
||||
prefix: string;
|
||||
sortOrder: number;
|
||||
category: CircuitGroupCategory;
|
||||
groupNumber: number;
|
||||
}>;
|
||||
components: Array<{
|
||||
id: string;
|
||||
circuitListId: string;
|
||||
sectionId: null;
|
||||
equipmentIdentifier: string;
|
||||
name: string;
|
||||
role: DistributionBoardComponentRole;
|
||||
placement: DistributionBoardComponentPlacement;
|
||||
sortOrder: number;
|
||||
}>;
|
||||
}
|
||||
|
||||
export interface NormalizedDistributionBoardStructureSnapshot {
|
||||
distributionBoard: DistributionBoardStructureSnapshot["distributionBoard"];
|
||||
circuitList: DistributionBoardStructureSnapshot["circuitList"];
|
||||
sections: Array<
|
||||
LegacyCircuitSectionSnapshot & {
|
||||
category: CircuitGroupCategory | null;
|
||||
groupNumber: number | null;
|
||||
}
|
||||
>;
|
||||
components: DistributionBoardStructureSnapshot["components"];
|
||||
}
|
||||
|
||||
interface DistributionBoardStructureCommandPayload<
|
||||
@@ -97,6 +173,16 @@ interface LegacyDistributionBoardStructureProjectCommand
|
||||
| typeof distributionBoardDeleteCommandType;
|
||||
}
|
||||
|
||||
interface PreviousDistributionBoardStructureProjectCommand
|
||||
extends SerializedProjectCommand<
|
||||
DistributionBoardStructureCommandPayload<PreviousDistributionBoardStructureSnapshot>
|
||||
> {
|
||||
schemaVersion: typeof previousDistributionBoardStructureCommandSchemaVersion;
|
||||
type:
|
||||
| typeof distributionBoardInsertCommandType
|
||||
| typeof distributionBoardDeleteCommandType;
|
||||
}
|
||||
|
||||
export interface DistributionBoardInsertProjectCommand
|
||||
extends CurrentDistributionBoardStructureProjectCommand {
|
||||
type: typeof distributionBoardInsertCommandType;
|
||||
@@ -110,6 +196,7 @@ export interface DistributionBoardDeleteProjectCommand
|
||||
export type DistributionBoardStructureProjectCommand =
|
||||
| DistributionBoardInsertProjectCommand
|
||||
| DistributionBoardDeleteProjectCommand
|
||||
| PreviousDistributionBoardStructureProjectCommand
|
||||
| LegacyDistributionBoardStructureProjectCommand;
|
||||
|
||||
export function createDistributionBoardStructureSnapshot(
|
||||
@@ -143,6 +230,22 @@ export function createDistributionBoardStructureSnapshot(
|
||||
circuitListId: structureId,
|
||||
...section,
|
||||
})),
|
||||
components: [
|
||||
{
|
||||
id: crypto.randomUUID(),
|
||||
circuitListId: structureId,
|
||||
sectionId: null,
|
||||
...defaultMainSwitchComponent,
|
||||
sortOrder: 10,
|
||||
},
|
||||
{
|
||||
id: crypto.randomUUID(),
|
||||
circuitListId: structureId,
|
||||
sectionId: null,
|
||||
...defaultSurgeProtectiveDeviceComponent,
|
||||
sortOrder: 20,
|
||||
},
|
||||
],
|
||||
};
|
||||
assertDistributionBoardStructureSnapshot(structure);
|
||||
return structure;
|
||||
@@ -192,32 +295,71 @@ export function assertDistributionBoardDeleteProjectCommand(
|
||||
|
||||
export function normalizeDistributionBoardStructureProjectCommand(
|
||||
command: DistributionBoardStructureProjectCommand
|
||||
): DistributionBoardInsertProjectCommand | DistributionBoardDeleteProjectCommand {
|
||||
): NormalizedDistributionBoardStructureSnapshot {
|
||||
if (
|
||||
command.schemaVersion ===
|
||||
legacyDistributionBoardStructureCommandSchemaVersion
|
||||
) {
|
||||
const structure: DistributionBoardStructureSnapshot = {
|
||||
...command.payload.structure,
|
||||
return {
|
||||
distributionBoard: {
|
||||
...command.payload.structure.distributionBoard,
|
||||
floorId: null,
|
||||
supplyType: null,
|
||||
},
|
||||
circuitList: command.payload.structure.circuitList,
|
||||
sections: command.payload.structure.sections.map(
|
||||
normalizeLegacySection
|
||||
),
|
||||
components: [],
|
||||
};
|
||||
return command.type === distributionBoardInsertCommandType
|
||||
? createDistributionBoardInsertProjectCommand(structure)
|
||||
: createDistributionBoardDeleteProjectCommand(structure);
|
||||
}
|
||||
return command as
|
||||
| DistributionBoardInsertProjectCommand
|
||||
| DistributionBoardDeleteProjectCommand;
|
||||
if (
|
||||
command.schemaVersion ===
|
||||
previousDistributionBoardStructureCommandSchemaVersion
|
||||
) {
|
||||
return {
|
||||
...command.payload.structure,
|
||||
sections: command.payload.structure.sections.map(
|
||||
normalizeLegacySection
|
||||
),
|
||||
components: [],
|
||||
};
|
||||
}
|
||||
return command.payload.structure;
|
||||
}
|
||||
|
||||
export function invertDistributionBoardStructureProjectCommand(
|
||||
command: DistributionBoardStructureProjectCommand
|
||||
): DistributionBoardStructureProjectCommand {
|
||||
return {
|
||||
...command,
|
||||
type:
|
||||
command.type === distributionBoardInsertCommandType
|
||||
? distributionBoardDeleteCommandType
|
||||
: distributionBoardInsertCommandType,
|
||||
} as DistributionBoardStructureProjectCommand;
|
||||
}
|
||||
|
||||
function normalizeLegacySection(
|
||||
section: LegacyCircuitSectionSnapshot
|
||||
): NormalizedDistributionBoardStructureSnapshot["sections"][number] {
|
||||
const category =
|
||||
section.key === "lighting" ||
|
||||
section.key === "single_phase" ||
|
||||
section.key === "three_phase"
|
||||
? section.key
|
||||
: null;
|
||||
return {
|
||||
...section,
|
||||
category,
|
||||
groupNumber: category === null ? null : 1,
|
||||
};
|
||||
}
|
||||
|
||||
export function assertDistributionBoardStructureSnapshot(
|
||||
structure: unknown
|
||||
): asserts structure is DistributionBoardStructureSnapshot {
|
||||
assertDistributionBoardStructureSnapshotVersion(structure, false);
|
||||
assertDistributionBoardStructureSnapshotVersion(structure, "current");
|
||||
}
|
||||
|
||||
function assertDistributionBoardStructureProjectCommand(
|
||||
@@ -239,36 +381,57 @@ function assertDistributionBoardStructureProjectCommand(
|
||||
) {
|
||||
assertDistributionBoardStructureSnapshotVersion(
|
||||
command.payload.structure,
|
||||
true
|
||||
"legacy"
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (
|
||||
command.schemaVersion !== distributionBoardStructureCommandSchemaVersion
|
||||
command.schemaVersion ===
|
||||
previousDistributionBoardStructureCommandSchemaVersion
|
||||
) {
|
||||
assertDistributionBoardStructureSnapshotVersion(
|
||||
command.payload.structure,
|
||||
"previous"
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (
|
||||
command.schemaVersion !==
|
||||
distributionBoardStructureCommandSchemaVersion
|
||||
) {
|
||||
throw new Error("Unsupported distribution-board structure command.");
|
||||
}
|
||||
assertDistributionBoardStructureSnapshotVersion(
|
||||
command.payload.structure,
|
||||
false
|
||||
"current"
|
||||
);
|
||||
}
|
||||
|
||||
function assertDistributionBoardStructureSnapshotVersion(
|
||||
structure: unknown,
|
||||
legacy: boolean
|
||||
version: "legacy" | "previous" | "current"
|
||||
) {
|
||||
if (!isPlainObject(structure) || Object.keys(structure).length !== 3) {
|
||||
const current = version === "current";
|
||||
if (
|
||||
!isPlainObject(structure) ||
|
||||
Object.keys(structure).length !== (current ? 4 : 3)
|
||||
) {
|
||||
throw new Error("Distribution-board structure is invalid.");
|
||||
}
|
||||
const { distributionBoard, circuitList, sections } = structure;
|
||||
const { distributionBoard, circuitList, sections, components } =
|
||||
structure;
|
||||
const expectedSections = current
|
||||
? defaultCircuitSectionDefinitions
|
||||
: legacyDefaultCircuitSectionDefinitions;
|
||||
if (
|
||||
!isPlainObject(distributionBoard) ||
|
||||
Object.keys(distributionBoard).length !== (legacy ? 3 : 5) ||
|
||||
Object.keys(distributionBoard).length !==
|
||||
(version === "legacy" ? 3 : 5) ||
|
||||
!isPlainObject(circuitList) ||
|
||||
Object.keys(circuitList).length !== 4 ||
|
||||
!Array.isArray(sections) ||
|
||||
sections.length !== defaultCircuitSectionDefinitions.length
|
||||
sections.length !== expectedSections.length ||
|
||||
(current && (!Array.isArray(components) || components.length !== 2))
|
||||
) {
|
||||
throw new Error("Distribution-board structure is incomplete.");
|
||||
}
|
||||
@@ -278,7 +441,7 @@ function assertDistributionBoardStructureSnapshotVersion(
|
||||
`distributionBoard.${field}`
|
||||
);
|
||||
}
|
||||
if (!legacy) {
|
||||
if (version !== "legacy") {
|
||||
assertNullableId(distributionBoard.floorId, "distributionBoard.floorId");
|
||||
assertNullableSupplyType(distributionBoard.supplyType);
|
||||
}
|
||||
@@ -296,8 +459,11 @@ function assertDistributionBoardStructureSnapshotVersion(
|
||||
const sectionIds = new Set<string>();
|
||||
for (let index = 0; index < sections.length; index += 1) {
|
||||
const section = sections[index];
|
||||
const expected = defaultCircuitSectionDefinitions[index];
|
||||
if (!isPlainObject(section) || Object.keys(section).length !== 6) {
|
||||
const expected = expectedSections[index];
|
||||
if (
|
||||
!isPlainObject(section) ||
|
||||
Object.keys(section).length !== (current ? 8 : 6)
|
||||
) {
|
||||
throw new Error("Default circuit section is invalid.");
|
||||
}
|
||||
assertNonEmptyString(section.id, "section.id");
|
||||
@@ -310,13 +476,64 @@ function assertDistributionBoardStructureSnapshotVersion(
|
||||
section.key !== expected.key ||
|
||||
section.displayName !== expected.displayName ||
|
||||
section.prefix !== expected.prefix ||
|
||||
section.sortOrder !== expected.sortOrder
|
||||
section.sortOrder !== expected.sortOrder ||
|
||||
(current &&
|
||||
(!("category" in expected) ||
|
||||
section.category !== expected.category ||
|
||||
section.groupNumber !== expected.groupNumber))
|
||||
) {
|
||||
throw new Error(
|
||||
"Distribution-board structure has invalid default sections."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (current) {
|
||||
assertDefaultComponents(components, circuitList.id);
|
||||
}
|
||||
}
|
||||
|
||||
function assertDefaultComponents(
|
||||
components: unknown,
|
||||
circuitListId: unknown
|
||||
) {
|
||||
if (!Array.isArray(components)) {
|
||||
throw new Error("Default distribution-board components are invalid.");
|
||||
}
|
||||
const expectedComponents = [
|
||||
{ ...defaultMainSwitchComponent, sortOrder: 10 },
|
||||
{ ...defaultSurgeProtectiveDeviceComponent, sortOrder: 20 },
|
||||
];
|
||||
const componentIds = new Set<string>();
|
||||
for (let index = 0; index < expectedComponents.length; index += 1) {
|
||||
const component = components[index];
|
||||
const expected = expectedComponents[index];
|
||||
if (!isPlainObject(component) || Object.keys(component).length !== 8) {
|
||||
throw new Error(
|
||||
"Default distribution-board component is invalid."
|
||||
);
|
||||
}
|
||||
assertNonEmptyString(component.id, "component.id");
|
||||
if (componentIds.has(component.id)) {
|
||||
throw new Error(
|
||||
"Default distribution-board component ids must be unique."
|
||||
);
|
||||
}
|
||||
componentIds.add(component.id);
|
||||
if (
|
||||
component.circuitListId !== circuitListId ||
|
||||
component.sectionId !== null ||
|
||||
component.equipmentIdentifier !== expected.equipmentIdentifier ||
|
||||
component.name !== expected.name ||
|
||||
component.role !== expected.role ||
|
||||
component.placement !== expected.placement ||
|
||||
component.sortOrder !== expected.sortOrder
|
||||
) {
|
||||
throw new Error(
|
||||
"Distribution-board structure has invalid default components."
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function assertNullableId(value: unknown, field: string) {
|
||||
|
||||
Reference in New Issue
Block a user