Files
th-hotel-simple/docs/project/requirements/M010-rooming-list-excel-generation-v1.md

12 KiB
Raw Blame History

M010 Rooming List Excel 生成 V1

项目 内容
文档状态 后端 CP1 已实现,第一版直接下载 .xlsx,不落库、不上传 OSS
适用范围 从旅行团名单 Excel 解析护照姓名,并生成酒店 / PMS 可导入的 Rooming List Excel
当前目标 第一阶段已支持前端上传来源 Excel、填写分房和目标列默认值后端同步生成目标格式 .xlsx 供浏览器下载
依赖能力 登录权限、酒店上下文、Apache POI 或等价 Excel 读写能力

1. 背景

当前系统已经支持 Manual Invoice 生成,但运营中还存在另一类独立工具诉求:旅行社或渠道提供一份名单 Excel里面包含旅客护照姓名酒店侧需要整理成 PMS / 导入模板要求的 Rooming List Excel。

本功能第一版只解决“来源名单到目标 Rooming List”的结构转换和分房填表问题不依赖订单、任务、SuperAgent、AgentBus 或 OPERA。

2. 第一阶段定位

第一阶段应做到:

  • 前端上传 .xls / .xlsx 来源名单。
  • 后端解析来源名单中的护照姓名字段。
  • 前端输入每间房人数。
  • 前端填写或选择目标 Excel 中除姓名外的字段。
  • 后端按来源名单顺序分组,生成目标格式 Excel。
  • 浏览器直接下载生成后的 .xlsx 文件。

第一阶段不做:

  • 不落业务订单。
  • 不创建任务。
  • 不上传 OSS。
  • 不新增生成记录表。
  • 不做历史查询和重下载。
  • 不接真实 OPERA / OHIP。
  • 不做复杂房型混住、拖拽换房或手工调整入住人顺序。
  • 不从任务详情或订单详情自动预填字段。

3. 与现有模块关系

本功能属于 Reservation 运营工具,不属于 M008 通用文件转换,也不属于 M009 Manual Invoice。

边界说明:

  • M008 负责 Excel 转 PDF面向平台文件转换和调试能力。
  • M009 负责 Proforma Invoice 生成,输出 PDF 并上传 OSS。
  • M010 负责 Rooming List Excel 生成,第一版只输出 .xlsx 文件流。

因此第一版建议在 Reservation 模块内新增独立接口、权限码和服务,不复用发票生成权限,也不让前端调用 M008 调试接口。

4. 来源 Excel 解析规则

基于当前样例来源文件,第一版默认识别以下表头:

来源字段 中文说明 第一版用途
护照全名 护照姓名,可能包含 / 或空格 解析为目标 Excel 的 NameFirst Name

第一版只使用 护照全名 生成目标姓名字段。来源文件中的证件号、生日、性别、年龄等字段暂不自动写入目标 Excel除非后续单独确认。

4.1 姓名拆分

支持的输入格式:

LI/CHUNHONG
LI CHUNHONG
LIU/JIAYI

规则:

  • 先 trim 首尾空格。
  • 优先按 / 拆分。
  • 如果没有 /,按连续空白拆分。
  • 第一段写入目标 Name
  • 剩余部分合并后写入目标 First Name
  • 如果无法拆出两段,返回明确校验错误,由前端提示用户修正来源 Excel 或后续增加字段映射。

中文说明:

  • 当前目标模板中 Name 更接近姓氏字段,First Name 更接近名字段。
  • 第一版不尝试判断中文、韩文、英文姓名顺序,也不做大小写改写。

5. 分房生成规则

前端需要传入 people_per_room,表示每间房人数。

规则:

  • 按来源 Excel 中旅客出现顺序分组。
  • room_count = ceil(total_people / people_per_room)
  • 每组第一位旅客写入目标 Excel 的 NameFirst Name
  • 同组剩余旅客写入目标 Excel 的 Accompanying Guests
  • 多个陪同人使用英文逗号 , 分隔。
  • 最后一组人数不足 people_per_room 时,仍按一间房生成一行。

