PR-1 of the Unified Fristenrechner. Purely additive: new search-grouping layer + per-rule date override capability. No coverage changes yet (those land in PR-2 = Phase B1 UPC counterclaim cross-flows). Migrations: - 037: paliad.deadline_concepts (id, slug, name_de/en, aliases text[], party, category, sort_order). Trigram + GIN indexes for the search bar. - 038: deadline_rules.concept_id (uuid FK), legal_source (text); event_deadlines.legal_source; trigger_events.concept_id (text slug, soft-link — youpc imports keep their bigint PK). - 039: deadline_rules.condition_flag text → text[] (USING ARRAY[old]). Semantic: rule renders iff every element is in CalcOptions.Flags. Single-element arrays preserve the legacy with_ccr swap exactly. - 040: seed 30 concept rows + backfill all 74 fristenrechner deadline_rules with concept_id; backfill legal_source from existing rule_code (e.g. 'RoP.023' → 'UPC.RoP.23.1', '§ 276 ZPO' → 'DE.ZPO.276.1', 'Art. 108 EPÜ' → 'EU.EPÜ.108', 'R. 79(1) EPÜ' → 'EU.EPC-R.79.1'). Calculator (services/fristenrechner.go): - ConditionFlag is now pq.StringArray (matches text[] schema). New allFlagsSet() helper gates rule rendering; rules with multi-element flags require ALL of them set (prep for Phase B1 with_amend ∧ with_cci). - CalcOptions.AnchorOverrides map[string]string (rule_code → YYYY-MM-DD). The tree-walk consults overrideDates[parent.code] before reading the computed-date map; lets a downstream rule re-anchor on a user-set date. - IsCourtSet rows that get an override stop being placeholder and emit the user's date as a real anchor (so downstream cost_app etc. compute off it). New IsOverridden flag in UIDeadline so the UI can highlight user-edited rows. - LegalSource surfaced on UIDeadline for future search-card display. UI (frontend/src/client/fristenrechner.ts + global.css + i18n): - Each timeline / column rule date is click-to-edit. Click → inline date input → blur or Enter → POST with anchorOverrides → re-render. Empty value clears the override. Escape cancels. Root-event rows (the trigger anchor) stay non-editable — that's the trigger-date input. - Override map cleared on proceeding switch / reset; persists across trigger-date / flag toggle changes within the same proceeding. - New CSS: subtle hover underline on .frist-date-edit; lime border on .timeline-date--overridden + .frist-date-edit-input. - New i18n key deadlines.date.edit.hint (DE + EN). Handler (handlers/fristenrechner.go): - POST body gains optional anchorOverrides map<string,string>; passed through to CalcOptions. Tests: - TestAllFlagsSet covers single-flag legacy semantic, two-flag AND semantic, empty-required unconditional, extra-flags-no-effect. - Existing TestIsCourtDeterminedRule unchanged. Phase A ships standalone — Phase B1 (UPC counterclaim cross-flows) and Phase C/D (search backend + concept-card UI) follow.
59 lines
2.8 KiB
SQL
59 lines
2.8 KiB
SQL
-- t-paliad-131 Phase A1: paliad.deadline_concepts — the Unifier shape.
|
||
--
|
||
-- One concept = one legal idea ("Klageerwiderung", "Berufungsfrist",
|
||
-- "Wiedereinsetzung") that adapts duration / legal_source / notes per
|
||
-- proceeding-type context. Adding this layer above paliad.deadline_rules
|
||
-- lets the search bar group hits per concept (one card with proceeding
|
||
-- pills inside) instead of returning one row per (concept × proceeding).
|
||
--
|
||
-- Slug naming convention:
|
||
-- - EN slug for concepts native to UPC/EPC AND for shared concepts that
|
||
-- exist in both DE and UPC/EPC (statement-of-defence, reply-to-defence,
|
||
-- notice-of-appeal, opposition, re-establishment-of-rights). HLC primary
|
||
-- working surface is German for users but slugs are internal.
|
||
-- - DE slug only for concepts that exist exclusively in German law
|
||
-- (nichtzulassungsbeschwerde, versaeumnisurteil-einspruch,
|
||
-- hinweisbeschluss-stellungnahme).
|
||
--
|
||
-- party = the dominant case across contexts. Per-rule primary_party
|
||
-- override on paliad.deadline_rules takes precedence in the UI pill.
|
||
|
||
CREATE TABLE paliad.deadline_concepts (
|
||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
slug text NOT NULL UNIQUE,
|
||
name_de text NOT NULL,
|
||
name_en text NOT NULL,
|
||
description text,
|
||
aliases text[] NOT NULL DEFAULT '{}',
|
||
party text,
|
||
category text NOT NULL DEFAULT 'submission'
|
||
CHECK (category IN ('submission','decision','order','hearing','other')),
|
||
sort_order int NOT NULL DEFAULT 100,
|
||
is_active bool NOT NULL DEFAULT true,
|
||
created_at timestamptz NOT NULL DEFAULT now(),
|
||
updated_at timestamptz NOT NULL DEFAULT now()
|
||
);
|
||
|
||
COMMENT ON TABLE paliad.deadline_concepts IS
|
||
'The Unifier layer above paliad.deadline_rules. One row per legal '
|
||
'concept (Klageerwiderung, Berufungsfrist, …); deadline_rules.concept_id '
|
||
'links rule rows from different proceeding-types to the same concept.';
|
||
|
||
COMMENT ON COLUMN paliad.deadline_concepts.aliases IS
|
||
'Synonyms (DE, EN, colloquial) the search bar matches against. '
|
||
'Curated in seed migrations; not user-editable in v1.';
|
||
|
||
COMMENT ON COLUMN paliad.deadline_concepts.party IS
|
||
'Dominant party across contexts (claimant / defendant / both / court). '
|
||
'Per-rule paliad.deadline_rules.primary_party overrides for cases where '
|
||
'a context has a different responsible party (e.g. EPA Einspruch '
|
||
'Erwiderung is owed by the Patentinhaber, but the dominant case for '
|
||
'the statement-of-defence concept is defendant).';
|
||
|
||
CREATE INDEX deadline_concepts_trgm_de ON paliad.deadline_concepts
|
||
USING gin (name_de gin_trgm_ops);
|
||
CREATE INDEX deadline_concepts_trgm_en ON paliad.deadline_concepts
|
||
USING gin (name_en gin_trgm_ops);
|
||
CREATE INDEX deadline_concepts_aliases ON paliad.deadline_concepts
|
||
USING gin (aliases);
|