Files
wyndham-ARR/database/015_booking_excel_review_drafts.sql
2026-07-31 15:11:42 +08:00

124 lines
4.6 KiB
PL/PgSQL

-- Durable Booking Excel extraction drafts and item-level human review.
-- PostgreSQL 15+. Migrations 008-014 remain immutable.
BEGIN;
DO $$
BEGIN
IF current_database() <> 'booking_test' THEN
RAISE EXCEPTION
'ARR Booking review migration is allowed only in booking_test';
END IF;
IF to_regclass('booking.current_source_batch') IS NULL
OR to_regclass('booking.room_items') IS NULL
OR to_regclass('ingestion.artifacts') IS NULL THEN
RAISE EXCEPTION
'ARR migrations 008 through 014 must be applied first';
END IF;
IF to_regclass('booking.extraction_drafts') IS NOT NULL
OR to_regclass('booking.extraction_draft_items') IS NOT NULL THEN
RAISE EXCEPTION
'ARR Booking review migration is already applied';
END IF;
END;
$$;
CREATE TABLE booking.extraction_drafts (
draft_id text PRIMARY KEY CHECK (
draft_id ~ '^bookingdraft-[0-9a-f]{32}$'
),
source_artifact_id bigint NOT NULL UNIQUE
REFERENCES ingestion.artifacts(id),
draft_status text NOT NULL CHECK (
draft_status IN ('reviewing', 'activated', 'superseded')
),
processor_version text NOT NULL CHECK (btrim(processor_version) <> ''),
rule_set_sha256 character(64) NOT NULL CHECK (
rule_set_sha256 ~ '^[0-9a-f]{64}$'
),
source_sha256 character(64) NOT NULL CHECK (
source_sha256 ~ '^[0-9a-f]{64}$'
),
source_byte_size bigint NOT NULL CHECK (source_byte_size > 0),
source_rows integer NOT NULL CHECK (source_rows > 0),
worksheet_count integer NOT NULL CHECK (worksheet_count > 0),
distinct_group_codes integer NOT NULL CHECK (distinct_group_codes > 0),
extracted_items integer NOT NULL CHECK (extracted_items > 0),
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
activated_source_batch_id bigint UNIQUE
REFERENCES booking.source_batches(id),
activated_at timestamptz,
CONSTRAINT extraction_drafts_status_shape CHECK (
(
draft_status = 'reviewing'
AND activated_source_batch_id IS NULL
AND activated_at IS NULL
)
OR (
draft_status = 'activated'
AND activated_source_batch_id IS NOT NULL
AND activated_at IS NOT NULL
)
OR (
draft_status = 'superseded'
AND activated_source_batch_id IS NULL
AND activated_at IS NULL
)
)
);
CREATE INDEX extraction_drafts_status_created_idx
ON booking.extraction_drafts (draft_status, created_at DESC);
CREATE TABLE booking.extraction_draft_items (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
draft_id text NOT NULL
REFERENCES booking.extraction_drafts(draft_id),
source_worksheet text NOT NULL CHECK (btrim(source_worksheet) <> ''),
source_row_no integer NOT NULL CHECK (source_row_no > 0),
item_no integer NOT NULL CHECK (item_no > 0),
group_code_raw text NOT NULL CHECK (btrim(group_code_raw) <> ''),
group_code_key text GENERATED ALWAYS AS (
upper(btrim(group_code_raw))
) STORED,
hotel_raw text NOT NULL CHECK (btrim(hotel_raw) <> ''),
room_type_raw text NOT NULL CHECK (btrim(room_type_raw) <> ''),
room_type_code text CHECK (
room_type_code IS NULL OR btrim(room_type_code) <> ''
),
quantity integer NOT NULL CHECK (quantity BETWEEN 1 AND 9999),
review_status text NOT NULL CHECK (
review_status IN ('confirmed', 'pending', 'deleted')
),
automatic boolean NOT NULL,
source_fragment text NOT NULL DEFAULT '',
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
CONSTRAINT extraction_draft_items_position_unique UNIQUE (
draft_id,
source_worksheet,
source_row_no,
item_no
),
CONSTRAINT extraction_draft_items_review_shape CHECK (
(review_status = 'confirmed' AND room_type_code IS NOT NULL)
OR (review_status = 'pending' AND room_type_code IS NULL)
OR review_status = 'deleted'
)
);
CREATE INDEX extraction_draft_items_draft_status_idx
ON booking.extraction_draft_items (draft_id, review_status, id);
CREATE INDEX extraction_draft_items_group_idx
ON booking.extraction_draft_items (draft_id, group_code_key);
COMMENT ON TABLE booking.extraction_drafts IS
'Private Booking Excel extraction drafts. A reviewing draft never changes the active accepted Booking source.';
COMMENT ON TABLE booking.extraction_draft_items IS
'Editable extracted room items. Pending items are excluded until confirmed; deleted items remain audit-visible.';
COMMIT;