# QBD / LianTai Email Table Rules

This reference defines shared QBD / LianTai Excel and table evidence rules for booking-desk Skills.

Read this reference when the current message, attachment, sender, subject, or extracted evidence indicates a QBD or LianTai Excel/table workflow.

## Trigger Signals

Read this reference when any of these signals appears in `body_current`, attachment names, attachment content, sender, subject, or extracted evidence:

- Sender or channel indicates QBD, Q.B.D, LianTai, Lian Tai, Liantai, LT, DY, FIT, or related agency workflow.
- Sender includes known QBD / LianTai accounts such as `op.qbdtravel@gmail.com` or `opfit.liantaitravel@gmail.com`.
- Subject or body includes `QBD BOOKING UPDATE`, `UPDATE BOOKING`, `BOOKING UPDATE`, `AMEND BOOKING`, `AMD`, `AMEND GROUP CODE`, `AMEND ALLOTMENT`, `CANCEL`, `CXL`, `NAME LIST`, `Rooming List`, `Voucher`, or similar task signals.
- Attachments include Excel/table files, screenshots of tables, or table-like booking grids from QBD / LianTai.
- Attachment headers, sheet names, columns, or evidence include `Q.B.D TRAVEL GROUP CO.,LTD.`, `LIAN TAI TRAVEL GROUP`, `โรงแรม`, `โรงแรมให้ สถานะ`, `CFM`, `AMD`, `CXL`, highlighted rows, yellow fill, red text, or strikethrough text.

If any trigger signal is present but the table/highlight/row evidence is unavailable, unreadable, or ambiguous, do not guess. Output structured manual_review and include the missing table evidence in manual_review.evidence_to_check.

## Evidence Priority

- Treat `body_current` as the only source for creating a current `normal_task`.
- Use `body_thread`, historical attachments, previous status rows, and routing context only as evidence context.
- If `body_current` contains the current executable action, `body_thread` may bind the target key when the latest relevant thread segment clearly supplies one `group_code`, one parent group, or a known upstream task. Record the target source; do not treat historical actions themselves as current actions.
- QBD / LianTai email bodies often contain only a short instruction; detailed booking parameters may live in Excel, PDF, image, or screenshot attachments.
- Current table evidence may decide the current task even when the email subject contains historical signals such as NEW, FINAL, AMEND, Voucher, or Cancel.

## Highlighted / Yellow Rows

- Highlighted rows, yellow fill, or highlighted cells indicate the rows or fields the hotel currently needs to process.
- QBD workflows must prioritize rows with background color, fill color, or yellow highlight as the current pending rows.
- Non-highlighted rows are historical context or completion evidence unless `body_current` explicitly says to process all rows.
- Do not use AMD/CXL/CFM status dates by themselves to expand the set of current rows.
- If the runtime cannot read color/highlight information from the attachment, output `manual_review` unless the current row set is still unambiguous from other current evidence.

## Current Row To Event Splitting

- For QBD / LianTai Excel or table workflows, each current effective highlighted / yellow row is one independent current event.
- Use this rule for New Booking, Update / Amendment, Cancel / CXL, Allotment / Control Block, and similar row-based task signals.
- Assign each current effective row its own `source_event_index`.
- Output one independent `ai_task_result` for each current effective row.
- Treat each row as one downstream task card candidate: `table row = source_event_index = ai_task_result = task card`.
- Do not merge different table rows into one task, even when multiple rows share the same `group_code`, `confirmation_number`, stay dates, hotel, batch, supplier, subject, or attachment.
- Do not replace multiple row-level outputs with `source_event_count`, array-valued `case_keys.group_code`, summary `highlighted_rows`, or a single summary `room_items` list.
- For row-based outputs, each `ai_task_result.case_keys.group_code` should represent that row's key only; each result must carry row-level `extracted_fields.table_evidence`.
- If one row contains multiple room type / room quantity / price details, keep those details inside that row's own `extracted_fields`, such as `room_items`.
- If one row is incomplete or ambiguous, output structured `manual_review` for that row only; do not block other rows that can be processed safely.
- Preserve row-level evidence for every generated result, including attachment name, sheet name, row number or row label, highlight status, and action/status cell value.

Controlled exception:

- If the same current effective row contains an S01 / S02 / S06 primary business action and Trace / Guest Request / extra bed evidence, generate both the primary task and an S07 linked task.
- Execute the primary task first and S07 second.
- Do not merge the primary task and S07 into one `ai_task_result`.
- If `source_event_index` must be an integer, assign S07 a new integer index and preserve the same-row relationship through `parent_source_event_index`, `linked_task_group_id`, and `execution_order`.

## LianTai Table Rules

- LianTai update tables often use the hotel column (`โรงแรม` / 酒店) as the main field for actual stay dates, room type, room quantity, price, breakfast, and restaurant notes.
- Prefer the date range at the start of the hotel column for actual arrival and departure dates, such as `09-11` meaning arrival day 9 and departure day 11.
- Resolve month and year from the sheet name, file name, or batch context, such as `BOOKING 06-2026` or `WYNDHAM 06.26`.
- Rows with highlight and no completed hotel status are usually pending current work.
- After hotel processing, highlight is normally removed and the hotel status column records `CFM`, `AMD`, or `CXL` plus a date. This status is completion evidence, not a standalone new task.
- The hotel column may contain a composite unit price expression that provides both Rate Code evidence and Fix Charge evidence, such as `2000THB+500`, `1800THB+500`, or `2000THB*2` followed by `+附加500*2`.
- In a composite unit price expression, the component before `+` is the room-price component for Rate Code logic; the component after `+` is the additional-charge component for `fix_charge_items`.
- Do not add the two components together for Rate Code logic. For example, do not treat `2000THB+500` as `2500`.
- Do not trigger Fix Charge only because a row contains `TWN`, `DBL`, `2000THB`, or `1800THB`. Trigger it only when a separable additional-charge component is present.
- Fix Charge amount is not fixed to 500. Use the extracted component after `+` as the unit amount.
- If a composite expression contains `*quantity`, preserve the quantity evidence in raw fields when useful, but do not require AI to calculate total Fix Charge amount.
- Composite unit price evidence belongs only to the current table row; do not carry a Fix Charge component across rows.
- If table row evidence, highlight/current-row evidence, or the price area is unreadable or ambiguous, output structured `manual_review` instead of guessing.

## QBD Table Rules

- QBD booking update tables must first filter current rows by background color, fill color, or yellow highlight.
- Within current rows, use the action/remark column to identify candidate task semantics such as AMEND BOOKING, AMEND GROUP CODE, AMD ALLOTMENT, CANCEL BOOKING, or CXL.
- Red text can be a cancel or abnormal-action clue, but it must still be interpreted with current row/highlight and action evidence.
- Non-highlighted rows with AMD/CXL dates are historical or already-processed evidence unless `body_current` explicitly reopens them.

## Before / After Rules

- Strikethrough text is usually the before value.
- Text after the strikethrough, text below it, or the next related row is usually the after value.
- Apply this before/after rule to room type, room quantity, group code, block name, dates, rate, and other amendable fields.
- If before/after cannot be reliably reconstructed, keep known fields in `extracted_fields`, set uncertain fields to `null` or candidate arrays, and output structured `manual_review`.

## FIT / Group / Allotment Decision

- Do not classify Group/FIT from the attachment header or table title alone.
- Use the total room quantity for the same booking or row:
  - Less than 5 rooms usually means FIT Reservation.
  - 5 rooms or more usually means Group Block.
- For Update / Amendment, use the target after room quantity.
- Use Allotment / Control Block only when the current row, action, object code, or context clearly indicates allotment, allocation, control block, 控房, or 配额.
- In the LianTai / agency workflow, a current plain-text `AMEND + FINAL BOOKING` can still be an Allotment / Control Block creation event when it lists one parent group code followed by multiple new child `group_code` lines with stay dates and room allocations. In the hotel system this is handled like New Booking / Allotment creation, not a simple S02 before-after amendment.
- For this parent-to-child allocation pattern, treat each child `group_code` line as a row-equivalent current event. Output one S01 New Booking / Allotment task per child code when the child code, stay dates, and room allocations are readable. Preserve the parent code as `parent_group_code` / `allocation_parent_group_code`.
- Do not output `manual_review` merely because the parent group is being split, before values are not restated per child, or the subject/body contains `AMEND`. Output `manual_review` only for the affected child line if that line's child code, dates, room allocation, object type, room mapping, or rate/price rule cannot be safely extracted.
- If the current parent-to-child allocation text also contains group-level service requests such as registration table, welcome drink, welcome screen, key cards, meal notes, or other guest requests, generate S07 linked task(s) bound to the parent group or allocation parent unless the request explicitly targets only one child group.

## Skill-Specific Effects

- New Booking: table rows can provide new FIT, Group Block, or Allotment / Control Block creation parameters. Routing context still decides whether an apparently new request is duplicate or blocked.
- New Booking: parent-to-child `AMEND + FINAL BOOKING` allocation text can provide row-equivalent child Allotment / Control Block creation parameters; route to S01 when the child group lines are readable.
- New Booking: if a current row includes a LianTai composite unit price expression, keep the primary task as New Booking and pass the additional-charge component in `extracted_fields.fix_charge_items`.
- Amend Group Code: current rows with clear `AMEND GROUP CODE` / `AMEND GROUP CODE TO` evidence route to S06. Fixed column positions are evidence locations only; do not treat a specific column as the business rule itself.
- Trace / Reservation Notes: extra bed / 加床 / `เตียงเสริม` / `U-เตียงเสริม` / `เสริมเตียง` is Trace / Guest Request. It is not room quantity, room type, FIT/Group evidence, Rate Code evidence, or Fix Charge evidence.
- Trace / Reservation Notes: if a current row includes Trace / Guest Request / extra bed together with S01 / S02 / S06, generate an S07 linked task after the primary task. Do not rely on a fixed column to identify this evidence.
- Update Booking / Amendment: table rows can define `update_subtypes`, before/after fields, changed room type/quantity, dates, guest count, trace/request, rate/settlement price, or Fix Charge maintenance. If the same indivisible row also contains clear Amend Group Code evidence, keep S06 as the primary task and pass other row details as backend same-event information, except Trace / Guest Request / extra bed, which should also create S07 linked task.
- Update Booking / Amendment: if a current row includes a LianTai composite unit price expression or explicit Fix Charge maintenance, use `update_fix_charge` when the target order and action are clear.
- Cancel Booking: current rows with Cancel/CXL evidence can identify cancellation requests. Use table context and routing context to decide `cancel_object_type` as `fit_reservation`, `group_block`, or `allotment_control_block`.
- Cancel Booking: do not default-create S07 just because the canceled row contains historical extra bed / Guest Request. Only generate S07 when current explicitly asks to write a post-cancel note / trace.

## Output Requirements

- Record use of this reference in `context_used`.
- Preserve raw table evidence in `extracted_fields` when available: attachment name, sheet name, row number or row label, highlight status, action/status column value, raw date range, raw room type, raw room quantity, raw rate, and before/after evidence.
- Preserve composite unit price evidence when available: raw price expression, base room-price component, additional-charge component, and whether Fix Charge was detected.
- When outputting `manual_review`, include missing or ambiguous table evidence in `manual_review.evidence_to_check`, such as attachment name, sheet name, row number, highlight/color state, strikethrough state, or unreadable cells.
