Commit graph

63 commits

Author SHA1 Message Date
b893c72534 Add logical distribution board feed links 2026-09-27 22:21:58 +02:00
dce31ee143 Add optional room areas 2026-09-27 20:00:03 +02:00
598003554a Merge remote-tracking branch 'origin/main' into feature/cable-sizing 2026-09-27 16:54:12 +02:00
Grovy311
37a70b6b36 Add the rough power balance module for early design phases
In LPH 2/3 there are no circuits yet, but the office needs a power
balance by DIN 276 cost group, as in the Excel template "Leistungsbilanz -
KG400": each trade enters consumers by piece or by area (W/m²) with GLF
and cos phi; the balance sums AV and SV per cost group, adds a reserve and
derives the maximum current.

The module is separate from the circuit structure: own tables
(migration 0010), own folder src/estimate-balance and an import-free
shared calculation used by API and UI. Writes go through project commands
(estimate-balance.insert/.update/.delete with complete documents), so
revision checks and Undo/Redo apply; it is not part of project snapshots
or transfer yet. A comparison endpoint sums the device rows of all circuit
lists by cost group (longest prefix) against the estimate.

The UI adds a sidebar entry, a list of Stände (template KG 400, empty or
copy) and a spreadsheet-like editor with autosave, AMEV picker for the
GLF, totals, reserve, maximum current, comparison table and print layout.
The tests reproduce the template example exactly (143.24 kW, 148.48 kVA,
157.56 kW / 163.33 kVA with 10 % reserve, 235.75 A). See
docs/estimate-balance.md and issue #7.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 17:39:28 +02:00
Grovy311
cd89c4a499 Add buildings above floors and a building structure page
Projects with several buildings could not be structured: floors and rooms
hung directly off the project. Floors can now belong to a building
(migration 0009: table buildings, nullable floors.building_id). Rooms and
distribution boards keep their floor; their building follows from it.
Existing floors stay without a building.

Buildings use the location-structure command store with
project-building.insert/.update/.delete, inverses and persistent Undo/Redo;
deleting a building with assigned floors is rejected. Floor commands carry
buildingId since command version 2. Version 1 floor commands from existing
history predate buildings and are upgraded with buildingId = null before
they are executed and persisted, so forward and inverse keep one version.

Project snapshot schema 7 stores buildings and floor.buildingId; versions
1-6 are upgraded without buildings. Restore and portable transfer include
buildings, and the transfer remaps building ids.

Buildings, floors and rooms move from the project overview to their own
page /projects/:id/struktur with three columns (Gebäude -> Etagen -> Räume)
that filter each other, and a sidebar entry. Floor selects in the board and
room dialogs are grouped by building. Unchanged dialogs close without a
command. Details in docs/building-structure.md; see issue #6.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 12:52:34 +02:00
Grovy311
49488f4e1b Add optional cable-sizing module
Per-circuit cross-section recommendation as a separate module attached to
the circuit list. It never writes project data itself: "Übernehmen" applies
cable type, cross-section and length through the regular circuit.update
command, so revisions and Undo/Redo stay intact.

- Pure domain module (src/cable-sizing) with IEC 60364-5-52:2009 Annex B
  tables for PVC and XLPE, copper and aluminium, methods A1, A2, B1, B2, C,
  D1, D2 and E. Every value was cross-checked against public reproductions;
  where sources differ the lower value is used (docs/cable-sizing-module.md).
- Temperature and grouping between table values round to the safer value;
  values outside the tables return no result instead of a factor of 1.
  Ground methods use B.52.18 (D2) and B.52.19 A (D1).
- Overload protection: circuit-breakers In <= Iz; gG fuses additionally
  I2 <= 1.45 Iz with I2 = 1.6/1.9/2.1 In.
- Inputs prefilled from the circuit: power, phase (group or device rows),
  project voltage, power-weighted cos phi, length and protective device.
- Opened from a "Leitungsberechnung" button in the row actions, not from a
  grid cell, so cable cells keep the spreadsheet behavior.
- Stateless API under /api/cable-sizing; no database table or migration.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 11:16:18 +02:00
Grovy311
7692699ee2 Add print cover fields and office profile
- Project settings gain siteAddress, workStage, projectLead and
  projectEditor (project.update-settings schema version 3, migration 0009);
  versions 2 and 1 stay executable and keep the current cover values.
  Snapshot schema 6 carries the fields; older versions upgrade with null.
- Global office profile (office name/address) next to the document logo:
  table document_branding_settings, PUT /api/document-branding/office,
  editable from the print view toolbar.
- Cover page reads all fields; empty values show the "[ergänzen]" marker.
  The Planstände editor column shows the project editor.
- Shared logo constants moved to a dependency-free module so the Next.js
  bundler can import them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 10:39:18 +02:00
Grovy311
4779e4a1a7 Add print view, board info card and document logo upload
- Seitenansicht (/projects/:projectId/print): tabular cover page, board
  overview with supply structure and power sums, one plan per board with a
  repeating title block; PDF via the browser print dialog with named @page
  rules (A4 portrait cover, A4/A3 landscape plans, page x of y).
- Distribution-board info card (board number, location, fed-from, remark)
  in the board edit dialog, persisted through the additively extended
  distribution-board.update command (migration 0008, snapshot schema 6,
  legacy subtree commands normalized).
- Global document logo upload (PNG/JPEG/SVG, max 2 MB) outside project
  revisions and snapshots.
- fed-from stays free text; the overview hierarchy and cumulated sums are
  preliminary until the feed link is modeled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 10:38:59 +02:00
b45dc5002d Fix code-review findings across domain, persistence, server and frontend
Full-codebase review turned up five real correctness/security bugs and
a dozen smaller inconsistencies; all are fixed here with matching test
coverage:

