Files
ARR-2.0-0918/database/022_daily_report_retirement.down.sql
T

112 lines
3.8 KiB
PL/PgSQL

-- Operator-only rollback; refuses to discard any retirement or withdrawn publication.
BEGIN;
DO $$
BEGIN
IF current_database() <> 'booking_test' THEN
RAISE EXCEPTION 'ARR daily lifecycle rollback is allowed only in booking_test';
END IF;
IF EXISTS (SELECT 1 FROM ingestion.daily_run_retirements)
OR EXISTS (SELECT 1 FROM reporting.monthly_runs WHERE report_status = 'withdrawn' OR withdrawn_at IS NOT NULL) THEN
RAISE EXCEPTION 'refusing rollback: daily retirement or withdrawn monthly audit exists';
END IF;
END $$;
DROP TRIGGER daily_run_retirements_immutable ON ingestion.daily_run_retirements;
DROP FUNCTION ingestion.protect_daily_run_retirement();
DROP TABLE ingestion.daily_run_retirements;
DROP INDEX reporting.monthly_runs_live_snapshot_unique;
ALTER TABLE reporting.monthly_runs
DROP CONSTRAINT monthly_runs_report_status_check,
DROP CONSTRAINT monthly_runs_status_shape,
DROP COLUMN withdrawn_at;
ALTER TABLE reporting.monthly_runs
ADD CONSTRAINT monthly_runs_report_status_check CHECK (report_status IN ('reserved', 'active', 'superseded', 'failed')),
ADD CONSTRAINT monthly_runs_snapshot_unique UNIQUE (period_start, source_snapshot_sha256),
ADD CONSTRAINT monthly_runs_status_shape CHECK (
(
report_status = 'reserved'
AND workbook_artifact_id IS NULL
AND result_artifact_id IS NULL
AND semantic_sha256 IS NULL
AND failure_code IS NULL
AND failure_message IS NULL
AND published_at IS NULL
AND superseded_at IS NULL
AND failed_at IS NULL
)
OR (
report_status = 'active'
AND workbook_artifact_id IS NOT NULL
AND result_artifact_id IS NOT NULL
AND semantic_sha256 IS NOT NULL
AND failure_code IS NULL
AND failure_message IS NULL
AND published_at IS NOT NULL
AND superseded_at IS NULL
AND failed_at IS NULL
)
OR (
report_status = 'superseded'
AND workbook_artifact_id IS NOT NULL
AND result_artifact_id IS NOT NULL
AND semantic_sha256 IS NOT NULL
AND failure_code IS NULL
AND failure_message IS NULL
AND published_at IS NOT NULL
AND superseded_at IS NOT NULL
AND failed_at IS NULL
)
OR (
report_status = 'failed'
AND workbook_artifact_id IS NULL
AND result_artifact_id IS NULL
AND semantic_sha256 IS NULL
AND failure_code IS NOT NULL
AND btrim(failure_code) <> ''
AND published_at IS NULL
AND superseded_at IS NULL
AND failed_at IS NOT NULL
)
);
CREATE OR REPLACE FUNCTION finance.validate_current_daily_version()
RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
IF NOT EXISTS (
SELECT 1
FROM finance.daily_versions AS version
WHERE version.id = NEW.daily_version_id
AND version.business_date = NEW.business_date
AND version.version_status = 'active'
) THEN
RAISE EXCEPTION
'current business date must reference an active daily version';
END IF;
RETURN NEW;
END;
$$;
CREATE OR REPLACE FUNCTION reporting.protect_published_monthly_child()
RETURNS trigger
LANGUAGE plpgsql
AS $$
DECLARE
parent_id bigint;
BEGIN
parent_id := COALESCE(OLD.report_id, NEW.report_id);
IF EXISTS (
SELECT 1
FROM reporting.monthly_runs AS run
WHERE run.id = parent_id
AND run.report_status IN ('active', 'superseded')
) THEN
RAISE EXCEPTION
'published monthly report lineage and manifest are immutable';
END IF;
RETURN COALESCE(NEW, OLD);
END;
$$;
COMMIT;