Add public building project setting
This commit is contained in:
@@ -0,0 +1 @@
|
||||
ALTER TABLE `projects` ADD `is_public_building` integer DEFAULT false NOT NULL;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,13 @@
|
||||
"when": 1785499119431,
|
||||
"tag": "0000_whole_surge",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 1,
|
||||
"version": "6",
|
||||
"when": 1785511894897,
|
||||
"tag": "0001_add_public_building_setting",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -40,22 +40,33 @@ export class ProjectSettingsProjectCommandRepository
|
||||
if (!current) {
|
||||
throw new Error("Project not found.");
|
||||
}
|
||||
const target = input.command.payload;
|
||||
const target: ProjectSettingsValues =
|
||||
input.command.schemaVersion === 1
|
||||
? {
|
||||
...input.command.payload,
|
||||
isPublicBuilding: current.isPublicBuilding,
|
||||
}
|
||||
: input.command.payload;
|
||||
if (projectSettingsEqual(current, target)) {
|
||||
throw new Error("Project settings did not change.");
|
||||
}
|
||||
|
||||
const inverse = createProjectSettingsUpdateProjectCommand({
|
||||
const inverseValues: ProjectSettingsValues = {
|
||||
name: current.name,
|
||||
internalProjectNumber: current.internalProjectNumber,
|
||||
externalProjectNumber: current.externalProjectNumber,
|
||||
buildingOwner: current.buildingOwner,
|
||||
description: current.description,
|
||||
isPublicBuilding: current.isPublicBuilding,
|
||||
singlePhaseVoltageV: current.singlePhaseVoltageV,
|
||||
threePhaseVoltageV: current.threePhaseVoltageV,
|
||||
enabledDistributionBoardSupplyTypes:
|
||||
current.enabledDistributionBoardSupplyTypes,
|
||||
});
|
||||
};
|
||||
const inverse =
|
||||
input.command.schemaVersion === 1
|
||||
? createBaselineProjectSettingsUpdateCommand(inverseValues)
|
||||
: createProjectSettingsUpdateProjectCommand(inverseValues);
|
||||
assertDisabledSupplyTypesAreUnused(tx, input.projectId, target);
|
||||
const updated = tx
|
||||
.update(projects)
|
||||
@@ -71,6 +82,26 @@ export class ProjectSettingsProjectCommandRepository
|
||||
}
|
||||
}
|
||||
|
||||
function createBaselineProjectSettingsUpdateCommand(
|
||||
values: ProjectSettingsValues
|
||||
) {
|
||||
return {
|
||||
schemaVersion: 1 as const,
|
||||
type: "project.update-settings" as const,
|
||||
payload: {
|
||||
name: values.name,
|
||||
internalProjectNumber: values.internalProjectNumber,
|
||||
externalProjectNumber: values.externalProjectNumber,
|
||||
buildingOwner: values.buildingOwner,
|
||||
description: values.description,
|
||||
singlePhaseVoltageV: values.singlePhaseVoltageV,
|
||||
threePhaseVoltageV: values.threePhaseVoltageV,
|
||||
enabledDistributionBoardSupplyTypes:
|
||||
values.enabledDistributionBoardSupplyTypes,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function projectSettingsEqual(
|
||||
current: ProjectSettingsValues,
|
||||
target: ProjectSettingsValues
|
||||
@@ -81,6 +112,7 @@ function projectSettingsEqual(
|
||||
current.externalProjectNumber === target.externalProjectNumber &&
|
||||
current.buildingOwner === target.buildingOwner &&
|
||||
current.description === target.description &&
|
||||
current.isPublicBuilding === target.isPublicBuilding &&
|
||||
current.singlePhaseVoltageV === target.singlePhaseVoltageV &&
|
||||
current.threePhaseVoltageV === target.threePhaseVoltageV
|
||||
&& sameSupplyTypes(
|
||||
|
||||
@@ -208,6 +208,7 @@ function replaceProjectState(
|
||||
externalProjectNumber: state.project.externalProjectNumber,
|
||||
buildingOwner: state.project.buildingOwner,
|
||||
description: state.project.description,
|
||||
isPublicBuilding: state.project.isPublicBuilding,
|
||||
singlePhaseVoltageV: state.project.singlePhaseVoltageV,
|
||||
threePhaseVoltageV: state.project.threePhaseVoltageV,
|
||||
enabledDistributionBoardSupplyTypes:
|
||||
|
||||
@@ -39,6 +39,7 @@ export function readProjectStateSnapshot(
|
||||
externalProjectNumber: projects.externalProjectNumber,
|
||||
buildingOwner: projects.buildingOwner,
|
||||
description: projects.description,
|
||||
isPublicBuilding: projects.isPublicBuilding,
|
||||
singlePhaseVoltageV: projects.singlePhaseVoltageV,
|
||||
threePhaseVoltageV: projects.threePhaseVoltageV,
|
||||
enabledDistributionBoardSupplyTypes:
|
||||
@@ -233,6 +234,7 @@ export function readProjectStateSnapshot(
|
||||
externalProjectNumber: project.externalProjectNumber,
|
||||
buildingOwner: project.buildingOwner,
|
||||
description: project.description,
|
||||
isPublicBuilding: project.isPublicBuilding,
|
||||
singlePhaseVoltageV: project.singlePhaseVoltageV,
|
||||
threePhaseVoltageV: project.threePhaseVoltageV,
|
||||
enabledDistributionBoardSupplyTypes:
|
||||
|
||||
@@ -25,6 +25,7 @@ export class ProjectRepository {
|
||||
externalProjectNumber: input.externalProjectNumber ?? null,
|
||||
buildingOwner: input.buildingOwner ?? null,
|
||||
description: input.description ?? null,
|
||||
isPublicBuilding: input.isPublicBuilding ?? false,
|
||||
singlePhaseVoltageV: input.singlePhaseVoltageV ?? 230,
|
||||
threePhaseVoltageV: input.threePhaseVoltageV ?? 400,
|
||||
enabledDistributionBoardSupplyTypes: [
|
||||
|
||||
@@ -9,6 +9,9 @@ export const projects = sqliteTable("projects", {
|
||||
externalProjectNumber: text("external_project_number"),
|
||||
buildingOwner: text("building_owner"),
|
||||
description: text("description"),
|
||||
isPublicBuilding: integer("is_public_building", { mode: "boolean" })
|
||||
.notNull()
|
||||
.default(false),
|
||||
singlePhaseVoltageV: integer("single_phase_voltage_v").notNull().default(230),
|
||||
threePhaseVoltageV: integer("three_phase_voltage_v").notNull().default(400),
|
||||
enabledDistributionBoardSupplyTypes: text(
|
||||
|
||||
@@ -6,7 +6,8 @@ import {
|
||||
|
||||
export const projectSettingsUpdateCommandType =
|
||||
"project.update-settings" as const;
|
||||
export const projectSettingsUpdateCommandSchemaVersion = 1 as const;
|
||||
export const projectSettingsUpdateCommandSchemaVersion = 2 as const;
|
||||
const previousProjectSettingsUpdateCommandSchemaVersion = 1 as const;
|
||||
|
||||
export interface ProjectSettingsValues {
|
||||
name: string;
|
||||
@@ -14,21 +15,37 @@ export interface ProjectSettingsValues {
|
||||
externalProjectNumber: string | null;
|
||||
buildingOwner: string | null;
|
||||
description: string | null;
|
||||
isPublicBuilding: boolean;
|
||||
singlePhaseVoltageV: number;
|
||||
threePhaseVoltageV: number;
|
||||
enabledDistributionBoardSupplyTypes: DistributionBoardSupplyType[];
|
||||
}
|
||||
|
||||
export interface ProjectSettingsUpdateProjectCommand
|
||||
type PreviousProjectSettingsValues = Omit<
|
||||
ProjectSettingsValues,
|
||||
"isPublicBuilding"
|
||||
>;
|
||||
|
||||
export interface CurrentProjectSettingsUpdateProjectCommand
|
||||
extends SerializedProjectCommand<ProjectSettingsValues> {
|
||||
schemaVersion: typeof projectSettingsUpdateCommandSchemaVersion;
|
||||
type: typeof projectSettingsUpdateCommandType;
|
||||
}
|
||||
|
||||
interface PreviousProjectSettingsUpdateProjectCommand
|
||||
extends SerializedProjectCommand<PreviousProjectSettingsValues> {
|
||||
schemaVersion: typeof previousProjectSettingsUpdateCommandSchemaVersion;
|
||||
type: typeof projectSettingsUpdateCommandType;
|
||||
}
|
||||
|
||||
export type ProjectSettingsUpdateProjectCommand =
|
||||
| CurrentProjectSettingsUpdateProjectCommand
|
||||
| PreviousProjectSettingsUpdateProjectCommand;
|
||||
|
||||
export function createProjectSettingsUpdateProjectCommand(
|
||||
values: ProjectSettingsValues
|
||||
): ProjectSettingsUpdateProjectCommand {
|
||||
const command: ProjectSettingsUpdateProjectCommand = {
|
||||
): CurrentProjectSettingsUpdateProjectCommand {
|
||||
const command: CurrentProjectSettingsUpdateProjectCommand = {
|
||||
schemaVersion: projectSettingsUpdateCommandSchemaVersion,
|
||||
type: projectSettingsUpdateCommandType,
|
||||
payload: { ...values },
|
||||
@@ -42,7 +59,8 @@ export function assertProjectSettingsUpdateProjectCommand(
|
||||
): asserts command is ProjectSettingsUpdateProjectCommand {
|
||||
if (
|
||||
command.type !== projectSettingsUpdateCommandType ||
|
||||
command.schemaVersion !== projectSettingsUpdateCommandSchemaVersion
|
||||
(command.schemaVersion !== projectSettingsUpdateCommandSchemaVersion &&
|
||||
command.schemaVersion !== previousProjectSettingsUpdateCommandSchemaVersion)
|
||||
) {
|
||||
throw new Error("Unsupported project settings update command.");
|
||||
}
|
||||
@@ -58,8 +76,7 @@ export function assertProjectSettingsUpdateProjectCommand(
|
||||
!isNullableTrimmedString(command.payload.buildingOwner, 200) ||
|
||||
!isNullableTrimmedString(command.payload.description, 2000) ||
|
||||
!isPositiveFiniteNumber(command.payload.singlePhaseVoltageV) ||
|
||||
!isPositiveFiniteNumber(command.payload.threePhaseVoltageV) ||
|
||||
Object.keys(command.payload).length !== 8
|
||||
!isPositiveFiniteNumber(command.payload.threePhaseVoltageV)
|
||||
) {
|
||||
throw new Error(
|
||||
"Project settings update command contains invalid values."
|
||||
@@ -74,6 +91,18 @@ export function assertProjectSettingsUpdateProjectCommand(
|
||||
"Project settings update command contains invalid supply types."
|
||||
);
|
||||
}
|
||||
const isPreviousSchema =
|
||||
command.schemaVersion === previousProjectSettingsUpdateCommandSchemaVersion;
|
||||
if (
|
||||
(isPreviousSchema && Object.keys(command.payload).length !== 8) ||
|
||||
(!isPreviousSchema &&
|
||||
(typeof command.payload.isPublicBuilding !== "boolean" ||
|
||||
Object.keys(command.payload).length !== 9))
|
||||
) {
|
||||
throw new Error(
|
||||
"Project settings update command contains invalid values."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function isValidSupplyTypes(
|
||||
|
||||
@@ -19,13 +19,14 @@ import {
|
||||
resolveProjectVoltage,
|
||||
} from "../services/project-voltage.service.js";
|
||||
|
||||
export const projectStateSnapshotSchemaVersion = 1 as const;
|
||||
export const projectStateSnapshotSchemaVersion = 2 as const;
|
||||
const previousProjectStateSnapshotSchemaVersion = 1 as const;
|
||||
|
||||
const idSchema = z.string().trim().min(1);
|
||||
const nullableStringSchema = z.string().nullable();
|
||||
const finiteNumberSchema = z.number().finite();
|
||||
|
||||
const projectSchema = z
|
||||
const previousProjectSchema = z
|
||||
.object({
|
||||
id: idSchema,
|
||||
name: z.string().trim().min(1),
|
||||
@@ -42,6 +43,10 @@ const projectSchema = z
|
||||
})
|
||||
.strict();
|
||||
|
||||
const projectSchema = previousProjectSchema
|
||||
.extend({ isPublicBuilding: z.boolean() })
|
||||
.strict();
|
||||
|
||||
const distributionBoardSchema = z
|
||||
.object({
|
||||
id: idSchema,
|
||||
@@ -267,6 +272,15 @@ export const projectStateSnapshotSchema = z
|
||||
})
|
||||
.strict();
|
||||
|
||||
const previousProjectStateSnapshotSchema = z
|
||||
.object({
|
||||
schemaVersion: z.literal(previousProjectStateSnapshotSchemaVersion),
|
||||
project: previousProjectSchema,
|
||||
distributionBoards: z.array(distributionBoardSchema),
|
||||
...projectStateSnapshotContents,
|
||||
})
|
||||
.strict();
|
||||
|
||||
export type ProjectStateSnapshot = z.infer<
|
||||
typeof projectStateSnapshotSchema
|
||||
>;
|
||||
@@ -274,12 +288,35 @@ export type ProjectStateSnapshot = z.infer<
|
||||
export function parseProjectStateSnapshot(
|
||||
value: unknown
|
||||
): ProjectStateSnapshot {
|
||||
const parsedSnapshot = projectStateSnapshotSchema.parse(value);
|
||||
const parsedSnapshot = projectStateSnapshotSchema.parse(
|
||||
upgradePreviousProjectStateSnapshot(value)
|
||||
);
|
||||
const snapshot = normalizeSnapshotPhaseTypes(parsedSnapshot);
|
||||
assertProjectStateSnapshotRelations(snapshot);
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
function upgradePreviousProjectStateSnapshot(value: unknown): unknown {
|
||||
if (
|
||||
value === null ||
|
||||
typeof value !== "object" ||
|
||||
Array.isArray(value) ||
|
||||
(value as { schemaVersion?: unknown }).schemaVersion !==
|
||||
previousProjectStateSnapshotSchemaVersion
|
||||
) {
|
||||
return value;
|
||||
}
|
||||
const previous = previousProjectStateSnapshotSchema.parse(value);
|
||||
return {
|
||||
...previous,
|
||||
schemaVersion: projectStateSnapshotSchemaVersion,
|
||||
project: {
|
||||
...previous.project,
|
||||
isPublicBuilding: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function normalizeSnapshotPhaseTypes(
|
||||
snapshot: ProjectStateSnapshot
|
||||
): ProjectStateSnapshot {
|
||||
|
||||
@@ -14,6 +14,7 @@ export interface ProjectSettingsInput {
|
||||
externalProjectNumber: string | null;
|
||||
buildingOwner: string | null;
|
||||
description: string | null;
|
||||
isPublicBuilding: boolean;
|
||||
singlePhaseVoltageV: number;
|
||||
threePhaseVoltageV: number;
|
||||
enabledDistributionBoardSupplyTypes: DistributionBoardSupplyType[];
|
||||
@@ -54,6 +55,9 @@ export function ProjectSettingsModal({
|
||||
const [description, setDescription] = useState(
|
||||
project.description ?? ""
|
||||
);
|
||||
const [isPublicBuilding, setIsPublicBuilding] = useState(
|
||||
project.isPublicBuilding
|
||||
);
|
||||
const [singlePhaseVoltageV, setSinglePhaseVoltageV] = useState(
|
||||
String(project.singlePhaseVoltageV)
|
||||
);
|
||||
@@ -82,6 +86,7 @@ export function ProjectSettingsModal({
|
||||
externalProjectNumber: toNullableString(externalProjectNumber),
|
||||
buildingOwner: toNullableString(buildingOwner),
|
||||
description: toNullableString(description),
|
||||
isPublicBuilding,
|
||||
singlePhaseVoltageV: Number(singlePhaseVoltageV),
|
||||
threePhaseVoltageV: Number(threePhaseVoltageV),
|
||||
enabledDistributionBoardSupplyTypes,
|
||||
@@ -269,6 +274,27 @@ export function ProjectSettingsModal({
|
||||
value={description}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-12">
|
||||
<label className="form-check">
|
||||
<input
|
||||
checked={isPublicBuilding}
|
||||
className="form-check-input"
|
||||
id="public-building"
|
||||
onChange={(event) =>
|
||||
setIsPublicBuilding(event.target.checked)
|
||||
}
|
||||
type="checkbox"
|
||||
/>
|
||||
<span className="form-check-label">
|
||||
Öffentliches Gebäude
|
||||
</span>
|
||||
</label>
|
||||
<div className="form-text ms-4">
|
||||
Wird bei der späteren Leitungsauslegung berücksichtigt,
|
||||
insbesondere bei der Auswahl halogenfreier Kabel und
|
||||
Leitungen.
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12 col-md-6">
|
||||
<label className="form-label" htmlFor="single-phase-voltage">
|
||||
Standardspannung 1-phasig [V]
|
||||
|
||||
@@ -18,6 +18,7 @@ export interface ProjectDto {
|
||||
externalProjectNumber: string | null;
|
||||
buildingOwner: string | null;
|
||||
description: string | null;
|
||||
isPublicBuilding: boolean;
|
||||
singlePhaseVoltageV: number;
|
||||
threePhaseVoltageV: number;
|
||||
enabledDistributionBoardSupplyTypes: DistributionBoardSupplyType[];
|
||||
|
||||
@@ -245,6 +245,7 @@ export function updateProjectSettings(
|
||||
externalProjectNumber: string | null;
|
||||
buildingOwner: string | null;
|
||||
description: string | null;
|
||||
isPublicBuilding: boolean;
|
||||
singlePhaseVoltageV: number;
|
||||
threePhaseVoltageV: number;
|
||||
enabledDistributionBoardSupplyTypes: ProjectDto["enabledDistributionBoardSupplyTypes"];
|
||||
|
||||
@@ -8,6 +8,7 @@ export const createProjectSchema = z.object({
|
||||
externalProjectNumber: z.string().trim().max(100).optional(),
|
||||
buildingOwner: z.string().trim().max(200).optional(),
|
||||
description: z.string().trim().max(2000).optional(),
|
||||
isPublicBuilding: z.boolean().optional(),
|
||||
singlePhaseVoltageV: z.number().positive().optional(),
|
||||
threePhaseVoltageV: z.number().positive().optional(),
|
||||
});
|
||||
@@ -20,6 +21,7 @@ export const updateProjectSettingsSchema = z
|
||||
externalProjectNumber: z.string().trim().max(100).nullable(),
|
||||
buildingOwner: z.string().trim().max(200).nullable(),
|
||||
description: z.string().trim().max(2000).nullable(),
|
||||
isPublicBuilding: z.boolean(),
|
||||
singlePhaseVoltageV: z.number().positive(),
|
||||
threePhaseVoltageV: z.number().positive(),
|
||||
enabledDistributionBoardSupplyTypes: z
|
||||
|
||||
Reference in New Issue
Block a user