实现 M002 订单任务入站与队列规则
This commit is contained in:
@@ -10,4 +10,9 @@
|
||||
- `frontend-development-guidelines.md`:当前项目前端专属规范。
|
||||
- `go-live-notes.md`:当前项目上线注意事项,记录上线前检查、环境变量、安全、AgentBus、验证和回滚。
|
||||
- `requirements/M001-source-message-inbox-prd.md`:M001 邮件来源入口 PRD,记录 AgentBus 邮件 JSON 入库、历史查询、原文读取和媒体引用边界。
|
||||
- `requirements/M002-order-task-workflow-v1.md`:M002 订单任务主流程 V1,记录 SourceMessage 之后的 SuperAgent 抽取、订单挂靠、任务处理和 OPERA/OHIP 模拟操作边界。
|
||||
- `requirements/M002-order-task-workflow-v2.md`:M002 订单任务主流程 V2,记录 AI 过渡层、任务卡矩阵、系统主任务类型、临时订单、订单号候选和 OPERA 模拟回填边界。
|
||||
- `requirements/M002-superagent-task-result-api-contract.md`:M002 SuperAgent 任务结果入站接口契约,记录 HMAC 鉴权、请求响应、幂等和错误码。
|
||||
- `requirements/M002-backend-data-model-design.md`:M002 后端数据模型设计,记录 AI 过渡层、订单、任务、任务卡、审计和 OPERA 模拟结果表。
|
||||
- `requirements/M002-backend-checkpoint-plan.md`:M002 后端 checkpoint 计划,记录后端实现拆分、交付物和验收标准。
|
||||
- `integrations/superagent-agentbus-project-integration-guide.md`:当前项目 SuperAgent 与 AgentBus 验证记录和项目级接入细节。
|
||||
|
||||
@@ -82,6 +82,11 @@
|
||||
- `server/src/main/resources/db/migration/V1__create_source_message_inbox.sql`
|
||||
- `server/src/main/resources/db/migration/V2__create_source_message_original_access_audit.sql`
|
||||
|
||||
当前 M002 订单任务相关 migration:
|
||||
|
||||
- `server/src/main/resources/db/migration/V3__create_reservation_ai_task_workflow.sql`
|
||||
- `server/src/main/resources/db/migration/V4__harden_reservation_task_queue_and_manual_conversion.sql`
|
||||
|
||||
上线前确认:
|
||||
|
||||
- 目标数据库为空库或 Flyway history 与当前代码一致。
|
||||
@@ -89,6 +94,31 @@
|
||||
- migration 在 UAT 或测试库已经跑过。
|
||||
- 表和字段中文注释能正常创建。
|
||||
- 数据库时间按 UTC 写入,接口层负责返回 ISO 8601。
|
||||
- 执行 V4 前,如果目标库已有 M002 试运行数据,必须先检查 ACTIVE 订单业务号重复和同订单任务队列序号重复。
|
||||
|
||||
V4 前置检查 SQL:
|
||||
|
||||
```sql
|
||||
SELECT hotel_id, order_key_type, order_business_key, COUNT(*) AS duplicate_count
|
||||
FROM workflow_reservation_order
|
||||
WHERE order_status = 'ACTIVE'
|
||||
AND order_key_type IN ('GROUP_CODE', 'CONFIRMATION_NUMBER')
|
||||
AND order_business_key IS NOT NULL
|
||||
GROUP BY hotel_id, order_key_type, order_business_key
|
||||
HAVING COUNT(*) > 1;
|
||||
|
||||
SELECT hotel_id, order_id, queue_participation, execution_order, COUNT(*) AS duplicate_count
|
||||
FROM workflow_reservation_task
|
||||
GROUP BY hotel_id, order_id, queue_participation, execution_order
|
||||
HAVING COUNT(*) > 1;
|
||||
```
|
||||
|
||||
处理要求:
|
||||
|
||||
- 如果任一 SQL 返回记录,不要继续执行 V4。
|
||||
- ACTIVE 订单业务号重复时,先由业务确认保留哪一条 ACTIVE,其他订单应转为 `LOGIC_DELETED`、`ENDED` 或完成任务迁移后再上线。
|
||||
- 同订单任务队列序号重复时,先按来源顺序和审计证据重新分配 `execution_order`,确认前置任务关系正确后再上线。
|
||||
- 不要为了让唯一索引创建成功而随意删除订单、任务或 AI 原始记录。
|
||||
|
||||
禁止事项:
|
||||
|
||||
|
||||
316
docs/project/requirements/M002-backend-checkpoint-plan.md
Normal file
316
docs/project/requirements/M002-backend-checkpoint-plan.md
Normal file
@@ -0,0 +1,316 @@
|
||||
# M002 Backend Checkpoint Plan 后端开发 Checkpoint 计划
|
||||
|
||||
## 文档信息
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 文档版本 | 0.1 |
|
||||
| 日期 | 2026-07-07 |
|
||||
| 状态 | 后端开发计划草稿 |
|
||||
| 适用范围 | M002 后端实现拆分、交付物和验收标准 |
|
||||
| 主要读者 | 后端、测试、产品、后续协作 agent |
|
||||
|
||||
## 1. 文档定位
|
||||
|
||||
本文把 `M002-order-task-workflow-v2.md`、`M002-superagent-task-result-api-contract.md` 和 `M002-backend-data-model-design.md` 拆成可执行后端 checkpoint。
|
||||
|
||||
每个 checkpoint 都应先读项目规范,再按本项目包结构和注释要求实现。不要一次性把完整后端做完,也不要在不确定字段或目录归属时先写再重构。
|
||||
|
||||
## 2. 开发前必读
|
||||
|
||||
后端开发前必须先读:
|
||||
|
||||
- `AGENTS.md`
|
||||
- `README.md`
|
||||
- `docs/project/backend-development-guidelines.md`
|
||||
- `docs/import/reusable/backend-development-guidelines.md`
|
||||
- `docs/import/reusable/backend-base-structure-pagination-guidelines.md`
|
||||
- `docs/import/reusable/alibaba-java-coding-guidelines-summary.md`
|
||||
- `docs/project/requirements/M002-order-task-workflow-v2.md`
|
||||
- `docs/project/requirements/M002-superagent-task-result-api-contract.md`
|
||||
- `docs/project/requirements/M002-backend-data-model-design.md`
|
||||
- `docs/import/20260706/开发AI先读_工作顺序.md`
|
||||
- `docs/import/20260706/AI输出参数并集字典.xlsx`
|
||||
- `docs/import/20260706/任务卡展示编辑矩阵.xlsx`
|
||||
|
||||
## 3. 代码组织要求
|
||||
|
||||
后端实现必须继续遵守当前项目包结构习惯:
|
||||
|
||||
- `control` 放 Controller 具体实现。
|
||||
- `service` 放 Service 接口。
|
||||
- `service.impl` 放 Service 实现类。
|
||||
- `domain` 放 Entity。
|
||||
- `mapper` 放 MyBatis Mapper。
|
||||
- `repository` 放 Repository 接口和具体实现。
|
||||
- `common.dto`、`common.request`、`common.result` 放通用数据载体。
|
||||
- `common.enums` 放枚举。
|
||||
- 外部系统适配类放在对应 `integrations.<capability>.<provider>.adapter` 包。
|
||||
|
||||
Controller、Service、Service 实现类的方法必须有中文注释。Entity 字段必须有中文注释。Mapper 继承 MyBatis-Plus 的自带方法不强制写注释,自定义方法按复杂度补充中文注释。
|
||||
|
||||
## 4. Checkpoint 1:接口契约与安全骨架
|
||||
|
||||
名称:`m002-cp01-superagent-intake-security`
|
||||
|
||||
目标:
|
||||
|
||||
- 建立 SuperAgent 任务结果入站接口骨架。
|
||||
- 完成 HMAC 鉴权、请求体大小限制、timestamp 和 nonce 防重放。
|
||||
- 暂不创建完整订单任务,只返回受控错误或最小接收结果。
|
||||
|
||||
建议范围:
|
||||
|
||||
- 新增配置项:`SUPERAGENT_TASK_RESULT_HMAC_SECRET` 等。
|
||||
- 新增 HMAC 校验组件。
|
||||
- 新增 nonce 去重存储,第一版可用数据库或可控缓存实现。
|
||||
- 新增请求 / 响应 DTO。
|
||||
- 新增统一错误响应。
|
||||
|
||||
验收标准:
|
||||
|
||||
- 缺失 Header 返回 `401`。
|
||||
- timestamp 超时返回 `401`。
|
||||
- 签名错误返回 `401`。
|
||||
- nonce 重放返回 `409`。
|
||||
- 请求体过大返回 `413`。
|
||||
- 响应和日志不暴露 secret、签名原文或完整请求体。
|
||||
|
||||
不做:
|
||||
|
||||
- 不做业务字段合法性判断。
|
||||
- 不执行 OPERA 模拟。
|
||||
- 不开发前端页面。
|
||||
|
||||
## 5. Checkpoint 2:AI 过渡层持久化
|
||||
|
||||
名称:`m002-cp02-ai-transition-persistence`
|
||||
|
||||
目标:
|
||||
|
||||
- 建立 AI 接收批次表和 AI 过渡表。
|
||||
- 保存 `source_message_id + ai_task_results[] + extraction_warnings[]`。
|
||||
- 实现系统生成幂等键,保证重复提交不重复创建记录。
|
||||
|
||||
建议范围:
|
||||
|
||||
- Flyway migration。
|
||||
- Entity、Mapper、Repository。
|
||||
- 批次幂等键生成。
|
||||
- item 幂等键生成。
|
||||
- `source_message_id` 存在性校验。
|
||||
- 保存 AI 原始 JSON 和常用物理列。
|
||||
|
||||
验收标准:
|
||||
|
||||
- 同一请求重复提交返回幂等重放,不重复插入。
|
||||
- 同一 `source_message_id` 不同请求体第一版返回 `409`。
|
||||
- 每个 item 保存 `array_index`、`source_event_index` 和 `execution_order`。
|
||||
- 保存 `ai_payload_json`,用户后续修改不得覆盖该字段。
|
||||
|
||||
不做:
|
||||
|
||||
- 不创建 OPERA 操作。
|
||||
- 不实现任务详情编辑。
|
||||
|
||||
## 6. Checkpoint 3:订单、任务和任务卡最小模型
|
||||
|
||||
名称:`m002-cp03-order-task-card-model`
|
||||
|
||||
目标:
|
||||
|
||||
- 建立订单、任务和任务卡表。
|
||||
- 将 AI 过渡记录映射成系统订单、任务和任务卡。
|
||||
- 完成主任务类型和任务卡类型映射。
|
||||
|
||||
建议范围:
|
||||
|
||||
- 订单状态枚举:`TEMPORARY`、`ACTIVE`、`ENDED`、`LOGIC_DELETED`。
|
||||
- 任务状态枚举:`PENDING_CONFIRM`、`READY`、`EXECUTING`、`FAILED`、`COMPLETED`。
|
||||
- 系统主任务类型枚举。
|
||||
- 任务卡类型枚举。
|
||||
- Message Notification 创建临时订单和只读任务卡。
|
||||
- Fallback / manual_review 创建临时订单和人工复核任务卡。
|
||||
|
||||
验收标准:
|
||||
|
||||
- New Booking 无业务号时创建临时订单。
|
||||
- Update / Cancel 可匹配订单时挂已有订单,不可匹配时挂临时订单。
|
||||
- Message Notification 挂临时订单,但 `queue_participation=false`。
|
||||
- 任务保存 AI 原始 `task_type`、系统主任务类型、任务卡类型和 subtype。
|
||||
- 任务初始状态符合数据模型设计。
|
||||
|
||||
不做:
|
||||
|
||||
- 不实现用户编辑确认。
|
||||
- 不实现 OPERA 模拟。
|
||||
|
||||
## 7. Checkpoint 4:订单挂靠与队列可处理状态
|
||||
|
||||
名称:`m002-cp04-order-queue-availability`
|
||||
|
||||
目标:
|
||||
|
||||
- 实现订单挂靠规则和同订单任务执行顺序。
|
||||
- 实现实时计算任务是否可处理。
|
||||
- 不落库 `BLOCKED` 状态。
|
||||
|
||||
建议范围:
|
||||
|
||||
- 按 `order_id + execution_order` 查询任务队列。
|
||||
- 前置参与队列任务未完成时,后续任务只读。
|
||||
- 前置参与队列任务为 `FAILED` 或 `COMPLETED` 时视为结束,不阻塞后续任务。
|
||||
- `queue_participation=false` 的任务不阻塞队列。
|
||||
- 数据库通过 `hotel_id + order_id + queue_participation + execution_order` 唯一约束兜底,服务层遇到并发队列序号冲突时重新取号重试。
|
||||
- 联动任务识别 `parent_source_event_index`、`linked_task_group_id`、`blocked_until_parent_completed`。
|
||||
- 第一版可先提供任务详情接口,返回实时可处理状态和只读原因,前端页面后续再定。
|
||||
|
||||
验收标准:
|
||||
|
||||
- 同一次 AI 返回多个任务时保留数组顺序。
|
||||
- 前置任务未完成时后续任务不能编辑、确认、执行或重试。
|
||||
- 前置任务为 `FAILED` 时后续任务不再被阻塞。
|
||||
- Message Notification 不阻塞其他任务,也不被其他任务阻塞。
|
||||
- 任务切换订单后按目标订单队列重新计算可处理状态。
|
||||
|
||||
不做:
|
||||
|
||||
- 不允许用户强制完成前置任务。
|
||||
- 不允许跳过失败 OPERA 操作。
|
||||
|
||||
## 8. Checkpoint 5:任务详情、编辑和确认 payload
|
||||
|
||||
名称:`m002-cp05-task-detail-confirmed-payload`
|
||||
|
||||
目标:
|
||||
|
||||
- 提供任务详情读取接口。
|
||||
- 支持用户编辑任务卡字段。
|
||||
- 用户确认后生成 `confirmed_payload_json`。
|
||||
|
||||
建议范围:
|
||||
|
||||
- 任务详情 Response 包含 AI 原始摘要、任务卡字段、可处理状态和阻塞原因。
|
||||
- 第一版任务卡字段矩阵写在代码 Provider 中,避免 Controller / Service 直接硬编码。
|
||||
- 保存 `draft_payload_json`。
|
||||
- 确认时生成 `confirmed_payload_json`。
|
||||
- 审计用户字段修改和确认。
|
||||
|
||||
验收标准:
|
||||
|
||||
- 不可处理任务详情只能查看,不能编辑或确认。
|
||||
- 可处理任务可以保存草稿。
|
||||
- 用户确认后任务进入 `READY`。
|
||||
- OPERA 参数不得从 `ai_payload_json` 读取。
|
||||
- 用户修改不覆盖 AI 原始 JSON。
|
||||
|
||||
不做:
|
||||
|
||||
- 不接真实 OPERA。
|
||||
- 不把 Excel 全量字段导入数据库。
|
||||
|
||||
## 9. Checkpoint 6:人工复核转换和订单迁移
|
||||
|
||||
名称:`m002-cp06-manual-review-conversion`
|
||||
|
||||
目标:
|
||||
|
||||
- 实现 Fallback / manual_review 的人工处理。
|
||||
- 支持转为 New / Update / Cancel。
|
||||
- 支持任务从临时订单迁移到已有订单。
|
||||
|
||||
建议范围:
|
||||
|
||||
- 转换类型接口。
|
||||
- 订单切换接口。
|
||||
- 临时订单逻辑删除。
|
||||
- 转换原因字段第一版允许为空,但必须记录审计。
|
||||
- 转为 `UPDATE_BOOKING` 或 `CANCEL_BOOKING` 时目标订单 ID 必填。
|
||||
- 审计转换、迁移和删除。
|
||||
|
||||
验收标准:
|
||||
|
||||
- 转为 `NEW_BOOKING` 时临时订单可继续保留;如果 AI 原始 `case_keys` 已有 Group Code 或 Confirmation No.,第一版可先以 `AI_CANDIDATE` 激活原临时订单。
|
||||
- 转为 `UPDATE_BOOKING` 或 `CANCEL_BOOKING` 时必须选择目标订单。
|
||||
- 原临时订单无有效任务后进入 `LOGIC_DELETED`。
|
||||
- 所有转换都记录前后快照;原因有则记录,没有则为空。
|
||||
|
||||
不做:
|
||||
|
||||
- 不允许绕过前置任务直接完成。
|
||||
- 不做 AI 业务合法性二次判断。
|
||||
|
||||
## 10. Checkpoint 7:OPERA 模拟操作与重试
|
||||
|
||||
名称:`m002-cp07-opera-simulation-results`
|
||||
|
||||
目标:
|
||||
|
||||
- 建立 OPERA 模拟逻辑操作和 attempt 记录。
|
||||
- 支持执行、失败、重试和结果展示。
|
||||
- 支持 New Booking 在必要时回填订单业务号。
|
||||
|
||||
建议范围:
|
||||
|
||||
- 从 `confirmed_payload_json` 生成模拟操作。
|
||||
- 每个任务可生成多条操作。
|
||||
- 每次执行或重试新增 attempt。
|
||||
- 失败任务进入 `FAILED`。
|
||||
- 全部必要操作成功后任务进入 `COMPLETED`。
|
||||
- 从 `business_key_candidates_json` 回填订单业务号。
|
||||
- 第一版先在订单表设计 `business_key_source`、`business_key_backfilled_at` 等字段,OPERA 模拟执行模块后续再写入。
|
||||
|
||||
验收标准:
|
||||
|
||||
- 未确认任务不能执行 OPERA 模拟。
|
||||
- 不可处理任务不能执行 OPERA 模拟。
|
||||
- 失败操作不能跳过。
|
||||
- 用户不能强制完成任务。
|
||||
- 重试不覆盖历史 attempt。
|
||||
- New Booking 无业务号时,模拟成功后可回填 Confirmation Number 或 Group Code 含义字段。
|
||||
|
||||
不做:
|
||||
|
||||
- 不接真实 OPERA 接口。
|
||||
- 不写死真实 OPERA 返回字段路径。
|
||||
|
||||
## 11. Checkpoint 8:审计、查询和收口
|
||||
|
||||
名称:`m002-cp08-audit-query-hardening`
|
||||
|
||||
目标:
|
||||
|
||||
- 补齐审计查询、列表筛选、安全收口和回归测试。
|
||||
|
||||
建议范围:
|
||||
|
||||
- 订单任务审计查询。
|
||||
- 任务列表基础筛选。
|
||||
- 订单详情下任务时间线。
|
||||
- 安全日志检查。
|
||||
- 关键接口集成测试。
|
||||
|
||||
验收标准:
|
||||
|
||||
- 能追溯 AI 接收、任务创建、订单挂靠、用户修改、确认、迁移、OPERA 模拟和重试。
|
||||
- 列表不返回完整 AI payload、邮件正文、附件 URL 或 Secret。
|
||||
- 所有关键路径有测试覆盖。
|
||||
- `./mvnw test` 通过,或明确说明环境问题。
|
||||
|
||||
## 12. 建议开发节奏
|
||||
|
||||
建议一次只做一个 checkpoint。每个 checkpoint 完成后:
|
||||
|
||||
- 先自查是否符合项目包结构和中文注释规范。
|
||||
- 运行相关测试。
|
||||
- 做 code review。
|
||||
- 再进入下一个 checkpoint。
|
||||
|
||||
如果实现过程中遇到以下情况,必须先暂停确认:
|
||||
|
||||
- 订单状态需要新增第五种。
|
||||
- 任务状态需要新增新状态。
|
||||
- OPERA 模拟结果字段需要写死真实路径。
|
||||
- Excel 字段矩阵需要从代码配置改成数据库配置。
|
||||
- 某个类不知道应该放在哪个包。
|
||||
- 需要调整已确认的 SuperAgent 接口契约。
|
||||
400
docs/project/requirements/M002-backend-data-model-design.md
Normal file
400
docs/project/requirements/M002-backend-data-model-design.md
Normal file
@@ -0,0 +1,400 @@
|
||||
# M002 Backend Data Model Design 后端数据模型设计
|
||||
|
||||
## 文档信息
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 文档版本 | 0.1 |
|
||||
| 日期 | 2026-07-07 |
|
||||
| 状态 | 后端数据模型草稿 |
|
||||
| 适用范围 | AI 过渡层、订单、任务、任务卡、审计和 OPERA 模拟结果 |
|
||||
| 主要读者 | 后端、数据库、测试、后续协作 agent |
|
||||
|
||||
## 1. 文档定位
|
||||
|
||||
本文定义 M002 第一阶段后端数据模型草案,用于支撑 SuperAgent 任务结果入站、订单挂靠、任务卡确认、队列顺序、审计和 OPERA 模拟结果。
|
||||
|
||||
本文不是最终建表 SQL。后续写代码前,应按本项目后端规范补充 Flyway migration、Entity 中文注释、Mapper、Repository、Service 和测试。
|
||||
|
||||
## 2. 设计原则
|
||||
|
||||
- 保留 AI 原始 JSON,不覆盖、不重写、不丢字段。
|
||||
- 用户确认后的数据写入 `confirmed_payload_json`,OPERA 模拟只读取确认后的 payload。
|
||||
- 高频查询、幂等、排序和状态机字段冗余为物理列。
|
||||
- 任务卡字段第一版先写在代码里,但必须通过低耦合 Provider 封装,后续可迁移为数据库配置。
|
||||
- `BLOCKED` 不作为任务持久状态,而是根据同订单前置任务是否完成实时计算。
|
||||
- 用户不允许强制完成任务。
|
||||
- 用户不能跳过失败的 OPERA 模拟操作。
|
||||
- 同订单队列可处理状态实时计算时,`FAILED` 和 `COMPLETED` 都视为前置任务已结束,不阻塞后续任务。
|
||||
- OPERA 当前是模拟结构,后续真实系统接入时通过 adapter 映射,不污染核心任务模型。
|
||||
|
||||
## 3. 枚举
|
||||
|
||||
### 3.1 订单状态
|
||||
|
||||
| 状态 | 中文说明 |
|
||||
| --- | --- |
|
||||
| `TEMPORARY` | 临时订单,用于 New Booking 未取得业务号、Fallback、Message Notification 或暂无法匹配订单的任务容器 |
|
||||
| `ACTIVE` | 有效订单,可承载可处理业务任务 |
|
||||
| `ENDED` | 已结束订单,例如已完成、已取消或业务生命周期结束;仍可查看历史 |
|
||||
| `LOGIC_DELETED` | 逻辑删除订单,主要用于临时订单迁移后废弃,不再承载新任务 |
|
||||
|
||||
### 3.2 任务状态
|
||||
|
||||
| 状态 | 中文说明 |
|
||||
| --- | --- |
|
||||
| `PENDING_CONFIRM` | 待用户确认订单归属和任务字段 |
|
||||
| `READY` | 已确认,等待执行 OPERA 模拟 |
|
||||
| `EXECUTING` | 正在执行 OPERA 模拟 |
|
||||
| `FAILED` | OPERA 模拟失败,必须重试或修正后再执行,不能跳过 |
|
||||
| `COMPLETED` | 任务已完成 |
|
||||
|
||||
说明:
|
||||
|
||||
- `Message Notification` 不参与执行队列,可在创建后直接进入 `COMPLETED` 或保持只读完成态。
|
||||
- `manual_review` / `Fallback` 默认进入 `PENDING_CONFIRM`,等待人工转换或处理。
|
||||
- 阻塞态通过查询同订单前置任务实时计算,不落 `BLOCKED` 状态。
|
||||
|
||||
### 3.3 系统主任务类型
|
||||
|
||||
| 类型 | 中文说明 |
|
||||
| --- | --- |
|
||||
| `NEW_BOOKING` | 新建订单任务 |
|
||||
| `UPDATE_BOOKING` | 更新订单任务,下面包含多种任务卡 |
|
||||
| `CANCEL_BOOKING` | 取消订单任务 |
|
||||
| `MANUAL_REVIEW` | 人工复核 / Fallback 任务 |
|
||||
| `INFORMATIONAL_MESSAGE` | 只读信息提醒任务,不参与执行队列 |
|
||||
|
||||
### 3.4 任务卡类型
|
||||
|
||||
第一版建议包含:
|
||||
|
||||
- `NEW_BOOKING`
|
||||
- `UPDATE_BOOKING`
|
||||
- `CANCEL_BOOKING`
|
||||
- `VOUCHER_RECEIVED`
|
||||
- `ROOMING_LIST`
|
||||
- `AMEND_GROUP_CODE`
|
||||
- `TRACE_RESERVATION_NOTES`
|
||||
- `TA_RECORDER`
|
||||
- `MESSAGE_NOTIFICATION`
|
||||
- `FALLBACK_REVIEW`
|
||||
|
||||
## 4. 表设计总览
|
||||
|
||||
| 表名 | 中文说明 |
|
||||
| --- | --- |
|
||||
| `workflow_reservation_ai_batch` | AI 任务结果接收批次表 |
|
||||
| `workflow_reservation_ai_transition` | AI 任务结果过渡表,一条 AI item 一行 |
|
||||
| `workflow_reservation_order` | 订单表 |
|
||||
| `workflow_reservation_task` | 任务表 |
|
||||
| `workflow_reservation_task_card` | 任务卡确认数据表 |
|
||||
| `workflow_reservation_audit_log` | 订单任务审计表 |
|
||||
| `workflow_reservation_opera_operation` | OPERA 模拟逻辑操作表 |
|
||||
| `workflow_reservation_opera_operation_attempt` | OPERA 模拟操作尝试记录表 |
|
||||
|
||||
表名前缀使用 `workflow_reservation`,表示当前属于 reservation 工作流,不放入平台中立 `platform` 模块。
|
||||
|
||||
## 5. AI 接收批次表
|
||||
|
||||
表名:`workflow_reservation_ai_batch`
|
||||
|
||||
| 字段 | 类型建议 | 中文说明 |
|
||||
| --- | --- | --- |
|
||||
| `id` | `BIGINT` | 批次 ID |
|
||||
| `hotel_id` | `VARCHAR(64)` | 酒店或业务上下文 |
|
||||
| `source_message_id` | `BIGINT` | 关联 SourceMessage |
|
||||
| `request_payload_sha256` | `CHAR(64)` | 原始请求体 SHA-256 |
|
||||
| `batch_idempotency_key` | `CHAR(64)` | 系统生成的批次幂等键 |
|
||||
| `client_id` | `VARCHAR(128)` | SuperAgent 调用方 ID |
|
||||
| `request_id` | `VARCHAR(128)` | 调用方请求 ID,可为空 |
|
||||
| `received_at` | `DATETIME(6)` | 接收时间 |
|
||||
| `item_count` | `INT` | AI item 数量 |
|
||||
| `extraction_warnings_json` | `LONGTEXT` | 抽取警告 JSON |
|
||||
| `created_at` / `updated_at` | `DATETIME(6)` | 创建和更新时间 |
|
||||
|
||||
索引建议:
|
||||
|
||||
- 唯一索引:`hotel_id + batch_idempotency_key`
|
||||
- 普通索引:`hotel_id + source_message_id`
|
||||
- 普通索引:`hotel_id + received_at`
|
||||
|
||||
## 6. AI 过渡表
|
||||
|
||||
表名:`workflow_reservation_ai_transition`
|
||||
|
||||
一条 `ai_task_results[]` item 对应一行。
|
||||
|
||||
| 字段 | 类型建议 | 中文说明 |
|
||||
| --- | --- | --- |
|
||||
| `id` | `BIGINT` | AI 过渡记录 ID |
|
||||
| `hotel_id` | `VARCHAR(64)` | 酒店或业务上下文 |
|
||||
| `batch_id` | `BIGINT` | 接收批次 ID |
|
||||
| `source_message_id` | `BIGINT` | 来源消息 ID |
|
||||
| `source_event_index` | `INT` | AI current 事件序号 |
|
||||
| `array_index` | `INT` | AI 返回列表中的顺序,建议从 1 开始 |
|
||||
| `execution_order` | `INT` | 映射到订单任务队列的初始顺序 |
|
||||
| `catalog_code` | `VARCHAR(32)` | Skill 目录代码 |
|
||||
| `skill_id` | `VARCHAR(128)` | Skill 标识 |
|
||||
| `result_type` | `VARCHAR(32)` | AI 结果类型 |
|
||||
| `ai_task_type` | `VARCHAR(64)` | AI 原始任务类型 |
|
||||
| `system_task_type` | `VARCHAR(64)` | 系统主任务类型 |
|
||||
| `task_card_type` | `VARCHAR(64)` | 任务卡类型 |
|
||||
| `task_subtype` | `VARCHAR(128)` | 业务动作 subtype |
|
||||
| `current_or_history` | `VARCHAR(32)` | 当前或历史标识 |
|
||||
| `group_code` | `VARCHAR(128)` | Group Code 候选 |
|
||||
| `confirmation_number` | `VARCHAR(128)` | Confirmation Number 候选 |
|
||||
| `item_payload_sha256` | `CHAR(64)` | 单个 item JSON 哈希 |
|
||||
| `item_idempotency_key` | `CHAR(64)` | 系统生成 item 幂等键 |
|
||||
| `manual_reason_code` | `VARCHAR(128)` | 人工复核原因码 |
|
||||
| `parent_source_event_index` | `INT` | 父任务事件序号 |
|
||||
| `linked_task_group_id` | `VARCHAR(128)` | 联动任务组 ID |
|
||||
| `blocked_until_parent_completed` | `TINYINT(1)` | 是否等待父任务完成 |
|
||||
| `ai_payload_json` | `LONGTEXT` | AI 原始 item JSON |
|
||||
| `case_keys_json` | `LONGTEXT` | 订单候选键 JSON |
|
||||
| `extracted_fields_json` | `LONGTEXT` | AI 业务字段 JSON |
|
||||
| `manual_review_json` | `LONGTEXT` | 人工复核 JSON |
|
||||
| `informational_message_json` | `LONGTEXT` | 信息提醒 JSON |
|
||||
| `attachments_json` | `LONGTEXT` | 附件 JSON |
|
||||
| `context_used_json` | `LONGTEXT` | 上下文 JSON |
|
||||
| `created_at` / `updated_at` | `DATETIME(6)` | 创建和更新时间 |
|
||||
|
||||
索引建议:
|
||||
|
||||
- 唯一索引:`hotel_id + item_idempotency_key`
|
||||
- 普通索引:`hotel_id + source_message_id + source_event_index`
|
||||
- 普通索引:`hotel_id + result_type + ai_task_type`
|
||||
- 普通索引:`hotel_id + group_code`
|
||||
- 普通索引:`hotel_id + confirmation_number`
|
||||
|
||||
## 7. 订单表
|
||||
|
||||
表名:`workflow_reservation_order`
|
||||
|
||||
| 字段 | 类型建议 | 中文说明 |
|
||||
| --- | --- | --- |
|
||||
| `id` | `BIGINT` | 系统内部订单 ID |
|
||||
| `hotel_id` | `VARCHAR(64)` | 酒店或业务上下文 |
|
||||
| `order_key_type` | `VARCHAR(32)` | 业务号类型:`GROUP_CODE`、`CONFIRMATION_NUMBER`、`TEMPORARY` |
|
||||
| `order_business_key` | `VARCHAR(128)` | 真实业务号 |
|
||||
| `active_business_key` | `VARCHAR(128)` | ACTIVE 订单唯一约束辅助键,ACTIVE 业务订单时等于真实业务号,其他状态为空 |
|
||||
| `temporary_order_code` | `VARCHAR(128)` | 临时订单展示编号 |
|
||||
| `order_status` | `VARCHAR(32)` | 订单状态 |
|
||||
| `business_key_source` | `VARCHAR(64)` | 业务号来源,例如 `AI_CANDIDATE`、`USER_CONFIRMED`、`OPERA_SIMULATION_RESULT` |
|
||||
| `business_key_backfilled_at` | `DATETIME(6)` | New Booking 成功后回填真实业务号的 UTC 时间 |
|
||||
| `display_name` | `VARCHAR(256)` | 前端展示名称 |
|
||||
| `source_message_id` | `BIGINT` | 首次创建该订单的来源消息 |
|
||||
| `created_from_task_id` | `BIGINT` | 首次创建该订单的任务 ID,可为空 |
|
||||
| `ended_at` | `DATETIME(6)` | 订单进入 ENDED 的时间 |
|
||||
| `logic_deleted_at` | `DATETIME(6)` | 逻辑删除时间 |
|
||||
| `logic_deleted_reason` | `VARCHAR(512)` | 逻辑删除原因 |
|
||||
| `version` | `BIGINT` | 乐观锁版本 |
|
||||
| `created_at` / `updated_at` | `DATETIME(6)` | 创建和更新时间 |
|
||||
|
||||
索引建议:
|
||||
|
||||
- 普通索引:`hotel_id + order_status + updated_at`
|
||||
- 普通索引:`hotel_id + order_key_type + order_business_key`
|
||||
- 唯一索引:`hotel_id + order_key_type + active_business_key`,用于保证同一 `hotel_id + GROUP_CODE` / `hotel_id + CONFIRMATION_NUMBER` 只能有一个 ACTIVE 订单
|
||||
- 唯一索引:`hotel_id + temporary_order_code`
|
||||
|
||||
说明:
|
||||
|
||||
- MySQL 第一版不依赖部分唯一索引;通过 `active_business_key` 在 ACTIVE 业务订单时写入真实业务号、非 ACTIVE 或临时订单为空,配合唯一索引保证同一业务号只能有一个 ACTIVE 订单。
|
||||
- `LOGIC_DELETED` 订单不得再挂新任务。
|
||||
|
||||
## 8. 任务表
|
||||
|
||||
表名:`workflow_reservation_task`
|
||||
|
||||
| 字段 | 类型建议 | 中文说明 |
|
||||
| --- | --- | --- |
|
||||
| `id` | `BIGINT` | 系统任务 ID |
|
||||
| `hotel_id` | `VARCHAR(64)` | 酒店或业务上下文 |
|
||||
| `order_id` | `BIGINT` | 当前挂靠订单 ID |
|
||||
| `source_message_id` | `BIGINT` | 来源消息 ID |
|
||||
| `ai_transition_id` | `BIGINT` | AI 过渡记录 ID |
|
||||
| `result_type` | `VARCHAR(32)` | AI 结果类型 |
|
||||
| `ai_task_type` | `VARCHAR(64)` | AI 原始任务类型 |
|
||||
| `system_task_type` | `VARCHAR(64)` | 系统主任务类型 |
|
||||
| `task_card_type` | `VARCHAR(64)` | 任务卡类型 |
|
||||
| `task_subtype` | `VARCHAR(128)` | 业务动作 subtype |
|
||||
| `task_status` | `VARCHAR(32)` | 任务状态 |
|
||||
| `queue_participation` | `TINYINT(1)` | 是否参与订单执行队列 |
|
||||
| `execution_order` | `INT` | 同订单执行顺序 |
|
||||
| `parent_task_id` | `BIGINT` | 父任务 ID,可为空 |
|
||||
| `parent_source_event_index` | `INT` | 父任务 source event index |
|
||||
| `linked_task_group_id` | `VARCHAR(128)` | 联动任务组 ID |
|
||||
| `blocked_until_parent_completed` | `TINYINT(1)` | 是否等待父任务完成 |
|
||||
| `last_failure_reason` | `VARCHAR(512)` | 最近失败原因摘要 |
|
||||
| `confirmed_at` | `DATETIME(6)` | 用户确认时间 |
|
||||
| `completed_at` | `DATETIME(6)` | 完成时间 |
|
||||
| `version` | `BIGINT` | 乐观锁版本 |
|
||||
| `created_at` / `updated_at` | `DATETIME(6)` | 创建和更新时间 |
|
||||
|
||||
索引建议:
|
||||
|
||||
- 普通索引:`hotel_id + order_id + queue_participation + execution_order`
|
||||
- 唯一索引:`hotel_id + order_id + queue_participation + execution_order`,用于防止并发创建任务时出现相同队列序号
|
||||
- 普通索引:`hotel_id + task_status + updated_at`
|
||||
- 普通索引:`hotel_id + source_message_id`
|
||||
- 普通索引:`hotel_id + ai_transition_id`
|
||||
|
||||
队列规则:
|
||||
|
||||
- `queue_participation=false` 的任务不阻塞队列,适用于 `Message Notification`。
|
||||
- 是否可编辑、可确认、可执行由服务层实时计算。
|
||||
- 当前任务前面存在未完成且参与队列的任务时,本任务只能查看。
|
||||
|
||||
## 9. 任务卡确认数据表
|
||||
|
||||
表名:`workflow_reservation_task_card`
|
||||
|
||||
| 字段 | 类型建议 | 中文说明 |
|
||||
| --- | --- | --- |
|
||||
| `id` | `BIGINT` | 任务卡 ID |
|
||||
| `hotel_id` | `VARCHAR(64)` | 酒店或业务上下文 |
|
||||
| `task_id` | `BIGINT` | 所属任务 |
|
||||
| `task_card_type` | `VARCHAR(64)` | 任务卡类型 |
|
||||
| `field_contract_version` | `VARCHAR(64)` | 字段契约版本,第一版可写 `code-v1` |
|
||||
| `ai_payload_json` | `LONGTEXT` | 任务卡使用的 AI 原始 JSON 快照 |
|
||||
| `draft_payload_json` | `LONGTEXT` | 用户编辑草稿,可为空 |
|
||||
| `confirmed_payload_json` | `LONGTEXT` | 用户确认后的最终 payload |
|
||||
| `confirmed_by` | `VARCHAR(128)` | 确认人 |
|
||||
| `confirmed_at` | `DATETIME(6)` | 确认时间 |
|
||||
| `created_at` / `updated_at` | `DATETIME(6)` | 创建和更新时间 |
|
||||
|
||||
索引建议:
|
||||
|
||||
- 唯一索引:`hotel_id + task_id`
|
||||
- 普通索引:`hotel_id + task_card_type`
|
||||
|
||||
说明:
|
||||
|
||||
- 第一版任务卡字段配置写在代码中,但通过 `TaskCardFieldDefinitionProvider` 之类的接口提供,避免 Controller / Service 直接依赖硬编码数组。
|
||||
- 后续如果改为数据库配置,只替换 Provider 实现,不改任务核心流程。
|
||||
|
||||
## 10. 审计表
|
||||
|
||||
表名:`workflow_reservation_audit_log`
|
||||
|
||||
| 字段 | 类型建议 | 中文说明 |
|
||||
| --- | --- | --- |
|
||||
| `id` | `BIGINT` | 审计 ID |
|
||||
| `hotel_id` | `VARCHAR(64)` | 酒店或业务上下文 |
|
||||
| `order_id` | `BIGINT` | 订单 ID,可为空 |
|
||||
| `task_id` | `BIGINT` | 任务 ID,可为空 |
|
||||
| `operation_id` | `BIGINT` | OPERA 模拟操作 ID,可为空 |
|
||||
| `actor_type` | `VARCHAR(32)` | 操作人类型,例如 `SYSTEM`、`USER`、`SUPERAGENT` |
|
||||
| `actor_id` | `VARCHAR(128)` | 操作人标识 |
|
||||
| `action` | `VARCHAR(128)` | 操作类型 |
|
||||
| `reason` | `VARCHAR(512)` | 操作原因 |
|
||||
| `before_snapshot_json` | `LONGTEXT` | 变更前摘要 JSON |
|
||||
| `after_snapshot_json` | `LONGTEXT` | 变更后摘要 JSON |
|
||||
| `occurred_at` | `DATETIME(6)` | 发生时间 |
|
||||
| `created_at` | `DATETIME(6)` | 记录创建时间 |
|
||||
|
||||
索引建议:
|
||||
|
||||
- 普通索引:`hotel_id + order_id + occurred_at`
|
||||
- 普通索引:`hotel_id + task_id + occurred_at`
|
||||
- 普通索引:`hotel_id + action + occurred_at`
|
||||
|
||||
审计不得保存 Secret、Token、完整邮件正文、真实附件 URL 或不必要的个人敏感信息。
|
||||
|
||||
## 11. OPERA 模拟逻辑操作表
|
||||
|
||||
表名:`workflow_reservation_opera_operation`
|
||||
|
||||
一条任务可能生成多条 OPERA 模拟逻辑操作。
|
||||
|
||||
| 字段 | 类型建议 | 中文说明 |
|
||||
| --- | --- | --- |
|
||||
| `id` | `BIGINT` | OPERA 模拟操作 ID |
|
||||
| `hotel_id` | `VARCHAR(64)` | 酒店或业务上下文 |
|
||||
| `order_id` | `BIGINT` | 订单 ID |
|
||||
| `task_id` | `BIGINT` | 任务 ID |
|
||||
| `operation_type` | `VARCHAR(128)` | 操作类型,例如创建预订、更新字段、取消订单 |
|
||||
| `operation_status` | `VARCHAR(32)` | 操作状态:`PENDING`、`EXECUTING`、`SUCCESS`、`FAILED` |
|
||||
| `operation_order` | `INT` | 同任务下操作顺序 |
|
||||
| `confirmed_payload_json` | `LONGTEXT` | 生成该操作时使用的确认 payload 快照 |
|
||||
| `business_key_candidates_json` | `LONGTEXT` | 从模拟结果解析出的订单业务号候选 |
|
||||
| `last_failure_reason` | `VARCHAR(512)` | 最近失败原因 |
|
||||
| `retry_count` | `INT` | 已重试次数 |
|
||||
| `created_at` / `updated_at` | `DATETIME(6)` | 创建和更新时间 |
|
||||
|
||||
索引建议:
|
||||
|
||||
- 普通索引:`hotel_id + task_id + operation_order`
|
||||
- 普通索引:`hotel_id + operation_status + updated_at`
|
||||
|
||||
## 12. OPERA 模拟尝试记录表
|
||||
|
||||
表名:`workflow_reservation_opera_operation_attempt`
|
||||
|
||||
每次执行或重试都新增一条 attempt,不能覆盖历史。
|
||||
|
||||
| 字段 | 类型建议 | 中文说明 |
|
||||
| --- | --- | --- |
|
||||
| `id` | `BIGINT` | 尝试记录 ID |
|
||||
| `hotel_id` | `VARCHAR(64)` | 酒店或业务上下文 |
|
||||
| `operation_id` | `BIGINT` | 所属逻辑操作 |
|
||||
| `task_id` | `BIGINT` | 所属任务 |
|
||||
| `attempt_no` | `INT` | 第几次尝试,从 1 开始 |
|
||||
| `attempt_status` | `VARCHAR(32)` | 尝试状态:`SUCCESS`、`FAILED` |
|
||||
| `request_payload_json` | `LONGTEXT` | 本次模拟请求 payload |
|
||||
| `response_payload_json` | `LONGTEXT` | 本次模拟响应 payload |
|
||||
| `business_key_candidates_json` | `LONGTEXT` | 本次响应中的业务号候选 |
|
||||
| `failure_reason` | `VARCHAR(512)` | 失败原因 |
|
||||
| `started_at` | `DATETIME(6)` | 开始时间 |
|
||||
| `finished_at` | `DATETIME(6)` | 结束时间 |
|
||||
| `created_at` | `DATETIME(6)` | 记录创建时间 |
|
||||
|
||||
索引建议:
|
||||
|
||||
- 唯一索引:`hotel_id + operation_id + attempt_no`
|
||||
- 普通索引:`hotel_id + task_id + created_at`
|
||||
|
||||
规则:
|
||||
|
||||
- 用户不能跳过失败的 OPERA 模拟操作。
|
||||
- 失败后任务进入 `FAILED`,只能通过修正 payload 后重试或重新执行使其成功。
|
||||
- 不允许用户强制把失败任务改成 `COMPLETED`。
|
||||
- 后续真实 OPERA 接入时,应通过 adapter 把真实响应映射到 `response_payload_json` 和 `business_key_candidates_json`。
|
||||
|
||||
## 13. 订单业务号回填
|
||||
|
||||
只有 `NEW_BOOKING` 且 `confirmed_payload_json` 没有可用业务号时,才从 OPERA 模拟成功结果回填订单业务号。
|
||||
|
||||
回填来源暂定为 `business_key_candidates_json`,示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"key_type": "CONFIRMATION_NUMBER",
|
||||
"business_key": "CNF123456",
|
||||
"source": "OPERA_SIMULATION_RESULT",
|
||||
"raw_path": "reserved.for.future.real.opera.path"
|
||||
}
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
- 当前没有真实 OPERA 返回样例,`raw_path` 只能预留。
|
||||
- FIT Reservation 回填 `CONFIRMATION_NUMBER`。
|
||||
- Group / Block / Allotment 回填 `GROUP_CODE` 或后续确认的对应业务号类型。
|
||||
|
||||
## 14. 第一版不落库的内容
|
||||
|
||||
以下内容第一版不建议单独建表:
|
||||
|
||||
- 任务卡字段矩阵配置:先写在代码 Provider 中。
|
||||
- 任务阻塞状态:实时计算,不落 `BLOCKED`。
|
||||
- OPERA 真实接口字段映射:后续真实系统接入后在 adapter 层补充。
|
||||
- 全量 Excel 字段路径:引用 `任务卡展示编辑矩阵.xlsx`,不手抄成数据库。
|
||||
|
||||
## 15. 待确认问题
|
||||
|
||||
- `ENDED` 是否仅表示取消完成,还是也包含正常完成后的历史订单。
|
||||
- 临时订单逻辑删除前是否需要保留空订单一段时间。
|
||||
- OPERA 真实响应字段出现后,是否需要新增稳定字段而不是只放 JSON。
|
||||
- 任务卡字段代码 Provider 的具体类名和包路径,后续实现时按项目规范确认。
|
||||
334
docs/project/requirements/M002-order-task-workflow-v1.md
Normal file
334
docs/project/requirements/M002-order-task-workflow-v1.md
Normal file
@@ -0,0 +1,334 @@
|
||||
# M002 Order Task Workflow 订单任务主流程 V1
|
||||
|
||||
## 文档信息
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 文档版本 | 0.1 |
|
||||
| 日期 | 2026-07-06 |
|
||||
| 状态 | 第一版流程草稿 |
|
||||
| 适用范围 | SourceMessage 之后的 SuperAgent 抽取、订单挂靠、任务处理、OPERA/OHIP 模拟操作主流程 |
|
||||
| 主要读者 | 产品、后端、前端、测试、后续协作 agent |
|
||||
|
||||
## 1. 文档定位
|
||||
|
||||
本文记录 TH Hotel 当前确认的订单任务主流程第一版理解,用于承接已经完成的
|
||||
`SourceMessage Inbox` 能力,并为后续 PRD、接口契约、数据模型和实现 checkpoint 提供
|
||||
统一业务语义。
|
||||
|
||||
本文只沉淀流程和边界,不代表已经开始实现代码。后续进入开发前,仍需要补充具体任务字段、
|
||||
SuperAgent 创建任务接口契约、前端页面范围、数据库模型和验收标准。
|
||||
|
||||
## 2. 已确认结论
|
||||
|
||||
- AgentBus 是当前原始消息起点,后续也可能增加其他入口。
|
||||
- AgentBus 只负责原始来源事实进入本系统,当前已经通过 `SourceMessage Inbox` 保存。
|
||||
- SuperAgent 是黑盒抽取能力,本系统不关心它内部如何抽取。
|
||||
- SuperAgent 不直连本系统数据库,只能通过本系统后端接口查询已有订单和任务上下文。
|
||||
- SuperAgent 抽取成功后,通过调用本系统后端接口创建一个或多个任务。
|
||||
- SuperAgent 告知的任务类型是本系统创建任务的依据,本系统暂时不做业务合法性判断。
|
||||
- 本系统只做接口鉴权、基础 JSON 可解析性、幂等键、必要技术字段等技术校验。
|
||||
- 任务必须挂靠到订单下,异常任务也需要先创建临时订单作为处理容器。
|
||||
- 同一次 SuperAgent 调用如果返回多个任务,必须按返回 JSON 列表顺序确定任务执行顺序。
|
||||
- 同一个订单下,前一个任务未完成时,后续任务只能查看,不能编辑、确认或执行模拟操作。
|
||||
- 用户在任务详情页可以查看、修改字段内容,并确认订单归属。
|
||||
- 用户确认字段和订单关系后,才能执行 OPERA/OHIP 模拟操作。
|
||||
- 当前 OHIP/OPERA 不接真实接口,只做模拟操作。
|
||||
- 所有任务类型转换、订单切换、临时订单逻辑删除都必须记录审计和原因。
|
||||
|
||||
## 3. 总体流程
|
||||
|
||||
```text
|
||||
AgentBus / 未来其他入口
|
||||
→ SourceMessage Inbox 记录原始来源事实
|
||||
→ SuperAgent 读取或处理原始来源数据
|
||||
→ SuperAgent 抽取结构化 JSON
|
||||
→ SuperAgent 通过本系统后端接口查询已有订单和任务上下文
|
||||
→ SuperAgent 调用本系统接口创建一个或多个任务
|
||||
→ 本系统按任务类型和返回顺序创建任务并挂靠订单
|
||||
→ 用户在任务详情页查看、修改字段、确认订单归属
|
||||
→ 用户确认后执行 OPERA/OHIP 模拟操作
|
||||
→ 任务完成后,同订单下后续任务解锁处理
|
||||
```
|
||||
|
||||
中文说明:
|
||||
|
||||
- `SourceMessage Inbox` 是来源事实层,不表达订单、任务或业务结论。
|
||||
- SuperAgent 负责抽取并告知任务类型,但不直接改变本系统最终业务状态。
|
||||
- Order / Task 是本系统后续业务核心,本系统必须掌握任务顺序、可处理状态、审计和模拟操作结果。
|
||||
|
||||
## 4. 与 M001 SourceMessage 的关系
|
||||
|
||||
已完成的 M001 只覆盖以下能力:
|
||||
|
||||
```text
|
||||
AgentBus 原始消息
|
||||
→ SourceMessage Inbox 落库
|
||||
→ 查询安全摘要
|
||||
→ 受控读取原文
|
||||
→ 记录原文读取审计
|
||||
```
|
||||
|
||||
M001 不做以下事情:
|
||||
|
||||
- 不创建订单。
|
||||
- 不创建任务。
|
||||
- 不调用 SuperAgent。
|
||||
- 不判断任务类型。
|
||||
- 不执行 OPERA/OHIP 模拟操作。
|
||||
- 不自动 ACK、回复客户或写业务结果。
|
||||
|
||||
因此,本文流程和当前 SourceMessage 代码没有冲突。SourceMessage 是后续订单任务流程的上游来源事实。
|
||||
|
||||
## 5. 核心角色与职责边界
|
||||
|
||||
| 模块或外部系统 | 职责 | 不负责 |
|
||||
| --- | --- | --- |
|
||||
| AgentBus | 接收邮件等外部渠道消息,并把原始 payload 推送给本系统 | 不做 AI 抽取,不创建任务,不调用业务写接口 |
|
||||
| SourceMessage Inbox | 保存原始来源事实、幂等、查询安全摘要、受控读取原文 | 不表达订单归属,不表达任务类型,不表达业务合法性 |
|
||||
| SuperAgent | 抽取结构化 JSON,判断任务类型,调用本系统后端接口创建任务 | 不直连数据库,不绕过本系统权限和审计,不直接执行 OPERA/OHIP |
|
||||
| Order | 承载任务队列、订单号、临时订单状态和业务订单关系 | 不保存 SuperAgent 外部协议细节 |
|
||||
| Task | 承载任务类型、抽取字段、用户确认字段、处理状态和执行顺序 | 不直接替代订单,不直接保存原始邮件全文 |
|
||||
| Operation Simulation | 记录用户确认后的 OPERA/OHIP 模拟操作、结果和重试 | 当前不调用真实 OHIP/OPERA 接口 |
|
||||
|
||||
## 6. SuperAgent 任务创建边界
|
||||
|
||||
SuperAgent 创建任务时,本系统只做技术接收校验,不做业务合法性判断。
|
||||
|
||||
技术校验包括:
|
||||
|
||||
- 接口鉴权和调用方身份校验。
|
||||
- 请求 JSON 可解析。
|
||||
- 幂等键或批次标识存在。
|
||||
- 任务列表结构可识别。
|
||||
- 任务类型是本系统已经约定的稳定代码。
|
||||
- 任务列表顺序可保留。
|
||||
|
||||
暂时不做的业务判断包括:
|
||||
|
||||
- 不判断任务是否应该是 `NEW_BOOKING`。
|
||||
- 不判断任务是否应该是 `UPDATE_BOOKING`。
|
||||
- 不判断任务是否应该是 `CANCEL_BOOKING`。
|
||||
- 不根据字段缺失自动改成异常任务。
|
||||
- 不判断 `CANCEL_BOOKING` 前是否真的存在已完成的 `NEW_BOOKING`。
|
||||
- 不判断房型、日期、金额、订单号等字段是否业务合理。
|
||||
|
||||
如果 SuperAgent 告知是异常任务,本系统就按异常任务创建。如果 SuperAgent 告知是其他已知任务类型,本系统就按该类型创建。
|
||||
|
||||
## 7. 订单模型第一版理解
|
||||
|
||||
订单应至少区分内部身份、临时展示编号和真实业务订单号。
|
||||
|
||||
| 概念 | 中文说明 |
|
||||
| --- | --- |
|
||||
| `orderId` | 本系统内部订单 ID,永远存在,用于任务挂靠和内部引用 |
|
||||
| `temporaryOrderCode` | 临时订单编号或前端展示编号,用于还没有明确真实订单号的场景 |
|
||||
| `businessOrderNo` | 真实业务订单号,可能来自 SuperAgent 抽取结果、用户确认字段或后续模拟操作回填 |
|
||||
| `orderStatus` | 订单状态,例如临时、有效、逻辑删除等 |
|
||||
| `deletedReason` | 逻辑删除原因,主要用于异常任务转移后删除原临时订单 |
|
||||
|
||||
`NEW_BOOKING` 任务不一定都需要等待 OPERA 模拟创建后才获得真实订单号。系统应优先查看用户确认后的字段中是否已有订单号:
|
||||
|
||||
- 如果确认字段中已有订单号,则优先使用该订单号作为 `businessOrderNo`。
|
||||
- 如果确认字段中没有订单号,则先使用内部订单 ID 或临时编号追踪,后续如果模拟操作返回真实订单号再回填。
|
||||
|
||||
## 8. 任务模型第一版理解
|
||||
|
||||
任务至少需要保存 SuperAgent 原始抽取内容和用户确认后的内容。
|
||||
|
||||
| 概念 | 中文说明 |
|
||||
| --- | --- |
|
||||
| `taskId` | 本系统内部任务 ID |
|
||||
| `orderId` | 当前挂靠订单 ID |
|
||||
| `taskType` | 任务类型,由 SuperAgent 或后续人工转换确定 |
|
||||
| `taskStatus` | 任务状态,用于控制是否可编辑、可确认、可执行 |
|
||||
| `batchId` | SuperAgent 创建任务批次 ID 或调用 ID |
|
||||
| `batchItemIndex` | 同一次 SuperAgent 返回列表中的顺序,从 0 或 1 开始需后续统一 |
|
||||
| `orderSequence` | 订单下的任务执行顺序 |
|
||||
| `extractedJson` | SuperAgent 原始抽取 JSON,不应被用户编辑覆盖 |
|
||||
| `confirmedJson` | 用户修改并确认后的 JSON,用于后续模拟操作 |
|
||||
| `sourceMessageId` | 关联 SourceMessage ID,便于追溯原始邮件或来源消息 |
|
||||
|
||||
任务类型当前确认:
|
||||
|
||||
- `NEW_BOOKING`:新建订单任务。
|
||||
- `UPDATE_BOOKING`:更新订单任务。后续可按字段组在前端展示不同卡片。
|
||||
- `CANCEL_BOOKING`:取消订单任务。
|
||||
- `EXCEPTION`:异常任务,表示 SuperAgent 无法判断属于前三类。
|
||||
|
||||
关于“任务大致 5 种”的表述,当前只确认以上 4 类。后续新增类型以具体任务分类和字段定义为准。
|
||||
|
||||
## 9. 任务顺序与可处理状态
|
||||
|
||||
订单下的任务必须按顺序处理。
|
||||
|
||||
排序规则第一版:
|
||||
|
||||
```text
|
||||
orderId + orderSequence
|
||||
```
|
||||
|
||||
同一次 SuperAgent 调用创建多个任务时:
|
||||
|
||||
- 必须保留 SuperAgent 返回 JSON 列表中的任务顺序。
|
||||
- 同一个批次里,列表前面的任务优先执行。
|
||||
- 不能只依赖创建时间排序,因为同批次任务时间可能完全一样。
|
||||
|
||||
后续任务的可处理规则:
|
||||
|
||||
- 当前面存在未完成任务时,后续任务只能查看。
|
||||
- 后续任务不能编辑字段。
|
||||
- 后续任务不能确认订单关系。
|
||||
- 后续任务不能执行 OPERA/OHIP 模拟操作。
|
||||
- 后续任务不能重试模拟操作。
|
||||
|
||||
任务切换订单后:
|
||||
|
||||
- 必须记录操作人、原订单、新订单、原因和时间。
|
||||
- 任务进入目标订单队列后,需要按目标订单任务队列规则重新判断是否可处理。
|
||||
- 如果目标订单前面已有未完成任务,该任务切过去后也只能查看。
|
||||
|
||||
## 10. Task Detail 行为
|
||||
|
||||
任务详情页不是只读确认页,而是用户处理任务的主要工作台。
|
||||
|
||||
任务可处理时,用户可以:
|
||||
|
||||
- 查看 SuperAgent 原始抽取结果。
|
||||
- 查看关联 SourceMessage 的安全摘要或受控原文入口。
|
||||
- 修改字段内容。
|
||||
- 确认订单归属。
|
||||
- 对异常任务选择转换目标类型。
|
||||
- 输入转换、切换或删除原因。
|
||||
- 确认后触发 OPERA/OHIP 模拟操作。
|
||||
- 查看每条模拟操作结果。
|
||||
- 对失败或允许重试的模拟操作发起重试。
|
||||
|
||||
任务不可处理时,用户只能查看:
|
||||
|
||||
- 任务基础信息。
|
||||
- 当前挂靠订单。
|
||||
- 抽取字段和已确认字段。
|
||||
- 阻塞原因,例如“同订单下前置任务未完成”。
|
||||
- 前置任务信息或跳转入口。
|
||||
|
||||
## 11. 异常任务处理流程
|
||||
|
||||
异常任务也必须挂靠订单。创建异常任务时,系统创建一个新的临时订单,并将异常任务挂靠到该临时订单。
|
||||
|
||||
```text
|
||||
SuperAgent 创建 EXCEPTION 任务
|
||||
→ 系统创建临时订单
|
||||
→ 异常任务挂靠临时订单
|
||||
→ 用户在任务详情页处理异常任务
|
||||
→ 用户选择转为 NEW_BOOKING / UPDATE_BOOKING / CANCEL_BOOKING
|
||||
→ 用户填写原因并确认
|
||||
→ 系统写审计
|
||||
```
|
||||
|
||||
### 11.1 转为 NEW_BOOKING
|
||||
|
||||
- 临时订单继续保留。
|
||||
- 任务类型从 `EXCEPTION` 改为 `NEW_BOOKING`。
|
||||
- 用户可以修改并确认字段。
|
||||
- 系统优先查看确认字段中的订单号是否有值。
|
||||
- 如果订单号有值,则将该值作为真实业务订单号。
|
||||
- 如果订单号无值,则继续使用临时编号追踪,后续模拟操作如返回真实订单号再回填。
|
||||
- 必须记录任务类型变更审计和原因。
|
||||
|
||||
### 11.2 转为 UPDATE_BOOKING
|
||||
|
||||
- 用户选择一个已有订单。
|
||||
- 任务类型从 `EXCEPTION` 改为 `UPDATE_BOOKING`。
|
||||
- 任务从临时订单切换到目标订单。
|
||||
- 原临时订单逻辑删除。
|
||||
- 必须记录任务类型变更、订单关系变更、临时订单逻辑删除审计和原因。
|
||||
- 切换后必须受目标订单任务队列顺序约束。
|
||||
|
||||
### 11.3 转为 CANCEL_BOOKING
|
||||
|
||||
- 用户选择一个已有订单。
|
||||
- 任务类型从 `EXCEPTION` 改为 `CANCEL_BOOKING`。
|
||||
- 任务从临时订单切换到目标订单。
|
||||
- 原临时订单逻辑删除。
|
||||
- 必须记录任务类型变更、订单关系变更、临时订单逻辑删除审计和原因。
|
||||
- 切换后必须受目标订单任务队列顺序约束。
|
||||
|
||||
## 12. OPERA/OHIP 模拟操作
|
||||
|
||||
当前阶段没有真实 OHIP/OPERA 接口,只做模拟操作。
|
||||
|
||||
模拟操作第一版规则:
|
||||
|
||||
- 只有当前订单下可处理的任务才能执行模拟操作。
|
||||
- 执行前必须完成字段修改和订单关系确认。
|
||||
- 一个任务可能生成多条模拟操作。
|
||||
- 任务详情页需要展示每条模拟操作的结果。
|
||||
- 每条模拟操作应有独立状态、失败原因、重试次数和最近执行时间。
|
||||
- 重试必须可追溯,不能覆盖历史执行结果。
|
||||
- 任务是否完成,需要根据该任务要求的模拟操作是否全部达到完成条件判断。
|
||||
|
||||
模拟操作的具体类型、字段、完成条件和重试限制后续另行定义。
|
||||
|
||||
## 13. 审计要求
|
||||
|
||||
以下行为必须有审计:
|
||||
|
||||
- SuperAgent 创建任务批次。
|
||||
- 同批次内每个任务的创建顺序。
|
||||
- 用户修改任务字段。
|
||||
- 用户确认订单关系。
|
||||
- 任务类型转换。
|
||||
- 任务切换订单。
|
||||
- 临时订单逻辑删除。
|
||||
- OPERA/OHIP 模拟操作执行。
|
||||
- 模拟操作重试。
|
||||
|
||||
审计至少应包含:
|
||||
|
||||
| 字段 | 中文说明 |
|
||||
| --- | --- |
|
||||
| `actor` | 操作人或系统调用方 |
|
||||
| `action` | 操作类型 |
|
||||
| `reason` | 用户填写或系统记录的原因 |
|
||||
| `beforeSnapshot` | 变更前摘要 |
|
||||
| `afterSnapshot` | 变更后摘要 |
|
||||
| `occurredAt` | 发生时间 |
|
||||
|
||||
审计中不得记录 Secret、Token、完整邮件正文、附件 URL 或不必要的个人敏感信息。
|
||||
|
||||
## 14. 暂不包含范围
|
||||
|
||||
第一版流程文档暂不定义:
|
||||
|
||||
- 具体 SuperAgent 创建任务接口 JSON Schema。
|
||||
- 具体订单表、任务表、操作表结构。
|
||||
- 具体前端页面布局。
|
||||
- 具体任务字段和卡片展示规则。
|
||||
- 真实 OHIP/OPERA 接口调用。
|
||||
- SuperAgent 内部 prompt、skill 或抽取实现。
|
||||
- 业务字段合法性判断规则。
|
||||
- 任务类型之外的自动分类逻辑。
|
||||
|
||||
## 15. 后续建议 checkpoint
|
||||
|
||||
建议后续按以下顺序拆分,不一次性做完:
|
||||
|
||||
1. 定义 SuperAgent 调本系统创建任务接口契约。
|
||||
2. 定义 Order / Task / Task Audit / Operation Simulation 的最小数据模型。
|
||||
3. 实现任务入站创建、幂等、批次顺序和订单挂靠。
|
||||
4. 实现任务详情读取、字段编辑和订单关系确认。
|
||||
5. 实现异常任务转换、订单切换和临时订单逻辑删除。
|
||||
6. 实现 OPERA/OHIP 模拟操作结果和重试机制。
|
||||
7. 再根据前端页面范围实现列表、详情和队列状态展示。
|
||||
|
||||
## 16. 待确认问题
|
||||
|
||||
- SuperAgent 创建任务接口的正式 JSON 格式是什么。
|
||||
- SuperAgent 任务批次 ID 和每个任务 item 的幂等键由谁生成。
|
||||
- `batchItemIndex` 从 0 开始还是从 1 开始。
|
||||
- 订单号字段在不同任务类型的 `confirmedJson` 中具体叫什么。
|
||||
- 任务状态机需要哪些稳定状态。
|
||||
- 模拟操作的完成条件和失败后是否允许跳过。
|
||||
- 任务完成是否允许人工强制完成,若允许需要什么权限和审计。
|
||||
- 第五种任务类型是否存在,若存在具体业务含义是什么。
|
||||
500
docs/project/requirements/M002-order-task-workflow-v2.md
Normal file
500
docs/project/requirements/M002-order-task-workflow-v2.md
Normal file
@@ -0,0 +1,500 @@
|
||||
# M002 Order Task Workflow 订单任务主流程 V2
|
||||
|
||||
## 文档信息
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 文档版本 | 0.2 |
|
||||
| 日期 | 2026-07-07 |
|
||||
| 状态 | 第二版需求草稿 |
|
||||
| 适用范围 | SourceMessage 之后的 AI 过渡层、订单挂靠、任务卡、人工确认、OPERA 模拟操作主流程 |
|
||||
| 主要读者 | 产品、后端、前端、测试、后续协作 agent |
|
||||
|
||||
## 1. 文档定位
|
||||
|
||||
本文是 `M002-order-task-workflow-v1.md` 的第二版修正,目标是把本项目已经讨论确认的订单任务主流程,与 2026-07-06 导入的 AI 任务卡契约对齐。
|
||||
|
||||
本文只定义业务边界、数据语义和后续实现约束,不代表已经开始写代码。后续开发前仍需要拆分 checkpoint,并补充接口契约、表结构、状态机、前端页面和测试验收标准。
|
||||
|
||||
## 2. 本版核心修正
|
||||
|
||||
相对 V1,本版有以下修正:
|
||||
|
||||
- 增加 `AI 过渡层`:系统必须先保存 AI 原始输出,再生成订单、任务和任务卡。
|
||||
- 不再使用 `EXCEPTION` 作为底层结果类型,AI 第一版结果类型统一以 `normal_task`、`manual_review`、`informational_message` 为准。
|
||||
- 系统主任务类型收敛为 `NEW_BOOKING`、`UPDATE_BOOKING`、`CANCEL_BOOKING`、`MANUAL_REVIEW`,另保留 `INFORMATIONAL_MESSAGE` 作为不参与执行队列的只读提醒任务。
|
||||
- 除 `New Booking`、`Cancel Booking`、`Fallback/manual_review` 外,其他业务处理类卡片原则上都归到 `UPDATE_BOOKING` 下的不同任务卡。
|
||||
- `Message Notification` 也挂到临时订单下面,便于归档和详情查看,但不参与订单任务执行队列,不阻塞其他任务,也不被其他任务阻塞。
|
||||
- 任务卡字段以 `任务卡展示编辑矩阵.xlsx` 为权威来源,不在代码里随意扩展或重命名字段路径。
|
||||
- 系统必须同时保存 AI 原始 `task_type`、系统主任务类型、任务卡类型和业务动作 subtype。
|
||||
- `ai_payload_json` 与 `confirmed_payload_json` 必须分离。OPERA 模拟只能读取用户确认后的 `confirmed_payload_json`。
|
||||
- 订单业务号候选字段和 OPERA 模拟回填边界需要明确记录,但 OPERA 返回 JSON 字段名目前未知,不能写死。
|
||||
|
||||
## 3. 权威输入资料
|
||||
|
||||
本版需求参考以下资料:
|
||||
|
||||
| 资料 | 作用 |
|
||||
| --- | --- |
|
||||
| `docs/project/requirements/M001-source-message-inbox-prd.md` | 上游 SourceMessage Inbox 边界 |
|
||||
| `docs/project/requirements/M002-order-task-workflow-v1.md` | 第一版整体业务流程 |
|
||||
| `docs/import/20260706/开发AI先读_工作顺序.md` | AI 过渡表、任务卡、确认 payload 和 OPERA 写入工作顺序 |
|
||||
| `docs/import/20260706/AI输出参数并集字典.xlsx` | AI 输出字段路径、字段含义、建议存储方式和索引建议 |
|
||||
| `docs/import/20260706/任务卡展示编辑矩阵.xlsx` | 任务卡字段展示、编辑、校验和 OPERA 写入约束 |
|
||||
| `docs/import/20260706/0630AI_副本 2/01_main_agent_prompt.md` | Main Agent 输出职责和聚合 JSON 结构 |
|
||||
| `docs/import/20260706/0630AI_副本 2/02_agent_workflow.md` | AI 侧事件拆分、Skill 调用和结果聚合流程 |
|
||||
| `docs/import/20260706/0630AI_副本 2/03_skill_catalog.md` | Skill 目录、结果类型、任务类型和统一输出字段 |
|
||||
| `docs/import/20260706/0630AI_副本 2/skill/S01-S08*.md` | 各业务任务卡的抽取规则和边界 |
|
||||
| `docs/import/20260706/0630AI_副本 2/references/qbd_liantai_email_table_rules.md` | QBD / LianTai 表格邮件拆分和证据规则 |
|
||||
| `docs/import/20260706/0630AI_副本 2/skill/*/references/rate_code_rules.md` | Rate Code 判断规则 |
|
||||
| `docs/import/20260706/0630AI_副本 2/skill/*/references/room_type_mapping_rules.md` | 房型映射规则 |
|
||||
|
||||
说明:`开发AI先读_工作顺序.md` 中提到的 `AI过渡表开发契约_README.md` 和 `AI过渡表开发契约_两张样例表.xlsx` 在当前导入目录下未找到同名文件。当前以已经导入的两张独立 Excel 作为字段和任务卡矩阵来源。
|
||||
|
||||
## 4. 总体流程
|
||||
|
||||
```text
|
||||
AgentBus / 未来其他入口
|
||||
→ SourceMessage Inbox 记录原始来源事实
|
||||
→ SuperAgent / Main Agent 读取 SourceMessage 并拆分 current 事件
|
||||
→ 对每个事件调用对应 Skill
|
||||
→ 聚合输出 source_message_id + ai_task_results[] + extraction_warnings[]
|
||||
→ 本系统接收 AI 结果并写入 AI 过渡层
|
||||
→ 本系统根据 result_type + task_type + task_subtype 生成订单、任务和任务卡
|
||||
→ 用户在任务详情页查看、修改字段、确认订单归属
|
||||
→ 系统生成 confirmed_payload_json
|
||||
→ 用户触发 OPERA 模拟操作
|
||||
→ 系统保存每条模拟操作结果、失败原因和重试记录
|
||||
```
|
||||
|
||||
中文说明:
|
||||
|
||||
- `SourceMessage Inbox` 是来源事实层,不表达订单、任务或业务结论。
|
||||
- AI 只输出 JSON,不直接写数据库、不直接创建真实任务卡、不直接写 OPERA。
|
||||
- 本系统负责保存 AI 原始 JSON、创建任务卡、接收用户修改、生成确认后的 payload、执行 OPERA 模拟并记录结果。
|
||||
- SuperAgent 不直连本系统数据库,只能通过本系统后端接口查询已有订单和任务上下文。
|
||||
|
||||
## 5. AI 输出接收边界
|
||||
|
||||
导入文档已经定义了 SuperAgent / Main Agent 应输出的核心业务结构,但还没有定义完整 HTTP 接口契约。
|
||||
|
||||
AI 聚合输出的顶层结构应包含:
|
||||
|
||||
| 字段 | 中文说明 |
|
||||
| --- | --- |
|
||||
| `source_message_id` | 关联的 SourceMessage ID |
|
||||
| `ai_task_results[]` | AI 拆分出的一个或多个任务结果,顺序必须保留 |
|
||||
| `extraction_warnings[]` | 抽取警告,不直接等同于业务任务 |
|
||||
|
||||
`ai_task_results[]` 中关键字段包括:
|
||||
|
||||
| 字段 | 中文说明 |
|
||||
| --- | --- |
|
||||
| `source_event_index` | AI 拆分出的 current 事件序号,同一次来源消息内用于排序 |
|
||||
| `catalog_code` | Skill 目录代码,例如 S01、S02 |
|
||||
| `skill_id` | 具体 Skill 标识 |
|
||||
| `result_type` | AI 结果类型,第一版只使用 `normal_task`、`manual_review`、`informational_message` |
|
||||
| `task_type` | AI 原始任务类型,例如 `New Booking`、`Voucher Received` |
|
||||
| `task_subtype` / 业务动作 | 更细的业务动作,用于任务卡字段路由 |
|
||||
| `current_or_history` | 当前事件还是历史证据 |
|
||||
| `case_keys` | 订单关联候选键,例如 `group_code`、`confirmation_number` |
|
||||
| `visible_reason` | 给用户看的生成原因 |
|
||||
| `relevant_message_excerpt` | 相关邮件片段 |
|
||||
| `attachments` / `file_references` | 附件和文件引用 |
|
||||
| `context_used` | AI 使用的上下文摘要 |
|
||||
| `extracted_fields` | 业务字段主体 |
|
||||
| `manual_review` | 人工复核结构化原因和证据 |
|
||||
| `informational_message` | 信息提醒内容 |
|
||||
| `additional_operations` | AI 建议的附加动作 |
|
||||
| `idempotency_key` | 幂等键,最终来源和生成规则待确认 |
|
||||
|
||||
待补充的 HTTP 契约包括 URL、Method、Header、鉴权、幂等策略、错误响应格式、是否允许重复推送同一个 `source_message_id`。
|
||||
|
||||
## 6. AI 过渡层数据要求
|
||||
|
||||
系统接收 AI 输出后,应先写入 AI 过渡层,再创建任务卡。过渡层用于追溯、幂等、筛选、人工确认和 OPERA 参数组装。
|
||||
|
||||
推荐保存完整 JSON:
|
||||
|
||||
| JSON 字段 | 中文说明 |
|
||||
| --- | --- |
|
||||
| `ai_payload_json` | AI 原始结果,禁止被用户编辑覆盖 |
|
||||
| `case_keys_json` | AI 给出的订单关联候选键 |
|
||||
| `extracted_fields_json` | AI 抽取的业务字段 |
|
||||
| `manual_review_json` | 人工复核信息 |
|
||||
| `informational_message_json` | 信息提醒内容 |
|
||||
| `attachments_json` | 附件和文件引用 |
|
||||
| `context_used_json` | AI 使用的上下文 |
|
||||
| `confirmed_payload_json` | 用户修改并确认后的最终参数 |
|
||||
|
||||
推荐冗余物理列:
|
||||
|
||||
| 物理列 | 中文说明 |
|
||||
| --- | --- |
|
||||
| `source_message_id` | 来源消息 ID |
|
||||
| `source_event_index` | AI 事件序号 |
|
||||
| `catalog_code` | Skill 目录代码 |
|
||||
| `skill_id` | Skill 标识 |
|
||||
| `result_type` | AI 结果类型 |
|
||||
| `ai_task_type` | AI 原始任务类型 |
|
||||
| `system_task_type` | 系统主任务类型 |
|
||||
| `task_card_type` | 任务卡类型 |
|
||||
| `task_subtype` | 业务动作 subtype |
|
||||
| `current_or_history` | 当前或历史标识 |
|
||||
| `group_code` | 冗余的 Group Code 候选 |
|
||||
| `confirmation_number` | 冗余的 Confirmation Number 候选 |
|
||||
| `idempotency_key` | 幂等键 |
|
||||
| `manual_reason_code` | 人工复核原因码 |
|
||||
| `parent_source_event_index` | 父任务事件序号 |
|
||||
| `linked_task_group_id` | 联动任务组 ID |
|
||||
| `blocked_until_parent_completed` | 是否等待父任务完成 |
|
||||
| `execution_order` | 同订单下执行顺序 |
|
||||
| `created_at` / `updated_at` | 创建和更新时间 |
|
||||
|
||||
不要把所有嵌套字段都建成物理列。只有高频查询、筛选、幂等、排序、队列控制和状态机需要的字段才冗余。
|
||||
|
||||
## 7. 任务分类模型
|
||||
|
||||
### 7.1 AI 结果类型
|
||||
|
||||
AI 第一版结果类型只接受:
|
||||
|
||||
| `result_type` | 中文说明 | 是否可直接 OPERA 模拟 |
|
||||
| --- | --- | --- |
|
||||
| `normal_task` | 可生成业务任务卡的正常任务 | 需用户确认后才允许 |
|
||||
| `manual_review` | 需要人工复核的结构化任务 | 不允许直接写 OPERA |
|
||||
| `informational_message` | 只读信息提醒 | 不允许写 OPERA |
|
||||
|
||||
不使用 `exception_task` 和 `no_action`。原来讨论中的异常任务,在本版统一落为 `manual_review`;没有业务动作的信息提醒,统一落为 `informational_message`。
|
||||
|
||||
### 7.2 系统主任务类型
|
||||
|
||||
系统内部主任务类型建议为:
|
||||
|
||||
| 系统主任务类型 | 中文说明 |
|
||||
| --- | --- |
|
||||
| `NEW_BOOKING` | 新建订单任务 |
|
||||
| `UPDATE_BOOKING` | 更新订单任务,下面承载多个不同任务卡 |
|
||||
| `CANCEL_BOOKING` | 取消订单任务 |
|
||||
| `MANUAL_REVIEW` | 人工复核或 Fallback 任务 |
|
||||
| `INFORMATIONAL_MESSAGE` | 信息提醒任务,只归档展示,不参与执行队列 |
|
||||
|
||||
### 7.3 AI 任务类型到系统任务和卡片的映射
|
||||
|
||||
| AI `task_type` | 系统主任务类型 | 任务卡类型 | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| `New Booking` | `NEW_BOOKING` | `NEW_BOOKING` | 新建 FIT、Group Block、Allotment / Control Block |
|
||||
| `Update Booking` | `UPDATE_BOOKING` | `UPDATE_BOOKING` | 通用订单修改卡 |
|
||||
| `Voucher Received` | `UPDATE_BOOKING` | `VOUCHER_RECEIVED` | 凭证类更新卡 |
|
||||
| `Rooming List` | `UPDATE_BOOKING` | `ROOMING_LIST` | 名单/分房表处理卡 |
|
||||
| `Amend Group Code` | `UPDATE_BOOKING` | `AMEND_GROUP_CODE` | 修改 Group Code 卡 |
|
||||
| `Trace / Reservation Notes` | `UPDATE_BOOKING` | `TRACE_RESERVATION_NOTES` | Trace 或备注卡,可作为联动任务 |
|
||||
| `TA Recorder` | `UPDATE_BOOKING` | `TA_RECORDER` | TA Recorder 维护卡,通常由 Rooming List 派生 |
|
||||
| `Cancel Booking` | `CANCEL_BOOKING` | `CANCEL_BOOKING` | 取消 FIT、Group Block、Allotment / Control Block |
|
||||
| `Message Notification` | `INFORMATIONAL_MESSAGE` | `MESSAGE_NOTIFICATION` | 挂临时订单,只读展示,不参与执行队列 |
|
||||
| `Fallback` | `MANUAL_REVIEW` | `FALLBACK_REVIEW` | 人工复核任务 |
|
||||
|
||||
系统不得丢弃 AI 原始 `task_type`。任务落库时应同时保存 AI 原始任务类型、系统主任务类型、任务卡类型和业务动作 subtype。
|
||||
|
||||
## 8. Message Notification 处理规则
|
||||
|
||||
`Message Notification` 用于感谢、知会、已收到、转发说明、信息同步等没有明确业务执行动作的消息。
|
||||
|
||||
本系统处理规则:
|
||||
|
||||
- 创建临时订单作为归档容器。
|
||||
- 创建只读信息提醒任务卡。
|
||||
- 不参与订单任务执行队列。
|
||||
- 不阻塞同订单其他可执行任务。
|
||||
- 不被同订单其他可执行任务阻塞。
|
||||
- 不允许编辑业务字段。
|
||||
- 不允许确认后执行 OPERA 模拟。
|
||||
- 可在详情页展示 `visible_reason`、`relevant_message_excerpt`、`attachments` 和 `informational_message`。
|
||||
|
||||
## 9. 任务卡字段约束
|
||||
|
||||
任务卡字段以 `docs/import/20260706/任务卡展示编辑矩阵.xlsx` 为权威来源。系统不得直接把整个 `ai_task_results[]` 渲染成表单,也不得绕过矩阵自行扩展字段含义。
|
||||
|
||||
字段矩阵通过以下列控制任务详情页行为:
|
||||
|
||||
| 列 | 中文说明 |
|
||||
| --- | --- |
|
||||
| `任务卡名称` | 前端任务卡名称 |
|
||||
| `result_type` | 适用的 AI 结果类型 |
|
||||
| `task_type` | 适用的 AI 原始任务类型 |
|
||||
| `task_subtype/业务动作` | 适用的业务动作 |
|
||||
| `字段路径` | 从 AI JSON 或确认 JSON 中取值的路径 |
|
||||
| `展示名` | 前端展示名称 |
|
||||
| `是否展示` | 是否在任务卡展示 |
|
||||
| `是否可编辑` | 用户是否可编辑 |
|
||||
| `是否为输入方式编辑` | 是否普通输入 |
|
||||
| `是否为下拉框方式编辑` | 是否下拉选择 |
|
||||
| `是否日期选择` | 是否日期控件 |
|
||||
| `是否数字输入` | 是否数字输入 |
|
||||
| `是否文件展示` | 是否文件或附件展示 |
|
||||
| `是否表格编辑` | 是否表格型编辑 |
|
||||
| `下拉选项/枚举值` | 可选值,系统不得自行扩展 |
|
||||
| `是否必填` | 用户确认前是否必填 |
|
||||
| `展示条件` | 字段显示条件 |
|
||||
| `校验规则` | 用户确认前校验规则 |
|
||||
| `确认后写入位置` | 写入 `confirmed_payload_json` 的位置 |
|
||||
| `是否参与Opera写入` | 是否允许进入 OPERA 参数 |
|
||||
| `Opera API参数映射` | OPERA 参数映射意图 |
|
||||
|
||||
### 9.1 关键卡片字段摘要
|
||||
|
||||
本节只摘录核心字段,完整字段以 Excel 矩阵为准。
|
||||
|
||||
| 任务卡 | 关键字段 |
|
||||
| --- | --- |
|
||||
| New Booking | `case_keys.group_code`、`case_keys.confirmation_number`、入住/离店日期、房量、房型原文、Opera 房型代码、Rate Code、结算价、Fix Charge、子团房量、表格行证据 |
|
||||
| Update Booking | `case_keys.group_code`、`case_keys.confirmation_number`、修改类型、修改前/后、Rate / 结算价结果、Fix Charge、表格行证据 |
|
||||
| Cancel Booking | `case_keys.group_code`、`case_keys.confirmation_number`、取消对象类型、取消范围、取消生效日期、取消备注 |
|
||||
| Voucher Received | 原始凭证、凭证类型、`case_keys.group_code`、确认后动作、凭证展示字段、部门流转、关联 Group Code |
|
||||
| Rooming List | 名单文件、名单类型、目标 Key、文件类型判断、附件 / Sheet 绑定、后续动作意图、派生任务候选 |
|
||||
| Amend Group Code | 旧 Group Code、新 Group Code |
|
||||
| Trace / Reservation Notes | `case_keys.group_code`、`case_keys.confirmation_number`、Trace 类型、通知部门、Trace Text、入住人数更新、改价公式、父任务事件序号 |
|
||||
| TA Recorder | Group Code、名单 / 分房附件、TA Recorder 状态、Rooming List 父任务 |
|
||||
| Message Notification | 生成原因、邮件片段、附件、信息提醒内容 |
|
||||
| Fallback / manual_review | 复核原因码、复核说明、复核记录类型、阻断点、缺失字段、冲突点、建议核对证据、建议人工动作、候选 Group Code、候选 Confirmation No. |
|
||||
|
||||
## 10. AI 原始值和人工确认值
|
||||
|
||||
AI 原始输出和用户确认值必须分离。
|
||||
|
||||
| 概念 | 中文说明 |
|
||||
| --- | --- |
|
||||
| `ai_payload_json` | AI 原始输出,作为证据和审计,不被用户编辑覆盖 |
|
||||
| `confirmed_payload_json` | 用户修改并确认后的最终业务参数 |
|
||||
|
||||
系统规则:
|
||||
|
||||
- 任务详情首次展示可从 `ai_payload_json` 按矩阵字段路径取值。
|
||||
- 用户编辑后必须写入 `confirmed_payload_json`。
|
||||
- 用户确认前必须按矩阵和后端硬校验检查必填、类型、枚举和执行条件。
|
||||
- OPERA 模拟只能从 `confirmed_payload_json` 取值。
|
||||
- 不允许直接从 `ai_payload_json` 组装 OPERA 参数。
|
||||
- 不允许因为用户修改而覆盖 AI 原始输出。
|
||||
|
||||
## 11. 订单业务号和临时订单
|
||||
|
||||
系统不应只用一个含义模糊的“订单号”。建议至少区分:
|
||||
|
||||
| 字段 | 中文说明 |
|
||||
| --- | --- |
|
||||
| `order_id` | 系统内部订单 ID,永远存在 |
|
||||
| `order_key_type` | 业务号类型,例如 `GROUP_CODE`、`CONFIRMATION_NUMBER`、`TEMPORARY` |
|
||||
| `order_business_key` | 真实业务号,例如 Group Code 或 Confirmation Number |
|
||||
| `temporary_order_code` | 临时订单展示编号 |
|
||||
|
||||
### 11.1 可作为订单业务号候选的字段
|
||||
|
||||
订单业务号候选字段包括:
|
||||
|
||||
| 字段路径 | 适用场景 | 中文说明 |
|
||||
| --- | --- | --- |
|
||||
| `case_keys.group_code` | Group / Block / Allotment 类任务 | 主要 Group Code 候选 |
|
||||
| `case_keys.confirmation_number` | FIT Reservation 类任务 | 主要 Confirmation Number 候选 |
|
||||
| `extracted_fields.old_group_code` | Amend Group Code | 定位原订单 |
|
||||
| `extracted_fields.new_group_code` | Amend Group Code | 修改成功后的新业务号候选 |
|
||||
| `extracted_fields.group_code` | TA Recorder 等卡片 | 任务卡内 Group Code 候选 |
|
||||
| `extracted_fields.target_key` | Rooming List | 目标 Key,需要判断实际是 Group Code 还是 Confirmation Number |
|
||||
| `related_group_codes[]` | Voucher 等场景 | 关联展示或候选,不应自动作为唯一主订单号 |
|
||||
|
||||
系统匹配订单时应优先使用用户确认后的 `confirmed_payload_json`;如果尚未确认,只能把 AI 字段作为候选和展示依据。
|
||||
|
||||
### 11.2 New Booking 的订单号处理
|
||||
|
||||
`NEW_BOOKING` 不一定都需要等待 OPERA 模拟创建后才有真实业务号。
|
||||
|
||||
规则:
|
||||
|
||||
- 如果用户确认后的 payload 已有可用业务号,优先使用该业务号。
|
||||
- FIT Reservation 优先看 `confirmation_number`。
|
||||
- Group / Block / Allotment 优先看 `group_code`。
|
||||
- 如果确认后的 payload 没有可用业务号,先创建临时订单并使用 `temporary_order_code` 展示和追踪。
|
||||
- OPERA 模拟创建成功后,如果结果中返回真实业务号,再回填订单业务号。
|
||||
- 第一版尚未实现确认 payload 时,Fallback 转 `NEW_BOOKING` 可先读取 AI 原始 `case_keys.group_code` / `case_keys.confirmation_number` 作为 `AI_CANDIDATE`,用于把原临时订单激活为 ACTIVE;后续用户确认字段时再把来源升级为 `USER_CONFIRMED`。
|
||||
|
||||
### 11.3 什么时候从 OPERA 模拟结果回填订单号
|
||||
|
||||
只有在 `NEW_BOOKING` 且确认后的 payload 没有可用业务号时,才需要从 OPERA 模拟结果回填订单号。
|
||||
|
||||
| 任务场景 | 回填业务含义 |
|
||||
| --- | --- |
|
||||
| New FIT Reservation | 从 OPERA 模拟结果中的 Confirmation No. / Reservation Confirmation Number 含义字段回填 |
|
||||
| New Group Block | 从 OPERA 模拟结果中的 Group Code / Block Code 含义字段回填 |
|
||||
| New Allotment / Control Block | 从 OPERA 模拟结果中的 Group Code / Block Code / Allotment Code 含义字段回填 |
|
||||
|
||||
当前导入文档没有定义 OPERA 模拟结果的 JSON 字段名,因此不能在需求中写死 `result.confirmationNumber`、`result.groupCode` 等具体路径。该字段名需要在 OPERA 模拟模块设计时另行确认。
|
||||
|
||||
### 11.4 非 New Booking 的订单号规则
|
||||
|
||||
`UPDATE_BOOKING`、`CANCEL_BOOKING`、`Voucher Received`、`Rooming List`、`Trace / Reservation Notes`、`TA Recorder` 等任务,原则上不应依赖 OPERA 模拟结果生成订单号。
|
||||
|
||||
这些任务应先通过 `case_keys` 或对应卡片字段挂靠已有订单;如果无法自动归属,则创建或使用临时订单,并等待人工确认订单关系。
|
||||
|
||||
## 12. 订单挂靠和临时订单
|
||||
|
||||
任务必须挂靠到订单下,便于详情查看、队列控制和审计。
|
||||
|
||||
| 场景 | 挂靠规则 |
|
||||
| --- | --- |
|
||||
| New Booking 有业务号 | 按确认后的业务号创建或匹配订单 |
|
||||
| New Booking 无业务号 | 创建临时订单 |
|
||||
| Update Booking 可匹配已有订单 | 挂靠已有订单 |
|
||||
| Update Booking 无法匹配订单 | 挂靠临时订单,等待人工确认 |
|
||||
| Cancel Booking 可匹配已有订单 | 挂靠已有订单 |
|
||||
| Cancel Booking 无法匹配订单 | 挂靠临时订单,等待人工确认 |
|
||||
| Fallback / manual_review | 先挂靠临时订单,人工处理时可转换类型和订单归属 |
|
||||
| Message Notification | 挂靠临时订单,只读归档 |
|
||||
|
||||
任务从临时订单迁移到已有订单时,必须记录审计。若原临时订单已无有效任务,应逻辑删除,并记录删除原因。
|
||||
|
||||
## 13. 任务顺序和可处理状态
|
||||
|
||||
同一个订单下,任务必须按顺序处理。
|
||||
|
||||
排序依据:
|
||||
|
||||
```text
|
||||
order_id + execution_order
|
||||
```
|
||||
|
||||
同一次 AI 返回多个任务时:
|
||||
|
||||
- 必须保留 `ai_task_results[]` 列表顺序。
|
||||
- 可使用 `source_event_index`、`execution_order` 或批次内 item index 保存顺序。
|
||||
- 不得只依赖创建时间,因为同批次任务创建时间可能完全一致。
|
||||
|
||||
处理规则:
|
||||
|
||||
- 前置任务未完成时,后续任务只能查看。
|
||||
- `FAILED` 视为当前前置任务已经结束,不阻塞后续任务;用户不能跳过失败的 OPERA 操作,但失败任务本身不再卡住后续任务查看和处理顺序。
|
||||
- 后续任务不能编辑字段。
|
||||
- 后续任务不能确认订单关系。
|
||||
- 后续任务不能执行 OPERA 模拟。
|
||||
- 后续任务不能重试 OPERA 模拟。
|
||||
- `Message Notification` 不参与执行队列,不阻塞其他任务,也不被其他任务阻塞。
|
||||
- 联动任务可通过 `parent_source_event_index`、`linked_task_group_id`、`blocked_until_parent_completed` 表达依赖。
|
||||
|
||||
## 14. 人工复核和 Fallback
|
||||
|
||||
`manual_review` 是结构化人工复核,不是空结果,也不是系统失败。
|
||||
|
||||
人工复核卡至少应展示:
|
||||
|
||||
- `manual_review.reason_code`
|
||||
- `manual_review.visible_reason`
|
||||
- `manual_review.review_record_type`
|
||||
- `manual_review.blocking_points[]`
|
||||
- `manual_review.missing_fields[]`
|
||||
- `manual_review.conflicting_points[]`
|
||||
- `manual_review.evidence_to_check[]`
|
||||
- `manual_review.suggested_human_actions[]`
|
||||
|
||||
Fallback 处理规则:
|
||||
|
||||
- 创建 `MANUAL_REVIEW` 任务。
|
||||
- 默认挂靠临时订单。
|
||||
- 用户处理时可以选择转为 `NEW_BOOKING`、`UPDATE_BOOKING` 或 `CANCEL_BOOKING`。
|
||||
- 转换时必须记录审计;原因字段第一版允许为空。
|
||||
- 转为 `NEW_BOOKING` 时,临时订单可以继续保留;如果已有确认 payload 则优先使用确认业务号,第一版尚未实现确认 payload 时可先使用 AI 原始 `case_keys` 中的业务号候选。
|
||||
- 转为 `UPDATE_BOOKING` 或 `CANCEL_BOOKING` 时,用户必须选择目标订单;任务迁移后原临时订单无有效任务时可逻辑删除。
|
||||
- 类型转换、订单迁移和临时订单逻辑删除都必须记录审计。
|
||||
|
||||
## 15. OPERA 模拟操作
|
||||
|
||||
当前阶段没有真实 OHIP / OPERA 接口,只做 OPERA 模拟操作。
|
||||
|
||||
允许进入 OPERA 模拟的前置条件:
|
||||
|
||||
- `result_type = normal_task`。
|
||||
- 当前任务是订单执行队列中可处理的任务。
|
||||
- 用户已确认订单归属。
|
||||
- 用户已确认字段,且系统已生成 `confirmed_payload_json`。
|
||||
- 字段矩阵中 `是否参与Opera写入` 为 `是` 或满足 `条件参与`。
|
||||
- 后端硬校验通过。
|
||||
|
||||
不允许进入 OPERA 模拟的场景:
|
||||
|
||||
- `manual_review`。
|
||||
- `informational_message`。
|
||||
- 未确认的 AI 原始值。
|
||||
- 证据字段、只读字段、历史字段、uncertain 字段。
|
||||
- S04 的 `voucher_display_fields` 等展示字段。
|
||||
- 字段矩阵明确 `是否参与Opera写入=否` 的字段。
|
||||
|
||||
一个任务可能产生多条 OPERA 模拟操作。任务详情页应展示每条模拟操作的结果、状态、失败原因、重试次数和最近执行时间。重试必须保留历史记录,不能覆盖原始失败记录。
|
||||
|
||||
## 16. 审计要求
|
||||
|
||||
以下行为必须记录审计:
|
||||
|
||||
- AI 结果接收批次。
|
||||
- `ai_task_results[]` 中每个 item 的创建顺序。
|
||||
- AI 原始 JSON 保存。
|
||||
- 订单自动挂靠或临时订单创建。
|
||||
- 用户修改任务字段。
|
||||
- 用户确认订单关系。
|
||||
- `confirmed_payload_json` 生成。
|
||||
- 任务类型转换。
|
||||
- 任务切换订单。
|
||||
- 临时订单逻辑删除。
|
||||
- OPERA 模拟操作执行。
|
||||
- OPERA 模拟操作重试。
|
||||
- 从 OPERA 模拟结果回填订单业务号。
|
||||
|
||||
审计至少包含:
|
||||
|
||||
| 字段 | 中文说明 |
|
||||
| --- | --- |
|
||||
| `actor` | 操作人或系统调用方 |
|
||||
| `action` | 操作类型 |
|
||||
| `reason` | 用户填写或系统记录的原因 |
|
||||
| `before_snapshot` | 变更前摘要 |
|
||||
| `after_snapshot` | 变更后摘要 |
|
||||
| `occurred_at` | 发生时间 |
|
||||
|
||||
审计中不得记录 Secret、Token、完整邮件正文、真实附件 URL 或不必要的个人敏感信息。
|
||||
|
||||
## 17. 暂不包含范围
|
||||
|
||||
本版暂不定义:
|
||||
|
||||
- SuperAgent 调本系统的正式 HTTP 接口契约。
|
||||
- 幂等键到底由 SuperAgent 生成还是本系统生成。
|
||||
- 订单完整状态机。
|
||||
- 任务完整状态机。
|
||||
- OPERA 模拟结果 JSON 字段名。
|
||||
- 真实 OHIP / OPERA 接口地址、鉴权和返回结构。
|
||||
- 前端具体页面布局和交互细节。
|
||||
- 全量 158 条任务卡字段配置复制版。
|
||||
- Rate Code 和房型规则的代码实现。
|
||||
|
||||
## 18. 待确认问题
|
||||
|
||||
- SuperAgent 创建任务接口的 URL、Method、Header、鉴权和错误响应格式。
|
||||
- SuperAgent 查询上下文接口暂不在本 checkpoint 实现,但 SuperAgent 侧已经在整理,后续梳理未完成事项时必须持续提醒。
|
||||
- `source_event_index`、批次 item index、`execution_order` 的最终编号规则是否都从 1 开始。
|
||||
- `idempotency_key` 的来源和冲突处理策略。
|
||||
- 订单状态机有哪些稳定状态。
|
||||
- 任务状态机有哪些稳定状态。
|
||||
- `Message Notification` 是否需要在前端订单列表上单独标识为只读提醒。
|
||||
- OPERA 模拟结果中 Confirmation No.、Group Code、Block Code、Allotment Code 的具体字段路径。
|
||||
- 临时订单在无任务后是否立即逻辑删除,还是保留一段时间便于追溯。
|
||||
- 用户是否允许强制完成任务;如果允许,需要什么权限和审计原因。
|
||||
|
||||
## 19. 后续建议 checkpoint
|
||||
|
||||
建议后续按以下顺序拆分:
|
||||
|
||||
1. 定义 SuperAgent 调本系统的任务结果接收接口契约。
|
||||
2. 定义 AI 过渡层、订单、任务、任务卡、审计、OPERA 模拟结果的最小数据模型。
|
||||
3. 定义系统主任务类型、任务卡类型、`result_type`、任务状态和订单状态枚举。
|
||||
4. 实现 AI 结果接收、幂等、顺序保存和任务卡创建。
|
||||
5. 实现订单自动挂靠、临时订单创建和人工订单切换。
|
||||
6. 实现任务详情字段展示、编辑、确认和 `confirmed_payload_json`。
|
||||
7. 实现任务队列阻塞规则和 `Message Notification` 只读归档规则。
|
||||
8. 实现 OPERA 模拟操作结果底表、重试和订单业务号回填。
|
||||
9. 根据前端页面范围实现列表、详情和只读/可处理状态展示。
|
||||
@@ -0,0 +1,378 @@
|
||||
# M002 SuperAgent Task Result API Contract
|
||||
|
||||
## 文档信息
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 文档版本 | 0.1 |
|
||||
| 日期 | 2026-07-07 |
|
||||
| 状态 | 后端接口契约草稿 |
|
||||
| 适用范围 | SuperAgent / Main Agent 调用本系统提交 AI 任务结果 |
|
||||
| 主要读者 | 后端、SuperAgent 对接方、测试、后续协作 agent |
|
||||
|
||||
## 1. 文档定位
|
||||
|
||||
本文定义 SuperAgent / Main Agent 向本系统提交 `ai_task_results[]` 的第一版后端接口契约。
|
||||
|
||||
本文承接 `M002-order-task-workflow-v2.md`,只定义本系统入站接口、鉴权、幂等、请求响应和技术校验边界,不定义 SuperAgent 内部 prompt、Skill 实现、OPERA 真实接口或前端展示细节。
|
||||
|
||||
## 2. 接口概览
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| Method | `POST` |
|
||||
| Path | `/api/integrations/superagent/task-results` |
|
||||
| Content-Type | `application/json` |
|
||||
| 响应格式 | `application/json` |
|
||||
| 一次请求范围 | 只能包含一个 `source_message_id` |
|
||||
| 业务动作 | 接收 AI 结果、写入 AI 过渡层、生成订单 / 任务 / 任务卡 |
|
||||
| 鉴权方式 | HMAC-SHA256 签名 |
|
||||
|
||||
中文说明:
|
||||
|
||||
- 该接口是服务到服务的入站接口,不给前端直接调用。
|
||||
- SuperAgent 不直连数据库,只能通过本接口提交任务结果。
|
||||
- 本接口只做技术校验和系统接收,不替代用户确认和 OPERA 模拟操作。
|
||||
|
||||
## 3. 鉴权方案
|
||||
|
||||
第一版使用 HMAC-SHA256 签名,做到简单、可实现、可防重放。
|
||||
|
||||
### 3.1 环境变量
|
||||
|
||||
| 环境变量 | 是否必填 | 中文说明 |
|
||||
| --- | --- | --- |
|
||||
| `SUPERAGENT_TASK_RESULT_HMAC_SECRET` | 是 | SuperAgent 任务结果入站签名密钥,只能通过 Secret 注入 |
|
||||
| `SUPERAGENT_TASK_RESULT_CLOCK_SKEW_SECONDS` | 否 | 请求时间允许偏移,默认 `300` 秒 |
|
||||
| `SUPERAGENT_TASK_RESULT_NONCE_TTL_SECONDS` | 否 | Nonce 去重窗口,默认 `600` 秒 |
|
||||
| `SUPERAGENT_TASK_RESULT_MAX_BODY_BYTES` | 否 | 请求体最大字节数,默认 `1048576` |
|
||||
|
||||
如果 `SUPERAGENT_TASK_RESULT_HMAC_SECRET` 为空,生产环境应拒绝接口调用。
|
||||
|
||||
### 3.2 请求 Header
|
||||
|
||||
| Header | 是否必填 | 中文说明 |
|
||||
| --- | --- | --- |
|
||||
| `X-TH-Hotel-SuperAgent-Client-Id` | 是 | 调用方客户端 ID,用于区分不同 SuperAgent 调用方 |
|
||||
| `X-TH-Hotel-SuperAgent-Timestamp` | 是 | UTC 时间,ISO-8601 格式,例如 `2026-07-07T08:30:00Z` |
|
||||
| `X-TH-Hotel-SuperAgent-Nonce` | 是 | 每次请求唯一随机值,用于防重放 |
|
||||
| `X-TH-Hotel-SuperAgent-Signature` | 是 | HMAC 签名,格式 `sha256=<lowercase-hex>` |
|
||||
| `X-TH-Hotel-Request-Id` | 否 | 调用方请求 ID,用于排查和日志串联 |
|
||||
|
||||
### 3.3 签名串
|
||||
|
||||
签名使用原始请求体字节计算 SHA-256,再参与 HMAC。
|
||||
|
||||
规范签名串:
|
||||
|
||||
```text
|
||||
POST
|
||||
/api/integrations/superagent/task-results
|
||||
<X-TH-Hotel-SuperAgent-Timestamp>
|
||||
<X-TH-Hotel-SuperAgent-Nonce>
|
||||
<X-TH-Hotel-SuperAgent-Client-Id>
|
||||
<lowercase-hex-sha256-of-raw-body>
|
||||
```
|
||||
|
||||
签名算法:
|
||||
|
||||
```text
|
||||
signature = HMAC_SHA256(SUPERAGENT_TASK_RESULT_HMAC_SECRET, canonical_string)
|
||||
```
|
||||
|
||||
Header 写法:
|
||||
|
||||
```text
|
||||
X-TH-Hotel-SuperAgent-Signature: sha256=<lowercase-hex-signature>
|
||||
```
|
||||
|
||||
### 3.4 服务端校验
|
||||
|
||||
服务端必须按顺序完成以下校验:
|
||||
|
||||
1. 校验必要 Header 是否存在。
|
||||
2. 校验 timestamp 可解析且在允许时间窗口内。
|
||||
3. 校验同一个 `client_id + nonce` 在 TTL 窗口内没有被使用过。
|
||||
4. 计算原始请求体 SHA-256。
|
||||
5. 使用 HMAC secret 重新计算签名。
|
||||
6. 使用常量时间比较签名。
|
||||
7. 鉴权通过后再解析 JSON。
|
||||
|
||||
日志和错误响应不得输出 secret、签名原文、完整请求体、邮件正文、附件 URL 或个人敏感信息。
|
||||
|
||||
## 4. 请求体
|
||||
|
||||
请求体沿用 AI 导入文档定义的聚合结构。
|
||||
|
||||
```json
|
||||
{
|
||||
"source_message_id": "1900000000000000001",
|
||||
"ai_task_results": [
|
||||
{
|
||||
"source_event_index": 1,
|
||||
"catalog_code": "S01",
|
||||
"skill_id": "S01_new_booking_skill",
|
||||
"result_type": "normal_task",
|
||||
"task_type": "New Booking",
|
||||
"task_subtype": "new_fit_reservation",
|
||||
"current_or_history": "current",
|
||||
"case_keys": {
|
||||
"group_code": null,
|
||||
"confirmation_number": null
|
||||
},
|
||||
"visible_reason": "邮件正文包含新建预订请求。",
|
||||
"relevant_message_excerpt": "Please create a new booking...",
|
||||
"attachments": [],
|
||||
"file_references": [],
|
||||
"context_used": {},
|
||||
"extracted_fields": {},
|
||||
"manual_review": null,
|
||||
"informational_message": null,
|
||||
"additional_operations": [],
|
||||
"idempotency_key": null
|
||||
}
|
||||
],
|
||||
"extraction_warnings": []
|
||||
}
|
||||
```
|
||||
|
||||
### 4.1 顶层字段
|
||||
|
||||
| 字段 | 是否必填 | 中文说明 |
|
||||
| --- | --- | --- |
|
||||
| `source_message_id` | 是 | 关联本系统 SourceMessage ID;一次请求只能有一个 |
|
||||
| `ai_task_results[]` | 是 | AI 拆分出的任务结果列表,必须保留数组顺序 |
|
||||
| `extraction_warnings[]` | 否 | 抽取警告;不直接等同于业务任务 |
|
||||
|
||||
第一版要求 `ai_task_results[]` 至少包含一条记录。没有业务动作时应由 AI 输出 `Message Notification` 或 `Fallback/manual_review`,而不是提交空数组。
|
||||
|
||||
### 4.2 `ai_task_results[]` 字段
|
||||
|
||||
| 字段 | 是否必填 | 中文说明 |
|
||||
| --- | --- | --- |
|
||||
| `source_event_index` | 是 | AI current 事件序号,建议从 1 开始 |
|
||||
| `catalog_code` | 是 | Skill 目录代码,例如 S01、S02 |
|
||||
| `skill_id` | 是 | Skill 标识 |
|
||||
| `result_type` | 是 | 只接受 `normal_task`、`manual_review`、`informational_message` |
|
||||
| `task_type` | 是 | AI 原始任务类型 |
|
||||
| `task_subtype` | 否 | 业务动作 subtype;有则用于任务卡路由 |
|
||||
| `current_or_history` | 否 | 当前或历史标识 |
|
||||
| `case_keys` | 否 | 订单关联候选键 |
|
||||
| `visible_reason` | 否 | 给用户看的生成原因 |
|
||||
| `relevant_message_excerpt` | 否 | 相关邮件片段,注意不要超长 |
|
||||
| `attachments` / `file_references` | 否 | 附件和文件引用 |
|
||||
| `context_used` | 否 | AI 使用的上下文 |
|
||||
| `extracted_fields` | 否 | 业务字段主体 |
|
||||
| `manual_review` | 条件必填 | `result_type=manual_review` 时应提供 |
|
||||
| `informational_message` | 条件必填 | `result_type=informational_message` 时应提供 |
|
||||
| `additional_operations` | 否 | 附加动作建议 |
|
||||
| `idempotency_key` | 否 | 可忽略;本系统第一版自行生成幂等键 |
|
||||
|
||||
## 5. 技术校验边界
|
||||
|
||||
本接口只做技术校验,不做业务合法性判断。
|
||||
|
||||
### 5.1 必须校验
|
||||
|
||||
- 鉴权签名合法。
|
||||
- 请求体大小不超过限制。
|
||||
- JSON 可解析。
|
||||
- 顶层只有一个 `source_message_id`。
|
||||
- `source_message_id` 对应的 SourceMessage 存在。
|
||||
- `ai_task_results[]` 是非空数组。
|
||||
- `result_type` 属于允许值。
|
||||
- `task_type` 属于当前系统可识别的稳定值或可进入 Fallback 处理。
|
||||
- 同一个请求内 `source_event_index` 和数组顺序可保存。
|
||||
- 关键字符串长度不超过数据库限制。
|
||||
|
||||
### 5.2 不在本接口判断
|
||||
|
||||
- 不判断 AI 任务类型是否业务正确。
|
||||
- 不判断房型、价格、日期、Rate Code 是否合理。
|
||||
- 不判断 Cancel Booking 前是否已经有 New Booking。
|
||||
- 不因为字段缺失自动改成 Fallback。
|
||||
- 不直接执行 OPERA 模拟。
|
||||
- 不直接把 AI 原始值写入 OPERA 参数。
|
||||
|
||||
## 6. 幂等设计
|
||||
|
||||
`idempotency_key` 第一版由系统生成,不依赖 SuperAgent 传值。
|
||||
|
||||
### 6.1 请求哈希
|
||||
|
||||
系统必须保存原始请求体的 SHA-256:
|
||||
|
||||
```text
|
||||
request_payload_sha256 = sha256(raw_request_body)
|
||||
```
|
||||
|
||||
### 6.2 批次幂等键
|
||||
|
||||
批次幂等键建议:
|
||||
|
||||
```text
|
||||
batch_idempotency_key =
|
||||
sha256(
|
||||
"superagent-task-result-batch:v1"
|
||||
+ "|" + source_message_id
|
||||
+ "|" + request_payload_sha256
|
||||
)
|
||||
```
|
||||
|
||||
作用:
|
||||
|
||||
- 相同请求体重复提交时识别为幂等重放。
|
||||
- 同一个 `source_message_id` 如果提交了不同请求体,不会被误认为同一个批次。
|
||||
|
||||
### 6.3 item 幂等键
|
||||
|
||||
每条 `ai_task_results[]` 的幂等键建议:
|
||||
|
||||
```text
|
||||
item_idempotency_key =
|
||||
sha256(
|
||||
"superagent-task-result-item:v1"
|
||||
+ "|" + source_message_id
|
||||
+ "|" + source_event_index
|
||||
+ "|" + array_index
|
||||
+ "|" + catalog_code
|
||||
+ "|" + skill_id
|
||||
+ "|" + result_type
|
||||
+ "|" + task_type
|
||||
+ "|" + task_subtype
|
||||
+ "|" + item_payload_sha256
|
||||
)
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
- `array_index` 按 AI 返回列表顺序保存,建议从 1 开始。
|
||||
- `item_payload_sha256` 是单个 item 规范 JSON 或原始片段的 SHA-256。
|
||||
- 数据库应对 `hotel_id + item_idempotency_key` 建唯一约束。
|
||||
|
||||
### 6.4 重复提交处理
|
||||
|
||||
| 场景 | 处理方式 |
|
||||
| --- | --- |
|
||||
| 完全相同请求体重复提交 | 返回已有 batch 和 item,不重复创建任务 |
|
||||
| 同一 `source_message_id` 不同请求体 | 作为潜在冲突处理,第一版建议拒绝并返回 `IDEMPOTENCY_CONFLICT`,除非后续明确支持重新抽取版本 |
|
||||
| 同一请求内 item 幂等键重复 | 拒绝请求,返回 `DUPLICATE_TASK_RESULT_ITEM` |
|
||||
|
||||
## 7. 系统映射规则
|
||||
|
||||
接口接收后,应将 AI 字段映射到系统字段。
|
||||
|
||||
| AI 字段 | 系统字段 | 中文说明 |
|
||||
| --- | --- | --- |
|
||||
| `task_type` | `ai_task_type` | 保留 AI 原始任务类型 |
|
||||
| `result_type` | `result_type` | 保留 AI 结果类型 |
|
||||
| `task_type + result_type` | `system_task_type` | 映射为系统主任务类型 |
|
||||
| `task_type + task_subtype` | `task_card_type` | 映射为任务卡类型 |
|
||||
| `source_event_index + array_index` | `execution_order` | 生成同订单任务顺序 |
|
||||
| 完整 item JSON | `ai_payload_json` | 保存 AI 原始 payload |
|
||||
| `case_keys` | `case_keys_json` | 保存订单候选键 |
|
||||
| `extracted_fields` | `extracted_fields_json` | 保存业务字段 |
|
||||
| `manual_review` | `manual_review_json` | 保存人工复核结构 |
|
||||
| `informational_message` | `informational_message_json` | 保存信息提醒 |
|
||||
|
||||
系统主任务类型映射以 `M002-order-task-workflow-v2.md` 为准。
|
||||
|
||||
## 8. 响应体
|
||||
|
||||
### 8.1 创建成功
|
||||
|
||||
首次成功创建时返回 `201 Created`。
|
||||
|
||||
```json
|
||||
{
|
||||
"request_id": "req-20260707-0001",
|
||||
"source_message_id": "1900000000000000001",
|
||||
"batch_id": "1900000000000001001",
|
||||
"idempotent_replay": false,
|
||||
"accepted_count": 1,
|
||||
"items": [
|
||||
{
|
||||
"source_event_index": 1,
|
||||
"array_index": 1,
|
||||
"ai_transition_id": "1900000000000002001",
|
||||
"order_id": "1900000000000003001",
|
||||
"task_id": "1900000000000004001",
|
||||
"system_task_type": "NEW_BOOKING",
|
||||
"task_card_type": "NEW_BOOKING",
|
||||
"task_status": "PENDING_CONFIRM",
|
||||
"order_status": "TEMPORARY",
|
||||
"execution_order": 1
|
||||
}
|
||||
],
|
||||
"warnings": []
|
||||
}
|
||||
```
|
||||
|
||||
### 8.2 幂等重放
|
||||
|
||||
相同请求体重复提交时返回 `200 OK`。
|
||||
|
||||
```json
|
||||
{
|
||||
"request_id": "req-20260707-0002",
|
||||
"source_message_id": "1900000000000000001",
|
||||
"batch_id": "1900000000000001001",
|
||||
"idempotent_replay": true,
|
||||
"accepted_count": 1,
|
||||
"items": [],
|
||||
"warnings": [
|
||||
{
|
||||
"code": "IDEMPOTENT_REPLAY",
|
||||
"message": "相同请求已经处理,本次未重复创建任务。"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 9. 错误响应
|
||||
|
||||
错误响应统一结构:
|
||||
|
||||
```json
|
||||
{
|
||||
"request_id": "req-20260707-0003",
|
||||
"error_code": "AUTH_SIGNATURE_INVALID",
|
||||
"message": "签名校验失败。",
|
||||
"details": []
|
||||
}
|
||||
```
|
||||
|
||||
常见错误码:
|
||||
|
||||
| HTTP 状态 | error_code | 中文说明 |
|
||||
| --- | --- | --- |
|
||||
| 401 | `AUTH_HEADER_MISSING` | 鉴权 Header 缺失 |
|
||||
| 401 | `AUTH_TIMESTAMP_INVALID` | 请求时间无效或超出窗口 |
|
||||
| 401 | `AUTH_SIGNATURE_INVALID` | 签名不匹配 |
|
||||
| 409 | `AUTH_NONCE_REPLAY` | Nonce 重放 |
|
||||
| 413 | `REQUEST_BODY_TOO_LARGE` | 请求体过大 |
|
||||
| 400 | `INVALID_JSON` | JSON 不可解析 |
|
||||
| 400 | `SOURCE_MESSAGE_REQUIRED` | `source_message_id` 缺失 |
|
||||
| 404 | `SOURCE_MESSAGE_NOT_FOUND` | SourceMessage 不存在 |
|
||||
| 400 | `TASK_RESULTS_EMPTY` | `ai_task_results[]` 为空 |
|
||||
| 400 | `TASK_RESULT_UNSUPPORTED_TYPE` | `result_type` 或 `task_type` 不可识别 |
|
||||
| 400 | `DUPLICATE_TASK_RESULT_ITEM` | 同一请求内 item 重复 |
|
||||
| 409 | `IDEMPOTENCY_CONFLICT` | 同一 SourceMessage 出现不同请求体重复提交 |
|
||||
| 500 | `INTERNAL_ERROR` | 系统内部错误 |
|
||||
|
||||
错误响应不得返回原始请求体、邮件正文、附件 URL、Token、签名 secret 或完整个人敏感信息。
|
||||
|
||||
## 10. 验收标准
|
||||
|
||||
第一版接口实现完成时至少满足:
|
||||
|
||||
- 缺失 HMAC Header 时返回 `401`。
|
||||
- timestamp 超出窗口时返回 `401`。
|
||||
- nonce 重放时返回 `409`。
|
||||
- 签名错误时返回 `401`。
|
||||
- 一个请求只能包含一个 `source_message_id`。
|
||||
- `source_message_id` 不存在时返回 `404`。
|
||||
- 相同请求重复提交不会重复创建任务。
|
||||
- 同一 `source_message_id` 不同请求体重复提交返回 `409`。
|
||||
- 成功接收后能保存 AI 过渡层记录,并返回 batch、task 和 order 标识。
|
||||
- 日志和响应不暴露 secret、签名原文、完整邮件正文或附件 URL。
|
||||
Reference in New Issue
Block a user