diff --git a/frontend/src/client/fristenrechner.ts b/frontend/src/client/fristenrechner.ts index aa00f5c..4f4dca9 100644 --- a/frontend/src/client/fristenrechner.ts +++ b/frontend/src/client/fristenrechner.ts @@ -114,27 +114,24 @@ async function calculate() { // Flags — proceeding-specific checkboxes: // upc.inf.cfi: with_ccr (always available); with_amend (nested under - // with_ccr — R.30 application is only available with a CCR); - // with_po (mig 095, R.19.1 preliminary objection). - // upc.rev.cfi: with_amend (R.49.2.a), with_cci (R.49.2.b), - // with_po (R.19.1 via R.46) as three independent gates; - // all combinations are valid. + // with_ccr — R.30 application is only available with a CCR). + // upc.rev.cfi: with_amend (R.49.2.a) and with_cci (R.49.2.b) as two + // independent gates; both can be on simultaneously. + // R.19 Einspruch is NOT flag-gated (mig 098, m's 2026-05-18 call): it's + // an always-available optional submission, surfaced as priority='optional' + // without a separate checkbox. const ccrFlag = document.getElementById("ccr-flag") as HTMLInputElement | null; const infAmendFlag = document.getElementById("inf-amend-flag") as HTMLInputElement | null; - const infPoFlag = document.getElementById("inf-po-flag") as HTMLInputElement | null; const revAmendFlag = document.getElementById("rev-amend-flag") as HTMLInputElement | null; const revCciFlag = document.getElementById("rev-cci-flag") as HTMLInputElement | null; - const revPoFlag = document.getElementById("rev-po-flag") as HTMLInputElement | null; const flags: string[] = []; if (selectedType === "upc.inf.cfi") { if (ccrFlag?.checked) flags.push("with_ccr"); if (ccrFlag?.checked && infAmendFlag?.checked) flags.push("with_amend"); - if (infPoFlag?.checked) flags.push("with_po"); } if (selectedType === "upc.rev.cfi") { if (revAmendFlag?.checked) flags.push("with_amend"); if (revCciFlag?.checked) flags.push("with_cci"); - if (revPoFlag?.checked) flags.push("with_po"); } // Forward any user-set per-rule date overrides so downstream rules @@ -514,24 +511,18 @@ function selectProceeding(btn: HTMLButtonElement) { // ccr-flag → upc.inf.cfi only // inf-amend-flag → upc.inf.cfi only, but disabled until ccr-flag is on // (R.30 amend only available with a CCR) - // inf-po-flag → upc.inf.cfi only (R.19.1 preliminary objection, mig 095) // rev-amend-flag → upc.rev.cfi only // rev-cci-flag → upc.rev.cfi only - // rev-po-flag → upc.rev.cfi only (R.19.1 via R.46, mig 095) const priorityRow = document.getElementById("priority-date-row"); if (priorityRow) priorityRow.style.display = selectedType === "epa.grant.exa" ? "" : "none"; const ccrRow = document.getElementById("ccr-flag-row"); if (ccrRow) ccrRow.style.display = selectedType === "upc.inf.cfi" ? "" : "none"; const infAmendRow = document.getElementById("inf-amend-flag-row"); if (infAmendRow) infAmendRow.style.display = selectedType === "upc.inf.cfi" ? "" : "none"; - const infPoRow = document.getElementById("inf-po-flag-row"); - if (infPoRow) infPoRow.style.display = selectedType === "upc.inf.cfi" ? "" : "none"; const revAmendRow = document.getElementById("rev-amend-flag-row"); if (revAmendRow) revAmendRow.style.display = selectedType === "upc.rev.cfi" ? "" : "none"; const revCciRow = document.getElementById("rev-cci-flag-row"); if (revCciRow) revCciRow.style.display = selectedType === "upc.rev.cfi" ? "" : "none"; - const revPoRow = document.getElementById("rev-po-flag-row"); - if (revPoRow) revPoRow.style.display = selectedType === "upc.rev.cfi" ? "" : "none"; syncInfAmendEnabled(); populateCourtPickerCore("court-picker-row", "court-picker", selectedType); @@ -632,14 +623,10 @@ document.addEventListener("DOMContentLoaded", () => { const infAmendFlag = document.getElementById("inf-amend-flag") as HTMLInputElement | null; if (infAmendFlag) infAmendFlag.addEventListener("change", () => scheduleProcCalc(0)); - const infPoFlag = document.getElementById("inf-po-flag") as HTMLInputElement | null; - if (infPoFlag) infPoFlag.addEventListener("change", () => scheduleProcCalc(0)); const revAmendFlag = document.getElementById("rev-amend-flag") as HTMLInputElement | null; if (revAmendFlag) revAmendFlag.addEventListener("change", () => scheduleProcCalc(0)); const revCciFlag = document.getElementById("rev-cci-flag") as HTMLInputElement | null; if (revCciFlag) revCciFlag.addEventListener("change", () => scheduleProcCalc(0)); - const revPoFlag = document.getElementById("rev-po-flag") as HTMLInputElement | null; - if (revPoFlag) revPoFlag.addEventListener("change", () => scheduleProcCalc(0)); const courtPicker = document.getElementById("court-picker") as HTMLSelectElement | null; if (courtPicker) courtPicker.addEventListener("change", () => scheduleProcCalc(0)); diff --git a/frontend/src/client/i18n.ts b/frontend/src/client/i18n.ts index c81fc84..1ca2306 100644 --- a/frontend/src/client/i18n.ts +++ b/frontend/src/client/i18n.ts @@ -221,10 +221,8 @@ const translations: Record> = { "deadlines.court.label": "Gericht:", "deadlines.flag.ccr": "Mit Widerklage auf Nichtigkeit", "deadlines.flag.inf_amend": "Mit Antrag auf Patentänderung (R.30)", - "deadlines.flag.inf_po": "Mit Einspruch (R.19)", "deadlines.flag.rev_amend": "Mit Antrag auf Patentänderung (R.49.2.a)", "deadlines.flag.rev_cci": "Mit Verletzungswiderklage (R.49.2.b)", - "deadlines.flag.rev_po": "Mit Einspruch (R.19 i.V.m. R.46)", "deadlines.calculate": "Fristen berechnen", "deadlines.print": "Drucken", "deadlines.reset": "\u2190 Neu berechnen", @@ -2792,10 +2790,8 @@ const translations: Record> = { "deadlines.court.label": "Court:", "deadlines.flag.ccr": "Counterclaim for revocation filed", "deadlines.flag.inf_amend": "Application to amend the patent filed (R.30)", - "deadlines.flag.inf_po": "Preliminary objection filed (R.19)", "deadlines.flag.rev_amend": "Application to amend the patent filed (R.49.2.a)", "deadlines.flag.rev_cci": "Counterclaim for infringement filed (R.49.2.b)", - "deadlines.flag.rev_po": "Preliminary objection filed (R.19 via R.46)", "deadlines.calculate": "Calculate Deadlines", "deadlines.print": "Print", "deadlines.reset": "\u2190 Start Over", diff --git a/frontend/src/client/verfahrensablauf.ts b/frontend/src/client/verfahrensablauf.ts index 288ddb9..c393ae6 100644 --- a/frontend/src/client/verfahrensablauf.ts +++ b/frontend/src/client/verfahrensablauf.ts @@ -80,25 +80,22 @@ function showStep(n: number) { // gating semantics stay identical: with_amend on upc.inf.cfi is // nested under with_ccr (R.30 is only available with a CCR); // upc.rev.cfi exposes with_amend + with_cci as two independent -// gates; with_po (RoP 19.1, mig 095) gates the optional preliminary -// objection rule on both inf and rev. +// gates. R.19 Einspruch is NOT flag-gated (mig 098, m's 2026-05-18 +// call): it's just an always-available optional submission, so it +// has no checkbox. function readFlags(): string[] { const ccr = document.getElementById("ccr-flag") as HTMLInputElement | null; const infAmend = document.getElementById("inf-amend-flag") as HTMLInputElement | null; - const infPo = document.getElementById("inf-po-flag") as HTMLInputElement | null; const revAmend = document.getElementById("rev-amend-flag") as HTMLInputElement | null; const revCci = document.getElementById("rev-cci-flag") as HTMLInputElement | null; - const revPo = document.getElementById("rev-po-flag") as HTMLInputElement | null; const flags: string[] = []; if (selectedType === "upc.inf.cfi") { if (ccr?.checked) flags.push("with_ccr"); if (ccr?.checked && infAmend?.checked) flags.push("with_amend"); - if (infPo?.checked) flags.push("with_po"); } if (selectedType === "upc.rev.cfi") { if (revAmend?.checked) flags.push("with_amend"); if (revCci?.checked) flags.push("with_cci"); - if (revPo?.checked) flags.push("with_po"); } return flags; } @@ -200,10 +197,8 @@ function syncFlagRows() { }; show("ccr-flag-row", selectedType === "upc.inf.cfi"); show("inf-amend-flag-row", selectedType === "upc.inf.cfi"); - show("inf-po-flag-row", selectedType === "upc.inf.cfi"); show("rev-amend-flag-row", selectedType === "upc.rev.cfi"); show("rev-cci-flag-row", selectedType === "upc.rev.cfi"); - show("rev-po-flag-row", selectedType === "upc.rev.cfi"); syncInfAmendEnabled(); } @@ -297,7 +292,7 @@ document.addEventListener("DOMContentLoaded", () => { syncInfAmendEnabled(); scheduleCalc(0); }); - (["inf-amend-flag", "inf-po-flag", "rev-amend-flag", "rev-cci-flag", "rev-po-flag"]).forEach((id) => { + (["inf-amend-flag", "rev-amend-flag", "rev-cci-flag"]).forEach((id) => { const cb = document.getElementById(id) as HTMLInputElement | null; if (cb) cb.addEventListener("change", () => scheduleCalc(0)); }); diff --git a/frontend/src/fristenrechner.tsx b/frontend/src/fristenrechner.tsx index c38c50b..0723be6 100644 --- a/frontend/src/fristenrechner.tsx +++ b/frontend/src/fristenrechner.tsx @@ -512,12 +512,6 @@ export function renderFristenrechner(): string { Mit Antrag auf Patentänderung (R.30) - - diff --git a/frontend/src/i18n-keys.ts b/frontend/src/i18n-keys.ts index 2dfd737..51af5ae 100644 --- a/frontend/src/i18n-keys.ts +++ b/frontend/src/i18n-keys.ts @@ -1028,10 +1028,8 @@ export type I18nKey = | "deadlines.filter.today" | "deadlines.flag.ccr" | "deadlines.flag.inf_amend" - | "deadlines.flag.inf_po" | "deadlines.flag.rev_amend" | "deadlines.flag.rev_cci" - | "deadlines.flag.rev_po" | "deadlines.form.approval_hint" | "deadlines.heading" | "deadlines.inbox.all" diff --git a/frontend/src/verfahrensablauf.tsx b/frontend/src/verfahrensablauf.tsx index 5b6ea19..5f4cee7 100644 --- a/frontend/src/verfahrensablauf.tsx +++ b/frontend/src/verfahrensablauf.tsx @@ -191,12 +191,6 @@ export function renderVerfahrensablauf(): string { Mit Antrag auf Patentänderung (R.30) - - diff --git a/internal/db/migrations/098_drop_with_po_flag.down.sql b/internal/db/migrations/098_drop_with_po_flag.down.sql new file mode 100644 index 0000000..8cdff16 --- /dev/null +++ b/internal/db/migrations/098_drop_with_po_flag.down.sql @@ -0,0 +1,10 @@ +-- Revert mig 098 — restore the with_po condition_expr (mig 095 shape). +-- audit_reason required: set via SET LOCAL paliad.audit_reason in tooling. + +UPDATE paliad.deadline_rules dr + SET condition_expr = '{"flag":"with_po"}'::jsonb + FROM paliad.proceeding_types pt + WHERE dr.proceeding_type_id = pt.id + AND pt.code IN ('upc.inf.cfi', 'upc.rev.cfi') + AND dr.rule_code = 'RoP.019.1' + AND dr.condition_expr IS NULL; diff --git a/internal/db/migrations/098_drop_with_po_flag.up.sql b/internal/db/migrations/098_drop_with_po_flag.up.sql new file mode 100644 index 0000000..f703fb1 --- /dev/null +++ b/internal/db/migrations/098_drop_with_po_flag.up.sql @@ -0,0 +1,24 @@ +-- t-paliad-207 — drop the `with_po` flag from the two RoP 19 rules. +-- m's call 2026-05-18 (interactive session): the Einspruch (R. 19) is +-- not flag-gated — it's just an optional submission the defendant can +-- always make, triggered by the SoC. Same reasoning that drove the +-- always-fire decision for the appeal-spawn rules in t-paliad-203 F2.3 +-- ("appeal is always a possibility"). +-- +-- Net effect: the calculator will surface the R.19 row on every UPC_INF +-- / UPC_REV calc as an optional row (priority='optional' already set +-- by mig 095, unchanged here). The save-modal pre-uncheck behaviour +-- for optional priority handles the "user opts in" gesture without a +-- separate flag. +-- +-- Two rows updated; pinned by proceeding code so this stays correct +-- after any rule-id reshuffle. Idempotent: the WHERE clause matches +-- the live shape, so re-apply is a no-op. + +UPDATE paliad.deadline_rules dr + SET condition_expr = NULL + FROM paliad.proceeding_types pt + WHERE dr.proceeding_type_id = pt.id + AND pt.code IN ('upc.inf.cfi', 'upc.rev.cfi') + AND dr.rule_code = 'RoP.019.1' + AND dr.condition_expr::text LIKE '%with_po%';