Derive device voltages from project settings
This commit is contained in:
@@ -58,6 +58,8 @@ export interface CircuitTreeSectionBlock {
|
||||
export interface CircuitTreeResponse {
|
||||
circuitListId: string;
|
||||
currentRevision: number;
|
||||
singlePhaseVoltageV: number;
|
||||
threePhaseVoltageV: number;
|
||||
sections: CircuitTreeSectionBlock[];
|
||||
}
|
||||
|
||||
|
||||
@@ -3,11 +3,16 @@ import {
|
||||
defaultDistributionBoardSupplyTypes,
|
||||
distributionBoardSupplyTypes,
|
||||
} from "../../shared/constants/distribution-board.js";
|
||||
import {
|
||||
resolveCircuitPhaseType,
|
||||
resolveProjectVoltage,
|
||||
} from "../services/project-voltage.service.js";
|
||||
|
||||
export const legacyProjectStateSnapshotSchemaVersion = 1 as const;
|
||||
export const previousProjectStateSnapshotSchemaVersion = 2 as const;
|
||||
export const distributionBoardProjectStateSnapshotSchemaVersion = 3 as const;
|
||||
export const projectStateSnapshotSchemaVersion = 4 as const;
|
||||
export const supplyTypesProjectStateSnapshotSchemaVersion = 4 as const;
|
||||
export const projectStateSnapshotSchemaVersion = 5 as const;
|
||||
|
||||
const idSchema = z.string().trim().min(1);
|
||||
const nullableStringSchema = z.string().nullable();
|
||||
@@ -198,15 +203,20 @@ const distributionBoardProjectStateSnapshotSchema = z
|
||||
})
|
||||
.strict();
|
||||
|
||||
export const projectStateSnapshotSchema = z
|
||||
const supplyTypesProjectStateSnapshotSchema = z
|
||||
.object({
|
||||
schemaVersion: z.literal(projectStateSnapshotSchemaVersion),
|
||||
schemaVersion: z.literal(supplyTypesProjectStateSnapshotSchemaVersion),
|
||||
project: currentProjectSchema,
|
||||
distributionBoards: z.array(distributionBoardSchema),
|
||||
...commonProjectStateSnapshotContents,
|
||||
})
|
||||
.strict();
|
||||
|
||||
export const projectStateSnapshotSchema =
|
||||
supplyTypesProjectStateSnapshotSchema.extend({
|
||||
schemaVersion: z.literal(projectStateSnapshotSchemaVersion),
|
||||
});
|
||||
|
||||
export type ProjectStateSnapshot = z.infer<
|
||||
typeof projectStateSnapshotSchema
|
||||
>;
|
||||
@@ -217,23 +227,33 @@ export function parseProjectStateSnapshot(
|
||||
const version = isPlainObject(value) ? value.schemaVersion : undefined;
|
||||
const snapshot =
|
||||
version === legacyProjectStateSnapshotSchemaVersion
|
||||
? upgradeDistributionBoardProjectStateSnapshot(
|
||||
upgradePreviousProjectStateSnapshot(
|
||||
upgradeLegacyProjectStateSnapshot(
|
||||
legacyProjectStateSnapshotSchema.parse(value)
|
||||
? upgradeSupplyTypesProjectStateSnapshot(
|
||||
upgradeDistributionBoardProjectStateSnapshot(
|
||||
upgradePreviousProjectStateSnapshot(
|
||||
upgradeLegacyProjectStateSnapshot(
|
||||
legacyProjectStateSnapshotSchema.parse(value)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
: version === previousProjectStateSnapshotSchemaVersion
|
||||
? upgradeDistributionBoardProjectStateSnapshot(
|
||||
upgradePreviousProjectStateSnapshot(
|
||||
previousProjectStateSnapshotSchema.parse(value)
|
||||
? upgradeSupplyTypesProjectStateSnapshot(
|
||||
upgradeDistributionBoardProjectStateSnapshot(
|
||||
upgradePreviousProjectStateSnapshot(
|
||||
previousProjectStateSnapshotSchema.parse(value)
|
||||
)
|
||||
)
|
||||
)
|
||||
: version === distributionBoardProjectStateSnapshotSchemaVersion
|
||||
? upgradeDistributionBoardProjectStateSnapshot(
|
||||
distributionBoardProjectStateSnapshotSchema.parse(value)
|
||||
? upgradeSupplyTypesProjectStateSnapshot(
|
||||
upgradeDistributionBoardProjectStateSnapshot(
|
||||
distributionBoardProjectStateSnapshotSchema.parse(value)
|
||||
)
|
||||
)
|
||||
: version === supplyTypesProjectStateSnapshotSchemaVersion
|
||||
? upgradeSupplyTypesProjectStateSnapshot(
|
||||
supplyTypesProjectStateSnapshotSchema.parse(value)
|
||||
)
|
||||
: projectStateSnapshotSchema.parse(value);
|
||||
assertProjectStateSnapshotRelations(snapshot);
|
||||
return snapshot;
|
||||
@@ -271,10 +291,10 @@ function upgradePreviousProjectStateSnapshot(
|
||||
|
||||
function upgradeDistributionBoardProjectStateSnapshot(
|
||||
snapshot: z.infer<typeof distributionBoardProjectStateSnapshotSchema>
|
||||
): ProjectStateSnapshot {
|
||||
): z.infer<typeof supplyTypesProjectStateSnapshotSchema> {
|
||||
return {
|
||||
...snapshot,
|
||||
schemaVersion: projectStateSnapshotSchemaVersion,
|
||||
schemaVersion: supplyTypesProjectStateSnapshotSchemaVersion,
|
||||
project: {
|
||||
...snapshot.project,
|
||||
enabledDistributionBoardSupplyTypes: [
|
||||
@@ -284,6 +304,37 @@ function upgradeDistributionBoardProjectStateSnapshot(
|
||||
};
|
||||
}
|
||||
|
||||
function upgradeSupplyTypesProjectStateSnapshot(
|
||||
snapshot: z.infer<typeof supplyTypesProjectStateSnapshotSchema>
|
||||
): ProjectStateSnapshot {
|
||||
const settings = snapshot.project;
|
||||
const sectionById = new Map(
|
||||
snapshot.circuitSections.map((section) => [section.id, section])
|
||||
);
|
||||
return {
|
||||
...snapshot,
|
||||
schemaVersion: projectStateSnapshotSchemaVersion,
|
||||
projectDevices: snapshot.projectDevices.map((device) => ({
|
||||
...device,
|
||||
voltageV: resolveProjectVoltage(device.phaseType, settings),
|
||||
})),
|
||||
circuits: snapshot.circuits.map((circuit) => {
|
||||
const section = sectionById.get(circuit.sectionId);
|
||||
if (!section) {
|
||||
return circuit;
|
||||
}
|
||||
const phaseType = resolveCircuitPhaseType(
|
||||
section.key,
|
||||
circuit.deviceRows.map((row) => row.phaseType)
|
||||
);
|
||||
return {
|
||||
...circuit,
|
||||
voltage: resolveProjectVoltage(phaseType, settings),
|
||||
};
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
||||
return value !== null && typeof value === "object" && !Array.isArray(value);
|
||||
}
|
||||
@@ -364,6 +415,14 @@ function assertProjectStateSnapshotRelations(
|
||||
}
|
||||
for (const device of snapshot.projectDevices) {
|
||||
assertProjectOwnership(device.projectId, projectId, "project device");
|
||||
if (
|
||||
device.voltageV !==
|
||||
resolveProjectVoltage(device.phaseType, snapshot.project)
|
||||
) {
|
||||
throw new Error(
|
||||
"Snapshot project device voltage must match project settings."
|
||||
);
|
||||
}
|
||||
}
|
||||
for (const floor of snapshot.floors) {
|
||||
assertProjectOwnership(floor.projectId, projectId, "floor");
|
||||
@@ -394,6 +453,18 @@ function assertProjectStateSnapshotRelations(
|
||||
"Snapshot circuit reserve state must match its device rows."
|
||||
);
|
||||
}
|
||||
const expectedVoltage = resolveProjectVoltage(
|
||||
resolveCircuitPhaseType(
|
||||
section.key,
|
||||
circuit.deviceRows.map((row) => row.phaseType)
|
||||
),
|
||||
snapshot.project
|
||||
);
|
||||
if (circuit.voltage !== expectedVoltage) {
|
||||
throw new Error(
|
||||
"Snapshot circuit voltage must match project settings."
|
||||
);
|
||||
}
|
||||
for (const row of circuit.deviceRows) {
|
||||
if (row.circuitId !== circuit.id) {
|
||||
throw new Error(
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
export type ElectricalPhaseType = "single_phase" | "three_phase";
|
||||
|
||||
export interface ProjectVoltageSettings {
|
||||
singlePhaseVoltageV: number;
|
||||
threePhaseVoltageV: number;
|
||||
}
|
||||
|
||||
export function resolveProjectVoltage(
|
||||
phaseType: ElectricalPhaseType,
|
||||
settings: ProjectVoltageSettings
|
||||
) {
|
||||
return phaseType === "three_phase"
|
||||
? settings.threePhaseVoltageV
|
||||
: settings.singlePhaseVoltageV;
|
||||
}
|
||||
|
||||
export function resolveCircuitPhaseType(
|
||||
sectionKey: string,
|
||||
devicePhaseTypes: ReadonlyArray<string | null | undefined> = []
|
||||
): ElectricalPhaseType {
|
||||
if (sectionKey === "three_phase") {
|
||||
return "three_phase";
|
||||
}
|
||||
if (sectionKey === "lighting" || sectionKey === "single_phase") {
|
||||
return "single_phase";
|
||||
}
|
||||
const assignedPhaseTypes = devicePhaseTypes.filter(
|
||||
(phaseType): phaseType is ElectricalPhaseType =>
|
||||
phaseType === "single_phase" || phaseType === "three_phase"
|
||||
);
|
||||
return assignedPhaseTypes.length > 0 &&
|
||||
assignedPhaseTypes.every((phaseType) => phaseType === "three_phase")
|
||||
? "three_phase"
|
||||
: "single_phase";
|
||||
}
|
||||
Reference in New Issue
Block a user