实现房表生成第二种名单样式
This commit is contained in:
@@ -62,7 +62,7 @@
|
||||
| `requirements/M007-agentbus-superagent-auto-dispatch-v1.md` | 当前有效 | M007 AgentBus 新邮件入库后异步分发 SuperAgent 的后端 V1 方案,当前默认关闭,等待测试机联调。 |
|
||||
| `requirements/M008-excel-to-pdf-conversion-v1.md` | 当前有效 | M008 Excel 转 PDF 文件转换能力方案,记录 LibreOffice headless、手动上传转换、邮件附件自动派生 PDF 和部署要求;CP2 已实现手动上传后端接口。 |
|
||||
| `requirements/M009-manual-invoice-generation-v1.md` | 当前有效 | M009 Manual Invoice 手工开票生成方案;后端 CP2 已支持无订单 / 无任务手工填写、填充 Excel 模板、转 PDF、OSS 输出和生成记录。 |
|
||||
| `requirements/M010-rooming-list-excel-generation-v1.md` | 当前有效 | M010 Rooming List Excel 生成方案;后端 CP1 已支持前端上传来源名单和手工字段,同步生成 `.xlsx` 直接下载,不落库、不上传 OSS;CP2 已实现来源 `旅游日期` 派生 Arrival / Departure、Adults 系统计算,以及目标默认值区域只保留 Payment Type / Nationality。 |
|
||||
| `requirements/M010-rooming-list-excel-generation-v1.md` | 当前有效 | M010 Rooming List Excel 生成方案;后端 CP1 已支持前端上传来源名单和手工字段,同步生成 `.xlsx` 直接下载,不落库、不上传 OSS;CP2 已实现来源 `旅游日期` 派生 Arrival / Departure、Adults 系统计算,以及目标默认值区域只保留 Payment Type / Nationality;CP3 已实现第二种 `英文姓` + `英文名` 名单样式,并由用户补充 Arrival / Departure。 |
|
||||
| `requirements/M011-booking-excel-pre-superagent-enrichment-v1.md` | 当前有效 | M011 Booking Excel 附件预处理方案;CP1/CP2/CP3 已支持 Debug EML 和 AgentBus dispatch 调 SuperAgent 前排除人员名单类 Excel、抽取 Booking / 附加费类 Excel 高亮行并追加 `attachment_extractions[]`;测试机 AgentBus 增强已开启,生产默认关闭;CP4 暂不推进。 |
|
||||
|
||||
## 集成契约
|
||||
|
||||
@@ -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` 直接下载;CP2 已实现:来源 Excel `旅游日期` 派生 Arrival / Departure,Adults 由系统按分房结果计算,目标默认值区域只保留 Payment Type / Nationality;前端 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 / Departure,Adults 由系统按分房结果计算,目标默认值区域只保留 Payment Type / Nationality;CP3 已实现:兼容 `英文姓` + `英文名` 第二种名单样式,并由用户补充 Arrival / Departure;前端 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`。M010 CP2 已实现:前端保留上传文件、每房人数、Room Type,目标默认值区域只保留 Payment Type 和 Nationality;后端从来源 Excel `旅游日期` 派生 Arrival / Departure,并按分房结果派生 Adults。
|
||||
- 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。M010 CP3 已实现:兼容 `英文姓` + `英文名` 第二种名单样式,页面恢复 Arrival / Departure 两个日期输入;第一种 `旅游日期` 样式可不填,第二种样式必须由用户填写。
|
||||
- Booking Excel 附件预处理已按 M011 落地 CP1/CP2/CP3:Debug 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[]` 白名单内业务字段。
|
||||
|
||||
@@ -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 下载处理。CP2 已实现:后端从来源 Excel `旅游日期` 派生 Arrival / Departure,Adults 按分房结果计算,目标默认值区域只保留 Payment Type / Nationality。 |
|
||||
| `POST /api/reservation/rooming-lists/generations` | 生成 Rooming List Excel | 必须带 Bearer token,需要 `RESERVATION_ROOMING_LIST_GENERATE`;请求为 multipart/form-data,成功后直接返回 `.xlsx` 文件流,前端按 Blob 下载处理。CP2 已实现:后端从来源 Excel `旅游日期` 派生 Arrival / Departure,Adults 按分房结果计算,目标默认值区域只保留 Payment Type / Nationality。CP3 已实现:兼容 `英文姓` + `英文名` 第二种来源样式,并在该样式下使用前端提交的 `arrival` / `departure`。 |
|
||||
|
||||
### 5.1 本轮新增 / 修改接口说明
|
||||
|
||||
@@ -463,7 +463,7 @@ M009 后端 CP2 已实现:页面可不依赖订单或任务,用户手工填
|
||||
|
||||
### 5.12 Rooming List Excel 生成页面接入方向
|
||||
|
||||
M010 后端 CP1 已实现。第一版生成结果直接下载 `.xlsx`,不落库、不上传 OSS,不依赖订单或任务。CP2 已实现,前后端按本节新口径接入。
|
||||
M010 后端 CP1 已实现。第一版生成结果直接下载 `.xlsx`,不落库、不上传 OSS,不依赖订单或任务。CP2 已实现,前后端按本节新口径接入。CP3 已实现:兼容 `英文姓` + `英文名` 第二种来源名单样式,并由用户补充入住 / 离店日期。
|
||||
|
||||
接口:
|
||||
|
||||
@@ -483,19 +483,20 @@ 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;CP1 后端默认识别 `护照全名` 列,CP2 还需要识别 `旅游日期` 列。
|
||||
- 姓名支持 `LI/CHUNHONG` 和 `LI CHUNHONG` 两类格式;后端会把第一段写入目标 `Name`,剩余部分写入目标 `First Name`。
|
||||
- 该页面上传来源名单 Excel;第一种来源样式后端识别 `护照全名` 和 `旅游日期`,第二种来源样式后端识别 `英文姓` 和 `英文名`。
|
||||
- 第一种来源样式姓名支持 `LI/CHUNHONG` 和 `LI CHUNHONG` 两类格式;后端会把第一段写入目标 `Name`,剩余部分写入目标 `First Name`。第二种来源样式直接使用 `英文姓` 写入 `Name`,使用 `英文名` 写入 `First Name`。
|
||||
- 前端必须让用户输入 `people_per_room` 和目标 `Room Type`,后端按名单顺序分组,并用 `ceil(total_people / people_per_room)` 生成房间行。
|
||||
- 每组第一位旅客写入 `Name` / `First Name`,同组剩余旅客写入 `Accompanying Guests`,多人用英文逗号分隔。
|
||||
- CP2 起前端不再展示或提交 `Arrival` / `Departure`,后端从来源 Excel 的 `旅游日期` 派生。样例 `2026年5月9日-5月14日` 应生成 `Arrival=2026/05/09`、`Departure=2026/05/14`。
|
||||
- CP3 起前端恢复 `Arrival` / `Departure` 日期输入:第一种来源样式可不填,后端优先从来源 Excel 的 `旅游日期` 派生;第二种来源样式必须填写,后端使用用户提交日期写入目标 Excel。样例 `2026年5月9日-5月14日` 仍应生成 `Arrival=2026/05/09`、`Departure=2026/05/14`。
|
||||
- 第二种来源样式中领队也进入房表;例如 `23+1` 表示 23 位客人 + 1 位领队全部参与分房,实际人数以后端读取到的有效名单行数为准。
|
||||
- CP2 起前端不再展示或提交 `Adults`,后端按每个分房行的实际人数派生;尾房不足满房人数时按尾房实际人数写入。`Children` 第一版固定为 `0`。
|
||||
- CP2 起目标默认值区域只保留 `Payment Type` 和 `Nationality`:`Payment Type` 默认 `BTQR`,当前允许 `BTQR`、`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 必填字段缺失、`people_per_room` 数字格式错误、`payment_type` / `nationality` 枚举错误,`details[]` 返回字段级提示。
|
||||
- `ROOMING_LIST_SOURCE_FILE_INVALID` 应覆盖来源文件缺失、非 Excel、无法读取、缺少 `护照全名`、缺少 `旅游日期`、旅游日期格式无法解析或同一文件出现多个不同旅游日期区间。
|
||||
- `ROOMING_LIST_VALIDATION_FAILED` 应覆盖 multipart 必填字段缺失、`people_per_room` 数字格式错误、第二种来源样式下缺少或错误的 `arrival` / `departure`、`payment_type` / `nationality` 枚举错误,`details[]` 返回字段级提示。
|
||||
- `ROOMING_LIST_SOURCE_FILE_INVALID` 应覆盖来源文件缺失、非 Excel、无法读取、既不能识别第一种 `护照全名` + `旅游日期`、也不能识别第二种 `英文姓` + `英文名`、第一种来源样式旅游日期格式无法解析或同一文件出现多个不同旅游日期区间。
|
||||
- 页面不要把上传文件内容、客人名单、生成文件内容写入浏览器日志、埋点、错误上报、URL 或 localStorage。
|
||||
- 第一版没有 preview 接口、生成记录接口、OSS URL、历史下载和订单 / 任务预填;前端不要在页面上承诺这些能力。
|
||||
|
||||
|
||||
@@ -17,7 +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 自动计算和目标默认值字段收口 |
|
||||
| Done | Rooming List Excel 生成接口 `POST /api/reservation/rooming-lists/generations` | 房表生成页面 | CP1 已完成;CP2 已实现旅游日期派生、Adults 自动计算和目标默认值字段收口;CP3 已实现第二种 `英文姓` + `英文名` 名单样式和用户补 Arrival / Departure |
|
||||
| P1 | S10/S99 源邮件只读通知卡与旧 S000/S999 兼容 | 任务列表、任务详情来源邮件查看 | 已完成第一版:旧 S000/S999 兼容,新结构化 S10/S99 可入站并在任务列表 / 详情只读展示 |
|
||||
| P1 | type-known manual review 同卡复核解阻 | 任务详情复核 | 已完成第一版:原业务任务卡复核、字段修正、订单归属确认、READY 流转 |
|
||||
| P1 | 任务卡前端字段白名单元数据接口 | 字段白名单调试、版本对齐 | 未完成;若任务详情已透出完整元数据,可后置 |
|
||||
@@ -1184,9 +1184,9 @@ POST /api/reservation/invoices/manual-generations
|
||||
- 第一版已写入 `workflow_reservation_invoice_generation` 生成记录和业务审计,但暂不提供前端查询历史列表 / 详情接口。
|
||||
- 错误响应中的 `error_code` 用于前端主错误文案映射;`message` / `details[]` 只作为折叠技术详情展示,不直接铺给普通用户。
|
||||
|
||||
## 13. Rooming List Excel 生成接口 CP2 契约
|
||||
## 13. Rooming List Excel 生成接口 CP2 / CP3 契约
|
||||
|
||||
M010 Rooming List Excel 生成接口 CP1 已实现,前端 V1 已接入 `/reservation/rooming-lists/new`。CP2 不新增路径,继续收口同一个正式业务接口。
|
||||
M010 Rooming List Excel 生成接口 CP1 已实现,前端 V1 已接入 `/reservation/rooming-lists/new`。CP2 不新增路径,继续收口同一个正式业务接口。CP3 已实现兼容第二种来源名单样式,仍复用本接口。
|
||||
|
||||
路径:
|
||||
|
||||
@@ -1202,14 +1202,14 @@ CP2 前端提交字段:
|
||||
| `hotel_id` | 否 | 当前选择酒店;不传时由后端按登录用户酒店上下文解析。 |
|
||||
| `people_per_room` | 是 | 每间房人数,正整数。 |
|
||||
| `room_type` | 是 | 目标 Excel 的 Room Type。 |
|
||||
| `arrival` | 条件必填 | CP3 第二种来源名单样式必填,格式 `yyyy-MM-dd`;第一种 `旅游日期` 样式可不填。 |
|
||||
| `departure` | 条件必填 | CP3 第二种来源名单样式必填,格式 `yyyy-MM-dd`;必须晚于 `arrival`。 |
|
||||
| `payment_type` | 否 | 目标 Excel 的 Payment Type;默认 `BTQR`,当前允许 `BTQR`、`CA`。 |
|
||||
| `nationality` | 是 | 目标 Excel 的 Nationality;只允许 `KR`、`CHN`。 |
|
||||
|
||||
CP2 前端不再提交:
|
||||
CP3 前端仍不提交:
|
||||
|
||||
```text
|
||||
arrival
|
||||
departure
|
||||
title
|
||||
rate_code
|
||||
adults
|
||||
@@ -1222,19 +1222,25 @@ id_number
|
||||
|
||||
后端派生规则:
|
||||
|
||||
- 从来源 Excel `旅游日期` 列解析入住和离店日期;样例 `2026年5月9日-5月14日` 派生 `Arrival=2026/05/09`、`Departure=2026/05/14`。
|
||||
- 第一种来源样式:从来源 Excel `旅游日期` 列解析入住和离店日期;样例 `2026年5月9日-5月14日` 派生 `Arrival=2026/05/09`、`Departure=2026/05/14`。
|
||||
- 第二种来源样式:来源 Excel 表头包含 `英文姓`、`英文名`,没有可靠入住 / 离店日期;后端使用前端提交的 `arrival` / `departure` 写入目标 Excel。
|
||||
- 第二种来源样式姓名生成规则:`Name=英文姓`,`First Name=英文名`,不再拆分字符串。
|
||||
- 第二种来源样式中领队也进入房表;例如 `23+1` 表示 23 位客人 + 1 位领队全部参与分房,实际人数以后端读取到的有效名单行数为准。
|
||||
- `Adults` 按当前分房行实际人数计算;尾房人数不足时按实际人数写入。
|
||||
- `Children` 固定为 `0`。
|
||||
- `Title`、`Rate Code`、`VIP`、`Email`、`ID Type`、`ID Number` 第一版固定为空。
|
||||
- 如果来源 Excel 缺少 `旅游日期`、日期格式无法解析、结束日期不晚于起始日期,或同一文件出现多个不同旅游日期区间,后端返回受控错误,不生成 Excel。
|
||||
- 如果来源 Excel 既不能识别第一种 `护照全名` + `旅游日期`,也不能识别第二种 `英文姓` + `英文名`,后端返回受控错误,不生成 Excel。
|
||||
- 第一种来源样式缺少 `旅游日期`、日期格式无法解析、结束日期不晚于起始日期,或同一文件出现多个不同旅游日期区间,后端返回受控错误,不生成 Excel。
|
||||
- 第二种来源样式缺少 `arrival` / `departure`、日期格式无法解析,或 `departure` 不晚于 `arrival`,后端返回受控错误,不生成 Excel。
|
||||
|
||||
前端诉求:
|
||||
|
||||
- 页面第一部分保留上传来源 Excel、每房人数、Room Type。
|
||||
- 页面第一部分保留上传来源 Excel、每房人数、Room Type,并恢复 `Arrival` / `Departure` 日期输入。
|
||||
- `Arrival` / `Departure` 在第一种来源样式下可不填;当用户上传第二种没有 `旅游日期` 的名单时必须填写。页面文案建议说明“来源名单没有旅游日期时请填写入住 / 离店日期”。
|
||||
- 目标默认值区域只保留 Payment Type 和 Nationality 两个下拉。
|
||||
- Payment Type 默认选中 `BTQR`,当前提供 `BTQR`、`CA` 两个选项。
|
||||
- Nationality 只提供 `KR` 和 `CHN`。
|
||||
- 前端不读取完整 Excel 作为权威解析结果;旅游日期和成人数以后端生成结果为准。
|
||||
- 前端不读取完整 Excel 作为权威解析结果;来源样式识别、旅客名单和成人数以后端生成结果为准。
|
||||
- 页面不要把上传文件内容、客人名单、生成文件内容写入浏览器日志、埋点、错误上报、URL 或 localStorage。
|
||||
|
||||
## 14. 已确认后置接口
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 文档状态 | 后端 CP1 已实现;CP2 已实现旅游日期派生、Adults 系统计算和目标默认值字段收口 |
|
||||
| 文档状态 | 后端 CP1 已实现;CP2 已实现旅游日期派生、Adults 系统计算和目标默认值字段收口;CP3 第二种来源名单样式已实现 |
|
||||
| 适用范围 | 从旅行团名单 Excel 解析护照姓名,并生成酒店 / PMS 可导入的 Rooming List Excel |
|
||||
| 当前目标 | CP1 已支持前端上传来源 Excel、填写分房和目标列默认值,后端同步生成目标格式 `.xlsx`;CP2 收口为后端从来源 `旅游日期` 派生入住 / 离店日期,成人数由系统按分房结果计算,目标默认值区域只保留付款方式和国籍 |
|
||||
| 当前目标 | CP1 已支持前端上传来源 Excel、填写分房和目标列默认值,后端同步生成目标格式 `.xlsx`;CP2 收口为后端从来源 `旅游日期` 派生入住 / 离店日期,成人数由系统按分房结果计算,目标默认值区域只保留付款方式和国籍;CP3 兼容 `英文姓` + `英文名` 第二种名单样式,并由用户补充入住 / 离店日期 |
|
||||
| 依赖能力 | 登录权限、酒店上下文、Apache POI 或等价 Excel 读写能力 |
|
||||
|
||||
## 1. 背景
|
||||
@@ -36,6 +36,15 @@ CP2 目标调整:
|
||||
- `Payment Type` 前端默认为 `BTQR`,当前可选择 `BTQR` 或 `CA`,后端按同一枚举校验。
|
||||
- `Nationality` 前端只允许选择 `KR` 或 `CHN`,后端按同一枚举校验。
|
||||
|
||||
CP3 目标调整:
|
||||
|
||||
- 继续复用同一个生成接口和同一个前端页面,不新增上传入口。
|
||||
- 兼容第二种来源名单样式:表头包含 `英文姓`、`英文名`,没有 `护照全名` 和 `旅游日期`。
|
||||
- 第二种样式的姓名不再拆分字符串,直接使用 `英文姓` 写入目标 `Name`,使用 `英文名` 写入目标 `First Name`。
|
||||
- 第二种样式没有可靠入住 / 离店日期来源,前端需要恢复并提交 `arrival`、`departure` 两个日期字段;第一种样式仍可不填,由后端从来源 `旅游日期` 派生。
|
||||
- 第二种样式中的领队也进入房表。例如标题行 `23+1` 应理解为 23 位客人 + 1 位领队,合计 24 位入住人全部参与分房。
|
||||
- 来源表中的中文名、性别、出生日期、护照号码、出生地、签发地、签发日期、有效期等字段第一版仍不写入目标 Excel,也不在错误响应或日志中回显。
|
||||
|
||||
第一阶段不做:
|
||||
|
||||
- 不落业务订单。
|
||||
@@ -61,7 +70,11 @@ CP2 目标调整:
|
||||
|
||||
## 4. 来源 Excel 解析规则
|
||||
|
||||
基于当前样例来源文件,第一版默认识别以下表头:
|
||||
基于当前样例来源文件,当前支持两类来源名单格式。后端应先在来源 Excel 中识别表头组合,再选择对应解析器。
|
||||
|
||||
### 4.1 第一种来源样式:护照全名 + 旅游日期
|
||||
|
||||
第一种样式识别以下表头:
|
||||
|
||||
| 来源字段 | 中文说明 | 第一版用途 |
|
||||
| --- | --- | --- |
|
||||
@@ -70,7 +83,7 @@ CP2 目标调整:
|
||||
|
||||
CP1 只使用 `护照全名` 生成目标姓名字段。CP2 额外使用 `旅游日期` 派生目标 `Arrival` / `Departure`。来源文件中的证件号、生日、性别、年龄等字段暂不自动写入目标 Excel,除非后续单独确认。
|
||||
|
||||
### 4.1 姓名拆分
|
||||
#### 4.1.1 姓名拆分
|
||||
|
||||
支持的输入格式:
|
||||
|
||||
@@ -94,7 +107,7 @@ LIU/JIAYI
|
||||
- 当前目标模板中 `Name` 更接近姓氏字段,`First Name` 更接近名字段。
|
||||
- 第一版不尝试判断中文、韩文、英文姓名顺序,也不做大小写改写。
|
||||
|
||||
### 4.2 旅游日期解析
|
||||
#### 4.1.2 旅游日期解析
|
||||
|
||||
CP2 起后端应识别来源 Excel 的 `旅游日期` 表头,并从有名单数据的行中读取日期区间。
|
||||
|
||||
@@ -121,6 +134,36 @@ CP2 起后端应识别来源 Excel 的 `旅游日期` 表头,并从有名单
|
||||
- 当前样表第 2 行表头中包含 `旅游日期`,第 3 行起数据为 `2026年5月9日-5月14日`,可派生 `Arrival=2026/05/09`、`Departure=2026/05/14`。
|
||||
- CP2 暂不支持同一个文件中多批次、多旅游日期混合分房;如后续出现该真实场景,需要先设计按批次拆文件或按旅游日期分组生成多个 Sheet / 多个文件。
|
||||
|
||||
### 4.2 第二种来源样式:英文姓 + 英文名
|
||||
|
||||
第二种样式识别以下表头:
|
||||
|
||||
| 来源字段 | 中文说明 | 第一版用途 |
|
||||
| --- | --- | --- |
|
||||
| `英文姓` | 护照英文姓氏 | 直接写入目标 Excel 的 `Name` |
|
||||
| `英文名` | 护照英文名字 | 直接写入目标 Excel 的 `First Name` |
|
||||
|
||||
已确认样例:
|
||||
|
||||
```text
|
||||
Sheet1 第 1 行:SYNTHETIC-GROUP-001 23+1 12XX 领队...
|
||||
Sheet1 第 2 行:序号 / 中文名 / 英文姓 / 英文名 / 性别 / 出生日期 / 护照号码 / ...
|
||||
Sheet1 第 3 行起:名单数据
|
||||
```
|
||||
|
||||
解析规则:
|
||||
|
||||
- 在前若干行内查找同一行同时包含 `英文姓` 和 `英文名` 的表头。
|
||||
- 从表头下一行开始读取名单行。
|
||||
- `英文姓` 或 `英文名` 为空的行跳过;如后续需要强校验可单独确认。
|
||||
- 底部航班说明、空白行、合计说明等不进入名单。
|
||||
- 不读取也不返回中文名、性别、出生日期、护照号码、出生地、签发地、签发日期、有效期。
|
||||
- 标题行中的 `23+1` 只作为人工可读说明,不作为系统人数校验;实际入住人数以后端读取到的有效 `英文姓` + `英文名` 行数为准。
|
||||
- `23+1` 业务含义已确认:23 位客人 + 1 位领队,领队也要进入目标 Rooming List。
|
||||
- 第二种样式没有 `旅游日期`,后端不得从航班行猜测入住 / 离店日期;必须使用前端提交的 `arrival` / `departure`。
|
||||
|
||||
如果来源文件同时满足第一种和第二种表头组合,后端应优先使用第一种 `护照全名` + `旅游日期`,保持现有已上线行为稳定。
|
||||
|
||||
## 5. 分房生成规则
|
||||
|
||||
前端需要传入 `people_per_room`,表示每间房人数。
|
||||
@@ -162,8 +205,8 @@ people_per_room = 3
|
||||
| `Name` | 每间房第一位旅客的姓氏 / 第一段姓名 |
|
||||
| `First Name` | 每间房第一位旅客的名字 / 剩余姓名 |
|
||||
| `Title` | CP2 固定为空,后续如有稳定默认值再单独确认 |
|
||||
| `Arrival` | CP2 从来源 Excel `旅游日期` 起始日派生 |
|
||||
| `Departure` | CP2 从来源 Excel `旅游日期` 结束日派生 |
|
||||
| `Arrival` | 第一种样式从来源 Excel `旅游日期` 起始日派生;第二种样式使用前端提交的 `arrival` |
|
||||
| `Departure` | 第一种样式从来源 Excel `旅游日期` 结束日派生;第二种样式使用前端提交的 `departure` |
|
||||
| `Room Type` | 前端传入 |
|
||||
| `Rate Code` | CP2 固定为空,后续如需 Rate Code 选择再单独确认 |
|
||||
| `Number of Rooms` | 第一版每行固定为 `1`,后续如目标模板变化再调整 |
|
||||
@@ -180,7 +223,7 @@ people_per_room = 3
|
||||
中文说明:
|
||||
|
||||
- CP2 目标默认值区域只保留 `Payment Type` 和 `Nationality`,不再展示 `Title`、`Rate Code`、`Adults`、`Children`、`VIP`、`Email`、`ID Type`、`ID Number`。
|
||||
- `Arrival` / `Departure` 的业务来源是来源名单 Excel 的 `旅游日期`,前端不再手填。
|
||||
- `Arrival` / `Departure` 的业务来源按来源样式区分:第一种样式来自来源名单 Excel 的 `旅游日期`,第二种样式来自前端用户填写。
|
||||
- `Adults` 的业务来源是系统分房结果,前端不再手填。
|
||||
- 如后续需要恢复 Rate Code、Title、Email 或证件字段,需要单独确认字段来源、默认值和安全边界,不能直接把 CP1 自由文本框恢复为生产能力。
|
||||
|
||||
@@ -202,15 +245,15 @@ Content-Type: multipart/form-data
|
||||
| `hotel_id` | string | 否 | 酒店 ID;不传时按当前登录用户默认酒店或单酒店上下文解析 |
|
||||
| `people_per_room` | integer | 是 | 每间房人数,必须大于 0 |
|
||||
| `room_type` | string | 是 | 目标 Excel 的 `Room Type` |
|
||||
| `arrival` | date string | 条件必填 | CP3 第二种来源样式必填,格式 `yyyy-MM-dd`;第一种来源样式可不传,后端优先从 `旅游日期` 派生 |
|
||||
| `departure` | date string | 条件必填 | CP3 第二种来源样式必填,格式 `yyyy-MM-dd`;必须晚于 `arrival` |
|
||||
| `payment_type` | string | 否 | CP2 目标 Excel 的 `Payment Type`;为空时后端按 `BTQR` 处理;当前只允许 `BTQR`、`CA` |
|
||||
| `nationality` | string | 是 | CP2 目标 Excel 的 `Nationality`;当前只允许 `KR`、`CHN` |
|
||||
|
||||
CP2 不再接收以下前端业务字段作为生成依据:
|
||||
CP3 后仍不接收以下前端业务字段作为生成依据:
|
||||
|
||||
| 字段 | CP2 处理口径 |
|
||||
| 字段 | 处理口径 |
|
||||
| --- | --- |
|
||||
| `arrival` | 不由前端提交;后端从来源 Excel `旅游日期` 派生 |
|
||||
| `departure` | 不由前端提交;后端从来源 Excel `旅游日期` 派生 |
|
||||
| `title` | 固定为空 |
|
||||
| `rate_code` | 固定为空 |
|
||||
| `adults` | 后端按当前房间实际人数派生 |
|
||||
@@ -246,7 +289,9 @@ Content-Disposition: attachment; filename="rooming-list-<timestamp>.xlsx"
|
||||
- `people_per_room` 数字格式错误,返回 `ROOMING_LIST_VALIDATION_FAILED`。
|
||||
- `payment_type` 非 `BTQR` / `CA`,返回 `ROOMING_LIST_VALIDATION_FAILED`。
|
||||
- `nationality` 非 `KR` / `CHN`,返回 `ROOMING_LIST_VALIDATION_FAILED`。
|
||||
- 来源文件缺失、非 `.xls` / `.xlsx`、无法读取、缺少 `护照全名` 表头或缺少 / 无法解析 `旅游日期` 表头,返回 `ROOMING_LIST_SOURCE_FILE_INVALID`。
|
||||
- 第二种来源样式缺少 `arrival` / `departure`、日期格式错误或 `departure` 不晚于 `arrival`,返回 `ROOMING_LIST_VALIDATION_FAILED`。
|
||||
- 来源文件缺失、非 `.xls` / `.xlsx`、无法读取、既不能识别第一种 `护照全名` + `旅游日期`,也不能识别第二种 `英文姓` + `英文名`,返回 `ROOMING_LIST_SOURCE_FILE_INVALID`。
|
||||
- 第一种来源样式缺少 / 无法解析 `旅游日期` 表头,返回 `ROOMING_LIST_SOURCE_FILE_INVALID`。
|
||||
- 同一来源文件出现多个不同旅游日期区间,CP2 返回受控错误,不生成 Excel。
|
||||
- 错误详情只返回字段名或行号,不回显完整名单、证件号或源文件内容。
|
||||
|
||||
@@ -279,7 +324,7 @@ RESERVATION_ROOMING_LIST_GENERATE
|
||||
| `ReservationRoomingListGenerationController` | 接收前端上传请求,做登录、权限和酒店上下文校验 |
|
||||
| `ReservationRoomingListGenerationService` | 编排来源解析、分房、目标 Excel 渲染和文件响应 |
|
||||
| `ReservationRoomingListGenerationServiceImpl` | 具体业务实现 |
|
||||
| `RoomingListSourceExcelParser` | CP1 解析来源 Excel,提取护照姓名;CP2 需扩展为同时提取并校验统一旅游日期区间 |
|
||||
| `RoomingListSourceExcelParser` | CP1 解析来源 Excel,提取护照姓名;CP2 已扩展为同时提取并校验统一旅游日期区间;CP3 已扩展第二种 `英文姓` + `英文名` 样式,并在该样式下要求用户补日期 |
|
||||
| `RoomingListNameParser` | 拆分 `/` 或空格格式的护照姓名 |
|
||||
| `RoomingListGroupingService` | 按每房人数分组并生成目标行模型 |
|
||||
| `RoomingListExcelRenderer` | 生成目标格式 `.xlsx` |
|
||||
@@ -308,6 +353,7 @@ RESERVATION_ROOMING_LIST_GENERATE
|
||||
- 上传来源 Excel。
|
||||
- 填写每间房人数。
|
||||
- 填写目标 `Room Type`。
|
||||
- 填写 `Arrival` / `Departure`:第一种来源样式可不填,第二种来源样式必填;页面文案需说明“当来源名单没有旅游日期时请填写”。
|
||||
- 目标默认值区域只保留 `Payment Type` 和 `Nationality`。
|
||||
- `Payment Type` 使用下拉选择,默认 `BTQR`,当前可选择 `BTQR` 或 `CA`。
|
||||
- `Nationality` 使用下拉,只允许 `KR`、`CHN`。
|
||||
@@ -318,8 +364,8 @@ RESERVATION_ROOMING_LIST_GENERATE
|
||||
|
||||
- 不要在前端解析完整 Excel 作为权威结果;前端预览可以后置为后端 preview 接口。
|
||||
- 第一版如果没有 preview 接口,可以只展示用户输入和文件名,生成成功后直接下载。
|
||||
- CP2 页面不再展示或提交 `arrival`、`departure`、`title`、`rate_code`、`adults`、`children`、`vip`、`email`、`id_type`、`id_number`。
|
||||
- `arrival` / `departure` 由后端从来源 Excel `旅游日期` 解析后写入目标 Excel;前端不要自行读取 Excel 并推导日期。
|
||||
- CP3 页面重新展示并提交可选 `arrival`、`departure`;后端仅在第二种来源样式下要求这两个字段必填,第一种来源样式仍优先使用来源 Excel `旅游日期`。
|
||||
- 前端不要自行读取 Excel 并推导日期;如果用户上传第二种没有 `旅游日期` 的名单,由用户手工填写 `arrival` / `departure`。
|
||||
- `Adults` 由后端按分房结果计算;前端不要让用户覆盖。
|
||||
- 不要把上传文件内容、客人名单或生成文件内容写进浏览器日志、错误上报、URL 或 localStorage。
|
||||
|
||||
@@ -329,6 +375,11 @@ RESERVATION_ROOMING_LIST_GENERATE
|
||||
|
||||
- 能识别 `护照全名` 表头。
|
||||
- 能识别 `旅游日期` 表头,并把 `2026年5月9日-5月14日` 解析为 `Arrival=2026/05/09`、`Departure=2026/05/14`。
|
||||
- 能识别第二种来源样式 `英文姓` / `英文名` 表头。
|
||||
- 第二种来源样式下 `英文姓=FENG`、`英文名=MINNA` 能生成 `Name=FENG`、`First Name=MINNA`。
|
||||
- 第二种来源样式下领队也进入房表,实际人数以后端读取到的有效名单行数为准。
|
||||
- 第二种来源样式使用前端提交的 `arrival` / `departure` 写入目标 Excel。
|
||||
- 第二种来源样式缺少 `arrival` / `departure` 返回受控错误。
|
||||
- `LI/CHUNHONG` 能拆成 `Name=LI`、`First Name=CHUNHONG`。
|
||||
- `LI CHUNHONG` 能拆成 `Name=LI`、`First Name=CHUNHONG`。
|
||||
- 姓名首尾空格会 trim。
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
| `POST /api/reservation/tasks/{taskId}/opera-operations/{operationId}/retry` | `FRONTEND_USER` | 当前为 OPERA 模拟 | 登录 + `RESERVATION_OPERA_SIM_EXECUTE` + 酒店访问权 | 必须写业务审计和 attempt |
|
||||
| `GET /api/reservation/tasks/{taskId}/audits` | `FRONTEND_USER` | 已强制 Bearer 登录 + `RESERVATION_AUDIT_READ`;按任务实际所属酒店校验访问权 | 保持登录 + `RESERVATION_AUDIT_READ` + 酒店访问权 | 查询审计不再写审计 |
|
||||
| `POST /api/reservation/invoices/manual-generations` | `FRONTEND_USER` | 已实现 M009 CP2;强制 Bearer 登录 + `RESERVATION_INVOICE_GENERATE` + 酒店访问权;`task_id` / `order_id` 可为空,传入时反查对象所属酒店 | 保持登录 + `RESERVATION_INVOICE_GENERATE` + 酒店访问权;后续如增加历史列表或预填接口需单独登记权限 | 写业务审计,记录来源类型、模板版本、生成结果摘要;生成失败写入生成记录安全错误摘要 |
|
||||
| `POST /api/reservation/rooming-lists/generations` | `FRONTEND_USER` | 已实现 M010 CP1 / CP2;multipart 上传来源名单并直接下载 `.xlsx`;已在 multipart 参数绑定前前置校验登录和生成权限 | 登录 + `RESERVATION_ROOMING_LIST_GENERATE` + 酒店访问权;后端从来源 Excel `旅游日期` 派生 Arrival / Departure,Adults 按分房结果计算,目标默认值区域只保留 Payment Type / Nationality;Payment Type 默认 `BTQR` 且仅允许 `BTQR` / `CA`;第一版仍不落库、不上传 OSS | CP1 / CP2 不落生成记录表;错误响应不得记录完整名单、证件信息、源文件内容或生成文件内容;后续若增加历史记录再补业务审计 |
|
||||
| `POST /api/reservation/rooming-lists/generations` | `FRONTEND_USER` | 已实现 M010 CP1 / CP2 / CP3;CP3 兼容第二种 `英文姓` + `英文名` 名单样式;multipart 上传来源名单并直接下载 `.xlsx`;已在 multipart 参数绑定前前置校验登录和生成权限 | 登录 + `RESERVATION_ROOMING_LIST_GENERATE` + 酒店访问权;第一种来源样式后端从来源 Excel `旅游日期` 派生 Arrival / Departure,第二种来源样式由用户提交 Arrival / Departure;Adults 按分房结果计算,目标默认值区域只保留 Payment Type / Nationality;Payment Type 默认 `BTQR` 且仅允许 `BTQR` / `CA`;第一版仍不落库、不上传 OSS | CP1 / CP2 / CP3 不落生成记录表;错误响应不得记录完整名单、证件信息、源文件内容或生成文件内容;第二种样式不得回显中文名、护照号、生日、签发地等来源证件字段;后续若增加历史记录再补业务审计 |
|
||||
|
||||
### 3.2.1 V4 工作台、订单详情和任务详情页展示层技术信息边界
|
||||
|
||||
|
||||
Reference in New Issue
Block a user