962 lines
74 KiB
Markdown
962 lines
74 KiB
Markdown
# M002 V4 CP2 订单任务与多卡领域模型设计
|
||
|
||
## 文档信息
|
||
|
||
| 项目 | 内容 |
|
||
| --- | --- |
|
||
| 文档版本 | 0.9 |
|
||
| 日期 | 2026-07-21 |
|
||
| 状态 | CP2 设计已确认;CP3-CP8、CP11、CP13、CP14、V4 业务审计查询、停止 V4 普通业务双写旧任务、Room Information 后端展示模型和 Payment 附件安全摘要后端第一版已实现 |
|
||
| 适用范围 | M002 V4 入站后的订单任务、多卡、状态、查询和写操作设计 |
|
||
| 不适用范围 | 真实 PMS / OPERA / OHIP、前端页面视觉稿、生产历史数据迁移 |
|
||
|
||
## 1. 文档定位
|
||
|
||
M002 V4 CP1 已完成 SuperAgent V4 回调包入站解析、基础校验、路由适配和 AI transition 最小落库。早期 CP1 曾把可映射的 V4 event 临时接入 M002 V3 的订单 / 任务 / 任务卡链路;开发阶段最新决策已停止 V4 普通业务入站双写旧 `workflow_reservation_task`。
|
||
|
||
本文是 CP2 设计文档,用于把 2026-07-18 V4 字段契约落成后续可开发的数据模型和接口草案。
|
||
|
||
截至 CP14、V4 业务审计查询、停止旧任务双写、Room Information 后端展示模型、Rooming List 确认自动 DEF 后端联动和 Payment 附件安全摘要后端第一版,后端已实现本文第 10、11、12 节中的持久化和查询基线,并已把 SuperAgent V4 入站结果写入新表:普通业务包只创建 V4 订单任务、来源邮件展示卡、Basic Information 卡和业务卡,不再创建旧 `workflow_reservation_task`;V4 S10/S99 创建来源通知。当前已开放 V4 工作台、订单任务列表 / 详情、来源通知详情查询接口、订单详情 V4 订单任务时间线、V4 卡片确认接口、S10/S99 来源通知 ack 接口、V4 `REVIEW_REQUIRED` 卡复核解阻接口、V4 订单任务 / 来源通知审计查询接口、当前酒店数据库目录校验、卡片 `fields[]` 白名单、Account / Room Type / Rate Code lookup API、目录管理后台 CP1、订单列表 V4 继续处理入口字段、Room Information New / Update / Cancel 第一版业务展示模型、Rooming List 确认触发 Group Booking Status 自动置 `DEF`,以及 Payment 卡 `payment_attachments[]` 安全摘要。2026-07-21 OWNER RATE `RATECODE (2)` 只读整理已确认:Room Type 第一阶段只维护 `RM2`、`RM3`、`RM4`、`SU1`、`SU2`、`SU3` 六个稳定 code,不建 Account -> Room Type 关系;Rate Code 第一阶段暂不建立 Account 适用关系,Q.B.D / LIAN TAI 的 40 个规范化 Rate Code 作为酒店级目录候选。真实 PMS 同步继续后置,设计见 `M002-v4-real-catalog-lookup-api-design.md`。
|
||
|
||
2026-07-22 后,MCP `th_hotel_submit_task_results` 也已与本文模型对齐:MCP submit 只接受 M002 V4 包级结构,旧 V2/V3 submit payload 返回 `MCP_SUBMIT_V4_REQUIRED`,不会绕回旧 `workflow_reservation_task` 模型。
|
||
|
||
后续如本文与 `M002-v4-agent-callback-field-contract.md` 的字段契约冲突,以字段契约为准;如与安全边界冲突,以 `security-access-control-boundary.md` 为准。
|
||
|
||
## 2. CP1 已完成和 CP2 差距
|
||
|
||
| 主题 | CP1 当前实现 | V4 目标模型差距 |
|
||
| --- | --- | --- |
|
||
| 入站识别 | 已识别 `route_code`、`source_message`、`order_contexts[]`、`message_events[]` | CP4 已把有合法 event 的 `order_ref` 建成订单任务聚合;CP5 已开放 V4 安全查询接口 |
|
||
| SourceMessage | 已按 `source_message.source_message_id` 反查 SourceMessage Inbox | CP4 已固定生成普通业务包内邮件展示卡;邮件正文完整读取仍走 SourceMessage 会话接口 |
|
||
| Basic Information | 已写入 V4 Basic Information 独立卡 | CP6 已支持确认并锁定;CP7 已支持复核解阻;CP8 已支持目录校验和 `fields[]` 白名单;CP11 已改为按当前酒店数据库 Account 目录校验并派生 Market / Source |
|
||
| 业务 Event | V4 新业务主线已只创建 V4 order task / cards,不再双写旧 `workflow_reservation_task` | 旧 V2/V3 入站代码仍可作为历史参考保留,但开发阶段不维护旧任务兼容,测试数据可重建 |
|
||
| 技术错误 | 已落 `adapter_contract_error` transition | 已符合目标方向:不创建用户可处理卡 |
|
||
| 草稿 / READY / OPERA | 仍复用 V3 草稿、READY 和 OPERA 模拟骨架 | V4 新数据确认口径是不保存草稿、确认后锁定、当前不生成 OPERA |
|
||
| 前端查询 | 复用旧任务列表和任务详情 | CP5 已开放 V4 工作台、订单任务列表 / 详情、来源通知详情和订单详情 V4 时间线 |
|
||
|
||
## 3. 领域词汇
|
||
|
||
| 术语 | 英文建议 | 中文含义 |
|
||
| --- | --- | --- |
|
||
| AI 回调包 | AI Callback Package | SuperAgent 对本系统提交的一次 V4 JSON 包,对应一个 SourceMessage 和一个 AI batch |
|
||
| 来源邮件展示卡 | Source Message Display Card | 由包级 `source_message` 固定生成的只读展示卡,用于查看当前邮件正文、附件和会话入口 |
|
||
| 订单任务 | Reservation Order Task | 同一 `source_message_id + order_ref` 在本系统内形成的业务处理聚合,不等同 PMS 订单,也不等同旧 `workflow_reservation_task` 单任务 |
|
||
| 本地订单投影 | Reservation Order Projection | 本系统保存的订单归属和业务号投影,当前主要复用 `workflow_reservation_order` |
|
||
| 任务卡 | Reservation Task Card | 订单任务下可独立确认、独立锁定的卡片,例如 Basic Information、房间信息、Trace、Rooming List、Payment |
|
||
| 技术失败记录 | Adapter / Technical Error | Agent / Adapter / MCP 契约或技术异常,只进入 AI transition 或技术运行记录,不进入用户可处理任务卡 |
|
||
|
||
## 4. 核心关系
|
||
|
||
普通业务包:
|
||
|
||
```text
|
||
source_message
|
||
-> 1 个来源邮件展示卡
|
||
|
||
order_contexts[]
|
||
-> 每个 order_ref 创建 1 个订单任务
|
||
-> 每个订单任务创建 1 张 Basic Information 卡
|
||
|
||
message_events[]
|
||
-> 每个 event 按 order_ref 挂到对应订单任务
|
||
-> 每个 event 创建 1 张业务任务卡
|
||
|
||
target_order
|
||
-> 用于订单任务绑定本地订单投影
|
||
```
|
||
|
||
纯通知包 `route_code=S10`:
|
||
|
||
```text
|
||
source_message
|
||
-> 只显示来源邮件通知卡
|
||
-> 不创建订单任务
|
||
-> 不创建 Basic Information 或业务卡
|
||
```
|
||
|
||
技术异常:
|
||
|
||
```text
|
||
V4 package / event contract error
|
||
-> workflow_reservation_ai_transition
|
||
-> system_process_category=ADAPTER_CONTRACT_ERROR
|
||
-> 不创建订单任务
|
||
-> 不创建任务卡
|
||
```
|
||
|
||
## 5. 卡片类型第一版
|
||
|
||
| 卡片类型 | 来源 | 是否用户可确认 | 是否可编辑 | 中文说明 |
|
||
| --- | --- | --- | --- | --- |
|
||
| `SOURCE_MESSAGE_DISPLAY` | `source_message` | 否 | 否 | 普通业务包内固定展示当前邮件和附件入口 |
|
||
| `SOURCE_MESSAGE_NOTIFICATION` | `route_code=S10` | 是,仅确认已读 | 否 | 纯通知邮件,只需要用户确认已读 / 已处理 |
|
||
| `BASIC_INFORMATION` | `order_contexts[].basic_information` | 是 | 是 | 订单级 Account / Market / Source 卡,第一版 Agent 只给 `account_code` |
|
||
| `ROOM_INFORMATION` | `NEW_BOOKING` / `UPDATE_BOOKING` / `CANCEL_BOOKING` | 是 | 是 | 房型信息卡,卡内按 New / Update / Cancel 展示最终值、差异和系统派生字段 |
|
||
| `TRACE_RESERVATION_NOTES` | `TRACE_RESERVATION_NOTES` | 是 | 是 | Trace 卡,卡内可有普通备注和加床备注多条事项 |
|
||
| `ROOMING_LIST` | `ROOMING_LIST` | 是 | 否 | 第一版只做事项确认;不在 Agent 回调里保存名单 rows,不生成 Excel,不导入 PMS |
|
||
| `PAYMENT` | `PAYMENT` | 是 | 第一版主要确认附件关联 | 付款凭证卡;业务事实仍是 `attachment_ids[]` 引用包级附件,展示层可返回匹配后的附件安全摘要 |
|
||
|
||
说明:
|
||
|
||
- Basic Information 不是 event,但必须是独立任务卡。
|
||
- 来源邮件展示卡不是 event,普通业务包内只读,不参与订单执行阻塞。
|
||
- S10/S99 采用来源通知模型:任务列表 / 工作台可见,点击进入纯通知详情页;只显示邮件展示卡和确认按钮,不创建订单、不进订单列表、不参与订单阻塞,也不支持编辑、复核、OPERA 或人工终止。
|
||
- 同一 `order_ref` 下如果有多个相同 `event_type`,第一版按 event 数组项分别建卡;页面排序按固定卡片顺序,再按 `source_event_index` 排序。
|
||
|
||
## 6. 状态设计
|
||
|
||
### 6.1 订单任务状态
|
||
|
||
订单任务状态用于列表和页面入口,第一版按卡片状态派生,不允许用户直接编辑。为了便于列表查询,`order_task_status` 可以作为落库快照字段保存当前订单任务自身完成情况;同订单前置任务造成的阻塞不落入 `order_task_status`,而是在查询响应的 `availability` 中实时派生。
|
||
|
||
| 状态 | 中文含义 | 派生规则 |
|
||
| --- | --- | --- |
|
||
| `OPEN` | 仍有待处理卡 | 存在 `PENDING_CONFIRM` 或 `REVIEW_REQUIRED` 的可确认卡 |
|
||
| `COMPLETED` | 当前订单任务已完成 | 所有用户可确认卡均已 `CONFIRMED` |
|
||
|
||
查询响应可以额外返回 `display_status=BLOCKED`,表示当前订单任务因同订单前置订单任务未完成、Basic Information 未确认或权限不足而只能查看;该值由查询服务实时计算。
|
||
|
||
技术错误不派生订单任务状态,因为技术错误不创建订单任务。
|
||
|
||
### 6.2 卡片状态
|
||
|
||
| 状态 | 中文含义 | 允许动作 |
|
||
| --- | --- | --- |
|
||
| `READONLY` | 只读卡 | 只能查看,例如普通业务包的来源邮件展示卡 |
|
||
| `PENDING_CONFIRM` | 待确认 | 若没有前置阻塞,允许提交最终确认 |
|
||
| `REVIEW_REQUIRED` | 待人工复核 | 若没有前置阻塞,允许提交复核修正并确认 |
|
||
| `CONFIRMED` | 已确认锁定 | 只能查看,不允许再次编辑或覆盖 |
|
||
| `ACK_REQUIRED` | 通知待确认 | 仅用于 S10/S99 来源通知,落在 `workflow_reservation_v4_source_notification.notification_status` |
|
||
| `ACKED` | 通知已确认 | 仅用于 S10/S99 来源通知,落在 `workflow_reservation_v4_source_notification.notification_status` |
|
||
|
||
### 6.3 可操作性派生
|
||
|
||
接口响应应返回 `availability` 或等价字段,避免前端自己猜。
|
||
|
||
| 派生状态 | 中文含义 |
|
||
| --- | --- |
|
||
| `available=true` | 当前用户在权限、酒店、状态和阻塞规则下可以处理 |
|
||
| `blocked=true` | 当前卡只能查看 |
|
||
| `readonly_reason_code=PRIOR_CARD_NOT_CONFIRMED` | 同一订单任务内前置卡未确认 |
|
||
| `readonly_reason_code=PRIOR_ORDER_TASK_NOT_COMPLETED` | 同一本地订单下更早订单任务未完成 |
|
||
| `readonly_reason_code=CARD_LOCKED` | 当前卡已确认锁定 |
|
||
| `readonly_reason_code=SOURCE_MESSAGE_DISPLAY_READONLY` | 来源邮件展示卡只读 |
|
||
|
||
## 7. 确认、复核和锁定规则
|
||
|
||
### 7.1 不保存草稿
|
||
|
||
V4 新数据不再提供后端草稿保存。前端可以在页面本地维护未提交表单状态,但后端只接受最终确认或复核解阻提交。
|
||
|
||
原因:
|
||
|
||
- 2026-07-18 V4 契约已确认“不保存草稿”。
|
||
- V4 当前没有真实 OPERA / PMS 执行,后端不需要为半成品 payload 生成后续操作。
|
||
- 可以避免 V3 `draft_payload_json`、`READY` 和 OPERA 模拟骨架继续扩大。
|
||
|
||
### 7.2 最终确认
|
||
|
||
用户确认卡片时,后端保存:
|
||
|
||
- `confirmed_payload_json`:用户确认后的结构化字段。
|
||
- `confirmed_by`:当前登录用户 ID。
|
||
- `confirmed_at`:UTC 时间点。
|
||
- `card_status=CONFIRMED`。
|
||
|
||
确认后永久锁定。若后续发现错误,不覆盖原确认记录,应该通过审计记录和未来纠错流程表达。
|
||
|
||
### 7.3 人工复核
|
||
|
||
`manual_review=true` 或目录校验失败时,卡片进入 `REVIEW_REQUIRED`。
|
||
|
||
复核提交后:
|
||
|
||
- 不改写 AI 原始 payload。
|
||
- 用户修正写入 `review_resolution_json` 和 `confirmed_payload_json`。
|
||
- CP11 起确认和复核都会校验当前酒店数据库目录字段;Basic Information 的 `account_code` 必须来自当前酒店 ACTIVE Account 目录,通过后后端派生 `market_code` / `source_code`。
|
||
- 通过校验后卡片直接进入 `CONFIRMED`,不再进入 V3 `READY` 状态。
|
||
- `field_overrides[].field_pointer` 必须是当前卡 `fields[]` 白名单中允许编辑的 RFC 6901 JSON Pointer。`REVIEW_REQUIRED` 是整张原业务卡的复核状态,前端仍在原卡片内展示业务表单,问题字段用红字 / `validation_errors` 强调;用户可修改当前卡业务白名单内字段,不再限定只能改空值、`missing_fields[]` 或目录错误字段。
|
||
- Room Information 卡的 `fields[].editable` 和 `review-resolution` pointer 校验必须共用同一套字段策略;只要详情接口返回 `editable=true` 且 `write_target=review_resolution.field_overrides`,同一个 pointer 就不得再因为白名单不一致返回 `V4_REVIEW_POINTER_NOT_ALLOWED`。稳定 Room Information 模型允许复核补写当前卡白名单内缺失叶子字段,例如 `final_values.room_items[0].room_type_code` 原始值缺失但详情页返回可编辑时,命令侧必须接受同一 pointer。若仍被拒绝,应先通过 `GET /api/health` 检查测试机运行包;确认已部署后看后端日志 `review_pointer_policy=m002_v4_review_pointer_runtime_fix_v1`,其中会输出 order task、card、incoming pointer、query-side editable pointers、command-side allowed pointers、validation error pointers、`display_payload_has_room_information_final_values` 和 reject reason,但不得输出 payload、邮件正文、附件 URL 或敏感数据。
|
||
- 来源消息、路由、订单定位关系、诊断、缺失字段清单、`manual_review`、raw evidence 等只读字段不得提交。
|
||
- 如果订单任务归属未解决,复核请求必须提交 `confirmed_order_id`;后端按当前订单任务酒店校验该订单存在、非逻辑删除且不是系统隐藏订单。
|
||
- 如果订单任务已经有 `order_id` 且 `target_resolution_status=RESOLVED`,复核请求不能提交不同的 `confirmed_order_id`,否则返回 `V4_ORDER_REBIND_NOT_ALLOWED`;普通任务任意切换订单继续后置。
|
||
- `availability.reviewable=true` 且 `card_status=REVIEW_REQUIRED` 时,前端可以展示复核提交入口;普通确认接口仍拒绝 `REVIEW_REQUIRED` 卡。
|
||
|
||
### 7.4 Basic Information 目录规则
|
||
|
||
第一版 Basic Information 至少包含:
|
||
|
||
- Agent 原始 `account_code`。
|
||
- 信息系统目录校验状态。
|
||
- 后端派生的 `market_code` 和 `source_code` 快照,来源是 Account 目录。
|
||
|
||
如果 `account_code=null` 或目录不存在:
|
||
|
||
- 卡片进入 `REVIEW_REQUIRED`。
|
||
- 用户只能从信息系统已有 Account 目录中选择。
|
||
- 后端不得反向篡改 Agent 原始 `basic_information.manual_review`。
|
||
|
||
CP11 起 Account / Market / Source 目录使用本系统数据库目录,不依赖 SuperAgent 动态提供目录文件。当前初始目录来自固定种子导入,`source_system=FIXED_SEED_IMPORT`;V24 会覆盖 `HOTEL-TEST`、`HOTEL-DEV` 和迁移执行时已有的 `ACTIVE` 酒店。M002-V4-owner-rate-catalog-data-alignment 起,V25 和启动补种子已将 Room Type / Rate Code 固定种子收敛到 OWNER RATE 第一阶段目录。后续 Account / Market / Source 优先由系统管理维护,Room Type / Rate Code 未来优先来自 PMS / OPERA / OHIP 同步,本地目录表和 lookup API 设计见 `M002-v4-real-catalog-lookup-api-design.md`。
|
||
|
||
CP11 数据库初始化种子:
|
||
|
||
| 目录 | 第一版代码 |
|
||
| --- | --- |
|
||
| Account | `QBD_TRAVEL`、`LIAN_TAI`、`HANATOUR_TD` |
|
||
| Market | 由 Account 派生,当前固定为 `LEISURE` |
|
||
| Source | 由 Account 派生,当前固定为 `TRAVEL_AGENT` |
|
||
| Room Type | `RM2`、`RM3`、`RM4`、`SU1`、`SU2`、`SU3` |
|
||
| Rate Code | OWNER RATE `RATECODE (2)` 中 Q.B.D / LIAN TAI 的 40 个规范化酒店级候选,第一阶段暂不按 Account 过滤 |
|
||
|
||
说明:Room Type / Rate Code 当前只作为确认和字段控件的第一版校验 / 选项来源代码;已开放 `GET /api/reservation/lookups/accounts|room-types|rate-codes`。Rate Code 第一阶段仍按酒店级目录 lookup;房型 / 日期 / 价格过滤、Account 适用关系、真实 PMS 房型目录、Rate Code 配置中心和同步 run 后置。
|
||
|
||
## 8. 订单归属和 target_order
|
||
|
||
### 8.1 order_ref 和 target_order 分工
|
||
|
||
| 字段 | 用途 |
|
||
| --- | --- |
|
||
| `order_ref` | 当前回调包内归组,同一 `order_ref` 形成一个订单任务 |
|
||
| `target_order` | 本系统查找或创建本地订单投影,用于后续同订单阻塞和页面关联 |
|
||
|
||
不得用相同 `target_order=null` 合并订单任务;Agent 如果无法判断是否同单,应输出不同 `order_ref`。
|
||
|
||
### 8.2 本地订单绑定规则
|
||
|
||
| `booking_type` | `locator_type` | 第一版绑定规则 |
|
||
| --- | --- | --- |
|
||
| `GROUP` | `GROUP_CODE` | 按 `hotel_id + GROUP_CODE` 查找 ACTIVE 本地订单;不存在则创建或挂临时可见订单 |
|
||
| `FIT` | `BOOKING_CODE` | 按 `hotel_id + BOOKING_CODE` 查找本地订单投影;不存在则创建临时或 Booking Code 订单;若匹配多条则进入人工复核,不自动选单 |
|
||
| `FIT` | `CONFIRMATION_NUMBER` | 按 `hotel_id + CONFIRMATION_NUMBER` 查找 ACTIVE 本地订单;不存在则创建可见订单 |
|
||
| 任意 | 任意字段未解决 | 创建可见临时订单,订单任务和相关卡片进入复核或阻塞状态,等待用户确认订单归属 |
|
||
|
||
`FIT + BOOKING_CODE` 第一版不建立 ACTIVE 唯一约束。`BOOKING_CODE` 是拿到 `CONFIRMATION_NUMBER` 前的临时定位字段,后续不作为 PMS 永久主键;系统只在业务绑定时要求匹配结果至多一条。
|
||
|
||
### 8.3 复核场景订单归属确认
|
||
|
||
V4 CP2 只设计复核场景下的订单归属确认,不开放普通任务任意切换订单。
|
||
|
||
规则:
|
||
|
||
- 用户只能在 `REVIEW_REQUIRED` 卡片或订单任务归属未解决时确认订单归属。
|
||
- 订单归属确认必须写业务审计。
|
||
- 若确认到其他订单,原临时订单可在无其它任务引用时逻辑删除。
|
||
- 已确认锁定卡片不能通过该接口二次迁移订单。
|
||
- CP7 第一版只支持在复核解阻请求中提交 `confirmed_order_id` 完成未解决归属的一次性确认;如果订单任务已解析到某个订单且状态为 `RESOLVED`,只能确认同一订单,不能借复核接口切换到其它订单。
|
||
- 如果确认到的订单下存在更早未完成 V4 订单任务,后端拒绝当前复核提交,避免绕过同订单阻塞规则。
|
||
|
||
## 9. 同订单阻塞规则
|
||
|
||
V4 当前不做 OPERA / PMS 执行,但仍需要保留同订单处理顺序,避免用户先确认后续邮件导致业务事实倒置。
|
||
|
||
### 9.1 同一订单任务内
|
||
|
||
推荐固定顺序:
|
||
|
||
```text
|
||
10 BASIC_INFORMATION
|
||
30 ROOM_INFORMATION
|
||
40 TRACE_RESERVATION_NOTES
|
||
50 ROOMING_LIST
|
||
60 PAYMENT
|
||
90 SOURCE_MESSAGE_DISPLAY
|
||
```
|
||
|
||
规则:
|
||
|
||
- `BASIC_INFORMATION` 未确认时,其它业务卡只能查看,不能确认。
|
||
- 除 Basic Information 必须先确认外,第一版不强制业务卡之间逐张顺序确认;业务卡可独立确认,但页面仍按固定顺序展示。
|
||
- 同类型多张业务卡按 `source_event_index` 排序。
|
||
- `SOURCE_MESSAGE_DISPLAY` 只读、不阻塞,V4 任务详情页固定放在最下方,用于查看当前触发该订单任务的 SourceMessage 正文和附件摘要。
|
||
- Trace 卡普通事项内容字段统一使用 `trace_items[].text`,不使用 `trace_items[].content` 作为正式字段;`trace_items[].department_code` 第一版固定为 `FO`、`HSK`、`FO+HSK` 三个值,前端做固定下拉,不调用 Department lookup,也不允许自由文本。
|
||
- Trace `EXTRA_BED` 的 `target_room_type_code` 第一版只校验当前酒店 Room Type 目录存在,暂不要求必须属于当前订单已有房型;当前订单已有房型约束后置。
|
||
- Rooming List 卡第一版没有可编辑业务字段;页面展示为轻量事项确认卡,用户点击“确认卡片”仅表示已人工处理当前 Rooming List 事项,不代表名单已解析、Excel 已生成或 PMS 已导入。
|
||
- Room Information 卡下一阶段采用业务展示模型,不再只依赖通用 `fields[]` 扁平渲染;具体规则见“Room Information 卡展示模型”。
|
||
|
||
### 9.1.1 V4 任务详情页用户化展示边界
|
||
|
||
2026-07-21 已确认:`/reservation/order-tasks/{orderTaskId}` 默认面向普通酒店员工,不面向开发 / 测试。该页面的产品定位是“订单事项办理页”,不是“V4 任务卡模型调试页”。底层仍保持 Order Task / Task Card / SourceMessage 领域模型不变,但前端默认展示必须把模型语言翻译成业务语言。
|
||
|
||
展示口径:
|
||
|
||
- 页面主标题不直接使用“V4”“后端任务卡模型”“Task Card 模型”等技术描述,建议使用“处理预订事项”“订单事项处理”等业务文案。
|
||
- `Reservation Task Card` 在普通页面上显示为“事项”“待确认事项”或具体业务名称,不直接称为“卡片模型”。
|
||
- `SOURCE_MESSAGE_DISPLAY` 面向用户显示为“来源邮件”,固定在业务事项之后,默认折叠正文;正文仍只通过 SourceMessage conversation 权限链路读取。
|
||
- Basic Information 显示为“预订基础信息”,Room Information 显示为“房型与日期”或“房型信息”,Payment 显示为“付款凭证”,Trace 显示为“跟进事项”,Rooming List 显示为“房表事项”。
|
||
- 技术 ID、`order_task_id`、`card_id`、`source_event_index`、`order_ref`、`version`、`route_code`、JSON Pointer、`write_target`、payload 字段名、adapter 诊断和内部状态码默认不得出现在主摘要或业务事项区域;确需排查时只能放在折叠区或受控调试模式。
|
||
- 普通用户可见状态应使用业务文案映射,例如 `PENDING_CONFIRM` 显示为“待确认”,`REVIEW_REQUIRED` 显示为“需要复核”,`CONFIRMED` 显示为“已确认”,`RESOLVED` 显示为“复核已完成”,`OPEN` / `COMPLETED` 显示为“待处理” / “已完成”。
|
||
- 顶部摘要优先回答“这封邮件识别出了什么事项、当前还有什么要处理、下一步该点哪里”,而不是优先展示卡片数量和数据库 ID;已完成事项可以折叠为摘要,待处理或需复核事项应突出。
|
||
- 每张可处理事项卡的主动作按钮放在该事项卡右侧,和该卡状态同区域展示;`PENDING_CONFIRM` 和 `REVIEW_REQUIRED` 的用户可见主按钮均为“确认卡片”,但前端内部仍按卡片状态分别调用普通确认或复核解阻接口。已确认事项不显示主动作按钮,只显示“已确认”或“复核已完成”等状态。移动端可降级为卡片底部右对齐,但仍属于当前事项卡,不做页面底部统一确认按钮。
|
||
|
||
安全边界:
|
||
|
||
- 技术折叠区或调试模式也不得展示邮件正文、HTML、附件 URL、AI 原始 payload、raw evidence、PMS 原始响应、Secret、Token 或跨酒店数据。
|
||
- 如果后端接口为了路由、并发和提交必须返回 ID、`version`、`fields[]`、`write_target` 等稳定技术字段,前端可以用于内部逻辑,但默认用户页面不得把这些字段原样作为主文案。
|
||
- 本节只约束展示和信息层级,不改变 V4 入站、确认、复核、审计、权限、酒店隔离或 SourceMessage 读取链路。
|
||
|
||
### 9.1.2 V4 工作台 / 任务列表用户化展示边界
|
||
|
||
`/reservation/tasks` 默认面向普通酒店员工,产品定位是“待处理预订事项列表”或“预订事项工作台”,不是 V4 模型列表。该页面可以继续使用 `GET /api/reservation/workbench-items` 和 `GET /api/reservation/order-tasks` 的稳定 code 做查询、路由和筛选,但普通用户可见文案不得直接暴露内部 item type、card status 或 route 语汇。
|
||
|
||
默认展示口径:
|
||
|
||
- 列表标题建议使用“待处理预订事项”“预订事项”或“工作台”,不直接使用“V4 工作台”“Order Task 列表”“任务卡列表”等技术描述。
|
||
- 默认视图优先展示需要用户处理的事项,例如待确认、需要复核、待确认已读的来源通知;已完成事项保留筛选入口,但不应淹没默认工作队列。
|
||
- `ORDER_TASK` 面向用户显示为“预订事项”,`SOURCE_NOTIFICATION` 面向用户显示为“来源通知”或“需查看邮件”,不直接展示内部 `item_type` code。
|
||
- 任务类型面向用户显示为业务名称,例如新预订、修改预订、取消预订、付款凭证、跟进事项、房表事项;不要默认展示 `NEW_BOOKING`、`TRACE_RESERVATION_NOTES`、`ROOMING_LIST`、`PAYMENT` 等技术 code。
|
||
- 筛选项第一版面向普通用户建议为“全部”“待我处理 / 待处理”“需要复核”“已完成”“来源通知”。技术筛选如 `item_type`、`order_task_status`、`card_status`、`route_code`、`system_process_category` 可放入高级筛选或受控调试模式,不作为默认筛选文案。
|
||
- 列表行主动作保持业务化,例如“继续处理”“查看详情”“确认已读”;不把 V4 入口、旧任务 fallback 或 SourceMessage 模型差异暴露给普通用户。
|
||
- 空态文案使用业务语言,例如“暂无需要处理的预订事项”,不要显示“暂无 ORDER_TASK”或“暂无 V4 card_status 匹配结果”。
|
||
|
||
安全边界:
|
||
|
||
- 列表默认不展示邮件正文、附件 URL、AI 原始 payload、adapter 诊断、raw evidence、JSON Pointer、数据库 ID 或 route 诊断;必要的技术信息只能用于内部逻辑、高级筛选或受控调试模式。
|
||
- 高级筛选或调试模式不得突破酒店隔离、权限、SourceMessage 原文读取权限和敏感数据脱敏规则。
|
||
|
||
### 9.1.3 V4 订单详情页用户化展示边界
|
||
|
||
`/reservation/orders/{orderId}` 默认面向普通酒店员工,产品定位是“订单总览页”,不是 V4 时间线或任务卡调试页。该页面只展示订单当前确认快照、下一步处理入口、关联来源邮件和处理记录摘要,不在订单详情页直接确认、复核或编辑任务卡;具体办理动作仍进入 `/reservation/order-tasks/{orderTaskId}`。
|
||
|
||
展示口径:
|
||
|
||
- 页面标题优先显示订单业务名、Group Code、Confirmation Number 或用户可理解的订单名称,不把数据库 `order_id`、V4 字段名或内部 ID 作为第一视觉层级。
|
||
- `order_overview` 面向用户显示为“当前确认快照”或“订单信息总览”,不显示为 `order_overview` 或 V4 payload。
|
||
- `next_v4_action` 面向用户显示为“下一步处理”,例如“下一步:确认房型与日期”“下一步:复核付款凭证”;不直接展示 `action_type`、`action_status`、`card_id` 等内部 code。
|
||
- `related_source_messages[]` 面向用户显示为“关联来源邮件”,不直接展示 SourceMessage 模型名或内部 SourceMessage ID;需要正文时仍通过 SourceMessage conversation 权限链路读取。
|
||
- `v4_order_tasks[]` 面向用户显示为“处理记录”或“来源邮件处理记录”,不显示为“V4 时间线”。`cards[]` 面向用户显示为事项状态摘要,不显示为“卡片安全摘要”。
|
||
- 订单详情页可以显示业务状态摘要,例如预订基础信息、房型与日期、付款凭证、跟进事项、房表事项的状态;但不在该页展示可编辑表单、确认按钮或复核提交入口。
|
||
- 技术 ID、`order_task_id`、`card_id`、`source_message_id`、`version`、`route_code`、payload 字段名和内部状态码默认不得出现在订单详情主信息层级;确需排查时只能放入折叠区或受控调试模式。
|
||
|
||
安全边界:
|
||
|
||
- 订单详情 `order_overview` 只展示已确认 V4 卡片派生的订单事实,不把未确认 AI 建议或 display payload 当成订单事实。
|
||
- 订单详情不得直接返回或展示邮件正文、HTML、附件 URL、AI 原始 payload、raw evidence、PMS 原始响应、Secret、Token 或跨酒店数据。
|
||
- 本节只约束展示和信息层级,不改变订单详情接口作为订单总览页的定位,也不改变任务卡确认、复核、审计或 SourceMessage 读取链路。
|
||
|
||
### 9.2 同一本地订单下多个订单任务
|
||
|
||
如果多个 SourceMessage 或多个回调包绑定到同一本地订单:
|
||
|
||
- 按来源邮件接收时间、AI batch 接收时间、订单任务创建时间排序。
|
||
- 更早订单任务仍有未完成可确认卡时,后续订单任务只能查看。
|
||
- 技术错误 transition 不参与阻塞。
|
||
- S10/S99 来源通知不参与阻塞,也不被阻塞。
|
||
|
||
## 10. 数据表设计草案
|
||
|
||
### 10.1 继续复用的表
|
||
|
||
| 表 | 复用方式 |
|
||
| --- | --- |
|
||
| `platform_source_message_inbox` | 继续作为来源消息事实和外部 `source_message_id` 查询入口 |
|
||
| `workflow_reservation_ai_batch` | 继续保存一次 SuperAgent 回调包的幂等和批次信息 |
|
||
| `workflow_reservation_ai_transition` | 继续保存 event 级原始 payload、route、adapter error 和追踪信息 |
|
||
| `workflow_reservation_order` | 继续作为本地订单投影和订单列表数据源,但需要补 V4 所需 `BOOKING_CODE` 或 locator 相关能力 |
|
||
| `workflow_reservation_audit_log` | 继续保存卡片确认、复核、订单归属确认等业务审计 |
|
||
|
||
### 10.2 已新增表:`workflow_reservation_v4_order_task`
|
||
|
||
一条记录表示一个 `source_message_id + order_ref` 形成的 V4 订单任务。
|
||
|
||
| 字段 | 中文说明 |
|
||
| --- | --- |
|
||
| `id` | V4 订单任务 ID |
|
||
| `hotel_id` | 酒店 ID |
|
||
| `source_message_id` | SourceMessage Inbox 内部 ID |
|
||
| `ai_batch_id` | AI 回调批次 ID |
|
||
| `order_ref` | V4 包内订单引用 |
|
||
| `order_context_index` | `order_contexts[]` 中的一基序号,用于同一 SourceMessage 下稳定排序 |
|
||
| `order_id` | 绑定的本地订单投影 ID |
|
||
| `target_booking_type` | `GROUP` / `FIT` |
|
||
| `target_locator_type` | `GROUP_CODE` / `BOOKING_CODE` / `CONFIRMATION_NUMBER` |
|
||
| `target_locator_value` | 目标订单定位值,未解决时为空 |
|
||
| `target_resolution_status` | `RESOLVED` / `UNRESOLVED` / `CONFLICT` |
|
||
| `order_task_status` | 落库快照,仅保存 `OPEN` / `COMPLETED`;`BLOCKED` 由查询响应实时派生 |
|
||
| `source_received_at` | 来源邮件接收 UTC 时间,用于排序 |
|
||
| `version` | 乐观锁版本 |
|
||
| `created_at` / `updated_at` | UTC 创建和更新时间 |
|
||
| `logic_deleted_at` / `logic_deleted_reason` | 逻辑删除时间和原因,CP3 第一版只预留字段,Repository 默认排除逻辑删除记录 |
|
||
|
||
建议唯一约束:
|
||
|
||
```text
|
||
uk_reservation_v4_order_task_source_ref(hotel_id, source_message_id, order_ref)
|
||
uk_reservation_v4_order_task_source_index(hotel_id, source_message_id, order_context_index)
|
||
```
|
||
|
||
### 10.3 已新增表:`workflow_reservation_v4_task_card`
|
||
|
||
一条记录表示 V4 订单任务下的一张卡。
|
||
|
||
| 字段 | 中文说明 |
|
||
| --- | --- |
|
||
| `id` | V4 任务卡 ID |
|
||
| `hotel_id` | 酒店 ID |
|
||
| `v4_order_task_id` | 所属 V4 订单任务 ID;S10/S99 来源通知不挂订单任务,后续使用独立通知模型承载 |
|
||
| `source_message_id` | 来源消息 ID,便于查邮件会话 |
|
||
| `ai_transition_id` | 对应 event 的 AI transition ID;Basic Information 和来源邮件展示卡可为空 |
|
||
| `card_type` | 卡片类型 |
|
||
| `event_type` | 对应 V4 event_type;非 event 卡为空 |
|
||
| `source_event_index` | event 在 `message_events[]` 中的一基序号;非 event 卡固定为 `0`,避免 MySQL 唯一索引因 `NULL` 失效 |
|
||
| `card_sort_order` | 页面固定排序值 |
|
||
| `card_status` | `READONLY` / `PENDING_CONFIRM` / `REVIEW_REQUIRED` / `CONFIRMED` 等 |
|
||
| `review_status` | `PENDING` / `RESOLVED`,仅复核卡使用 |
|
||
| `ai_payload_json` | 当前卡使用的 AI 原始片段,不可被用户覆盖 |
|
||
| `display_payload_json` | 后端给前端展示的字段快照,可由 AI 和目录派生 |
|
||
| `confirmed_payload_json` | 用户最终确认后的字段 |
|
||
| `review_resolution_json` | 人工复核修正和订单归属确认结果 |
|
||
| `validation_errors_json` | 目录或业务校验错误摘要,不保存敏感正文 |
|
||
| `confirmed_by` / `confirmed_at` | 确认人和确认 UTC 时间 |
|
||
| `version` | 乐观锁版本 |
|
||
| `created_at` / `updated_at` | UTC 创建和更新时间 |
|
||
| `logic_deleted_at` / `logic_deleted_reason` | 逻辑删除时间和原因,CP3 第一版只预留字段,Repository 默认排除逻辑删除记录 |
|
||
|
||
建议唯一约束:
|
||
|
||
```text
|
||
uk_reservation_v4_task_card_slot(hotel_id, v4_order_task_id, card_sort_order, source_event_index)
|
||
```
|
||
|
||
约束说明:
|
||
|
||
- `SOURCE_MESSAGE_DISPLAY`、`BASIC_INFORMATION` 等非 event 卡使用 `source_event_index=0`。
|
||
- event 业务卡使用一基 `source_event_index`。
|
||
- 同一个订单任务下,固定卡片顺序 + `source_event_index` 必须唯一,防止入站重试或幂等异常重复创建同一张卡。
|
||
|
||
### 10.4 已新增表:`workflow_reservation_v4_source_notification`
|
||
|
||
一条记录表示一个 S10/S99 来源通知。它不挂订单任务、不创建订单、不进入订单列表,只用于任务列表 / 工作台和纯通知详情页。
|
||
|
||
| 字段 | 中文说明 |
|
||
| --- | --- |
|
||
| `id` | 来源通知 ID |
|
||
| `hotel_id` | 酒店 ID,第一版使用系统默认酒店或 SourceMessage 所属酒店 |
|
||
| `source_message_id` | SourceMessage Inbox 内部 ID |
|
||
| `ai_batch_id` | AI 回调批次 ID |
|
||
| `ai_transition_id` | S10/S99 对应 AI transition ID |
|
||
| `route_code` | `S10` 或 `S99` |
|
||
| `notification_status` | `ACK_REQUIRED` / `ACKED` |
|
||
| `raw_payload_json` | S10/S99 原始 AI 片段或包级摘要 |
|
||
| `ack_by` / `ack_at` | 确认人和确认 UTC 时间 |
|
||
| `source_received_at` | 来源邮件接收 UTC 时间,用于任务列表 / 工作台排序 |
|
||
| `version` | 乐观锁版本,用于确认按钮并发控制 |
|
||
| `created_at` / `updated_at` | UTC 创建和更新时间 |
|
||
| `logic_deleted_at` / `logic_deleted_reason` | 逻辑删除时间和原因,CP3 第一版只预留字段,Repository 默认排除逻辑删除记录 |
|
||
|
||
建议唯一约束:
|
||
|
||
```text
|
||
uk_reservation_v4_notification_message_batch(hotel_id, source_message_id, ai_batch_id)
|
||
```
|
||
|
||
### 10.5 暂不新增的表
|
||
|
||
| 表或能力 | 暂不新增原因 |
|
||
| --- | --- |
|
||
| V4 草稿表 | V4 已确认不保存草稿 |
|
||
| V4 OPERA operation 表 | 当前不做真实 OPERA / OHIP,也不生成 OPERA 模拟 |
|
||
| 技术错误用户任务表 | 技术错误不进入用户任务体系,先用 AI transition 和 dispatch run |
|
||
| 目录表 | CP11 已新增 `workflow_reservation_catalog_account`、`workflow_reservation_catalog_code`;CP13 已完成目录管理后台 CP1;真实同步 run 后置 |
|
||
|
||
## 11. Entity / Mapper / Repository 边界草案
|
||
|
||
后续 Java 实现必须遵守当前后端目录规范。
|
||
|
||
### 11.1 domain
|
||
|
||
已新增:
|
||
|
||
- `ReservationV4OrderTaskEntity`:映射 `workflow_reservation_v4_order_task`。
|
||
- `ReservationV4TaskCardEntity`:映射 `workflow_reservation_v4_task_card`。
|
||
- `ReservationV4SourceNotificationEntity`:映射 `workflow_reservation_v4_source_notification`。
|
||
|
||
Entity 字段必须有中文注释,说明字段业务含义、来源和状态代码范围。
|
||
|
||
### 11.2 mapper
|
||
|
||
已新增:
|
||
|
||
- `ReservationV4OrderTaskMapper`
|
||
- `ReservationV4TaskCardMapper`
|
||
- `ReservationV4SourceNotificationMapper`
|
||
|
||
Mapper 只放 MyBatis-Plus 基础访问和必要语义化查询。自定义方法需要中文注释。
|
||
|
||
### 11.3 repository
|
||
|
||
已新增:
|
||
|
||
- `ReservationV4WorkflowRepository`
|
||
- `MybatisReservationV4WorkflowRepository`
|
||
- `ReservationV4SourceNotificationRepository`
|
||
- `MybatisReservationV4SourceNotificationRepository`
|
||
|
||
CP3 Repository 已封装:
|
||
|
||
- 按 SourceMessage + order_ref 幂等创建订单任务。
|
||
- 按 `order_context_index` 保留同一 SourceMessage 下多个 `order_contexts[]` 的稳定顺序。
|
||
- 创建 Basic Information / SourceMessage / Event 卡的基础插入方法;非 event 卡 `source_event_index` 固定写入 `0`。
|
||
- 按 SourceMessage + AI batch 幂等创建 S10/S99 来源通知。
|
||
- 查询订单任务详情和卡片列表。
|
||
- 查询来源通知列表和详情。
|
||
- 卡片状态的 version 乐观锁更新基础方法。
|
||
- 来源通知状态的 version 乐观锁更新基础方法。
|
||
- event 卡必须传入正数一基 `source_event_index`;漏传会拒绝写入,避免被误当成非 event 卡。
|
||
|
||
CP6 已实现普通卡片确认和 S10/S99 来源通知 ack 的业务 Service 和 API;V4 复核解阻、复核场景订单归属确认仍属于后续 checkpoint。
|
||
|
||
Service 不直接访问 Mapper。
|
||
|
||
### 11.4 service
|
||
|
||
建议新增或拆分:
|
||
|
||
- `ReservationV4TaskIntakeService`:已实现,V4 入站从 AI transition 落 V4 订单任务、卡片和 S10/S99 来源通知。
|
||
- `ReservationV4OrderTaskQueryService`:前端查询订单任务列表和详情。
|
||
- `ReservationV4CommandService`:已实现卡片确认和 S10/S99 来源通知确认;后续继续承接 V4 复核和订单归属确认。
|
||
- `ReservationV4SourceNotificationService`:来源通知查询已并入 V4 查询服务,确认已并入 V4 命令服务。
|
||
|
||
当前 `ReservationAiTaskIntakeServiceImpl` 已在 V4 分支调用 `ReservationV4TaskIntakeService` 完成新模型写入;查询和确认已拆到独立 V4 service,后续复核仍应继续留在 V4 命令侧,避免主入站类继续膨胀。
|
||
|
||
## 12. 前端查询接口
|
||
|
||
以下查询接口已在 CP5 实现。所有接口都属于 `FRONTEND_USER`,必须带 Bearer token,权限码为 `RESERVATION_TASK_READ`,并按酒店访问权校验。查询接口只返回安全摘要、展示 payload、确认 payload、复核结果和状态,不返回邮件正文、附件 URL、`ai_payload_json` 或来源通知原始 payload。
|
||
|
||
V4 前端接口不继续扩展旧 `/api/reservation/tasks/**` 作为 V4 主模型入口。第一版中,工作台统一列表使用 `/api/reservation/workbench-items`,业务订单任务使用 `/api/reservation/order-tasks/**`,S10/S99 来源通知详情使用 `/api/reservation/source-notifications/**`。
|
||
|
||
### 12.1 工作台统一列表
|
||
|
||
```text
|
||
GET /api/reservation/workbench-items
|
||
分类:FRONTEND_USER
|
||
权限:RESERVATION_TASK_READ
|
||
```
|
||
|
||
用途:
|
||
|
||
- 作为 V4 任务列表 / 工作台的第一版统一入口。
|
||
- 同时返回业务订单任务和 S10/S99 来源通知。
|
||
- 前端按 `item_type` 区分跳转目标。
|
||
|
||
返回摘要应包含:
|
||
|
||
- `item_type`:`ORDER_TASK` / `SOURCE_NOTIFICATION`。
|
||
- `target_id`:订单任务 ID 或来源通知 ID。
|
||
- `source_message_summary`
|
||
- `display_order_key`:S10/S99 来源通知为空。
|
||
- `card_counts`:S10/S99 来源通知为空或只返回通知状态。
|
||
- `next_action_card_id`:S10/S99 来源通知为空。
|
||
- `notification_status`:仅 S10/S99 来源通知返回 `ACK_REQUIRED` / `ACKED`。
|
||
- `order_task_status`:仅业务订单任务返回 `OPEN` / `COMPLETED`。
|
||
- `display_status`:可返回 `OPEN` / `BLOCKED` / `COMPLETED` / `ACK_REQUIRED` / `ACKED`。
|
||
- `readonly_reason_code`
|
||
- `created_at` / `updated_at`:工作台条目创建和更新时间,主要用于同一来源时间下的稳定排序和前端调试。
|
||
|
||
排序规则:
|
||
|
||
- 默认按 `source_received_at` 倒序。
|
||
- 同一来源时间下按记录 `updated_at`、`created_at`、数字 ID 倒序。
|
||
|
||
### 12.2 业务订单任务列表
|
||
|
||
```text
|
||
GET /api/reservation/order-tasks
|
||
分类:FRONTEND_USER
|
||
权限:RESERVATION_TASK_READ
|
||
```
|
||
|
||
查询参数:
|
||
|
||
| 参数 | 中文说明 |
|
||
| --- | --- |
|
||
| `hotel_id` | 可选,按用户酒店访问权校验 |
|
||
| `order_id` | 可选,查询某个本地订单下的订单任务 |
|
||
| `card_status` | 可选,筛选含某类待处理卡的订单任务 |
|
||
| `keyword` | 可选,匹配邮件主题、发件人、Group Code、Booking Code、Confirmation Number |
|
||
| `page_num` / `page_size` | 分页 |
|
||
|
||
筛选说明:
|
||
|
||
- `order_task_status` 只接受 `OPEN` / `COMPLETED`,非法值返回 `V4_ORDER_TASK_STATUS_INVALID`。
|
||
- `card_status` 只接受 `READONLY` / `PENDING_CONFIRM` / `REVIEW_REQUIRED` / `CONFIRMED`,非法值返回 `V4_CARD_STATUS_INVALID`。
|
||
- `card_status` 按业务 / 可处理卡筛选,固定的 `SOURCE_MESSAGE_DISPLAY` 来源邮件只读卡不参与匹配,避免 `READONLY` 把所有普通业务任务都筛出来。
|
||
|
||
返回摘要应包含:
|
||
|
||
- `order_task_id`
|
||
- `order_ref`
|
||
- `order_id`
|
||
- `display_order_key`
|
||
- `source_message_summary`
|
||
- `card_counts`
|
||
- `next_action_card_id`
|
||
- `order_task_status`
|
||
- `display_status`
|
||
- `readonly_reason_code`
|
||
|
||
说明:
|
||
|
||
- 该接口只返回业务订单任务,不返回 S10/S99 来源通知。
|
||
- V4 任务列表 / 工作台页面第一版优先使用 `GET /api/reservation/workbench-items`。
|
||
|
||
### 12.3 订单任务详情
|
||
|
||
```text
|
||
GET /api/reservation/order-tasks/{orderTaskId}
|
||
分类:FRONTEND_USER
|
||
权限:RESERVATION_TASK_READ
|
||
```
|
||
|
||
返回结构:
|
||
|
||
```json
|
||
{
|
||
"order_task": {},
|
||
"bound_order": {},
|
||
"source_message_card": {},
|
||
"basic_information_card": {},
|
||
"business_cards": [],
|
||
"adapter_contract_errors": [],
|
||
"availability": {}
|
||
}
|
||
```
|
||
|
||
前端应以返回的 `cards[]` 和 `availability` 为准渲染,不自行拼完整字段矩阵。
|
||
|
||
`adapter_contract_errors[]` 返回同一 AI 批次中未生成业务卡的 V4 event 级契约错误诊断块,只包含白名单诊断字段,例如 `event_type`、`source_event_index`、`contract_errors`、`reason_code`、`missing_fields` 等;不返回完整 AI payload、邮件正文、附件 URL 或 raw evidence。
|
||
|
||
来源邮件摘要必须按当前查询酒店过滤。如果 V4 订单任务因脏引用指向了其它酒店的 SourceMessage,详情接口只能返回该 `source_message_id` 的空摘要占位,不得透出对方酒店的主题、外部消息 ID、发件人或会话信息。
|
||
|
||
V4 任务详情页的 `SOURCE_MESSAGE_DISPLAY` 固定展示在 Basic Information 和业务卡之后。该卡在页面上应展示“当前触发这条 V4 order task 的那封 SourceMessage 正文”,但正文不由本接口直接返回;前端应使用 `source_message_summary.source_message_id` 调用 `GET /api/source-messages/{sourceMessageId}/conversation`,并在同会话结果中定位当前 SourceMessage。HTML 邮件优先使用 `html_body_sanitized`,纯文本邮件使用 `text_body`;如果用户缺少 `SOURCE_MESSAGE_ORIGINAL_READ` 或会话接口失败,降级展示安全摘要和查看邮件会话入口。
|
||
|
||
来源邮件卡附件仍只展示名称 / 类型 / 大小等非 URL 摘要;如果 `source_message_card.display_payload`、会话返回的附件或内联媒体中包含直接 URL 字符串,前端不得在 V4 任务详情普通卡片区域直接渲染具体 URL,附件外链只能在 SourceMessage 原文权限链路中按既有规则处理。
|
||
|
||
Room Information 卡展示模型:
|
||
|
||
- `ROOM_INFORMATION` 卡只由 `NEW_BOOKING`、`UPDATE_BOOKING`、`CANCEL_BOOKING` 三类 event 触发;`TRACE_RESERVATION_NOTES`、`ROOMING_LIST`、`PAYMENT` 不触发房型信息卡。
|
||
- SuperAgent 仍只输出字段契约中的业务字段。Nights、Breakfast、Group Booking Status、Block ID、Confirmation Number 和 Adult 不由 SuperAgent 输出;其中 Adult 第一版不在卡内展示。
|
||
- 后端已在 `GET /api/reservation/order-tasks/{orderTaskId}` 的 Room Information 业务卡 `display_payload.room_information` 中补稳定展示模型,结构为 `event_type`、`booking_type`、`current_values`、`proposed_values`、`final_values`、`change_summary[]`、`group_booking_status_options[]`。前端按该展示模型渲染业务 UI,不再从 Agent raw payload / `target_order` 自行推导;如果存量或调试数据里已经持久化为稳定 `room_information.final_values` 模型,后端会按该稳定模型归一化展示和复核,不再回退到 Agent raw 推导。`fields[]` 继续作为确认 / 复核的可编辑字段白名单。`fields[].write_target` 对前端只表达请求体目标,例如 `confirmed_payload` 或 `review_resolution.field_overrides`,不暴露后端内部列名。
|
||
- `fields[]` 的 Room Information 主路径统一为 `/room_information/final_values/...`,例如 `/room_information/final_values/arrival_date`、`/room_information/final_values/room_items/0/room_type_code`。确认接口收到该结构时,后端会从展示模型派生 `confirmed_payload_json.room_information.final_values`,并重新计算 `nights`、`breakfast_included` 和 `group_booking_status_label`;只读字段、Agent `target_order`、Adult 和前端注入字段不会写入确认快照。`REVIEW_REQUIRED` 状态下,当前卡白名单内业务字段可以返回 `editable=true` 并允许同一 pointer 走 `review-resolution`,不再限定只能修空值、`missing_fields[]` 或目录错误字段。
|
||
- `NEW_BOOKING`:卡片展示创建后的最终值。Agent 提供 `target_order`、`arrival_date`、`departure_date`、`rate_code`、`booking_scenario`、`room_items[]`,Fit 可提供 `guest_name`;后端派生 `nights`、`breakfast_included` 和 Group Booking Status。
|
||
- `UPDATE_BOOKING`:后端从本地订单投影读取当前值,用 Agent `after` 合并得到最终值;页面上方展示本次实际变化的 `change_summary[]`,例如 `入住日期:2026-07-12 -> 2026-07-20`。如果日期变化导致 `nights` 变化,`nights` 也必须出现在差异区;字段区展示合并后的最终值。
|
||
- `CANCEL_BOOKING`:不使用 Agent 输出当前订单快照;后端从本地订单投影读取当前值并只读展示,用户只确认整单取消。Cancel 卡不允许编辑 Group Booking Status、Breakfast、日期、Rate Code 或房型房量。
|
||
- `nights` 由后端按酒店本地业务日期计算:`departure_date - arrival_date`,不涉及时区和 UTC;日期缺失、非法或离店早于入住时,`nights` 为空。第一版确认校验要求日期必填,后续如需更严格营业日规则另开 checkpoint。
|
||
- `breakfast_included` 是卡片展示和确认使用的布尔字段。Group 固定含早,前端显示勾选且只读;Fit 按 Rate Code 派生,Rate Code 包含 `RB` 时含早,包含 `RO` 时不含早;如果 Rate Code 无法派生,前端显示必填勾选框,由用户确认是否含早。
|
||
- Group Booking Status 仅 Group 显示,稳定 code 为 `TEN`、`DEF`、`INQ`,前端显示 `TEN-Tentative`、`DEF-Definite`、`INQ-Inquiry`。New Group 默认 `TEN`;`booking_scenario=STANDARD | PROPOSAL` 仅保留为 Agent 场景参考,不映射 Group Booking Status。`NEW_BOOKING` / `UPDATE_BOOKING` 确认前可手动改选,`CANCEL_BOOKING` 只读。
|
||
- `ROOMING_LIST` 卡确认时,如果同订单为 Group,后端已把 Group Booking Status 自动置为 `DEF`,即使此前为 `TEN` 或 `INQ`;该自动变更写入 `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 字段,仍只展示既有确认快照字段。Fit 不显示也不变更 Group Booking Status。
|
||
- `target_order.locator_value` 不作为前端可编辑字段,也不在普通任务详情的 Basic Information 或普通业务卡 `display_payload` / `confirmed_payload` 中返回;订单归属错误时通过 V4 复核选择正确订单或创建正确订单投影,不直接改写 Agent 原始 `target_order.locator_value`。但 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 原始定位字段。普通业务卡还会移除邮件 HTML、raw evidence、附件原始 URL 和 PMS 原始响应等敏感字段。
|
||
- Block ID 和 Confirmation Number 第一版只读;存在本地投影或未来 PMS 结果时展示,否则为空。Block ID 仅 Group 显示,Confirmation Number 仅 Fit 显示。
|
||
|
||
V4 任务详情页第一版字段白名单:
|
||
|
||
| 卡片 | 可编辑字段 | 只读 / 派生字段 |
|
||
| --- | --- | --- |
|
||
| `BASIC_INFORMATION` | `basic_information.account_code` | `market_code`、`source_code`、Account 显示名等由后端按 Account 目录派生 |
|
||
| `ROOM_INFORMATION` / `NEW_BOOKING` | `group_block_name` 或 `fit_name`、`arrival_date`、`departure_date`、`rate_code`、`room_items[].room_type_code`、`room_items[].room_count`、Group 的 `group_booking_status`、无法从 Fit Rate Code 派生时的 `breakfast_included` | `nights`、Group 固定 `breakfast_included=true`、Fit 可由 Rate Code 派生的 `breakfast_included`、Adult、Block ID、Confirmation Number、Agent 原始 `target_order` |
|
||
| `ROOM_INFORMATION` / `UPDATE_BOOKING` | 修改后的 `arrival_date`、`departure_date`、`room_items[].room_type_code`、`room_items[].room_count`、Group 的 `group_booking_status`、无法从 Fit Rate Code 派生时的 `breakfast_included` | 当前值、本次变化摘要、`nights` 差异、Rate Code、Adult、Block ID、Confirmation Number、Agent 原始 `target_order` |
|
||
| `ROOM_INFORMATION` / `CANCEL_BOOKING` | 无;用户只确认取消事项 | 本地订单投影当前值、`nights`、`breakfast_included`、Group Booking Status、Rate Code、房型房量、Block ID、Confirmation Number |
|
||
| `TRACE_RESERVATION_NOTES` | GENERAL:`trace_items[].text`、`trace_items[].department_code`;EXTRA_BED:`trace_items[].target_room_type_code`、`trace_items[].extra_bed_room_count`、`trace_items[].department_code` | `department_code` 第一版只允许 `FO`、`HSK`、`FO+HSK`,字段返回 `fixed_options[]` 三个固定选项,不允许自由文本;`target_room_type_code` 校验当前酒店 Room Type 目录;`extra_bed_room_count` 必须为正整数;不返回或确认 `content`、`target_order`、邮件正文、附件 URL、raw evidence 或 AI 原始 payload |
|
||
| `ROOMING_LIST` | 无;用户只确认 Rooming List 事项 | 来源邮件正文和附件摘要通过底部 `SOURCE_MESSAGE_DISPLAY` 查看;确认后 Group 自动置为 `DEF` |
|
||
| `PAYMENT` | 无;用户只确认附件关联事项 | `attachment_ids[]`、`payment_attachments[]` 安全摘要、图片缩略图、文件名、类型、大小、预览 / 下载可用性 |
|
||
| `SOURCE_MESSAGE_DISPLAY` | 无 | 当前触发该 V4 order task 的 SourceMessage 正文,只读且默认长度折叠,可展开全文 |
|
||
|
||
Rooming List 卡事项确认规则:
|
||
|
||
- Rooming List 卡第一版只做事项确认,不做名单解析、附件预览、Excel 生成或 PMS 导入。
|
||
- `ROOMING_LIST` event 不输出 `rows[]`、逐人名单、同住分组、18 列、Excel 或 PMS 导入参数,也不要求单独输出 `attachment_ids[]`。
|
||
- 页面应展示卡片标题、状态、目标订单信息和“确认卡片”按钮;如需查看来源内容,仍通过本订单任务底部的 `SOURCE_MESSAGE_DISPLAY` 查看当前触发 SourceMessage 正文和附件摘要。
|
||
- 用户点击“确认卡片”表示已人工处理该 Rooming List 事项;该确认会更新 V4 卡片状态和订单任务派生状态;如果同订单为 Group 且存在可更新的已确认 Room Information 快照,后端同时覆盖该快照里的 `group_booking_status=DEF` 和 `group_booking_status_label=DEF-Definite`,不改变 Agent 原始 payload,并写入可通过 V4 订单任务审计接口查询的 `V4_ROOMING_LIST_AUTO_DEF` 摘要。没有可更新投影时确认仍成功,只记录安全审计提示,不临时创建不完整 Room Information。该动作不代表 M010 Rooming List Excel 已生成,也不代表 PMS / OPERA / OHIP 已执行。
|
||
- 独立 Rooming List Excel 生成能力仍属于 M010 `/reservation/rooming-lists/new` 工具页面,第一版不嵌入 V4 Rooming List 卡。
|
||
|
||
Payment 卡附件展示规则:
|
||
|
||
- Payment 卡业务字段仍以 Agent 返回的 `attachment_ids[]` 为准,用于确认这些附件是否为当前订单付款凭证;这不代表已收款、已入账或付款状态已确认。第一版 `attachment_ids[]` 是只读业务事实,前端展示后只允许“确认卡片”,不允许用户增删、替换或重新选择附件集合。
|
||
- 后端已在 Payment 卡 `display_payload.payment_attachments[]` 中返回安全摘要,由 `attachment_ids[]` 匹配当前触发 SourceMessage 的包级附件或同酒店 SourceMessage 媒体摘要生成。匹配只认包级附件 ID / `external_media_id`,不认本系统媒体表内部 row ID,也不按文件名猜测。字段为 `attachment_id`、`file_name`、`content_type`、`size_bytes`、`is_image`、`preview_available`、`download_available`,可选 `external_media_id` / `unavailable_reason_code`;不得包含 `externalUrl`、OSS URL、签名参数或附件原始二进制。
|
||
- 图片判断以 `content_type` 以 `image/` 开头为主;图片在 Payment 卡内展示缩略图,点击后打开大图预览。缩略图和大图实际 URL 不从 `GET /api/reservation/order-tasks/{orderTaskId}` 返回,前端必须在具备 `SOURCE_MESSAGE_READ + SOURCE_MESSAGE_ORIGINAL_READ` 时调用 `GET /api/source-messages/{sourceMessageId}/conversation`,定位当前 SourceMessage 后按 `external_media_id` / `attachment_id` 匹配对应附件。
|
||
- 非图片附件统一显示文件列表,至少展示文件名、类型和大小,并提供下载动作;第一版不在 Payment 卡内嵌 PDF、Word、Excel 或压缩包预览。
|
||
- 2026-07-24 已确认:用户触发图片预览或文件下载时,前端 DOM 的 `img[src]` 或 `a[href]` 可以临时持有 conversation 接口返回的受权限附件 URL。该允许范围只覆盖当前用户、当前 SourceMessage、被 Payment `attachment_ids[]` 引用的附件和当前页面渲染 / 下载动作;V4 task detail API、页面可见文本、确认 payload、日志、错误上报、URL query 和 localStorage 仍不得暴露附件 URL。
|
||
- 入站 `PAYMENT.attachment_ids[]` 无法匹配同包 `source_message.attachments[].id` 时,不创建用户可处理 Payment 卡,只写 `adapter_contract_error` transition 或按 S10 / 技术异常规则处理。只有 `attachment_ids[]` 已合法匹配、但用户缺少原文读取权限、会话接口失败、附件 URL 缺失或媒体预览链路暂不可用时,Payment 卡才展示安全摘要和“无法预览 / 无法下载”的状态,不应把附件 URL 或错误详情暴露给普通用户。
|
||
- 前端不得把附件外链写入日志、错误上报、URL query、localStorage 或确认 payload;Payment 第一版确认卡片时只提交 `version` 和必要审计说明,不提交 `attachment_ids[]`、附件 URL 或完整附件对象。后续如需支持人工选择 / 增删付款凭证附件,必须另行定义数组编辑契约和后端审计口径。
|
||
|
||
### 12.4 S10/S99 来源通知详情
|
||
|
||
```text
|
||
GET /api/reservation/source-notifications/{notificationId}
|
||
分类:FRONTEND_USER
|
||
权限:RESERVATION_TASK_READ
|
||
```
|
||
|
||
返回结构:
|
||
|
||
```json
|
||
{
|
||
"notification": {},
|
||
"source_message_card": {},
|
||
"conversation_summary": {},
|
||
"availability": {}
|
||
}
|
||
```
|
||
|
||
说明:
|
||
|
||
- 只用于 S10/S99 来源通知详情页。
|
||
- 不返回 `order_task`、`bound_order`、`basic_information_card` 或 `business_cards`。
|
||
- 邮件正文、附件 URL 和会话原文读取仍按 SourceMessage 权限和原文读取审计规则处理。
|
||
- 来源通知详情页复用 V4 来源消息卡展示规则:普通页面只显示安全摘要和附件名称;附件 URL、完整正文和 HTML 只允许通过 SourceMessage 会话详情权限链路查看。
|
||
|
||
### 12.5 订单详情时间线
|
||
|
||
已在旧订单详情接口内兼容扩展:
|
||
|
||
```text
|
||
GET /api/reservation/orders/{orderId}
|
||
分类:FRONTEND_USER
|
||
权限:RESERVATION_ORDER_READ
|
||
```
|
||
|
||
用于订单详情页展示 V4 订单总览和 V4 订单任务时间线,同时保留旧 `tasks[]`。M002 V4 CP15.1 已补齐 `order_overview`、`next_v4_action`、`related_source_messages[]` 和 `v4_order_tasks[].cards[]`。`include_tasks=false` 时 `tasks[]`、`v4_order_tasks[]` 和 `related_source_messages[]` 都返回空数组,`order_overview` 为空快照,`next_v4_action.action_type=NONE`。
|
||
|
||
`order_overview` 只从已确认 V4 卡片派生:
|
||
|
||
- Basic Information 已确认后,返回 `account_code`、`account_name`、`market_code`、`source_code`;
|
||
- Room Information 已确认后,返回 `arrival_date`、`departure_date`、`rate_code`、`room_items[]`;下一阶段 Room Information 展示模型实现后,可继续从确认快照派生 `nights`、`breakfast_included` 和 Group Booking Status;
|
||
- Trace / Rooming List / Payment 返回对应最新卡片状态,方便订单详情展示待处理事项;
|
||
- 未确认 AI 建议不得进入 `order_overview`,避免把未处理内容展示成订单事实。
|
||
|
||
`next_v4_action` 使用和订单列表一致的下一步处理口径:Basic Information 优先;业务卡中 `REVIEW_REQUIRED` 优先于 `PENDING_CONFIRM`;无待处理卡时 `action_type=NONE`。订单详情页应使用该字段跳转 V4 订单任务详情页,不在订单详情页直接确认或复核。
|
||
|
||
`v4_order_tasks[]` 每项返回:
|
||
|
||
- `order_task_id`
|
||
- `order_ref`
|
||
- `order_task_status`
|
||
- `card_counts`
|
||
- `cards[]`
|
||
- `source_message_summary`
|
||
- `source_received_at`
|
||
- `created_at`
|
||
- `updated_at`
|
||
- `latest_activity_at`
|
||
|
||
说明:
|
||
|
||
- 排序沿用 V4 Repository 的同订单顺序:`source_received_at`、`source_message_id`、`order_context_index`、`created_at`、数字 ID 正序。
|
||
- `source_message_summary` 只返回安全摘要,不返回邮件正文、HTML、附件 URL 或 AI 原始 payload;原文仍走 SourceMessage 会话接口。
|
||
- `latest_activity_at` 为 V4 订单任务自身 `updated_at` 与其下卡片 `updated_at` 的最大值。
|
||
- `cards[]` 只返回卡片安全摘要,不返回业务字段 payload;订单详情页如需处理字段,必须跳转 V4 订单任务详情接口。
|
||
- 接口权限仍使用 `RESERVATION_ORDER_READ`,并按订单实际所属酒店校验访问权;V4 任务读取时继续以该订单酒店过滤,避免跨酒店脏数据泄露。
|
||
|
||
### 12.6 订单列表 V4 继续处理入口
|
||
|
||
旧订单列表接口继续作为订单视角入口:
|
||
|
||
```text
|
||
GET /api/reservation/orders
|
||
分类:FRONTEND_USER
|
||
权限:RESERVATION_ORDER_READ
|
||
```
|
||
|
||
在保留旧字段 `open_task_count` 和 `next_processable_task_id` 的基础上,M002 V4 CP14 已补齐以下 V4 字段,并新增订单列表统一展示计数字段:
|
||
|
||
| 字段 | 中文说明 |
|
||
| --- | --- |
|
||
| `open_work_item_count` | 订单列表统一待处理工作项数量;开发阶段不考虑旧数据,第一版等于 `v4_open_order_task_count` |
|
||
| `next_v4_order_task_id` | 当前订单下第一条仍需用户处理的 V4 订单任务 ID |
|
||
| `next_v4_action_card_id` | 该 V4 订单任务下第一张仍需确认或复核的卡片 ID |
|
||
| `next_v4_action_type` | `CONFIRM` / `REVIEW` / `NONE` |
|
||
| `next_v4_action_status` | `PENDING_CONFIRM` / `REVIEW_REQUIRED`;没有待处理卡时为空 |
|
||
| `v4_open_order_task_count` | 当前订单下未完成 V4 订单任务数,`COMPLETED` 不计入 |
|
||
|
||
派生规则:
|
||
|
||
- 只统计绑定到订单的 V4 订单任务;S10/S99 来源通知不创建订单,不进入订单列表字段统计。
|
||
- `open_work_item_count` 是前端展示待处理数量的统一口径;第一版忽略旧 V2/V3 数据,不叠加 `open_task_count`。
|
||
- 同订单 V4 订单任务沿用 Repository 队列顺序:`source_received_at`、`source_message_id`、`order_context_index`、`created_at`、数字 ID 正序。
|
||
- `order_task_status=COMPLETED` 的 V4 订单任务不计入 `v4_open_order_task_count`,也不作为下一步入口。
|
||
- 同一 V4 订单任务内,Basic Information 必须优先于业务卡。
|
||
- Basic 已确认后,业务卡中 `REVIEW_REQUIRED` 优先于普通 `PENDING_CONFIRM`。
|
||
- `next_v4_action_type=CONFIRM` 时前端调用卡片确认接口;`REVIEW` 时调用复核解阻接口;`NONE` 表示该订单没有 V4 待处理入口。
|
||
|
||
前端订单列表“继续处理”应优先使用 `next_v4_order_task_id` 跳转 V4 订单任务详情;没有 V4 待处理入口时,开发阶段通常不再回退旧任务入口。`next_processable_task_id` 仅作为历史 V2/V3 诊断兼容字段保留,测试数据清理后新 V4 订单不应返回该字段。
|
||
|
||
开发 / 测试阶段旧任务口径:
|
||
|
||
- V4 普通业务入站不再创建旧 `workflow_reservation_task`,也不再创建旧 `workflow_reservation_task_card`、旧任务草稿、旧 OPERA 模拟操作。
|
||
- `open_task_count` 仍表示旧任务表原始未关闭诊断计数;开发 / 测试环境应通过专项 SQL 清理旧任务及其直接依赖数据,清理后新 V4 订单列表中该值应为 0。
|
||
- `next_processable_task_id` 仍按旧 V2/V3 队列实时计算,但开发阶段不维护旧任务兼容;清理旧任务后,新 V4 订单不应再返回旧任务入口。
|
||
- 开发阶段不维护 V2/V3 旧任务兼容,测试数据可重建。
|
||
- 该策略仅限开发 / 测试阶段,不代表生产迁移方案;生产数据迁移策略不在本 checkpoint 处理,后续上线前另开迁移方案。
|
||
|
||
### 12.7 V4 业务审计查询
|
||
|
||
V4 卡片确认、复核解阻、复核场景订单归属确认和 S10/S99 来源通知 ack 已写入 `workflow_reservation_audit_log`。由于 V4 新模型不再使用旧 `workflow_reservation_task.id` 作为主承载,第一版审计查询按写入快照中的 V4 目标 ID 关联:
|
||
|
||
```text
|
||
GET /api/reservation/order-tasks/{orderTaskId}/audits
|
||
GET /api/reservation/source-notifications/{notificationId}/audits
|
||
```
|
||
|
||
接口规则:
|
||
|
||
- 两个接口都必须 Bearer 登录。
|
||
- 权限码统一使用 `RESERVATION_AUDIT_READ`。
|
||
- 后端先反查 V4 订单任务或来源通知的真实 `hotel_id`,再校验当前用户酒店访问权。
|
||
- `order-tasks/{orderTaskId}/audits` 第一版返回 `V4_CARD_CONFIRM`、`V4_CARD_REVIEW_RESOLVE` 等订单任务相关业务审计。
|
||
- `source-notifications/{notificationId}/audits` 第一版返回 `V4_SOURCE_NOTIFICATION_ACK`。
|
||
- 响应沿用旧审计行结构:`audit_id`、`order_id`、`task_id`、`operation_id`、`actor_type`、`actor_id`、`action`、`reason`、`before_snapshot`、`after_snapshot`、`occurred_at`。
|
||
- 审计快照只作为前端时间线展示数据,后端会清理 `raw`、正文、HTML、token、secret、私有 URL 和完整 payload 字段,前端仍不能把未知 URL-like 字符串直渲成附件或正文。
|
||
|
||
## 13. 前端写操作接口
|
||
|
||
### 13.1 确认卡片
|
||
|
||
```text
|
||
POST /api/reservation/order-tasks/{orderTaskId}/cards/{cardId}/confirm
|
||
分类:FRONTEND_USER
|
||
权限:RESERVATION_TASK_CONFIRM
|
||
```
|
||
|
||
请求要点:
|
||
|
||
- 请求 JSON 必须携带 `version`;`confirmed_payload` 可选,未传时后端使用当前展示 payload 作为确认快照。
|
||
- 前端只应提交当前卡 `fields[]` 中可编辑字段。后端确认时以当前卡展示快照为基准合并 `confirmed_payload`,未出现在展示快照 / 字段白名单中的字段会被忽略,不会写入 `confirmed_payload_json`。
|
||
- Basic Information 确认时 `basic_information.account_code` 必须是当前酒店数据库 Account 目录值;后端确认前会派生 `account_name`、`market_code` 和 `source_code` 写入 `confirmed_payload_json`。
|
||
- Room Information 确认时,前端优先提交 `confirmed_payload.room_information.final_values` 中当前 `fields[]` 可编辑字段;后端会生成稳定确认快照 `confirmed_payload_json.room_information.final_values`。该快照不包含 Agent 原始 `target_order`,也不包含邮件正文、附件 URL、raw evidence、Adult 或前端注入字段。
|
||
- 业务卡确认时,当前已递归校验已有 `rate_code`、`room_items[].room_type_code` 是否在当前酒店数据库目录中;Rate Code 第一阶段暂不校验 Account 适用关系。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`。
|
||
- 不提交草稿。
|
||
- 必须带 `version` 做并发校验。
|
||
- 后端确认后卡片 `CONFIRMED` 并锁定。
|
||
- 返回刷新后的 `GET /api/reservation/order-tasks/{orderTaskId}` 详情结构。
|
||
- Basic Information 必须先确认;业务卡第一版不强制逐张顺序确认。
|
||
- `SOURCE_MESSAGE_DISPLAY`、`CONFIRMED`、`REVIEW_REQUIRED` 卡不能通过该接口确认。
|
||
|
||
### 13.2 复核并确认卡片
|
||
|
||
```text
|
||
POST /api/reservation/order-tasks/{orderTaskId}/cards/{cardId}/review-resolution
|
||
分类:FRONTEND_USER
|
||
权限:RESERVATION_MANUAL_REVIEW_RESOLVE
|
||
```
|
||
|
||
请求要点:
|
||
|
||
- 提交 `field_overrides[]`。
|
||
- 可提交复核场景订单归属确认。
|
||
- 请求 JSON 必须携带卡片 `version`;可选 `reason` 写入业务审计摘要;`confirmed_order_id` 表示复核场景确认后的本地订单 ID。
|
||
- 如果订单任务当前 `order_id=null` 或 `target_resolution_status!=RESOLVED`,`confirmed_order_id` 必填;后端会按订单任务所属酒店查询并校验真实可见订单。
|
||
- `field_overrides[]` 每项包含 `field_pointer` 和 `value`;`field_pointer` 只允许指向当前卡 `fields[]` 中可编辑业务字段,不允许指向 `source_message`、`route_code`、`card_type`、`target_order`、`order_ref`、`missing_fields`、`manual_review`、`raw_evidence`、`validation_errors` 等只读诊断字段。
|
||
- 第一版允许的写入容器是 `basic_information`、Room Information 的 `room_information.final_values` 和历史兼容 `business_fields`。复核态允许编辑当前卡业务字段白名单内的已有叶子字段;不允许替换整个对象 / 数组、新增未知字段或提交后端未返回为可编辑的字段。
|
||
- 复核提交后同样执行目录校验;Basic Information 复核成功后会在 `confirmed_payload_json.basic_information` 中写入派生的 `account_name`、`market_code`、`source_code`。
|
||
- 如果订单任务已经有 `order_id` 且 `target_resolution_status=RESOLVED`,`confirmed_order_id` 只能为空或等于当前订单 ID;提交其它订单 ID 会返回 `V4_ORDER_REBIND_NOT_ALLOWED`。
|
||
- Basic Information 必须先确认;如果 Basic Information 自身是 `REVIEW_REQUIRED`,允许通过本接口先复核并确认 Basic。
|
||
- 解阻过程不改写 `ai_payload_json`;用户修正写入 `review_resolution_json`,最终确认快照写入 `confirmed_payload_json`。
|
||
- 校验通过后直接 `CONFIRMED`。
|
||
- 写业务审计。
|
||
- 返回刷新后的 `GET /api/reservation/order-tasks/{orderTaskId}` 详情结构;对应卡片 `review_status=RESOLVED`、`confirmed_by` 和 `confirmed_at` 会返回。
|
||
|
||
### 13.3 S10/S99 通知确认
|
||
|
||
```text
|
||
POST /api/reservation/source-notifications/{notificationId}/ack
|
||
分类:FRONTEND_USER
|
||
权限:RESERVATION_TASK_CONFIRM
|
||
```
|
||
|
||
S10/S99 已确认采用来源通知模型,不继续复用隐藏技术订单或旧 `SOURCE_MESSAGE_ONLY` 任务确认方式。第一版通知详情只显示邮件展示卡和确认按钮,确认动作表示已读 / 已处理。
|
||
|
||
请求要点:
|
||
|
||
- 必须带 `version` 做并发校验。
|
||
- 仅允许 `route_code=S10/S99` 的来源通知;其它路由即使状态为 `ACK_REQUIRED` 也不能通过该接口确认。
|
||
- 确认后 `notification_status=ACKED`,写确认人和 UTC 确认时间。
|
||
- 重复提交已确认通知按幂等成功返回当前已确认状态,不新增审计,不允许回退到 `ACK_REQUIRED`。
|
||
- 返回刷新后的 `GET /api/reservation/source-notifications/{notificationId}` 详情结构。
|
||
|
||
## 14. 旧 V3 / V2 兼容和废弃边界
|
||
|
||
开发阶段已确认可以清空数据,因此后续 V4 开发可以不迁移历史任务数据。V4 后新业务主线只写 V4 模型;开发阶段不维护 V2/V3 旧任务兼容,测试数据可重建。该策略仅限开发 / 测试阶段,不代表生产迁移方案;生产数据迁移策略不在本 checkpoint 处理,后续上线前另开迁移方案。
|
||
|
||
### 14.1 可继续保留
|
||
|
||
- `workflow_reservation_ai_batch`
|
||
- `workflow_reservation_ai_transition`
|
||
- `workflow_reservation_order`
|
||
- `workflow_reservation_audit_log`
|
||
- SuperAgent V3 / V2 入站兼容代码,直到正式切换前
|
||
|
||
### 14.2 V4 新数据不再使用
|
||
|
||
- `workflow_reservation_task_card.draft_payload_json`
|
||
- V3 `READY` 作为确认后等待 OPERA 的状态语义
|
||
- V3 OPERA 模拟自动生成
|
||
- V2 `ai_task_results[]` 字段矩阵作为新 V4 页面主模型
|
||
- 旧 `S000/S999` 作为新入站格式
|
||
- Fallback 转 New / Update / Cancel 作为 V4 主入口
|
||
|
||
### 14.3 可以后续专项废弃
|
||
|
||
- V2 `text/plain S000/S999` 兼容入口。
|
||
- 旧 `ai_task_results[]` 入站入口。
|
||
- V3 40 路由中不再被 V4 使用的历史 subtype。
|
||
- `workflow_reservation_task` 作为 V4 多卡主模型的直接承载方式。
|
||
- 旧 V2/V3 任务详情、草稿保存和最终确认接口,待 V4 新模型落地并完成前端切换后逐步废弃。
|
||
|
||
开发 / 测试环境旧任务清理参考 `../operations/dev-test-v4-legacy-task-cleanup.md`。废弃或删除生产历史链路前,必须先确认前端、MCP、SuperAgent 联调方和测试 fixture 都已切到 V4,并单独制定生产迁移方案。
|
||
|
||
## 15. 安全、权限和审计
|
||
|
||
后续实现接口时必须同步更新 `security-access-control-boundary.md`。
|
||
|
||
第一版建议:
|
||
|
||
| 能力 | 分类 | 权限码 | 审计 |
|
||
| --- | --- | --- | --- |
|
||
| 查询工作台、订单任务列表 / 详情、来源通知详情 | `FRONTEND_USER` | `RESERVATION_TASK_READ` | 只读默认不写业务审计 |
|
||
| 查询 V4 订单任务 / 来源通知业务审计 | `FRONTEND_USER` | `RESERVATION_AUDIT_READ` | 查询审计不再写审计;审计快照脱敏后返回 |
|
||
| 确认卡片 | `FRONTEND_USER` | `RESERVATION_TASK_CONFIRM` | 写业务审计 |
|
||
| 复核解阻 | `FRONTEND_USER` | `RESERVATION_MANUAL_REVIEW_RESOLVE` | 写业务审计 |
|
||
| 确认 S10/S99 来源通知 | `FRONTEND_USER` | `RESERVATION_TASK_CONFIRM` | 写业务审计 |
|
||
| 读取邮件正文 / 附件 / Payment 凭证预览和下载 | `FRONTEND_USER` | `SOURCE_MESSAGE_READ` + `SOURCE_MESSAGE_ORIGINAL_READ` | 写原文读取审计 |
|
||
| SuperAgent V4 回调 | `THIRD_PARTY_SUPERAGENT` | HMAC 机器鉴权 | 写 AI batch / transition |
|
||
|
||
AI 原始 payload、邮件正文、附件 URL 和技术 trace 不应直接进入普通列表接口。
|
||
|
||
## 16. 后续开发 checkpoint
|
||
|
||
| Checkpoint | 目标 | 主要交付 |
|
||
| --- | --- | --- |
|
||
| M002-V4-CP3 | V4 表结构和基础 Repository | 新增 V4 order task / card / source notification 表、Entity、Mapper、Repository、测试 |
|
||
| M002-V4-CP4 | V4 入站落新模型 | 已完成:SuperAgent V4 回调创建订单任务、Basic Information 卡、业务卡、邮件展示卡和 S10/S99 来源通知 |
|
||
| M002-V4-CP5 | V4 查询接口 | 已完成:工作台统一列表、订单任务列表、订单任务详情、来源通知详情查询接口,以及旧订单详情响应内的 `v4_order_tasks[]` V4 订单任务时间线 |
|
||
| M002-V4-CP6 | V4 卡片确认和 S10/S99 ack | 已完成:不保存草稿,支持普通卡片确认、确认后锁定、Basic Information 前置约束、同订单前置任务写侧阻塞、业务审计、version 并发校验和 S10/S99 来源通知确认 |
|
||
| M002-V4-CP7 | V4 复核解阻与订单归属确认 | 已完成:支持 `REVIEW_REQUIRED` 卡字段修正、复核说明、复核场景订单归属确认、version 并发校验、直接 `CONFIRMED`、审计和 availability.reviewable |
|
||
| M002-V4-CP8 | 受控目录第一版 | 已完成第一版:Account 固定目录校验、Market / Source 派生、RoomType / RateCode 固定种子校验、V4 任务卡 `fields[]` 字段白名单 |
|
||
| M002-V4-CP9 | V4 前端契约收口 | 字段、控件、availability、错误展示和旧任务入口切换 |
|
||
| M002-V4-CP10 | 旧 V3 / V2 能力收口评估 | 明确哪些兼容入口可以关闭,哪些仍保留只读历史 |
|
||
| M002-V4-CP11 | DB 管理目录与 Lookup API V1 | 已完成:新增 Account / Code 目录表、DirectoryService DB 实现、Account / Room Type / Rate Code lookup 查询接口、权限、酒店隔离和测试;同步 run 后置 |
|
||
| M002-V4-CP12 | 前端 Lookup 接入 | V4 卡片字段按 `options_source` 调用 lookup,替换固定种子硬编码选项,处理 stale / warning / 空目录 |
|
||
| M002-V4-CP13 | 目录管理后台 V1 | Account / Market / Source 管理,临时 Room Type / Rate Code 管理,目录维护权限和管理审计 |
|
||
| M002-V4-CP14 | 订单列表 V4 继续处理入口 | 已完成:`GET /api/reservation/orders` 返回 V4 下一步订单任务、卡片、动作类型、动作状态和 open 数,前端可优先跳 V4 订单任务详情 |
|
||
| M002-V4-CP14.5 | OWNER RATE 目录导入口径 | 已完成:V25 和启动补种子按人工确认结果维护 6 个 Room Type 和 Q.B.D / LIAN TAI 的 40 个酒店级 Rate Code 候选;暂不新增 Account + Rate Code 适用关系 |
|
||
| M002-V4-CP14.6 | Payment 附件预览 | 已完成前后端第一版:Payment 卡返回付款凭证附件安全摘要,不返回 URL;前端通过 SourceMessage 原文权限链路做图片缩略图 / 大图预览和非图片下载 |
|
||
| M002-V4-CP14.7 | Rooming List 事项确认卡 | 已完成前端轻量展示:Rooming List 卡第一版只展示事项和确认按钮,不解析名单、不预览附件、不生成 Excel、不导入 PMS |
|
||
| M002-V4-CP14.8 | Room Information 展示模型 | 已完成前后端第一版:后端返回 `display_payload.room_information` 稳定展示模型;前端按 New / Update / Cancel 业务表单展示最终值、差异、Nights、Breakfast、Group Booking Status 和本地订单投影;Adult 不显示 |
|
||
| M002-V4-CP14.9 | Rooming List 确认自动 DEF | 已完成后端第一版:确认 `ROOMING_LIST` 卡时,Group 同订单存在可更新 Room Information 确认快照则自动置 `DEF` 并写审计;Fit 不变更;无投影不造脏数据 |
|
||
| M002-V4-CP14.10 | 复核态卡片字段白名单和统一确认交互 | 已完成前端第一版:`REVIEW_REQUIRED` 保持原业务卡内编辑,问题字段红字提示,前端按钮显示“确认卡片”但调用 `review-resolution`;后端 `fields[]` 返回当前卡业务字段白名单,复核写入不再只限空值或目录错误字段 |
|
||
| M002-V4-CP15 | V4 业务审计查询 | 已完成:`GET /api/reservation/order-tasks/{orderTaskId}/audits` 和 `GET /api/reservation/source-notifications/{notificationId}/audits` 返回卡片确认、复核解阻和来源通知 ack 的脱敏审计流水 |
|
||
| M002-V4-CP15.1 | 订单详情 V4 化后端补齐 | 已完成:`GET /api/reservation/orders/{orderId}` 返回 `order_overview`、`next_v4_action`、`related_source_messages[]` 和 `v4_order_tasks[].cards[]`,支撑订单总览页 |
|
||
| M002-V4-CP16 | PMS / OPERA / OHIP 目录同步 | 同步 Adapter、同步 run、最后成功快照、失败重试和同步状态管理入口 |
|
||
|
||
## 17. 已确认设计决策
|
||
|
||
1. V4 前端接口不继续扩展旧 `/api/reservation/tasks/**`;工作台统一列表新开 `/api/reservation/workbench-items`,业务订单任务新开 `/api/reservation/order-tasks/**`,S10/S99 来源通知使用 `/api/reservation/source-notifications/**`。
|
||
2. `FIT + BOOKING_CODE` 第一版不建立 ACTIVE 唯一约束;业务绑定时要求匹配结果至多一条,匹配多条进入人工复核。
|
||
3. `BOOKING_CODE` 只是拿到 `CONFIRMATION_NUMBER` 前的临时定位字段,后续不作为 PMS 永久主键。
|
||
4. S10/S99 采用来源通知模型:任务列表 / 工作台展示,不挂隐藏技术订单;通知详情只显示邮件展示卡和确认按钮。
|
||
5. S10/S99 不创建订单、不进订单列表、不参与订单阻塞,也不支持编辑、复核、OPERA 或人工终止。
|
||
6. 第一版不强制所有业务卡逐张顺序确认,但 Basic Information 必须先确认。
|
||
7. Basic Information 的 Account / Market / Source 目录当前使用本系统数据库目录;第一版初始化数据来自固定种子导入,但运行时不再读取后端固定 Map。
|
||
8. 普通业务邮件的来源邮件展示卡只读展示,不需要用户确认;用户只确认 Basic Information 和具体业务卡。
|
||
9. S10/S99 因为没有业务卡,邮件展示卡需要确认按钮,用来记录已读 / 已处理。
|
||
10. V4 新模型落地并完成前端切换后,旧 V2/V3 任务详情、草稿保存和最终确认接口可以逐步废弃。
|