Implements the four audit recommendations from §6.1 of docs/audit-fristenrechner-completeness-2026-04-30.md plus a holiday- adjustment cap fix surfaced by PR-2's smoke test. (1) UPC_INF CCR-conditional rejoinder Public Fristenrechner now flips inf.reply (RoP.029.b → RoP.029.a) and inf.rejoin (1mo / RoP.029.c → 2mo / RoP.029.d) when the user ticks "Mit Widerklage auf Nichtigkeit." Implemented via a new `condition_flag` column on paliad.deadline_rules: when the rule names a flag and the API request's flags array contains it, the calculator substitutes alt_duration_value/unit and alt_rule_code. Independent of the existing `condition_rule_id` mechanism (which references a real rule in the same proceeding tree — only useful for matter-attached trees that already seed the CCR rule). (2) UPC_APP / internal APP grounds anchoring `app.grounds` is now anchored on the trigger date (the appealed decision) with a 4-month duration, not chained 2mo after `app.notice`. Per RoP 220.1 the legal rule is "4 months from notification of the decision," independent of when the notice itself was filed. The chain only happened to give the right answer when both legs landed on a working day; under holiday rollover (e.g. notice deadline pushed to Monday) the grounds deadline drifted off the 4mo legal target. (3) EP_GRANT publish anchor on priority date New `anchor_alt` column on paliad.deadline_rules. ep_grant.publish carries `anchor_alt='priority_date'`. The Fristenrechner UI surfaces an optional "Prioritätstag" input (visible only when EP_GRANT is selected) that, when populated, anchors the publish-A1 calculation on the priority date instead of the filing. Falls back to filing date when the priority field is empty (the case for purely-EP applications with no foreign priority claim). (4) Rule-code format normalisation Migration 029 normalises 'RoP 23' → 'RoP.023', 'RoP 29b' / 'RoP.029b' → 'RoP.029.b', 'RoP 220.1' → 'RoP.220.1', etc. across deadline_rules. Matches the canonical youpc format already used by the PR-1 imported event-deadline rule codes. (+) AdjustForNonWorkingDays cap bumped 30 → 60 Surfaced by the PR-2 smoke test: SoD on 2026-04-30 (3mo from trigger) landed on Sat 2026-08-29 instead of Mon 2026-08-31. The 30-iteration safety bound on AdjustForNonWorkingDays cannot walk past the 33-day UPC summer vacation plus flanking weekends. Bumped to 60. Pure-Go one-liner, locked by a follow-up production smoke (real paliad.holidays seed has the UPC vacation). Schema (migration 029): two new nullable text columns on paliad.deadline_rules — `condition_flag` and `anchor_alt`. Both ignored by every existing rule; only the rows updated above carry values. Models: DeadlineRule gains ConditionFlag + AnchorAlt (nilable strings). Service: FristenrechnerService.Calculate now takes a CalcOptions struct (PriorityDateStr, Flags). API handler accepts optional priorityDate and flags fields on POST /api/tools/fristenrechner. Frontend: TSX surfaces the priority-date row + CCR checkbox conditionally on selectedType (only EP_GRANT / UPC_INF respectively). Client TS reads them and threads through the API call. New i18n keys for both DE+EN. Migration 029 dry-run validated on prod Supabase (BEGIN/ROLLBACK): schema + UPDATEs apply cleanly, rule states match expected post-fix shape. Tests + go build/vet + bun build all clean.
38 lines
1.7 KiB
SQL
38 lines
1.7 KiB
SQL
-- Reverses 029_tier1_rule_fixes. Rule_code normalisation is intentionally
|
|
-- one-way; the down-step only restores the parent_id chain on app.grounds
|
|
-- so an out-of-band rollback can resume the prior shape if needed. The
|
|
-- new columns (condition_flag, anchor_alt) stay on the table — harmless
|
|
-- when null and removing them would force re-applying the data fixes.
|
|
|
|
UPDATE paliad.deadline_rules
|
|
SET parent_id = (SELECT id FROM paliad.deadline_rules
|
|
WHERE proceeding_type_id = (SELECT id FROM paliad.proceeding_types WHERE code = 'UPC_APP')
|
|
AND code = 'app.notice'),
|
|
duration_value = 2,
|
|
deadline_notes = NULL
|
|
WHERE proceeding_type_id = (SELECT id FROM paliad.proceeding_types WHERE code = 'UPC_APP')
|
|
AND code = 'app.grounds';
|
|
|
|
UPDATE paliad.deadline_rules
|
|
SET parent_id = (SELECT id FROM paliad.deadline_rules
|
|
WHERE proceeding_type_id = (SELECT id FROM paliad.proceeding_types WHERE code = 'APP')
|
|
AND code = 'app.notice'),
|
|
duration_value = 2,
|
|
deadline_notes = NULL
|
|
WHERE proceeding_type_id = (SELECT id FROM paliad.proceeding_types WHERE code = 'APP')
|
|
AND code = 'app.grounds';
|
|
|
|
UPDATE paliad.deadline_rules
|
|
SET condition_flag = NULL,
|
|
alt_duration_value = NULL,
|
|
alt_duration_unit = NULL,
|
|
alt_rule_code = NULL
|
|
WHERE proceeding_type_id = (SELECT id FROM paliad.proceeding_types WHERE code = 'UPC_INF')
|
|
AND code IN ('inf.reply', 'inf.rejoin');
|
|
|
|
UPDATE paliad.deadline_rules
|
|
SET anchor_alt = NULL,
|
|
deadline_notes = 'Ab Prioritätstag'
|
|
WHERE proceeding_type_id = (SELECT id FROM paliad.proceeding_types WHERE code = 'EP_GRANT')
|
|
AND code = 'ep_grant.publish';
|