diff --git a/README.md b/README.md index 520edd2..86e93df 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,11 @@ implementiert. ## Unterstützter Arbeitsablauf - Projekte, Verteilungen, Etagen und Räume verwalten -- pro Verteilung eine Stromkreisliste mit festen Bereichen bearbeiten +- pro Verteilung geschützte Stromkreisgruppen für Beleuchtung, 1-phasige und + 3-phasige Stromkreise verwalten +- Hauptschalter, Überspannungsableiter, Gruppenschutz und zusätzliche + Verteilergeräte in der Stromkreisliste abbilden +- Schutzgeräte je Stromkreis und optional je Gruppe konfigurieren - leere, einzeilige und mehrzeilige Stromkreise abbilden - Stromkreise und Gerätezeilen per Drag-and-drop umstrukturieren - Projektgeräte einfügen, verknüpfen und kontrolliert synchronisieren @@ -90,6 +94,7 @@ Frontend und API laufen anschließend auf denselben Ports wie im Docker-Setup. npm test npm run build:api npm run build:web +npm run typecheck:scripts npx tsc --noEmit -p tsconfig.next.json ``` diff --git a/docs/circuit-list-editor-api.md b/docs/circuit-list-editor-api.md index 2062d1b..b7b303e 100644 --- a/docs/circuit-list-editor-api.md +++ b/docs/circuit-list-editor-api.md @@ -59,16 +59,23 @@ this value for optimistic concurrency checks. - clients cannot submit arbitrary `project.restore-state` payloads through the generic command endpoint -The public dispatcher currently supports `circuit.update`, `circuit.insert`, -`circuit.delete`, `circuit-device-row.update`, -`circuit-device-row.insert`, `circuit-device-row.delete`, -`circuit-device-row.move`, `circuit-device-row.move-with-new-circuit`, -`circuit.reorder-section`, `circuit.reorder-sections`, -`circuit.renumber-section` and -`project-device.update`, `project-device.insert`, `project-device.delete` and -`project-device.sync-rows` as well as `project.update-settings`, all with -schema version `1`. Other command types -are rejected. Insert commands contain the complete entity or circuit block +The public dispatcher supports the Circuit and CircuitDeviceRow commands +`circuit.update`, `circuit.insert`, `circuit.delete`, +`circuit-device-row.update`, `circuit-device-row.insert`, +`circuit-device-row.delete`, `circuit-device-row.move`, +`circuit-device-row.move-with-new-circuit`, `circuit.reorder-section`, +`circuit.reorder-sections` and `circuit.renumber-section`. + +Protected-board structure uses +`distribution-board-component.insert|update|delete`, +`circuit-group.insert|update|delete|reorder|renumber`, +`circuit.move-group`, `circuit-group.delete-subtree` and +`circuit-protection.update`. A subtree restore is normally emitted only as the +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`; +older stored formats can remain supported by their owning command boundary. +Unsupported types are rejected. Insert commands contain the complete entity or circuit block with stable ids; delete commands include the expected parent identity. Circuit snapshots contain zero, one or multiple complete device rows. Move commands contain each row's expected and target circuit plus its exact expected and @@ -101,6 +108,24 @@ targets occupied by other sections, then applies swaps through collision-safe temporary identifiers. Undo restores the exact prior identifiers; sort positions and device rows remain unchanged. +`circuit-group.reorder` changes only complete group sort assignments. +`circuit-group.renumber` carries every affected group, child circuit and group +component with expected and target identifiers so swaps can be applied +collision-safely. `circuit.move-group` changes one complete circuit's group, +BMK and position and stores the deterministic target BMK. The target group must +have the same category. + +`circuit-group.delete-subtree` carries the complete warned group state, +including both protection layers and every device-row link/override value. The +server captures the current subtree again inside the transaction and rejects a +stale or incomplete snapshot. Undo restores the same UUIDs through the stored +inverse command. + +`circuit-protection.update` inserts or replaces the complete validated +one-to-one circuit protection state. Users cannot remove the required +protection row; removal is available only to a stored inverse when undoing its +initial creation. + `project-device.sync-rows` represents `synchronize`, `disconnect` and `reconnect` operations. Every selected row carries complete expected and target snapshots of all ProjectDevice-sync fields, the link and `overriddenFields`. diff --git a/docs/circuit-list-editor-architecture.md b/docs/circuit-list-editor-architecture.md index a81c73a..2a761df 100644 --- a/docs/circuit-list-editor-architecture.md +++ b/docs/circuit-list-editor-architecture.md @@ -17,13 +17,15 @@ The pure grid modules have no React state and are covered by focused unit tests. ## Domain Model Overview - `CircuitSection` - - Groups circuits by planning section (for example lighting, single-phase, three-phase). - - Owns section metadata (`key`, `displayName`, `prefix`, ordering). + - Represents a protected circuit group in one of the categories lighting, + single-phase or three-phase. + - Owns category, positive group number, generated prefix, display name and + ordering. - `Circuit` - Core electrical unit in the list. - Owns circuit-level identifiers and technical data: - `equipmentIdentifier` (BMK) - - protection data + - one explicit one-to-one protection device - cable data - reserve state - voltage and optional control requirement for future sizing @@ -43,6 +45,10 @@ The pure grid modules have no React state and are covered by focused unit tests. - `ProjectDevice` - Reusable device template entity at project level. - Can be linked to `CircuitDeviceRow` entries, with copied display values on insert. +- `DistributionBoardComponent` + - Represents fixed header components, optional group protection and manually + named auxiliary footer devices with their own unique BMK. + - Group protection may own a separate one-to-one protection configuration. - Retained legacy migration source - Old `consumers` rows, mappings and reports are available only to explicit database upgrade tooling. @@ -77,7 +83,9 @@ Section-level `-frei-` placeholder rows represent insertion targets for creating `equipmentIdentifier` / BMK is circuit-owned (`Circuit.equipmentIdentifier`). - Device rows do not have their own BMK. -- Existing identifiers must stay stable unless explicitly changed by user action. +- Existing identifiers stay stable on sort, insert and delete. Explicit + renumbering may change them, and a user-initiated complete-circuit move to + another same-category group assigns the next target-group identifier. - Renumbering is explicit, not implicit on move/sort/delete. ## Data Ownership Split: Circuit vs Device Row @@ -113,9 +121,9 @@ The sibling `/tree` route is a read-only structure preview. Old ## Future Persistence Direction -Persistent undo/redo, project revisions, logical snapshots, external-model exchange and PostgreSQL readiness are specified in [Project History and External Model Architecture](./project-history-and-external-model-architecture.md). - -Critical multi-write commands already use explicit persistence transaction -adapters. The next step is to compose these command boundaries into server-side, -project-scoped revisions and change sets. Database backups remain separate from -user-visible project snapshots. +Persistent Undo/Redo, project revisions and logical snapshots are implemented +through project-scoped commands and the shared transaction boundary. Database +backups remain separate from user-visible project snapshots. External-model +exchange and PostgreSQL readiness are specified in +[Project History and External Model Architecture](./project-history-and-external-model-architecture.md) +and remain future work. diff --git a/docs/circuit-list-editor-interactions.md b/docs/circuit-list-editor-interactions.md index 8fc7ded..3867143 100644 --- a/docs/circuit-list-editor-interactions.md +++ b/docs/circuit-list-editor-interactions.md @@ -28,6 +28,7 @@ The editor can have a selected cell without an active editor input. `editingCell The UI works from a normalized `visibleRows` model built from filtered/sorted sections: - section header rows +- fixed header, group-protection and auxiliary footer component rows - circuit rows (`circuitCompact`, `circuitSummary`, `reserveCircuit`) - device rows (`deviceRow`) - section placeholder rows (`placeholder`) @@ -86,9 +87,13 @@ Intent is separated by drag source type: - phase type, category, linked project device and local row values remain unchanged - target creation, row assignments and reserve-state updates use one SQLite transaction - circuit drag (BMK handle): - - reorder circuits inside same section only - - cross-section reorder is rejected - - the complete section order is validated and stored in one SQLite transaction + - reorder one or multiple circuits inside the same group without changing BMKs + - move exactly one circuit into another group of the same category + - a cross-group move assigns the highest existing target suffix plus one; + gaps are not filled + - cross-category and cross-group multi-circuit moves are rejected + - same-group reorder validates the complete group order; cross-group move + stores the one exact source/target transition - bulk device row move: - supported via multi-selection + drag - multi-circuit move: @@ -96,7 +101,23 @@ Intent is separated by drag source type: The sidebar insertion controls use the same project-device placement rules as drag-and-drop. Invalid section and circuit options are disabled after selecting a project device. -Cross-section device moves show confirmation-required feedback before drop. The confirmation names source and target sections and warns that the unchanged device classification may need manual review. Cancelling leaves every row and circuit unchanged. Moving never renumbers existing circuits. +Cross-section device moves show confirmation-required feedback before drop. The confirmation names source and target sections and warns that the unchanged device classification may need manual review. Cancelling leaves every row and circuit unchanged. Device-row moves never renumber circuits; the explicitly initiated complete-circuit group move is the sole automatic BMK-changing move. + +## Protected Group and Component Controls + +- New groups are created manually in one of the three supported categories and + receive the highest existing category group number plus one. +- Group reorder buttons move only relative to category peers and never change a + group number or BMK. +- `Gruppen-BMK neu nummerieren` is an explicit confirmed category-wide action. + It follows the persisted group order and updates group prefixes, optional + `.0` protection BMKs and circuit BMKs together. +- Optional group upstream protection and group FI as well as auxiliary footer + components use labeled, type-dependent modals. +- Each circuit protection device uses its own modal; only fields valid for the + selected type are shown. +- Removing a populated group warns with circuit, device-row and group + protection counts. The complete deletion remains persistently undoable. ## Filtering and Sorting @@ -118,7 +139,8 @@ Cross-section device moves show confirmation-required feedback before drop. The - Column visibility and order are configurable. - BMK column (`equipmentIdentifier`) is locked as first column. -- Layout is saved in local storage (`circuitTreeEditor.columnLayout.v1`). +- Layout is saved in local storage under a project-specific key so switching + distribution boards preserves the same project layout. ## Undo/Redo @@ -138,8 +160,10 @@ Covered operations include: - insert/delete circuit - insert/delete row - edit cell values -- moves (single/bulk rows, circuit reorder) -- renumber and identifier update flows +- moves (single/bulk rows, circuit reorder and same-category group move) +- circuit and group renumber/identifier flows +- component, group and protection editing +- warned populated-group deletion and exact restoration - apply sorted order The editor toolbar exposes availability through its Undo/Redo buttons. The diff --git a/docs/circuit-list-editor-known-limitations.md b/docs/circuit-list-editor-known-limitations.md index 4913da5..d0f3ab5 100644 --- a/docs/circuit-list-editor-known-limitations.md +++ b/docs/circuit-list-editor-known-limitations.md @@ -16,5 +16,11 @@ - Final electrical sizing logic is not implemented yet. - No full norm-compliant voltage-drop and protection-dimensioning calculation flow yet. - Sorting is view-only until users explicitly apply sorted order. -- Cross-section circuit drag-reorder is intentionally blocked. +- Complete-circuit drag supports one circuit at a time between groups of the + same category. Cross-category moves and multi-circuit moves across group + boundaries are intentionally rejected; multi-circuit reorder inside one + group remains supported. +- Protection and cable values are planner-owned manual selections. The later + sizing/warning engine does not yet validate them against load, length or + voltage-drop rules. - Legacy consumer UI and server endpoints are removed; retained source rows and migration mappings remain available only for upgrade traceability. diff --git a/docs/current-architecture.md b/docs/current-architecture.md index 98feb35..358d9c4 100644 --- a/docs/current-architecture.md +++ b/docs/current-architecture.md @@ -296,15 +296,15 @@ einen vollständigen Zielzustand aus; ID, Eigentum, Rolle und Platzierungszone bleiben dabei unverändert. Projekt-, Listen- und Gruppenzugehörigkeit sowie veraltete Zustände werden innerhalb derselben Transaktion geprüft. Die festen Kopfkomponenten Hauptschalter und Überspannungsableiter sind von diesen -allgemeinen Commands ausgeschlossen. API- und Editorintegration folgen in den -nächsten Arbeitspaketen. +allgemeinen Commands ausgeschlossen. Veränderliche Gruppen- und Fußkomponenten +werden im Editor über eigene Modale und diese Commands verwaltet. Leere Stromkreisgruppen werden über `circuit-group.insert`, `circuit-group.update` und `circuit-group.delete` verwaltet. Ihr vollständiger Snapshot koppelt Kategorie, positive Gruppennummer und daraus abgeleiteten BMK-Präfix; allgemeine Updates ändern ausschließlich den Anzeigenamen. Löschen verlangt einen exakt unveränderten Zustand ohne Stromkreise und ohne -Gruppenkomponenten. Das bestätigte Löschen befüllter Unterbäume bleibt ein -eigener späterer Command. +Gruppenkomponenten. Befüllte Gruppen verwenden getrennt davon den vollständigen +`circuit-group.delete-subtree`-Command mit ausdrücklicher Warnung. `circuit-group.reorder` sortiert Gruppen als vollständige Stromkreislisten- Zuordnung. Jede vorhandene Gruppe muss mit erwarteter und neuer Position enthalten sein. Der Command verändert ausschließlich `sortOrder`; Nummern, @@ -481,8 +481,9 @@ Kopieren in ein Projekt erzeugt ein eigenständiges Projektgerät. veränderliche Verteilerkomponenten, Gruppen einschließlich befüllter Unterbäume sowie vollständige Gruppensortierung sind integriert. Der Editor zeigt die geschützte Struktur an und bearbeitet veränderliche Gruppen- und - Fußkomponenten über dedizierte Command-Modale. Gruppenverwaltung und - Stromkreisschutz folgen in weiteren abgegrenzten Arbeitspaketen. + Fußkomponenten über dedizierte Command-Modale. Gruppenanlage, -umbenennung, + -sortierung, explizite Neunummerierung, Same-Category-Stromkreiswechsel, + geschütztes Unterbaumlöschen und Stromkreisschutz sind integriert. PostgreSQL ist bewusst nicht implementiert. Die Domainregeln und Transaktionsgrenzen sollen portabel bleiben; Schema und Betriebsmodell benötigen diff --git a/docs/development-workflow.md b/docs/development-workflow.md index 175891c..b4447f0 100644 --- a/docs/development-workflow.md +++ b/docs/development-workflow.md @@ -45,10 +45,16 @@ Projekt- oder Kundendaten versehentlich ins Repository. Für einen lokalen Testbestand: 1. In der UI ein Projekt `Demo` anlegen. -2. Im Projekt eine Verteilung `UV-01` erstellen. +2. Im Projekt eine Verteilung `UV-01` erstellen. Die Stromkreisliste enthält + danach Hauptschalter, Überspannungsableiter und je eine Gruppe für + Beleuchtung, 1-phasige und 3-phasige Stromkreise. 3. Ein Projektgerät mit unkritischen Fantasiewerten anlegen. -4. Die erzeugte Stromkreisliste öffnen und das Gerät in einen passenden Bereich +4. Die erzeugte Stromkreisliste öffnen und das Gerät in eine passende Gruppe ziehen. +5. Optional eine zweite Gruppe derselben Kategorie, einen Gruppen-FI und ein + zusätzliches Verteilergerät anlegen. Damit lassen sich Gruppensortierung, + explizite Neunummerierung, Stromkreiswechsel und persistentes Undo/Redo ohne + reale Projekt- oder Kundendaten prüfen. Dateien unter `data/` und `data/backups/` dürfen nicht committed werden. diff --git a/docs/spec/08-current-product-backlog.md b/docs/spec/08-current-product-backlog.md index 2d929c3..22004c5 100644 --- a/docs/spec/08-current-product-backlog.md +++ b/docs/spec/08-current-product-backlog.md @@ -10,7 +10,7 @@ requirements and intended sequencing, not proof of implementation. ## Distribution Board Components and Protection Groups -- [ ] Implement the agreed protected circuit-group and distribution-board +- [x] Implement the agreed protected circuit-group and distribution-board component model in phased work packages. - [x] Phase A: central protection catalog, validation, defaults and pure grouped BMK rules. @@ -43,7 +43,7 @@ requirements and intended sequencing, not proof of implementation. - [x] Explicit same-category group renumbering updates prefixes and all child BMK atomically. - [x] Single-circuit moves between same-category groups with automatic next-free BMK assignment. - [x] Populated-group delete warning and explicit subtree deletion. -- [ ] Phase E: editor projection and editing. +- [x] Phase E: editor projection and editing. - [ ] Phase F: documentation and full GUI verification. - [ ] Keep full electrical sizing and cable-dimensioning rules separate until the planner supplies the calculation requirements. diff --git a/docs/spec/09-distribution-board-components-and-protection-groups.md b/docs/spec/09-distribution-board-components-and-protection-groups.md index ff96ed6..9a7c56c 100644 --- a/docs/spec/09-distribution-board-components-and-protection-groups.md +++ b/docs/spec/09-distribution-board-components-and-protection-groups.md @@ -2,10 +2,11 @@ ## Status -This document defines the agreed target behavior for distribution-board -components, protected circuit groups and circuit protection devices. Phase A -and the relational Phase-B1 foundation are implemented; later sections remain -requirements and are not proof of runtime or editor support. +This document records the agreed and implemented behavior for +distribution-board components, protected circuit groups and circuit +protection devices. Delivery phases A through E are complete. Phase F retains +the final GUI checklist; the current runtime paths are documented in +`docs/current-architecture.md`. Full rule-based protection and cable sizing is deliberately deferred. This phase establishes the structure and manually selected technical values that a @@ -739,12 +740,7 @@ Acceptance: ### E. Editor Projection and Editing -Status: In progress. The complete tree read model E1, pure structural -projection E2a, grid rendering E2b and mutable component editing E3a are -complete. Basic group management E3b1 is also complete. Circuit-protection -editing now has its persistent E3b2a command boundary; insertion defaults and -the editor modal are complete in E3b2b. Structural drag/renumber/delete -workflows remain pending. +Status: Complete. - render fixed header components - render group components and circuit blocks @@ -777,8 +773,8 @@ Implemented in E1/E2a/E2b/E3a: category's highest existing number plus one and its prefix is generated - group editing changes only the display name; category, number, prefix and child BMKs remain stable -- an exactly empty group can be removed through the persistent group command; - populated deletion stays disabled until the dedicated warning UI is present +- an exactly empty group can be removed through the compact persistent group + command - `circuit-protection.update` inserts or updates one validated 1:1 protection snapshot, rejects stale state and preserves exact persistent Undo/Redo - user commands cannot remove circuit protection; a nullable target exists @@ -791,6 +787,15 @@ Implemented in E1/E2a/E2b/E3a: the old flat protection columns now project the new 1:1 data read-only - group controls move a group only to the adjacent peer of the same category; the complete list order is one persistent command and no number or BMK changes +- explicit category-wide group renumbering follows the visible persisted group + order, updates every affected prefix and child BMK atomically and preserves + outgoing-circuit suffixes +- dragging one circuit into another group of the same category moves the + complete circuit and assigns the highest target suffix plus one; same-group + multi-circuit drag remains a pure reorder +- populated-group deletion shows the affected circuit, device-row and group + protection counts before sending the complete subtree to the guarded + delete/restore command Acceptance: @@ -801,8 +806,12 @@ Acceptance: ### F. Documentation and Full Verification +Status: Documentation and automated verification complete; GUI checklist +pending. + - update current architecture, API and interaction documentation -- update demo/sample data +- update the safe local demo-data instructions; no versioned customer-like + seed data is introduced - run focused domain and transaction tests - run the complete required test, build and type-check suite - perform the agreed GUI test checklist @@ -830,14 +839,15 @@ Acceptance: - Snapshot incompatibility: version payloads and test every supported upgrade path. -## Open Implementation Decisions +## Resolved Implementation Decisions -These decisions may be resolved during the relevant delivery phase without -changing the agreed domain behavior: - -- exact relational implementation of the shared BMK ownership boundary -- presentation of group ownership through indentation, headings or a column -- filter behavior for structural component rows +- a trigger-maintained circuit-list registry enforces shared BMK uniqueness + across circuits and distribution-board components +- group headings and full-width structural rows show ownership without adding + a permanent group column +- structural component rows remain outside editable-cell filtering and + spreadsheet navigation; circuit filtering continues to preserve complete + circuit blocks - explicit UI for converting retained legacy identifiers to grouped numbering - whether fixed header components become editable beyond name and BMK in this phase