Add optional room areas

This commit is contained in:
Julian Appel 2026-09-27 20:00:03 +02:00
parent a6500e2b26
commit dce31ee143
26 changed files with 3669 additions and 78 deletions

View file

@ -13,6 +13,7 @@ zugeordneten Etagen lassen sich nicht löschen.
|---|---|---|
| `buildings` | `id`, `project_id` (FK, cascade), `name`, `sort_order` | Gebäude eines Projekts |
| `floors` | `building_id` (nullable FK → `buildings`, `ON DELETE set null`) | optionales übergeordnetes Gebäude |
| `rooms` | `area_m2` (nullable `REAL`) | optional gepflegte Netto-Raumfläche in m² |
Migration `0009_buildings`. Bestehende Etagen behalten `building_id = null` und
erscheinen in der Oberfläche als „Ohne Gebäude“. Es gibt keine Zwangsmigration
@ -20,6 +21,11 @@ und kein automatisch angelegtes Standardgebäude. Vor dem Anwenden der Migration
auf eine bestehende Datenbank ist wie bei jeder Schemamigration eine separate
Datenbanksicherung anzulegen.
Migration `0011_glossy_norman_osborn` ergänzt ausschließlich das nullable Feld
`rooms.area_m2`. Bestehende Räume behalten damit eine unbekannte Fläche. Vor
dem Anwenden auf eine bestehende Datenbank ist ebenfalls eine separate
Datenbanksicherung erforderlich.
## Befehle, Undo/Redo
Alle Änderungen laufen über die bestehende Orts-Struktur
@ -41,17 +47,22 @@ persistentem Undo/Redo:
Vorwärts- und Inversbefehle sind Version 2. Das ist bei linearer Historie
exakt: Wird ein Gebäude später zugeordnet, liegt dieser neuere Befehl im
Undo-Stapel vor dem alten Befehl und wird zuerst zurückgenommen.
- Raumbefehle bleiben unverändert (Version 1).
- Raumbefehle `project-room.insert/.update/.delete` haben seit Schema-Version
**2** das Feld `areaM2`. Version-1-Befehle werden beim Einlesen mit
`areaM2 = null` hochgestuft. Vor einem alten Update oder Delete wird weiterhin
der vollständige erwartete Datensatz verglichen; eine inzwischen vorhandene
Fläche kann deshalb nicht unbemerkt gelöscht werden.
## Snapshots und Transfer
Projekt-Snapshot-Schema **7** enthält `buildings` und `floors[].buildingId`.
Alle älteren unterstützten Versionen (1–6) werden beim Einlesen mit leerer
Gebäudeliste und `buildingId = null` hochgestuft; gespeicherte Sicherungspunkte
bleiben wiederherstellbar. Die Relationen werden geprüft (Gebäude gehört zum
Projekt, `buildingId` verweist auf ein Gebäude des Snapshots). Restore löscht
und schreibt Gebäude zusammen mit den Etagen; der Projekt-Transfer vergibt neue
Gebäude-IDs und stellt die Etagenverweise um.
Projekt-Snapshot-Schema **8** enthält zusätzlich `rooms[].areaM2`. Version 7
wird mit `areaM2 = null` hochgestuft; die älteren unterstützten Versionen 1–6
werden außerdem mit leerer Gebäudeliste und `buildingId = null` hochgestuft.
Gespeicherte Sicherungspunkte bleiben wiederherstellbar. Die Relationen werden
geprüft (Gebäude gehört zum Projekt, `buildingId` verweist auf ein Gebäude des
Snapshots). Restore und Projekttransfer erhalten die Raumfläche. Das portable
Transferformat bleibt Version 2, weil es den versionierten Projektsnapshot
bereits einbettet; beim Duplizieren werden nur IDs und Relationen umgesetzt.
## API
@ -63,6 +74,10 @@ Gebäude-IDs und stellt die Etagenverweise um.
- `POST/PUT /api/projects/:projectId/floors[/:floorId]` akzeptieren zusätzlich
optional `buildingId` (`string | null`). Fehlt das Feld, bleibt beim Bearbeiten
das bisherige Gebäude erhalten; ältere Clients funktionieren unverändert.
- `POST/PUT /api/projects/:projectId/rooms[/:roomId]` akzeptieren zusätzlich
optional `areaM2` (`number | null`, endlich und ≥ 0). Beim Anlegen bedeutet
ein fehlendes Feld `null`; beim Bearbeiten bleibt die vorhandene Fläche
erhalten, wenn das Feld fehlt.
## Oberfläche
@ -74,10 +89,24 @@ nur dessen Etagen, Klick auf eine Etage nur deren Räume, „Alle“ hebt den Fi
auf. Hinzufügen, Bearbeiten und Löschen laufen über Icon-Buttons wie in der
Stromkreisliste.
Der Raumdialog pflegt die optionale **Fläche [m²]** mit deutscher
Dezimaltrennzeichen-Eingabe. Gemeint ist die Netto-Raumfläche, wie sie der
Revit-Raumparameter „Fläche“ liefert, nicht eine Flächenart nach DIN 277. Die
Fläche wird ohne fachliche Rundung gespeichert und mit zwei Nachkommastellen
angezeigt. Die Gebäudestruktur zeigt die Fläche je Raum sowie Summen je Etage,
je Gebäude, „Ohne Etage“ und „Ohne Gebäude“. Fehlende Flächen werden nicht als
Nullfläche ausgegeben, sondern separat gezählt, damit Teilsummen erkennbar
bleiben.
## Offen
- Revit: Eine Übernahme des Gebäudes aus Revit ist derzeit nicht geplant. Die
Revit-Arbeit ist insgesamt zurückgestellt und läuft später über die
Linear-CSV; das Modell steht einer späteren CSV-Zuordnung nicht im Weg.
- Raumflächen werden derzeit ausschließlich manuell gepflegt. Ein späterer
Revit-Abgleich muss die Phase-14-Regeln mit externem Modellzustand, Vorschau
und ausdrücklicher Bestätigung einhalten.
- Eine W/m²-Auswertung oder Übernahme der Raumfläche in Flächenlasten ist nicht
Teil dieser Funktion; das ist Folgethema von Issue #20.
- Sortierung von Gebäuden per Drag-and-drop ist noch nicht umgesetzt; neue
Gebäude werden hinten angehängt.