Merge: t-paliad-303 — backfill applies_to_target: Schadensbemessung (merits) + Bucheinsicht (order) (mig 138) (m/paliad#134)
This commit is contained in:
@@ -0,0 +1,71 @@
|
|||||||
|
-- 138_appeal_target_backfill_merits_order DOWN — t-paliad-303, m/paliad#134
|
||||||
|
--
|
||||||
|
-- Removes 'schadensbemessung' from the merits-track rules and
|
||||||
|
-- 'bucheinsicht' from the order-track rules, restoring the pre-137
|
||||||
|
-- shape (endentscheidung-only / anordnung-only / kostenentscheidung-only).
|
||||||
|
|
||||||
|
-- ---------------------------------------------------------------
|
||||||
|
-- 0. Audit reason (required by mig 079 trigger for any UPDATE on
|
||||||
|
-- paliad.deadline_rules).
|
||||||
|
-- ---------------------------------------------------------------
|
||||||
|
|
||||||
|
SELECT set_config(
|
||||||
|
'paliad.audit_reason',
|
||||||
|
'mig 138 DOWN: t-paliad-303 — strip Schadensbemessung/Bucheinsicht from applies_to_target per m/paliad#134',
|
||||||
|
true);
|
||||||
|
|
||||||
|
-- ---------------------------------------------------------------
|
||||||
|
-- 1. Strip new targets via array_remove.
|
||||||
|
--
|
||||||
|
-- WHERE clauses pinned to upc.apl.unified to avoid touching unrelated
|
||||||
|
-- rules that might have been added later under other proceeding types.
|
||||||
|
-- ---------------------------------------------------------------
|
||||||
|
|
||||||
|
-- 1a. Remove schadensbemessung from merits-track rows.
|
||||||
|
UPDATE paliad.deadline_rules dr
|
||||||
|
SET applies_to_target = array_remove(dr.applies_to_target, 'schadensbemessung')
|
||||||
|
FROM paliad.proceeding_types pt
|
||||||
|
WHERE pt.id = dr.proceeding_type_id
|
||||||
|
AND pt.code = 'upc.apl.unified'
|
||||||
|
AND dr.is_active = true
|
||||||
|
AND 'schadensbemessung' = ANY(dr.applies_to_target);
|
||||||
|
|
||||||
|
-- 1b. Remove bucheinsicht from order-track rows.
|
||||||
|
UPDATE paliad.deadline_rules dr
|
||||||
|
SET applies_to_target = array_remove(dr.applies_to_target, 'bucheinsicht')
|
||||||
|
FROM paliad.proceeding_types pt
|
||||||
|
WHERE pt.id = dr.proceeding_type_id
|
||||||
|
AND pt.code = 'upc.apl.unified'
|
||||||
|
AND dr.is_active = true
|
||||||
|
AND 'bucheinsicht' = ANY(dr.applies_to_target);
|
||||||
|
|
||||||
|
-- ---------------------------------------------------------------
|
||||||
|
-- 2. Sanity check — no row may carry the new targets after the down.
|
||||||
|
-- ---------------------------------------------------------------
|
||||||
|
|
||||||
|
DO $$
|
||||||
|
DECLARE
|
||||||
|
schad_left int;
|
||||||
|
buch_left int;
|
||||||
|
BEGIN
|
||||||
|
SELECT COUNT(*) INTO schad_left
|
||||||
|
FROM paliad.deadline_rules dr
|
||||||
|
JOIN paliad.proceeding_types pt ON pt.id = dr.proceeding_type_id
|
||||||
|
WHERE pt.code = 'upc.apl.unified'
|
||||||
|
AND dr.is_active = true
|
||||||
|
AND 'schadensbemessung' = ANY(dr.applies_to_target);
|
||||||
|
SELECT COUNT(*) INTO buch_left
|
||||||
|
FROM paliad.deadline_rules dr
|
||||||
|
JOIN paliad.proceeding_types pt ON pt.id = dr.proceeding_type_id
|
||||||
|
WHERE pt.code = 'upc.apl.unified'
|
||||||
|
AND dr.is_active = true
|
||||||
|
AND 'bucheinsicht' = ANY(dr.applies_to_target);
|
||||||
|
|
||||||
|
IF schad_left > 0 THEN
|
||||||
|
RAISE EXCEPTION '[mig 138 DOWN] FAILED — % rows still carry schadensbemessung', schad_left;
|
||||||
|
END IF;
|
||||||
|
IF buch_left > 0 THEN
|
||||||
|
RAISE EXCEPTION '[mig 138 DOWN] FAILED — % rows still carry bucheinsicht', buch_left;
|
||||||
|
END IF;
|
||||||
|
RAISE NOTICE '[mig 138 DOWN] stripped schadensbemessung + bucheinsicht from upc.apl.unified rules';
|
||||||
|
END $$;
|
||||||
@@ -0,0 +1,232 @@
|
|||||||
|
-- 138_appeal_target_backfill_merits_order — t-paliad-303, m/paliad#134
|
||||||
|
--
|
||||||
|
-- Slice B1 (mig 134) introduced the unified upc.apl.unified proceeding type
|
||||||
|
-- with 5 appeal_target enum values: endentscheidung, kostenentscheidung,
|
||||||
|
-- anordnung, schadensbemessung, bucheinsicht. The first three each carry
|
||||||
|
-- rules; schadensbemessung and bucheinsicht returned an empty timeline
|
||||||
|
-- because no rules referenced them yet.
|
||||||
|
--
|
||||||
|
-- m's 2026-05-26 decision (#134): extend applies_to_target on the existing
|
||||||
|
-- rules — Schadensbemessung := merits track (R.224 anchored on R.118
|
||||||
|
-- substantive decisions), Bucheinsicht := order track (R.220.2 +
|
||||||
|
-- R.224.2.b + R.235.2 + R.237 + R.238.2 etc.). Legal premise verified
|
||||||
|
-- against the 16 live rules — every endentscheidung rule is a generic
|
||||||
|
-- R.224 merits step, every anordnung rule is a generic R.220/224/235/237/
|
||||||
|
-- 238 order step. No rule carries content specific to a particular kind
|
||||||
|
-- of underlying decision/order. Audit on the comment trail of #134.
|
||||||
|
|
||||||
|
-- ---------------------------------------------------------------
|
||||||
|
-- 0. Audit reason (required by mig 079 trigger for any UPDATE on
|
||||||
|
-- paliad.deadline_rules — both UPDATEs below trigger it).
|
||||||
|
-- ---------------------------------------------------------------
|
||||||
|
|
||||||
|
SELECT set_config(
|
||||||
|
'paliad.audit_reason',
|
||||||
|
'mig 138: t-paliad-303 — extend applies_to_target for Schadensbemessung (merits) + Bucheinsicht (order) per m/paliad#134',
|
||||||
|
true);
|
||||||
|
|
||||||
|
-- ---------------------------------------------------------------
|
||||||
|
-- 1. Audit-first DO block.
|
||||||
|
--
|
||||||
|
-- Resolve upc.apl.unified, count the rows we are about to touch, and
|
||||||
|
-- RAISE EXCEPTION if anything looks wrong (proceeding type missing,
|
||||||
|
-- merits/order rule counts off, or a rule already carries the new
|
||||||
|
-- target — which would mean an earlier partial run).
|
||||||
|
-- ---------------------------------------------------------------
|
||||||
|
|
||||||
|
DO $$
|
||||||
|
DECLARE
|
||||||
|
rec record;
|
||||||
|
upc_apl_id int;
|
||||||
|
merits_count int;
|
||||||
|
order_count int;
|
||||||
|
schad_already int;
|
||||||
|
buch_already int;
|
||||||
|
BEGIN
|
||||||
|
SELECT id INTO upc_apl_id
|
||||||
|
FROM paliad.proceeding_types
|
||||||
|
WHERE code = 'upc.apl.unified';
|
||||||
|
IF upc_apl_id IS NULL THEN
|
||||||
|
RAISE EXCEPTION '[mig 138] upc.apl.unified proceeding_type not found — mig 134 must run first';
|
||||||
|
END IF;
|
||||||
|
RAISE NOTICE '[mig 138] upc.apl.unified proceeding_type_id = %', upc_apl_id;
|
||||||
|
|
||||||
|
SELECT COUNT(*) INTO merits_count
|
||||||
|
FROM paliad.deadline_rules
|
||||||
|
WHERE proceeding_type_id = upc_apl_id
|
||||||
|
AND is_active = true
|
||||||
|
AND 'endentscheidung' = ANY(applies_to_target);
|
||||||
|
SELECT COUNT(*) INTO order_count
|
||||||
|
FROM paliad.deadline_rules
|
||||||
|
WHERE proceeding_type_id = upc_apl_id
|
||||||
|
AND is_active = true
|
||||||
|
AND 'anordnung' = ANY(applies_to_target);
|
||||||
|
|
||||||
|
RAISE NOTICE '[mig 138] live counts: endentscheidung=% anordnung=%', merits_count, order_count;
|
||||||
|
IF merits_count <> 7 THEN
|
||||||
|
RAISE EXCEPTION '[mig 138] expected 7 endentscheidung rules under upc.apl.unified, got %', merits_count;
|
||||||
|
END IF;
|
||||||
|
IF order_count <> 7 THEN
|
||||||
|
RAISE EXCEPTION '[mig 138] expected 7 anordnung rules under upc.apl.unified, got %', order_count;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
SELECT COUNT(*) INTO schad_already
|
||||||
|
FROM paliad.deadline_rules
|
||||||
|
WHERE proceeding_type_id = upc_apl_id
|
||||||
|
AND is_active = true
|
||||||
|
AND 'schadensbemessung' = ANY(applies_to_target);
|
||||||
|
SELECT COUNT(*) INTO buch_already
|
||||||
|
FROM paliad.deadline_rules
|
||||||
|
WHERE proceeding_type_id = upc_apl_id
|
||||||
|
AND is_active = true
|
||||||
|
AND 'bucheinsicht' = ANY(applies_to_target);
|
||||||
|
IF schad_already > 0 THEN
|
||||||
|
RAISE EXCEPTION '[mig 138] % rules already carry schadensbemessung — partial run?', schad_already;
|
||||||
|
END IF;
|
||||||
|
IF buch_already > 0 THEN
|
||||||
|
RAISE EXCEPTION '[mig 138] % rules already carry bucheinsicht — partial run?', buch_already;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
RAISE NOTICE '[mig 138] rules to extend with schadensbemessung (merits track):';
|
||||||
|
FOR rec IN
|
||||||
|
SELECT dr.id, dr.rule_code, dr.legal_source, dr.name, dr.applies_to_target
|
||||||
|
FROM paliad.deadline_rules dr
|
||||||
|
WHERE dr.proceeding_type_id = upc_apl_id
|
||||||
|
AND dr.is_active = true
|
||||||
|
AND 'endentscheidung' = ANY(dr.applies_to_target)
|
||||||
|
ORDER BY dr.sequence_order, dr.rule_code NULLS LAST
|
||||||
|
LOOP
|
||||||
|
RAISE NOTICE '[mig 138] merits % % % pre=% → post=%',
|
||||||
|
COALESCE(rec.rule_code, '(no-code)'),
|
||||||
|
COALESCE(rec.legal_source, '(no-source)'),
|
||||||
|
rec.name,
|
||||||
|
rec.applies_to_target,
|
||||||
|
rec.applies_to_target || 'schadensbemessung'::text;
|
||||||
|
END LOOP;
|
||||||
|
|
||||||
|
RAISE NOTICE '[mig 138] rules to extend with bucheinsicht (order track):';
|
||||||
|
FOR rec IN
|
||||||
|
SELECT dr.id, dr.rule_code, dr.legal_source, dr.name, dr.applies_to_target
|
||||||
|
FROM paliad.deadline_rules dr
|
||||||
|
WHERE dr.proceeding_type_id = upc_apl_id
|
||||||
|
AND dr.is_active = true
|
||||||
|
AND 'anordnung' = ANY(dr.applies_to_target)
|
||||||
|
ORDER BY dr.sequence_order, dr.rule_code NULLS LAST
|
||||||
|
LOOP
|
||||||
|
RAISE NOTICE '[mig 138] order % % % pre=% → post=%',
|
||||||
|
COALESCE(rec.rule_code, '(no-code)'),
|
||||||
|
COALESCE(rec.legal_source, '(no-source)'),
|
||||||
|
rec.name,
|
||||||
|
rec.applies_to_target,
|
||||||
|
rec.applies_to_target || 'bucheinsicht'::text;
|
||||||
|
END LOOP;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
-- ---------------------------------------------------------------
|
||||||
|
-- 2. Extend applies_to_target.
|
||||||
|
--
|
||||||
|
-- Narrow WHERE clauses key off upc.apl.unified + existing target +
|
||||||
|
-- absence of new target, so the UPDATEs are idempotent in spirit
|
||||||
|
-- (the audit block above already RAISE EXCEPTIONed if any row
|
||||||
|
-- already had the new value).
|
||||||
|
-- ---------------------------------------------------------------
|
||||||
|
|
||||||
|
-- 2a. Schadensbemessung := merits track (7 rules expected).
|
||||||
|
UPDATE paliad.deadline_rules dr
|
||||||
|
SET applies_to_target = applies_to_target || 'schadensbemessung'::text
|
||||||
|
FROM paliad.proceeding_types pt
|
||||||
|
WHERE pt.id = dr.proceeding_type_id
|
||||||
|
AND pt.code = 'upc.apl.unified'
|
||||||
|
AND dr.is_active = true
|
||||||
|
AND 'endentscheidung' = ANY(dr.applies_to_target)
|
||||||
|
AND NOT ('schadensbemessung' = ANY(dr.applies_to_target));
|
||||||
|
|
||||||
|
-- 2b. Bucheinsicht := order track (7 rules expected).
|
||||||
|
UPDATE paliad.deadline_rules dr
|
||||||
|
SET applies_to_target = applies_to_target || 'bucheinsicht'::text
|
||||||
|
FROM paliad.proceeding_types pt
|
||||||
|
WHERE pt.id = dr.proceeding_type_id
|
||||||
|
AND pt.code = 'upc.apl.unified'
|
||||||
|
AND dr.is_active = true
|
||||||
|
AND 'anordnung' = ANY(dr.applies_to_target)
|
||||||
|
AND NOT ('bucheinsicht' = ANY(dr.applies_to_target));
|
||||||
|
|
||||||
|
-- ---------------------------------------------------------------
|
||||||
|
-- 3. Post-migration sanity check.
|
||||||
|
--
|
||||||
|
-- Hard-fail on any divergence: the two new targets must each cover
|
||||||
|
-- 7 rules, the original three targets must be unchanged in count,
|
||||||
|
-- and no rule has lost its prior target.
|
||||||
|
-- ---------------------------------------------------------------
|
||||||
|
|
||||||
|
DO $$
|
||||||
|
DECLARE
|
||||||
|
schad_post int;
|
||||||
|
buch_post int;
|
||||||
|
end_post int;
|
||||||
|
anord_post int;
|
||||||
|
cost_post int;
|
||||||
|
target_distribution record;
|
||||||
|
BEGIN
|
||||||
|
SELECT COUNT(*) INTO schad_post
|
||||||
|
FROM paliad.deadline_rules dr
|
||||||
|
JOIN paliad.proceeding_types pt ON pt.id = dr.proceeding_type_id
|
||||||
|
WHERE pt.code = 'upc.apl.unified'
|
||||||
|
AND dr.is_active = true
|
||||||
|
AND 'schadensbemessung' = ANY(dr.applies_to_target);
|
||||||
|
SELECT COUNT(*) INTO buch_post
|
||||||
|
FROM paliad.deadline_rules dr
|
||||||
|
JOIN paliad.proceeding_types pt ON pt.id = dr.proceeding_type_id
|
||||||
|
WHERE pt.code = 'upc.apl.unified'
|
||||||
|
AND dr.is_active = true
|
||||||
|
AND 'bucheinsicht' = ANY(dr.applies_to_target);
|
||||||
|
SELECT COUNT(*) INTO end_post
|
||||||
|
FROM paliad.deadline_rules dr
|
||||||
|
JOIN paliad.proceeding_types pt ON pt.id = dr.proceeding_type_id
|
||||||
|
WHERE pt.code = 'upc.apl.unified'
|
||||||
|
AND dr.is_active = true
|
||||||
|
AND 'endentscheidung' = ANY(dr.applies_to_target);
|
||||||
|
SELECT COUNT(*) INTO anord_post
|
||||||
|
FROM paliad.deadline_rules dr
|
||||||
|
JOIN paliad.proceeding_types pt ON pt.id = dr.proceeding_type_id
|
||||||
|
WHERE pt.code = 'upc.apl.unified'
|
||||||
|
AND dr.is_active = true
|
||||||
|
AND 'anordnung' = ANY(dr.applies_to_target);
|
||||||
|
SELECT COUNT(*) INTO cost_post
|
||||||
|
FROM paliad.deadline_rules dr
|
||||||
|
JOIN paliad.proceeding_types pt ON pt.id = dr.proceeding_type_id
|
||||||
|
WHERE pt.code = 'upc.apl.unified'
|
||||||
|
AND dr.is_active = true
|
||||||
|
AND 'kostenentscheidung' = ANY(dr.applies_to_target);
|
||||||
|
|
||||||
|
RAISE NOTICE '[mig 138] post: schadensbemessung=% bucheinsicht=% endentscheidung=% anordnung=% kostenentscheidung=%',
|
||||||
|
schad_post, buch_post, end_post, anord_post, cost_post;
|
||||||
|
|
||||||
|
IF schad_post <> 7 THEN
|
||||||
|
RAISE EXCEPTION '[mig 138] FAILED — expected 7 schadensbemessung rules, got %', schad_post;
|
||||||
|
END IF;
|
||||||
|
IF buch_post <> 7 THEN
|
||||||
|
RAISE EXCEPTION '[mig 138] FAILED — expected 7 bucheinsicht rules, got %', buch_post;
|
||||||
|
END IF;
|
||||||
|
IF end_post <> 7 THEN
|
||||||
|
RAISE EXCEPTION '[mig 138] FAILED — endentscheidung count drifted: expected 7, got %', end_post;
|
||||||
|
END IF;
|
||||||
|
IF anord_post <> 7 THEN
|
||||||
|
RAISE EXCEPTION '[mig 138] FAILED — anordnung count drifted: expected 7, got %', anord_post;
|
||||||
|
END IF;
|
||||||
|
IF cost_post <> 2 THEN
|
||||||
|
RAISE EXCEPTION '[mig 138] FAILED — kostenentscheidung count drifted: expected 2, got %', cost_post;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
FOR target_distribution IN
|
||||||
|
SELECT unnest(applies_to_target) AS target, COUNT(*) AS n
|
||||||
|
FROM paliad.deadline_rules dr
|
||||||
|
JOIN paliad.proceeding_types pt ON pt.id = dr.proceeding_type_id
|
||||||
|
WHERE pt.code = 'upc.apl.unified' AND dr.is_active = true
|
||||||
|
GROUP BY unnest(applies_to_target)
|
||||||
|
ORDER BY 1
|
||||||
|
LOOP
|
||||||
|
RAISE NOTICE '[mig 138] post: applies_to_target=% count=%',
|
||||||
|
target_distribution.target, target_distribution.n;
|
||||||
|
END LOOP;
|
||||||
|
END $$;
|
||||||
@@ -144,7 +144,7 @@ func TestLookupEvents(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("appeal_target=schadensbemessung returns empty (no rules seeded yet)", func(t *testing.T) {
|
t.Run("appeal_target=schadensbemessung returns upc.apl merits rules (mig 138 backfill)", func(t *testing.T) {
|
||||||
matches, err := catalog.LookupEvents(ctx, lp.EventLookupAxes{
|
matches, err := catalog.LookupEvents(ctx, lp.EventLookupAxes{
|
||||||
Jurisdiction: "UPC",
|
Jurisdiction: "UPC",
|
||||||
AppealTarget: lp.AppealTargetSchadensbemessung,
|
AppealTarget: lp.AppealTargetSchadensbemessung,
|
||||||
@@ -152,8 +152,68 @@ func TestLookupEvents(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("LookupEvents: %v", err)
|
t.Fatalf("LookupEvents: %v", err)
|
||||||
}
|
}
|
||||||
if len(matches) != 0 {
|
// mig 138 (t-paliad-303, m/paliad#134) extends the 7 merits-track
|
||||||
t.Errorf("schadensbemessung should be empty until rules seeded; got %d rows", len(matches))
|
// rules under upc.apl.unified with applies_to_target ⊇ {schadensbemessung}
|
||||||
|
// because R.224 is uniform across substantive R.118 decisions.
|
||||||
|
if len(matches) == 0 {
|
||||||
|
t.Fatal("expected upc.apl schadensbemessung rules after mig 138 backfill")
|
||||||
|
}
|
||||||
|
for _, m := range matches {
|
||||||
|
if m.DepthFromAnchor != 1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
found := false
|
||||||
|
for _, t := range m.Rule.AppliesToTarget {
|
||||||
|
if t == lp.AppealTargetSchadensbemessung {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
t.Errorf("anchor row %s missing schadensbemessung target: %v",
|
||||||
|
m.Rule.Name, m.Rule.AppliesToTarget)
|
||||||
|
}
|
||||||
|
if m.ProceedingType.Code != "upc.apl.unified" {
|
||||||
|
t.Errorf("anchor row %s came from %s, want upc.apl.unified",
|
||||||
|
m.Rule.Name, m.ProceedingType.Code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("appeal_target=bucheinsicht returns upc.apl order rules (mig 138 backfill)", func(t *testing.T) {
|
||||||
|
matches, err := catalog.LookupEvents(ctx, lp.EventLookupAxes{
|
||||||
|
Jurisdiction: "UPC",
|
||||||
|
AppealTarget: lp.AppealTargetBucheinsicht,
|
||||||
|
}, lp.EventLookupDepthAllFollowing)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("LookupEvents: %v", err)
|
||||||
|
}
|
||||||
|
// mig 138 (t-paliad-303, m/paliad#134) extends the 7 order-track
|
||||||
|
// rules under upc.apl.unified with applies_to_target ⊇ {bucheinsicht}
|
||||||
|
// because R.220.2 / R.224.2.b / R.235.2 / R.237 / R.238.2 are
|
||||||
|
// uniform across the orders they appeal.
|
||||||
|
if len(matches) == 0 {
|
||||||
|
t.Fatal("expected upc.apl bucheinsicht rules after mig 138 backfill")
|
||||||
|
}
|
||||||
|
for _, m := range matches {
|
||||||
|
if m.DepthFromAnchor != 1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
found := false
|
||||||
|
for _, t := range m.Rule.AppliesToTarget {
|
||||||
|
if t == lp.AppealTargetBucheinsicht {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
t.Errorf("anchor row %s missing bucheinsicht target: %v",
|
||||||
|
m.Rule.Name, m.Rule.AppliesToTarget)
|
||||||
|
}
|
||||||
|
if m.ProceedingType.Code != "upc.apl.unified" {
|
||||||
|
t.Errorf("anchor row %s came from %s, want upc.apl.unified",
|
||||||
|
m.Rule.Name, m.ProceedingType.Code)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user