实现 Rooming List CP2 字段收口

This commit is contained in:
andy
2026-07-22 15:29:33 +07:00
parent 71191a10b0
commit 1236df86cf
24 changed files with 704 additions and 481 deletions

View File

@@ -47,7 +47,7 @@
| 任务卡字段控件契约 V1 | `docs/project/requirements/M002-task-field-control-contract-v1.md` | 后端已返回 `fields[]` 控件元数据,规定人工复核控件复用和前后端边界;前端待接入。 |
| 订单任务多卡模型 V4 | `docs/project/requirements/M002-v4-order-task-card-domain-model-cp2.md` | 当前 V4 主入口后端已开放工作台统一列表、V4 订单任务列表 / 详情、卡片确认、复核解阻、S10/S99 来源通知详情和 ack前端已完成 V4 页面第一版、目录 lookup 接入、订单详情 V4 时间线消费、系统设置目录管理 CP1以及 Room Information 业务展示模型接入Payment 附件预览和 Rooming List 轻量卡展示仍待后续实现。 |
| Manual Invoice 手工开票生成 | `docs/project/requirements/M009-manual-invoice-generation-v1.md` | 当前有效;后端 CP2 已支持无订单 / 无任务手工填写字段、填 Excel 模板、转 PDF、OSS 输出和生成记录。 |
| Rooming List Excel 生成 | `docs/project/requirements/M010-rooming-list-excel-generation-v1.md` | 当前有效;后端 CP1 已支持前端上传来源名单并填写目标字段,同步生成 `.xlsx` 直接下载;前端 V1 已新增 `/reservation/rooming-lists/new`,按 Blob 下载处理,不落库、不上传 OSS。 |
| Rooming List Excel 生成 | `docs/project/requirements/M010-rooming-list-excel-generation-v1.md` | 当前有效;后端 CP1 已支持前端上传来源名单并填写目标字段,同步生成 `.xlsx` 直接下载;CP2 已实现:来源 Excel `旅游日期` 派生 Arrival / DepartureAdults 由系统按分房结果计算,目标默认值区域只保留 Payment Type / Nationality前端 V1 已新增 `/reservation/rooming-lists/new`,按 Blob 下载处理,不落库、不上传 OSS。 |
| Booking Excel 附件预处理 | `docs/project/requirements/M011-booking-excel-pre-superagent-enrichment-v1.md` | 当前有效Debug EML 和 AgentBus dispatch 已支持调 SuperAgent 前排除人员名单类 Excel、抽取 Booking / 附加费类 Excel 高亮行并生成 `attachment_extractions[]`;测试机 AgentBus 增强已开启生产默认关闭CP4 暂不推进。 |
| 订单任务主流程 V2 | `docs/project/requirements/M002-order-task-workflow-v2.md` | 已实现阶段记录,保留用于理解当前代码中的 S000/S999、订单任务流转和 OPERA 模拟骨架。 |
| 后端 checkpoint | `docs/project/requirements/M002-backend-checkpoint-plan.md` | 阶段记录,用于理解后端拆分和验收。 |
@@ -64,7 +64,7 @@
- 真实 OPERA / OHIP 接入后置;当前仅有 OPERA 模拟骨架。
- 任务卡字段控件契约 V1 后端第一版已完成,任务详情 `fields[]` 已返回 `control_type/edit_scope/write_target/options_source/raw_readonly/control_hint`;前端后续按契约接入,不要硬编码 PMS 房型、Rate Code 或未冻结枚举。
- Manual Invoice 第一阶段按 M009 推进:后端已提供 `POST /api/reservation/invoices/manual-generations`,前端已新增 `/reservation/invoices/new` 手工开票页面,并已按 `invoice.html` 原型的三段式业务结构对齐;页面可以不依赖订单或任务,用户手工填写 / 选择字段后由后端业务接口填充 Excel 模板并生成 PDF前端不得直接调用 M008 的调试上传转换接口来完成业务开票。侧边栏入口仍以登录后端返回的 menus 为准,建议后续在菜单管理中配置 `RESERVATION_MANUAL_INVOICE` / `/reservation/invoices/new` / `RESERVATION_INVOICE_GENERATE`
- Rooming List Excel 后端 CP1 和前端 V1 已按 M010 落地:接口为 `POST /api/reservation/rooming-lists/generations`,前端页面为 `/reservation/rooming-lists/new`,上传来源名单、填写每房人数和目标列字段,后端同步返回 `.xlsx` 下载;该能力不依赖订单或任务,第一版不落库、不上传 OSS权限码为 `RESERVATION_ROOMING_LIST_GENERATE`
- Rooming List Excel 后端 CP1 和前端 V1 已按 M010 落地:接口为 `POST /api/reservation/rooming-lists/generations`,前端页面为 `/reservation/rooming-lists/new`,上传来源名单、填写每房人数和目标列字段,后端同步返回 `.xlsx` 下载;该能力不依赖订单或任务,第一版不落库、不上传 OSS权限码为 `RESERVATION_ROOMING_LIST_GENERATE`M010 CP2 已实现前端保留上传文件、每房人数、Room Type目标默认值区域只保留 Payment Type 和 Nationality后端从来源 Excel `旅游日期` 派生 Arrival / Departure并按分房结果派生 Adults。
- Booking Excel 附件预处理已按 M011 落地 CP1/CP2/CP3Debug EML 和 AgentBus dispatch 调用 SuperAgent 前由后端解析 Excel 附件,排除人员名单类文件,只把 Booking Update / 附加费表的高亮行业务摘要追加为 `attachment_extractions[]`;第一版不新增前端普通业务入口,测试机 AgentBus 增强已开启生产默认关闭CP4 暂不推进。
- Reservation V4 目录管理后台 CP1 已前后端接入:系统设置下新增 `/system/reservation-catalogs`,需要登录用户具备 `RESERVATION_CATALOG_MANAGE`;前端可维护 Account、Room Type、Rate Code 的列表、新增、启用 / 停用,并明确提示停用目录不再进入普通 V4 任务卡 lookup。
- V4 任务卡复核态已确认:`REVIEW_REQUIRED` 仍在原业务卡内编辑和确认,页面主按钮文案统一为“确认卡片”;前端必须按 `card_status` 调用普通确认或复核解阻接口,且只提交后端 `fields[]` 白名单内业务字段。

