leistungsbilanz-ts/src/frontend/types.ts
Julian Appel e48042bde3 Add per-project socket limit and Revit socket device-type flag
- Project setting maxSocketsPerCircuit (migration 0018,
  project.update-settings schema 4, snapshot schema 11); older command
  and snapshot versions keep or upgrade the value to null.
- Revit configuration schema 2 marks device types as socket; version 1
  stays readable and derives the flag from socketCount family rules.
- Settings dialog field and device-type card on the Revit page.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 21:18:08 +01:00

721 lines
19 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import type { DistributionBoardSupplyType } from "../shared/constants/distribution-board";
import type { CircuitGroupCategory } from "../shared/constants/circuit-group";
import type {
DistributionBoardComponentPlacement,
DistributionBoardComponentRole,
} from "../shared/constants/distribution-board-component";
import type {
BreakerTripCharacteristic,
FuseUtilizationCategory,
NoCircuitProtectionDeviceType,
ProtectionDeviceType,
RcdType,
} from "../shared/constants/protection-device";
import type { ExternalModelConfiguration } from "../external-model/configuration/external-model-configuration";
export interface ExternalModelConfigurationSnapshotDto {
id: string;
projectId: string;
configuration: ExternalModelConfiguration;
}
export interface ExternalInitialImportPlanDto {
fileName: string;
sha256: string;
byteLength: number;
rowCount: number;
objectCount: number;
passthroughCount: number;
suspectObjectCount: number;
suspectRowNumbers: number[];
warnings: string[];
sourceRooms: Array<{
sourceRoomKey: string;
roomNumber: string;
roomName: string;
objectCount: number;
suggestedRoomId: string | null;
matchStatus: "exact-number" | "ambiguous-number" | "new";
candidateRoomIds: string[];
}>;
familyGroups: Array<{
familyAndType: string;
objectCount: number;
classified: boolean;
deviceTypeId: string | null;
deviceTypeName: string | null;
quantityRule: "one" | "socketCount" | null;
}>;
issueCounts: {
unknownFamilyAndType: number;
invalidPower: number;
invalidQuantity: number;
missingRoom: number;
};
objects: Array<{ worksharingId: string; ifcGuid: string | null; sourceRoomKey: string | null; sourceValues: { familyAndType: string }; suggestedPlanningValues: { simultaneityFactor: number; effectiveQuantity: number }; issues: string[] }>;
existing: {
floors: Array<{ id: string; name: string; sortOrder: number }>;
rooms: Array<{
id: string;
floorId: string | null;
roomNumber: string;
roomName: string;
}>;
distributionBoards: Array<{
id: string;
name: string;
floorId: string | null;
}>;
projectDevices: Array<{
id: string;
name: string;
displayName: string;
category: string | null;
connectionKind: string | null;
powerPerUnit: number;
}>;
};
}
export interface ApplyExternalInitialImportInput {
expectedRevision: number;
expectedSha256: string;
fileName: string;
contentBase64: string;
sourceName: string;
configuration: ExternalModelConfiguration;
objectsWithoutRoomDefaultDistributionBoardId: string | null;
roomDecisions: Array<{
sourceRoomKey: string;
roomId: string | null;
defaultDistributionBoardId: string | null;
}>;
familyProjectDeviceDecisions: Array<{
familyAndType: string;
projectDeviceId: string | null;
}>;
}
export interface ExternalInitialImportStatusDto {
imported: boolean;
sourceName: string | null;
objectCount: number;
missingObjectCount: number;
importedAtIso: string | null;
fileName: string | null;
}
export interface ExternalInitialImportResultDto extends ProjectCommandResultDto {
import: {
sourceId: string;
importBatchId: string;
objectCount: number;
};
}
export interface ExternalFollowUpImportPlanDto extends ExternalInitialImportPlanDto {
newObjectCount: number;
changedObjectCount: number;
unchangedObjectCount: number;
missingObjectCount: number;
returnDeviationCount: number;
newObjectWorksharingIds: string[];
newSourceRoomKeys: string[];
newFamilyAndTypes: string[];
changes: Array<{ objectId: string; worksharingId: string; familyAndType: string; changedFields: string[]; previousQuantity: number; suggestedQuantity: number; circuitDeviceRowId: string | null }>;
missingObjects: Array<{ objectId: string; worksharingId: string; familyAndType: string; circuitDeviceRowId: string | null }>;
returnDeviations: Array<{ objectId: string; worksharingId: string; fields: string[] }>;
}
export interface ApplyExternalFollowUpImportInput {
expectedRevision: number;
expectedSha256: string;
configuration: ExternalModelConfiguration;
objectsWithoutRoomDefaultDistributionBoardId: string | null;
sourceChangeDecisions: Array<{ objectId: string; accept: boolean }>;
roomDecisions: Array<{ sourceRoomKey: string; roomId: string | null; defaultDistributionBoardId: string | null }>;
familyProjectDeviceDecisions: Array<{ familyAndType: string; projectDeviceId: string | null }>;
}
export interface ExternalFollowUpImportResultDto extends ProjectCommandResultDto {
import: { importBatchId: string; objectCount: number; newObjectCount: number; changedObjectCount: number; missingObjectCount: number };
}
export interface ExternalProjectObjectDto {
id: string; worksharingId: string; ifcGuid: string | null; deviceTypeId: string;
familyAndType: string; selectionMarker: string; sourceCircuitIdentifier: string;
sourceRoomNumber: string; sourceRoomName: string; roomId: string | null;
distributionBoardId: string | null; linkedProjectDeviceId: string | null;
circuitDeviceRowId: string | null; presenceStatus: "present" | "missing";
planningValues: { displayName: string | null; category: CircuitGroupCategory | null; connectionKind: string | null; effectiveQuantity: number; powerPerUnitW: number | null; simultaneityFactor: number | null; cosPhi: number | null; costGroup: string | null; remark: string | null };
}
export interface ExternalProjectObjectsDto {
currentRevision: number; sourceName: string | null;
distributionBoards: Array<{ id: string; name: string }>;
projectDevices: Array<{ id: string; name: string; displayName: string }>;
objects: ExternalProjectObjectDto[];
}
export type ExternalReturnScopeDto = "all" | "deviating" | "selected";
export interface ExternalReturnWorkbookDto {
fileName: string;
contentBase64: string;
sha256: string;
objectCount: number;
warnings: string[];
}
export interface ExternalExportBatchDto {
id: string;
projectId: string;
projectRevision: number;
importBatchId: string;
exportedAtIso: string;
fileName: string;
sha256: string;
configurationSha256: string;
scope: ExternalReturnScopeDto;
objectCount: number;
}
export interface ProjectDto {
id: string;
name: string;
internalProjectNumber: string | null;
externalProjectNumber: string | null;
buildingOwner: string | null;
description: string | null;
isPublicBuilding: boolean;
singlePhaseVoltageV: number;
threePhaseVoltageV: number;
enabledDistributionBoardSupplyTypes: DistributionBoardSupplyType[];
siteAddress: string | null;
workStage: string | null;
projectLead: string | null;
projectEditor: string | null;
maxSocketsPerCircuit: number | null;
currentRevision: number;
}
export interface OfficeProfileDto {
officeName: string | null;
officeAddress: string | null;
}
export interface ProjectHistoryStateDto {
projectId: string;
currentRevision: number;
undoDepth: number;
redoDepth: number;
undoChangeSetId: string | null;
redoChangeSetId: string | null;
}
export type ProjectRevisionSourceDto =
| "user"
| "undo"
| "redo"
| "restore"
| "migration";
export interface ProjectRevisionSummaryDto {
revisionId: string;
changeSetId: string;
revisionNumber: number;
createdAtIso: string;
actorId: string | null;
source: ProjectRevisionSourceDto;
description: string | null;
commandType: string;
payloadSchemaVersion: number;
}
export interface ProjectRevisionPageDto {
projectId: string;
currentRevision: number;
revisions: ProjectRevisionSummaryDto[];
nextBeforeRevision: number | null;
}
export interface ProjectSnapshotMetadataDto {
id: string;
projectId: string;
sourceRevision: number;
sourceRevisionMetadata: ProjectRevisionSummaryDto | null;
schemaVersion: number;
kind: "named" | "automatic";
name: string;
description: string | null;
payloadSha256: string;
createdAtIso: string;
createdByActorId: string | null;
}
export interface ProjectSnapshotRestoreResultDto
extends ProjectCommandResultDto {
snapshot: ProjectSnapshotMetadataDto;
}
export interface ProjectSettingsCommandResultDto
extends ProjectCommandResultDto {
project: ProjectDto;
}
export interface ProjectCommandDto {
schemaVersion: number;
type: string;
payload: unknown;
}
export interface ProjectCommandResultDto {
revision: {
revisionId: string;
changeSetId: string;
projectId: string;
revisionNumber: number;
createdAtIso: string;
};
history: ProjectHistoryStateDto;
}
export interface DistributionBoardInfoDto {
boardNumber: string | null;
location: string | null;
fedFrom: string | null;
remark: string | null;
}
export interface DistributionBoardDto extends DistributionBoardInfoDto {
id: string;
projectId: string;
name: string;
floorId: string | null;
supplyType: DistributionBoardSupplyType | null;
simultaneityFactor: number;
feedingDistributionBoardId: string | null;
feedingCircuitId: string | null;
}
export interface DocumentLogoMetadataDto {
mimeType: string;
fileName: string | null;
sizeBytes: number;
updatedAtIso: string;
}
export interface DistributionBoardCommandResultDto
extends ProjectCommandResultDto {
distributionBoard: DistributionBoardDto;
}
export interface DistributionBoardCopyCommandResultDto
extends DistributionBoardCommandResultDto {
circuitList: CircuitListDto;
}
export interface DistributionBoardImportCommandResultDto
extends DistributionBoardCopyCommandResultDto {
/** Notes on source-project data that the import did not carry over. */
adjustments: string[];
}
export interface DistributionBoardDeleteCommandResultDto
extends ProjectCommandResultDto {
distributionBoardId: string;
}
export interface CircuitListDto {
id: string;
projectId: string;
distributionBoardId: string;
name: string;
}
export interface BuildingDto {
id: string;
projectId: string;
name: string;
sortOrder: number;
}
export interface ProjectBuildingCommandResultDto
extends ProjectCommandResultDto {
building: BuildingDto;
}
export interface FloorDto {
id: string;
projectId: string;
name: string;
sortOrder: number;
buildingId: string | null;
}
export interface ProjectFloorCommandResultDto
extends ProjectCommandResultDto {
floor: FloorDto;
}
export interface RoomDto {
id: string;
projectId: string;
floorId: string | null;
roomNumber: string;
roomName: string;
areaM2: number | null;
}
export interface GlobalDeviceDto {
id: string;
name: string;
displayName: string;
category: string | null;
quantity: number;
installedPowerPerUnitKw: number;
demandFactor: number;
voltageV: number | null;
phaseCount: 1 | 3 | null;
powerFactor: number | null;
note: string | null;
}
export interface ProjectDeviceDto {
id: string;
projectId: string;
name: string;
displayName: string;
phaseType: "single_phase" | "three_phase";
connectionKind: string | null;
costGroup: string | null;
category: CircuitGroupCategory;
quantity: number;
powerPerUnit: number;
simultaneityFactor: number;
totalPower: number;
cosPhi: number | null;
remark: string | null;
voltageV: number | null;
}
export interface ProjectRoomCommandResultDto
extends ProjectCommandResultDto {
room: RoomDto;
}
export interface ProjectDeviceCommandResultDto
extends ProjectCommandResultDto {
projectDevice: ProjectDeviceDto;
}
export interface CreateBuildingInput {
name: string;
}
export interface CreateFloorInput {
name: string;
/** Omitted = keep the current assignment on update; null = no building. */
buildingId?: string | null;
}
export interface CreateRoomInput {
floorId?: string;
roomNumber: string;
roomName: string;
areaM2: number | null;
}
export interface CreateGlobalDeviceInput {
name: string;
displayName: string;
category?: string;
quantity: number;
installedPowerPerUnitKw: number;
demandFactor: number;
phaseCount: 1 | 3;
powerFactor?: number;
note?: string;
}
export interface CreateProjectDeviceInput {
name: string;
displayName: string;
connectionKind?: string;
costGroup?: string;
category: CircuitGroupCategory;
quantity: number;
powerPerUnit: number;
simultaneityFactor: number;
cosPhi?: number;
remark?: string;
}
export interface ProjectDeviceSyncDifferenceDto {
field: ProjectDeviceSyncField;
currentValue: string | number | null;
sourceValue: string | number | null;
isOverridden: boolean;
}
export interface ProjectDeviceSyncRowDto {
rowId: string;
circuitId: string;
equipmentIdentifier: string;
circuitDisplayName: string | null;
circuitListId: string;
circuitListName: string;
distributionBoardId: string;
distributionBoardName: string;
rowDisplayName: string;
overriddenFields: ProjectDeviceSyncField[];
differences: ProjectDeviceSyncDifferenceDto[];
}
export interface ProjectDeviceSyncPreviewDto {
projectDevice: {
id: string;
name: string;
displayName: string;
};
rows: ProjectDeviceSyncRowDto[];
}
export interface ProjectDeviceSyncCommandResultDto
extends ProjectCommandResultDto {
preview: ProjectDeviceSyncPreviewDto;
}
export interface CircuitTreeDeviceRowDto {
id: string;
linkedProjectDeviceId?: string;
sortOrder: number;
name: string;
displayName: string;
phaseType?: string;
connectionKind?: string;
costGroup?: string;
category?: string;
level?: string;
roomId?: string;
roomNumberSnapshot?: string;
roomNameSnapshot?: string;
quantity: number;
manualQuantity: number;
powerPerUnit: number;
simultaneityFactor: number;
cosPhi?: number;
remark?: string;
overriddenFields?: string;
rowTotalPower: number;
externalObjectCount?: number;
}
export interface CircuitTreeProtectionDeviceDto {
type: ProtectionDeviceType;
ratedCurrentA: number;
fuseUtilizationCategory?: FuseUtilizationCategory;
tripCharacteristic?: BreakerTripCharacteristic;
rcdType?: RcdType;
ratedResidualCurrentMa?: number;
}
// Explicit "no protection device" on a circuit; shown as "–". A circuit
// without protectionDevice is still open for planning.
export interface CircuitTreeNoProtectionDeviceDto {
type: NoCircuitProtectionDeviceType;
}
export type CircuitTreeCircuitProtectionDeviceDto =
| CircuitTreeProtectionDeviceDto
| CircuitTreeNoProtectionDeviceDto;
export interface CircuitTreeComponentDto {
id: string;
circuitListId: string;
sectionId?: string;
equipmentIdentifier: string;
name: string;
role: DistributionBoardComponentRole;
placement: DistributionBoardComponentPlacement;
sortOrder: number;
protectionDevice?: CircuitTreeProtectionDeviceDto;
}
export interface CircuitTreeCircuitDto {
id: string;
circuitListId: string;
sectionId: string;
equipmentIdentifier: string;
displayName?: string;
sortOrder: number;
cableType?: string;
cableCrossSection?: string;
cableLength?: number;
rcdAssignment?: string;
terminalDesignation?: string;
voltage?: number;
controlRequirement?: string;
status?: string;
isReserve: boolean;
remark?: string;
circuitTotalPower: number;
circuitApparentPower: number;
circuitCosPhi: number;
deviceRows: CircuitTreeDeviceRowDto[];
downstreamBoardLoads: CircuitTreeDownstreamBoardLoadDto[];
protectionDevice?: CircuitTreeCircuitProtectionDeviceDto;
}
export interface CircuitTreeSectionDto {
id: string;
key: string;
displayName: string;
prefix: string;
sortOrder: number;
category?: CircuitGroupCategory;
groupNumber?: number;
sectionTotalPower: number;
components: CircuitTreeComponentDto[];
circuits: CircuitTreeCircuitDto[];
}
export interface CircuitTreeResponseDto {
circuitListId: string;
distributionBoardId: string;
distributionBoardName: string;
distributionBoardNumber?: string;
distributionBoardSupplyType?: DistributionBoardSupplyType;
feedingReference?: CircuitTreeFeedingReferenceDto;
currentRevision: number;
singlePhaseVoltageV: number;
threePhaseVoltageV: number;
distributionBoardSimultaneityFactor: number;
distributionBoardTotalPower: number;
distributionBoardTotalPowerWithSimultaneityFactor: number;
headerComponents: CircuitTreeComponentDto[];
sections: CircuitTreeSectionDto[];
footerComponents: CircuitTreeComponentDto[];
}
export interface CircuitTreeDownstreamBoardLoadDto {
distributionBoardId: string;
name: string;
boardNumber?: string;
supplyType?: DistributionBoardSupplyType;
activePowerKw: number;
apparentPowerKva: number;
cosPhi: number;
}
export interface CircuitTreeFeedingReferenceDto {
distributionBoardId: string;
circuitListId: string;
distributionBoardName: string;
distributionBoardNumber?: string;
circuitId?: string;
circuitEquipmentIdentifier?: string;
circuitDisplayName?: string;
circuitCategory?: CircuitGroupCategory;
}
export interface ProjectCircuitTreesResponseDto {
currentRevision: number;
trees: CircuitTreeResponseDto[];
}
export interface ExternalCircuitListObjectDto {
id: string;
ifcGuid: string;
selectionMarker: string;
familyAndType: string;
sourceCircuitIdentifier: string;
displayName: string | null;
category: string | null;
connectionKind: string | null;
effectiveQuantity: number;
powerPerUnitW: number | null;
sourceRoomNumber: string;
sourceRoomName: string;
roomId: string | null;
linkedProjectDeviceId: string | null;
circuitDeviceRowId: string | null;
presenceStatus: "present" | "missing";
}
export interface ExternalCircuitListObjectsDto {
sourceName: string | null;
objectCount: number;
unassignedObjectCount: number;
objects: ExternalCircuitListObjectDto[];
}
export interface CreateCircuitInputDto {
sectionId: string;
equipmentIdentifier: string;
displayName?: string;
sortOrder: number;
cableType?: string;
cableCrossSection?: string;
cableLength?: number;
rcdAssignment?: string;
terminalDesignation?: string;
voltage?: number;
controlRequirement?: string;
status?: string;
isReserve?: boolean;
remark?: string;
}
export interface CreateCircuitDeviceRowInputDto {
linkedProjectDeviceId?: string;
name: string;
displayName: string;
phaseType?: string;
connectionKind?: string;
costGroup?: string;
category?: string;
level?: string;
roomId?: string;
roomNumberSnapshot?: string;
roomNameSnapshot?: string;
quantity: number;
powerPerUnit: number;
simultaneityFactor: number;
cosPhi?: number;
remark?: string;
overriddenFields?: string;
sortOrder?: number;
}
import type { ProjectDeviceSyncField } from "../shared/constants/project-device-sync-fields";
// ── Grobe Leistungsbilanz (LPH 2/3) ─────────────────────────────────────
// The document shapes are shared with the API; see
// src/shared/estimate-balance/estimate-balance.ts.
import type {
EstimateBalanceSnapshot,
EstimateComparison,
} from "../shared/estimate-balance/estimate-balance";
export type EstimateBalanceDto = EstimateBalanceSnapshot;
export type EstimateComparisonDto = EstimateComparison;
export type EstimateBalanceTemplate = "kg400" | "empty" | "copy";
export interface CreateEstimateBalanceInput {
name: string;
workStage?: string | null;
dateIso?: string | null;
template: EstimateBalanceTemplate;
/** Required for template "copy". */
copyFromBalanceId?: string;
}
export interface EstimateBalanceCommandResultDto extends ProjectCommandResultDto {
balance: EstimateBalanceDto;
}
/** PUT result: either a new revision or an unchanged document. */
export type EstimateBalanceUpdateResultDto =
| EstimateBalanceCommandResultDto
| { unchanged: true; balance: EstimateBalanceDto };