Merge remote-tracking branch 'origin/main' into feature/cable-sizing
This commit is contained in:
commit
598003554a
136 changed files with 27182 additions and 1669 deletions
|
|
@ -59,6 +59,14 @@ this value for optimistic concurrency checks.
|
|||
- clients cannot submit arbitrary `project.restore-state` payloads through
|
||||
the generic command endpoint
|
||||
|
||||
Grobbilanzen sind bewusst kein Teil dieser logischen Snapshots. Der portable
|
||||
Projektexport unter `GET /projects/:projectId/export` verwendet dagegen
|
||||
Transferformat 2 und enthält alle Grobbilanzen. Die beiden Importwege
|
||||
`POST /projects/:projectId/import` und `POST /projects/import` prüfen ihre
|
||||
Prüfsumme; Ersetzen übernimmt die Grobbilanzen atomar und mit Undo/Redo,
|
||||
Duplizieren vergibt neue IDs. Transferformat 1 bleibt ohne Grobbilanzen
|
||||
importierbar.
|
||||
|
||||
The public dispatcher supports the Circuit and CircuitDeviceRow commands
|
||||
`circuit.update`, `circuit.insert`, `circuit.delete`,
|
||||
`circuit-device-row.update`, `circuit-device-row.insert`,
|
||||
|
|
@ -74,8 +82,9 @@ Protected-board structure uses
|
|||
persisted inverse of a delete. The dispatcher also supports the documented
|
||||
project-device, project settings, distribution-board and project-location
|
||||
commands. The generic editor commands listed here use schema version `1`.
|
||||
`project.update-settings` uses version `2` and still accepts supported baseline
|
||||
version `1` commands without changing the newer building classification.
|
||||
`project.update-settings` uses version `3` (including the print cover fields)
|
||||
and still accepts version `2` and supported baseline version `1` commands
|
||||
without changing the newer cover fields or building classification.
|
||||
Pre-baseline formats remain unsupported. Unsupported types or schema versions
|
||||
are rejected. Insert commands contain the complete entity or circuit block
|
||||
with stable ids; delete commands include the expected parent identity. Circuit
|
||||
|
|
@ -173,6 +182,9 @@ synchronizes linked circuit rows implicitly.
|
|||
- `PUT /projects/:projectId`
|
||||
- request:
|
||||
`{ "expectedRevision": 12, "isPublicBuilding": true, "singlePhaseVoltageV": 230, "threePhaseVoltageV": 400, "enabledDistributionBoardSupplyTypes": ["AV", "MSR", "SiBe"], ...projectMetadata }`
|
||||
- optional print cover fields `siteAddress` (max. 500), `workStage` (max.
|
||||
100), `projectLead` and `projectEditor` (max. 200 each); omitted fields keep
|
||||
their value, empty strings are stored as `null`
|
||||
- executes `project.update-settings` as one atomic revision
|
||||
- response:
|
||||
`{ "project": { ... }, "revision": { ... }, "history": { ... } }`
|
||||
|
|
@ -210,6 +222,12 @@ A stale `expectedRevision` returns HTTP `409` with
|
|||
`PROJECT_REVISION_CONFLICT`. Undo or redo without an eligible stack entry
|
||||
returns HTTP `409` with `PROJECT_HISTORY_OPERATION_UNAVAILABLE`.
|
||||
|
||||
## Estimate Balance (Grobe Leistungsbilanz)
|
||||
|
||||
Separate module under `/projects/:projectId/estimate-balances`; complete
|
||||
documents are written through `estimate-balance.insert/.update/.delete` project
|
||||
commands. Endpoints, payloads and calculation rules: `docs/estimate-balance.md`.
|
||||
|
||||
## Circuit-First Endpoints
|
||||
|
||||
### Distribution Board Setup
|
||||
|
|
@ -230,9 +248,13 @@ returns HTTP `409` with `PROJECT_HISTORY_OPERATION_UNAVAILABLE`.
|
|||
- stale revisions return `409 PROJECT_REVISION_CONFLICT`
|
||||
- `PUT /projects/:projectId/distribution-boards/:distributionBoardId`
|
||||
- body:
|
||||
`{ "floorId": null, "supplyType": "AV", "expectedRevision": 13 }`
|
||||
- executes `distribution-board.update`; floor and supply type are restored
|
||||
together by persistent Undo/Redo
|
||||
`{ "floorId": null, "supplyType": "AV", "simultaneityFactor": 1, "expectedRevision": 13 }`
|
||||
- optional info-card fields: `boardNumber` (max. 50), `location`,
|
||||
`fedFrom` (max. 200 each) and `remark` (max. 2000); strings are trimmed
|
||||
and an empty string is stored as `null`
|
||||
- executes `distribution-board.update`; all submitted values, including the
|
||||
submitted info fields, are restored together by persistent Undo/Redo
|
||||
- `fedFrom` is free text until the logical feed link is modeled
|
||||
- `POST /projects/:projectId/distribution-boards/:distributionBoardId/copy`
|
||||
- body: `{ "name": "UV-02 Kopie", "expectedRevision": 14 }`
|
||||
- duplicates the complete distribution-board subtree with new owning UUIDs
|
||||
|
|
@ -249,15 +271,27 @@ returns HTTP `409` with `PROJECT_HISTORY_OPERATION_UNAVAILABLE`.
|
|||
`distribution-board.delete-subtree`. Persistent Undo/Redo restores or
|
||||
removes the same complete subtree, including protection devices.
|
||||
|
||||
### Project Floors and Rooms
|
||||
### Project Buildings, Floors and Rooms
|
||||
|
||||
- `GET /projects/:projectId/buildings`
|
||||
- `POST /projects/:projectId/buildings`
|
||||
- body: `{ "name": "Haus A", "expectedRevision": 12 }`
|
||||
- executes `project-building.insert` with a stable building id
|
||||
- response: `{ "building": { ... }, "revision": { ... }, "history": { ... } }`
|
||||
- `PUT /projects/:projectId/buildings/:buildingId`
|
||||
- body: `{ "name": "Haus B", "expectedRevision": 13 }` (name only)
|
||||
- `DELETE /projects/:projectId/buildings/:buildingId`
|
||||
- body: `{ "expectedRevision": 14 }`
|
||||
- rejects buildings with assigned floors
|
||||
- `POST /projects/:projectId/floors`
|
||||
- body: `{ "name": "EG", "expectedRevision": 13 }`
|
||||
- executes `project-floor.insert` with a stable floor id
|
||||
- body: `{ "name": "EG", "buildingId": "building_1", "expectedRevision": 13 }`
|
||||
(`buildingId` optional, `null` = no building)
|
||||
- executes `project-floor.insert` (command version 2) with a stable floor id
|
||||
- response: `{ "floor": { ... }, "revision": { ... }, "history": { ... } }`
|
||||
- `PUT /projects/:projectId/floors/:floorId`
|
||||
- body: `{ "name": "1. OG", "expectedRevision": 14 }`
|
||||
- executes an exact persistent floor update
|
||||
- body: `{ "name": "1. OG", "buildingId": null, "expectedRevision": 14 }`
|
||||
- executes an exact persistent floor update of name and/or building; a
|
||||
missing `buildingId` keeps the current building
|
||||
- `DELETE /projects/:projectId/floors/:floorId`
|
||||
- body: `{ "expectedRevision": 15 }`
|
||||
- rejects floors with assigned rooms or distribution boards
|
||||
|
|
@ -447,3 +481,27 @@ Full request example and calculation rules: `docs/cable-sizing-module.md`.
|
|||
Parser errors expose stable codes such as `header-not-found`,
|
||||
`ambiguous-header`, `invalid-ifc-guid` and `duplicate-ifc-guid`. The confirmed
|
||||
import uploads and parses the file again and verifies its hash.
|
||||
|
||||
## Document Branding (print view)
|
||||
|
||||
Office-wide branding for the print view. These endpoints are mounted at
|
||||
`/api/document-branding`, outside `/api/projects`, because the data is global
|
||||
and intentionally not part of project revisions, snapshots or transfer.
|
||||
|
||||
- `GET /document-branding`
|
||||
- returns `{ "logo": { "mimeType", "fileName", "sizeBytes", "updatedAtIso" } | null, "office": { "officeName", "officeAddress" } }`
|
||||
- `GET /document-branding/logo`
|
||||
- returns the stored image bytes with its media type, or `404` without logo
|
||||
- responses carry `X-Content-Type-Options: nosniff` and a restrictive
|
||||
Content-Security-Policy so an SVG logo cannot execute scripts
|
||||
- `PUT /document-branding/logo`
|
||||
- request: `{ "fileName": "logo.png", "mimeType": "image/png", "contentBase64": "..." }`
|
||||
- accepted types: `image/png`, `image/jpeg`, `image/svg+xml`; at most 2 MB
|
||||
after decoding; the content signature must match the declared type
|
||||
- replaces an existing logo; returns the logo metadata
|
||||
- `DELETE /document-branding/logo`
|
||||
- removes the logo; returns `204`
|
||||
- `PUT /document-branding/office`
|
||||
- request: `{ "officeName": "…" | null, "officeAddress": "…" | null }`
|
||||
(at most 200 / 500 characters; empty text is stored as not set)
|
||||
- returns `{ "office": { "officeName", "officeAddress" } }`
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue