# Evidence Topic: Booking Excel extraction program

## Metadata

- Date: 2026-07-31
- Status: Implemented, migrated and runtime-active; first real source activation pending
- Scope: Raw Tour Code/`โรงแรม` XLSX parsing, editable/batch-deletable review drafts, HTTP transport and current-source activation
- Confidence: Fact
- Source: supplied workbook, deterministic parser output, source/migration inspection, unit/integration tests, browser QA, live database transaction probe and authenticated runtime probe
- Last verified: 2026-07-31 12:43 +08:00
- Stale trigger: parser/review API change, migration change or first real draft activation

## Question

Does ARR2.0 now contain the requested program that extracts Tour Code plus one or more room-type/quantity rows, keeps
uncertain items for human correction/deletion and activates only a fully reviewed workbook?

## Evidence

- The parser reads only worksheets containing Tour Code plus exact `โรงแรม`, strips Tour Code whitespace,
  uses physically-last-row replacement/cancellation semantics and does not infer cancellation from yellow fill.
- Parenthesized `【label】 quantity` items are split in source order. Missing outside quantity defaults to one. Numeric
  variants normalize to `U-TWN`/`U-DBL`; `高级房TWN`/`高级房DBL` normalize to `TWN`/`DBL`. Unknown or unbracketed room
  names preserve raw text and parsed/default quantity as pending.
- A direct parse of the supplied `ai样板.xlsx` found one source sheet, 26 distinct Tour Codes, 37 room items and 7
  pending items. Confirmed quantity is 198; all extracted quantities including pending are 208.
- Supplied examples replay exactly: `LLT260715AC` becomes separate `TWN / 12` and `DBL / 9` items;
  `LT260715LD` becomes confirmed `U-TWN / 17` plus pending raw `U-เตียงเสริม13 / 2`.
- Migration 015 stores confirmed/pending/deleted item state outside canonical Booking facts. Repository activation rejects
  pending or empty drafts, groups confirmed items back into source rows, creates immutable accepted facts and switches
  `booking.current_source_batch` in the same transaction.
- The desktop review table exposes Tour Code, raw label, editable room type/quantity, status, save and delete. Pending
  items are visually separated and excluded until saved; discard and whole-draft activation are explicit operations.
- Review pages are fixed at 50 records. Individual and all-visible checkboxes feed a strict 1-50-unique-ID batch route;
  the PostgreSQL repository soft-deletes the entire set under one advisory-locked transaction and rolls back if any
  selected item is missing, already deleted, foreign to the draft or no longer reviewing. The old item route remains.
- Single and batch delete use one native in-page modal with count-aware copy, focus containment/restoration, backdrop,
  button and explicit Escape cancellation. Isolated browser QA selected one, two and all 50 visible rows, proved no
  browser-native prompt appeared and did not invoke the confirm action or any deletion endpoint.
- The upload helper, review kicker/description/guidance and source counts/time were removed as requested. The later
  filename-context follow-up removed the separate accepted/historical-source status and summary completely. The review
  heading is `Booking记录提取`, with `summary.filename` directly below it as the provenance for the displayed records.
- `arr_web.server` now forwards POST/PATCH/DELETE through the same bounded request-body gate. Real loopback socket tests
  cover PATCH and DELETE forwarding, security headers, missing length and oversized requests.
- Migrations 014/015 were applied after a transaction-only migration probe. Current batch 1 retained 867 room items,
  348 Group Codes and quantity 867; the review tables remained empty after application.
- A real-PostgreSQL transaction-only vertical slice created a two-item draft with one pending item, edited that item to
  `EXTRA BED`, activated one immutable source row with quantity three, then rolled back the outer transaction. Batch 1
  remained current and zero synthetic drafts/artifacts remained.
- Port 8766 restarted at 12:43:37 +08 with the final review-filename source. Authenticated health reports database, processing,
  monthly, download, company-report and company-source-upload readiness true; the draft endpoint is empty and logout succeeds.
  Anonymous PATCH/DELETE reach the application and return JSON `401 AUTH_REQUIRED`, proving the old HTTP 501 gap is gone.
- JavaScript syntax, 40 focused Web/review/router tests and repository commit/rollback tests passed. Final post-change
  discovery ran 346 tests in 100.681 seconds: all passed, with 10 environment-dependent optional renderer/private-fixture skips.
- The filename-context follow-up passed JavaScript/HTML checks, 36 focused Web/company/review/router tests and a clean
  346-test discovery in 98.882 seconds with the same 10 expected skips. Isolated desktop and 390-pixel QA used a long
  filename, found no horizontal overflow or console errors and submitted no upload, deletion or activation.
- Authenticated isolated browser QA covered desktop and 390-pixel upload/review/generation layouts, pending-item
  editing, 1/2/50-row selection, single/batch dialog cancellation, zero horizontal overflow and zero console errors.
- An expanded Booking/company/real-XLSX suite passed 55/55. The live read-only July 31 snapshot supplied 417 Finance
  facts, 27 current Booking items and 27 matched Group Code versions; the processor returned valid reports for all five
  companies with row counts 138/139/1/33/3 and zero errors. Missing/unmatched Booking Room cells remained blank.
- Company generation reads `booking.v_current_room_items` and `booking.v_group_room_item_summary` on every repeatable-
  read snapshot, so a reviewed Booking activation is visible to the next report without re-importing Opera/Finance.
- The Web release gate intentionally keeps July `21-month-end` closed until 2026-08-01 00:00 Asia/Bangkok. Earlier July
  periods are open but currently contain zero rows, so they do not prove populated Booking Room enrichment.

## Finding

The requested extraction capability is implemented, migrated and active in the authenticated company-report page.
Uncertain labels preserve their quantity and remain explicit, editable, removable draft records; they cannot silently
enter accepted room counts. The HTTP and database transaction gaps found during the earlier audit are repaired. The
company-channel processor is already ready for this workflow; the remaining boundary is activation of an actual
operator workbook, not another enrichment-algorithm change.

## Open Items

- Perform one explicitly authorized real workbook upload -> review/edit/delete -> activation before replacing the current
  business Booking source. Activation is complete-source replacement, so use a checkpointed complete workbook and a
  restoration plan on the shared test database.
- Run a released populated company-report period after activation. For current July month-end, wait until the Bangkok
  release boundary or use an isolated coordinator/clock fixture.
- Decide separately whether latest-state single-operator review is sufficient or reviewer/reason/revision history is
  required.
