-- Deterministic monthly-report worksheet manifest -- PostgreSQL 15+ -- Target database: booking_test (connect to that database before running). -- Additive migration; do not edit applied migrations 001-005 in place. BEGIN; CREATE TABLE finance.report_channel_manifest ( report_version_id bigint NOT NULL REFERENCES finance.report_versions(id), worksheet text NOT NULL CHECK ( btrim(worksheet) <> '' AND char_length(worksheet) <= 31 ), worksheet_order integer NOT NULL CHECK (worksheet_order > 0), row_count integer NOT NULL CHECK (row_count >= 0), PRIMARY KEY (report_version_id, worksheet), CONSTRAINT report_channel_manifest_order_unique UNIQUE (report_version_id, worksheet_order) ); COMMENT ON TABLE finance.report_channel_manifest IS 'Exact worksheet names, one-based order, and row counts for one immutable monthly-channel report artifact; empty worksheets are retained with row_count zero.'; CREATE OR REPLACE FUNCTION finance.validate_report_channel_manifest_parent() RETURNS trigger LANGUAGE plpgsql AS $$ BEGIN IF NOT EXISTS ( SELECT 1 FROM finance.report_versions AS report WHERE report.id = NEW.report_version_id AND report.report_kind = 'monthly_channel' ) THEN RAISE EXCEPTION 'channel manifest must reference a monthly_channel report'; END IF; RETURN NEW; END; $$; CREATE TRIGGER report_channel_manifest_parent_guard BEFORE INSERT OR UPDATE ON finance.report_channel_manifest FOR EACH ROW EXECUTE FUNCTION finance.validate_report_channel_manifest_parent(); -- Controlled backfill for the already-verified July 2026 monthly artifact in -- booking_test. On a clean deployment this inserts zero rows. If another -- current legacy monthly report exists, the guard below aborts the migration -- so its sheet order can be inspected rather than guessed. WITH verified_legacy_report AS ( SELECT report.id FROM finance.report_versions AS report JOIN booking.file_objects AS artifact ON artifact.id = report.artifact_file_id WHERE report.report_kind = 'monthly_channel' AND report.period_start = DATE '2026-07-01' AND report.period_end = DATE '2026-07-31' AND report.as_of_date = DATE '2026-07-26' AND report.company_scope = '*' AND report.report_status = 'active' AND report.is_current AND artifact.file_kind = 'monthly_xlsx' AND artifact.sha256 = '592fee9b1e3e8290ed1e115d7eb213f09e780fa2bda08f6e270a34e7eaedd09f' ), manifest(worksheet, worksheet_order, row_count) AS ( VALUES ('LIANTAI-GROUP', 1, 195), ('LIANTAI-FIT', 2, 275), ('QBD', 3, 258), ('DY-AI-Easy-KB', 4, 74), ('FENGRUN', 5, 41), ('T- HANATOUR TD CO., L', 6, 24) ) INSERT INTO finance.report_channel_manifest ( report_version_id, worksheet, worksheet_order, row_count ) SELECT legacy.id, manifest.worksheet, manifest.worksheet_order, manifest.row_count FROM verified_legacy_report AS legacy CROSS JOIN manifest; DO $$ BEGIN IF EXISTS ( SELECT 1 FROM finance.report_versions AS report WHERE report.report_kind = 'monthly_channel' AND report.report_status = 'active' AND report.is_current AND NOT EXISTS ( SELECT 1 FROM finance.report_channel_manifest AS manifest WHERE manifest.report_version_id = report.id ) ) THEN RAISE EXCEPTION 'current legacy monthly report requires an inspected channel manifest'; END IF; END; $$; CREATE OR REPLACE FUNCTION finance.protect_published_report_channel_manifest() RETURNS trigger LANGUAGE plpgsql AS $$ DECLARE target_report_version_id bigint; BEGIN target_report_version_id := CASE WHEN TG_OP = 'DELETE' THEN OLD.report_version_id ELSE NEW.report_version_id END; IF EXISTS ( SELECT 1 FROM finance.report_versions AS report WHERE report.id = target_report_version_id AND report.report_status IN ('active', 'superseded') ) THEN RAISE EXCEPTION 'published monthly report channel manifest is immutable'; END IF; RETURN CASE WHEN TG_OP = 'DELETE' THEN OLD ELSE NEW END; END; $$; CREATE TRIGGER published_report_channel_manifest_guard BEFORE INSERT OR UPDATE OR DELETE ON finance.report_channel_manifest FOR EACH ROW EXECUTE FUNCTION finance.protect_published_report_channel_manifest(); CREATE OR REPLACE FUNCTION finance.validate_monthly_report_channel_manifest() RETURNS trigger LANGUAGE plpgsql AS $$ DECLARE manifest_count integer; first_order integer; last_order integer; BEGIN IF NEW.report_kind = 'monthly_channel' AND NEW.report_status = 'active' AND NEW.is_current THEN SELECT count(*), min(worksheet_order), max(worksheet_order) INTO manifest_count, first_order, last_order FROM finance.report_channel_manifest WHERE report_version_id = NEW.id; IF manifest_count = 0 OR first_order <> 1 OR last_order <> manifest_count THEN RAISE EXCEPTION 'active monthly report requires a continuous channel manifest'; END IF; END IF; RETURN NEW; END; $$; CREATE TRIGGER monthly_report_channel_manifest_guard BEFORE INSERT OR UPDATE OF report_status, is_current ON finance.report_versions FOR EACH ROW EXECUTE FUNCTION finance.validate_monthly_report_channel_manifest(); COMMIT;