feat: sync latest ARR implementation
This commit is contained in:
123
database/015_booking_excel_review_drafts.sql
Normal file
123
database/015_booking_excel_review_drafts.sql
Normal file
@@ -0,0 +1,123 @@
|
||||
-- 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;
|
||||
Reference in New Issue
Block a user