173 lines
7.4 KiB
PL/PgSQL
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;
|