Compare commits
2 Commits
3fbf3ac622
...
6b6d2c2a42
| Author | SHA1 | Date | |
|---|---|---|---|
| 6b6d2c2a42 | |||
| 30d6f1a2e1 |
@@ -2,12 +2,33 @@
|
||||
|
||||
## Project Goal
|
||||
|
||||
Build a spreadsheet-like electrical distribution board circuit list editor.
|
||||
Maintain and extend a spreadsheet-like electrical distribution board circuit list editor.
|
||||
|
||||
The editor is used for electrical planning in execution design.
|
||||
|
||||
It must support circuits, device rows, project devices, drag-and-drop restructuring, stable equipment identifiers and later electrical sizing logic.
|
||||
|
||||
## Current Supported Architecture
|
||||
|
||||
- Frontend: Next.js App Router under `src/app` with reusable editor modules under `src/frontend`.
|
||||
- API: Express composition starts in `src/server/index.ts`.
|
||||
- Domain rules: `src/domain`.
|
||||
- Persistence: SQLite/Drizzle schemas, repositories and migrations under `src/db`.
|
||||
- Primary editor route:
|
||||
`src/app/projects/[projectId]/circuit-lists/[circuitListId]/tree-edit/page.tsx`.
|
||||
- Primary editor component: `src/frontend/components/circuit-tree-editor.tsx`.
|
||||
- Grid ownership, projection, insertion and safety rules live in the pure
|
||||
`src/frontend/components/circuit-grid-*.ts` modules.
|
||||
- Critical multi-write commands use injected transaction repositories with real
|
||||
SQLite commit/rollback tests.
|
||||
|
||||
The supported runtime model is Circuit-First. The former Consumer UI and API are
|
||||
removed. Retained `consumers` rows, migration mappings and reports are upgrade-only
|
||||
data accessed by `npm run db:migrate:legacy-consumers`; do not build application
|
||||
features on them.
|
||||
|
||||
See `docs/current-architecture.md` for the complete module and request flow.
|
||||
|
||||
## Critical Domain Rules
|
||||
|
||||
- A circuit is not the same thing as one device row.
|
||||
@@ -112,6 +133,9 @@ Renumber only when the user explicitly triggers "Renumber section".
|
||||
|
||||
The circuit list table should behave like a spreadsheet.
|
||||
|
||||
User-facing frontend text must be German unless a domain-standard technical term
|
||||
is intentionally retained.
|
||||
|
||||
Cells show static text by default.
|
||||
|
||||
Inline edit starts by:
|
||||
@@ -196,7 +220,8 @@ After saving, the row becomes linked to the new project device.
|
||||
|
||||
## Undo / Redo
|
||||
|
||||
Implement undo/redo for structural and destructive operations.
|
||||
Session-local undo/redo exists for structural and destructive operations.
|
||||
Persistent project-wide undo/redo remains future work.
|
||||
|
||||
Required operations:
|
||||
|
||||
@@ -232,6 +257,46 @@ Future sizing will need:
|
||||
|
||||
Users must be able to override sizing suggestions.
|
||||
|
||||
## Persistence and Migration Rules
|
||||
|
||||
- SQLite is the currently supported database.
|
||||
- Never edit an already applied migration.
|
||||
- Back up an existing database before applying a new migration.
|
||||
- Inspect generated SQL; it must contain only the intended schema change.
|
||||
- Keep database backups separate from future logical project snapshots.
|
||||
- Do not import the global SQLite singleton into domain services.
|
||||
- Keep synchronous SQLite transaction behavior inside persistence adapters.
|
||||
- Preserve stable UUIDs and explicit transaction boundaries for a later
|
||||
PostgreSQL adapter.
|
||||
|
||||
## Current Deferred Work
|
||||
|
||||
- persistent project revisions and undo/redo
|
||||
- named logical snapshots and restore
|
||||
- Revit/CSV/IFCGUID round-trip
|
||||
- full electrical sizing
|
||||
- multi-user/PostgreSQL operation
|
||||
- supported production deployment
|
||||
|
||||
Do not implement these while working on an unrelated phase.
|
||||
|
||||
## Documentation and Verification
|
||||
|
||||
- `README.md` is the setup entry point.
|
||||
- `docs/README.md` is the documentation map.
|
||||
- `docs/current-architecture.md` describes current code paths.
|
||||
- `docs/spec/` contains requirements and roadmap, not proof of implementation.
|
||||
- `docs/archive/` is historical and must not drive current implementation.
|
||||
|
||||
For a normal code change run the relevant focused tests plus:
|
||||
|
||||
- `npm test`
|
||||
- `npm run build:api`
|
||||
- `npm run build:web`
|
||||
- `npx tsc --noEmit -p tsconfig.next.json`
|
||||
|
||||
Use a concise imperative commit message for each completed, verified work package.
|
||||
|
||||
## Response Style for Codex
|
||||
|
||||
Be concise.
|
||||
|
||||
@@ -1,225 +1,121 @@
|
||||
# Leistungsbilanz – Hauptdokumentation
|
||||
# Leistungsbilanz
|
||||
|
||||
Diese Anwendung unterstützt die elektrische Fachplanung (TGA/ELT) bei der Erstellung und Pflege von Leistungsbilanzen und Stromkreislisten.
|
||||
Leistungsbilanz ist eine Webanwendung für die elektrische Ausführungsplanung. Im
|
||||
Mittelpunkt steht ein tabellenähnlicher Stromkreislisten-Editor, der Stromkreise,
|
||||
Gerätezeilen und wiederverwendbare Projektgeräte fachlich getrennt behandelt.
|
||||
|
||||
Sie ist als praxisnahe Webanwendung für kleine Teams gedacht (ca. 2–3 gleichzeitige Nutzer), mit Schwerpunkt auf schneller tabellarischer Bearbeitung statt komplexer Enterprise-Strukturen.
|
||||
Das Projekt befindet sich in aktiver Entwicklung. Der lokale Entwicklungsbetrieb
|
||||
mit SQLite und Docker Compose ist unterstützt. Ein Produktionsdeployment,
|
||||
persistentes Undo/Redo, Projektversionen und der Revit-/IFCGUID-Datenaustausch sind
|
||||
noch nicht implementiert.
|
||||
|
||||
## Sinn und Ziel der Anwendung
|
||||
## Unterstützter Arbeitsablauf
|
||||
|
||||
Die Anwendung soll Planer dabei unterstützen:
|
||||
- Projekte, Verteilungen, Etagen und Räume verwalten
|
||||
- pro Verteilung eine Stromkreisliste mit festen Bereichen bearbeiten
|
||||
- leere, einzeilige und mehrzeilige Stromkreise abbilden
|
||||
- Stromkreise und Gerätezeilen per Drag-and-drop umstrukturieren
|
||||
- Projektgeräte einfügen, verknüpfen und kontrolliert synchronisieren
|
||||
- komplette Stromkreisblöcke filtern und sortieren
|
||||
- BMKs stabil halten und nur auf ausdrücklichen Befehl neu nummerieren
|
||||
- Änderungen innerhalb der aktuellen Editorsitzung rückgängig machen und wiederholen
|
||||
|
||||
1. Projekte anzulegen und zu verwalten.
|
||||
2. Verteilungen pro Projekt anzulegen.
|
||||
3. Verbraucher strukturiert in Stromkreislisten zu erfassen.
|
||||
4. Installierte Leistung, Gleichzeitigkeitsleistung und Strom automatisch zu berechnen.
|
||||
5. Gerätevorlagen global sowie projektbezogen zu verwalten und wiederzuverwenden.
|
||||
6. Planungsdaten schrittweise zu vervollständigen, ohne unnötige Pflichtfeldhürden.
|
||||
## Technik
|
||||
|
||||
Fachlich stehen folgende Begriffe im Zentrum:
|
||||
- Next.js 16, React 19 und TypeScript für das Frontend
|
||||
- Express 5 und Zod für die API
|
||||
- SQLite, `better-sqlite3` und Drizzle ORM für die Persistenz
|
||||
- eigener Spreadsheet-Grid statt eines Bootstrap-Tabellenframeworks
|
||||
- Node.js-Test-Runner für Domain-, Grid- und SQLite-Integrationstests
|
||||
|
||||
- Projekt
|
||||
- Verteilung
|
||||
- Stromkreisliste
|
||||
- Verbraucher/Gerät
|
||||
- installierte Leistung
|
||||
- Gleichzeitigkeitsfaktor
|
||||
- berechnete Leistung
|
||||
- Spannung (1-phasig / 3-phasig)
|
||||
- Strom
|
||||
## Schnellstart mit Docker
|
||||
|
||||
## Anforderungsbasis
|
||||
Voraussetzungen:
|
||||
|
||||
Die fachliche Basis stammt aus [docs/electrical-load-balance-requirements-context-dump.md](docs/electrical-load-balance-requirements-context-dump.md).
|
||||
- Git
|
||||
- Docker Desktop mit Docker Compose
|
||||
|
||||
Die folgende Liste fasst die zentralen Anforderungen zusammen und zeigt den aktuellen Umsetzungsstand im Code.
|
||||
```powershell
|
||||
git clone <repository-url>
|
||||
Set-Location leistungsbilanz-ts
|
||||
docker compose up --build --detach
|
||||
```
|
||||
|
||||
## Anforderungsliste mit Ist-Stand
|
||||
Danach:
|
||||
|
||||
### 1) Projektverwaltung
|
||||
- Anforderung: Projekte erstellen und anzeigen.
|
||||
- Status: Erfüllt.
|
||||
- Umsetzung: UI in `src/app/projects/page.tsx`, API in `src/server/controllers/project.controller.ts`.
|
||||
- Frontend: <http://localhost:3001>
|
||||
- API-Healthcheck: <http://localhost:3000/health>
|
||||
|
||||
### 2) Verteilungen pro Projekt
|
||||
- Anforderung: Mehrere Verteilungen pro Projekt.
|
||||
- Status: Erfüllt.
|
||||
- Umsetzung: `src/server/controllers/distribution-board.controller.ts`, `src/app/projects/[projectId]/page.tsx`.
|
||||
Der API-Container führt ausstehende Migrationen und die Schemaprüfung beim Start
|
||||
automatisch aus. Die SQLite-Datei liegt auf dem Host unter
|
||||
`data/leistungsbilanz.db` und bleibt beim Stoppen erhalten.
|
||||
|
||||
### 3) Genau eine Stromkreisliste pro Verteilung
|
||||
- Anforderung: Jede Verteilung besitzt genau eine Stromkreisliste.
|
||||
- Status: Erfüllt.
|
||||
- Umsetzung: Beim Erstellen einer Verteilung wird automatisch eine Stromkreisliste angelegt (`createDistributionBoard` + `CircuitListRepository.createForDistributionBoard`).
|
||||
```powershell
|
||||
docker compose ps
|
||||
docker compose logs --follow
|
||||
docker compose down
|
||||
```
|
||||
|
||||
### 4) Tabellarische Stromkreisbearbeitung
|
||||
- Anforderung: Einträge als Tabellenzeilen anlegen, bearbeiten, löschen.
|
||||
- Status: Erfüllt.
|
||||
- Umsetzung: `src/app/projects/[projectId]/circuit-lists/page.tsx`, API `src/server/controllers/consumer.controller.ts`.
|
||||
Der Compose-Stack startet Entwicklungsserver mit Quellcode-Mounts. Er ist kein
|
||||
Produktionsdeployment. Details stehen in
|
||||
[Deployment und Betrieb](docs/deployment.md).
|
||||
|
||||
### 5) Bis zu drei parallele Stromkreislisten
|
||||
- Anforderung: 1–3 Listen parallel, Standard = 1, inkl. Kopieren zwischen Listen.
|
||||
- Status: Erfüllt.
|
||||
- Umsetzung: `activeListCount`, Slot-Logik und Kopierfunktionen in `src/app/projects/[projectId]/circuit-lists/page.tsx`.
|
||||
## Direkte lokale Entwicklung
|
||||
|
||||
### 6) Geräteverwaltung global + projektbezogen
|
||||
- Anforderung: Globale Geräteliste und Projektgeräteliste.
|
||||
- Status: Erfüllt.
|
||||
- Umsetzung: Seiten `src/app/projects/page.tsx` und `src/app/projects/[projectId]/page.tsx`, API-Routen für `global-devices` und `project-devices`.
|
||||
Voraussetzungen:
|
||||
|
||||
### 7) Geräte zwischen global und Projekt kopieren
|
||||
- Anforderung: Kopieren in beide Richtungen.
|
||||
- Status: Erfüllt.
|
||||
- Umsetzung: `copyGlobalDeviceToProject` und `copyProjectDeviceToGlobal`.
|
||||
- Node.js 22
|
||||
- npm
|
||||
|
||||
### 8) `name` + `displayName` bei Geräten
|
||||
- Anforderung: Interner Name und Anzeigename getrennt.
|
||||
- Status: Erfüllt.
|
||||
- Umsetzung: DB-Schema, Validierung, UI und Copy-Flows sind angepasst.
|
||||
```powershell
|
||||
npm ci
|
||||
npm run db:migrate
|
||||
npm run db:verify:circuit-schema
|
||||
npm run dev:api
|
||||
```
|
||||
|
||||
### 9) Geräte-Link an Stromkreiseinträgen
|
||||
- Anforderung: Eintrag kann mit Projektgerät verknüpft/entkoppelt werden; verknüpfte Einträge aktualisieren sich bei Geräteänderung.
|
||||
- Status: Erfüllt.
|
||||
- Umsetzung: Felder `projectDeviceId` + `isLinkedToDevice`, Sync in `syncLinkedConsumersFromProjectDevice`.
|
||||
In einem zweiten Terminal:
|
||||
|
||||
### 10) Unvollständige Einträge zulassen
|
||||
- Anforderung: Einträge sollen grundsätzlich auch unvollständig möglich sein.
|
||||
- Status: Teilweise erfüllt.
|
||||
- Umsetzung: Backend akzeptiert optionale Kernfelder und setzt Defaults.
|
||||
- Hinweis: Das manuelle Schnellformular im UI verlangt weiterhin einen Namen für den direkten Anlege-Flow.
|
||||
```powershell
|
||||
npm run dev:web
|
||||
```
|
||||
|
||||
### 11) Add Count (mehrere Einträge aus einem Gerät erzeugen)
|
||||
- Anforderung: getrennt von `quantity`.
|
||||
- Status: Erfüllt.
|
||||
- Umsetzung: `addCount` bei „Projektgerät übernehmen“ in der Stromkreislistenansicht.
|
||||
Frontend und API laufen anschließend auf denselben Ports wie im Docker-Setup.
|
||||
|
||||
### 12) Duplizieren und Kopieren von Einträgen
|
||||
- Anforderung: Duplizieren in derselben Liste + Kopieren in andere Listen.
|
||||
- Status: Erfüllt.
|
||||
- Umsetzung: Zeilenaktionen „Dupl.“ und Listenkopie, plus Auswahl-Kopie.
|
||||
## Qualitätssicherung
|
||||
|
||||
### 13) Sortieren, Filtern, Bulk-Edit
|
||||
- Anforderung: erweiterte Tabellenfunktionen.
|
||||
- Status: Erfüllt (Basisumfang).
|
||||
- Umsetzung: Filterfeld, Sortierfeld/-richtung und Sammeländerung für Auswahlwerte.
|
||||
```powershell
|
||||
npm test
|
||||
npm run build:api
|
||||
npm run build:web
|
||||
npx tsc --noEmit -p tsconfig.next.json
|
||||
```
|
||||
|
||||
### 14) Räume und Etagen
|
||||
- Anforderung: Projektbezogene Räume/Etagen und Zuordnung zu Einträgen.
|
||||
- Status: Erfüllt.
|
||||
- Umsetzung: Floors/Rooms in Projektansicht und Raumzuordnung in Stromkreisliste.
|
||||
Wichtige Datenbankbefehle:
|
||||
|
||||
### 15) Projektspezifische Spannungsstandards (1-ph/3-ph)
|
||||
- Anforderung: 230 V / 400 V als Standard, in Projekteigenschaften editierbar, in Berechnung verwendet.
|
||||
- Status: Erfüllt.
|
||||
- Umsetzung: Projekteinstellungen + Nutzung in Berechnungsservice.
|
||||
```powershell
|
||||
npm run db:backup
|
||||
npm run db:migrate
|
||||
npm run db:verify:circuit-schema
|
||||
npm run db:generate
|
||||
```
|
||||
|
||||
### 16) Spaltensteuerung in der Tabelle
|
||||
- Anforderung: Attribute ein-/ausblenden und Spaltenreihenfolge ändern.
|
||||
- Status: Erfüllt.
|
||||
- Umsetzung: Spaltenmanager in `circuit-lists/page.tsx`.
|
||||
`db:backup` verwendet die SQLite-Online-Backup-API und prüft das Ergebnis auf
|
||||
Integrität und Fremdschlüsselverletzungen. Vor jeder Migration einer bestehenden
|
||||
Datenbank ist ein Backup erforderlich.
|
||||
|
||||
### 17) Feste Auswahllisten für Domänenfelder
|
||||
- Anforderung: feste Werte für Felder wie `deviceType`, `phaseType`, Schutz/Kabel usw.
|
||||
- Status: Erfüllt.
|
||||
- Umsetzung: zentrale Listen in `src/shared/constants/consumer-option-lists.ts`, Validierung über `z.enum(...)`, UI-Selects.
|
||||
`db:migrate:legacy-consumers` und `db:backfill:sections` sind ausschließlich
|
||||
Upgrade-Werkzeuge für ältere Datenbanken. Neue Installationen benötigen sie nicht.
|
||||
|
||||
### 18) Tests über reine Formeln hinaus
|
||||
- Anforderung: zusätzliche Tests für Link-/Eintragsverhalten.
|
||||
- Status: Erfüllt.
|
||||
- Umsetzung: `tests/consumer-linking.service.test.ts` und `tests/consumer-schema-options.test.ts`.
|
||||
## Dokumentation
|
||||
|
||||
## Technische Architektur (für neue Entwickler)
|
||||
- [Dokumentationsübersicht](docs/README.md)
|
||||
- [Aktuelle Architektur](docs/current-architecture.md)
|
||||
- [Editor-Interaktionen](docs/circuit-list-editor-interactions.md)
|
||||
- [API des Stromkreislisten-Editors](docs/circuit-list-editor-api.md)
|
||||
- [Entwicklungs- und Contributor-Workflow](docs/development-workflow.md)
|
||||
- [Bekannte Einschränkungen](docs/circuit-list-editor-known-limitations.md)
|
||||
- [Roadmap](docs/spec/07-implementation-phases-todo.md)
|
||||
|
||||
### Backend
|
||||
- Node.js + Express
|
||||
- Einstieg: `src/server/index.ts`
|
||||
- API-Module:
|
||||
- Projekte/Verteilungen/Räume/Etagen
|
||||
- Verbraucher (Stromkreiseinträge)
|
||||
- globale und projektbezogene Geräte
|
||||
|
||||
### Frontend
|
||||
- Next.js (App Router) + React + Bootstrap
|
||||
- Hauptseiten:
|
||||
- `src/app/projects/page.tsx` (Projektliste + globale Geräte)
|
||||
- `src/app/projects/[projectId]/page.tsx` (Projektdetails, Verteilungen, Räume/Etagen, Projektgeräte)
|
||||
- `src/app/projects/[projectId]/circuit-lists/page.tsx` (Stromkreislisten-Editor)
|
||||
|
||||
### Datenbank
|
||||
- SQLite + Drizzle ORM
|
||||
- Schema unter `src/db/schema`
|
||||
- Migrationen unter `src/db/migrations`
|
||||
|
||||
### Domänen- und Rechenlogik
|
||||
- Berechnung: `src/domain/calculations/power-calculation.ts`
|
||||
- Anreicherung/Businesslogik: `src/domain/services/power-balance.service.ts`
|
||||
- Geräte-Link-Logik: `src/domain/services/consumer-linking.service.ts`
|
||||
|
||||
## Schneller Entwicklungsstart
|
||||
|
||||
### Mit Docker (empfohlen fuer kurze Sessions)
|
||||
|
||||
Voraussetzung: Docker Desktop mit aktivem Docker-Compose-Plugin.
|
||||
|
||||
1. Sicherstellen, dass keine direkt gestartete API und kein direkt gestartetes Frontend mehr auf Port 3000/3001 laufen.
|
||||
2. `npm run docker:up` (baut und startet beide Container im Hintergrund)
|
||||
3. Frontend unter `http://localhost:3001` oeffnen.
|
||||
|
||||
Beim Start fuehrt der API-Container ausstehende Drizzle-Migrationen und die Circuit-First-Schemapruefung aus. Die vorhandene SQLite-Datenbank wird ueber `./data:/app/data` eingebunden und bleibt nach `npm run docker:down` erhalten. Quellcodeaenderungen unter `src/` werden von beiden Entwicklungsservern automatisch erkannt.
|
||||
|
||||
Weitere Docker-Befehle:
|
||||
|
||||
- `npm run docker:down` - Frontend und API stoppen
|
||||
- `npm run docker:logs` - laufende Containerlogs anzeigen (`Ctrl+C` beendet nur die Logansicht)
|
||||
- `docker compose ps` - Status und Healthchecks anzeigen
|
||||
- `Invoke-WebRequest http://localhost:3000/health` - API-Healthcheck pruefen
|
||||
|
||||
Bewusster Datenbank-Reset unter PowerShell:
|
||||
|
||||
1. `npm run docker:down`
|
||||
2. `npm run db:backup`
|
||||
3. `Remove-Item -LiteralPath .\data\leistungsbilanz.db`
|
||||
4. `npm run docker:up`
|
||||
|
||||
Der Reset entfernt die aktive lokale Datenbank. Die zuvor erzeugte Sicherung bleibt unter `data/backups/` erhalten.
|
||||
|
||||
### Ohne Docker
|
||||
|
||||
1. `npm install`
|
||||
2. `npm run db:migrate`
|
||||
3. `npm run db:verify:circuit-schema`
|
||||
4. `npm run dev:api` (API auf Port 3000)
|
||||
5. In einem zweiten Terminal `npm run dev:web` (Frontend auf Port 3001)
|
||||
|
||||
## Wichtige Befehle
|
||||
|
||||
- `npm run dev:api` – API lokal starten
|
||||
- `npm run dev:web` – Frontend lokal starten
|
||||
- `npm run build:api` – Backend bauen
|
||||
- `npm run build:web` – Frontend bauen
|
||||
- `npm test` – Testlauf
|
||||
- `npm run db:generate` – Migrationen generieren
|
||||
- `npm run db:migrate` – Migrationen ausführen
|
||||
|
||||
### Circuit-First lokale Migration
|
||||
|
||||
- `npm run db:backup` – lokale SQLite sichern
|
||||
- `npm run db:migrate` – pending Migrationen ausführen
|
||||
- `npm run db:verify:circuit-schema` – Circuit-First Tabellenprüfung
|
||||
- `npm run db:backfill:sections` – Default-Sections für bestehende Listen anlegen
|
||||
- `npm run db:migrate:legacy-consumers` – Legacy-Consumers explizit in Circuit-First überführen
|
||||
|
||||
Siehe auch: `docs/local-db-circuit-first-migration.md`
|
||||
|
||||
## Ergänzende Dokumente
|
||||
|
||||
- Anforderungen (Quelle): [docs/electrical-load-balance-requirements-context-dump.md](docs/electrical-load-balance-requirements-context-dump.md)
|
||||
- Abgleich „Anforderung vs. Implementierung“: [docs/anforderungs-abgleich.md](docs/anforderungs-abgleich.md)
|
||||
|
||||
## Circuit-List Editor Dokumentation
|
||||
|
||||
- Architektur: [docs/circuit-list-editor-architecture.md](docs/circuit-list-editor-architecture.md)
|
||||
- Interaktionen: [docs/circuit-list-editor-interactions.md](docs/circuit-list-editor-interactions.md)
|
||||
- API: [docs/circuit-list-editor-api.md](docs/circuit-list-editor-api.md)
|
||||
- Migration: [docs/circuit-list-editor-migration.md](docs/circuit-list-editor-migration.md)
|
||||
- Bekannte Limitierungen: [docs/circuit-list-editor-known-limitations.md](docs/circuit-list-editor-known-limitations.md)
|
||||
|
||||
Diese Dokumente beschreiben den aktuellen circuit-first Editorstand und dienen als sichere Entwicklungsbasis fuer Folgeschritte.
|
||||
Für LLM-gestützte Änderungen enthält [AGENTS.md](AGENTS.md) die verbindlichen
|
||||
Domänenregeln, unterstützten Einstiegspunkte und Architekturgrenzen.
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
# Dokumentationsübersicht
|
||||
|
||||
Diese Seite ist der Einstieg in die Projektdokumentation. Aussagen zum aktuellen
|
||||
System stehen unter „Aktuell“. Zukunftsentwürfe und historische Unterlagen sind
|
||||
ausdrücklich getrennt und dürfen nicht als bereits implementiert verstanden werden.
|
||||
|
||||
## Aktuell
|
||||
|
||||
- [Aktuelle Systemarchitektur](current-architecture.md) – Laufzeit, Modulgrenzen,
|
||||
Datenfluss und unterstützte Codepfade
|
||||
- [Stromkreislisten-Architektur](circuit-list-editor-architecture.md) –
|
||||
fachliches Modell und Grid-Aufteilung
|
||||
- [Editor-Interaktionen](circuit-list-editor-interactions.md) – Tastatur,
|
||||
Drag-and-drop, Sortierung, Filterung und Undo/Redo
|
||||
- [Editor-API](circuit-list-editor-api.md) – unterstützte Circuit-First-Endpunkte
|
||||
- [Bekannte Einschränkungen](circuit-list-editor-known-limitations.md) –
|
||||
bewusst noch nicht implementierte oder begrenzte Funktionen
|
||||
|
||||
## Entwicklung und Betrieb
|
||||
|
||||
- [Entwicklungs- und Contributor-Workflow](development-workflow.md)
|
||||
- [Deployment und Betrieb](deployment.md)
|
||||
- [Lokale Circuit-First-Datenbankmigration](local-db-circuit-first-migration.md)
|
||||
- [Retained Legacy-Datenmigration](circuit-list-editor-migration.md) –
|
||||
ausschließlich für Upgrades alter Datenbanken
|
||||
|
||||
## Zukunftsarchitektur
|
||||
|
||||
- [Projektversionen und externer Modellaustausch](project-history-and-external-model-architecture.md)
|
||||
- [Zukünftige Dimensionierung](spec/06-future-sizing-and-calculations.md)
|
||||
- [Roadmap und Phasen](spec/07-implementation-phases-todo.md)
|
||||
|
||||
## Fachliche Referenzspezifikation
|
||||
|
||||
Die folgenden Dokumente beschreiben Zielregeln und Anforderungen. Nicht jeder
|
||||
Punkt ist bereits umgesetzt; der aktuelle Stand ergibt sich aus Architektur,
|
||||
Limitierungen und Roadmap.
|
||||
|
||||
- [Domänenkontext](spec/01-domain-context.md)
|
||||
- [Funktionale Anforderungen](spec/02-functional-requirements.md)
|
||||
- [Datenmodellkonzept](spec/03-data-model-concept.md)
|
||||
- [UI- und Interaktionsanforderungen](spec/04-ui-interaction-requirements.md)
|
||||
- [Verknüpfte Projektgeräte und Synchronisierung](spec/05-linked-devices-and-sync.md)
|
||||
|
||||
## Archiv
|
||||
|
||||
- [Frühe Codex-Promptvorlagen](archive/initial-codex-prompts.md) – historischer
|
||||
Arbeitsstand, keine aktuelle Implementierungsanweisung
|
||||
@@ -1,4 +1,8 @@
|
||||
# Codex Prompt Templates
|
||||
# Archived Initial Codex Prompt Templates
|
||||
|
||||
> Historical document. These prompts predate the supported Circuit-First
|
||||
> architecture and must not be used as current implementation instructions. Use
|
||||
> `AGENTS.md`, `docs/current-architecture.md` and the current roadmap instead.
|
||||
|
||||
Use these prompts step by step. Do not ask Codex to build the whole application in one pass.
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
## Scope
|
||||
|
||||
The circuit-first editor uses tree + circuit + row endpoints. Legacy consumer endpoints still exist for compatibility and migration, but should not be extended for new circuit-list behavior.
|
||||
The circuit-first editor uses tree, circuit, row and project-device endpoints.
|
||||
All paths below are mounted below `/api`. There is no Consumer application API.
|
||||
|
||||
## Circuit-First Endpoints
|
||||
|
||||
|
||||
@@ -40,9 +40,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.
|
||||
- Legacy `Consumer`
|
||||
- Old row-first model still present for compatibility/migration.
|
||||
- Should not be extended for new circuit-list behavior.
|
||||
- Retained legacy migration source
|
||||
- Old `consumers` rows, mappings and reports are available only to explicit
|
||||
database upgrade tooling.
|
||||
- They are not application-domain entities and have no UI or API.
|
||||
|
||||
## Why A Circuit Is Not One Row
|
||||
|
||||
@@ -104,10 +105,14 @@ Primary circuit-first editor route:
|
||||
|
||||
- `/projects/:projectId/circuit-lists/:circuitListId/tree-edit`
|
||||
|
||||
Legacy route remains separate (read-only/preview/migration transition path) and is intentionally not merged into the editable tree editor.
|
||||
The sibling `/tree` route is a read-only structure preview. Old
|
||||
`/projects/:projectId/circuit-lists` bookmarks redirect to the project page.
|
||||
|
||||
## 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).
|
||||
|
||||
Near-term refactoring must move command and transaction ownership toward server-side, project-scoped change sets. Database backups remain separate from user-visible project snapshots.
|
||||
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.
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
- No project revision or logical snapshot model is implemented yet.
|
||||
- No Revit/CSV/IFCGUID import and export workflow is implemented yet.
|
||||
- Persistence currently targets local SQLite; PostgreSQL is an architectural option, not an implemented runtime.
|
||||
- No global cross-project device library workflow is implemented yet.
|
||||
- The global device library supports basic CRUD and copy operations, but has no
|
||||
versioning, permissions or controlled synchronization model.
|
||||
- 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.
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
# Circuit List Editor Migration
|
||||
|
||||
## Status
|
||||
|
||||
Upgrade-only. New installations already use the Circuit-First schema and do not
|
||||
run this workflow.
|
||||
|
||||
## Goal
|
||||
|
||||
Migrate legacy row-first consumers into the circuit-first model without deleting legacy data.
|
||||
@@ -80,4 +85,6 @@ Do not delete legacy consumers yet.
|
||||
|
||||
- legacy read/write endpoints have been removed from the application server
|
||||
- migration trace tables reference old/new mapping
|
||||
- keeping legacy rows allows comparison and rollback validation during transition
|
||||
- retained rows allow upgrade verification and audit of the completed mapping
|
||||
- a future automatic cleanup migration must migrate and verify old databases
|
||||
before dropping these source and trace tables
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
# Aktuelle Systemarchitektur
|
||||
|
||||
## Status und unterstützter Pfad
|
||||
|
||||
Der unterstützte Editor ist Circuit-First:
|
||||
|
||||
`Project → DistributionBoard → CircuitList → CircuitSection → Circuit → CircuitDeviceRow`
|
||||
|
||||
Ein Stromkreis ist nicht dasselbe wie eine Gerätezeile. BMK, Schutz- und Kabeldaten
|
||||
gehören zum Stromkreis; Last-, Raum- und Kategoriedaten gehören zur Gerätezeile.
|
||||
|
||||
Die frühere Consumer-Oberfläche und ihre API sind entfernt. Die Tabelle
|
||||
`consumers` sowie Mappings und Reports bleiben ausschließlich erhalten, damit
|
||||
ältere Datenbanken über den expliziten Upgrade-Befehl migriert und geprüft werden
|
||||
können.
|
||||
|
||||
## Laufzeit
|
||||
|
||||
```text
|
||||
Browser :3001
|
||||
│
|
||||
▼
|
||||
Next.js App Router ── /api/* Rewrite ──▶ Express API :3000
|
||||
│
|
||||
▼
|
||||
Repository / Transaktion
|
||||
│
|
||||
▼
|
||||
data/leistungsbilanz.db (SQLite)
|
||||
```
|
||||
|
||||
Im Docker-Entwicklungssetup laufen Frontend und API in getrennten Containern. Das
|
||||
Frontend leitet `/api/*` über `API_INTERNAL_URL` an die API weiter. Die Datenbank
|
||||
liegt über einen Host-Mount außerhalb des Containers.
|
||||
|
||||
## Wichtige Einstiegspunkte
|
||||
|
||||
- `src/app/projects/page.tsx` – Projektliste und globale Gerätebibliothek
|
||||
- `src/app/projects/[projectId]/page.tsx` – Projektstammdaten, Verteilungen,
|
||||
Räume und Projektgeräte
|
||||
- `src/app/projects/[projectId]/circuit-lists/[circuitListId]/tree-edit/page.tsx`
|
||||
– unterstützte Editorroute
|
||||
- `src/frontend/components/circuit-tree-editor.tsx` – Editorzustand,
|
||||
Befehlsausführung, Drag-and-drop und sitzungslokales Undo/Redo
|
||||
- `src/frontend/components/circuit-grid-*.ts` – reine Grid-Projektion,
|
||||
Zellbesitz, Einfügen und Sicherheitsregeln
|
||||
- `src/frontend/utils/api.ts` – typisierte Frontend-API-Aufrufe
|
||||
- `src/server/index.ts` und `src/server/routes/` – API-Komposition
|
||||
- `src/domain/services/` – fachliche Command- und Synchronisierungsregeln
|
||||
- `src/db/repositories/` – Abfragen, Persistenzmapper und Transaktionsadapter
|
||||
- `src/db/schema/` und `src/db/migrations/` – SQLite-Schema und Migrationen
|
||||
|
||||
## Daten- und Befehlsfluss
|
||||
|
||||
1. Das Grid projiziert den geladenen Circuit-Tree in sichtbare Zeilen.
|
||||
2. Eine Benutzeraktion wird im Frontend validiert und als API-Befehl gesendet.
|
||||
3. Controller validieren Requestdaten mit Zod.
|
||||
4. Domain-Services prüfen fachliche Regeln wie BMK-Eindeutigkeit,
|
||||
Abschnittszuordnung und Reserveverhalten.
|
||||
5. Repositories schreiben Daten. Kritische Mehrfachschreibvorgänge besitzen
|
||||
explizite SQLite-Transaktionsadapter mit Commit-/Rollback-Integrationstests.
|
||||
6. Das Frontend lädt den Circuit-Tree neu und stellt Auswahl beziehungsweise
|
||||
Viewport soweit möglich wieder her.
|
||||
|
||||
Die React-Historie ist derzeit sitzungslokal. Persistente Projektrevisionen,
|
||||
optimistische Revisionsprüfungen und serverseitiges Undo/Redo sind die nächste
|
||||
Architekturphase.
|
||||
|
||||
## Projektgeräte
|
||||
|
||||
`ProjectDevice` verwendet ausschließlich die kanonischen Circuit-First-Felder:
|
||||
`phaseType`, `powerPerUnit`, `simultaneityFactor`, `cosPhi`, `remark` sowie
|
||||
optionale technische und kategorisierende Felder.
|
||||
|
||||
Beim Einfügen entsteht eine verknüpfte `CircuitDeviceRow`. Der Anzeigename wird
|
||||
kopiert, aber nicht still synchronisiert. Spätere Änderungen am Projektgerät
|
||||
werden als Diff angezeigt und nur für ausdrücklich gewählte Felder und Zeilen
|
||||
übernommen.
|
||||
|
||||
Die globale Gerätebibliothek ist ein einfacher, datenbankweiter Vorlagenbestand.
|
||||
Kopieren in ein Projekt erzeugt ein eigenständiges Projektgerät.
|
||||
|
||||
## Persistenz und Migration
|
||||
|
||||
- SQLite ist die aktuell unterstützte Datenbank.
|
||||
- Fremdschlüssel werden für jeden Datenbankkontext aktiviert.
|
||||
- `npm run db:migrate` wendet Drizzle-Migrationen an.
|
||||
- `npm run db:verify:circuit-schema` prüft erforderliche und entfernte Spalten.
|
||||
- `npm run db:backup` erzeugt ein konsistentes und verifiziertes Online-Backup.
|
||||
- Angewendete Migrationen werden niemals nachträglich verändert.
|
||||
- `db:migrate:legacy-consumers` ist Upgrade-Werkzeug, kein Anwendungspfad.
|
||||
|
||||
PostgreSQL ist bewusst nicht implementiert. Die Domainregeln und
|
||||
Transaktionsgrenzen sollen portabel bleiben; Schema und Betriebsmodell benötigen
|
||||
bei einem späteren Wechsel trotzdem einen eigenen PostgreSQL-Adapter.
|
||||
|
||||
## Noch nicht unterstützt
|
||||
|
||||
- persistentes Undo/Redo und Projektversionen
|
||||
- Mehrbenutzerbetrieb und Konfliktauflösung
|
||||
- Revit-/CSV-/IFCGUID-Round-trip
|
||||
- vollständige elektrische Dimensionierung
|
||||
- Produktionsdeployment
|
||||
|
||||
Details: [Bekannte Einschränkungen](circuit-list-editor-known-limitations.md) und
|
||||
[Zukunftsarchitektur](project-history-and-external-model-architecture.md).
|
||||
@@ -0,0 +1,60 @@
|
||||
# Deployment und Betrieb
|
||||
|
||||
## Aktueller Status
|
||||
|
||||
Es gibt derzeit kein unterstütztes Produktionsdeployment.
|
||||
|
||||
`compose.yaml` ist ausschließlich für lokale Entwicklung vorgesehen. Es startet
|
||||
`tsx watch` und `next dev`, bindet Quellcode vom Host ein und enthält weder TLS,
|
||||
Authentifizierung, Reverse Proxy, Prozesshärtung noch ein zentral betriebenes
|
||||
Datenbanksystem. Der Stack darf deshalb nicht als produktionsreif bezeichnet oder
|
||||
öffentlich erreichbar gemacht werden.
|
||||
|
||||
## Entwicklungs-Topologie
|
||||
|
||||
| Komponente | Port | Healthcheck | Persistenz |
|
||||
| --- | ---: | --- | --- |
|
||||
| Next.js Web | 3001 | `GET /` | keine |
|
||||
| Express API | 3000 | `GET /health` | `./data:/app/data` |
|
||||
| SQLite | Datei | Integritäts-/FK-Prüfung via Backup und Skript | `data/leistungsbilanz.db` |
|
||||
|
||||
Verwendete Umgebungsvariablen:
|
||||
|
||||
- `PORT` – API-Port, Standard `3000`
|
||||
- `API_INTERNAL_URL` – internes API-Ziel des Next.js-Rewrites, im Compose-Netz
|
||||
`http://api:3000`
|
||||
- `NEXT_TELEMETRY_DISABLED=1`
|
||||
- `CHOKIDAR_USEPOLLING=true` und `WATCHPACK_POLLING=true` für lokale
|
||||
Dateibeobachtung in Docker
|
||||
|
||||
Beim API-Start laufen zuerst `npm run db:migrate` und
|
||||
`npm run db:verify:circuit-schema`.
|
||||
|
||||
## Voraussetzungen für ein späteres Produktionssetup
|
||||
|
||||
Vor einer produktiven Installation werden mindestens benötigt:
|
||||
|
||||
- reproduzierbare Produktionsimages und ein Next.js-Produktionsstartskript
|
||||
- TLS-Termination und Reverse Proxy
|
||||
- Authentifizierung, Autorisierung und Benutzer-/Rollenmodell
|
||||
- definierte Secrets- und Konfigurationsverwaltung
|
||||
- persistenter, gesicherter Datenbankbetrieb
|
||||
- kontrollierter einmaliger Migrationsschritt vor dem API-Rollout
|
||||
- Monitoring, strukturierte Logs und Alarmierung
|
||||
- getestete Backup-, Restore- und Rollback-Prozeduren
|
||||
- Entscheidung, ob SQLite für einen einzelnen Prozess genügt oder PostgreSQL für
|
||||
Mehrbenutzerbetrieb erforderlich ist
|
||||
|
||||
Bis diese Punkte umgesetzt und getestet sind, besteht die „Installation“ aus dem
|
||||
lokalen Entwicklungsstart in der README.
|
||||
|
||||
## Backup und Wiederherstellung
|
||||
|
||||
`npm run db:backup` erzeugt unter `data/backups/` ein konsistentes SQLite-Backup,
|
||||
öffnet es unabhängig und prüft Integrität sowie Fremdschlüssel. Diese
|
||||
Dateisicherungen sind von zukünftigen logischen Projektversionen getrennt.
|
||||
|
||||
Eine produktive Restore-Anweisung wird erst zusammen mit einem unterstützten
|
||||
Produktionsbetrieb veröffentlicht. Lokale Wiederherstellung darf nur bei
|
||||
gestoppter API, gegen eine separate Datei und nach erneuter Integritätsprüfung
|
||||
erfolgen.
|
||||
@@ -0,0 +1,110 @@
|
||||
# Entwicklungs- und Contributor-Workflow
|
||||
|
||||
## Erstes lokales Setup
|
||||
|
||||
Der empfohlene Einstieg ist Docker Compose:
|
||||
|
||||
```powershell
|
||||
docker compose up --build --detach
|
||||
docker compose ps
|
||||
```
|
||||
|
||||
Ein sauberer Clone enthält keine SQLite-Datenbank. Beim ersten Start werden
|
||||
`data/leistungsbilanz.db`, alle Tabellen und Migrationseinträge automatisch
|
||||
angelegt. Das Frontend ist unter <http://localhost:3001> erreichbar.
|
||||
|
||||
Für direkte Node.js-Entwicklung:
|
||||
|
||||
```powershell
|
||||
npm ci
|
||||
npm run db:migrate
|
||||
npm run db:verify:circuit-schema
|
||||
```
|
||||
|
||||
Danach `npm run dev:api` und `npm run dev:web` in getrennten Terminals starten.
|
||||
|
||||
## Leere lokale Datenbank
|
||||
|
||||
Eine bestehende lokale Datenbank lässt sich recoverable ersetzen:
|
||||
|
||||
```powershell
|
||||
docker compose down
|
||||
npm run db:backup
|
||||
Move-Item -LiteralPath .\data\leistungsbilanz.db .\data\leistungsbilanz.previous.db
|
||||
docker compose up --build --detach
|
||||
```
|
||||
|
||||
Die verschobene Datei und das verifizierte Backup bleiben lokal erhalten. Vor dem
|
||||
Verschieben müssen die Container beendet sein, damit keine WAL-Sidecar-Datei aktiv
|
||||
ist.
|
||||
|
||||
## Sichere Beispieldaten
|
||||
|
||||
Es gibt aktuell keinen versionierten Seed-Datensatz. Dadurch gelangen keine
|
||||
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.
|
||||
3. Ein Projektgerät mit unkritischen Fantasiewerten anlegen.
|
||||
4. Die erzeugte Stromkreisliste öffnen und das Gerät in einen passenden Bereich
|
||||
ziehen.
|
||||
|
||||
Dateien unter `data/` und `data/backups/` dürfen nicht committed werden.
|
||||
|
||||
## Arbeitsablauf für Änderungen
|
||||
|
||||
1. Von einem aktuellen Branch einen kleinen Feature- oder Fix-Branch erstellen.
|
||||
2. Relevante Domänenregeln in `AGENTS.md` und die aktuelle Architektur lesen.
|
||||
3. Änderungen in einem fachlich geschlossenen Paket umsetzen.
|
||||
4. Tests und Dokumentation proportional zur Änderung aktualisieren.
|
||||
5. Alle erforderlichen Prüfungen ausführen.
|
||||
6. Mit einer kurzen, prägnanten Nachricht committen.
|
||||
|
||||
Empfohlene Commitnachrichten sind imperativ und beschreiben das Ergebnis, zum
|
||||
Beispiel `Preserve circuit blocks during filtering`.
|
||||
|
||||
## Pflichtprüfungen
|
||||
|
||||
```powershell
|
||||
npm test
|
||||
npm run build:api
|
||||
npm run build:web
|
||||
npx tsc --noEmit -p tsconfig.next.json
|
||||
git diff --check
|
||||
```
|
||||
|
||||
Bei Docker- oder Laufzeitänderungen zusätzlich:
|
||||
|
||||
```powershell
|
||||
docker compose up --build --detach
|
||||
docker compose ps
|
||||
Invoke-WebRequest http://localhost:3000/health
|
||||
```
|
||||
|
||||
Bei sichtbaren Editoränderungen ist außerdem ein kurzer GUI-Test erforderlich.
|
||||
|
||||
## Migrationen
|
||||
|
||||
1. Bestehende lokale Datenbank sichern: `npm run db:backup`.
|
||||
2. Schema unter `src/db/schema/` ändern.
|
||||
3. `npm run db:generate` ausführen.
|
||||
4. Das generierte SQL vollständig prüfen; es darf nur die beabsichtigte Änderung
|
||||
enthalten.
|
||||
5. Upgrade-/Erhaltungstest ergänzen, wenn Spalten oder Beziehungen geändert
|
||||
werden.
|
||||
6. `npm test`, `npm run db:migrate` und
|
||||
`npm run db:verify:circuit-schema` ausführen.
|
||||
|
||||
Bereits angewendete SQL-Migrationen dürfen nicht geändert oder neu sortiert
|
||||
werden. Korrekturen erfolgen immer über eine neue Migration.
|
||||
|
||||
## Pull-Request-Handoff
|
||||
|
||||
Die Beschreibung sollte enthalten:
|
||||
|
||||
- fachliches Ergebnis
|
||||
- Datenmodell- und API-Auswirkung
|
||||
- ausgeführte Tests
|
||||
- erforderliche manuelle Migration oder GUI-Prüfung
|
||||
- bekannte Einschränkungen oder bewusst verschobene Arbeit
|
||||
@@ -2,6 +2,10 @@
|
||||
|
||||
This project uses SQLite at `data/leistungsbilanz.db` and Drizzle migrations in `src/db/migrations`.
|
||||
|
||||
This document is an upgrade runbook for databases created before the Circuit-First
|
||||
cutover. A clean installation only needs the normal `db:migrate` and schema
|
||||
verification steps documented in the main README.
|
||||
|
||||
## Safe command order
|
||||
|
||||
1. Backup local DB (required before schema/data migration)
|
||||
@@ -16,8 +20,9 @@ and requires both `PRAGMA integrity_check` and `PRAGMA foreign_key_check` to pas
|
||||
Database backups are operational recovery files and remain separate from the future
|
||||
user-visible project version history.
|
||||
|
||||
2. Apply pending schema migrations (includes `0008_circuit_first_model` and the additive
|
||||
`0009_project_device_circuit_fields` transition)
|
||||
2. Apply pending schema migrations (includes `0008_circuit_first_model`, the additive
|
||||
`0009_project_device_circuit_fields` transition and the post-cutover
|
||||
`0011_project_device_canonical_fields` cleanup)
|
||||
|
||||
```bash
|
||||
npm run db:migrate
|
||||
|
||||
@@ -129,13 +129,19 @@ Drizzle schemas and migrations are dialect-specific and will require a deliberat
|
||||
|
||||
## Near-Term Refactoring Constraints
|
||||
|
||||
Before implementing the future features:
|
||||
Completed foundation:
|
||||
|
||||
- add real SQLite rollback tests around the persistence boundary
|
||||
- stop adding direct imports of the global SQLite client to domain services
|
||||
- extract transaction ownership from oversized repositories incrementally
|
||||
- modularize editor history commands independently from UI rendering
|
||||
- preserve stable domain IDs during legacy cleanup
|
||||
- real SQLite commit/rollback tests cover critical multi-write commands
|
||||
- transaction ownership for row moves, synchronization, renumbering and migration
|
||||
is isolated in injected persistence adapters
|
||||
- database backup and independent restore verification are automated
|
||||
- the Consumer application path is removed and stable domain IDs are preserved
|
||||
- editor grid projection and safety rules are separated from React rendering
|
||||
|
||||
Remaining constraints before implementing history:
|
||||
|
||||
- model project-scoped command descriptions independently from React callbacks
|
||||
- route all future history-enabled mutations through one project revision boundary
|
||||
- do not model IFCGUID as an overloaded circuit equipment identifier
|
||||
- keep database backup/restore checks separate from project history tests
|
||||
|
||||
|
||||
@@ -344,6 +344,7 @@ Implemented foundation:
|
||||
- circuit and device-row persistence value mapping is separated from the general repositories
|
||||
- the legacy consumer UI and application read/write endpoints are removed after verified data cutover
|
||||
- retained legacy rows are accessible only through explicit database upgrade tooling
|
||||
- project devices no longer persist duplicate legacy power, phase, cosPhi or remark fields
|
||||
|
||||
## Phase 12: Project Revisions and Persistent Undo / Redo
|
||||
|
||||
@@ -451,3 +452,13 @@ Acceptance criteria:
|
||||
- an LLM receives domain invariants, current module boundaries and deferred architecture direction without relying on stale legacy files
|
||||
- every README command and internal documentation link is verified
|
||||
- production instructions describe a real tested deployment path or clearly state that none is supported yet
|
||||
|
||||
Implemented handoff:
|
||||
|
||||
- README is a concise setup and project entry point without prototype status lists
|
||||
- `docs/README.md` separates current, operational, future, specification and archived material
|
||||
- current runtime, module boundaries and upgrade-only legacy data are documented explicitly
|
||||
- contributor workflow covers clean databases, safe demo data, migrations, tests and commits
|
||||
- development Compose is clearly separated from the currently unsupported production deployment
|
||||
- `AGENTS.md` points LLM-assisted work to supported code paths and deferred architecture
|
||||
- obsolete frontend placeholder documents were removed and early Codex prompts were archived
|
||||
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "leistungsbilanz",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"description": "Spreadsheet-style circuit list editor for electrical distribution planning",
|
||||
"main": "dist/server/index.js",
|
||||
"scripts": {
|
||||
"dev": "npm run dev:api",
|
||||
@@ -14,8 +14,8 @@
|
||||
"build:api": "tsc -p tsconfig.json",
|
||||
"build:web": "next build",
|
||||
"start": "node dist/server/index.js",
|
||||
"test": "tsx --test tests/project-device-schema.test.ts tests/project-device-placement.service.test.ts tests/project-device-sync.service.test.ts tests/legacy-consumer-migration-planner.test.ts tests/legacy-consumer-migration.repository.test.ts tests/circuit-numbering.service.test.ts tests/circuit-write.rules.test.ts tests/circuit-power-calculation.test.ts tests/circuit-tree.controller.test.ts tests/circuit-grid-insertion.test.ts tests/circuit-grid-safety.test.ts tests/circuit-grid-model.test.ts tests/circuit-grid-projection.test.ts tests/distribution-board.repository.test.ts tests/circuit-device-row-transaction.repository.test.ts tests/project-device-row-sync.repository.test.ts tests/circuit-section-transaction.repository.test.ts tests/database-backup.test.ts",
|
||||
"test:watch": "tsx --watch --test tests/project-device-schema.test.ts tests/project-device-placement.service.test.ts tests/project-device-sync.service.test.ts tests/legacy-consumer-migration-planner.test.ts tests/legacy-consumer-migration.repository.test.ts tests/circuit-numbering.service.test.ts tests/circuit-write.rules.test.ts tests/circuit-power-calculation.test.ts tests/circuit-tree.controller.test.ts tests/circuit-grid-insertion.test.ts tests/circuit-grid-safety.test.ts tests/circuit-grid-model.test.ts tests/circuit-grid-projection.test.ts tests/distribution-board.repository.test.ts tests/circuit-device-row-transaction.repository.test.ts tests/project-device-row-sync.repository.test.ts tests/circuit-section-transaction.repository.test.ts tests/database-backup.test.ts",
|
||||
"test": "tsx --test tests/project-device-schema.test.ts tests/project-device-schema-migration.test.ts tests/project-device-placement.service.test.ts tests/project-device-sync.service.test.ts tests/legacy-consumer-migration-planner.test.ts tests/legacy-consumer-migration.repository.test.ts tests/circuit-numbering.service.test.ts tests/circuit-write.rules.test.ts tests/circuit-power-calculation.test.ts tests/circuit-tree.controller.test.ts tests/circuit-grid-insertion.test.ts tests/circuit-grid-safety.test.ts tests/circuit-grid-model.test.ts tests/circuit-grid-projection.test.ts tests/distribution-board.repository.test.ts tests/circuit-device-row-transaction.repository.test.ts tests/project-device-row-sync.repository.test.ts tests/circuit-section-transaction.repository.test.ts tests/database-backup.test.ts",
|
||||
"test:watch": "tsx --watch --test tests/project-device-schema.test.ts tests/project-device-schema-migration.test.ts tests/project-device-placement.service.test.ts tests/project-device-sync.service.test.ts tests/legacy-consumer-migration-planner.test.ts tests/legacy-consumer-migration.repository.test.ts tests/circuit-numbering.service.test.ts tests/circuit-write.rules.test.ts tests/circuit-power-calculation.test.ts tests/circuit-tree.controller.test.ts tests/circuit-grid-insertion.test.ts tests/circuit-grid-safety.test.ts tests/circuit-grid-model.test.ts tests/circuit-grid-projection.test.ts tests/distribution-board.repository.test.ts tests/circuit-device-row-transaction.repository.test.ts tests/project-device-row-sync.repository.test.ts tests/circuit-section-transaction.repository.test.ts tests/database-backup.test.ts",
|
||||
"db:generate": "drizzle-kit generate",
|
||||
"db:migrate": "drizzle-kit migrate",
|
||||
"db:backup": "tsx scripts/db-backup.ts",
|
||||
|
||||
@@ -33,6 +33,16 @@ const projectDeviceColumns = new Set(
|
||||
const missingProjectDeviceColumns = requiredProjectDeviceColumns.filter(
|
||||
(name) => !projectDeviceColumns.has(name)
|
||||
);
|
||||
const removedProjectDeviceColumns = [
|
||||
"installed_power_per_unit_kw",
|
||||
"demand_factor",
|
||||
"phase_count",
|
||||
"power_factor",
|
||||
"note",
|
||||
];
|
||||
const remainingRemovedProjectDeviceColumns = removedProjectDeviceColumns.filter(
|
||||
(name) => projectDeviceColumns.has(name)
|
||||
);
|
||||
const requiredCircuitColumns = ["control_requirement"];
|
||||
const circuitColumns = new Set(
|
||||
db.prepare("PRAGMA table_info(circuits)").all().map((column) => column.name)
|
||||
@@ -55,6 +65,14 @@ if (missingProjectDeviceColumns.length > 0) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (remainingRemovedProjectDeviceColumns.length > 0) {
|
||||
console.error(
|
||||
"Transitional project-device columns still present:",
|
||||
remainingRemovedProjectDeviceColumns.join(", ")
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (missingCircuitColumns.length > 0) {
|
||||
console.error("Missing circuit columns:", missingCircuitColumns.join(", "));
|
||||
process.exit(1);
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
ALTER TABLE `project_devices` DROP COLUMN `installed_power_per_unit_kw`;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE `project_devices` DROP COLUMN `demand_factor`;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE `project_devices` DROP COLUMN `phase_count`;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE `project_devices` DROP COLUMN `power_factor`;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE `project_devices` DROP COLUMN `note`;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -78,6 +78,13 @@
|
||||
"when": 1784746800000,
|
||||
"tag": "0010_circuit_control_requirement",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 11,
|
||||
"version": "6",
|
||||
"when": 1784832541202,
|
||||
"tag": "0011_project_device_canonical_fields",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -37,12 +37,7 @@ export class ProjectDeviceRepository {
|
||||
simultaneityFactor: input.simultaneityFactor,
|
||||
cosPhi: input.cosPhi ?? null,
|
||||
remark: input.remark ?? null,
|
||||
installedPowerPerUnitKw: input.powerPerUnit,
|
||||
demandFactor: input.simultaneityFactor,
|
||||
voltageV: input.voltageV ?? null,
|
||||
phaseCount: input.phaseType === "three_phase" ? 3 : 1,
|
||||
powerFactor: input.cosPhi ?? null,
|
||||
note: input.remark ?? null,
|
||||
});
|
||||
const created = await this.findById(projectId, id);
|
||||
if (!created) {
|
||||
@@ -77,12 +72,7 @@ export class ProjectDeviceRepository {
|
||||
simultaneityFactor: input.simultaneityFactor,
|
||||
cosPhi: input.cosPhi ?? null,
|
||||
remark: input.remark ?? null,
|
||||
installedPowerPerUnitKw: input.powerPerUnit,
|
||||
demandFactor: input.simultaneityFactor,
|
||||
voltageV: input.voltageV ?? null,
|
||||
phaseCount: input.phaseType === "three_phase" ? 3 : 1,
|
||||
powerFactor: input.cosPhi ?? null,
|
||||
note: input.remark ?? null,
|
||||
})
|
||||
.where(
|
||||
and(eq(projectDevices.id, projectDeviceId), eq(projectDevices.projectId, projectId))
|
||||
|
||||
@@ -17,11 +17,5 @@ export const projectDevices = sqliteTable("project_devices", {
|
||||
simultaneityFactor: real("simultaneity_factor").notNull().default(1),
|
||||
cosPhi: real("cos_phi"),
|
||||
remark: text("remark"),
|
||||
// Transitional mirror columns retained until a dedicated schema cleanup migration removes them.
|
||||
installedPowerPerUnitKw: real("installed_power_per_unit_kw").notNull(),
|
||||
demandFactor: real("demand_factor").notNull(),
|
||||
voltageV: real("voltage_v"),
|
||||
phaseCount: integer("phase_count"),
|
||||
powerFactor: real("power_factor"),
|
||||
note: text("note"),
|
||||
});
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
# Frontend Placeholder
|
||||
|
||||
Frontend implementation will move here in the next step (React/Next.js).
|
||||
The backend API, domain logic, and SQLite persistence are now prepared.
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
# Frontend Utils Placeholder
|
||||
|
||||
Shared UI utility helpers will be implemented during the Next.js migration step.
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
import assert from "node:assert/strict";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { describe, it } from "node:test";
|
||||
import Database from "better-sqlite3";
|
||||
|
||||
describe("project device canonical-field migration", () => {
|
||||
it("preserves canonical values while removing transitional mirror columns", () => {
|
||||
const sqlite = new Database(":memory:");
|
||||
try {
|
||||
sqlite.exec(`
|
||||
CREATE TABLE project_devices (
|
||||
id text PRIMARY KEY NOT NULL,
|
||||
power_per_unit real NOT NULL,
|
||||
simultaneity_factor real NOT NULL,
|
||||
phase_type text NOT NULL,
|
||||
cos_phi real,
|
||||
remark text,
|
||||
voltage_v real,
|
||||
installed_power_per_unit_kw real NOT NULL,
|
||||
demand_factor real NOT NULL,
|
||||
phase_count integer,
|
||||
power_factor real,
|
||||
note text
|
||||
);
|
||||
INSERT INTO project_devices VALUES (
|
||||
'device-1',
|
||||
0.25,
|
||||
0.8,
|
||||
'three_phase',
|
||||
0.95,
|
||||
'Canonical remark',
|
||||
400,
|
||||
0.25,
|
||||
0.8,
|
||||
3,
|
||||
0.95,
|
||||
'Canonical remark'
|
||||
);
|
||||
`);
|
||||
|
||||
const migrationSql = fs.readFileSync(
|
||||
path.resolve(
|
||||
"src",
|
||||
"db",
|
||||
"migrations",
|
||||
"0011_project_device_canonical_fields.sql"
|
||||
),
|
||||
"utf8"
|
||||
);
|
||||
for (const statement of migrationSql.split("--> statement-breakpoint")) {
|
||||
if (statement.trim()) {
|
||||
sqlite.exec(statement);
|
||||
}
|
||||
}
|
||||
|
||||
const columns = (
|
||||
sqlite.prepare("PRAGMA table_info(project_devices)").all() as Array<{
|
||||
name: string;
|
||||
}>
|
||||
).map((column) => column.name);
|
||||
assert.deepEqual(columns, [
|
||||
"id",
|
||||
"power_per_unit",
|
||||
"simultaneity_factor",
|
||||
"phase_type",
|
||||
"cos_phi",
|
||||
"remark",
|
||||
"voltage_v",
|
||||
]);
|
||||
assert.deepEqual(
|
||||
sqlite
|
||||
.prepare(
|
||||
`SELECT
|
||||
power_per_unit AS powerPerUnit,
|
||||
simultaneity_factor AS simultaneityFactor,
|
||||
phase_type AS phaseType,
|
||||
cos_phi AS cosPhi,
|
||||
remark,
|
||||
voltage_v AS voltageV
|
||||
FROM project_devices
|
||||
WHERE id = ?`
|
||||
)
|
||||
.get("device-1"),
|
||||
{
|
||||
powerPerUnit: 0.25,
|
||||
simultaneityFactor: 0.8,
|
||||
phaseType: "three_phase",
|
||||
cosPhi: 0.95,
|
||||
remark: "Canonical remark",
|
||||
voltageV: 400,
|
||||
}
|
||||
);
|
||||
} finally {
|
||||
sqlite.close();
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user