352 lines
22 KiB
Markdown
352 lines
22 KiB
Markdown
# 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 der schrittweise Historien-Cutover
|
||
- `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/server/composition/` – Verdrahtung fachlicher Services mit konkreten
|
||
SQLite-Repositories
|
||
- `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.
|
||
|
||
Der Editor besitzt keinen sitzungslokalen Undo-/Redo-Stapel mehr. Beim initialen
|
||
Laden und nach jedem Tree-Reload liest er den persistenten History-Status und
|
||
gleicht dessen Revision mit `currentRevision` des Trees ab. Das Datenmodell
|
||
besitzt einen projektbezogenen Revisionszähler sowie getrennte Revision-/Change-Set-
|
||
Tabellen. Eine direkt getestete Persistence-Funktion schreibt diese
|
||
Historienmetadaten innerhalb der zentralen Command-Transaktion optimistisch und
|
||
atomar fort. Vorwärts- und Rückwärtskommandos besitzen einen
|
||
versionierten, JSON-sicheren Umschlag; Typ und Payload können dadurch nach
|
||
einem Neustart verlustfrei rekonstruiert werden. Alle aktuell unterstützten
|
||
Circuit-, Gerätezeilen-, Projektgeräte-, Projektstruktur- und
|
||
Projekteinstellungsänderungen
|
||
verwenden typisierte Command-Stores, die Fachänderung, automatisch erzeugtes
|
||
inverses Kommando, Revision und Historienstapel gemeinsam committen
|
||
beziehungsweise zurückrollen.
|
||
Gerätezeilen-Kommandos bewahren dabei auch lokale ProjectDevice-Overrides und
|
||
prüfen Projektzugehörigkeit von Verknüpfungen und Räumen. Projektweite,
|
||
persistente Undo-/Redo-Stacks verwalten die zulässige LIFO-Reihenfolge und
|
||
verwerfen den Redo-Zweig bei einem neuen Benutzerkommando. Ihr Status ist über
|
||
`GET /api/projects/:projectId/history` lesbar. Die unveränderliche,
|
||
absteigend paginierte Revisions-Timeline ist ohne Befehls-Payloads über
|
||
`GET /api/projects/:projectId/history/revisions` lesbar. Ein zentraler
|
||
Dispatcher führt die nachfolgend beschriebenen typisierten Kommandos über
|
||
öffentliche Command-, Undo- und Redo-Endpunkte aus.
|
||
Alle unterstützten Runtime-Project-Command-Stores einschließlich der
|
||
vollständigen Snapshot-Wiederherstellung verwenden dabei
|
||
`project-command-transaction.persistence.ts` als gemeinsame äußere
|
||
Transaktionsgrenze. Sie führt Fachänderung, Revisions-Append und
|
||
History-Transition in fester Reihenfolge innerhalb derselben SQLite-Transaktion
|
||
aus. Für CircuitDeviceRow-Feldänderungen übernimmt eine typisierte Variante den
|
||
während der Fachänderung um Override-Metadaten ergänzten Forward-Command. Die
|
||
fachlichen Validierungs-, Forward- und Inversenregeln bleiben im jeweiligen
|
||
Store.
|
||
Die Low-Level-Funktion `appendProjectRevision` bleibt ein internes Detail dieser
|
||
Persistenzgrenze und wird direkt mit einer realen SQLite-Transaktion getestet.
|
||
Ein eigenständiges Runtime-Revisions-Repository existiert nicht.
|
||
`ProjectDeviceSyncService` und `CircuitNumberingService` kennen nur schmale,
|
||
fachlich benannte Reader-Interfaces. Ihre SQLite-Repositories werden
|
||
ausschließlich in `src/server/composition/` erzeugt und injiziert.
|
||
Auch die allgemeinen Projekt-, Geräte-, Raum-, Geschoss- und Circuit-
|
||
Repositories verlangen einen expliziten `AppDatabase`-Kontext. Ihre
|
||
Anwendungsinstanzen werden zentral in
|
||
`src/server/composition/application-repositories.ts` erzeugt; Controller
|
||
importieren weder den globalen SQLite-Client noch konkrete Repository-Klassen.
|
||
`circuit-device-row.insert` und `circuit-device-row.delete` sind atomare
|
||
Strukturkommandos. Beim Löschen wird die vollständige Zeile im inversen
|
||
Kommando gesichert, sodass Undo dieselbe UUID und alle Fachwerte wiederherstellt.
|
||
`circuit.insert` und `circuit.delete` behandeln einen
|
||
Stromkreis mit null, einer oder mehreren Gerätezeilen als vollständigen Block.
|
||
Undo bewahrt dabei sämtliche Circuit-/Row-UUIDs und ändert keine
|
||
Betriebsmittelkennzeichen. Bestehende Circuit- und Gerätezeilen-Zelländerungen
|
||
sowie eigenständiges Einfügen und Löschen verwendet das Grid bereits über die
|
||
öffentliche Command-Grenze. Neue Circuits und Gerätezeilen erhalten ihre stabile
|
||
UUID vor dem Command; Löschen und Undo bewahren diese Identität. Der Tree liefert
|
||
dazu `currentRevision`; Undo/Redo für diese Aktionen läuft über die projektweite
|
||
Serverhistorie. Direkte Feld-PATCH-, Struktur-POST-, Move-, Circuit- und
|
||
Gerätezeilen-DELETE-Endpunkte sind entfernt. Gerätezeilen-Moves,
|
||
Stromkreis-Reorders und die explizite Neunummerierung im Grid verwenden die
|
||
persistenten Kommandos. Die Toolbar leitet ihre Undo-/Redo-Verfügbarkeit direkt
|
||
aus den serverseitigen Stack-Tiefen ab, sodass ein Reload die Bedienbarkeit
|
||
nicht unterbricht.
|
||
|
||
Benannte logische Projektstände werden in `project_snapshots` getrennt von
|
||
Datenbank-Backups gespeichert. `POST /api/projects/:projectId/snapshots`
|
||
erzeugt bei passender erwarteter Revision transaktional einen vollständigen,
|
||
schema-versionierten Projektzustand mit SHA-256-Prüfwert. Enthalten sind
|
||
Projekteinstellungen, Verteiler, Stromkreislisten, Bereiche, Stromkreise und
|
||
Gerätezeilen sowie Projektgeräte, Geschosse und Räume. Globale Geräte,
|
||
Legacy-Consumer und Migrationsberichte sind nicht Teil des Projekt-Snapshots.
|
||
Create/List verändern weder Projektrevision noch Undo-/Redo-Stapel.
|
||
`kind` unterscheidet benannte und automatische Stände. Die zentrale
|
||
Revisionspersistenz erzeugt nach jeweils 25 weiteren Projektänderungen
|
||
transaktional einen automatischen Stand. Pro Projekt bleiben die neuesten 12
|
||
automatischen Stände erhalten; ältere automatische Stände werden in derselben
|
||
Transaktion entfernt. Benannte Stände und die unveränderliche Revisionshistorie
|
||
sind von dieser Aufbewahrung ausdrücklich ausgeschlossen.
|
||
`POST /api/projects/:projectId/snapshots/:snapshotId/restore` prüft Payload,
|
||
Prüfsumme, erwartete Revision und den unmittelbar zuvor gelesenen
|
||
Projektzustand. Der Restore ersetzt alle unterstützten Projektdaten in einer
|
||
Transaktion und schreibt dabei eine neue Revision mit Quelle `restore` sowie
|
||
ein vollständiges inverses Kommando. Undo und Redo können deshalb auch einen
|
||
Restore nach einem Neustart exakt zurücknehmen oder wiederholen. Kompatible
|
||
Upgrade-only-Verknüpfungen und Migrationsnachweise bleiben erhalten, obwohl sie
|
||
nicht Bestandteil des logischen Snapshots sind.
|
||
Die Projektseite bindet diese APIs in einem einklappbaren Bereich
|
||
„Versionen und Sicherungspunkte“ ein. Dort können Benutzer Sicherungspunkte
|
||
benennen, jeden aufgeführten benannten oder automatischen Stand nach
|
||
expliziter Bestätigung wiederherstellen und die paginierte Revisions-Timeline
|
||
mit deutschen Quellen- und Änderungsbezeichnungen lesen. Die Snapshot-Liste
|
||
ordnet jede positive `sourceRevision` serverseitig ihren unveränderlichen
|
||
Revisionsmetadaten zu. Dadurch zeigt auch ein älterer automatischer Stand die
|
||
auslösende Änderung, ohne eine zweite frei formulierte Beschreibung zu
|
||
speichern oder von den zuletzt paginiert geladenen Timeline-Einträgen
|
||
abzuhängen. Revision null wird als Projektstart dargestellt.
|
||
Projektweites Rückgängig/Wiederholen bleibt im Kopf dieses Bereichs auch im
|
||
eingeklappten Zustand erreichbar. Die Verfügbarkeit stammt direkt aus den
|
||
persistierten Server-Stacks; nach einer Historienaktion oder einem Restore lädt
|
||
die Seite sämtliche Projektdaten neu.
|
||
`circuit-device-row.move` verschiebt oder sortiert eine oder mehrere Zeilen
|
||
zwischen vorhandenen Stromkreisen derselben Liste. Erwartete und neue
|
||
Stromkreis-/Sortierpositionen machen Forward und Inverse deterministisch;
|
||
Reservewerte aller beteiligten Stromkreise werden atomar neu abgeleitet. Das
|
||
Kompositkommando `circuit-device-row.move-with-new-circuit` bildet auch das
|
||
Verschieben auf einen freien Platz ab: Ein Zielstromkreis mit stabiler UUID und
|
||
BMK wird zusammen mit allen Zeilenbewegungen erzeugt. Undo stellt die exakten
|
||
Quellpositionen wieder her und löscht den erzeugten Stromkreis nur, wenn dessen
|
||
Felder und vollständiger Zeilenbestand unverändert sind.
|
||
Der Editor erzeugt die vollständigen Move-Zuweisungen aus dem geladenen Tree,
|
||
vergibt für neue Ziele vor dem Kommando eine stabile UUID und führt das
|
||
Toolbar-Undo/Redo über die projektweite Historie aus.
|
||
Die Projektgerätepalette belegt keine permanente Layoutspalte mehr. Sie wird
|
||
über die Editor-Toolbar als überlagernder Drawer geöffnet, während das
|
||
Stromkreis-Grid standardmäßig die gesamte verfügbare Breite nutzt. Auswahl,
|
||
Schnelleinfügen und die vorhandenen Drag-and-drop-Payloads bleiben im Drawer
|
||
unverändert verfügbar; während eines aktiven Projektgeräte-Drags kann er nicht
|
||
geschlossen werden. Der Drawer liegt am rechten Fensterrand und verdeckt damit
|
||
nicht die führenden BMK- und Anzeigenamenspalten. Das Grid zeigt Geräte- und
|
||
Stromkreisleistungen in einer gemeinsamen Spalte `Gesamtsumme`: Gerätezeilen
|
||
verwenden `rowTotalPower`, Stromkreis-Sammelzeilen `circuitTotalPower`.
|
||
Zahlen werden ausschließlich für die Anzeige deutsch und begrenzt formatiert;
|
||
gespeicherte Werte und Bearbeitungsentwürfe behalten ihre volle Genauigkeit.
|
||
Jeder Abschnitt liefert und zeigt seine aufsummierte Stromkreisleistung. Die
|
||
Stromkreisliste zeigt außerdem die ungefilterte Gesamtleistung des Verteilers,
|
||
den am Verteiler gespeicherten Gleichzeitigkeitsfaktor und die daraus
|
||
abgeleitete Gesamtleistung unter Berücksichtigung dieses Faktors. Sortierung
|
||
und Filter verändern diese fachlichen Summen nicht.
|
||
Reihenfolge und Sichtbarkeit der Grid-Spalten sind reine UI-Präferenzen. Sie
|
||
werden im Browser unter einem projektspezifischen Schlüssel gespeichert und
|
||
deshalb beim Wechsel zwischen Verteilern desselben Projekts wiederverwendet,
|
||
ohne Projektrevisionen oder fachliche Snapshots zu erzeugen.
|
||
`circuit.reorder-section` speichert die erwartete und neue Sortierposition
|
||
jedes Stromkreises eines vollständigen Abschnitts. Forward, Undo und Redo
|
||
ändern ausschließlich `sortOrder`; Stromkreisblöcke, Gerätezeilen und BMKs
|
||
bleiben unverändert. `circuit.renumber-section` bildet die getrennte,
|
||
ausdrücklich ausgelöste Neunummerierung ab. Es speichert alle erwarteten und
|
||
neuen BMKs des Abschnitts, löst Tauschkollisionen über temporäre Werte und
|
||
ändert weder Sortierung noch Gerätezeilen.
|
||
Die Bereichsaktion erzeugt die vollständigen erwarteten und neuen BMKs aus
|
||
Präfix und aktueller Stromkreisreihenfolge und verwendet das persistente
|
||
Kommando für Toolbar-Undo/Redo. Die früheren direkten Renumber- und
|
||
Identifier-Restore-Endpunkte sowie ihr separater Transaktionsadapter sind
|
||
entfernt.
|
||
Drag-and-drop verwendet `circuit.reorder-section`. Die explizite Übernahme
|
||
einer sortierten Ansicht verwendet `circuit.reorder-sections`, damit alle
|
||
betroffenen Bereiche in einer Transaktion und als ein Undo-Schritt gespeichert
|
||
werden. Direkte Reorder-Endpunkte existieren nicht mehr.
|
||
`project-device.sync-rows` persistiert Synchronisierung, Trennen und erneutes
|
||
Verknüpfen als atomaren Mehrzeilen-Command. Jede betroffene Zeile enthält den
|
||
vollständigen erwarteten und neuen Stand aller synchronisierbaren Felder,
|
||
einschließlich ProjectDevice-Verknüpfung und lokaler Override-Metadaten. Damit
|
||
werden stille Überschreibungen veralteter Zeilen verhindert und Undo/Redo stellt
|
||
exakt die vorherigen lokalen Werte wieder her. Die Synchronisieren- und
|
||
Trennen-Endpunkte sowie die Projektseite verwenden diesen Command mit
|
||
optimistischer Revisionsprüfung. Rückgängig/Wiederholen erfolgt dort
|
||
einheitlich über die persistente projektweite Historie; der frühere
|
||
sitzungslokale Spezial-Undo und separate direkte Restore-/Reconnect-Schreibwege
|
||
existieren nicht mehr.
|
||
`project-device.update` versioniert Änderungen an den kanonischen
|
||
Projektgerätefeldern unabhängig davon. Der Store erzeugt die Inverse aus dem
|
||
gespeicherten Gerät und schreibt Geräteänderung, Revision und Historienstapel
|
||
atomar. Verknüpfte Stromkreiszeilen werden dabei bewusst nicht automatisch
|
||
synchronisiert. Der ProjectDevice-`PUT`-Endpunkt und die Projektseite verwenden
|
||
diesen Command mit optimistischer Revisionsprüfung.
|
||
`project-device.insert` und `project-device.delete` versionieren außerdem den
|
||
Lebenszyklus eines Projektgeräts mit stabiler UUID. Beim Löschen speichert das
|
||
inverse Insert den vollständigen Gerätestand sowie vollständige, nach dem
|
||
Löschen erwartete Snapshots aller zuvor verknüpften Gerätezeilen. Undo setzt
|
||
die Links nur zurück, wenn diese Zeilen weiterhin zum Projekt gehören,
|
||
unverknüpft und vollständig unverändert sind. Gerät, Linkänderungen, Revision
|
||
und Historienstapel teilen dieselbe Transaktion. Create, Import aus der globalen
|
||
Gerätebibliothek und Delete laufen über dieselbe Command-Grenze; ihre Antworten
|
||
liefern Gerät und aktualisierten Historienstand an die Projektseite zurück.
|
||
`project.update-settings` versioniert Projektname, interne und externe
|
||
Projektnummer, Bauherr, Beschreibung, beide Standardspannungen sowie die im
|
||
Projekt freigeschalteten Verteiler-Netzarten als eine atomare Änderung. Der
|
||
Systemkatalog besteht aus `AV`, `SV`, `EV`, `USV`, `MSR` und `SiBe`; mindestens
|
||
eine Netzart muss aktiv bleiben und eine bereits von einer Verteilung
|
||
verwendete Netzart kann nicht deaktiviert werden. Die Projektseite bearbeitet diese Angaben in einem
|
||
beschrifteten Einstellungsmodal statt in einer permanenten Formularkarte. Der
|
||
Store leitet das inverse Kommando aus dem gespeicherten Projekt ab und schreibt
|
||
Werte, Revision und Historienstapel gemeinsam. `PUT /api/projects/:projectId`
|
||
verlangt deshalb `expectedRevision`, liefert Projekt plus aktualisierten
|
||
Historienstand und besitzt keinen separaten direkten Settings-Schreibweg mehr.
|
||
Kommando- und Snapshot-Versionen vor dieser Erweiterung bleiben les- und
|
||
ausführbar; fehlende Metadaten werden dabei als `null` behandelt.
|
||
Die Projektseite zeigt Verteilungen, Etagen und Räume als kompakte
|
||
Bestandsübersichten; ihre versionierten Erstellwege öffnen beschriftete Modals
|
||
statt dauerhafter Eingabezeilen. Projektgeräte werden als durchsuchbare,
|
||
fünfspaltige Übersicht dargestellt. Manuelle Anlage, Übernahme aus der globalen
|
||
Bibliothek und vollständige Bearbeitung erfolgen in einem gemeinsamen Modal.
|
||
Die anschließende Vorschau verknüpfter Stromkreiszeilen bleibt davon getrennt,
|
||
damit Änderungen weiterhin niemals still synchronisiert werden.
|
||
`GET /api/projects/:projectId/export` verpackt denselben vollständigen
|
||
Projektzustand in ein portables, format- und schema-versioniertes JSON-Dokument
|
||
mit SHA-256-Prüfsumme. `POST /api/projects/:projectId/import` prüft Format,
|
||
Snapshot-Relationen und Prüfsumme vor jedem Schreibzugriff. Der Modus `replace`
|
||
läuft über `project.restore-state` und ist dadurch eine atomare, dauerhaft
|
||
rückgängig machbare Projektrevision. Der Modus `duplicate` ordnet Projekt-,
|
||
Struktur-, Geräte-, Raum-, Stromkreis- und Gerätezeilen-UUIDs vollständig neu
|
||
zu und legt die Kopie mit Revision `0` in einer Transaktion an. Upgrade-only-
|
||
Consumer-Verweise werden nicht in die Kopie übernommen; fachliche Verknüpfungen
|
||
innerhalb des unterstützten Laufzeitmodells bleiben erhalten. Die
|
||
Projektübersicht verwendet dafür den separaten Collection-Endpunkt
|
||
`POST /api/projects/import`, der ausschließlich eine neue Kopie anlegt und
|
||
deshalb weder eine bestehende Projekt-ID noch `expectedRevision` annimmt. Das
|
||
Ersetzen eines Projekts bleibt auf dessen Einstellungsmodal und den
|
||
projektgebundenen Endpunkt beschränkt.
|
||
`distribution-board.insert` versioniert die Anlage einer Verteilung als einen
|
||
vollständigen Block aus Verteilung, Stromkreisliste und vier Standardbereichen.
|
||
Alle UUIDs entstehen vor dem Command und bleiben über Undo/Redo stabil.
|
||
`distribution-board.delete` ist die persistierte Inverse und entfernt nur den
|
||
vollständig unveränderten, weiterhin stromkreislosen Block. Controller und
|
||
Projektseite übergeben die erwartete Projektrevision; der frühere direkte
|
||
Controller-Schreibweg ist entfernt. Verteilungen besitzen eine optionale
|
||
Etagenreferenz sowie eine Netzart aus dem Projektkatalog. Anlage und
|
||
nachträgliche Bearbeitung prüfen die Projektzugehörigkeit der Etage und die
|
||
Freigabe der Netzart in den Projekteinstellungen.
|
||
`distribution-board.update` versioniert Etage, Netzart und den
|
||
verteilerweiten Gleichzeitigkeitsfaktor gemeinsam und stellt alle Werte über
|
||
dauerhaftes Undo/Redo wieder her. Der Faktor liegt zwischen `0` und `1` und
|
||
ist für bestehende sowie neu angelegte Verteilungen standardmäßig `1`.
|
||
Snapshot-Schema 6 und der portable Projekttransfer enthalten diesen Wert;
|
||
Schema 5 und älter werden mit dem neutralen Faktor `1` hochgestuft.
|
||
Snapshot-Schema 4 enthält bereits Etage und Netzart; Schema 1/2 sowie
|
||
gespeicherte Version-1-Strukturcommands werden ohne erfundene Zuordnung
|
||
hochgestuft. Snapshot-Schema 3 wird mit allen sechs Netzarten als
|
||
Projektauswahl hochgestuft.
|
||
`project-floor.insert` und `project-room.insert` versionieren die Anlage von
|
||
Geschossen und Räumen mit stabilen UUIDs. Die vollständigen Datensätze bilden
|
||
jeweils die persistierte Inverse für Undo/Redo. Ein Geschoss wird durch Undo nur
|
||
entfernt, solange ihm weder ein Raum noch eine Verteilung zugeordnet wurde. Ein
|
||
Raum wird nur entfernt,
|
||
solange weder eine CircuitDeviceRow noch ein aufbewahrter Upgrade-Datensatz auf
|
||
ihn verweist. Beide POST-Endpunkte verlangen `expectedRevision`, liefern den
|
||
aktualisierten Historienstand und besitzen keinen direkten Create-Schreibweg
|
||
mehr.
|
||
|
||
## 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.
|
||
- `npm run typecheck:scripts` prüft alle TypeScript-Wartungs- und
|
||
Upgrade-Skripte mit ihren Anwendungspfaden, ohne Code zu erzeugen.
|
||
- Angewendete Migrationen werden niemals nachträglich verändert.
|
||
- `db:migrate:legacy-consumers` ist Upgrade-Werkzeug, kein Anwendungspfad.
|
||
Der fachliche Migrationsdienst kennt nur schmale Reader-/Store-Ports unter
|
||
`src/domain/ports`; konkrete SQLite-Repositories werden ausschließlich im
|
||
CLI-Skript zusammengesetzt.
|
||
- Allgemeine Circuit-, Gerätezeilen-, CircuitList- und DistributionBoard-
|
||
Repositories stellen im Anwendungspfad nur noch benötigte Leseabfragen bereit.
|
||
Fachliche Schreibvorgänge liegen in den typisierten Command-Repositories;
|
||
Upgrade-Schreibvorgänge bleiben in expliziten Migrationsadaptern.
|
||
- Die vollständige Verteilungs-Testfixture liegt unter
|
||
`tests/support/distribution-board-fixture.ts` und ist kein exportierter
|
||
Produktions-Schreibweg.
|
||
|
||
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
|
||
|
||
- 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).
|