调整Rooming List导出日期格式

This commit is contained in:
andy
2026-07-22 17:43:23 +07:00
parent 0de960372b
commit 76d253afc4
6 changed files with 16 additions and 14 deletions

View File

@@ -485,7 +485,7 @@ RESERVATION_ROOMING_LIST_GENERATE
- 姓名支持 `LI/CHUNHONG``LI CHUNHONG` 两类格式;后端会把第一段写入目标 `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`
- 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` 默认 `BTQR`,当前允许 `BTQR``CA``Nationality` 只允许 `KR``CHN`
- CP2 页面不再展示或提交 `Title``Rate Code``VIP``Email``ID Type``ID Number`,这些目标列第一版固定为空。

View File

@@ -1221,7 +1221,7 @@ 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`
- `Adults` 按当前分房行实际人数计算;尾房人数不足时按实际人数写入。
- `Children` 固定为 `0`
- `Title``Rate Code``VIP``Email``ID Type``ID Number` 第一版固定为空。

View File

@@ -110,15 +110,15 @@ CP2 起后端应识别来源 Excel 的 `旅游日期` 表头,并从有名单
- 右侧结束日期可以省略年份;省略年份时继承起始日期年份。
- 右侧结束日期可以省略月份;省略月份时继承起始日期月份。
- 支持常见区间分隔符,例如 ```-````—``至``到`
- `Arrival` 使用起始日期,格式化为 `yyyy-MM-dd`
- `Departure` 使用结束日期,格式化为 `yyyy-MM-dd`
- `Arrival` 使用起始日期,格式化为 `yyyy/MM/dd`
- `Departure` 使用结束日期,格式化为 `yyyy/MM/dd`
- 旅游日期属于酒店本地业务日期,不按 UTC 时间点换算。
- 同一来源文件中参与生成的名单行必须解析出同一个旅游日期区间如果出现多个不同区间CP2 先返回受控错误,不自动混合生成。
- 如果缺少 `旅游日期` 表头、旅游日期为空、格式无法解析或结束日期不晚于起始日期,返回 `ROOMING_LIST_SOURCE_FILE_INVALID` 或统一受控业务错误,不应生成半成品 Excel。
中文说明:
- 当前样表第 2 行表头中包含 `旅游日期`,第 3 行起数据为 `2026年5月9日5月14日`,可派生 `Arrival=2026-05-09``Departure=2026-05-14`
- 当前样表第 2 行表头中包含 `旅游日期`,第 3 行起数据为 `2026年5月9日5月14日`,可派生 `Arrival=2026/05/09``Departure=2026/05/14`
- CP2 暂不支持同一个文件中多批次、多旅游日期混合分房;如后续出现该真实场景,需要先设计按批次拆文件或按旅游日期分组生成多个 Sheet / 多个文件。
## 5. 分房生成规则
@@ -328,7 +328,7 @@ RESERVATION_ROOMING_LIST_GENERATE
后端测试建议覆盖:
- 能识别 `护照全名` 表头。
- 能识别 `旅游日期` 表头,并把 `2026年5月9日5月14日` 解析为 `Arrival=2026-05-09``Departure=2026-05-14`
- 能识别 `旅游日期` 表头,并把 `2026年5月9日5月14日` 解析为 `Arrival=2026/05/09``Departure=2026/05/14`
- `LI/CHUNHONG` 能拆成 `Name=LI``First Name=CHUNHONG`
- `LI CHUNHONG` 能拆成 `Name=LI``First Name=CHUNHONG`
- 姓名首尾空格会 trim。

View File

@@ -21,6 +21,8 @@ import org.springframework.stereotype.Component;
@Component
public class RoomingListExcelRenderer {
private static final DateTimeFormatter TARGET_DATE_FORMATTER =
DateTimeFormatter.ofPattern("yyyy/MM/dd");
private static final String[] HEADERS = {
"Line",
"Name",
@@ -98,8 +100,8 @@ public class RoomingListExcelRenderer {
row.createCell(1).setCellValue(room.primaryGuest().lastName());
row.createCell(2).setCellValue(room.primaryGuest().firstName());
row.createCell(3).setCellValue("");
row.createCell(4).setCellValue(arrival.format(DateTimeFormatter.ISO_LOCAL_DATE));
row.createCell(5).setCellValue(departure.format(DateTimeFormatter.ISO_LOCAL_DATE));
row.createCell(4).setCellValue(arrival.format(TARGET_DATE_FORMATTER));
row.createCell(5).setCellValue(departure.format(TARGET_DATE_FORMATTER));
row.createCell(6).setCellValue(defaultString(request.roomType()));
row.createCell(7).setCellValue("");
row.createCell(8).setCellValue(1);

View File

@@ -101,9 +101,9 @@ class ReservationRoomingListGenerationControllerTest {
.andExpect(result -> assertThat(workbookCell(result.getResponse().getContentAsByteArray(), 1, 3))
.isEmpty())
.andExpect(result -> assertThat(workbookCell(result.getResponse().getContentAsByteArray(), 1, 4))
.isEqualTo("2026-05-09"))
.isEqualTo("2026/05/09"))
.andExpect(result -> assertThat(workbookCell(result.getResponse().getContentAsByteArray(), 1, 5))
.isEqualTo("2026-05-14"))
.isEqualTo("2026/05/14"))
.andExpect(result -> assertThat(workbookCell(result.getResponse().getContentAsByteArray(), 1, 9))
.isEqualTo("2"))
.andExpect(result -> assertThat(workbookCell(result.getResponse().getContentAsByteArray(), 1, 10))

View File

@@ -60,8 +60,8 @@ class ReservationRoomingListGenerationServiceImplTest {
assertThat(cellText(firstRoom.getCell(1))).isEqualTo("LI");
assertThat(cellText(firstRoom.getCell(2))).isEqualTo("CHUNHONG");
assertThat(cellText(firstRoom.getCell(3))).isEmpty();
assertThat(cellText(firstRoom.getCell(4))).isEqualTo("2026-05-09");
assertThat(cellText(firstRoom.getCell(5))).isEqualTo("2026-05-14");
assertThat(cellText(firstRoom.getCell(4))).isEqualTo("2026/05/09");
assertThat(cellText(firstRoom.getCell(5))).isEqualTo("2026/05/14");
assertThat(cellText(firstRoom.getCell(6))).isEqualTo("UG1");
assertThat(cellText(firstRoom.getCell(7))).isEmpty();
assertThat(cellText(firstRoom.getCell(8))).isEqualTo("1");
@@ -119,8 +119,8 @@ class ReservationRoomingListGenerationServiceImplTest {
try (XSSFWorkbook workbook = new XSSFWorkbook(new ByteArrayInputStream(generatedFile.content()))) {
Row firstRoom = workbook.getSheetAt(0).getRow(1);
assertThat(cellText(firstRoom.getCell(4))).isEqualTo("2026-05-09");
assertThat(cellText(firstRoom.getCell(5))).isEqualTo("2026-05-14");
assertThat(cellText(firstRoom.getCell(4))).isEqualTo("2026/05/09");
assertThat(cellText(firstRoom.getCell(5))).isEqualTo("2026/05/14");
}
}