View File

@@ -96,7 +96,7 @@
| `GET/POST/PUT /api/admin/menus...` | 系统管理菜单维护 | 需要 `SYSTEM_MENU_MANAGE`;允许保存未知路由,前端必须有未知路由兜底页;已提供完整菜单树查询和批量树排序保存。 |
| `GET/POST/PUT /api/admin/hotels...` | 系统管理酒店维护 | 需要 `HOTEL_MANAGE`;新增酒店默认 `DISABLED`,单酒店阶段不能启用第二家 `ACTIVE`。 |
| `GET /api/admin/audits` | 系统管理操作审计 | 需要 `SYSTEM_ADMIN_CONSOLE_ACCESS`用于查看管理后台写操作审计不包含密码、token、secret。 |
| `POST /api/reservation/rooming-lists/generations` | 生成 Rooming List Excel | 必须带 Bearer token需要 `RESERVATION_ROOMING_LIST_GENERATE`;请求为 multipart/form-data成功后直接返回 `.xlsx` 文件流,前端按 Blob 下载处理。 |
| `POST /api/reservation/rooming-lists/generations` | 生成 Rooming List Excel | 必须带 Bearer token需要 `RESERVATION_ROOMING_LIST_GENERATE`;请求为 multipart/form-data成功后直接返回 `.xlsx` 文件流,前端按 Blob 下载处理。CP2 已实现:后端从来源 Excel `旅游日期` 派生 Arrival / DepartureAdults 按分房结果计算,目标默认值区域只保留 Payment Type / Nationality。 |
### 5.1 本轮新增 / 修改接口说明
@@ -461,7 +461,7 @@ M009 后端 CP2 已实现:页面可不依赖订单或任务,用户手工填
### 5.12 Rooming List Excel 生成页面接入方向
M010 后端 CP1 已实现。第一版生成结果直接下载 `.xlsx`,不落库、不上传 OSS不依赖订单或任务。
M010 后端 CP1 已实现。第一版生成结果直接下载 `.xlsx`,不落库、不上传 OSS不依赖订单或任务。CP2 已实现,前后端按本节新口径接入。
接口:
@@ -481,15 +481,19 @@ RESERVATION_ROOMING_LIST_GENERATE
- 前端 V1 已新增 `/reservation/rooming-lists/new` 页面,按 `RESERVATION_ROOMING_LIST_GENERATE` 路由权限保护,并使用登录态 Bearer token 调用正式业务接口。
- 侧边栏入口不由前端硬编码公开,仍依赖后端登录态 `menus[]`。如需菜单中展示,建议菜单管理配置 `menu_code=RESERVATION_ROOMING_LIST``route_path=/reservation/rooming-lists/new``permission_code=RESERVATION_ROOMING_LIST_GENERATE`
- 该页面上传来源名单 Excel后端默认识别 `护照全名` 列。
- 该页面上传来源名单 ExcelCP1 后端默认识别 `护照全名`CP2 还需要识别 `旅游日期` 列。
- 姓名支持 `LI/CHUNHONG``LI CHUNHONG` 两类格式;后端会把第一段写入目标 `Name`,剩余部分写入目标 `First Name`
- 前端必须让用户输入 `people_per_room`,后端按名单顺序分组,并用 `ceil(total_people / people_per_room)` 生成房间行。
- 前端必须让用户输入 `people_per_room` 和目标 `Room Type`,后端按名单顺序分组,并用 `ceil(total_people / people_per_room)` 生成房间行。
- 每组第一位旅客写入 `Name` / `First Name`,同组剩余旅客写入 `Accompanying Guests`,多人用英文逗号分隔。
- `Line``Name``First Name``Number of Rooms``Accompanying Guests` 外,目标 Excel 其他字段第一版都由前端输入或选择,例如 `Title``Arrival``Departure``Room Type``Rate Code``Payment Type``Nationality`
- CP2 起前端不再展示或提交 `Arrival` / `Departure`,后端从来源 Excel 的 `旅游日期` 派生。样例 `2026年5月9日5月14日` 应生成 `Arrival=2026-05-09``Departure=2026-05-14`
- CP2 起前端不再展示或提交 `Adults`,后端按每个分房行的实际人数派生;尾房不足满房人数时按尾房实际人数写入。`Children` 第一版固定为 `0`
- CP2 起目标默认值区域只保留 `Payment Type``Nationality``Payment Type` 默认且当前唯一允许值为 `CA``Nationality` 只允许 `KR``CHN`
- CP2 页面不再展示或提交 `Title``Rate Code``VIP``Email``ID Type``ID Number`,这些目标列第一版固定为空。
- 第一版接口成功后直接返回 Excel 文件流,前端应按 Blob 下载处理,不要期待 JSON 里的 URL。
- 失败时返回统一 JSON 错误,例如 `ROOMING_LIST_VALIDATION_FAILED``ROOMING_LIST_SOURCE_FILE_INVALID``HOTEL_ACCESS_DENIED``FRONTEND_PERMISSION_DENIED`
- 该上传接口会在 multipart 参数绑定前先校验 Bearer token 和 `RESERVATION_ROOMING_LIST_GENERATE` 权限;未登录时优先返回 401不会因为缺少业务字段先返回 400。
- `ROOMING_LIST_VALIDATION_FAILED` 覆盖 multipart 必填字段缺失、日期格式错误和数字格式错误,`details[]` 返回字段级提示。
- `ROOMING_LIST_VALIDATION_FAILED` 覆盖 multipart 必填字段缺失、`people_per_room` 数字格式错误、`payment_type` / `nationality` 枚举错误,`details[]` 返回字段级提示。
- `ROOMING_LIST_SOURCE_FILE_INVALID` 应覆盖来源文件缺失、非 Excel、无法读取、缺少 `护照全名`、缺少 `旅游日期`、旅游日期格式无法解析或同一文件出现多个不同旅游日期区间。
- 页面不要把上传文件内容、客人名单、生成文件内容写入浏览器日志、埋点、错误上报、URL 或 localStorage。
- 第一版没有 preview 接口、生成记录接口、OSS URL、历史下载和订单 / 任务预填;前端不要在页面上承诺这些能力。

