EventDeadlineService.Calculate now reads source rows from paliad.deadline_rules directly (WHERE trigger_event_id IS NOT NULL), joining via UUID instead of title_de string. The legacy SELECTs against paliad.event_deadlines + paliad.event_deadline_rule_codes are gone. Migration 092: - Snapshots both legacy tables into _pre_092 audit anchors. - Adds paliad.deadline_rules.rule_codes text[] and backfills the 72 multi-code citations from event_deadline_rule_codes via the sequence_order = 1000 + ed.id convention from mig 085 (70 of 77 Pipeline-C deadlines carry codes; 7 are codeless). - Hard assertion ties source-junction-row count to backfilled text[]-element count — any sequence_order mismatch aborts the drop. - Drops the mig 086 read-only trigger (orphan once event_deadlines goes away). - Drops paliad.event_deadlines + paliad.event_deadline_rule_codes. - Final assertion: >=77 active deadline_rules with trigger_event_id NOT NULL — Slice 3 corpus must not have collapsed. - audit_reason wrapper at top so the deadline_rules UPDATE row-trigger records the reason in deadline_rule_audit. Verified via BEGIN..ROLLBACK against the live paliad DB: 72 codes backfilled into 70 rule_codes arrays, multi-code rules (RoP.029.a + RoP.030 for ed_id=6) preserve their ordering, composite rules (combine_op=max) remain intact, both tables drop cleanly, all assertions pass. Parity test rebound to deadline_rules — independent computation still re-runs applyDuration against raw column values for date/composite parity. EventDeadlineResult.ID stays int64 via the sequence_order - 1000 convention so the public /api/tools/event-deadlines wire shape is unchanged.
117 lines
5.4 KiB
PL/PgSQL
117 lines
5.4 KiB
PL/PgSQL
-- t-paliad-199 down — reverses 092_drop_event_deadlines_tables.up.sql.
|
|
--
|
|
-- Re-creates paliad.event_deadlines + paliad.event_deadline_rule_codes
|
|
-- with the schema they had at end of mig 086 (the read-only state right
|
|
-- before mig 092 dropped them), repopulates from the _pre_092
|
|
-- snapshots, restores the mig 086 read-only trigger, and drops the
|
|
-- rule_codes column the up migration added to paliad.deadline_rules.
|
|
--
|
|
-- The snapshot tables themselves stay — they're the source of this
|
|
-- rollback's data and a permanent audit artefact. A focused
|
|
-- follow-up slice / Slice 12 cleanup drops the snapshots once
|
|
-- Slice 9 is verified in prod.
|
|
|
|
SELECT set_config(
|
|
'paliad.audit_reason',
|
|
'rollback 092: restore paliad.event_deadlines + event_deadline_rule_codes from pre-drop snapshots and drop rule_codes column',
|
|
true);
|
|
|
|
-- =============================================================================
|
|
-- 1. Recreate paliad.event_deadlines. Schema matches the live state at
|
|
-- the start of mig 092 (post-mig-086, with the notes_en column from
|
|
-- mig 036 and the legal_source column from mig 038).
|
|
-- =============================================================================
|
|
|
|
CREATE TABLE IF NOT EXISTS paliad.event_deadlines (
|
|
id bigint PRIMARY KEY,
|
|
trigger_event_id bigint NOT NULL REFERENCES paliad.trigger_events(id) ON DELETE CASCADE,
|
|
title text NOT NULL,
|
|
title_de text NOT NULL DEFAULT '',
|
|
duration_value integer NOT NULL DEFAULT 0,
|
|
duration_unit text NOT NULL DEFAULT 'days'
|
|
CHECK (duration_unit IN ('days', 'weeks', 'months', 'working_days')),
|
|
timing text NOT NULL DEFAULT 'after'
|
|
CHECK (timing IN ('before', 'after')),
|
|
notes text NOT NULL DEFAULT '',
|
|
alt_duration_value integer,
|
|
alt_duration_unit text CHECK (alt_duration_unit IS NULL OR alt_duration_unit IN ('days', 'weeks', 'months', 'working_days')),
|
|
combine_op text CHECK (combine_op IS NULL OR combine_op IN ('max', 'min')),
|
|
is_active boolean NOT NULL DEFAULT true,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
notes_en text,
|
|
legal_source text
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS event_deadlines_trigger_event_idx
|
|
ON paliad.event_deadlines (trigger_event_id);
|
|
|
|
CREATE INDEX IF NOT EXISTS event_deadlines_active_idx
|
|
ON paliad.event_deadlines (is_active) WHERE is_active = true;
|
|
|
|
CREATE INDEX IF NOT EXISTS event_deadlines_legal_src_trgm
|
|
ON paliad.event_deadlines USING gin (legal_source gin_trgm_ops);
|
|
|
|
INSERT INTO paliad.event_deadlines
|
|
(id, trigger_event_id, title, title_de, duration_value, duration_unit,
|
|
timing, notes, alt_duration_value, alt_duration_unit, combine_op,
|
|
is_active, created_at, updated_at, notes_en, legal_source)
|
|
SELECT id, trigger_event_id, title, title_de, duration_value, duration_unit,
|
|
timing, notes, alt_duration_value, alt_duration_unit, combine_op,
|
|
is_active, created_at, updated_at, notes_en, legal_source
|
|
FROM paliad.event_deadlines_pre_092
|
|
ON CONFLICT (id) DO NOTHING;
|
|
|
|
-- =============================================================================
|
|
-- 2. Recreate paliad.event_deadline_rule_codes.
|
|
-- =============================================================================
|
|
|
|
CREATE TABLE IF NOT EXISTS paliad.event_deadline_rule_codes (
|
|
event_deadline_id bigint NOT NULL REFERENCES paliad.event_deadlines(id) ON DELETE CASCADE,
|
|
rule_code text NOT NULL,
|
|
sort_order integer NOT NULL DEFAULT 0,
|
|
PRIMARY KEY (event_deadline_id, rule_code)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS event_deadline_rule_codes_code_idx
|
|
ON paliad.event_deadline_rule_codes (rule_code);
|
|
|
|
INSERT INTO paliad.event_deadline_rule_codes
|
|
(event_deadline_id, rule_code, sort_order)
|
|
SELECT event_deadline_id, rule_code, sort_order
|
|
FROM paliad.event_deadline_rule_codes_pre_092
|
|
ON CONFLICT (event_deadline_id, rule_code) DO NOTHING;
|
|
|
|
-- =============================================================================
|
|
-- 3. Restore the mig 086 read-only trigger + function (the rolled-back
|
|
-- state IS "Slice 3 + Slice 9 only", which had the trigger in place).
|
|
-- =============================================================================
|
|
|
|
CREATE OR REPLACE FUNCTION paliad.event_deadlines_readonly_trigger()
|
|
RETURNS trigger
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
BEGIN
|
|
RAISE EXCEPTION
|
|
'paliad.event_deadlines is read-only after Phase 3 Slice 3 — '
|
|
'writes must go through paliad.deadline_rules (Pipeline C is '
|
|
'unified; the source table is preserved as an audit anchor '
|
|
'until Slice 9 drops it). Operation: %', TG_OP;
|
|
END;
|
|
$$;
|
|
|
|
DROP TRIGGER IF EXISTS event_deadlines_readonly ON paliad.event_deadlines;
|
|
CREATE TRIGGER event_deadlines_readonly
|
|
BEFORE INSERT OR UPDATE OR DELETE ON paliad.event_deadlines
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION paliad.event_deadlines_readonly_trigger();
|
|
|
|
-- =============================================================================
|
|
-- 4. Drop the rule_codes column the up migration added. The data is
|
|
-- preserved in paliad.event_deadline_rule_codes (just restored
|
|
-- above), so dropping the column doesn't lose history.
|
|
-- =============================================================================
|
|
|
|
ALTER TABLE paliad.deadline_rules
|
|
DROP COLUMN IF EXISTS rule_codes;
|