示例:

people_per_room = 3

第 1 组:
  Name = LI
  First Name = CHUNHONG
  Accompanying Guests = ZHANG GAILI, LI HONG

第 2 组:
  Name = LIU
  First Name = JIAYI
  Accompanying Guests = ZHU XINGTONG, CHEN YUCHAI

6. 目标 Excel 字段

目标 Excel 第一版按当前样例模板生成以下列:

目标列 第一版来源
Line 后端按生成行号从 1 递增
Name 每间房第一位旅客的姓氏 / 第一段姓名
First Name 每间房第一位旅客的名字 / 剩余姓名
Title 前端传入,第一版可为空
Arrival 前端传入
Departure 前端传入
Room Type 前端传入
Rate Code 前端传入
Number of Rooms 第一版每行固定为 1,后续如目标模板变化再调整
Adults 前端传入;为空时可由后端按当前分组人数派生
Children 前端传入;第一版默认可为 0
Payment Type 前端传入
VIP 前端传入,第一版可为空
Accompanying Guests 同房其他旅客姓名,英文逗号分隔
Nationality 前端传入
Email 前端传入,第一版可为空
ID Type 前端传入,第一版可为空
ID Number 前端传入,第一版可为空

中文说明:

  • LineNameFirst NameNumber of RoomsAccompanying Guests 外,第一版都由前端输入或选择。
  • 如果前端希望 Adults 自动等于当前房间人数,后端可以提供默认规则;但请求体仍建议显式保留覆盖字段,方便后续处理儿童、领队或特殊房间。

7. 接口契约

第一版已新增业务接口,不复用 M008 文件转换接口:

POST /api/reservation/rooming-lists/generations
Authorization: Bearer <access_token>
Content-Type: multipart/form-data

表单字段:

字段 类型 必填 中文说明
file file 来源 Excel 文件,仅支持 .xls / .xlsx
hotel_id string 酒店 ID不传时按当前登录用户默认酒店或单酒店上下文解析
people_per_room integer 每间房人数,必须大于 0
arrival string 入住日期,酒店本地业务日期,格式 yyyy-MM-dd
departure string 离店日期,酒店本地业务日期,格式 yyyy-MM-dd
room_type string 目标 Excel 的 Room Type
title string 目标 Excel 的 Title
rate_code string 目标 Excel 的 Rate Code
adults integer 目标 Excel 的 Adults;为空时可由后端按分组人数派生
children integer 目标 Excel 的 Children;为空时默认 0
payment_type string 目标 Excel 的 Payment Type
vip string 目标 Excel 的 VIP
nationality string 目标 Excel 的 Nationality
email string 目标 Excel 的 Email
id_type string 目标 Excel 的 ID Type
id_number string 目标 Excel 的 ID Number

成功响应:

HTTP 200
Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
Content-Disposition: attachment; filename="rooming-list-<timestamp>.xlsx"

错误响应沿用后端统一错误模型,例如:

{
  "error_code": "ROOMING_LIST_SOURCE_FILE_INVALID",
  "message": "来源名单文件不合法。",
  "details": [
    "未找到表头:护照全名"
  ]
}

已收口的第一版错误场景:

  • multipart 必填字段缺失,返回 ROOMING_LIST_VALIDATION_FAILED
  • arrival / departure 日期格式错误,返回 ROOMING_LIST_VALIDATION_FAILED
  • people_per_roomadultschildren 数字格式错误,返回 ROOMING_LIST_VALIDATION_FAILED
  • 来源文件缺失、非 .xls / .xlsx、无法读取或缺少 护照全名 表头,返回 ROOMING_LIST_SOURCE_FILE_INVALID
  • 错误详情只返回字段名或行号,不回显完整名单、证件号或源文件内容。

8. 权限、安全和审计

接口分类:FRONTEND_USER

已新增权限码:

