The Versorgung field suggests ELT and MSR (plus values already used in the balance) through a datalist and still accepts free text. The circuit number column is not needed in early design phases; it is removed from the data model, the regenerated migration 0010, the editor and the print. All cells are centered except "Verbraucher / Flächen", group titles and total labels. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
5.8 KiB
Grobe Leistungsbilanz (LPH 2/3)
Eigenes Modul für die Leistungsbilanz der Vor- und Entwurfsplanung, gegliedert nach Kostengruppen (DIN 276, KG 400). Es gibt dort noch keine Verteilungen und Stromkreise: Jedes Gewerk trägt unter seiner Kostengruppe Verbraucher als Stückzahl mit Einzelleistung oder als Fläche mit W/m² ein. Aufbau und Rechnung folgen der bisherigen Excel-Vorlage „Leistungsbilanz – KG400“. Abstimmung: Issue #7.
Das Modul ist nicht mit der Stromkreisstruktur verknüpft. Es liest die Gerätezeilen nur für den Vergleich „geschätzt ↔ detailliert“ und schreibt nichts in Stromkreislisten, Verteilungen oder Projektgeräte.
Aufbau
src/shared/estimate-balance/estimate-balance.ts Datenform, Rechnung, Vergleich (rein, ohne Imports)
src/estimate-balance/domain/estimate-balance-command.model.ts Snapshot-Schema (Zod), Befehle
src/estimate-balance/domain/estimate-balance-project-command.store.ts Store-Port
src/estimate-balance/api/estimate-balance-request.schemas.ts Request-Schemas
src/db/schema/estimate-balances.ts Tabellen (Migration 0010)
src/db/repositories/estimate-balance*.ts Lesen, Schreiben, Befehls-Store
src/server/controllers/estimate-balance.controller.ts API
src/app/projects/[projectId]/grobbilanz/ Übersicht der Stände und Editor
src/frontend/estimate-balance/ Editor-Komponenten und Helfer
Die gemeinsame Datei unter src/shared/estimate-balance hat keine Imports, weil
das Frontend sie direkt nutzt (Turbopack löst die .js-Suffixe der API nicht auf).
Datenmodell
| Tabelle | Inhalt |
|---|---|
estimate_balances |
ein Stand je Projekt (z. B. Vorplanung, Entwurfsplanung): Name, LPH, Datum, Reserve AV/SV in %, Sortierung |
estimate_groups |
Kostengruppe ("410" … "480", "" für „Allgemein“), Titel, „bearbeitet von“, Sortierung |
estimate_rows |
Versorgung (Auswahl ELT/MSR oder Freitext), Verbraucher/Fläche, Anzahl bzw. Fläche, Einheit (piece = St., area = m²), Anschluss (fest/Steckdose), Einzelleistung in W bzw. W/m², GLF, cos φ, SV ja/nein, Anmerkung |
Neue Stände entstehen aus der Vorlage KG 400 (410 Sanitär, 420 Wärme, 430 Luft, 434 Kälte, 440 Starkstrom, 450 Schwachstrom, 460 Förder, 470 Nutzungsspezifisch, 480 GA, Allgemein; Reserve AV 10 %), leer oder als Kopie eines bestehenden Stands mit neuen IDs. So lässt sich ein Stand einfrieren und später vergleichen.
Rechnung
- Zeile: P = Anzahl bzw. Fläche × Einzelleistung × GLF, S = P / cos φ.
- AV enthält alle Verbraucher (Normalversorgung). SV listet zusätzlich
die Zeilen mit „SV = ja“, die auch aus der Sicherheitsstromversorgung versorgt
werden müssen. Das ist die Lesart der Vorlage; die Regel liegt in
calculateEstimateRowund lässt sich dort zentral ändern. - Summen je Kostengruppe, Gesamtsumme, Reserve in % (AV und SV getrennt), Leistung inklusive Reserve und Maximalstrom I = S / (√3 · U) mit der Drehstromspannung aus den Projekteinstellungen.
- Anzeige wie in der Tabellenkalkulation gerundet (
roundEstimateValue, 40,175 → 40,18). Der Testtests/estimate-balance.test.tsrechnet das Beispiel der Vorlage vollständig nach (143,24 kW, 148,48 kVA, mit 10 % Reserve 157,56 kW / 163,33 kVA, 235,75 A).
Vergleich geschätzt ↔ detailliert
GET …/comparison summiert alle Gerätezeilen aller Stromkreislisten des
Projekts (Anzahl × Leistung je Stück × Geräte-GZF, wie der Stromkreisbaum) und
ordnet sie über das Feld Kostengruppe der Gerätezeile zu. Maßgeblich ist das
längste passende Präfix: 434 → Gruppe 434, 431 → Gruppe 430, 444 → 440.
Zeilen ohne passende Kostengruppe erscheinen als „nicht zugeordnet“. Der
Verteiler-GZF wird auf keiner Seite angewendet; ein fehlendes cos φ zählt als 1.
Verglichen wird die AV-Leistung (kW) mit Differenz absolut und in %.
Befehle, Undo/Redo
Alle Änderungen laufen über den bestehenden Projekt-Befehlsmechanismus mit Revision, Inverse und persistentem Undo/Redo:
estimate-balance.insert/estimate-balance.deletemit dem vollständigen Stand (Gruppen und Zeilen)estimate-balance.updatemit vollständigemexpected/target-Dokument; der Store prüft, dass der gespeicherte Stand genauexpectedentspricht, und ersetzt ihn atomar. Die Inverse ist das vertauschte Paar.
Der Editor speichert das ganze Dokument verzögert (Autosave); jeder
Speichervorgang ist ein Undo-Schritt. Unveränderte Dokumente erzeugen keine
Revision ({ unchanged: true }).
Bewusst nicht enthalten (Fragen an Julian, Issue #7)
- Die grobe Bilanz ist nicht Teil von Projekt-Snapshot, Restore und Projekttransfer; das Snapshot-Schema bleibt unverändert. Ein Restore lässt die Stände unverändert, eine Projektkopie übernimmt sie nicht.
- Keine Rechte je Gewerk; „bearbeitet von“ ist ein Freitext je Kostengruppe.
- Kostengruppen der Gerätezeilen sind nicht normiert; der Vergleich arbeitet mit Präfixen.
API
GET /api/projects/:projectId/estimate-balancesPOST /api/projects/:projectId/estimate-balances–{ "expectedRevision": 7, "name": "Entwurfsplanung", "workStage": "LPH 3", "dateIso": "2026-09-26", "template": "kg400" }(template:kg400|empty|copymitcopyFromBalanceId)GET /api/projects/:projectId/estimate-balances/:balanceIdPUT /api/projects/:projectId/estimate-balances/:balanceId–{ "expectedRevision": 8, "balance": { …vollständiges Dokument… } }DELETE /api/projects/:projectId/estimate-balances/:balanceId–{ "expectedRevision": 9 }GET /api/projects/:projectId/estimate-balances/:balanceId/comparison
Validierung: Name 1–200 Zeichen, getrimmte Texte, Anzahl/Fläche und
Einzelleistung ≥ 0, GLF 0–1, cos φ > 0 bis 1, Reserve 0–100 %, Datum
YYYY-MM-DD, eindeutige Gruppen- und Zeilen-IDs, unbekannte Felder werden
abgelehnt.