@@ -56,8 +56,8 @@
| `GET /api/reservation/tasks` | 查询任务列表 / 工作台 | 必须带 Bearer token, 需要 `RESERVATION_TASK_READ` ;未传 `order_id` 时按来源消息接收时间倒序,传 `order_id` 时按同订单队列顺序正序;用 `can_process` 和 `readonly_reason_code` 控制入口按钮;列表不返回 AI 原始 payload、邮件正文或附件 URL; 已返回来源邮件会话摘要字段, 并支持 `order_status` 按任务所属订单状态筛选;旧 S000/S999 和 V3 S10/S99 以 `task_type=SOURCE_MESSAGE_ONLY` 只读任务返回,列表已透出 `result_type` 、`ai_task_type` 、`route_code` 、`system_process_category` 。V4 S10/S99 不再进入该旧任务表,应从 V4 工作台来源通知接口展示。 |
| `GET /api/reservation/workbench-items` | 查询 V4 工作台统一列表 | 必须带 Bearer token, 需要 `RESERVATION_TASK_READ` ;返回 V4 业务订单任务和 S10/S99 来源通知混排摘要;支持 `hotel_id` 、`item_type` 、`keyword` 、`page_num` 、`page_size` ;默认按 `source_received_at` 倒序,同一来源时间下按 `updated_at` 、`created_at` 、数字 `target_id` 倒序;列表不返回邮件正文、附件 URL、`ai_payload_json` 或来源通知原始 payload。 |
| `GET /api/reservation/order-tasks` | 查询 V4 业务订单任务列表 | 必须带 Bearer token, 需要 `RESERVATION_TASK_READ` ;只返回 V4 业务订单任务,不包含 S10/S99 来源通知;支持 `hotel_id` 、`order_id` 、`order_task_status` 、`card_status` 、`keyword` 、`page_num` 、`page_size` ; `order_task_status` 非 `OPEN` / `COMPLETED` 返回 400, `card_status` 非 V4 卡状态返回 400; `card_status` 只筛业务 / 可处理卡,固定来源邮件展示卡不参与筛选。 |
| `GET /api/reservation/order-tasks/{orderTaskId}` | 查询 V4 订单任务详情 | 必须带 Bearer token, 需要 `RESERVATION_TASK_READ` ,后端按订单任务实际酒店校验访问权;返回 `order_task` 、`source_message_summary` 、`source_message_card` 、`basic_information_card` 、`business_cards[]` 、`card_counts` 、`adapter_contract_errors[]` 和 `availability` ;来源摘要按酒店过滤,邮件正文和附件仍走 SourceMessage 会话接口。V4 任务详情页展示顺序固定为 Basic Information、业务卡、SourceMessage Display; 来源邮件卡位于页面最下方, 正文限定为当前触发该 order task 的 SourceMessage 正文,前端用 `source_message_summary.source_message_id` 调用 `GET /api/source-messages/{sourceMessageId}/conversation` 后定位当前邮件。Payment 卡下一阶段可返回 `payment_attachments[]` 安全摘要用于展示凭证附件,但本接口不得返回附件 URL; 图片缩略图 / 大图和非图片下载 URL 仍通过 SourceMessage 会话权限链路取得。CP8 起每张 V4 任务卡返回 `fields[]` , 前端应以该字段白名单渲染可编辑控件。Room Information 卡已新增 `display_payload.room_information` 稳定展示模型,前端优先读取 `current_values` / `proposed_values` / `final_values` / `change_summary[]` ,不要再从 Agent raw payload、`business_fields` 或 `target_order` 自行推导业务展示。 |
| `GET /api/reservation/order-tasks/{orderTaskId}/audits` | 查询 V4 订单任务审计流水 | 必须带 Bearer token, 需要 `RESERVATION_AUDIT_READ` ,后端按订单任务实际酒店校验访问权;返回 `order_task_id` 和 `items[]` 。`items[]` 用于展示 V4 卡片确认、复核解阻和 订单归属确认轨迹, 只包含脱敏后的审计摘要, 不包含邮件正文、HTML、附件 URL、AI 原始 payload、token 或 secret。 |
| `GET /api/reservation/order-tasks/{orderTaskId}` | 查询 V4 订单任务详情 | 必须带 Bearer token, 需要 `RESERVATION_TASK_READ` ,后端按订单任务实际酒店校验访问权;返回 `order_task` 、`source_message_summary` 、`source_message_card` 、`basic_information_card` 、`business_cards[]` 、`card_counts` 、`adapter_contract_errors[]` 和 `availability` ;来源摘要按酒店过滤,邮件正文和附件仍走 SourceMessage 会话接口。V4 任务详情页展示顺序固定为 Basic Information、业务卡、SourceMessage Display; 来源邮件卡位于页面最下方, 正文限定为当前触发该 order task 的 SourceMessage 正文,前端用 `source_message_summary.source_message_id` 调用 `GET /api/source-messages/{sourceMessageId}/conversation` 后定位当前邮件。Payment 卡下一阶段可返回 `payment_attachments[]` 安全摘要用于展示凭证附件,但本接口不得返回附件 URL; 图片缩略图 / 大图和非图片下载 URL 仍通过 SourceMessage 会话权限链路取得。CP8 起每张 V4 任务卡返回 `fields[]` ,前端应以该字段白名单渲染可编辑控件; `write_target` 只返回 `confirmed_payload` 、`review_resolution.field_overrides` 、`none` 等前端安全语义,不暴露内部列名 。Room Information 卡已新增 `display_payload.room_information` 稳定展示模型,前端优先读取 `current_values` / `proposed_values` / `final_values` / `change_summary[]` ,不要再从 Agent raw payload、`business_fields` 或 `target_order` 自行推导业务展示; Basic Information 的 `display_payload` / `confirmed_payload` 不返回 Agent `target_order` 。 |
| `GET /api/reservation/order-tasks/{orderTaskId}/audits` | 查询 V4 订单任务审计流水 | 必须带 Bearer token, 需要 `RESERVATION_AUDIT_READ` ,后端按订单任务实际酒店校验访问权;返回 `order_task_id` 和 `items[]` 。`items[]` 用于展示 V4 卡片确认、复核解阻、 订单归属确认轨迹和 `V4_ROOMING_LIST_AUTO_DEF` 自动 DEF 摘要 , 只包含脱敏后的审计摘要, 不包含邮件正文、HTML、附件 URL、AI 原始 payload、token 或 secret。 |
| `GET /api/reservation/source-notifications/{notificationId}` | 查询 V4 S10/S99 来源通知详情 | 必须带 Bearer token, 需要 `RESERVATION_TASK_READ` ,后端按来源通知实际酒店校验访问权;只返回通知摘要、来源邮件通知卡、会话摘要和 `availability` ;不返回订单任务、业务卡、邮件正文、附件 URL 或原始 AI payload。 |
| `GET /api/reservation/source-notifications/{notificationId}/audits` | 查询 V4 S10/S99 来源通知审计流水 | 必须带 Bearer token, 需要 `RESERVATION_AUDIT_READ` ,后端按来源通知实际酒店校验访问权;返回 `notification_id` 和 `items[]` 。`items[]` 第一版用于展示来源通知 ack 记录,只包含脱敏后的审计摘要。 |
| `GET /api/reservation/lookups/accounts` | 查询 V4 Account 目录 | 必须带 Bearer token, 需要 `RESERVATION_TASK_READ` ,支持 `hotel_id` 、`keyword` 、`page_num` 、`page_size` ;返回统一 wrapper: `hotel_id` 、`catalog_type=ACCOUNT` 、`catalog_source` 、`catalog_version` 、`stale` 、`items[]` 、`page` 、`warnings[]` 。`keyword` 匹配目录 code 时后端按稳定 code 大写归一化处理,前端可传小写;匹配显示名仍按数据库比较规则。`keyword` 无匹配时 `items=[]` / `page.total=0` ,但只要酒店未过滤目录存在,`catalog_source/catalog_version` 仍保持真实目录元数据,不代表目录未初始化。前端在 `options_source=reservation_v4_account_catalog` 时调用,只提交 `items[].code` , Market / Source 以后端确认派生结果为准。 |
@@ -72,7 +72,7 @@
前端已在系统设置下新增 `/system/reservation-catalogs` 消费上述目录管理接口。页面入口要求 `RESERVATION_CATALOG_MANAGE` ,列表过滤直接传 `hotel_id` 、`keyword` 、`status` 、`page_num` 、`page_size` ; Account 新增第一版固定提交 `market_code=LEISURE` 、`source_code=TRAVEL_AGENT` ;状态重复提交按成功提示处理,不额外弹失败。
| `POST /api/reservation/order-tasks/{orderTaskId}/cards/{cardId}/confirm` | 确认 V4 订单任务卡 | 必须带 Bearer token, 需要 `RESERVATION_TASK_CONFIRM` ,请求 JSON 带 `version` ,可选 `confirmed_payload` ; Basic Information 必须先确认,业务卡第一版不强制逐张顺序确认;前端只提交当前卡 `fields[]` 中可编辑字段, 后端以展示快照为基准合并, 未开放字段会被忽略; Room Information 卡优先提交 `confirmed_payload.room_information.final_values` ,后端写入稳定确认快照并重新派生 Nights / Breakfast / Group Booking Status 文案,不写 Agent `target_order` 、Adult、邮件正文、附件 URL 或前端注入字段;确认 Rooming List 卡时前端只提交 `version` 即可,若同订单为 Group 且存在可更新 Room Information 确认快照,后端会自动把 Group Booking Status 置为 `DEF` 并写审计;没有可更新投影时确认仍成功且不创建不完整 Room Information; 确认前会按当前酒店数据库目录校验 Account / Room Type / Rate Code, 下一阶段 `rate_code` 还必须属于已确认 Account + 当前业务 event `booking_type` 的适用范围; Room Information 新结构错误路径形如 `room_information.final_values.room_items.0.room_type_code` ,历史兼容结构可能返回如 `business_fields.after.room_items.0.room_type_code` ,失败返回 `V4_FIELD_VALIDATION_FAILED` ;确认后卡片 `CONFIRMED` 、写 `confirmed_payload_json/confirmed_at/confirmed_by` 并锁定,重复确认返回错误;成功返回刷新后的订单任务详情。 |
| `POST /api/reservation/order-tasks/{orderTaskId}/cards/{cardId}/confirm` | 确认 V4 订单任务卡 | 必须带 Bearer token, 需要 `RESERVATION_TASK_CONFIRM` ,请求 JSON 带 `version` ,可选 `confirmed_payload` ; Basic Information 必须先确认,业务卡第一版不强制逐张顺序确认;前端只提交当前卡 `fields[]` 中可编辑字段, 后端以展示快照为基准合并, 未开放字段会被忽略; Room Information 卡优先提交 `confirmed_payload.room_information.final_values` ,后端写入稳定确认快照并重新派生 Nights / Breakfast / Group Booking Status 文案,不写 Agent `target_order` 、Adult、邮件正文、附件 URL 或前端注入字段;确认 Rooming List 卡时前端只提交 `version` 即可,若同订单为 Group 且存在可更新 Room Information 确认快照,后端会自动把 Group Booking Status 置为 `DEF` 并写审计,刷新详情时 `display_payload` / `confirmed_payload` 均显示 DEF ;没有可更新投影时确认仍成功且不创建不完整 Room Information; 确认前会按当前酒店数据库目录校验 Account / Room Type / Rate Code, 下一阶段 `rate_code` 还必须属于已确认 Account + 当前业务 event `booking_type` 的适用范围; Room Information 新结构错误路径形如 `room_information.final_values.room_items.0.room_type_code` ,历史兼容结构可能返回如 `business_fields.after.room_items.0.room_type_code` ,失败返回 `V4_FIELD_VALIDATION_FAILED` ;确认后卡片 `CONFIRMED` 、内部写入确认快照 / 确认人 / 确认时间 并锁定,重复确认返回错误;成功返回刷新后的订单任务详情。 |
| `POST /api/reservation/order-tasks/{orderTaskId}/cards/{cardId}/review-resolution` | V4 复核解阻并确认卡片 | 必须带 Bearer token, 需要 `RESERVATION_MANUAL_REVIEW_RESOLVE` ,仅用于 `card_status=REVIEW_REQUIRED` ;请求 JSON 带 `version` ,可选 `field_overrides[]` 和 `reason` ;订单任务归属未解决时 `confirmed_order_id` 必填,且必须是当前酒店下真实可见订单;`field_overrides[]` 只允许当前卡 `fields[]` 白名单内可编辑业务字段,问题字段可按 `fields[].validation_errors` 红字提示; Room Information 复核优先使用 `/room_information/final_values/...` pointer, 不允许指向 `nights` 、`target_order` 、Adult、Block ID、Confirmation Number 等只读 / 派生字段;成功后卡片 `CONFIRMED` 、`review_status=RESOLVED` ,写 `review_resolution_json/confirmed_payload_json/confirmed_at/confirmed_by` 并返回刷新后的订单任务详情。 |
| `POST /api/reservation/source-notifications/{notificationId}/ack` | 确认 V4 S10/S99 来源通知已读 / 已处理 | 必须带 Bearer token, 需要 `RESERVATION_TASK_CONFIRM` ,请求 JSON 带 `version` ;仅允许 `route_code=S10/S99` ;确认后 `notification_status=ACKED` ,写 `ack_by/ack_at` ,成功返回刷新后的来源通知详情;重复 ack 返回当前已确认状态且不新增审计;该动作不创建订单、不参与订单阻塞。 |
| `GET /api/reservation/order-tasks/{orderTaskId}/audits` / `GET /api/reservation/source-notifications/{notificationId}/audits` | 查询 V4 业务审计展示数据 | 必须带 Bearer token, 需要 `RESERVATION_AUDIT_READ` ;前端可在 V4 订单任务详情和 S10/S99 来源通知详情的“审计时间线”中调用。响应沿用旧审计行结构:`audit_id` 、`actor_type` 、`actor_id` 、`action` 、`reason` 、`before_snapshot` 、`after_snapshot` 、`occurred_at` 。快照已由后端脱敏,前端仍不要把未知 URL-like 字符串当附件或正文直渲。 |
@@ -309,7 +309,7 @@ Content-Type: application/json
- `extracted_fields.room_items.0.room_type_raw` 是房型原文证据,第一版返回 `control_type=readonly` 、`edit_scope=never` 、`raw_readonly=true` ;用户应确认或修改 `pms_room_type_code` ,不要覆盖 raw 原文。
- `extracted_fields.room_items.0.room_quantity` 返回 `control_type=number` ; `extracted_fields.room_items.0.pms_room_type_code` 返回 `control_type=select` 、`options_source=active_pms_room_type_catalog` 。
- type-known manual review 的 `manual_review.missing_fields[]` 应按 JSON Pointer 匹配 `fields[].field_pointer` ,并复用对应字段控件提交 `field_overrides[]` ;匹配不到的 pointer 不要临时生成任意输入框。
- 缺失字段会返回 `edit_scope=manual_review_only` 和 `write_target=review_resolution.field_overrides` ;同卡复核中其他可编辑业务字段可能返回 `normal_and_manual_review` ,前端第一版仍优先只渲染 `missing_fields[]` 指向的字段 。
- 缺失字段会返回 `edit_scope=manual_review_only` 和 `write_target=review_resolution.field_overrides` ;同卡复核中其他可编辑业务字段也 可能按当前卡白名单返回 `editable=true` ,前端不要只渲染 `missing_fields[]` 指向的字段,应该以 `fields[]` 中真实 `editable` 状态为准 。
- `field_overrides[]` 新页面优先提交 `field_pointer` ,可同时提交 `fields[]` 中的主 `field_path` ;不要提交旧扁平 key 作为新逻辑首选。
- `options_source=active_pms_room_type_catalog` 、`rate_code_catalog` 、`system_case_lookup` 第一版仅代表选项来源,真实目录 / lookup 未接入前,前端不得硬编码 PMS 房型、Rate Code 或系统对象全集。
- 后端可能返回 `control_hint=catalog_backend_pending` 、`lookup_backend_pending` 、`structured_table_editor_pending` , 用于提示前端目录、lookup 或表格编辑后端能力仍未接入。
@@ -499,7 +499,7 @@ RESERVATION_ROOMING_LIST_GENERATE
- `/reservation/order-tasks/{orderTaskId}` 应使用 `GET /api/reservation/order-tasks/{orderTaskId}` 展示 `basic_information_card` 、`business_cards[]` 、`source_message_card` 、`card_counts` 、`order_task` 摘要和 `adapter_contract_errors[]` 只读诊断;页面顺序固定为 Basic Information、业务卡、SourceMessage Display。
- `/reservation/source-notifications/{notificationId}` 应使用 `GET /api/reservation/source-notifications/{notificationId}` 展示 S10/S99 来源通知详情,并通过 `POST /api/reservation/source-notifications/{notificationId}/ack` 确认已读 / 已处理。
- V4 审计时间线应分别调用 `GET /api/reservation/order-tasks/{orderTaskId}/audits` 和 `GET /api/reservation/source-notifications/{notificationId}/audits` ;按钮权限使用 `/api/auth/me.permissions[]` 中的 `RESERVATION_AUDIT_READ` 。
- V4 卡片确认应使用 `POST /api/reservation/order-tasks/{orderTaskId}/cards/{cardId}/confirm` ,请求带 `version` ;前端只从当前卡 `fields[]` 中挑选 `editable=true` 、`raw_readonly!=true` 、`write_target` 指向确认 payload 的字段构造 `confirmed_payload` 。
- V4 卡片确认应使用 `POST /api/reservation/order-tasks/{orderTaskId}/cards/{cardId}/confirm` ,请求带 `version` ;前端只从当前卡 `fields[]` 中挑选 `editable=true` 、`raw_readonly!=true` 、`write_target=confirmed_ payload` 的字段构造 `confirmed_payload` 。
- V4 复核解阻应使用 `POST /api/reservation/order-tasks/{orderTaskId}/cards/{cardId}/review-resolution` ,请求带 `version` ; `field_overrides[]` 只使用当前卡 `fields[].field_pointer` ,订单任务归属未解决时允许用户填写 `confirmed_order_id` 。
- 所有按钮应按后端 `availability.confirmable` 、`availability.reviewable` 、`availability.ackable` 和前端权限共同控制;不可操作原因优先展示 `readonly_reason_message` ,否则按 `readonly_reason_code` 做友好映射。
- `fields[].validation_errors` 应展示在对应字段旁边;接口返回 `V4_FIELD_VALIDATION_FAILED` 且 `details[]` 带嵌套路径时,前端应尝试定位到对应 field, 定位不到则在当前卡片动作错误区展示。
@@ -526,9 +526,9 @@ RESERVATION_ROOMING_LIST_GENERATE
- M002 V4 入站解析与数据模型基线已完成第一版:后端可接收 `source_message + order_contexts[] + message_events[]` ,识别 `NEW_BOOKING` 、`UPDATE_BOOKING` 、`CANCEL_BOOKING` 、`TRACE_RESERVATION_NOTES` 、`ROOMING_LIST` 、`PAYMENT` ,并保存 V4 原始 payload、`route_code` 、系统处理分类和 `field_contract_version=20260718-v4` 。前端暂不需要直接调用 V4 回调接口。
- M002 V4 CP5 已完成查询接口:普通 V4 业务包可通过 `/api/reservation/workbench-items` 、`/api/reservation/order-tasks` 、`/api/reservation/order-tasks/{orderTaskId}` 查看; V4 S10/S99 来源通知可通过 `/api/reservation/source-notifications/{notificationId}` 查看。M002 V4 CP6 已开放普通卡片确认和 S10/S99 ack 写接口; M002 V4 CP7 已开放 `POST /api/reservation/order-tasks/{orderTaskId}/cards/{cardId}/review-resolution` 复核解阻接口; M002 V4 CP8 已开放 V4 卡片 `fields[]` 白名单和目录校验; M002 V4 CP11 已把固定种子迁移到数据库目录,并开放 Account / Room Type / Rate Code lookup API; 目录管理后台 CP1 已开放 Account / Room Type / Rate Code 后端列表、新增、启用 / 停用接口; V4 业务审计查询已补齐订单任务审计和来源通知 ack 审计两个只读接口。
- V4 任务卡的 `display_payload_json` 只保留后端白名单展示字段;`ai_payload_json` 才包含完整 SuperAgent 原始 event。后续 V4 查询接口不得把 `ai_payload_json` 、附件 URL 或 raw evidence 直接给普通页面渲染;前端对来源消息卡附件字段仍做 URL-like 文本兜底脱敏。
- Room Information 卡已由后端返回业务展示模型,前端已按该模型完成第一版业务化展示,不再自行从 Agent raw payload、`business_fields` 或 `target_order` 计算。读取路径是业务卡 `display_payload.room_information` : `NEW_BOOKING` 展示最终值, Group 的最终订单投影字段 `group_block_name` 可编辑,默认来自 `target_order.locator_value` 且 `locator_type=GROUP_CODE` ; Fit 的最终订单投影字段 `fit_name` 可编辑,默认来自 `guest_name ?? target_order.locator_value` ; Agent 原始 `target_order.locator_value` 始终只读 ,用户编辑只影响本系统最终订单投影和确认快照。`UPDATE_BOOKING` 顶部展示本地当前值到 Agent 修改后值的 `change_summary[]` ,日期变化时连带展示 Nights 差异,字段区展示合并后的最终值;`CANCEL_BOOKING` 从本地订单投影只读展示 current / final 模型, 不显示编辑控件。Nights 由后端按酒店本地日期派生, 前端只展示不计算; Adult 不显示。
- Room Information 卡已由后端返回业务展示模型,前端已按该模型完成第一版业务化展示,不再自行从 Agent raw payload、`business_fields` 或 `target_order` 计算。读取路径是业务卡 `display_payload.room_information` : `NEW_BOOKING` 展示最终值, Group 的最终订单投影字段 `group_block_name` 可编辑,默认来自 Agent `target_order.locator_value` 且 `locator_type=GROUP_CODE` ; Fit 的最终订单投影字段 `fit_name` 可编辑,默认来自 `guest_name ?? target_order.locator_value` ; Agent 原始 `target_order` 不在普通 `display_payload` / `confirmed_payload` 中暴露 ,用户编辑只影响本系统最终订单投影和确认快照。`UPDATE_BOOKING` 顶部展示本地当前值到 Agent 修改后值的 `change_summary[]` ,日期变化时连带展示 Nights 差异,字段区展示合并后的最终值;`CANCEL_BOOKING` 从本地订单投影只读展示 current / final 模型, 不显示编辑控件。Nights 由后端按酒店本地日期派生, 前端只展示不计算; Adult 不显示。
- Room Information 卡 Breakfast 前端显示为“含早”勾选框: Group 固定勾选且只读; Fit 由后端按最终 Rate Code 中 `RB` / `RO` 派生, 无法派生时作为必填勾选项。Group Booking Status 仅 Group 显示,稳定 code 为 `TEN` / `DEF` / `INQ` ,展示文案为 `TEN-Tentative` 、`DEF-Definite` 、`INQ-Inquiry` ; New Group 默认 `TEN` , `NEW_BOOKING` / `UPDATE_BOOKING` 确认前可改选,`CANCEL_BOOKING` 只读。
- Rooming List 卡确认存在跨卡联动:同订单为 Group 时,确认 `ROOMING_LIST` 后后端已把 Group Booking Status 自动置为 `DEF` ,即使此前为 `TEN` 或 `INQ` ; Fit 不显示也不变更该状态。该自动变更由后端写 `V4_ROOMING_LIST_AUTO_DEF` 审计,前端只展示刷新后的状态 ;如果没有可更新 Room Information 投影,确认仍成功,后端只写安全审计提示。
- Rooming List 卡确认存在跨卡联动:同订单为 Group 时,确认 `ROOMING_LIST` 后后端已把 Group Booking Status 自动置为 `DEF` ,即使此前为 `TEN` 或 `INQ` ; Fit 不显示也不变更该状态。该自动变更由后端写 `V4_ROOMING_LIST_AUTO_DEF` 审计,并在后续任务详情刷新时让 Room Information 的 `display_payload.room_information.final_values` 和 `confirmed_payload.room_information.final_values` 保持 DEF 口径一致;当前订单详情 `order_overview` 不返回 Group Booking Status 字段,仍只展示既有确认快照字段 ;如果没有可更新 Room Information 投影,确认仍成功,后端只写安全审计提示。
- Rooming List 卡第一版是轻量事项确认卡:前端展示卡片标题、状态、目标订单信息和“确认卡片”按钮即可;不要做名单 rows、附件预览、Excel 生成或 PMS 导入入口。确认仅表示该 Rooming List 事项已人工处理。
- Payment 卡下一阶段建议由后端在 `display_payload_json.payment_attachments[]` 返回安全摘要,字段只包含附件 ID、文件名、类型、大小、是否图片、是否可预览 / 下载等,不包含外链。第一版 `attachment_ids[]` 是 Agent 返回的只读业务事实,前端只展示并确认卡片,不允许用户增删、替换或重新选择附件集合,也不把 `attachment_ids[]` 、`externalUrl` 或完整附件对象提交回确认接口。
- V4 复核态卡片仍是原业务卡,不新建单独复核任务卡;页面状态显示“需要复核”,问题字段用 `fields[].validation_errors` 红字提示,主按钮文案统一为“确认卡片”。前端内部必须根据 `card_status=REVIEW_REQUIRED` 调用 `review-resolution` ,不要调用普通 `confirm` 。
@@ -539,10 +539,10 @@ RESERVATION_ROOMING_LIST_GENERATE
- M002 V4 CP3 已新增 V4 订单任务、任务卡、S10/S99 来源通知三张表和 Repository 基线; M002 V4 CP4 已把正式 V4 回调写入这些表; M002 V4 CP5 已开放查询; M002 V4 CP6 已开放普通卡片确认和 S10/S99 ack; M002 V4 CP7 已开放复核解阻与复核场景订单归属确认; M002 V4 CP8 已开放目录校验和 V4 任务卡 `fields[]` 字段白名单; M002 V4 CP11 已新增目录表、数据库种子和 lookup API; 目录管理后台 CP1 已新增 `RESERVATION_CATALOG_MANAGE` 后端接口; V4 审计查询已开放 `RESERVATION_AUDIT_READ` 下的订单任务审计和来源通知审计。
- V4 订单任务和卡片 `availability` 已新增 `reviewable` 。当前语义:`REVIEW_REQUIRED` 卡如果未被 Basic Information 或前置订单任务阻塞,会返回 `read_only=false` 、`editable=true` 、`confirmable=false` 、`reviewable=true` 、`readonly_reason_code=PROCESSABLE` ;前端应调用 `review-resolution` ,不要调用普通 `confirm` 。
- CP11 起 V4 入站阶段按当前酒店数据库目录做校验: Account 缺失或不存在时 Basic Information 卡直接 `REVIEW_REQUIRED` ;业务卡已有 `room_items[].room_type_code` 或 `rate_code` 但不在当前酒店目录时,业务卡也会直接 `REVIEW_REQUIRED` ,错误会回显在 `fields[].validation_errors` 。
- CP8 / Room Information 展示模型后,确认接口按 `fields[]` 白名单收口:前端可以只提交用户修改过的可编辑字段,不建议整包回传 `display_payload` 。后端会从当前卡展示快照生成确认快照,并只合并可写叶子字段;来源邮件、路由、`target_order` 、`order_ref` 、`manual_review` 、校验诊断字段以及前端额外注入字段不会写入 `confirmed_payload_json` 。
- CP8 / Room Information 展示模型后,确认接口按 `fields[]` 白名单收口:前端可以只提交用户修改过的可编辑字段,不建议整包回传 `display_payload` 。后端会从当前卡展示快照生成确认快照,并只合并可写叶子字段;来源邮件、路由、`target_order` 、`order_ref` 、`manual_review` 、校验诊断字段以及前端额外注入字段不会写入内部确认快照 。
- 业务卡目录校验会递归检查稳定模型或历史兼容结构。例如 Room Information 新结构的房型位于 `/room_information/final_values/room_items/0/room_type_code` ,错误详情会使用 `room_information.final_values.room_items.0.room_type_code` ;历史兼容 `UPDATE_BOOKING` 的房型可能仍使用 `business_fields.after.room_items.0.room_type_code` 。前端展示错误时优先用 `fields[].validation_errors` ,接口 400 时可直接展示 `details[]` 。
- `review-resolution` 请求示例:`{"version":0,"reason":"确认房型映射","confirmed_order_id":"123456","field_overrides":[{"field_pointer":"/room_information/final_values/room_items/0/room_type_code","value":"RM2"}]}` 。`confirmed_order_id` 在订单任务归属未解决时必填;如果订单任务已经绑定订单且 `target_resolution_status=RESOLVED` ,只能不传或传当前同一个订单 ID, 不能借该接口切换到其它订单。`field_pointer` 必须来自当前卡 `fields[]` 中可编辑的 `basic_information.*` 、`room_information.final_values.*` 或历史兼容 `business_fields.*` 叶子字段;复核态允许编辑当前卡业务白名单内字段,不再限定只能改空值、`missing_fields[]` 或目录错误字段。前端不要提交来源邮件、路由、`target_order` 、`order_ref` 、缺失字段清单、`manual_review` 、raw evidence、校验诊断字段, 也不能替换整个对象 / 数组。
- V4 `fields[]` 第一版字段说明: Basic Information 固定返回 `/basic_information/account_code` 、`/basic_information/market_code` 、`/basic_information/source_code` ;其中 Account `control_type=select` 、`options_source=reservation_v4_account_catalog` , Market / Source 为只读派生字段。Room Information 字段统一返回 `/room_information/final_values/...` ,例如 `/room_information/final_values/arrival_date` 、`/room_information/final_values/room_items/0/room_type_code` ;前端不要自行补未返回字段。
- V4 `fields[]` 第一版字段说明: Basic Information 固定返回 `/basic_information/account_code` 、`/basic_information/market_code` 、`/basic_information/source_code` ;其中 Account `control_type=select` 、`options_source=reservation_v4_account_catalog` , Market / Source 为只读派生字段。Room Information 字段统一返回 `/room_information/final_values/...` ,例如 `/room_information/final_values/arrival_date` 、`/room_information/final_values/room_items/0/room_type_code` ; `REVIEW_REQUIRED` 状态下只要字段仍在当前卡业务白名单内且未被前置阻塞,就会返回 `editable=true` 并允许 `review-resolution` 提交同一个 pointer; 前端不要自行补未返回字段。
- V4 CP11 已开放独立目录 lookup API。前端应使用 `GET /api/reservation/lookups/accounts` 、`GET /api/reservation/lookups/room-types` 、`GET /api/reservation/lookups/rate-codes` 渲染 Account / Room Type / Rate Code 选项;用户提交确认或复核时只提交稳定 `code` ,不要提交显示名、派生 Market / Source 或目录完整对象; 后端确认前仍会重新校验目录。Rate Code 下一阶段依赖 Account + `booking_type` :前端需在 Account 已选 / 已确认且能取得当前业务 event `booking_type` 后再请求 Rate Code, Account 改变后清空或重新校验已选 Rate Code; 缺失条件时禁用或空态, 不硬编码 OWNER RATE Excel。`keyword` 查不到只表示当前筛选无结果,不能仅凭 `items=[]` 判断目录未初始化,应结合 `catalog_source` 、`catalog_version` 和 `warnings[]` 。
- M002 V4 CP12 前端已接入上述三个 lookup API: V4 多卡详情页会按当前卡 `fields[].options_source` 拉取目录选项,空 `items[]` 、`stale=true` 和 `warnings[]` 作为非阻塞提示展示; Account 选择后只展示目录返回的 `market_code` / `source_code` 辅助确认,确认 / 复核请求仍只提交用户选择的 code。
- V4 新模型确认口径是不保存后端草稿、卡片最终确认后锁定、技术异常不进入用户可处理卡、当前不生成 OPERA 模拟操作。Basic Information 必须先确认;其它业务卡第一版不强制逐张顺序确认。现有 V3 `draft` 、`confirm` 、`manual-review-resolutions` 和 OPERA 模拟接口仍只代表旧链路能力,不能直接等同 V4 多卡最终接口。