RESERVATION_ROOMING_LIST_GENERATE

管控要求:

  • 必须登录。
  • 必须拥有 RESERVATION_ROOMING_LIST_GENERATE 权限。
  • 上传接口在 multipart 参数绑定前执行登录和权限前置校验,未登录或无权限请求不会进入来源文件解析。
  • 必须校验用户对 hotel_id 的访问权。
  • 第一版直接下载、不落库,因此不写生成记录表。
  • 当前 CP1 不新增持久化审计表;后续如增加生成记录或历史下载,再补业务审计落库。
  • 日志和错误响应不得输出完整名单、证件号、源文件内容或生成文件内容。

9. 后端实现拆分

已实现类职责:

类 / 能力 中文职责
ReservationRoomingListGenerationController 接收前端上传请求,做登录、权限和酒店上下文校验
ReservationRoomingListGenerationService 编排来源解析、分房、目标 Excel 渲染和文件响应
ReservationRoomingListGenerationServiceImpl 具体业务实现
RoomingListSourceExcelParser 解析来源 Excel提取护照姓名
RoomingListNameParser 拆分 / 或空格格式的护照姓名
RoomingListGroupingService 按每房人数分组并生成目标行模型
RoomingListExcelRenderer 生成目标格式 .xlsx
ReservationRoomingListGenerationRequest multipart 外的业务参数请求模型
ReservationRoomingListGeneratedFile 生成后的下载文件字节和文件名
ReservationRoomingListGuestDto 解析后的旅客姓名结构
ReservationRoomingListRoomDto 分房后的目标行结构

中文说明:

  • 第一版不需要新增 Entity、Mapper 和 Repository。
  • 如果后续要生成记录、OSS 上传、历史查询或重下载,再新增 workflow_reservation_rooming_list_generation 表。
  • 解析和渲染能力应和 Controller 解耦,便于单元测试。
  • 目标 Excel 固定列宽,不调用 POI autoSizeColumn,避免后端运行环境依赖本机字体或图形环境。

10. 前端实现建议

第一版页面可以放在 Reservation 工具入口,例如:

/reservation/rooming-lists/new

页面能力:

  • 上传来源 Excel。
  • 填写每间房人数。
  • 填写或选择 Arrival、Departure、Room Type、Rate Code、Payment Type、Nationality 等字段。
  • 展示解析预览:总人数、预计房间数、前几行分房结果。
  • 点击生成后下载 .xlsx

前端注意:

  • 不要在前端解析完整 Excel 作为权威结果;前端预览可以后置为后端 preview 接口。
  • 第一版如果没有 preview 接口,可以只展示用户输入和文件名,生成成功后直接下载。
  • 不要把上传文件内容、客人名单或生成文件内容写进浏览器日志、错误上报、URL 或 localStorage。

11. 测试范围

后端测试建议覆盖:

  • 能识别 护照全名 表头。
  • LI/CHUNHONG 能拆成 Name=LIFirst Name=CHUNHONG
  • LI CHUNHONG 能拆成 Name=LIFirst Name=CHUNHONG
  • 姓名首尾空格会 trim。
  • people_per_room=3 时 32 人生成 11 行。
  • 尾房人数不足时仍生成一行。
  • Accompanying Guests 使用英文逗号拼接。
  • 未找到表头时返回明确错误。
  • 非 Excel 文件、空文件、超大文件返回明确错误。
  • 无 token、无权限、无酒店访问权被拦截。

12. 后续版本候选

后续可以继续扩展:

  • 生成记录表和历史下载。
  • 生成文件上传 OSS。
  • 后端预览接口。
  • 支持前端手工调整分房顺序。
  • 支持不同房间不同人数。
  • 支持字段映射配置,允许用户选择来源 Excel 中的姓名列。
  • 支持从订单、任务或 SourceMessage 附件自动带入名单。
  • 支持从任务详情或订单详情预填 Arrival、Departure、Room Type、Rate Code 等字段。