758 lines
33 KiB
Markdown
758 lines
33 KiB
Markdown
# M002 V4 Agent 回调字段契约
|
||
|
||
## 文档信息
|
||
|
||
| 项目 | 内容 |
|
||
| --- | --- |
|
||
| 文档版本 | 1.5 |
|
||
| 日期 | 2026-07-19 |
|
||
| 状态 | 当前 V4 字段基线;后端已完成 CP1 入站解析基线、CP2 多卡模型设计、CP3 持久化基线、CP4 入站写入新模型和 CP5 查询接口,V4 写接口仍需后续 checkpoint |
|
||
| 适用范围 | 0718 业务基线下,Agent → Adapter / MCP → 信息系统的业务回调字段 |
|
||
| 不适用范围 | 数据库表设计、前端视觉细节、真实 PMS API、技术失败后台重试、旧 M002 V3 数据兼容 |
|
||
|
||
## 1. 文档定位
|
||
|
||
本文把 2026-07-18 导入的业务基线、Agent 回调问题答复、草案审查答复和剩余 10 项确认回复,整理为 M002 V4 的 Agent 回调字段契约。
|
||
|
||
本契约用于后续 M002 V4 主流程设计、后端领域建模、前端页面模型、Adapter / MCP Schema 对齐和 SuperAgent 联调。当前后端已按本文完成 V4 入站解析基线:能识别 V4 包、校验关键契约、保存 AI transition / 任务卡原始 payload,并把可映射的六类 event 先接入现有订单任务链路。
|
||
|
||
V4 订单任务与多卡领域模型的 CP2 设计已经单独落到 `M002-v4-order-task-card-domain-model-cp2.md`。截至 CP5,表结构、Entity、Mapper、Repository 基线已经实现,SuperAgent V4 入站已经能写入 V4 订单任务、来源邮件展示卡、Basic Information 卡、业务卡和 S10/S99 来源通知;V4 工作台、订单任务列表 / 详情和来源通知详情查询接口已实现,卡片确认、复核和来源通知 ack 写接口仍未实现。
|
||
|
||
当前已确认开发阶段数据可以清空,因此 M002 V4 后续可以按新模型重建,不要求兼容旧任务数据、旧草稿、旧 OPERA 模拟、旧 `S000/S999`、旧 Fallback 或旧 `case_keys`。
|
||
|
||
## 2. 输入资料与优先级
|
||
|
||
| 文档 | 用途 |
|
||
| --- | --- |
|
||
| `docs/import/20260718/0718给黄哥/01-预订任务信息系统业务需求说明书.md` | 0718 业务权威基线 |
|
||
| `docs/import/20260718/0718给黄哥/02-业务字段与卡片规则矩阵.md` | 业务卡字段、展示和确认规则 |
|
||
| `docs/import/20260718/0718给黄哥/03-业务验收场景清单.md` | 验收场景 |
|
||
| `docs/import/20260718/0718业务基线-Agent回调问题答复.md` | 第一版 Agent 目标回调结构说明 |
|
||
| `docs/import/20260718/0718-M002-V4-Agent回调草案审查与最新答复.md` | 对 V4 草案的最新业务修正;与上一份答复冲突时以本文为准 |
|
||
| `docs/import/20260718/0718-V4剩余10项确认回复.md` | 对剩余技术 key、校验和运行边界的确认 |
|
||
|
||
如果本文与早期 M002 V3、0711 / 0712 P0、旧草案或历史聊天记录冲突,M002 V4 字段和业务语义以本文为准。
|
||
|
||
## 3. 总体结构
|
||
|
||
一封当前邮件对应一个结果包。
|
||
|
||
普通业务包:
|
||
|
||
```json
|
||
{
|
||
"route_code": null,
|
||
"source_message": {},
|
||
"order_contexts": [],
|
||
"message_events": []
|
||
}
|
||
```
|
||
|
||
纯通知包:
|
||
|
||
```json
|
||
{
|
||
"route_code": "S10",
|
||
"source_message": {},
|
||
"order_contexts": [],
|
||
"message_events": []
|
||
}
|
||
```
|
||
|
||
核心关系:
|
||
|
||
```text
|
||
source_message
|
||
-> 提供当前邮件展示卡和附件资源
|
||
|
||
order_contexts[]
|
||
-> 每个 order_ref 一项,承载该订单任务的 Basic Information
|
||
|
||
message_events[]
|
||
-> 每个具体业务 Event 生成一张对应业务任务卡
|
||
|
||
source_message.source_message_id + order_ref
|
||
-> 一笔订单任务
|
||
|
||
target_order
|
||
-> 用于信息系统查单和绑定订单,不用于当前包内归组
|
||
```
|
||
|
||
## 4. 冻结 key
|
||
|
||
V4 正式采用并冻结以下 key:
|
||
|
||
| key | 中文说明 |
|
||
| --- | --- |
|
||
| `route_code` | 包级路由。普通业务为 `null`,纯通知为 `S10` 或 `S99` |
|
||
| `source_message` | 当前触发邮件的包级来源事实,只出现一次 |
|
||
| `order_contexts` | 订单级上下文集合,每个 `order_ref` 一项 |
|
||
| `message_events` | 业务事件数组,承载六类 Event |
|
||
| `order_ref` | 当前结果包内订单引用,用于聚合同一订单,不是 PMS 键或系统 ID |
|
||
| `target_order` | 目标订单定位信息,用于信息系统查单和绑定订单 |
|
||
| `attachment_ids` | Payment 关联包级附件的 ID 数组 |
|
||
|
||
SuperAgent、Adapter、MCP Schema 和信息系统最终必须使用完全相同的字段名与嵌套位置。
|
||
|
||
## 5. source_message
|
||
|
||
### 5.1 结构
|
||
|
||
```json
|
||
{
|
||
"source_message_id": "string",
|
||
"conversation_id": "string | null",
|
||
"subject": "string | null",
|
||
"sender": "string | null",
|
||
"sent_at": "2026-07-18T02:10:00Z",
|
||
"body": "string | null",
|
||
"body_content_type": "text/plain | text/html",
|
||
"attachments": []
|
||
}
|
||
```
|
||
|
||
### 5.2 字段规则
|
||
|
||
| 字段 | 必需 | 中文说明 |
|
||
| --- | --- | --- |
|
||
| `source_message_id` | 是 | 当前触发邮件的稳定唯一 ID;本项目映射为 SourceMessage Inbox 的 `external_message_id` |
|
||
| `conversation_id` | 否 | 当前邮件会话 ID;完整历史线程由信息系统按该值查询 |
|
||
| `subject` | 是,可为 `null` | 邮件主题 |
|
||
| `sender` | 是,可为 `null` | 邮件监听提供的单一发件人值,不拆 display / address |
|
||
| `sent_at` | 是,可为 `null` | 邮件发送时间,统一 UTC ISO-8601 |
|
||
| `body` | 是,可为 `null` | 当前邮件单一原文,Agent 原样转发,不清洗、摘要、翻译、重排或改写 |
|
||
| `body_content_type` | 是 | 正文格式,取值 `text/plain` 或 `text/html` |
|
||
| `attachments` | 是 | 包级附件数组 |
|
||
|
||
`received_at` 不是当前页面和业务处理必需字段。如基础设施需要,可作为内部技术元数据保存,不作为业务必传字段。
|
||
|
||
`body_content_type` 按当前项目建议由 AgentBus / 邮件监听层或 Adapter 提供;Debug EML 和 AgentBus 入库也应保存或派生该字段。信息系统根据该字段选择纯文本转义或 HTML 安全渲染,但不得改写保存的原始 `body`。
|
||
|
||
## 6. attachments
|
||
|
||
### 6.1 结构
|
||
|
||
```json
|
||
{
|
||
"id": "att-1",
|
||
"name": "payment-slip.jpg",
|
||
"content_type": "image/jpeg",
|
||
"url": "https://upstream-storage/...",
|
||
"size": 251524
|
||
}
|
||
```
|
||
|
||
### 6.2 字段规则
|
||
|
||
| 字段 | 必需 | 中文说明 |
|
||
| --- | --- | --- |
|
||
| `id` | 是 | 包内稳定附件引用 |
|
||
| `name` | 是 | 原始文件名 |
|
||
| `content_type` | 是 | MIME 类型 |
|
||
| `url` | 是 | 上游邮件监听或文件存储层提供的可访问地址 |
|
||
| `size` | 否 | 上游有值时原样传递 |
|
||
|
||
URL 由上游邮件监听或文件存储层提供。Agent 只原样转发,不生成、拼接、刷新或签发 URL。
|
||
|
||
Payment 只按 `attachment_ids[]` 引用附件,不在 Event 内复制文件名、类型、URL 或完整附件对象。
|
||
|
||
## 7. order_contexts
|
||
|
||
### 7.1 结构
|
||
|
||
```json
|
||
{
|
||
"order_ref": "order-1",
|
||
"basic_information": {
|
||
"account_code": "ACCOUNT_CODE",
|
||
"manual_review": null
|
||
}
|
||
}
|
||
```
|
||
|
||
### 7.2 规则
|
||
|
||
- 一笔订单只有一份 Basic Information。
|
||
- Basic Information 跟随订单,不跟随具体 Event。
|
||
- Basic Information 不是 `event_type`,但它是订单任务中的一张独立可确认、独立锁定任务卡。
|
||
- 同一订单下即使同时有 Update、Trace、Rooming List、Payment,也只显示一张 Basic Information 卡。
|
||
- 一封邮件可能包含多笔订单,因此 Basic Information 不能放成整个结果包唯一对象。
|
||
- 每个非 S10 订单至少有一个非空 `order_ref`,并且在 `order_contexts[]` 中只能出现一次。
|
||
- 每个具体 Event 必须引用一个已存在的 `order_ref`。
|
||
|
||
### 7.3 Basic Information 字段
|
||
|
||
| 字段 | 必需 | 中文说明 |
|
||
| --- | --- | --- |
|
||
| `account_code` | 是,可为 `null` | 信息系统 Account 目录中的稳定 code,不是自由文本或显示名称 |
|
||
| `manual_review` | 是 | `null` 或 `true`;为 `true` 时 `account_code` 必须存在可解释的未解决状态,例如 `null` |
|
||
|
||
Market 和 Source 不由 Agent 输出,由信息系统根据订单级 `account_code` 从目录派生。用户只能从信息系统已有 Account、Market、Source 中受控改选;不存在 Manual 或自由输入。
|
||
|
||
Agent 给出非空 `account_code`,但信息系统运行时目录不存在该值时,属于系统目录 / 契约校验问题:Basic Information 卡阻止确认并显示字段错误,但不得反向篡改 Agent 原始 `manual_review`。
|
||
|
||
不同 `order_ref` 可以对应不同 Account。
|
||
|
||
## 8. message_events 公共字段
|
||
|
||
### 8.1 结构
|
||
|
||
```json
|
||
{
|
||
"order_ref": "order-1",
|
||
"event_type": "UPDATE_BOOKING",
|
||
"target_order": {
|
||
"booking_type": "GROUP",
|
||
"locator_type": "GROUP_CODE",
|
||
"locator_value": "LLTQ260510QVIPA"
|
||
},
|
||
"manual_review": null
|
||
}
|
||
```
|
||
|
||
### 8.2 公共字段规则
|
||
|
||
| 字段 | 必需 | 中文说明 |
|
||
| --- | --- | --- |
|
||
| `order_ref` | 是 | 当前包内订单引用,必须存在于 `order_contexts[]` |
|
||
| `event_type` | 是 | 业务事件类型 |
|
||
| `target_order` | 是 | 目标订单定位信息,用于信息系统查单和绑定订单 |
|
||
| `manual_review` | 是 | `null` 或 `true`;只作用于当前 Event 对应任务卡 |
|
||
|
||
以下字段不属于 Event 公共字段:
|
||
|
||
- `account_code`:已改为订单级 Basic Information。
|
||
- `payload`:V4 直接使用各 Event 的专属业务字段,不增加通用 payload 层。
|
||
- `evidence`:不是信息系统页面业务必传。
|
||
- `event_index`:数组顺序不承载业务顺序,页面顺序由信息系统按固定卡片规则决定。
|
||
- `event_id`:如 transport / 幂等需要,另由技术契约增加,不能代替 `order_ref`。
|
||
|
||
## 9. event_type
|
||
|
||
V4 新数据只允许以下六种:
|
||
|
||
```text
|
||
NEW_BOOKING
|
||
UPDATE_BOOKING
|
||
CANCEL_BOOKING
|
||
TRACE_RESERVATION_NOTES
|
||
ROOMING_LIST
|
||
PAYMENT
|
||
```
|
||
|
||
| `event_type` | 对应卡片 | 中文说明 |
|
||
| --- | --- | --- |
|
||
| `NEW_BOOKING` | 房间信息 | 新建预订 |
|
||
| `UPDATE_BOOKING` | 房间信息 | 修改预订 |
|
||
| `CANCEL_BOOKING` | 房间信息 | 整单取消 |
|
||
| `TRACE_RESERVATION_NOTES` | Trace | 普通备注 / 加床备注 |
|
||
| `ROOMING_LIST` | Rooming List | 任务详情内嵌 Rooming List |
|
||
| `PAYMENT` | Payment | 付款凭证 |
|
||
|
||
Basic Information 不是 Event。邮件展示卡不是 Event,由 `source_message` 固定生成。
|
||
|
||
S10/S99 是包级来源通知路由,不属于上述业务枚举。S10 表示纯信息类邮件,S99 表示无法形成业务素材包;两者都不创建订单或业务卡。
|
||
|
||
Fallback、`Need Manual Review`、独立 Voucher、旧 Payment Evidence、Voucher Received 均不再作为新 Agent 输出。
|
||
|
||
## 10. target_order
|
||
|
||
### 10.1 结构
|
||
|
||
```json
|
||
{
|
||
"booking_type": "GROUP",
|
||
"locator_type": "GROUP_CODE",
|
||
"locator_value": "LLTQ260510QVIPA"
|
||
}
|
||
```
|
||
|
||
### 10.2 合法组合
|
||
|
||
| 场景 | `booking_type` | `locator_type` | `locator_value` |
|
||
| --- | --- | --- | --- |
|
||
| Group 的所有业务 | `GROUP` | `GROUP_CODE` | Group Code,即 Block Name |
|
||
| Fit New,以及与该 New 同包同目标的 Trace | `FIT` | `BOOKING_CODE` | Booking Code |
|
||
| 当前无 PMS API、尚无真实 Confirmation Number 的 Fit 后续业务 | `FIT` | `BOOKING_CODE` | 查询信息系统本地订单投影 |
|
||
| 已取得真实 Confirmation Number 的 Fit 后续业务 | `FIT` | `CONFIRMATION_NUMBER` | PMS Confirmation Number |
|
||
|
||
### 10.3 规则
|
||
|
||
- 当前包内同订单归组使用 `order_ref`,不是使用相同 `target_order` 或相同 `null`。
|
||
- `target_order` 用于信息系统查单和绑定订单。
|
||
- 同一 `order_ref` 下的非空 `target_order` 必须一致。
|
||
- 定位值未解决时保留原 Event,未知字段为 `null`,Event 的 `manual_review=true`。
|
||
- Agent 能判断多个 Event 属于同单但定位未解决时,仍使用相同 `order_ref`。
|
||
- Agent 连是否同单都无法判断时,使用不同 `order_ref`,不能把相同 `null` 合并。
|
||
- 不输出旧 `case_keys`、定位候选数组、原因码或 `missing_fields[]`。
|
||
- AMEND GROUP CODE 统一走 S10,不形成 Update Event。
|
||
|
||
## 11. NEW_BOOKING
|
||
|
||
### 11.1 结构
|
||
|
||
```json
|
||
{
|
||
"order_ref": "order-1",
|
||
"event_type": "NEW_BOOKING",
|
||
"target_order": {
|
||
"booking_type": "GROUP",
|
||
"locator_type": "GROUP_CODE",
|
||
"locator_value": "GROUP-CODE"
|
||
},
|
||
"arrival_date": "2026-07-26",
|
||
"departure_date": "2026-07-29",
|
||
"rate_code": "RATE_CODE",
|
||
"booking_scenario": "STANDARD",
|
||
"room_items": [
|
||
{
|
||
"room_type_code": "TWN",
|
||
"room_count": 1
|
||
}
|
||
],
|
||
"manual_review": null
|
||
}
|
||
```
|
||
|
||
Fit 条件字段:
|
||
|
||
```json
|
||
{
|
||
"guest_name": "REAL GUEST NAME | null"
|
||
}
|
||
```
|
||
|
||
### 11.2 字段规则
|
||
|
||
| 字段 | 适用 | 必需 | 中文说明 |
|
||
| --- | --- | --- | --- |
|
||
| `arrival_date` | Group / Fit | 是,可为 `null` | 入住日期,酒店本地日期 |
|
||
| `departure_date` | Group / Fit | 是,可为 `null` | 离店日期,酒店本地日期 |
|
||
| `rate_code` | Group / Fit | 是,可为 `null` | 订单级 Rate Code |
|
||
| `room_items[]` | Group / Fit | 是 | 完整房型清单 |
|
||
| `room_items[].room_type_code` | Group / Fit | 是,可为 `null` | 受控 RoomType code |
|
||
| `room_items[].room_count` | Group / Fit | 是 | 房量,正整数 |
|
||
| `booking_scenario` | Group | 是 | `STANDARD` 或 `PROPOSAL` |
|
||
| `guest_name` | Fit | 否,可为 `null` | Fit 真实客人姓名;首封无真实姓名时可以为空 |
|
||
|
||
### 11.3 派生和禁止字段
|
||
|
||
- Group Code 已在 `target_order.locator_value`,同时作为 Block Name。
|
||
- Fit Booking Code 已在 `target_order.locator_value`。
|
||
- Agent 不输出 `booking_name`、独立 `booking_code`、Nights、Breakfast、Group Booking Status、Adult、Block ID 或 Confirmation Number。
|
||
- `proposal` 不再使用布尔字段,改为 `booking_scenario=STANDARD | PROPOSAL`。
|
||
- Adult 由信息系统按 RoomType 映射派生。
|
||
- `room_items=[]` 只能表示已识别 New 但完整房型清单未解决,并必须 `manual_review=true`。
|
||
|
||
## 12. UPDATE_BOOKING
|
||
|
||
### 12.1 结构
|
||
|
||
```json
|
||
{
|
||
"order_ref": "order-1",
|
||
"event_type": "UPDATE_BOOKING",
|
||
"target_order": {
|
||
"booking_type": "GROUP",
|
||
"locator_type": "GROUP_CODE",
|
||
"locator_value": "GROUP-CODE"
|
||
},
|
||
"after": {
|
||
"arrival_date": "2026-07-27",
|
||
"departure_date": "2026-07-30",
|
||
"room_items": [
|
||
{
|
||
"room_type_code": "TWN",
|
||
"room_count": 3
|
||
}
|
||
]
|
||
},
|
||
"manual_review": null
|
||
}
|
||
```
|
||
|
||
### 12.2 after 三态和字段规则
|
||
|
||
`after` 是稀疏对象:字段缺省表示本次不修改。
|
||
|
||
| 字段 | 语义 |
|
||
| --- | --- |
|
||
| `after.guest_name` | Fit Name 更新 |
|
||
| `after.arrival_date` | 修改后入住日期 |
|
||
| `after.departure_date` | 修改后离店日期 |
|
||
| `after.room_items` 不存在 | 本次邮件没有要求修改房型或房量 |
|
||
| `after.room_items=null` | 已识别本次涉及房型或房量修改,但无法形成修改后的完整房型清单;必须同时 `manual_review=true` |
|
||
| `after.room_items=[...]` | 修改后的完整房型清单,不是只输出变化行 |
|
||
|
||
### 12.3 规则
|
||
|
||
- 字段存在但为 `null`,表示已识别要改该字段、但目标值未解决,同时 `manual_review=true`;`null` 不表示清空。
|
||
- 只要修改涉及房型或房量,`after.room_items[]` 必须是修改后的完整房型清单。
|
||
- 不使用空数组表达“无法形成完整房型清单”。
|
||
- 如果修改后整笔订单不再保留任何房间,应按整单 `CANCEL_BOOKING` 处理,而不是提交空的 Update 房型清单。
|
||
- Rate Code 不允许出现在 Update。若 Agent 仍输出,按业务契约错误处理,不能静默忽略后继续执行。
|
||
- Before、原订单和完整最新订单由信息系统查单后生成,不由 Agent 输出。
|
||
|
||
## 13. CANCEL_BOOKING
|
||
|
||
### 13.1 结构
|
||
|
||
```json
|
||
{
|
||
"order_ref": "order-1",
|
||
"event_type": "CANCEL_BOOKING",
|
||
"target_order": {
|
||
"booking_type": "GROUP",
|
||
"locator_type": "GROUP_CODE",
|
||
"locator_value": "GROUP-CODE"
|
||
},
|
||
"manual_review": null
|
||
}
|
||
```
|
||
|
||
### 13.2 规则
|
||
|
||
- `CANCEL_BOOKING` 本身已经表示整单取消。
|
||
- 不输出 `cancel_scope`、`cancel_reason`、`after` 或当前订单快照。
|
||
- 减少房量、删除房型、修改日期或修改 Fit Name 属于 Update,不是 Cancel。
|
||
- 当前订单快照由信息系统查单后只读展示。
|
||
|
||
## 14. TRACE_RESERVATION_NOTES
|
||
|
||
### 14.1 结构
|
||
|
||
```json
|
||
{
|
||
"order_ref": "order-1",
|
||
"event_type": "TRACE_RESERVATION_NOTES",
|
||
"target_order": {
|
||
"booking_type": "GROUP",
|
||
"locator_type": "GROUP_CODE",
|
||
"locator_value": "GROUP-CODE"
|
||
},
|
||
"trace_items": [
|
||
{
|
||
"item_type": "GENERAL",
|
||
"text": "HONEYMOON SETUP",
|
||
"department_code": "FO"
|
||
},
|
||
{
|
||
"item_type": "EXTRA_BED",
|
||
"target_room_type_code": "TWN",
|
||
"extra_bed_room_count": 1,
|
||
"department_code": "FO+HSK"
|
||
}
|
||
],
|
||
"manual_review": null
|
||
}
|
||
```
|
||
|
||
### 14.2 字段规则
|
||
|
||
| 字段 | 适用 | 必需 | 中文说明 |
|
||
| --- | --- | --- | --- |
|
||
| `trace_items[]` | Trace | 是 | 同一订单一张 Trace 卡,卡内多条事项 |
|
||
| `item_type` | Trace item | 是 | `GENERAL` 或 `EXTRA_BED` |
|
||
| `text` | GENERAL | 是,可为 `null` | 普通备注内容 |
|
||
| `department_code` | GENERAL / EXTRA_BED | 是 | 信息系统受控部门或组合部门 code |
|
||
| `target_room_type_code` | EXTRA_BED | 是,可为 `null` | 加床目标房型 |
|
||
| `extra_bed_room_count` | EXTRA_BED | 是 | 加床房间数量 |
|
||
|
||
### 14.3 规则
|
||
|
||
- EXTRA_BED 不输出自由 `content`;信息系统固定显示 `SET EXTRA BED`。
|
||
- EXTRA_BED 不输出 `adult_after_extra_bed`;信息系统按当前 / 基础 Adult +1 计算,页面确认前允许用户纠正。
|
||
- Department code 由 Agent 必传,值来自信息系统维护的受控部门目录或组合目录。
|
||
- 加床目标房型不在当前订单时,Trace 卡不能确认,并提示用户核对目标房型和订单关联。
|
||
- 只有订单定位本身不可信时,才触发共享查单门槛阻断整个订单上下文。
|
||
|
||
## 15. ROOMING_LIST
|
||
|
||
### 15.1 结构
|
||
|
||
```json
|
||
{
|
||
"order_ref": "order-1",
|
||
"event_type": "ROOMING_LIST",
|
||
"target_order": {
|
||
"booking_type": "GROUP",
|
||
"locator_type": "GROUP_CODE",
|
||
"locator_value": "GROUP-CODE"
|
||
},
|
||
"manual_review": null
|
||
}
|
||
```
|
||
|
||
### 15.2 规则
|
||
|
||
- 只适用于 Group。
|
||
- 当前 Agent 只需识别这是 Rooming List 任务。
|
||
- 不输出 `rows[]`、逐人名单、同住分组、18 列、Excel 或 PMS 导入参数。
|
||
- 当前也不要求 Rooming List Event 单独输出 `attachment_ids[]`。
|
||
- 原附件已经在包级 `source_message.attachments[]`,只在邮件展示卡查看。
|
||
- 页面固定展示 12 个必填字段表头的标准表格示意,当前内容不代表附件已经真实转换。
|
||
- 未来取得 PMS API 后,按真实接口重新冻结住客与执行参数,不直接恢复历史草案中的 `rows[]`。
|
||
|
||
## 16. PAYMENT
|
||
|
||
### 16.1 结构
|
||
|
||
```json
|
||
{
|
||
"order_ref": "order-1",
|
||
"event_type": "PAYMENT",
|
||
"target_order": {
|
||
"booking_type": "GROUP",
|
||
"locator_type": "GROUP_CODE",
|
||
"locator_value": "GROUP-CODE"
|
||
},
|
||
"attachment_ids": ["att-1", "att-2"],
|
||
"manual_review": null
|
||
}
|
||
```
|
||
|
||
### 16.2 规则
|
||
|
||
- `attachment_ids[]` 至少一项。
|
||
- ID 不重复。
|
||
- 每个 ID 都必须存在于同包 `source_message.attachments[]`。
|
||
- 每个 ID 必须属于当前订单的付款凭证。
|
||
- 一笔订单多份凭证放在同一个 Payment Event。
|
||
- `attachment_ids[]` 没有业务顺序。
|
||
- Payment 不输出 `account_code`、金额、付款日期、付款人、交易号、银行账号、付款状态、Department 或完整附件对象。
|
||
|
||
没有任何凭证附件时,不能创建正常的空 Payment 卡:
|
||
|
||
- 来源附件存在,但 Agent 没有关联任何 ID:Agent / Adapter 契约错误。
|
||
- 来源本身没有可用于 Payment 卡的付款凭证:不形成正常 Payment,按 S10 展示原邮件。
|
||
- 附件 metadata 存在但 URL 无法读取:附件或存储技术异常。
|
||
|
||
## 17. manual_review
|
||
|
||
### 17.1 合法值
|
||
|
||
`manual_review` 只允许:
|
||
|
||
```json
|
||
null
|
||
```
|
||
|
||
或:
|
||
|
||
```json
|
||
true
|
||
```
|
||
|
||
正常数据为 `null`,不使用 `false`。
|
||
|
||
### 17.2 校验规则
|
||
|
||
- Event 的人工复核只属于该 Event 对应任务卡。
|
||
- Basic Information 的人工复核放在订单级 `basic_information.manual_review`,只属于 Basic Information 卡。
|
||
- 未解决值放在原业务字段位置,例如 `rate_code=null`、`room_type_code=null` 或 `account_code=null`。
|
||
- `manual_review=true` 时,当前 Basic Information 或 Event 中必须存在至少一个由该 Schema 允许的未解决标记。
|
||
- 未解决标记可以是特定可空字段、被允许的空清单或不完整 item。
|
||
- 来源冲突时,把无法可靠决定的原业务字段置为 `null`。
|
||
- 不能笼统认为任何空数组都能解释 `manual_review=true`。
|
||
- 所有字段完整、合法且通过目录校验,却仍输出 `manual_review=true`,属于 Agent / Adapter 契约异常。
|
||
|
||
不增加以下字段:
|
||
|
||
- `manual_review_info`
|
||
- `missing_fields[]`
|
||
- `reason_code`
|
||
- 字段路径
|
||
- 候选值
|
||
- 复核说明对象
|
||
|
||
具体字段错误路径、错误码和页面提示由信息系统根据 Schema、目录和业务规则生成。
|
||
|
||
## 18. S10/S99 来源通知
|
||
|
||
### 18.1 结构
|
||
|
||
```json
|
||
{
|
||
"route_code": "S10",
|
||
"source_message": {},
|
||
"order_contexts": [],
|
||
"message_events": []
|
||
}
|
||
```
|
||
|
||
### 18.2 规则
|
||
|
||
- 只显示邮件展示卡。
|
||
- 不显示 Basic Information、房间信息或其他业务卡。
|
||
- 不需要 `order_ref`、`target_order`、Account 或业务字段。
|
||
- 采用来源通知模型:任务列表 / 工作台展示,点击进入纯通知详情页,不挂隐藏技术订单。
|
||
- 不创建订单、不进入订单列表、不参与订单阻塞,也不支持编辑、复核、OPERA 或人工终止。
|
||
- 用户点击“确认”后任务完成。
|
||
- 不提供人工终止。
|
||
- 不调用 PMS,不修改订单。
|
||
- S10/S99 第一版只表达来源通知类型,不输出 Fallback、原因码、通知说明或 `Need Manual Review`。
|
||
|
||
## 19. 技术异常
|
||
|
||
下列情况不生成酒店用户可见任务,也不转换成 S10 或人工复核:
|
||
|
||
- 非法 JSON。
|
||
- 输出不符合 Schema。
|
||
- Event 引用了不存在的 `order_ref`。
|
||
- 同一 `order_ref` 下出现冲突的非空 `target_order`。
|
||
- Rate Code 出现在 Update。
|
||
- `manual_review=true` 但没有任何可识别的未解决字段。
|
||
- Adapter 转换失败。
|
||
- MCP 提交失败。
|
||
- Agent / Skill 执行异常。
|
||
- 附件 metadata 存在但存储 URL 无法读取。
|
||
|
||
技术失败不属于酒店用户任务。后台 debug、告警和技术重试接口属于技术运维需求,不进入本次业务回调,也不在酒店用户任务卡上增加“重试”。
|
||
|
||
当前后端实现口径:
|
||
|
||
- 如果 V4 包级结构不符合契约,但 `source_message.source_message_id` 能按 SourceMessage Inbox 的 `external_message_id` 定位到邮件,后端会创建 AI batch,并写入一条 `catalog_code=M002V4`、`system_process_category=ADAPTER_CONTRACT_ERROR` 的 transition;不创建订单、任务或酒店用户可处理卡。
|
||
- 如果 `source_message.source_message_id` 缺失、无法解析或无法定位 SourceMessage,后端仍返回明确请求错误,不创建 AI batch / transition。
|
||
- 单个 `message_events[i]` 的契约错误只影响该 event,同包其它合法 event 继续按数组顺序处理。
|
||
- 普通 V4 业务包中,只有至少有一个合法业务 event 的 `order_ref` 会创建 V4 订单任务、来源邮件展示卡、Basic Information 卡和对应业务卡;全包只有契约错误 event 时不创建 V4 订单任务或用户可处理卡。
|
||
- V4 `route_code=S10/S99` 会写入 `workflow_reservation_v4_source_notification`,不再创建隐藏技术订单或旧 `workflow_reservation_task`;旧 V3 S10/S99 和旧文本 S000/S999 仍保留历史兼容链路。
|
||
|
||
当前项目可以保留 `platform_superagent_dispatch_run` 或同类技术运行记录作为主链路技术状态载体,后续另行设计查询、告警、超时和重试能力。
|
||
|
||
## 20. 受控 code 目录
|
||
|
||
Account、RoomType、RateCode、Department 的目录由信息系统或其主数据服务统一维护,并作为唯一事实源。
|
||
|
||
规则:
|
||
|
||
- SuperAgent 只能输出目录中已有的稳定 code。
|
||
- 不允许输出自由文本或自行创造 code。
|
||
- Agent 无法可靠匹配时,按对应业务字段的未解决规则处理。
|
||
- Agent 输出非空 code、但信息系统目录不存在该值时,属于目录校验或契约问题。
|
||
- Market 和 Source 由信息系统根据订单级 `account_code` 派生,不由 Agent 输出。
|
||
|
||
当前项目接受“SuperAgent 确定后把目录给本系统”的落地方式。第一阶段可以先以固定种子目录或版本化目录快照对齐;后续如需在线查询或目录同步接口,再另开需求。
|
||
|
||
## 21. 后端 V4 建模建议
|
||
|
||
后端 V4 可以按以下聚合模型实现:
|
||
|
||
```text
|
||
AI 回调包
|
||
-> 按 source_message.source_message_id 反查 SourceMessage Inbox external_message_id
|
||
-> 保存 AI Batch / 原始 payload
|
||
-> 校验 order_contexts[] 和 message_events[]
|
||
-> 按 source_message_id + order_ref 创建订单任务
|
||
-> 每个 order_ref 创建一张 Basic Information 卡
|
||
-> 每个 Event 创建一张业务卡
|
||
-> 固定补邮件展示卡
|
||
-> target_order 用于查单和绑定本地订单投影
|
||
```
|
||
|
||
建议新增或调整模型概念:
|
||
|
||
| 概念 | 中文说明 |
|
||
| --- | --- |
|
||
| 订单任务 | 同一来源邮件 + 同一 `order_ref` 的聚合容器 |
|
||
| 任务卡 | 独立确认、独立锁定的业务卡 |
|
||
| 本地订单投影 | 当前无 PMS API 阶段,用于保存 New / Update / Cancel 后的信息系统内最新订单状态 |
|
||
| 技术失败记录 | Agent / Adapter / MCP 技术异常,不进用户任务列表 |
|
||
|
||
## 22. 已确认技术口径
|
||
|
||
| 项目 | 当前口径 |
|
||
| --- | --- |
|
||
| V4 key | `route_code`、`source_message`、`order_contexts`、`message_events`、`order_ref`、`target_order`、`attachment_ids` |
|
||
| `source_message_id` 映射 | 本项目按 SourceMessage Inbox 的 `external_message_id` 处理 |
|
||
| 时间格式 | UTC ISO-8601,例如 `2026-07-18T02:10:00Z` |
|
||
| 正文格式 | 单一 `body` + `body_content_type=text/plain/text/html` |
|
||
| code 目录 | 信息系统主数据是唯一事实源,目录同步方式后置 |
|
||
| 技术异常 channel | 需要独立建设,不进入酒店用户任务体系;当前先保留设计空间 |
|
||
| Payment 附件 | 正常 Payment 必须 `attachment_ids.length > 0` |
|
||
| `manual_review` validator | 按各对象条件 Schema 校验,必须能由可识别未解决字段解释 |
|
||
| Update room_items | 不存在 / `null` / 数组三态 |
|
||
| Fit Booking Code 临时定位 | 当前无 Confirmation Number 时可用 Booking Code 查本地订单投影;第一版不建立 ACTIVE 唯一约束,匹配多条进入人工复核 |
|
||
| V4 前端资源路径 | 新开 `/api/reservation/order-tasks/**`,不扩展旧 `/api/reservation/tasks/**` 作为 V4 主入口 |
|
||
| Basic Information 前置 | Basic Information 必须先确认;业务卡之间第一版不强制逐张顺序确认 |
|
||
| Account 目录 | 第一版使用信息系统后端固定种子数据 |
|
||
|
||
## 23. 后续仍需技术对齐
|
||
|
||
以下事项不会改变 V4 页面业务含义,但会影响联调和实现细节:
|
||
|
||
1. SuperAgent、Adapter、MCP Schema 和信息系统 DTO 使用同一份 V4 Schema。
|
||
2. `body_content_type` 的来源是 AgentBus / 邮件监听层还是 Adapter 派生。
|
||
3. `dispatch_run_id`、超时、错误 channel 和技术失败查询入口如何落地。
|
||
4. Account、RoomType、RateCode、Department 目录如何提供给 SuperAgent,以及目录版本如何管理。
|
||
5. 如需 `event_id` 或幂等键,应作为 transport 字段设计,不作为业务页面字段。
|
||
|
||
## 24. 当前开发结论
|
||
|
||
- 0718 业务基线覆盖 M002 V3 的任务级草稿、READY、OPERA 模拟、Fallback、S99 和旧 Need Manual Review 页面语义。
|
||
- 新数据按 `S10/S99` 表达来源通知;两者都采用同一来源通知模型。
|
||
- 用户可见任务按订单任务 + 多卡建模。
|
||
- 普通业务邮件的来源邮件展示卡只读展示,不需要用户确认。
|
||
- S10/S99 因为没有业务卡,邮件展示卡需要确认按钮,用于记录已读 / 已处理。
|
||
- Basic Information 必须先确认;其它业务卡第一版可以独立确认,不强制逐张顺序确认。
|
||
- 每张业务卡独立确认、确认后永久锁定。
|
||
- 不保存草稿。
|
||
- 当前无 PMS API,不生成 OPERA 模拟操作和 PMS 成功语义。
|
||
- 技术异常不创建用户可见任务。
|
||
- 开发阶段不兼容老数据,允许清空旧任务相关数据后迁移。
|
||
|
||
## 25. 后端 CP1 已落地范围
|
||
|
||
2026-07-18 后端已完成 M002 V4 入站解析与数据模型基线,当前代码支持:
|
||
|
||
- `POST /api/integrations/superagent/task-results` 接收 V4 JSON 包:`route_code`、`source_message`、`order_contexts[]`、`message_events[]`。
|
||
- `source_message.source_message_id` 按 SourceMessage Inbox 的 `external_message_id` 定位当前邮件;SuperAgent 不传内部数据库 ID。
|
||
- V4 `route_code=S10/S99` 写入 `workflow_reservation_v4_source_notification` 来源通知模型;旧 `SOURCE_MESSAGE_ONLY` 只读特殊任务仅保留给 V3 S10/S99 和旧 S000/S999 兼容数据。
|
||
- 普通业务包要求 `route_code=null`,并按 `message_events[]` 数组顺序处理。
|
||
- 第一版识别六类 `event_type`:`NEW_BOOKING`、`UPDATE_BOOKING`、`CANCEL_BOOKING`、`TRACE_RESERVATION_NOTES`、`ROOMING_LIST`、`PAYMENT`。
|
||
- 能映射到现有稳定任务卡的 event 会创建业务任务,并在 `ai_payload_json` 中保存 `v4_source_message`、`v4_order_context`、`v4_message_event`、`route_code`、系统处理分类和 `field_contract_version=20260718-v4`。
|
||
- V4 入站校验和路由已拆分为独立 Validator / Router,主业务 service 只负责编排、幂等和落库。
|
||
- V4 包级契约错误在 SourceMessage 可定位时只写 `adapter_contract_error` transition,不创建订单、任务或用户可处理卡。
|
||
- `PAYMENT.attachment_ids[]` 必须能匹配 `source_message.attachments[].id`;不匹配时只写 `adapter_contract_error` transition,不创建用户可处理业务任务。
|
||
- `UPDATE_BOOKING` 中出现 `rate_code` 或 `after.rate_code` 时按 `UPDATE_RATE_CODE_NOT_ALLOWED` 写入 `adapter_contract_error` transition。
|
||
- `manual_review` 只接受 `null` 或布尔 `true`;`true` 必须能由当前对象中可识别的未解决字段解释。
|
||
|
||
当前 CP4 已完成:
|
||
|
||
- 普通 V4 业务包按 `source_message_id + order_ref` 写入 `workflow_reservation_v4_order_task`。
|
||
- 普通 V4 业务包固定创建 `SOURCE_MESSAGE_DISPLAY` 只读卡和 `BASIC_INFORMATION` 可确认 / 可复核卡。
|
||
- 合法 V4 event 按 `event_type` 创建 `ROOM_INFORMATION`、`TRACE_RESERVATION_NOTES`、`ROOMING_LIST` 或 `PAYMENT` 业务卡;event 契约错误只落 AI transition。
|
||
- V4 S10/S99 写入 `workflow_reservation_v4_source_notification`,状态为 `ACK_REQUIRED`。
|
||
|
||
当前 CP5 已完成:
|
||
|
||
- `GET /api/reservation/workbench-items` 查询 V4 工作台统一列表,混排 V4 业务订单任务和 S10/S99 来源通知。
|
||
- `GET /api/reservation/order-tasks` 查询 V4 业务订单任务列表,不包含 S10/S99 来源通知。
|
||
- `GET /api/reservation/order-tasks/{orderTaskId}` 查询 V4 订单任务详情,按来源邮件展示卡、Basic Information 卡和业务卡拆分。
|
||
- `GET /api/reservation/source-notifications/{notificationId}` 查询 V4 S10/S99 来源通知详情。
|
||
- CP5 查询接口强制 Bearer 登录、`RESERVATION_TASK_READ` 和酒店访问权;不返回邮件正文、附件 URL、`ai_payload_json` 或来源通知原始 payload。
|
||
|
||
当前仍未完成:
|
||
|
||
- 普通 V4 业务包暂时仍保留旧 V3 任务状态、草稿和 OPERA 模拟骨架兼容,便于前端过渡;V4 写接口和前端页面完成后再逐步废弃旧链路。
|
||
- V4 卡片确认、复核解阻和 S10/S99 来源通知 ack 写接口。
|
||
- 尚未接入真实 PMS / OPERA / OHIP。
|
||
- 尚未改造前端 V4 页面模型。
|
||
|
||
## 26. 后端 CP2 设计文档状态
|
||
|
||
2026-07-18 已新增 `M002-v4-order-task-card-domain-model-cp2.md`,明确以下后续开发方向:
|
||
|
||
- 普通业务包按 `source_message_id + order_ref` 形成 V4 订单任务。
|
||
- 普通业务包固定展示来源邮件卡,但该卡只读、不阻塞、不替代邮件会话接口。
|
||
- 每个 `order_ref` 创建一张 Basic Information 卡。
|
||
- 每个 `message_events[]` event 创建一张业务卡,卡片按固定业务顺序展示。
|
||
- S10/S99 后续按来源通知模型实现,不再挂隐藏技术订单;只在任务列表 / 工作台展示,并进入纯通知详情页确认已读 / 已处理。
|
||
- `FIT + BOOKING_CODE` 不建立 ACTIVE 唯一约束;业务绑定查到多条时进入人工复核。
|
||
- V4 前端工作台统一列表为 `/api/reservation/workbench-items`,业务订单任务接口新开 `/api/reservation/order-tasks/**`,S10/S99 来源通知详情为 `/api/reservation/source-notifications/{notificationId}`。
|
||
- V4 新数据不再保存后端草稿;用户只提交最终确认或复核解阻。
|
||
- 卡片确认后锁定,错误修正后续通过审计和未来纠错流程表达,不覆盖原确认。
|
||
- 技术异常只进入 AI transition / 技术运行记录,不进入用户可处理卡。
|
||
- CP3 已新增 V4 订单任务表、V4 任务卡表和 V4 来源通知表,继续复用 SourceMessage、AI batch、AI transition、Reservation Order 和业务审计表。
|
||
|
||
CP3 只完成表结构、Entity、Mapper、Repository、幂等创建、`order_context_index` 稳定排序、非 event 卡 `source_event_index=0` 和基础乐观锁更新。CP4 已把 V4 回调写入新模型。CP5 已开放查询接口。后续开发应继续补卡片确认 / 复核、S10/S99 ack 和前端页面。
|