diff --git a/changelogs-v2/2026-09/20_8030_全团需求汇总逐日房间补酒店维度与住宿日期-修改接口-管理后台.md b/changelogs-v2/2026-09/20_8030_全团需求汇总逐日房间补酒店维度与住宿日期-修改接口-管理后台.md index 80cba380..344b56a7 100644 --- a/changelogs-v2/2026-09/20_8030_全团需求汇总逐日房间补酒店维度与住宿日期-修改接口-管理后台.md +++ b/changelogs-v2/2026-09/20_8030_全团需求汇总逐日房间补酒店维度与住宿日期-修改接口-管理后台.md @@ -150,7 +150,7 @@ Authorization: Bearer | 589500 | 团期不存在(本次不变) | | 401 | 未登录(网关拦截) | -本次新增内部错误码 589574(资源服务住宿名称补全降级),**只在服务端降级日志里出现,不会传播给前端**。 +本次新增内部错误码 **589596**(资源服务住宿名称补全降级),**只在服务端降级日志里出现,不会传播给前端**。(初版误取 589574,该号是 #7932 的保留位,已于 2026-09-20 随 #8046 订正为 589596。) #### 业务边界 @@ -222,10 +222,28 @@ Authorization: Bearer ## 八、测试环境已验证 +TEST 环境(`hl-order-service-v3`,dev-v3,2026-09-20),团期 `jw测试1期`(`2101506167098511362`,出发 2026-09-27,6 晚)。 + ``` -待部署 TEST 后回填实测结果(工单 #8030 AC-1~AC-11) +AC-1 单户 6 晚逐晚不同酒店,hotels[] 与 hotelName 正确 ✓ +AC-2 同天多户不同酒店 → 出多条并按间数降序;同一酒店合并且间数相加 ✓ +AC-3 间数不变量 Σhotels == Σrooms:单测 + TEST 六天逐日实测 ✓ +AC-4 stayDate = 出发日 + dayNumber − 1,跨月 09-30 → 10-01 正确 ✓ +AC-5 字符串形态 hotelId 的存量 days JSON 正确解析(TEST 数据本就是字符串)✓ +AC-6 候选缺失 / hotelId 为空 → 归「未指定」一条恒排末位,间数不丢 ✓ +AC-7 酒店名:快照优先;快照置空后按 ID 批量补,实测补出正确名称 ✓ +AC-8 既有字段零变化:三个户数 / rooms[] / vehicleSeatSummary / + orderSpecialTags 与改前逐字一致 ✓ +AC-9 客户自订晚仍不计入(该日由 3 间降为 2 间) ✓ +AC-10 判权:低权限角色 1002/user → 589507;超管 200 ✓ +AC-11 changelog 按「修改接口」推送(提交 af00e6f) ✓ ``` +订正(2026-09-20,#8046 回归发现):本单新增的降级错误码原取 589574,该号被 #7932 +登记为保留位且有测试断言它必须空闲,#8030 当轮回归范围未覆盖该测试类故漏网。 +现已改为 **589596**(见下方「五、错误码」与 PR [#8055](https://git.1814.love:8443/wx/HL/pulls/8055) 第一个提交)。 +该码只在服务端降级路径产生,从不传播给前端,对前端无影响。 + --- ## 十、相关文档 diff --git a/changelogs-v2/2026-09/20_8046_团期用房新增子订单订房记录接口-新增接口-管理后台.md b/changelogs-v2/2026-09/20_8046_团期用房新增子订单订房记录接口-新增接口-管理后台.md new file mode 100644 index 00000000..e385d754 --- /dev/null +++ b/changelogs-v2/2026-09/20_8046_团期用房新增子订单订房记录接口-新增接口-管理后台.md @@ -0,0 +1,414 @@ +--- +schema: "hl-changelog/v2" +ticket: "8046" +title: "团期用房新增子订单订房记录接口" +consumer: "admin" +author: "jw(GIT)" +change_type: "新增接口" +backend_status: "deployed" +gateway_status: "not_required" +frontend_status: "pending" +frontend_owner: "mmg" +frontend_ref: "" +target_release: "" +verified_at: "2026-09-20" +status_note: "团期「查看需求 · 用房」板块是上下两块,此前只有上块(汇总)有接口。本次新增下块:GET /v3/admin/order/group-batch/{groupBatchId}/requirement/hotel-households,一次返回该团期下所有需订房子订单的逐晚填报明细——每户一张卡(团号 / 联系人 / 人数 / 定制师 / 需求状态 / 配房需求 / 特殊需求标签 / 打回原因)+ 逐晚(住宿日期 / 酒店 / 城市 + 区县 / 房型 / 间数;页面地点那列请用 district 而非 city)。此前这块数据只能逐户调 GET /v3/admin/order/{orderId}/itinerary,N 户 N 次。两块的数字关系是硬约束:汇总就是把子订单记录汇总出来的,requirement-summary 的逐日间数 == 本接口里 countedInSummary=true 那些户的逐日加总,一间不差;判据与逐晚间数都与汇总走同一份单源(RequirementStatus.isSummaryCounted 与 HotelRequirementDaysNormalizer),由单测守护。但本列表比汇总宽:被打回正在改的户也会列出来并标 countedInSummary=false(否则管理员一打回,那户就从页面消失,没法跟进谁还没改回来),前端应灰显并标注「打回中 · 未计入汇总」。客户自订晚同理——汇总整晚跳过,本接口仍列出该晚并置 customerSelfBooked=true、hotels 为空数组,避免卡片上「第 N 晚凭空消失」。requirement-summary 一字未改。" +updated_at: "2026-09-20" +base: "dev-v3" +--- + +# order-v3: 团期用房新增子订单订房记录接口 + +> **服务**: hl-order-service-v3 (端口 8086) +> **PR**: [#8055](https://git.1814.love:8443/wx/HL/pulls/8055)(主体)、[#8057](https://git.1814.love:8443/wx/HL/pulls/8057)(补 district)、[#8059](https://git.1814.love:8443/wx/HL/pulls/8059)(打回户改看最新版本行)、[#8060](https://git.1814.love:8443/wx/HL/pulls/8060)(AC-11 固化) +> **Issue**: [#8046](https://git.1814.love:8443/wx/HL/issues/8046) +> **日期**: 2026-09-20 +> **影响范围**: 管理后台「团期订单 → 查看需求」页的「用房」板块下半部分(子订单订房记录) + +--- + +## ⚠️ 关键变化 + +- **纯新增一个只读端点**,既有接口一个没动(`requirement-summary` 逐字未改)。 +- **汇总 == Σ子订单**:`requirement-summary` 的逐日间数严格等于本接口里 `countedInSummary=true` 那些户的逐日加总。两处走同一份状态判据与同一个 days 归一器,不是各算各的。 +- **本列表比汇总宽**:被打回正在改的户也列出来,标 `countedInSummary=false`。前端要灰显并标注「打回中 · 未计入汇总」,否则用户会觉得两块数字对不上。 +- **客户自订晚保留**:汇总整晚跳过,本接口列出该晚并标记,`hotels` 为空数组。 +- **地域是反查来的**:days JSON 里不存 city/district,按 hotelId 批量查资源库得到;取不到为 `null`,不影响间数。**页面地点那一列用 `district` 而不是 `city`**(见出参表说明)。 + +--- + +## 一、背景 + +原型「用房」板块是上下两块: + +| 块 | 内容 | 改前 | +|---|---|---| +| 上:汇总 | Day N \| 酒店 \| 房型 \| 所需间数 | ✅ `requirement-summary`(#8030 已交付) | +| 下:子订单订房记录 | 每户一张卡 + 逐晚(第N晚 / 日期 / 城市·酒店 / 间数 / 房型)+ 配房需求 + 打回 | ❌ **无接口** | + +下块此前只能逐户调 `GET /v3/admin/order/{orderId}/itinerary`,N 户就是 N 次请求。 + +最接近的现有端点 `GET /v3/admin/house/group-batches/{groupBatchId}/room-requirements` 三处对不上:结构是 day-major(第N晚 → 各户)而原型要 order-major(每户 → 逐晚);每户每晚只有 `roomCategory` + `roomCount`,**酒店在上游归一的「段视图」那步就被丢掉了**;另缺定制师姓名、真实房型名、需求级配房备注。 + +--- + +## 二、变更接口清单 + +| # | 接口 | 方法 | 路径 | 变更类型 | 说明 | +|---|------|------|------|----------|------| +| 1 | 团期子订单订房记录 | GET | `/v3/admin/order/group-batch/{groupBatchId}/requirement/hotel-households` | 新增 | 一次返回该团期下所有需订房子订单的逐晚填报明细 | + +--- + +## 三、接口详情 + +### 1. 团期子订单订房记录 `GET /v3/admin/order/group-batch/{groupBatchId}/requirement/hotel-households` + +**VO**: `Result` + +#### 使用场景 + +团期详情「查看需求」页「用房」板块的下半部分:逐户展示定制师填报了什么,团期管理员据此审核或打回。与上半部分的汇总表并列展示,两者各调各的接口。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| groupBatchId | Path | Long | ✅ | 团期 ID | 团期不存在返回 589500 | + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| groupBatchId | String | 团期 ID(字符串序列化防 JS 精度丢失) | +| departDate | String(yyyy-MM-dd) | 团期出发日;未定时为 `null`,此时各晚 `stayDate` 也全为 `null` | +| householdCount | Integer | 本列表户数(= 需订房户数,与汇总的 `hotelNeededOrderCount` 同口径) | +| countedHouseholdCount | Integer | 其中计入汇总间数的户数;小于 `householdCount` 时,差值就是正被打回的户 | +| households[] | List | 子订单订房记录,按 `orderNo` 升序 | +| households[].orderId | String | 子订单 ID | +| households[].orderNo | String | 子订单团号 | +| households[].customerName | String | 主联系人姓名 | +| households[].participantCount | Integer | 出行人数(成人+儿童+小童+婴儿,走订单域单源公式) | +| households[].consultantId | String | 定制师 ID;未指派为 `null` | +| households[].consultantName | String | 定制师姓名;未指派为 `null` | +| households[].status | String | 需求状态码(`PENDING_REVIEW` / `PENDING` / `PROCESSING` / `DONE` / `REJECTED_TO_CONSULTANT` / `REJECTED_TO_ADMIN`);该户尚未提交需求时为 `null` | +| households[].statusName | String | 状态中文名;状态为空或未知值时为 `null` | +| households[].countedInSummary | Boolean | **该户是否计入了汇总间数**。四个计入态为 `true`,两个打回态为 `false`,未提交需求为 `false` | +| households[].remark | String | 配房需求自由文本(如「希望安排有窗房间」);未填为 `null` | +| households[].specialTags | List\ | 特殊需求标签(`house_special_demand` 字典,如 连通房 / 同层相邻);未填为 `[]` | +| households[].returnRemark | String | 打回原因;未被打回过为 `null` | +| households[].returnedAt | String(yyyy-MM-dd HH:mm:ss) | 打回时间;未被打回过为 `null` | +| households[].days[] | List | 逐晚明细,按 `dayNumber` 升序;未提交需求时为 `[]` | +| households[].days[].dayNumber | Integer | 第几晚(从 1 起) | +| households[].days[].stayDate | String(yyyy-MM-dd) | 住宿日期 = 出发日 + dayNumber − 1;团期无出发日为 `null` | +| households[].days[].customerSelfBooked | Boolean | 该晚是否客户自订。为 `true` 时 `hotels` 为空数组且不计入汇总间数,**但该晚仍会列出** | +| households[].days[].hotels[] | List | 该晚的住宿(一般 1 家;「分住」时多家;自订晚为 `[]`) | +| households[].days[].hotels[].hotelId | String | 酒店 ID;该段没有候选或未填酒店时为 `null`(间数照常不丢) | +| households[].days[].hotels[].hotelName | String | 酒店名:优先取需求里落库的快照,快照缺的按 ID 批量补;资源服务不可用时为 `null` | +| households[].days[].hotels[].city | String | 酒店所在**地级市**中文名(如「呼伦贝尔市」),按 hotelId 反查资源库;未维护或资源服务不可用时为 `null` | +| households[].days[].hotels[].district | String | 酒店所在**区县**中文名(如「海拉尔区」「额尔古纳市」)。**页面上「海拉尔 · 海堂酒店」这一列请用本字段**,不要用 `city`——TEST 实测全库酒店的 `city` 几乎清一色「呼伦贝尔市」(额尔古纳 14 家、海拉尔 7 家、满洲里 6 家全在同一个 city 下),拿它渲染同一团期每晚都显示同一个地级市,区分不出地点 | +| households[].days[].hotels[].totalRoomCount | Integer | 该晚该酒店合计间数 | +| households[].days[].hotels[].rooms[] | List | 该晚该酒店的房型行(定制师填的原貌,不做合并) | +| households[].days[].hotels[].rooms[].roomTypeId | String | 房型 ID;未填为 `null` | +| households[].days[].hotels[].rooms[].roomTypeName | String | 房型名称,定制师填的真实房型;未填为 `null` | +| households[].days[].hotels[].rooms[].roomCategory | String | 房型大类编码(`room_category` 字典);缺失时为「未知」 | +| households[].days[].hotels[].rooms[].roomCategoryName | String | 房型大类中文名;字典无此编码或不可用时为 `null` | +| households[].days[].hotels[].rooms[].roomCount | Integer | 间数 | + +#### 请求示例 + +```http +GET /v3/admin/order/group-batch/2101506167098511362/requirement/hotel-households +Authorization: Bearer +``` + +#### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": { + "groupBatchId": "2101506167098511362", + "departDate": "2026-09-27", + "householdCount": 2, + "countedHouseholdCount": 2, + "households": [ + { + "orderId": "2101506167043985410", + "orderNo": "HL20260920105808925", + "customerName": "张三", + "participantCount": 6, + "consultantId": "2083457702519873537", + "consultantName": "金卫", + "status": "PENDING_REVIEW", + "statusName": "待审核", + "countedInSummary": true, + "remark": "", + "specialTags": [], + "returnRemark": null, + "returnedAt": null, + "days": [ + { + "dayNumber": 1, + "stayDate": "2026-09-27", + "customerSelfBooked": false, + "hotels": [ + { + "hotelId": "2023714929877450753", + "hotelName": "呼伦贝尔香格里拉大酒店", + "city": "呼伦贝尔市", + "district": "满洲里市", + "totalRoomCount": 2, + "rooms": [ + { + "roomTypeId": "3002000000000000013", + "roomTypeName": "大床房", + "roomCategory": "KING", + "roomCategoryName": "豪华大床", + "roomCount": 1 + }, + { + "roomTypeId": "3002000000000000013", + "roomTypeName": "大床房", + "roomCategory": "KING", + "roomCategoryName": "豪华大床", + "roomCount": 1 + } + ] + } + ] + }, + { + "dayNumber": 2, + "stayDate": "2026-09-28", + "customerSelfBooked": false, + "hotels": [ + { + "hotelId": "3001000000000000005", + "hotelName": "额尔古纳白桦大酒店", + "city": "呼伦贝尔市", + "district": "额尔古纳市", + "totalRoomCount": 2, + "rooms": [ + { + "roomTypeId": "3002000000000000005", + "roomTypeName": "主题标间", + "roomCategory": "STANDARD", + "roomCategoryName": "标间", + "roomCount": 1 + }, + { + "roomTypeId": "3002000000000000005", + "roomTypeName": "主题标间", + "roomCategory": "KING", + "roomCategoryName": "豪华大床", + "roomCount": 1 + } + ] + } + ] + } + ] + }, + { + "orderId": "2101507276118626306", + "orderNo": "HL20260920110233355", + "customerName": "王五", + "participantCount": 2, + "consultantId": "2083457702519873537", + "consultantName": "金卫", + "status": "PENDING_REVIEW", + "statusName": "待审核", + "countedInSummary": true, + "remark": null, + "specialTags": [], + "returnRemark": null, + "returnedAt": null, + "days": [ + { + "dayNumber": 1, + "stayDate": "2026-09-27", + "customerSelfBooked": false, + "hotels": [ + { + "hotelId": "3001000000000000005", + "hotelName": "额尔古纳白桦大酒店", + "city": "呼伦贝尔市", + "district": "额尔古纳市", + "totalRoomCount": 1, + "rooms": [ + { + "roomTypeId": "3002000000000000005", + "roomTypeName": "主题标间", + "roomCategory": "STANDARD", + "roomCategoryName": "标间", + "roomCount": 1 + } + ] + } + ] + } + ] + } + ] + } +} +``` + +> 上面是 TEST 环境 2026-09-20 的真实读数(团期 `jw测试1期`),为控制篇幅只保留了每户前 1–2 晚。 + +#### 空数据 / 降级响应 + +团期下没有需订房子订单时: + +```json +{ + "code": 200, + "message": "成功", + "data": { + "groupBatchId": "2101506167098511362", + "departDate": "2026-09-27", + "householdCount": 0, + "countedHouseholdCount": 0, + "households": [] + } +} +``` + +资源服务不可用时**不报错**:`hotelName` 回落到需求里的快照名(快照也没有才为 `null`)、`city` 与 `district` 为 `null`,间数与酒店 ID 照常返回。字典不可用时 `roomCategoryName` 为 `null`,`roomCategory` 编码与间数照常。某户 days JSON 损坏时该户 `days` 为 `[]`,**其它户不受影响**。 + +#### 错误响应 + +```json +{ + "code": 589507, + "message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)", + "data": null +} +``` + +| code | 触发条件 | +|---|---| +| 589507 | 当前角色没有 `group-batch:view` | +| 589500 | 团期不存在 | +| 401 | 未登录(网关拦截) | + +#### 业务边界 + +- **汇总 == Σ子订单(硬约束)**:`requirement-summary` 的 `dailyRoomBreakdown[].rooms[].totalRoomCount` 逐天等于本接口 `countedInSummary=true` 各户该晚各酒店 `rooms[].roomCount` 之和。两处用同一个状态判据(`RequirementStatus.isSummaryCounted`)和同一个 days 归一器,单测有「明细聚合回去必等于汇总视角」的不变量守护。 +- **列表比汇总宽**:被打回(`REJECTED_TO_CONSULTANT` / `REJECTED_TO_ADMIN`)的户仍出现在 `households[]`,`countedInSummary=false`。这是刻意的——汇总排除打回态是因为作废草稿的间数会让「全团要几间」随一份正在改的需求浮动(#7925);而明细若也排除,管理员一打回那户就从页面消失,没法跟进。 +- **打回户的 `status` / `returnRemark` / `days` 照常返回**:打回是*原地把需求行改成 `REJECTED_*` 并失活*,该户此时**没有任何 active 行**。本端点对这种户回退到最新一版历史记录取展示信息,所以前端能拿到「被谁打回、什么原因、原先填的是哪几晚」。而 `countedInSummary` 仍只认 active 行,与汇总严格同源。 +- **打回户与从未提交户可区分**:前者 `status=REJECTED_*` 且 `days` 非空,后者 `status=null` 且 `days` 为 `[]`。 +- **哪些户进列表**:`needsHotel=true` 的户 ∪ 已提交有效需求的户(#8023 同口径)。标记为需订房但一份需求都没提交的户**也会列出**,`status` 为 `null`、`days` 为 `[]`——这正是管理员要催的人。 +- **只取首方案**:一段有多个候选酒店时只取 `candidates[0]`,与汇总同口径(候选是房控择一,累加全部会翻倍)。 +- **分住**:同一晚拆多段住多家时 `hotels[]` 出多条;多段指向同一家酒店会合并成一条。 +- **排序**:`households[]` 按 `orderNo` 升序(`orderNo` 为空的排最后);`days[]` 按 `dayNumber` 升序。 +- **上限**:单次最多返回 500 户,超出截断并打 warn。团期正常几十户,超过说明数据异常。 +- **性能**:房型中文名与酒店名/城市都对整份结果**一次性批量**补齐,不在逐户逐晚的循环里打字典或 Feign。 + +--- + +## 四、契约约束与正确调用方式 + +- 本接口与 `requirement-summary` **并列调用**,不要用其中一个推算另一个:汇总不含逐户信息,本接口不含车辆/特殊需求全景。 +- 前端渲染两块时,若发现数字对不上,先看 `householdCount` 与 `countedHouseholdCount` 的差值——差值就是被打回的户数,属预期行为而非 bug。 +- `orderId` / `consultantId` / `groupBatchId` / `hotelId` 均为字符串序列化,**不要**当数字解析。 +- 打回动作仍走既有端点(`POST /v3/admin/order/{id}/hotel-requirement/reject` 单户、`POST .../group-batch/{id}/requirement/reject` 批量),本次未改。 + +--- + +## 六、边界行为 + +| 场景 | 行为 | +|---|---| +| 户被打回 | 仍在列表里,`countedInSummary=false`,带出 `status=REJECTED_*` / `returnRemark` / `returnedAt`,以及原先填的逐晚明细 | +| 户被打回后重新提交 | 回到 `countedInSummary=true`,打回痕迹清空(TEST 实测) | +| 户标记需订房但未提交需求 | 仍在列表里,`status` 为 null、`days` 为 `[]`、`countedInSummary=false` | +| 户 needsHotel=false 但已提交有效需求 | 在列表里(#8023 口径),`countedInSummary=true` | +| 户既没标记也没有效需求 | 不进列表 | +| 客户自订晚 | 该晚仍列出,`customerSelfBooked=true`、`hotels` 为 `[]` | +| 同一晚分住多家 | `hotels[]` 出多条,间数不丢 | +| 同一晚多段同一家 | 合并成一条 | +| 段未填酒店 | `hotelId` 为 `null` 的一条,间数不丢 | +| 团期无出发日 | 所有 `stayDate` 为 `null`,不推算 | +| 资源服务不可用 | `city` / `district` 为 `null`,`hotelName` 回落快照名 | +| 字典不可用 | `roomCategoryName` 为 `null`,编码与间数照常 | +| 某户 days JSON 损坏 | 该户 `days` 为 `[]`,其它户不受影响 | +| 团期下无在团子订单 | `households` 为 `[]`,不发起需求与资源服务调用 | + +--- + +## 六.7、影响评估 + +- **是否破坏向后兼容**: 纯新增端点,无任何既有接口改动。 +- **前端是否必须同步上线**: 否。不接入则「用房」板块保持现状(只有汇总表)。 +- **回滚**: 回滚本 PR 即可,只读接口、无数据变更、无表结构变更。 + +--- + +## 七、不影响范围 + +- `GET .../requirement-summary`(汇总)**一字未改**,既有字段与数值逐字不变。 +- `room-plans` / `allocations`(房务订房计划与分房结果)未动。 +- 住宿需求提交契约未动(**没有**往 days JSON 加 city 字段,城市一律由 hotelId 反查)。 +- 未改 hl-resource-service。 +- 打回 / 审核 / 确认相关端点未动。 +- 无数据库表结构变更,无 Flyway 迁移。 + +--- + +## 八、测试环境已验证 + +TEST 环境(`hl-order-service-v3`,dev-v3,2026-09-20),团期 `jw测试1期`(`2101506167098511362`,出发 2026-09-27,6 晚,3 个子订单 / 2 户需订房)。 + +``` +AC-1 单户多晚多酒店:张三 6 晚跨 3 家酒店,逐晚 hotels[] 与 rooms[] 正确 ✓ +AC-2 多户 + orderNo 升序 + 联系人/人数/定制师(金卫) 与订单表一致 ✓ +AC-3 交叉对账(程序化,非目测): + 逐日总数 Day1-6 汇总 3/3/3/3/3/3 == Σ子订单 3/3/3/3/3/3 ✓ + 逐日×酒店×大类 三级全等 ✓ +AC-4 打回王五后四件事同时成立: + ① 仍在列表里;② status=REJECTED_TO_CONSULTANT / statusName=驳回; + ③ returnRemark 与 returnedAt 带出,原填 6 晚明细仍可见; + ④ 汇总 Day1-6 由 3 降为 2,且降后 AC-3 等式仍全等 ✓ + 打回后重新提交 → countedInSummary 回到 true,打回痕迹清空 ✓ +AC-5 客户自订晚:第5晚仍列出、customerSelfBooked=true、hotels=[], + 汇总该日由 3 降为 2 ✓ +AC-6 未填酒店的段:hotelId=null 一条,间数不丢,不变量仍成立 ✓ +AC-7 酒店名:快照优先;快照缺名的按 ID 批量补出正确名称 ✓ +AC-8 stayDate = 出发日 + dayNumber − 1,跨月 09-30 → 10-01 正确 ✓ +AC-9 房型:roomTypeName(大床房/主题标间)与 roomCategoryName(豪华大床/ + 标间)均正确译出,单测显式打桩避免空洞断言 ✓ +AC-10 判权:低权限角色 1002/user → 589507 被拦;超管 200 ✓ +AC-11 批量加载:整份结果字典与资源服务各只调一次,去重后仅传 3 个 hotelId ✓ +``` + +地域字段实测:`city` 全部是「呼伦贝尔市」,`district` 分别是「满洲里市 / 额尔古纳市 / 海拉尔区」——**页面地点那一列必须用 `district`**。 + +单测:`GroupBatchHotelHouseholdServiceTest` 19/19、`HotelRequirementDaysNormalizerTest` 76/76(含「明细聚合回去必等于汇总视角」不变量)、相关回归 194/194。order-v3 全量 A 组 8334 用例 / B 组 3995 用例,3 个失败均非本次引入并逐个做过基线对照(`FinanceFeignContextMockInventoryTest` 基线同样红、`GroupBatchAuditVersionCasMySqlIT` 并发 flaky 单跑 10/10 绿、`MapperBoundaryArchTest` 已知基线红 #7989)。 + +--- + +## 十、相关文档 + +- 工单 [#8046](https://git.1814.love:8443/wx/HL/issues/8046) +- [#8030](https://git.1814.love:8443/wx/HL/issues/8030) 用房汇总(本接口的姊妹接口,同一板块的上半部分) +- [#8023](https://git.1814.love:8443/wx/HL/issues/8023) 需订房户判据(本接口沿用同一套 `countsTowardHotel` 口径) +- [#7925](https://git.1814.love:8443/wx/HL/issues/7925) 汇总计入状态集合(本次收口为 `RequirementStatus.isSummaryCounted` 单源) +- [#7316](https://git.1814.love:8443/wx/HL/issues/7316) `requirement-summary` 判权接 `group-batch:view`(本接口沿用) +- [#7324](https://git.1814.love:8443/wx/HL/issues/7324) 「团期看板要看全部版本而不是 active 行」——打回后无 active 行这一条的出处 + +--- + +## 关联 / 联系人 + +### 链接 + +- **Issue**: [#8046](https://git.1814.love:8443/wx/HL/issues/8046) +- **PR**: [#8055](https://git.1814.love:8443/wx/HL/pulls/8055)、[#8057](https://git.1814.love:8443/wx/HL/pulls/8057)、[#8059](https://git.1814.love:8443/wx/HL/pulls/8059)、[#8060](https://git.1814.love:8443/wx/HL/pulls/8060) + +### 联系人 + +- **后端负责人**: @jw +- **前端负责人**: @mmg