实现V4数据库目录与Lookup接口
This commit is contained in:
@@ -444,7 +444,7 @@ V3 P0.1 不做以下事项:
|
||||
- M002 V4 CP4 已补充新模型写入:普通 V4 业务包会额外创建 V4 订单任务、来源邮件展示卡、Basic Information 卡和业务卡;只有契约错误、没有合法业务 event 的包不会创建 V4 订单任务。
|
||||
- M002 V4 CP4 后,V4 `route_code=S10/S99` 写入 `workflow_reservation_v4_source_notification`,不再创建隐藏技术订单或旧任务;V3 S10/S99 和旧 S000/S999 仍保留历史兼容链路。
|
||||
- M002 V4 CP5 已开放 V4 查询接口:`GET /api/reservation/workbench-items`、`GET /api/reservation/order-tasks`、`GET /api/reservation/order-tasks/{orderTaskId}`、`GET /api/reservation/source-notifications/{notificationId}`。
|
||||
- M002 V4 CP6/CP7/CP8 已开放 V4 普通卡片确认、S10/S99 来源通知 ack、`REVIEW_REQUIRED` 卡复核解阻、复核场景订单归属确认、固定种子目录校验和 V4 卡片 `fields[]` 字段白名单。
|
||||
- M002 V4 CP6/CP7/CP8/CP11 已开放 V4 普通卡片确认、S10/S99 来源通知 ack、`REVIEW_REQUIRED` 卡复核解阻、复核场景订单归属确认、当前酒店数据库目录校验、V4 卡片 `fields[]` 字段白名单和 Account / Room Type / Rate Code lookup API。
|
||||
- V4 包级契约错误在 `source_message.source_message_id` 可定位时只写 `adapter_contract_error` transition,不创建订单、任务或用户可处理卡;`source_message_id` 缺失或 SourceMessage 不存在时仍返回明确错误。
|
||||
- V4 `PAYMENT.attachment_ids[]` 必须匹配 `source_message.attachments[].id`;V4 `UPDATE_BOOKING` 不接受 `rate_code` 或 `after.rate_code`;这类契约错误只落 `adapter_contract_error` transition,不创建用户可处理业务任务。
|
||||
- 40 条 P0.1 路由枚举 / 稳定配置。
|
||||
@@ -477,13 +477,13 @@ M002 V4 CP2 设计文档已落地:
|
||||
|
||||
- 文档路径:`docs/project/requirements/M002-v4-order-task-card-domain-model-cp2.md`。
|
||||
- 设计内容:SourceMessage 邮件展示卡、S10/S99 来源通知、`source_message_id + order_ref` 订单任务、Basic Information 独立卡、每个 V4 event 的业务卡、卡片确认 / 复核 / 锁定、同订单阻塞、表结构草案和后续接口草案。
|
||||
- 已确认:V4 工作台统一列表新开 `/api/reservation/workbench-items`,业务订单任务新开 `/api/reservation/order-tasks/**`,S10/S99 来源通知使用 `/api/reservation/source-notifications/**`;S10/S99 采用来源通知模型;`FIT + BOOKING_CODE` 不建 ACTIVE 唯一约束,匹配多条进人工复核;Basic Information 必须先确认,其它业务卡第一版不强制逐张确认;Account / Market / Source 目录第一版使用后端固定种子数据。
|
||||
- 当前状态:CP3 表结构 / Repository、CP4 入站写入新模型、CP5 查询接口、CP6 普通卡片确认 / S10/S99 ack、CP7 复核解阻和 CP8 固定目录 / 字段白名单已完成;V4 前端页面仍未实现。
|
||||
- 已确认:V4 工作台统一列表新开 `/api/reservation/workbench-items`,业务订单任务新开 `/api/reservation/order-tasks/**`,S10/S99 来源通知使用 `/api/reservation/source-notifications/**`;S10/S99 采用来源通知模型;`FIT + BOOKING_CODE` 不建 ACTIVE 唯一约束,匹配多条进人工复核;Basic Information 必须先确认,其它业务卡第一版不强制逐张确认;Account / Market / Source 目录当前按数据库目录读取和派生,真实目录与 Lookup API 设计见 `M002-v4-real-catalog-lookup-api-design.md`。
|
||||
- 当前状态:CP3 表结构 / Repository、CP4 入站写入新模型、CP5 查询接口、CP6 普通卡片确认 / S10/S99 ack、CP7 复核解阻、CP8 目录校验 / 字段白名单和 CP11 DB 目录 / lookup API 已完成;V4 前端页面仍未实现。
|
||||
|
||||
仍需后续 checkpoint 实现:
|
||||
|
||||
- V4 表结构和 Repository 落地已完成第一版:新增 V4 订单任务表、V4 任务卡表和 V4 来源通知表,并提供 Entity、Mapper、Repository、幂等创建、`order_context_index` 稳定排序、非 event 卡 `source_event_index=0` 和 version 乐观锁更新基础方法。
|
||||
- V4 入站写入新模型已完成第一版:真正创建 SourceMessage 展示卡、Basic Information 卡、业务卡和 S10/S99 来源通知。
|
||||
- V4 前端页面模型切换。
|
||||
- 真实 PMS 目录、Rate Code 配置中心或通用 lookup API 接入;当前 CP8 只是后端固定种子目录第一版。
|
||||
- 真实 PMS 目录同步、Rate Code 价格 / 适用范围配置中心、目录管理后台和 SuperAgent 目录机器接口仍后置;当前 CP11 只是把固定种子导入数据库并开放前端 lookup API,不代表已接 PMS 全量目录。
|
||||
- 真实 OPERA / OHIP、普通任务任意切换订单、字段矩阵从当前扁平结构整体迁移到 0711 P0 新结构、历史旧 Parent Cancel Booking payload 批量迁移。
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
| --- | --- |
|
||||
| 文档版本 | 1.5 |
|
||||
| 日期 | 2026-07-19 |
|
||||
| 状态 | 当前 V4 字段基线;后端已完成 CP1 入站解析基线、CP2 多卡模型设计、CP3 持久化基线、CP4 入站写入新模型、CP5 查询接口和 CP6 普通卡片确认 / S10/S99 ack |
|
||||
| 状态 | 当前 V4 字段基线;后端已完成 CP1-CP8,真实目录与 Lookup API 设计已落文档 |
|
||||
| 适用范围 | 0718 业务基线下,Agent → Adapter / MCP → 信息系统的业务回调字段 |
|
||||
| 不适用范围 | 数据库表设计、前端视觉细节、真实 PMS API、技术失败后台重试、旧 M002 V3 数据兼容 |
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
本契约用于后续 M002 V4 主流程设计、后端领域建模、前端页面模型、Adapter / MCP Schema 对齐和 SuperAgent 联调。当前后端已按本文完成 V4 入站解析基线:能识别 V4 包、校验关键契约、保存 AI transition / 任务卡原始 payload,并把可映射的六类 event 先接入现有订单任务链路。
|
||||
|
||||
V4 订单任务与多卡领域模型的 CP2 设计已经单独落到 `M002-v4-order-task-card-domain-model-cp2.md`。截至 CP6,表结构、Entity、Mapper、Repository 基线已经实现,SuperAgent V4 入站已经能写入 V4 订单任务、来源邮件展示卡、Basic Information 卡、业务卡和 S10/S99 来源通知;V4 工作台、订单任务列表 / 详情、来源通知详情查询接口、普通卡片确认和 S10/S99 ack 写接口已实现,V4 复核写接口仍未实现。
|
||||
V4 订单任务与多卡领域模型的 CP2 设计已经单独落到 `M002-v4-order-task-card-domain-model-cp2.md`。截至 CP11,表结构、Entity、Mapper、Repository、SuperAgent V4 入站写入、V4 查询、普通卡片确认、S10/S99 ack、V4 复核解阻、数据库目录和 Account / Room Type / Rate Code Lookup API 已实现。真实 PMS 同步和目录管理后台仍后置,方案见 `M002-v4-real-catalog-lookup-api-design.md`。
|
||||
|
||||
当前已确认开发阶段数据可以清空,因此 M002 V4 后续可以按新模型重建,不要求兼容旧任务数据、旧草稿、旧 OPERA 模拟、旧 `S000/S999`、旧 Fallback 或旧 `case_keys`。
|
||||
|
||||
@@ -193,13 +193,13 @@ Agent 给出非空 `account_code`,但信息系统运行时目录不存在该
|
||||
|
||||
不同 `order_ref` 可以对应不同 Account。
|
||||
|
||||
后端 CP8 第一版已落地固定种子目录:
|
||||
后端 CP11 第一版已落地当前酒店数据库目录:
|
||||
|
||||
- Account:`QBD_TRAVEL`、`LIAN_TAI`、`HANATOUR_TD`。
|
||||
- Market / Source:由 Account 派生,当前分别为 `LEISURE` / `TRAVEL_AGENT`。
|
||||
- SuperAgent 不需要输出 `market_code`、`source_code`、`account_name`,也不要输出显示名称替代 `account_code`。
|
||||
- 如果 SuperAgent 输出的 `account_code` 不在上述目录,后端会创建 `REVIEW_REQUIRED` Basic Information 卡,并在 `validation_errors_json` / 查询 `fields[].validation_errors` 中返回目录错误。
|
||||
- 如果 SuperAgent 输出的业务卡 `room_items[].room_type_code` 或 `rate_code` 不在上述固定目录,后端会创建 `REVIEW_REQUIRED` 业务卡,并在 `validation_errors_json` / 查询 `fields[].validation_errors` 中返回目录错误;用户可通过 V4 复核解阻接口提交对应字段 pointer 修正。
|
||||
- 如果 SuperAgent 输出的业务卡 `room_items[].room_type_code` 或 `rate_code` 不在当前酒店数据库目录,后端会创建 `REVIEW_REQUIRED` 业务卡,并在 `validation_errors_json` / 查询 `fields[].validation_errors` 中返回目录错误;用户可通过 V4 复核解阻接口提交对应字段 pointer 修正。
|
||||
|
||||
## 8. message_events 公共字段
|
||||
|
||||
@@ -639,7 +639,7 @@ Account、RoomType、RateCode、Department 的目录由信息系统或其主数
|
||||
- Agent 输出非空 code、但信息系统目录不存在该值时,属于目录校验或契约问题。
|
||||
- Market 和 Source 由信息系统根据订单级 `account_code` 派生,不由 Agent 输出。
|
||||
|
||||
当前项目接受“SuperAgent 确定后把目录给本系统”的落地方式。第一阶段可以先以固定种子目录或版本化目录快照对齐;后续如需在线查询或目录同步接口,再另开需求。
|
||||
当前项目接受“SuperAgent 确定后把目录给本系统”的落地方式。第一阶段已用固定种子目录完成开发闭环;真实目录、系统管理维护、PMS / OPERA / OHIP 同步、前端 lookup API、缓存、权限和兜底策略已在 `M002-v4-real-catalog-lookup-api-design.md` 中设计。该设计不改变 SuperAgent V4 输入契约:SuperAgent 仍只输出稳定 code,不输出显示名或自由文本。
|
||||
|
||||
## 21. 后端 V4 建模建议
|
||||
|
||||
@@ -674,7 +674,7 @@ AI 回调包
|
||||
| `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 目录 | 信息系统主数据是唯一事实源,目录同步方式后置 |
|
||||
| code 目录 | 信息系统数据库目录是唯一运行时事实源;当前目录由固定种子初始化导入,真实 PMS 同步与管理维护见 `M002-v4-real-catalog-lookup-api-design.md` |
|
||||
| 技术异常 channel | 需要独立建设,不进入酒店用户任务体系;当前先保留设计空间 |
|
||||
| Payment 附件 | 正常 Payment 必须 `attachment_ids.length > 0` |
|
||||
| `manual_review` validator | 按各对象条件 Schema 校验,必须能由可识别未解决字段解释 |
|
||||
@@ -682,7 +682,7 @@ AI 回调包
|
||||
| Fit Booking Code 临时定位 | 当前无 Confirmation Number 时可用 Booking Code 查本地订单投影;第一版不建立 ACTIVE 唯一约束,匹配多条进入人工复核 |
|
||||
| V4 前端资源路径 | 新开 `/api/reservation/order-tasks/**`,不扩展旧 `/api/reservation/tasks/**` 作为 V4 主入口 |
|
||||
| Basic Information 前置 | Basic Information 必须先确认;业务卡之间第一版不强制逐张顺序确认 |
|
||||
| Account 目录 | 第一版使用信息系统后端固定种子数据 |
|
||||
| Account 目录 | 第一版使用当前酒店数据库 Account 目录;`FIXED_SEED_IMPORT` 仅表示初始化来源,不代表运行时代码固定兜底 |
|
||||
|
||||
## 23. 后续仍需技术对齐
|
||||
|
||||
@@ -691,7 +691,7 @@ AI 回调包
|
||||
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,以及目录版本如何管理。
|
||||
4. Account、RoomType、RateCode、Department 目录如何提供给 SuperAgent,仍需在真实目录实现后确认是离线目录包还是独立机器接口。
|
||||
5. 如需 `event_id` 或幂等键,应作为 transport 字段设计,不作为业务页面字段。
|
||||
|
||||
## 24. 当前开发结论
|
||||
@@ -741,7 +741,7 @@ AI 回调包
|
||||
- `POST /api/reservation/order-tasks/{orderTaskId}/cards/{cardId}/confirm` 确认 V4 卡片,强制 Bearer 登录、`RESERVATION_TASK_CONFIRM`、酒店访问权和 version 并发校验。
|
||||
- `POST /api/reservation/source-notifications/{notificationId}/ack` 确认 V4 S10/S99 来源通知已读 / 已处理,强制 Bearer 登录、`RESERVATION_TASK_CONFIRM`、酒店访问权和 version 并发校验。
|
||||
- CP7 已完成 `POST /api/reservation/order-tasks/{orderTaskId}/cards/{cardId}/review-resolution` 复核解阻和复核场景订单归属确认。
|
||||
- CP8 已完成 Account 固定目录校验、Market / Source 派生、Room Type / Rate Code 第一版固定种子校验和 V4 任务卡 `fields[]` 白名单。
|
||||
- CP8 已完成 Account / Room Type / Rate Code 目录校验和 V4 任务卡 `fields[]` 白名单;CP11 已把固定种子导入数据库目录并开放 Account / Room Type / Rate Code lookup API。真实 PMS 同步和目录管理后台仍未实现。
|
||||
|
||||
当前仍未完成:
|
||||
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 文档版本 | 0.4 |
|
||||
| 文档版本 | 0.6 |
|
||||
| 日期 | 2026-07-19 |
|
||||
| 状态 | CP2 设计已确认;CP3 表结构、Entity、Mapper、Repository 基线已实现;CP4 入站写入新模型已实现;CP5 查询接口和订单详情 V4 时间线已实现;CP6 卡片确认和 S10/S99 ack 已实现 |
|
||||
| 状态 | CP2 设计已确认;CP3-CP8 已实现;CP11 DB 目录与 Lookup API V1 已实现 |
|
||||
| 适用范围 | M002 V4 入站后的订单任务、多卡、状态、查询和写操作设计 |
|
||||
| 不适用范围 | V4 复核接口、真实 PMS / OPERA / OHIP、前端页面视觉稿、历史数据迁移 |
|
||||
|
||||
@@ -16,7 +16,7 @@ M002 V4 CP1 已完成 SuperAgent V4 回调包入站解析、基础校验、路
|
||||
|
||||
本文是 CP2 设计文档,用于把 2026-07-18 V4 字段契约落成后续可开发的数据模型和接口草案。
|
||||
|
||||
截至 CP8,后端已实现本文第 10、11 节中的持久化基线,并已把 SuperAgent V4 入站结果写入新表:普通业务包创建 V4 订单任务、来源邮件展示卡、Basic Information 卡和业务卡;V4 S10/S99 创建来源通知。当前已开放 V4 工作台、订单任务列表 / 详情、来源通知详情查询接口、订单详情 V4 订单任务时间线、V4 卡片确认接口、S10/S99 来源通知 ack 接口、V4 `REVIEW_REQUIRED` 卡复核解阻接口,以及 Account / Room Type / Rate Code 固定种子目录第一版校验和卡片 `fields[]` 白名单。
|
||||
截至 CP11,后端已实现本文第 10、11 节中的持久化基线,并已把 SuperAgent V4 入站结果写入新表:普通业务包创建 V4 订单任务、来源邮件展示卡、Basic Information 卡和业务卡;V4 S10/S99 创建来源通知。当前已开放 V4 工作台、订单任务列表 / 详情、来源通知详情查询接口、订单详情 V4 订单任务时间线、V4 卡片确认接口、S10/S99 来源通知 ack 接口、V4 `REVIEW_REQUIRED` 卡复核解阻接口、当前酒店数据库目录校验、卡片 `fields[]` 白名单,以及 Account / Room Type / Rate Code lookup API。真实 PMS 同步和目录管理后台继续后置,设计见 `M002-v4-real-catalog-lookup-api-design.md`。
|
||||
|
||||
后续如本文与 `M002-v4-agent-callback-field-contract.md` 的字段契约冲突,以字段契约为准;如与安全边界冲突,以 `security-access-control-boundary.md` 为准。
|
||||
|
||||
@@ -26,7 +26,7 @@ M002 V4 CP1 已完成 SuperAgent 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 已支持 Account 固定目录校验、Market / Source 派生和 `fields[]` 白名单 |
|
||||
| Basic Information | 已写入 V4 Basic Information 独立卡 | CP6 已支持确认并锁定;CP7 已支持复核解阻;CP8 已支持目录校验和 `fields[]` 白名单;CP11 已改为按当前酒店数据库 Account 目录校验并派生 Market / Source |
|
||||
| 业务 Event | 可映射 event 临时创建旧 `workflow_reservation_task`,并已额外创建 V4 业务卡 | 旧任务链路仍作前端过渡兼容,后续 V4 查询和写接口完成后再逐步废弃 |
|
||||
| 技术错误 | 已落 `adapter_contract_error` transition | 已符合目标方向:不创建用户可处理卡 |
|
||||
| 草稿 / READY / OPERA | 仍复用 V3 草稿、READY 和 OPERA 模拟骨架 | V4 新数据确认口径是不保存草稿、确认后锁定、当前不生成 OPERA |
|
||||
@@ -171,7 +171,7 @@ V4 新数据不再提供后端草稿保存。前端可以在页面本地维护
|
||||
|
||||
- 不改写 AI 原始 payload。
|
||||
- 用户修正写入 `review_resolution_json` 和 `confirmed_payload_json`。
|
||||
- CP8 起确认和复核都会校验目录字段;Basic Information 的 `account_code` 必须来自第一版 Account 固定目录,通过后后端派生 `market_code` / `source_code`。
|
||||
- CP11 起确认和复核都会校验当前酒店数据库目录字段;Basic Information 的 `account_code` 必须来自当前酒店 ACTIVE Account 目录,通过后后端派生 `market_code` / `source_code`。
|
||||
- 通过校验后卡片直接进入 `CONFIRMED`,不再进入 V3 `READY` 状态。
|
||||
- `field_overrides[].field_pointer` 必须是当前卡 `display_payload_json` 中允许编辑的 RFC 6901 JSON Pointer;如果当前卡展示 payload 中存在显式 `missing_fields[]`,只允许提交该清单内的 pointer;如果没有显式清单,第一版只允许 `basic_information.*` 或 `business_fields.*` 下已经存在且值为 `null` / 空字符串的未解决叶子字段,或后端 `validation_errors_json` 指向的目录错误字段,不允许替换对象或数组。
|
||||
- 来源消息、路由、订单定位关系、诊断、缺失字段清单、`manual_review`、raw evidence 等只读字段不得提交。
|
||||
@@ -193,9 +193,9 @@ V4 新数据不再提供后端草稿保存。前端可以在页面本地维护
|
||||
- 用户只能从信息系统已有 Account 目录中选择。
|
||||
- 后端不得反向篡改 Agent 原始 `basic_information.manual_review`。
|
||||
|
||||
第一版 Account / Market / Source 目录使用后端固定种子数据,不依赖 SuperAgent 动态提供目录文件。后续如目录由管理后台维护或从外部系统同步,应以专项 checkpoint 设计目录版本、变更审计和回放影响。
|
||||
CP11 起 Account / Market / Source 目录使用本系统数据库目录,不依赖 SuperAgent 动态提供目录文件。当前初始目录来自固定种子导入,`source_system=FIXED_SEED_IMPORT`;V24 会覆盖 `HOTEL-TEST`、`HOTEL-DEV` 和迁移执行时已有的 `ACTIVE` 酒店。后续 Account / Market / Source 优先由系统管理维护,Room Type / Rate Code 未来优先来自 PMS / OPERA / OHIP 同步,本地目录表和 lookup API 设计见 `M002-v4-real-catalog-lookup-api-design.md`。
|
||||
|
||||
CP8 第一版固定种子:
|
||||
CP11 数据库初始化种子:
|
||||
|
||||
| 目录 | 第一版代码 |
|
||||
| --- | --- |
|
||||
@@ -205,7 +205,7 @@ CP8 第一版固定种子:
|
||||
| Room Type | `TWN`、`KING`、`DBL`、`SGL`、`TRP`、`RM1`、`RM2`、`RM3` |
|
||||
| Rate Code | `BAR`、`RACK`、`PACKAGE`、`GROUP`、`FIT` |
|
||||
|
||||
说明:Room Type / Rate Code 当前只作为确认和字段控件的第一版校验 / 选项来源代码;尚未接真实 PMS 房型目录、Rate Code 配置中心或通用 lookup API。
|
||||
说明:Room Type / Rate Code 当前只作为确认和字段控件的第一版校验 / 选项来源代码;已开放 `GET /api/reservation/lookups/accounts|room-types|rate-codes`,但尚未接真实 PMS 房型目录、Rate Code 配置中心、目录管理后台或同步 run。
|
||||
|
||||
## 8. 订单归属和 target_order
|
||||
|
||||
@@ -389,7 +389,7 @@ uk_reservation_v4_notification_message_batch(hotel_id, source_message_id, ai_bat
|
||||
| V4 草稿表 | V4 已确认不保存草稿 |
|
||||
| V4 OPERA operation 表 | 当前不做真实 OPERA / OHIP,也不生成 OPERA 模拟 |
|
||||
| 技术错误用户任务表 | 技术错误不进入用户任务体系,先用 AI transition 和 dispatch run |
|
||||
| 目录表 | Account、Market、Source 第一版已确认用后端固定种子数据;CP2 只设计边界,后续目录 checkpoint 再决定是否建表、导入或管理后台维护 |
|
||||
| 目录表 | CP11 已新增 `workflow_reservation_catalog_account`、`workflow_reservation_catalog_code`;真实同步 run 和目录管理后台后置 |
|
||||
|
||||
## 11. Entity / Mapper / Repository 边界草案
|
||||
|
||||
@@ -633,8 +633,8 @@ POST /api/reservation/order-tasks/{orderTaskId}/cards/{cardId}/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`。
|
||||
- 业务卡确认时,第一版会递归校验已有 `rate_code`、`room_items[].room_type_code` 是否在固定目录中;`UPDATE_BOOKING` 等嵌套结构会返回类似 `business_fields.after.room_items.0.room_type_code` 的错误路径,失败返回 `V4_FIELD_VALIDATION_FAILED`。
|
||||
- Basic Information 确认时 `basic_information.account_code` 必须是当前酒店数据库 Account 目录值;后端确认前会派生 `account_name`、`market_code` 和 `source_code` 写入 `confirmed_payload_json`。
|
||||
- 业务卡确认时,第一版会递归校验已有 `rate_code`、`room_items[].room_type_code` 是否在当前酒店数据库目录中;`UPDATE_BOOKING` 等嵌套结构会返回类似 `business_fields.after.room_items.0.room_type_code` 的错误路径,失败返回 `V4_FIELD_VALIDATION_FAILED`。
|
||||
- 不提交草稿。
|
||||
- 必须带 `version` 做并发校验。
|
||||
- 后端确认后卡片 `CONFIRMED` 并锁定。
|
||||
@@ -744,6 +744,10 @@ AI 原始 payload、邮件正文、附件 URL 和技术 trace 不应直接进入
|
||||
| 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 | PMS / OPERA / OHIP 目录同步 | 同步 Adapter、同步 run、最后成功快照、失败重试和同步状态管理入口 |
|
||||
|
||||
## 17. 已确认设计决策
|
||||
|
||||
@@ -753,7 +757,7 @@ AI 原始 payload、邮件正文、附件 URL 和技术 trace 不应直接进入
|
||||
4. S10/S99 采用来源通知模型:任务列表 / 工作台展示,不挂隐藏技术订单;通知详情只显示邮件展示卡和确认按钮。
|
||||
5. S10/S99 不创建订单、不进订单列表、不参与订单阻塞,也不支持编辑、复核、OPERA 或人工终止。
|
||||
6. 第一版不强制所有业务卡逐张顺序确认,但 Basic Information 必须先确认。
|
||||
7. Basic Information 的 Account / Market / Source 目录第一版使用后端固定种子数据。
|
||||
7. Basic Information 的 Account / Market / Source 目录当前使用本系统数据库目录;第一版初始化数据来自固定种子导入,但运行时不再读取后端固定 Map。
|
||||
8. 普通业务邮件的来源邮件展示卡只读展示,不需要用户确认;用户只确认 Basic Information 和具体业务卡。
|
||||
9. S10/S99 因为没有业务卡,邮件展示卡需要确认按钮,用来记录已读 / 已处理。
|
||||
10. V4 新模型落地并完成前端切换后,旧 V2/V3 任务详情、草稿保存和最终确认接口可以逐步废弃。
|
||||
|
||||
@@ -0,0 +1,494 @@
|
||||
# M002 V4 真实目录与 Lookup API 设计
|
||||
|
||||
## 文档信息
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 文档版本 | 0.2 |
|
||||
| 日期 | 2026-07-19 |
|
||||
| 状态 | CP11 已落地第一版数据库目录与 lookup API;后续真实 PMS 同步和目录管理后台继续后置 |
|
||||
| 适用范围 | M002 V4 Account、Market、Source、Room Type、Rate Code 目录来源、数据模型、前端 lookup、缓存、酒店隔离、权限和失败兜底 |
|
||||
| 不适用范围 | 真实 OPERA / OHIP 写操作、真实价格计算、前端页面实现、SuperAgent Prompt 修改、目录管理后台、SuperAgent 机器目录接口 |
|
||||
|
||||
## 1. 文档定位
|
||||
|
||||
M002 V4 CP8 已实现第一版固定种子目录校验;M002 V4 CP11 已把该目录迁移为数据库目录和前端 lookup API:
|
||||
|
||||
- Basic Information 的 `account_code` 必须存在于当前酒店数据库 Account 目录。
|
||||
- Market / Source 由 Account 派生,不由 SuperAgent 输出。
|
||||
- Room Type / Rate Code 第一版使用当前酒店数据库目录校验和字段选项提示。
|
||||
- 目录错误会让对应 V4 卡片进入 `REVIEW_REQUIRED`,用户通过复核解阻选择合法 code。
|
||||
|
||||
本文记录真实目录和 lookup API 的设计与 CP11 第一版实现。CP11 新增 `workflow_reservation_catalog_account`、`workflow_reservation_catalog_code` 两张表,并通过 Flyway 初始化 `HOTEL-TEST`、`HOTEL-DEV` 以及迁移执行时已存在的 `ACTIVE` 平台酒店的固定种子目录;不再在运行时代码中把固定种子作为全局目录事实。`workflow_reservation_catalog_sync_run`、真实 PMS / OPERA / OHIP 同步、目录管理后台和 SuperAgent 机器目录供给接口继续后置。
|
||||
|
||||
后续若本文与 `M002-v4-agent-callback-field-contract.md` 的 Agent 输入字段冲突,以 Agent 字段契约为准;若与 `security-access-control-boundary.md` 的接口权限冲突,以安全边界为准。
|
||||
|
||||
## 2. 当前固定种子目录
|
||||
|
||||
CP11 之前固定种子实现位于后端 `ReservationV4DirectoryService` 和 `FixedReservationV4DirectoryServiceImpl`。CP11 起实现改为 `ReservationV4DatabaseDirectoryServiceImpl`,目录读取只走数据库目录表;固定种子通过 `V24__create_reservation_catalog_tables.sql` 初始化导入 dev/test 基准酒店和迁移时已有 `ACTIVE` 酒店,来源标记为 `FIXED_SEED_IMPORT`。
|
||||
|
||||
| 目录 | 当前用途 | 当前固定值 | 当前限制 |
|
||||
| --- | --- | --- | --- |
|
||||
| Account | Basic Information 可选目录;SuperAgent 和用户提交都使用稳定 code | `QBD_TRAVEL`、`LIAN_TAI`、`HANATOUR_TD` | 已进入数据库初始化目录,仍不是 PMS 全量 Account,管理后台后置 |
|
||||
| Market | 由 Account 派生的订单级 Market | 当前 Account 均派生 `LEISURE` | 已进入通用代码目录,前端仍不直接编辑 |
|
||||
| Source | 由 Account 派生的订单级 Source | 当前 Account 均派生 `TRAVEL_AGENT` | 已进入通用代码目录,前端仍不直接编辑 |
|
||||
| Room Type | 房型 code 校验和字段选项提示 | `TWN`、`KING`、`DBL`、`SGL`、`TRP`、`RM1`、`RM2`、`RM3` | 已进入数据库初始化目录,仍不是 PMS 全量房型 |
|
||||
| Rate Code | Rate Code 校验和字段选项提示 | `BAR`、`RACK`、`PACKAGE`、`GROUP`、`FIT` | 已进入数据库初始化目录,不按日期、账号、房型过滤,不含价格 |
|
||||
|
||||
当前固定种子只能支撑开发和演示闭环,不能作为生产长期事实源。
|
||||
|
||||
## 3. 设计目标
|
||||
|
||||
真实目录能力要解决以下问题:
|
||||
|
||||
1. 前端不再硬编码 Account、Room Type、Rate Code 选项。
|
||||
2. 后端确认和复核仍然是最终校验者,前端 lookup 只用于选择体验。
|
||||
3. 每个目录都按 `hotel_id` 隔离,不能跨酒店泄露目录。
|
||||
4. 目录有来源、版本、更新时间和启停状态,便于排查 SuperAgent 输出 code 与系统目录不一致的问题。
|
||||
5. PMS / OPERA / OHIP 不稳定或暂未接入时,系统仍可使用最后一次成功目录快照或系统管理目录兜底。
|
||||
6. 固定种子目录可以作为 dev/test 或导入初始化兜底,但生产不应默认靠代码固定值。
|
||||
|
||||
## 4. 目录来源分层
|
||||
|
||||
目录来源按阶段分三层,后续可以逐步切换,不要求一步接真实 PMS。
|
||||
|
||||
| 阶段 | 来源 | 中文说明 | 适用目录 |
|
||||
| --- | --- | --- | --- |
|
||||
| Phase 0 | `FIXED_SEED_IMPORT` | CP11 已将固定种子通过 Flyway 导入数据库,不再作为运行时代码全局 Map | 当前 Account、Market、Source、Room Type、Rate Code |
|
||||
| Phase 1 | `SYSTEM_MANAGED` | 本系统数据库目录,由初始化脚本、管理后台或导入文件维护 | Account、Market、Source;也可临时维护 Room Type、Rate Code |
|
||||
| Phase 2 | `PMS_SYNC` | 后端从 PMS / OPERA / OHIP 同步目录到本系统本地表,业务查询只读本地快照 | Room Type、Rate Code 优先;Account、Market、Source 视 PMS 能力再接 |
|
||||
|
||||
原则:
|
||||
|
||||
- 业务确认接口只依赖本系统目录服务,不直接调用外部 PMS。
|
||||
- 真实 PMS / OHIP Adapter 只负责同步目录快照,不把厂商 DTO 直接暴露给业务服务或前端。
|
||||
- 同一目录可有 `source_system` 标记,但业务接口只使用稳定 `code`。
|
||||
|
||||
## 5. 目录归属建议
|
||||
|
||||
| 目录 | 第一版真实来源建议 | 未来 PMS / OPERA / OHIP 方向 | 前端是否可编辑 | 说明 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| Account | 本系统管理目录优先 | 可选同步 PMS profile / company / travel agent 主数据,但本系统仍维护映射 code | 是,Basic Information 选择 Account | Account 影响 Market / Source 派生,第一版建议先由系统管理维护,避免 PMS profile 字段未确认导致业务不可用 |
|
||||
| Market | 本系统管理目录 | 可选同步 PMS market code 配置 | 否,随 Account 派生展示 | 前端不直接改 Market;修改 Account 后后端派生 Market |
|
||||
| Source | 本系统管理目录 | 可选同步 PMS source code 配置 | 否,随 Account 派生展示 | 前端不直接改 Source;修改 Account 后后端派生 Source |
|
||||
| Room Type | PMS / OPERA / OHIP 同步目录优先 | 同步酒店有效房型、展示名、人数、启停状态 | 是,业务卡选择房型 | 若 PMS 未接入,可临时由系统管理维护或固定种子初始化 |
|
||||
| Rate Code | PMS / OPERA / OHIP 同步目录优先 | 同步有效 Rate Plan / Rate Code;价格和日期适用规则后置 | 是,New Booking 选择 Rate Code | 第一版 lookup 只选 code,不做价格计算 |
|
||||
|
||||
Department 目录在 V4 字段契约中也会被 Trace 使用,但当前固定种子 CP8 尚未实现。后续可沿用本文模型扩展 `DEPARTMENT`,不放入本 checkpoint。
|
||||
|
||||
## 6. 数据模型草案
|
||||
|
||||
### 6.1 推荐表:`workflow_reservation_catalog_account`
|
||||
|
||||
Account 单独建表,原因是它不仅有显示名称,还要派生 Market / Source。
|
||||
|
||||
| 字段 | 中文说明 |
|
||||
| --- | --- |
|
||||
| `id` | 内部主键 ID |
|
||||
| `hotel_id` | 酒店 ID,目录按酒店隔离 |
|
||||
| `account_code` | Account 稳定 code,大小写敏感 |
|
||||
| `account_name` | Account 显示名称 |
|
||||
| `market_code` | 该 Account 派生的 Market code |
|
||||
| `source_code` | 该 Account 派生的 Source code |
|
||||
| `status` | `ACTIVE` / `DISABLED` |
|
||||
| `source_system` | `SYSTEM_MANAGED` / `PMS_SYNC` / `FIXED_SEED_IMPORT` |
|
||||
| `external_account_id` | 外部 PMS profile 或 account ID,可为空 |
|
||||
| `catalog_version` | 目录版本,用于前端缓存和排查 |
|
||||
| `last_synced_at` | 外部同步成功 UTC 时间;系统管理数据可为空 |
|
||||
| `metadata_json` | 扩展元数据,不替代可查询字段 |
|
||||
| `version` | 乐观锁版本 |
|
||||
| `created_at` / `updated_at` | UTC 创建和更新时间 |
|
||||
| `logic_deleted_at` / `logic_deleted_reason` | 逻辑删除时间和原因 |
|
||||
|
||||
建议唯一约束:
|
||||
|
||||
```text
|
||||
uk_reservation_catalog_account_code(hotel_id, account_code)
|
||||
```
|
||||
|
||||
### 6.2 推荐表:`workflow_reservation_catalog_code`
|
||||
|
||||
Market、Source、Room Type、Rate Code 可先使用统一 code 表。
|
||||
|
||||
| 字段 | 中文说明 |
|
||||
| --- | --- |
|
||||
| `id` | 内部主键 ID |
|
||||
| `hotel_id` | 酒店 ID,目录按酒店隔离 |
|
||||
| `catalog_type` | `MARKET` / `SOURCE` / `ROOM_TYPE` / `RATE_CODE` |
|
||||
| `code` | 稳定目录 code,大小写敏感 |
|
||||
| `display_name` | 前端显示名称 |
|
||||
| `status` | `ACTIVE` / `DISABLED` |
|
||||
| `source_system` | `SYSTEM_MANAGED` / `PMS_SYNC` / `FIXED_SEED_IMPORT` |
|
||||
| `external_id` | 外部 PMS / OPERA / OHIP ID,可为空 |
|
||||
| `sort_order` | 前端默认排序 |
|
||||
| `effective_from` / `effective_to` | 生效日期范围,可为空;酒店本地业务日期语义 |
|
||||
| `catalog_version` | 目录版本,用于前端缓存和排查 |
|
||||
| `last_synced_at` | 外部同步成功 UTC 时间 |
|
||||
| `metadata_json` | 扩展元数据,例如房型人数、Rate Code 适用说明 |
|
||||
| `version` | 乐观锁版本 |
|
||||
| `created_at` / `updated_at` | UTC 创建和更新时间 |
|
||||
| `logic_deleted_at` / `logic_deleted_reason` | 逻辑删除时间和原因 |
|
||||
|
||||
建议唯一约束:
|
||||
|
||||
```text
|
||||
uk_reservation_catalog_code(hotel_id, catalog_type, code)
|
||||
```
|
||||
|
||||
### 6.3 推荐表:`workflow_reservation_catalog_sync_run`
|
||||
|
||||
如果接 PMS / OPERA / OHIP 同步,建议记录每次同步运行。
|
||||
|
||||
CP11 本轮没有创建该表。原因是当前不接真实 PMS / OPERA / OHIP 同步,暂时没有同步运行事实可记录;后续做同步 worker 或目录管理后台时,再新增该表和对应 Repository。
|
||||
|
||||
| 字段 | 中文说明 |
|
||||
| --- | --- |
|
||||
| `id` | 同步运行 ID |
|
||||
| `hotel_id` | 酒店 ID |
|
||||
| `catalog_type` | 同步目录类型 |
|
||||
| `source_system` | 外部来源系统 |
|
||||
| `sync_status` | `SUCCESS` / `FAILED` / `PARTIAL_SUCCESS` |
|
||||
| `started_at` / `finished_at` | UTC 开始和结束时间 |
|
||||
| `catalog_version` | 本次生成的目录版本 |
|
||||
| `items_seen_count` | 外部返回数量 |
|
||||
| `items_upserted_count` | 本系统写入或更新数量 |
|
||||
| `items_disabled_count` | 本系统停用数量 |
|
||||
| `safe_error_summary` | 安全错误摘要,不保存 Secret 或完整外部响应 |
|
||||
| `created_at` / `updated_at` | UTC 创建和更新时间 |
|
||||
|
||||
同步 run 是技术追踪,不直接给普通业务前端展示完整细节。管理后台后续如展示同步记录,应单独登记权限和脱敏规则。
|
||||
|
||||
## 7. 后端服务边界
|
||||
|
||||
CP11 已替换当前 `FixedReservationV4DirectoryServiceImpl`,保留 `ReservationV4DirectoryService` 作为业务稳定端口。
|
||||
|
||||
```text
|
||||
workflows.reservation.service
|
||||
ReservationV4DirectoryService
|
||||
- findAccount(hotelId, accountCode)
|
||||
- isKnownRoomTypeCode(hotelId, roomTypeCode)
|
||||
- isKnownRateCode(hotelId, rateCode)
|
||||
|
||||
workflows.reservation.repository
|
||||
ReservationV4CatalogRepository
|
||||
- 只封装本地目录表查询,不直接调用 PMS
|
||||
|
||||
workflows.reservation.service
|
||||
ReservationV4CatalogLookupService
|
||||
- listAccounts(...)
|
||||
- listRoomTypes(...)
|
||||
- listRateCodes(...)
|
||||
|
||||
integrations.ohip / integrations.pms
|
||||
CatalogSyncAdapter
|
||||
- 后续从 PMS / OPERA / OHIP 拉取目录并转换为本系统目录草稿
|
||||
```
|
||||
|
||||
规则:
|
||||
|
||||
- V4 入站、确认、复核只调用 `ReservationV4DirectoryService`。
|
||||
- 前端 lookup Controller 调用 `ReservationV4CatalogLookupService`,该服务同样只读本地目录表。
|
||||
- PMS / OHIP 同步 Adapter 只能写本地目录表或同步 run,不直接参与用户确认事务。
|
||||
- 如果目录服务不可用,确认接口 fail closed,不接受自由文本。
|
||||
|
||||
## 8. Lookup API 草案
|
||||
|
||||
Lookup API 属于前端业务查询接口,不给 SuperAgent 或 AgentBus 调用。
|
||||
|
||||
统一要求:
|
||||
|
||||
- 分类:`FRONTEND_USER`。
|
||||
- 鉴权:Bearer session token。
|
||||
- 权限:第一版建议复用 `RESERVATION_TASK_READ`;目录维护后台另行使用管理权限。
|
||||
- 酒店隔离:`hotel_id` 可选;不传时按当前用户默认酒店解析,传入时必须校验用户可访问。
|
||||
- 返回:只返回目录 code、显示名、状态、来源和安全元数据,不返回外部 PMS 原始响应。
|
||||
- 分页:`page_num` 从 1 开始,`page_size` 后端限制最大值。
|
||||
|
||||
### 8.1 Account Lookup
|
||||
|
||||
```text
|
||||
GET /api/reservation/lookups/accounts
|
||||
```
|
||||
|
||||
查询参数:
|
||||
|
||||
| 参数 | 必需 | 中文说明 |
|
||||
| --- | --- | --- |
|
||||
| `hotel_id` | 否 | 当前酒店 ID;未传时按当前用户默认酒店 |
|
||||
| `keyword` | 否 | 匹配 `account_code` 或 `account_name` |
|
||||
| `page_num` / `page_size` | 否 | 分页 |
|
||||
|
||||
第一版固定只返回 `ACTIVE` Account,不开放 `active_only=false`。
|
||||
|
||||
响应草案:
|
||||
|
||||
```json
|
||||
{
|
||||
"hotel_id": "HOTEL-TEST",
|
||||
"catalog_type": "ACCOUNT",
|
||||
"catalog_source": "FIXED_SEED_IMPORT",
|
||||
"catalog_version": "seed-20260719-v1",
|
||||
"stale": false,
|
||||
"items": [
|
||||
{
|
||||
"code": "QBD_TRAVEL",
|
||||
"display_name": "Q.B.D. TRAVEL GROUP CO., LTD",
|
||||
"status": "ACTIVE",
|
||||
"catalog_source": "FIXED_SEED_IMPORT",
|
||||
"market_code": "LEISURE",
|
||||
"market_name": "LEISURE",
|
||||
"source_code": "TRAVEL_AGENT",
|
||||
"source_name": "TRAVEL_AGENT"
|
||||
}
|
||||
],
|
||||
"page": {
|
||||
"page_num": 1,
|
||||
"page_size": 20,
|
||||
"total": 1
|
||||
},
|
||||
"warnings": []
|
||||
}
|
||||
```
|
||||
|
||||
前端用途:
|
||||
|
||||
- `fields[].options_source=reservation_v4_account_catalog` 时调用。
|
||||
- 用户选择 Account 后,前端可以立即展示响应中的 Market / Source;最终以后端确认接口派生结果为准。
|
||||
- 不允许用户自由输入 Account code。
|
||||
|
||||
### 8.2 Room Type Lookup
|
||||
|
||||
```text
|
||||
GET /api/reservation/lookups/room-types
|
||||
```
|
||||
|
||||
查询参数:
|
||||
|
||||
| 参数 | 必需 | 中文说明 |
|
||||
| --- | --- | --- |
|
||||
| `hotel_id` | 否 | 当前酒店 ID |
|
||||
| `keyword` | 否 | 匹配房型 code 或显示名 |
|
||||
| `page_num` / `page_size` | 否 | 分页 |
|
||||
|
||||
第一版固定只返回 `ACTIVE` Room Type,不接 `arrival_date` / `departure_date`,日期适用范围过滤后置。
|
||||
|
||||
响应草案:
|
||||
|
||||
```json
|
||||
{
|
||||
"hotel_id": "HOTEL-TEST",
|
||||
"catalog_type": "ROOM_TYPE",
|
||||
"catalog_source": "FIXED_SEED_IMPORT",
|
||||
"catalog_version": "seed-20260719-v1",
|
||||
"stale": false,
|
||||
"items": [
|
||||
{
|
||||
"code": "RM2",
|
||||
"display_name": "RM2",
|
||||
"status": "ACTIVE",
|
||||
"catalog_source": "FIXED_SEED_IMPORT",
|
||||
"adult_capacity": 2
|
||||
}
|
||||
],
|
||||
"page": {
|
||||
"page_num": 1,
|
||||
"page_size": 20,
|
||||
"total": 1
|
||||
},
|
||||
"warnings": []
|
||||
}
|
||||
```
|
||||
|
||||
前端用途:
|
||||
|
||||
- `fields[].options_source=reservation_v4_room_type_catalog` 时调用。
|
||||
- V4 业务卡里的 `room_items[].room_type_code`、`business_fields.after.room_items[].room_type_code`、加床目标房型等都应从该接口选。
|
||||
- 前端不要把旧固定种子当 PMS 全量房型。
|
||||
|
||||
### 8.3 Rate Code Lookup
|
||||
|
||||
```text
|
||||
GET /api/reservation/lookups/rate-codes
|
||||
```
|
||||
|
||||
查询参数:
|
||||
|
||||
| 参数 | 必需 | 中文说明 |
|
||||
| --- | --- | --- |
|
||||
| `hotel_id` | 否 | 当前酒店 ID |
|
||||
| `keyword` | 否 | 匹配 Rate Code 或显示名 |
|
||||
| `page_num` / `page_size` | 否 | 分页 |
|
||||
|
||||
第一版固定只返回 `ACTIVE` Rate Code,不接 `booking_type`、`account_code`、`arrival_date` / `departure_date`,适用范围和价格过滤后置。
|
||||
|
||||
响应草案:
|
||||
|
||||
```json
|
||||
{
|
||||
"hotel_id": "HOTEL-TEST",
|
||||
"catalog_type": "RATE_CODE",
|
||||
"catalog_source": "FIXED_SEED_IMPORT",
|
||||
"catalog_version": "seed-20260719-v1",
|
||||
"stale": false,
|
||||
"items": [
|
||||
{
|
||||
"code": "GROUP",
|
||||
"display_name": "GROUP",
|
||||
"status": "ACTIVE",
|
||||
"catalog_source": "FIXED_SEED_IMPORT",
|
||||
"pricing_available": false
|
||||
}
|
||||
],
|
||||
"page": {
|
||||
"page_num": 1,
|
||||
"page_size": 20,
|
||||
"total": 1
|
||||
},
|
||||
"warnings": []
|
||||
}
|
||||
```
|
||||
|
||||
前端用途:
|
||||
|
||||
- `fields[].options_source=reservation_v4_rate_code_catalog` 时调用。
|
||||
- 第一版只选 `rate_code`,不展示或计算真实价格。
|
||||
- V4 契约仍禁止 `UPDATE_BOOKING` 携带 Rate Code;lookup API 不改变该规则。
|
||||
|
||||
### 8.4 Market / Source Lookup
|
||||
|
||||
Market / Source 第一版不作为用户可编辑字段,不建议给普通业务表单单独开放选择。
|
||||
|
||||
如果后续系统管理后台需要维护 Market / Source,可使用管理接口或通用目录接口,但不应让 V4 Basic Information 页面绕过 Account 派生规则。
|
||||
|
||||
## 9. `fields[]` 与 lookup 的关系
|
||||
|
||||
后端任务详情字段仍是前端渲染白名单。Lookup API 只解决选项来源,不决定字段是否展示或可编辑。
|
||||
|
||||
| `options_source` | 对应 lookup | 前端行为 |
|
||||
| --- | --- | --- |
|
||||
| `reservation_v4_account_catalog` | `GET /api/reservation/lookups/accounts` | 渲染 Account 下拉 / 搜索选择,展示派生 Market / Source |
|
||||
| `reservation_v4_room_type_catalog` | `GET /api/reservation/lookups/room-types` | 渲染房型搜索选择 |
|
||||
| `reservation_v4_rate_code_catalog` | `GET /api/reservation/lookups/rate-codes` | 渲染 Rate Code 搜索选择 |
|
||||
| `static_enum` | 使用 `fields[].enum_options` | 不调用 lookup |
|
||||
| `system_case_lookup` | 后续订单 / 任务对象 lookup | 不属于本目录 checkpoint |
|
||||
|
||||
前端提交时仍按卡片确认或复核接口提交字段值。后端确认前再次校验目录,不能因为前端选项来自 lookup 就跳过后端校验。
|
||||
|
||||
## 10. 缓存设计
|
||||
|
||||
缓存是优化,不是事实源。本系统本地目录表才是业务查询事实源。
|
||||
|
||||
后续建议。CP11 第一版暂不加内存缓存,直接读取本系统本地目录表;原因是当前种子目录规模很小,先保证目录事实源、酒店隔离和确认校验一致。
|
||||
|
||||
- 目录 Service 增加内存缓存,缓存 key 包含 `hotel_id`、`catalog_type`、`keyword`、`active_only`、分页和过滤参数。
|
||||
- 精确校验类查询,例如 `findAccount(hotelId, accountCode)`、`isKnownRoomTypeCode(hotelId, code)`,使用单独短 TTL 缓存。
|
||||
- TTL 建议 5 分钟;真实同步后可根据 `catalog_version` 主动失效。
|
||||
- 管理后台修改目录或同步 run 成功后,清理对应酒店和目录类型缓存。
|
||||
- 多节点部署时,第一版可以依赖短 TTL;后续如目录变更频繁,再接 Redis 或事件广播失效。
|
||||
|
||||
响应应返回:
|
||||
|
||||
| 字段 | 中文说明 |
|
||||
| --- | --- |
|
||||
| `catalog_version` | 当前目录版本,前端可用于调试和避免重复请求 |
|
||||
| `catalog_source` | 当前目录主要来源,例如 `SYSTEM_MANAGED` / `PMS_SYNC` |
|
||||
| `stale` | 当前是否为过期但可用的最后成功快照 |
|
||||
| `warnings[]` | 非阻塞警告,例如 PMS 同步失败但仍返回本地快照 |
|
||||
|
||||
## 11. 失败兜底
|
||||
|
||||
| 场景 | Lookup API 行为 | 确认 / 复核行为 |
|
||||
| --- | --- | --- |
|
||||
| 目录有本地 Active 快照 | 返回 200 和可选项 | 按目录校验,通过后确认 |
|
||||
| PMS 同步失败,但有上次成功快照 | 返回 200,`stale=true`,带 warning | 仍可按本地快照确认,并在审计或 payload 中保留目录版本 |
|
||||
| PMS 同步失败且无本地快照 | 返回 200 空列表和 warning,或按后续实现返回明确错误 | 必填目录字段 fail closed,返回 `V4_CATALOG_UNAVAILABLE` 或 `V4_FIELD_VALIDATION_FAILED` |
|
||||
| SuperAgent 输出未知非空 code | 任务卡进入 `REVIEW_REQUIRED`,`fields[].validation_errors` 指向该字段 | 用户必须选择已知 code;不能自由输入原值 |
|
||||
| 目录 code 后续停用 | 已确认卡保持历史确认快照不回滚 | 新确认不能选择停用 code,除非后续设计允许历史兼容选择 |
|
||||
| 前端提交未返回字段或自由 code | 后端忽略未开放字段;目录字段校验失败 | 不写入 `confirmed_payload_json` |
|
||||
|
||||
生产建议:
|
||||
|
||||
- `FIXED_SEED` 可用于 dev/test 和初始化导入。
|
||||
- 生产如果真实目录为空,不应静默接受固定种子;应让卡片进入复核或目录不可用错误,避免写入错误 PMS code。
|
||||
|
||||
## 12. 权限、酒店隔离和审计
|
||||
|
||||
### 12.1 Lookup 查询权限
|
||||
|
||||
第一版 lookup 查询建议:
|
||||
|
||||
| 接口 | 分类 | 权限 | 酒店隔离 | 审计 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `GET /api/reservation/lookups/accounts` | `FRONTEND_USER` | `RESERVATION_TASK_READ` | 按用户可访问酒店校验 | 只读不写业务审计 |
|
||||
| `GET /api/reservation/lookups/room-types` | `FRONTEND_USER` | `RESERVATION_TASK_READ` | 按用户可访问酒店校验 | 只读不写业务审计 |
|
||||
| `GET /api/reservation/lookups/rate-codes` | `FRONTEND_USER` | `RESERVATION_TASK_READ` | 按用户可访问酒店校验 | 只读不写业务审计 |
|
||||
|
||||
复用 `RESERVATION_TASK_READ` 的原因:
|
||||
|
||||
- Lookup 是任务详情表单选项的辅助查询能力。
|
||||
- 目录值本身不包含邮件正文、附件、AI payload 或 PMS Secret。
|
||||
- 可以避免第一版为了表单下拉再新增一个普通用户权限码,降低前端角色配置复杂度。
|
||||
|
||||
### 12.2 目录维护权限
|
||||
|
||||
目录维护不在本 checkpoint 实现。后续如果做系统管理维护,建议新增:
|
||||
|
||||
```text
|
||||
RESERVATION_CATALOG_MANAGE
|
||||
```
|
||||
|
||||
用于 Account、Market、Source、临时 Room Type、Rate Code 的系统管理维护页面。写操作必须记录管理审计或业务配置审计。
|
||||
|
||||
### 12.3 第三方接口边界
|
||||
|
||||
SuperAgent 当前不调用本 lookup API。SuperAgent 目录供给后续有两种方式:
|
||||
|
||||
1. 线下或配置文件方式把目录版本给 SuperAgent。
|
||||
2. 单独设计机器接口,例如 `GET /api/integrations/superagent/catalogs/...`,使用 HMAC 鉴权和最小字段。
|
||||
|
||||
不得让 SuperAgent 使用前端 Bearer token 或前端 lookup API。
|
||||
|
||||
## 13. 前端使用方式
|
||||
|
||||
前端建议:
|
||||
|
||||
1. 先读取 V4 订单任务详情。
|
||||
2. 遍历每张卡 `fields[]`。
|
||||
3. 只有字段 `editable=true` 且 `control_type=select/lookup` 时才加载 lookup。
|
||||
4. 根据 `options_source` 选择 lookup 接口。
|
||||
5. 搜索输入做 debounce,不一次性拉全量。
|
||||
6. 显示 `stale=true` 或 `warnings[]` 时给用户非阻塞提醒。
|
||||
7. 用户提交确认或复核时只提交 code,不提交显示名、Market / Source 派生值或目录完整对象。
|
||||
8. 确认成功后以后端返回的 `confirmed_payload_json` / 刷新详情为准更新页面。
|
||||
|
||||
前端禁止:
|
||||
|
||||
- 硬编码 PMS 房型或 Rate Code 全集。
|
||||
- 把目录显示名当业务 code 提交。
|
||||
- 绕过 `fields[]` 自行补业务字段。
|
||||
- 使用 lookup API 给 SuperAgent、AgentBus 或 Debug 链路拼接输入。
|
||||
- 在浏览器保存目录中的外部 PMS ID、同步错误详情或任何 Secret。
|
||||
|
||||
## 14. 后续开发 checkpoint
|
||||
|
||||
| Checkpoint | 目标 | 主要交付 |
|
||||
| --- | --- | --- |
|
||||
| M002-V4-CP11 | DB 管理目录与 Lookup API V1 | 新增 Account / Code 目录表、Repository、DirectoryService DB 实现、Account / Room Type / Rate Code lookup 查询接口、权限和测试 |
|
||||
| M002-V4-CP12 | 前端 Lookup 接入 | V4 卡片字段渲染按 `options_source` 调用 lookup,替换固定种子硬编码选项,处理 stale / warning / 空目录 |
|
||||
| M002-V4-CP13 | 目录管理后台 V1 | Account / Market / Source 管理,临时 Room Type / Rate Code 管理,`RESERVATION_CATALOG_MANAGE` 权限和管理审计 |
|
||||
| M002-V4-CP14 | PMS / OPERA / OHIP 目录同步 | 同步 Adapter、同步 run 表、失败重试、最后成功快照、同步状态管理入口 |
|
||||
| M002-V4-CP15 | SuperAgent 目录供给 | 明确目录版本如何给 SuperAgent,必要时新增机器目录接口或导出包 |
|
||||
|
||||
CP11 已作为后端第一步落地,因为它不依赖真实 PMS,也能让前端后续不再硬编码当前固定种子。
|
||||
|
||||
## 15. 仍需确认的问题
|
||||
|
||||
1. Account 的第一版真实维护入口是否放在现有系统管理后台,还是先用导入 SQL / Excel 导入。
|
||||
2. Account code 是否继续使用本系统定义的稳定 code,例如 `QBD_TRAVEL`,还是必须对齐 PMS profile code。
|
||||
3. Market / Source 是否只允许随 Account 派生,还是未来允许用户在 Basic Information 中单独改选。
|
||||
4. Room Type 第一版真实目录是否先由系统管理维护,还是等 PMS / OHIP 同步后再替换。
|
||||
5. Rate Code 第一版是否只校验 code,还是需要按 `booking_type`、`account_code`、入住日期过滤。
|
||||
6. 生产是否允许 `FIXED_SEED` 作为兜底,还是只允许 dev/test 使用。
|
||||
7. SuperAgent 是否需要读取目录;如果需要,是离线给目录包,还是新增 HMAC 机器接口。
|
||||
|
||||
在这些问题未确认前,CP11 仍可以先按 DB 管理目录 + 前端 lookup 查询实现,不接真实 PMS,也不替换 SuperAgent 输入契约。
|
||||
Reference in New Issue
Block a user