fix(t-paliad-111): bug bundle (correctness) — UPC GESAMTKOSTEN, court-set dates, REGEL save flow

Three correctness bugs from the t-paliad-101 QA sweep, fixed together since
they all change displayed/saved numbers users rely on.

B1 — Kostenrechner UPC GESAMTKOSTEN double-count
  ComputeUPCInstance was setting InstanceTotal = effectiveCourtFee +
  recoverableCeiling. The R.152 recoverable-cost cap is the OPPOSING
  side's worst-case loss-of-suit liability, not the user's own cost —
  folding it into GESAMTKOSTEN inflated the UPC total under a label
  that means "your outlay," and the DE LG/OLG/BGH branches don't add
  any opponent estimate. Drop it from InstanceTotal; the ceiling
  still surfaces as its own RecoverableCeiling line item.

  Live pre-fix on paliad.de (Streitwert 100k, UPC 1. Instanz only):
    instanceTotal = 52600 = 14600 court fee + 38000 R.152 ceiling
  Post-fix:
    instanceTotal = 14600 (court fee only); RecoverableCeiling stays 38000

B3 — Court-determined Termine emit trigger date as a real-looking date
  Zwischenverfahren / Mündliche Verhandlung / Entscheidung all live in
  paliad.deadline_rules with duration_value=0 and parent_id=NULL, so
  Calculate() classified them as IsRootEvent and emitted the trigger
  date as their own DueDate. Worse, RoP.151 "Antrag auf Kostenentscheidung"
  parents off inf.decision and chained 1 month off the placeholder ->
  bogus deadline that the UI rendered as real.

  Fix: classify a zero-duration rule as IsCourtSet (not IsRootEvent)
  when primary_party = 'court' or event_type ∈ {hearing, decision,
  order}. Track court-set rule IDs and propagate IsCourtSet downstream
  to any rule whose parent is court-set, so RoP.151 also surfaces as
  court-set rather than a fabricated date. Save-modal already greys
  out IsCourtSet rows so the "Gerichtsbestimmte Termine ohne Datum
  werden übersprungen" footnote becomes truthful again.

  Live pre-fix on paliad.de (UPC_INF, trigger 2026-04-29):
    Zwischenverfahren / Oral / Entscheidung -> dueDate 2026-04-29
    Antrag auf Kostenentscheidung -> 2026-05-29 (bogus, +1mo from trigger)

B6 — Fristenrechner save flow stored rule code in TITLE
  Frontend was concatenating "RoP.023 — Klageerwiderung" into the
  title because deadlines had nowhere else to put the citation, and
  the /deadlines REGEL column ended up showing "—". Add migration 032
  with a paliad.deadlines.rule_code text column, plumb it through
  CreateDeadlineInput / insertTx, drop the now-redundant r.code AS
  rule_code JOIN alias on the list query (the deadline owns its
  citation), and render f.rule_code on the project-detail deadlines
  table + /deadlines events list + deadline-detail page.

Build, vet, and tests all clean. New unit test
TestIsCourtDeterminedRule pins the B3 discriminator across the
event_type / primary_party combinations seen in migrations 012 + 031.

Repro creds: tester@hlc.de
This commit is contained in:
m
2026-05-04 14:42:29 +02:00
parent 7463831932
commit 0be2dfb5a0
13 changed files with 199 additions and 19 deletions

View File

@@ -0,0 +1 @@
ALTER TABLE paliad.deadlines DROP COLUMN IF EXISTS rule_code;

View File

@@ -0,0 +1,21 @@
-- t-paliad-111 B6: store the legal rule citation (RoP.023, R.151, …) on
-- the Deadline row directly so the /deadlines list and project-detail
-- /deadlines tab can render REGEL without having to JOIN paliad.deadline_rules.
--
-- Before: the Fristenrechner save flow concatenated the rule code into
-- the title ("RoP.023 — Klageerwiderung") because deadlines had nowhere
-- else to put it; the REGEL column ended up showing "—" because rule_id
-- on the bulk-save payload is always NULL (no rule UUID round-trips
-- through the public Fristenrechner API).
--
-- After: the save flow sends rule_code as a plain string field, the
-- title stays clean ("Klageerwiderung"), and the list join becomes
-- redundant — the deadline owns its citation.
ALTER TABLE paliad.deadlines
ADD COLUMN IF NOT EXISTS rule_code text;
COMMENT ON COLUMN paliad.deadlines.rule_code IS
'Legal rule citation (e.g. "RoP.023") as it should appear in REGEL. '
'Free text — not FK-constrained — so the value survives rule-table '
'rewrites and accepts citations from sources outside paliad.deadline_rules.';