-- UPC Proceeding Timeline: Full event tree with conditional deadlines -- Ported from youpc.org migrations 039 + 040 -- Run against mgmt schema in youpc.org Supabase instance -- ======================================== -- 1. Add is_spawn + spawn_label columns -- ======================================== ALTER TABLE deadline_rules ADD COLUMN IF NOT EXISTS is_spawn BOOLEAN DEFAULT false, ADD COLUMN IF NOT EXISTS spawn_label TEXT; -- ======================================== -- 2. Clear existing UPC rules (fresh seed) -- ======================================== DELETE FROM deadline_rules WHERE proceeding_type_id IN ( SELECT id FROM proceeding_types WHERE code IN ('INF', 'REV', 'CCR', 'APM', 'APP', 'AMD') ); -- ======================================== -- 3. Ensure all proceeding types exist -- ======================================== INSERT INTO proceeding_types (code, name, description, is_active, sort_order, default_color) VALUES ('INF', 'Infringement', 'Patent infringement proceedings', true, 1, '#3b82f6'), ('REV', 'Revocation', 'Standalone revocation proceedings', true, 2, '#ef4444'), ('CCR', 'Counterclaim for Revocation', 'Counterclaim for revocation within infringement', true, 3, '#ef4444'), ('APM', 'Provisional Measures', 'Application for preliminary injunction', true, 4, '#f59e0b'), ('APP', 'Appeal', 'Appeal to the Court of Appeal', true, 5, '#8b5cf6'), ('AMD', 'Application to Amend Patent', 'Sub-proceeding for patent amendment during revocation', true, 6, '#10b981') ON CONFLICT (code) DO UPDATE SET name = EXCLUDED.name, description = EXCLUDED.description, default_color = EXCLUDED.default_color, sort_order = EXCLUDED.sort_order, is_active = EXCLUDED.is_active; -- ======================================== -- 4. Seed all proceeding events -- ======================================== DO $$ DECLARE v_inf INTEGER; v_rev INTEGER; v_ccr INTEGER; v_apm INTEGER; v_app INTEGER; v_amd INTEGER; -- INF event IDs v_inf_soc UUID; v_inf_sod UUID; v_inf_reply UUID; v_inf_rejoin UUID; v_inf_interim UUID; v_inf_oral UUID; v_inf_decision UUID; v_inf_prelim UUID; -- CCR event IDs v_ccr_root UUID; v_ccr_defence UUID; v_ccr_reply UUID; v_ccr_rejoin UUID; v_ccr_interim UUID; v_ccr_oral UUID; v_ccr_decision UUID; -- REV event IDs v_rev_app UUID; v_rev_defence UUID; v_rev_reply UUID; v_rev_rejoin UUID; v_rev_interim UUID; v_rev_oral UUID; v_rev_decision UUID; -- PI event IDs v_pi_app UUID; v_pi_resp UUID; v_pi_oral UUID; -- APP event IDs v_app_notice UUID; v_app_grounds UUID; v_app_response UUID; v_app_oral UUID; BEGIN SELECT id INTO v_inf FROM proceeding_types WHERE code = 'INF'; SELECT id INTO v_rev FROM proceeding_types WHERE code = 'REV'; SELECT id INTO v_ccr FROM proceeding_types WHERE code = 'CCR'; SELECT id INTO v_apm FROM proceeding_types WHERE code = 'APM'; SELECT id INTO v_app FROM proceeding_types WHERE code = 'APP'; SELECT id INTO v_amd FROM proceeding_types WHERE code = 'AMD'; -- ======================================== -- INFRINGEMENT PROCEEDINGS -- ======================================== -- Root: Statement of Claim v_inf_soc := gen_random_uuid(); INSERT INTO deadline_rules (id, proceeding_type_id, parent_id, code, name, description, primary_party, event_type, is_mandatory, duration_value, duration_unit, rule_code, deadline_notes, is_spawn, spawn_label, sequence_order, is_active) VALUES (v_inf_soc, v_inf, NULL, 'inf.soc', 'Statement of Claim', 'Claimant files the statement of claim with the Registry', 'claimant', 'filing', true, 0, 'months', NULL, NULL, false, NULL, 0, true); -- Preliminary Objection (from SoC) v_inf_prelim := gen_random_uuid(); INSERT INTO deadline_rules (id, proceeding_type_id, parent_id, code, name, description, primary_party, event_type, is_mandatory, duration_value, duration_unit, rule_code, deadline_notes, is_spawn, spawn_label, sequence_order, is_active) VALUES (v_inf_prelim, v_inf, v_inf_soc, 'inf.prelim', 'Preliminary Objection', 'Defendant raises preliminary objection (jurisdiction, admissibility)', 'defendant', 'filing', false, 1, 'months', 'R.19', 'Rarely triggers separate decision; usually decided with main case', false, NULL, 1, true); -- Statement of Defence (from SoC) v_inf_sod := gen_random_uuid(); INSERT INTO deadline_rules (id, proceeding_type_id, parent_id, code, name, description, primary_party, event_type, is_mandatory, duration_value, duration_unit, rule_code, deadline_notes, is_spawn, spawn_label, sequence_order, is_active) VALUES (v_inf_sod, v_inf, v_inf_soc, 'inf.sod', 'Statement of Defence', 'Defendant files the statement of defence', 'defendant', 'filing', true, 3, 'months', 'RoP.023', NULL, false, NULL, 2, true); -- Reply to Defence (from SoD) — CONDITIONAL: rule code changes if CCR v_inf_reply := gen_random_uuid(); INSERT INTO deadline_rules (id, proceeding_type_id, parent_id, code, name, description, primary_party, event_type, is_mandatory, duration_value, duration_unit, rule_code, deadline_notes, is_spawn, spawn_label, sequence_order, is_active) VALUES (v_inf_reply, v_inf, v_inf_sod, 'inf.reply', 'Reply to Defence', 'Claimant''s reply to the statement of defence (includes Defence to Counterclaim if CCR active)', 'claimant', 'filing', true, 2, 'months', 'RoP.029b', NULL, false, NULL, 1, true); -- Rejoinder (from Reply) — CONDITIONAL: duration changes if CCR v_inf_rejoin := gen_random_uuid(); INSERT INTO deadline_rules (id, proceeding_type_id, parent_id, code, name, description, primary_party, event_type, is_mandatory, duration_value, duration_unit, rule_code, deadline_notes, is_spawn, spawn_label, sequence_order, is_active) VALUES (v_inf_rejoin, v_inf, v_inf_reply, 'inf.rejoin', 'Rejoinder', 'Defendant''s rejoinder to the reply', 'defendant', 'filing', true, 1, 'months', 'RoP.029c', NULL, false, NULL, 0, true); -- Interim Conference v_inf_interim := gen_random_uuid(); INSERT INTO deadline_rules (id, proceeding_type_id, parent_id, code, name, description, primary_party, event_type, is_mandatory, duration_value, duration_unit, rule_code, deadline_notes, is_spawn, spawn_label, sequence_order, is_active) VALUES (v_inf_interim, v_inf, v_inf_rejoin, 'inf.interim', 'Interim Conference', 'Interim conference with the judge-rapporteur', 'court', 'hearing', true, 0, 'months', NULL, NULL, false, NULL, 0, true); -- Oral Hearing v_inf_oral := gen_random_uuid(); INSERT INTO deadline_rules (id, proceeding_type_id, parent_id, code, name, description, primary_party, event_type, is_mandatory, duration_value, duration_unit, rule_code, deadline_notes, is_spawn, spawn_label, sequence_order, is_active) VALUES (v_inf_oral, v_inf, v_inf_interim, 'inf.oral', 'Oral Hearing', 'Oral hearing before the panel', 'court', 'hearing', true, 0, 'months', NULL, NULL, false, NULL, 0, true); -- Decision v_inf_decision := gen_random_uuid(); INSERT INTO deadline_rules (id, proceeding_type_id, parent_id, code, name, description, primary_party, event_type, is_mandatory, duration_value, duration_unit, rule_code, deadline_notes, is_spawn, spawn_label, sequence_order, is_active) VALUES (v_inf_decision, v_inf, v_inf_oral, 'inf.decision', 'Decision', 'Panel delivers its decision', 'court', 'decision', true, 0, 'months', NULL, NULL, false, NULL, 0, true); -- Appeal (spawn from Decision — cross-type to APP) INSERT INTO deadline_rules (id, proceeding_type_id, parent_id, code, name, description, primary_party, event_type, is_mandatory, duration_value, duration_unit, rule_code, deadline_notes, is_spawn, spawn_label, sequence_order, is_active) VALUES (gen_random_uuid(), v_app, v_inf_decision, 'inf.appeal', 'Appeal', 'Appeal against infringement decision to Court of Appeal', 'both', 'filing', true, 2, 'months', 'RoP.220.1', NULL, true, 'Appeal filed', 0, true); -- ======================================== -- COUNTERCLAIM FOR REVOCATION (spawn from SoD) -- ======================================== v_ccr_root := gen_random_uuid(); INSERT INTO deadline_rules (id, proceeding_type_id, parent_id, code, name, description, primary_party, event_type, is_mandatory, duration_value, duration_unit, rule_code, deadline_notes, is_spawn, spawn_label, sequence_order, is_active) VALUES (v_ccr_root, v_ccr, v_inf_sod, 'ccr.counterclaim', 'Counterclaim for Revocation', 'Defendant files counterclaim challenging patent validity (included in SoD)', 'defendant', 'filing', true, 0, 'months', NULL, NULL, true, 'Includes counterclaim for revocation', 0, true); -- Defence to Counterclaim v_ccr_defence := gen_random_uuid(); INSERT INTO deadline_rules (id, proceeding_type_id, parent_id, code, name, description, primary_party, event_type, is_mandatory, duration_value, duration_unit, rule_code, deadline_notes, is_spawn, spawn_label, sequence_order, is_active) VALUES (v_ccr_defence, v_ccr, v_ccr_root, 'ccr.defence', 'Defence to Counterclaim', 'Patent proprietor files defence to revocation counterclaim', 'claimant', 'filing', true, 3, 'months', 'RoP.050', NULL, false, NULL, 0, true); -- Reply in CCR v_ccr_reply := gen_random_uuid(); INSERT INTO deadline_rules (id, proceeding_type_id, parent_id, code, name, description, primary_party, event_type, is_mandatory, duration_value, duration_unit, rule_code, deadline_notes, is_spawn, spawn_label, sequence_order, is_active) VALUES (v_ccr_reply, v_ccr, v_ccr_defence, 'ccr.reply', 'Reply in CCR', 'Reply in the counterclaim for revocation', 'defendant', 'filing', true, 2, 'months', NULL, 'Timing overlaps with infringement Rejoinder', false, NULL, 1, true); -- Rejoinder in CCR v_ccr_rejoin := gen_random_uuid(); INSERT INTO deadline_rules (id, proceeding_type_id, parent_id, code, name, description, primary_party, event_type, is_mandatory, duration_value, duration_unit, rule_code, deadline_notes, is_spawn, spawn_label, sequence_order, is_active) VALUES (v_ccr_rejoin, v_ccr, v_ccr_reply, 'ccr.rejoin', 'Rejoinder in CCR', 'Rejoinder in the counterclaim for revocation', 'claimant', 'filing', true, 2, 'months', NULL, NULL, false, NULL, 0, true); -- Interim Conference v_ccr_interim := gen_random_uuid(); INSERT INTO deadline_rules (id, proceeding_type_id, parent_id, code, name, description, primary_party, event_type, is_mandatory, duration_value, duration_unit, rule_code, deadline_notes, is_spawn, spawn_label, sequence_order, is_active) VALUES (v_ccr_interim, v_ccr, v_ccr_rejoin, 'ccr.interim', 'Interim Conference', 'Interim conference covering revocation issues', 'court', 'hearing', true, 0, 'months', NULL, 'May be combined with infringement IC', false, NULL, 0, true); -- Oral Hearing v_ccr_oral := gen_random_uuid(); INSERT INTO deadline_rules (id, proceeding_type_id, parent_id, code, name, description, primary_party, event_type, is_mandatory, duration_value, duration_unit, rule_code, deadline_notes, is_spawn, spawn_label, sequence_order, is_active) VALUES (v_ccr_oral, v_ccr, v_ccr_interim, 'ccr.oral', 'Oral Hearing', 'Oral hearing on validity', 'court', 'hearing', true, 0, 'months', NULL, NULL, false, NULL, 0, true); -- Decision v_ccr_decision := gen_random_uuid(); INSERT INTO deadline_rules (id, proceeding_type_id, parent_id, code, name, description, primary_party, event_type, is_mandatory, duration_value, duration_unit, rule_code, deadline_notes, is_spawn, spawn_label, sequence_order, is_active) VALUES (v_ccr_decision, v_ccr, v_ccr_oral, 'ccr.decision', 'Decision', 'Decision on validity of the patent', 'court', 'decision', true, 0, 'months', NULL, NULL, false, NULL, 0, true); -- Appeal from CCR INSERT INTO deadline_rules (id, proceeding_type_id, parent_id, code, name, description, primary_party, event_type, is_mandatory, duration_value, duration_unit, rule_code, deadline_notes, is_spawn, spawn_label, sequence_order, is_active) VALUES (gen_random_uuid(), v_app, v_ccr_decision, 'ccr.appeal', 'Appeal', 'Appeal against revocation decision to Court of Appeal', 'both', 'filing', true, 2, 'months', 'RoP.220.1', NULL, true, 'Appeal filed', 0, true); -- Application to Amend Patent (spawn from Defence to CCR) INSERT INTO deadline_rules (id, proceeding_type_id, parent_id, code, name, description, primary_party, event_type, is_mandatory, duration_value, duration_unit, rule_code, deadline_notes, is_spawn, spawn_label, sequence_order, is_active) VALUES (gen_random_uuid(), v_amd, v_ccr_defence, 'ccr.amend', 'Application to Amend Patent', 'Patent proprietor applies to amend the patent during revocation proceedings', 'claimant', 'filing', false, 0, 'months', NULL, NULL, true, 'Includes application to amend patent', 2, true); -- ======================================== -- STANDALONE REVOCATION -- ======================================== v_rev_app := gen_random_uuid(); INSERT INTO deadline_rules (id, proceeding_type_id, parent_id, code, name, description, primary_party, event_type, is_mandatory, duration_value, duration_unit, rule_code, deadline_notes, is_spawn, spawn_label, sequence_order, is_active) VALUES (v_rev_app, v_rev, NULL, 'rev.app', 'Application for Revocation', 'Applicant files standalone application for revocation of the patent', 'claimant', 'filing', true, 0, 'months', NULL, NULL, false, NULL, 0, true); v_rev_defence := gen_random_uuid(); INSERT INTO deadline_rules (id, proceeding_type_id, parent_id, code, name, description, primary_party, event_type, is_mandatory, duration_value, duration_unit, rule_code, deadline_notes, is_spawn, spawn_label, sequence_order, is_active) VALUES (v_rev_defence, v_rev, v_rev_app, 'rev.defence', 'Defence to Revocation', 'Patent proprietor files defence to revocation application', 'defendant', 'filing', true, 3, 'months', NULL, NULL, false, NULL, 0, true); v_rev_reply := gen_random_uuid(); INSERT INTO deadline_rules (id, proceeding_type_id, parent_id, code, name, description, primary_party, event_type, is_mandatory, duration_value, duration_unit, rule_code, deadline_notes, is_spawn, spawn_label, sequence_order, is_active) VALUES (v_rev_reply, v_rev, v_rev_defence, 'rev.reply', 'Reply', 'Reply in standalone revocation proceedings', 'claimant', 'filing', true, 2, 'months', NULL, NULL, false, NULL, 1, true); v_rev_rejoin := gen_random_uuid(); INSERT INTO deadline_rules (id, proceeding_type_id, parent_id, code, name, description, primary_party, event_type, is_mandatory, duration_value, duration_unit, rule_code, deadline_notes, is_spawn, spawn_label, sequence_order, is_active) VALUES (v_rev_rejoin, v_rev, v_rev_reply, 'rev.rejoin', 'Rejoinder', 'Rejoinder in standalone revocation proceedings', 'defendant', 'filing', true, 2, 'months', NULL, NULL, false, NULL, 0, true); v_rev_interim := gen_random_uuid(); INSERT INTO deadline_rules (id, proceeding_type_id, parent_id, code, name, description, primary_party, event_type, is_mandatory, duration_value, duration_unit, rule_code, deadline_notes, is_spawn, spawn_label, sequence_order, is_active) VALUES (v_rev_interim, v_rev, v_rev_rejoin, 'rev.interim', 'Interim Conference', 'Interim conference with the judge-rapporteur', 'court', 'hearing', true, 0, 'months', NULL, NULL, false, NULL, 0, true); v_rev_oral := gen_random_uuid(); INSERT INTO deadline_rules (id, proceeding_type_id, parent_id, code, name, description, primary_party, event_type, is_mandatory, duration_value, duration_unit, rule_code, deadline_notes, is_spawn, spawn_label, sequence_order, is_active) VALUES (v_rev_oral, v_rev, v_rev_interim, 'rev.oral', 'Oral Hearing', 'Oral hearing on validity in standalone revocation', 'court', 'hearing', true, 0, 'months', NULL, NULL, false, NULL, 0, true); v_rev_decision := gen_random_uuid(); INSERT INTO deadline_rules (id, proceeding_type_id, parent_id, code, name, description, primary_party, event_type, is_mandatory, duration_value, duration_unit, rule_code, deadline_notes, is_spawn, spawn_label, sequence_order, is_active) VALUES (v_rev_decision, v_rev, v_rev_oral, 'rev.decision', 'Decision', 'Decision on patent validity', 'court', 'decision', true, 0, 'months', NULL, NULL, false, NULL, 0, true); -- Appeal from REV INSERT INTO deadline_rules (id, proceeding_type_id, parent_id, code, name, description, primary_party, event_type, is_mandatory, duration_value, duration_unit, rule_code, deadline_notes, is_spawn, spawn_label, sequence_order, is_active) VALUES (gen_random_uuid(), v_app, v_rev_decision, 'rev.appeal', 'Appeal', 'Appeal against revocation decision to Court of Appeal', 'both', 'filing', true, 2, 'months', 'RoP.220.1', NULL, true, 'Appeal filed', 0, true); -- Application to Amend Patent from REV Defence INSERT INTO deadline_rules (id, proceeding_type_id, parent_id, code, name, description, primary_party, event_type, is_mandatory, duration_value, duration_unit, rule_code, deadline_notes, is_spawn, spawn_label, sequence_order, is_active) VALUES (gen_random_uuid(), v_amd, v_rev_defence, 'rev.amend', 'Application to Amend Patent', 'Patent proprietor applies to amend the patent', 'claimant', 'filing', false, 0, 'months', NULL, NULL, true, 'Includes application to amend patent', 2, true); -- ======================================== -- PRELIMINARY INJUNCTION -- ======================================== v_pi_app := gen_random_uuid(); INSERT INTO deadline_rules (id, proceeding_type_id, parent_id, code, name, description, primary_party, event_type, is_mandatory, duration_value, duration_unit, rule_code, deadline_notes, is_spawn, spawn_label, sequence_order, is_active) VALUES (v_pi_app, v_apm, NULL, 'pi.app', 'Application for Provisional Measures', 'Claimant files application for preliminary injunction', 'claimant', 'filing', true, 0, 'months', NULL, NULL, false, NULL, 0, true); v_pi_resp := gen_random_uuid(); INSERT INTO deadline_rules (id, proceeding_type_id, parent_id, code, name, description, primary_party, event_type, is_mandatory, duration_value, duration_unit, rule_code, deadline_notes, is_spawn, spawn_label, sequence_order, is_active) VALUES (v_pi_resp, v_apm, v_pi_app, 'pi.response', 'Response to PI Application', 'Defendant files response to preliminary injunction application', 'defendant', 'filing', true, 0, 'months', NULL, 'Deadline set by court', false, NULL, 0, true); v_pi_oral := gen_random_uuid(); INSERT INTO deadline_rules (id, proceeding_type_id, parent_id, code, name, description, primary_party, event_type, is_mandatory, duration_value, duration_unit, rule_code, deadline_notes, is_spawn, spawn_label, sequence_order, is_active) VALUES (v_pi_oral, v_apm, v_pi_resp, 'pi.oral', 'Oral Hearing', 'Oral hearing on provisional measures', 'court', 'hearing', true, 0, 'months', NULL, NULL, false, NULL, 0, true); INSERT INTO deadline_rules (id, proceeding_type_id, parent_id, code, name, description, primary_party, event_type, is_mandatory, duration_value, duration_unit, rule_code, deadline_notes, is_spawn, spawn_label, sequence_order, is_active) VALUES (gen_random_uuid(), v_apm, v_pi_oral, 'pi.order', 'Order on Provisional Measures', 'Court issues order on preliminary injunction', 'court', 'decision', true, 0, 'months', NULL, NULL, false, NULL, 0, true); -- ======================================== -- APPEAL (standalone) -- ======================================== v_app_notice := gen_random_uuid(); INSERT INTO deadline_rules (id, proceeding_type_id, parent_id, code, name, description, primary_party, event_type, is_mandatory, duration_value, duration_unit, rule_code, deadline_notes, is_spawn, spawn_label, sequence_order, is_active) VALUES (v_app_notice, v_app, NULL, 'app.notice', 'Notice of Appeal', 'Appellant files notice of appeal with the Court of Appeal', 'both', 'filing', true, 0, 'months', NULL, NULL, false, NULL, 0, true); v_app_grounds := gen_random_uuid(); INSERT INTO deadline_rules (id, proceeding_type_id, parent_id, code, name, description, primary_party, event_type, is_mandatory, duration_value, duration_unit, rule_code, deadline_notes, is_spawn, spawn_label, sequence_order, is_active) VALUES (v_app_grounds, v_app, v_app_notice, 'app.grounds', 'Statement of Grounds of Appeal', 'Appellant files statement of grounds', 'both', 'filing', true, 2, 'months', 'RoP.220.1', NULL, false, NULL, 0, true); v_app_response := gen_random_uuid(); INSERT INTO deadline_rules (id, proceeding_type_id, parent_id, code, name, description, primary_party, event_type, is_mandatory, duration_value, duration_unit, rule_code, deadline_notes, is_spawn, spawn_label, sequence_order, is_active) VALUES (v_app_response, v_app, v_app_grounds, 'app.response', 'Response to Appeal', 'Respondent files response to the appeal', 'both', 'filing', true, 2, 'months', NULL, NULL, false, NULL, 0, true); v_app_oral := gen_random_uuid(); INSERT INTO deadline_rules (id, proceeding_type_id, parent_id, code, name, description, primary_party, event_type, is_mandatory, duration_value, duration_unit, rule_code, deadline_notes, is_spawn, spawn_label, sequence_order, is_active) VALUES (v_app_oral, v_app, v_app_response, 'app.oral', 'Oral Hearing', 'Oral hearing before the Court of Appeal', 'court', 'hearing', true, 0, 'months', NULL, NULL, false, NULL, 0, true); INSERT INTO deadline_rules (id, proceeding_type_id, parent_id, code, name, description, primary_party, event_type, is_mandatory, duration_value, duration_unit, rule_code, deadline_notes, is_spawn, spawn_label, sequence_order, is_active) VALUES (gen_random_uuid(), v_app, v_app_oral, 'app.decision', 'Decision', 'Court of Appeal delivers its decision', 'court', 'decision', true, 0, 'months', NULL, NULL, false, NULL, 0, true); -- ======================================== -- 5. Set conditional deadlines (from 040) -- ======================================== -- Reply to Defence: rule code changes when CCR is active -- Default: RoP.029b | With CCR: RoP.029a UPDATE deadline_rules SET condition_rule_id = v_ccr_root, alt_rule_code = 'RoP.029a' WHERE id = v_inf_reply; -- Rejoinder: duration changes when CCR is active -- Default: 1 month RoP.029c | With CCR: 2 months RoP.029d UPDATE deadline_rules SET condition_rule_id = v_ccr_root, alt_duration_value = 2, alt_duration_unit = 'months', alt_rule_code = 'RoP.029d' WHERE id = v_inf_rejoin; END $$;