leistungsbilanz-ts/docs/estimate-balance.md
Grovy311 72189d23a5 Offer supply suggestions, drop the circuit column, center cells
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>
2026-09-26 17:56:53 +02:00

108 lines
5.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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
`calculateEstimateRow` und 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 Test `tests/estimate-balance.test.ts` rechnet 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.delete` mit dem vollständigen
Stand (Gruppen und Zeilen)
- `estimate-balance.update` mit vollständigem `expected`/`target`-Dokument; der
Store prüft, dass der gespeicherte Stand genau `expected` entspricht, 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-balances`
- `POST /api/projects/:projectId/estimate-balances` –
`{ "expectedRevision": 7, "name": "Entwurfsplanung", "workStage": "LPH 3", "dateIso": "2026-09-26", "template": "kg400" }`
(`template`: `kg400` | `empty` | `copy` mit `copyFromBalanceId`)
- `GET /api/projects/:projectId/estimate-balances/:balanceId`
- `PUT /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.