- BMK uniqueness silently allowed German-umlaut duplicates ("Ä1" vs
  "ä1") because the DB's normalized index only folds ASCII case. Added
  a shared Unicode-aware pre-check used by every circuit/component
  insert and rename path (one of which had no pre-check at all).
- CircuitDeviceRow.simultaneityFactor had no upper bound at the row
  level (command model and snapshot/restore schema), unlike every
  sibling entity, letting a bad value silently corrupt power totals.
- Grid cell editing silently misread German thousands-separator input
  ("1.500" parsed as 1.5); "." is now rejected outright with a clear
  message instead of guessing.
- The editor's shared command runner (runCommand/applyHistory) had no
  re-entrancy guard, so a double click/drop could fire the same
  command twice and race a BMK collision or revision conflict. Added a
  synchronous ref guard plus isSaving on the buttons that lacked it.
- GET .../next-identifier leaked circuit-numbering state for sections
  in other projects (no ownership check, 400 instead of 404). Moved
  under /projects/:projectId and scoped it.

Also: added the missing circuits.section_id / circuit_device_rows.
circuit_id indexes (migration 0006), gave FormModal a focus trap /
Escape-to-close / focus restore and rebuilt ProjectSettingsModal on
top of it instead of duplicated markup, removed dead code (3 orphaned
domain model files, an unused persistence helper, a wrapper only used
by its own test), pointed the project page at GET /projects/:id
instead of listing+filtering client-side, closed the gap between the
documented 18 MB CSV limit and the ~17.17 MiB actually enforced, added
missing upper bounds on several free-text fields, filled in nine
missing German labels in the revision timeline, replaced a
key-order-fragile JSON.stringify equality check with a real field
comparison, made an implicit sort-order assumption in three
renumbering helpers explicit, cleared the sidebar's target selection
when it no longer resolves after a tree reload, and fixed
updateGlobalDevice to check-then-write instead of write-then-check.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-06 21:31:16 +02:00
74bea1a3c9 Add Revit circuit list object feed 2026-08-02 18:59:01 +02:00
dac19b093c Add external row quantity foundation 2026-08-02 18:26:22 +02:00
8646f346e6 Add Revit initial import apply API 2026-08-02 17:42:29 +02:00
c9e5fdd876 Add Revit initial import planning 2026-08-02 17:38:17 +02:00
caa6caf99f Add Revit CSV preview API 2026-08-02 16:49:42 +02:00
1eed19ef6b Add editable project floors and rooms 2026-07-31 14:46:06 +02:00
1e3c721cfa Derive project device phases from category 2026-07-31 14:37:45 +02:00
734a2bcfc4 Create clean release database baseline 2026-07-31 14:07:26 +02:00
5bee3cb103 Add distribution board copy and delete controls 2026-07-31 12:03:52 +02:00
86f1d42e60 Expose distribution board copy and delete API 2026-07-31 11:59:31 +02:00
7a9530a914 Expose protected tree structure 2026-07-30 20:14:45 +02:00
9ea081179d Add distribution power summaries 2026-07-29 19:02:18 +02:00
dcb303284c Describe snapshot source revisions 2026-07-29 11:52:26 +02:00
084103bf54 Derive device voltages from project settings 2026-07-29 09:53:58 +02:00
b1a11397b3 Add configurable distribution supply types 2026-07-29 09:31:20 +02:00
194bc9c0b1 Add project overview import 2026-07-29 08:36:57 +02:00
da8115fe1d Add portable project transfer API 2026-07-28 18:34:57 +02:00
d7b98de56a Inject application database contexts 2026-07-26 12:30:42 +02:00
ac465a1cc0 Persist project locations 2026-07-26 10:56:29 +02:00
1cf26a932e Persist distribution board setup 2026-07-25 23:41:27 +02:00
b2763f72d5 Persist project settings updates 2026-07-25 23:08:07 +02:00
384a5769ab Restore named project snapshots 2026-07-25 22:41:24 +02:00
7c670fece3 Add named project snapshots 2026-07-25 22:15:22 +02:00
5a0c9019af Expose project revision timeline 2026-07-25 21:57:03 +02:00
c45afd0981 Persist section renumbering 2026-07-25 21:30:29 +02:00
abcb468807 Persist circuit reorders 2026-07-25 21:22:10 +02:00
08a2775a88 Persist device row moves 2026-07-25 21:09:02 +02:00
2eba4ea75e Persist circuit structure edits 2026-07-25 20:49:34 +02:00
76d8d59391 Persist circuit cell edits 2026-07-25 20:26:45 +02:00
3977a6e6e1 Persist project device synchronization 2026-07-24 11:47:03 +02:00
e930cb75b8 Route project devices through history 2026-07-24 10:57:50 +02:00
e4c7cf06e9 Add project command API 2026-07-23 21:56:13 +02:00
1e4dd26bb8 Add persistent history stacks 2026-07-23 21:48:24 +02:00
3fbf3ac622 Remove legacy consumer API 2026-07-23 20:00:48 +02:00
91baa6c76c Isolate project device sync transactions 2026-07-23 18:57:18 +02:00
30c7555c68 Isolate device row transactions 2026-07-23 18:33:22 +02:00
d7fda37576 Add real SQLite transaction tests 2026-07-23 18:22:32 +02:00
b2034c7dfb Create distribution boards atomically 2026-07-23 17:45:33 +02:00
0800f984bb Create circuits with rows atomically 2026-07-23 17:36:38 +02:00
5dc3ab90be Prepare circuits for future sizing 2026-07-22 20:53:04 +02:00
b2f5ce77a5 Make device sync atomic and undoable 2026-07-22 19:47:10 +02:00