-- Add one explicit active Booking source batch for full-workbook replacement imports. -- PostgreSQL 15+. Migrations 008-013 remain immutable. BEGIN; DO $$ BEGIN IF current_database() <> 'booking_test' THEN RAISE EXCEPTION 'ARR Booking current-source migration is allowed only in booking_test'; END IF; IF to_regclass('booking.source_batches') IS NULL OR to_regclass('booking.current_row_parses') IS NULL OR NOT EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_schema = 'ingestion' AND table_name = 'processing_runs' AND column_name = 'uploaded_filename' ) THEN RAISE EXCEPTION 'ARR migrations 008 through 013 must be applied first'; END IF; IF to_regclass('booking.current_source_batch') IS NOT NULL THEN RAISE EXCEPTION 'ARR Booking current-source migration is already applied'; END IF; END; $$; CREATE TABLE booking.current_source_batch ( singleton boolean PRIMARY KEY DEFAULT true CHECK (singleton), source_batch_id bigint NOT NULL UNIQUE REFERENCES booking.source_batches(id), activated_at timestamptz NOT NULL DEFAULT now() ); COMMENT ON TABLE booking.current_source_batch IS 'Singleton pointer to the one accepted full Booking source batch used by Finance matching and company reports.'; CREATE OR REPLACE FUNCTION booking.validate_current_source_batch() RETURNS trigger LANGUAGE plpgsql AS $$ BEGIN IF NOT EXISTS ( SELECT 1 FROM booking.source_batches AS batch WHERE batch.id = NEW.source_batch_id AND batch.batch_status = 'accepted' ) THEN RAISE EXCEPTION 'current Booking source must reference an accepted source batch'; END IF; RETURN NEW; END; $$; CREATE TRIGGER current_source_batch_acceptance_guard BEFORE INSERT OR UPDATE ON booking.current_source_batch FOR EACH ROW EXECUTE FUNCTION booking.validate_current_source_batch(); INSERT INTO booking.current_source_batch ( singleton, source_batch_id, activated_at ) SELECT true, accepted.id, COALESCE(accepted.finished_at, accepted.validated_at, accepted.created_at) FROM booking.source_batches AS accepted WHERE accepted.batch_status = 'accepted' ORDER BY accepted.finished_at DESC NULLS LAST, accepted.id DESC LIMIT 1; CREATE OR REPLACE VIEW booking.v_current_room_items AS SELECT source.id AS source_row_id, source.source_batch_id, source.source_worksheet, source.source_row_no, source.group_code_raw, source.group_code_key, source.type_of_room_raw, source.no_of_rooms AS source_no_of_rooms, parsed.id AS parse_version_id, parsed.version_no AS parse_version_no, item.item_no, item.room_type_raw, item.room_type_code, item.quantity, item.unit_price, item.currency_code, item.price_token_raw, item.source_fragment FROM booking.current_source_batch AS active_source JOIN booking.source_rows AS source ON source.source_batch_id = active_source.source_batch_id JOIN booking.current_row_parses AS current_parse ON current_parse.source_row_id = source.id JOIN booking.parse_versions AS parsed ON parsed.id = current_parse.parse_version_id JOIN booking.source_batches AS batch ON batch.id = source.source_batch_id JOIN booking.room_items AS item ON item.parse_version_id = parsed.id WHERE active_source.singleton AND batch.batch_status = 'accepted' AND parsed.parse_status = 'accepted'; COMMENT ON VIEW booking.v_current_room_items IS 'Accepted room items from the one active full Booking source batch; historical batches remain immutable but inactive.'; COMMIT;