View File

@@ -17,6 +17,7 @@
| P0 | 邮件会话详情接口 `GET /api/source-messages/{sourceMessageId}/conversation` | 邮件会话详情页 | 已完成第一版 |
| 联调 | 演示数据 seed 接口 `POST /api/system/reservation/demo-data` | 本地 / test 前端页面看效果 | 已完成;仅 dev/test 受控使用 |
| 联调 | Debug EML 上传接口 `POST /api/system/debug/eml-superagent-runs` | Debug 页面上传 `.eml` 看 SuperAgent 结果 | 已完成第一版;仅 dev/test 受控使用 |
| Done | Rooming List Excel 生成接口 `POST /api/reservation/rooming-lists/generations` | 房表生成页面 | CP1 已完成CP2 已实现旅游日期派生、Adults 自动计算和目标默认值字段收口 |
| P1 | S10/S99 源邮件只读通知卡与旧 S000/S999 兼容 | 任务列表、任务详情来源邮件查看 | 已完成第一版:旧 S000/S999 兼容,新结构化 S10/S99 可入站并在任务列表 / 详情只读展示 |
| P1 | type-known manual review 同卡复核解阻 | 任务详情复核 | 已完成第一版原业务任务卡复核、字段修正、订单归属确认、READY 流转 |
| P1 | 任务卡前端字段白名单元数据接口 | 字段白名单调试、版本对齐 | 未完成;若任务详情已透出完整元数据,可后置 |
@@ -1182,7 +1183,60 @@ POST /api/reservation/invoices/manual-generations
- 第一版已写入 `workflow_reservation_invoice_generation` 生成记录和业务审计,但暂不提供前端查询历史列表 / 详情接口。
- 错误响应中的 `error_code` 用于前端主错误文案映射;`message` / `details[]` 只作为折叠技术详情展示,不直接铺给普通用户。
## 13. 已确认后置接口
## 13. Rooming List Excel 生成接口 CP2 契约
M010 Rooming List Excel 生成接口 CP1 已实现,前端 V1 已接入 `/reservation/rooming-lists/new`。CP2 不新增路径,继续收口同一个正式业务接口。
路径:
```text
POST /api/reservation/rooming-lists/generations
```
CP2 前端提交字段:
| 字段 | 必填 | 说明 |
| --- | --- | --- |
| `file` | 是 | 来源 Excel 文件,仅支持 `.xls` / `.xlsx`。 |
| `hotel_id` | 否 | 当前选择酒店;不传时由后端按登录用户酒店上下文解析。 |
| `people_per_room` | 是 | 每间房人数,正整数。 |
| `room_type` | 是 | 目标 Excel 的 Room Type。 |
| `payment_type` | 否 | 目标 Excel 的 Payment Type默认和当前唯一允许值为 `CA`。 |
| `nationality` | 是 | 目标 Excel 的 Nationality只允许 `KR``CHN`。 |
CP2 前端不再提交:
```text
arrival
departure
title
rate_code
adults
children
vip
email
id_type
id_number
```
后端派生规则:
- 从来源 Excel `旅游日期` 列解析入住和离店日期;样例 `2026年5月9日5月14日` 派生 `Arrival=2026-05-09``Departure=2026-05-14`
- `Adults` 按当前分房行实际人数计算;尾房人数不足时按实际人数写入。
- `Children` 固定为 `0`
- `Title``Rate Code``VIP``Email``ID Type``ID Number` 第一版固定为空。
- 如果来源 Excel 缺少 `旅游日期`、日期格式无法解析、结束日期不晚于起始日期,或同一文件出现多个不同旅游日期区间,后端返回受控错误,不生成 Excel。
前端诉求:
- 页面第一部分保留上传来源 Excel、每房人数、Room Type。
- 目标默认值区域只保留 Payment Type 和 Nationality 两个下拉。
- Payment Type 默认选中 `CA`,当前不开放其他选项。
- Nationality 只提供 `KR``CHN`
- 前端不读取完整 Excel 作为权威解析结果;旅游日期和成人数以后端生成结果为准。
- 页面不要把上传文件内容、客人名单、生成文件内容写入浏览器日志、埋点、错误上报、URL 或 localStorage。
## 14. 已确认后置接口
普通任务切换订单接口继续后置,前端暂不开发提交能力。后续如果恢复开发,建议另行确认:
@@ -1211,7 +1265,7 @@ POST /api/reservation/tasks/{taskId}/order-binding
}
```
## 14. 待确认问题
## 15. 待确认问题
- 订单列表、任务列表当前统一使用 `items + page` 分页结构;邮件会话详情不分页,返回同一会话全部邮件。
- 邮件会话详情接口已优先使用 `GET /api/source-messages/{sourceMessageId}/conversation`