Files
wyndham-ARR/database/017_daily_price_review.down.sql
2026-08-06 22:40:18 +08:00

173 lines
7.4 KiB
PL/PgSQL

-- Protected rollback for migration 017. It deliberately refuses to discard any
-- review/audit/manual-price fact; use a forward corrective migration instead.
BEGIN;
DO $$
BEGIN
IF current_database() <> 'booking_test' THEN
RAISE EXCEPTION 'ARR daily price review rollback is allowed only in booking_test';
END IF;
IF to_regclass('ingestion.daily_review_cases') IS NULL THEN
RAISE EXCEPTION 'ARR daily price review migration is not applied';
END IF;
IF EXISTS (SELECT 1 FROM ingestion.daily_review_cases)
OR EXISTS (
SELECT 1
FROM finance.daily_versions
WHERE review_case_id IS NOT NULL
OR manual_override_sha256 IS NOT NULL
OR manually_priced_rows <> 0
)
OR EXISTS (
SELECT 1 FROM ingestion.processing_runs WHERE run_status = 'awaiting_review'
)
OR EXISTS (
SELECT 1 FROM ingestion.processing_attempts WHERE attempt_status = 'review_required'
)
OR EXISTS (
SELECT 1 FROM ingestion.processing_deliveries
WHERE delivery_status = 'recorded_review' OR result_status = 'review_required'
) THEN
RAISE EXCEPTION
'refusing destructive rollback: daily review or manual-pricing facts exist';
END IF;
END;
$$;
DO $$
BEGIN
IF to_regrole('arr_app') IS NOT NULL THEN
EXECUTE 'REVOKE SELECT, INSERT, UPDATE ON ingestion.daily_review_cases, ingestion.daily_review_items, ingestion.daily_review_events FROM arr_app';
EXECUTE 'REVOKE USAGE, SELECT ON SEQUENCE ingestion.daily_review_cases_id_seq, ingestion.daily_review_items_id_seq, ingestion.daily_review_events_id_seq FROM arr_app';
END IF;
END;
$$;
ALTER TABLE finance.daily_versions
DROP CONSTRAINT IF EXISTS daily_versions_review_lineage_shape;
DROP INDEX IF EXISTS finance.daily_versions_review_case_unique;
DROP INDEX IF EXISTS finance.daily_versions_source_rule_override_unique;
ALTER TABLE finance.daily_versions
DROP COLUMN manually_priced_rows,
DROP COLUMN manual_override_sha256,
DROP COLUMN review_case_id;
CREATE UNIQUE INDEX daily_versions_source_rule_unique
ON finance.daily_versions (
source_artifact_id,
business_date,
processor_version,
rule_set_sha256
)
WHERE business_date IS NOT NULL;
ALTER TABLE finance.daily_records
DROP CONSTRAINT IF EXISTS daily_records_retained_values;
ALTER TABLE finance.daily_records
ADD CONSTRAINT daily_records_retained_values CHECK (
outcome <> 'retained'
OR (
block_code IS NOT NULL
AND adults IS NOT NULL AND adults >= 0
AND children IS NOT NULL AND children >= 0
AND company_name IS NOT NULL AND btrim(company_name) <> ''
AND company_key IS NOT NULL AND btrim(company_key) <> ''
AND confirmation_no IS NOT NULL AND btrim(confirmation_no) <> ''
AND disp_room_no IS NOT NULL AND btrim(disp_room_no) <> ''
AND effective_rate_amount IS NOT NULL AND effective_rate_amount >= 0
AND full_name IS NOT NULL
AND no_of_rooms IS NOT NULL AND no_of_rooms > 0
AND rate_code IS NOT NULL
AND normalized_rate_code IS NOT NULL
AND arrival IS NOT NULL
AND departure IS NOT NULL
AND nights IS NOT NULL AND nights >= 0
AND real_price IS NOT NULL AND real_price >= 0
AND total_price IS NOT NULL AND total_price >= 0
AND channel_key IS NOT NULL AND btrim(channel_key) <> ''
AND pricing_method IN ('price_reference_exact', 'zero_price_exception')
)
);
ALTER TABLE ingestion.processing_deliveries
DROP CONSTRAINT IF EXISTS processing_deliveries_review_case_fk,
DROP COLUMN review_case_id,
DROP COLUMN manual_override_artifact_id;
DROP TRIGGER IF EXISTS daily_review_items_mutability_guard ON ingestion.daily_review_items;
DROP TRIGGER IF EXISTS daily_review_cases_immutability_guard ON ingestion.daily_review_cases;
DROP TRIGGER IF EXISTS daily_review_events_immutability_guard ON ingestion.daily_review_events;
DROP FUNCTION IF EXISTS ingestion.enforce_daily_review_item_mutability();
DROP FUNCTION IF EXISTS ingestion.enforce_daily_review_case_immutability();
DROP FUNCTION IF EXISTS ingestion.enforce_daily_review_event_immutability();
DROP TABLE ingestion.daily_review_events;
DROP TABLE ingestion.daily_review_items;
DROP TABLE ingestion.daily_review_cases;
ALTER TABLE ingestion.processing_deliveries
DROP CONSTRAINT IF EXISTS processing_deliveries_delivery_status_check,
DROP CONSTRAINT IF EXISTS processing_deliveries_result_status_check;
ALTER TABLE ingestion.processing_deliveries
ADD CONSTRAINT processing_deliveries_delivery_status_check CHECK (delivery_status IN (
'received', 'validating', 'committed', 'recorded_failure', 'rejected'
)),
ADD CONSTRAINT processing_deliveries_result_status_check CHECK (result_status IN (
'success', 'failed'
));
ALTER TABLE ingestion.processing_attempts
DROP CONSTRAINT IF EXISTS processing_attempts_attempt_status_check,
DROP CONSTRAINT IF EXISTS processing_attempts_terminal_shape;
ALTER TABLE ingestion.processing_attempts
ADD CONSTRAINT processing_attempts_attempt_status_check CHECK (attempt_status IN (
'queued', 'dispatched', 'running', 'delivered', 'succeeded', 'failed', 'cancelled'
)),
ADD CONSTRAINT processing_attempts_terminal_shape CHECK (
(attempt_status = 'succeeded' AND failure_code IS NULL AND finished_at IS NOT NULL)
OR (attempt_status = 'failed' AND failure_code IS NOT NULL AND finished_at IS NOT NULL)
OR (attempt_status = 'cancelled' AND finished_at IS NOT NULL)
OR attempt_status IN ('queued', 'dispatched', 'running', 'delivered')
);
ALTER TABLE ingestion.processing_runs
DROP CONSTRAINT IF EXISTS processing_runs_run_status_check,
DROP CONSTRAINT IF EXISTS processing_runs_terminal_shape;
ALTER TABLE ingestion.processing_runs
ADD CONSTRAINT processing_runs_run_status_check CHECK (run_status IN (
'received', 'queued', 'running', 'validating', 'accepted', 'rejected', 'failed', 'cancelled'
)),
ADD CONSTRAINT processing_runs_terminal_shape CHECK (
(
run_status = 'accepted'
AND failure_code IS NULL
AND validated_at IS NOT NULL
AND finished_at IS NOT NULL
AND (
pipeline_type <> 'opera_daily'
OR (
business_date IS NOT NULL
AND delivered_processor_version IS NOT NULL
AND delivered_rule_set_sha256 IS NOT NULL
AND result_schema_version IS NOT NULL
AND delivery_sha256 IS NOT NULL
AND (
(
result_delivery_mode = 'artifact_callback'
AND result_artifact_id IS NOT NULL
)
OR (
result_delivery_mode = 'direct_mcp'
AND result_artifact_id IS NULL
)
)
)
)
)
OR (run_status IN ('rejected', 'failed') AND failure_code IS NOT NULL AND finished_at IS NOT NULL)
OR (run_status = 'cancelled' AND finished_at IS NOT NULL)
OR run_status IN ('received', 'queued', 'running', 'validating')
);
COMMIT;