docs(7327): 订正 changelog —— PR-2 把「权威消失即软删」推翻为「转 REVOKED 不删」
changelog-filename-gate / validate (push) Failing after 2s

本篇写于 PR-1(#7600, 49ce99cc8)当天,同日 09:19 合入的 PR-2(#7603, d916986de)
把其中的行为改成了相反的。mmg 手上拿到的是错的,故就地订正而非另起新篇
(另起会把同一批接口的信息分裂到两个文件)。

订正 7 处(代理只报了 4 处,第 5-7 处是收尾时按「概念」做全文残留断言抓出来的):

1. 关键变化段:GROUP_BATCH_PLAN_REVOKED「本期产生不出来」-> 本期就会出现
2. 对平规则:「权威消失即软删,返回结果里不再出现」-> 不删,就地转 REVOKED
   + remark 加前缀 [团期来源已失效] ,实付/凭证/确认状态/source_id 锚点全保留,
   权威回归时按 source_id 三段认回、不新建重复行
3. 行为对照表「团期权威消失」行
4. 用例名 listHotel_groupAuthorityGone_softDeletes... -> ...revokes...
   (真名见 SettlementServiceGroupBatchReconcileTest.java:219)
5. sourceType 取值域表里仍写着「本期产生不出来」
6. 读写混合说明里的对平三动作仍写着「权威消失的软删」
7. 「会新建、更新或软删住宿行」加限定(团期行走转 REVOKED,此处软删指其它来源)

另:正文顶部新增「2026-09-13 订正」段集中对账,PR 行补 #7603。

frontend_status: not_required -> pending。原 not_required 闭环是在
「REVOKED 本期产生不出来」这个前提下做的,前提已失效。
它引出一个需要拍板的新问题:一条权威已消失的 REVOKED 行,核单员到底能不能删?
按现有前端逻辑它是「不可删的派生行」,但上游已不存在 —— 意味着它会永久留在核单页上。
后端这么设计是故意的(保住已录实付与凭证、以及认回锚点),但前端侧怎么展现没定过。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
这个提交包含在:
API Changelog Bot
2026-09-13 14:04:04 +08:00
共同撰写人 Claude Opus 5
父节点 551c56609f
当前提交 779f70f896
@@ -7,12 +7,12 @@ author: "wx(GIT)"
change_type: "修改接口"
backend_status: "deployed"
gateway_status: "verified"
frontend_status: "not_required"
frontend_status: "pending"
frontend_owner: "mmg"
frontend_ref: ""
target_release: ""
verified_at: ""
status_note: "Issue #7327 PR-1 已合并 dev-v3(PR #7600,终态提交 49ce99cc8),服务 hl-order-service-v3。住宿核单 Step1 的团期订单首次出现团期配房派生行;sourceType/sourceTypeName 是既有字段,本次只扩取值域,新增业务错误码 584129。接口路径、HTTP 方法、VO 字段集合均未变化,网关无新增路由。 前端 2026-09-13 闭环 not_required:逐块 grep 实证。①核单 Step1 住宿无独立来源列,来源合并「备注/来源」note 列 returnDetailAdapter.js firstValue(remark,note,sourceTypeName) 纯透传后端中文名,前端无 sourceType 映射表,新值自带中文「团期配房」天然兼容;行为分支只按 MANUAL 判手工行,新取值落入派生行语义不可删,保存 normalizeSource 原样回传不丢值。②584129 不带 silentError 走 request.js 通用业务码兜底 message.error 透后端原文,__handled 防双弹,无专属分支。③无「团期无住宿」workaround 可撤。零业务代码改动。"
status_note: "⚠️ 2026-09-13 订正:PR-2(PR #7603,终态提交 d916986de,同日 09:19 已合 dev-v3)把本篇四处结论推翻了——「权威消失即软删」改为「不删、就地转 GROUP_BATCH_PLAN_REVOKED、原样返回、权威回归时三段认回」,且 REVOKED 取值本期就会出现。详见正文顶部「🔴 2026-09-13 订正」段。前端原 2026-09-13 not_required 闭环是在「REVOKED 本期产生不出来」这个前提下做的,前提已失效,故退回 pending 等 mmg 重新判一次(要重判的具体问题见订正段末尾)。 【以下为 PR-1 原文】Issue #7327 PR-1 已合并 dev-v3(PR #7600,终态提交 49ce99cc8),服务 hl-order-service-v3。住宿核单 Step1 的团期订单首次出现团期配房派生行;sourceType/sourceTypeName 是既有字段,本次只扩取值域,新增业务错误码 584129。接口路径、HTTP 方法、VO 字段集合均未变化,网关无新增路由。 前端 2026-09-13 闭环 not_required:逐块 grep 实证。①核单 Step1 住宿无独立来源列,来源合并「备注/来源」note 列 returnDetailAdapter.js firstValue(remark,note,sourceTypeName) 纯透传后端中文名,前端无 sourceType 映射表,新值自带中文「团期配房」天然兼容;行为分支只按 MANUAL 判手工行,新取值落入派生行语义不可删,保存 normalizeSource 原样回传不丢值。②584129 不带 silentError 走 request.js 通用业务码兜底 message.error 透后端原文,__handled 防双弹,无专属分支。③无「团期无住宿」workaround 可撤。零业务代码改动。"
updated_at: "2026-09-13"
base: "dev-v3"
---
@@ -24,13 +24,47 @@ base: "dev-v3"
> - 二期(v3,`order-v3` 标签的工单)→ `changelogs-v2/{YYYY-MM}/`
>
> **服务**: hl-order-service-v3 (端口 8086)
> **PR**: #7600
> **PR**: #7600(PR-1)、#7603(PR-2,2026-09-13 订正来源)
> **Issue**: #7327
> **日期**: 2026-09-12
> **影响范围**: 管理后台核单 Step1 住宿明细(团期订单);订单详情 / 行程单 / 小程序行程的住宿段行数
---
## 🔴 2026-09-13 订正(PR-2 把本篇四处结论推翻了,请以本段为准)
本篇写于 **PR-1**(#7600,`49ce99cc8`)当天。**同日 09:19 合入的 PR-2**(#7603,`d916986de`)
把其中四处行为改成了相反的。下面四行已在正文就地改正,这里集中列出供对账:
| 本篇原来说 | 实际行为(PR-2 后) |
|---|---|
| `GROUP_BATCH_PLAN_REVOKED` **本期产生不出来**,下一期才会出现 | **本期就会出现。** 团期订房计划行一被删/改,对应核单行当场转成该取值 |
| **权威消失即软删**,返回结果里不再出现 | **不删。** 就地改 `sourceType=GROUP_BATCH_PLAN_REVOKED`、`remark` 打上前缀 `[团期来源已失效] `,**该行照样随 `GET step1` 返回** |
| (无) | **新增三段认回**:权威回归时按 `source_id` 精确认回原行,`sourceType` 改回 `GROUP_BATCH_PLAN`、剔掉一层前缀,**实付与凭证不丢、不新建重复行** |
| 用例 `listHotel_groupAuthorityGone_**softDeletes**DerivedRowAndKeepsRevokedAndManual` | 真实用例名是 `listHotel_groupAuthorityGone_**revokes**DerivedRowAndKeepsRevokedAndManual`(`SettlementServiceGroupBatchReconcileTest.java:219`) |
### 前端实际要处理什么
1. **`sourceType` 会真的出现 `GROUP_BATCH_PLAN_REVOKED`**,`sourceTypeName` = 团期配房(已失效)。后端直接给中文名,不需前端做映射表。
2. **该行的 `remark` 会被后端加上前缀 `[团期来源已失效] `**(末尾含一个空格,常量原文见 `SettlementService.java:178`)。
前缀**只加一层、只剔一层、只剔开头**(核单员可能在前缀后面写了自己的备注,整段清空会丢掉他的字)。
**前端不要拿这个前缀做任何判断**,它只供人读;要判失效一律看 `sourceType`。
3. **行数不会因失效而减少**。之前按本篇做了「失效后行会消失」预期的地方(空态、合计、分页总数)要重新看一眼。
### ⏸ 这次订正引出一个需要拍板的新问题
本篇原来的 `frontend_status: not_required` 闭环结论,是在「**REVOKED 本期产生不出来**」这个前提下做的,
而那个前提现在没了。其中一条原话是「行为分支只按 MANUAL 判手工行,新取值落入**派生行语义不可删**」——
> **一条权威已经消失的 REVOKED 行,核单员到底能不能删?**
> 按现有前端逻辑它是「不可删的派生行」,但它的上游已经不存在了——这意味着它会**永久留在核单页上**。
> 后端这么设计是故意的(要保住已录的实付与凭证、以及权威回归时的认回锚点),但**前端侧怎么展现、要不要给删除入口,本篇没定过**。
故 `frontend_status` 从 `not_required` 退回 **`pending`**,请 mmg 在新前提下重新判一次。
(这不是说原来那份分析做错了——它在它的前提下是对的;**失效的是前提,不是推理**。)
---
## ⚠️ 关键变化(非必须,本版与上版行为不同 / 纠错 / 撤销时必写)
一行红字说清:
@@ -38,7 +72,7 @@ base: "dev-v3"
- **`sourceType` / `sourceTypeName` 不是新增字段,是既有字段**。这两个字段在本次改动之前就存在于 `HotelItemVO` 上,前端按「新增字段」去找会找不到。**本次变的是取值域**:`sourceType` 多出 `GROUP_BATCH_PLAN`(`sourceTypeName` = 团期配房)与 `GROUP_BATCH_PLAN_REVOKED`(`sourceTypeName` = 团期配房(已失效))两个取值。
- 前端/调用方以前以为的是:核单 Step1 住宿明细只有两类行——配房派生行(`HOUSE_ASSIGNMENT`)与手工行(`MANUAL`);团期订单的住宿明细是空的。
- 实际现在是:**团期订单的住宿明细第一次出现团期配房派生行**,`sourceType=GROUP_BATCH_PLAN`。这类行按「住宿事实」聚合成一行(同订单 + 同入住日 + 同酒店 + 同房型的多条分房记录合并为一行,间数求和、计划成本按合计间数重算)。
- `GROUP_BATCH_PLAN_REVOKED` 本期产生不出来(后端本期既不产出也不认领该取值),下一期才会出现;前端做取值域映射时一并纳入即可,不必为它设计交互。
- ✅ **(2026-09-13 订正)`GROUP_BATCH_PLAN_REVOKED` 本期就会出现**(PR-2 `d916986de` 起)。团期订房计划行被删或改成别的酒店/房型时,对应核单行**不删**、就地转成该取值并照样返回,`sourceTypeName` = 团期配房(已失效)。**前端本期就要能展示它。**
- 新增业务错误码 **584129**:把一条「团期配房未分平」的住宿行置为已确认时被拒绝。
---
@@ -74,7 +108,7 @@ base: "dev-v3"
管理后台「核单结算 - Step1 住宿」页面进入或刷新时调用,拿到该订单当前应展示的全部住宿明细行(派生行 + 手工行)。返回的每一行都带 `id`,前端后续 `PUT` 回写时必须原样带回该 `id`,否则会被当成新增行。
本接口是**读写混合**的:服务端在返回前会把库里的核单草稿与房务权威对平(缺的补、变的改、权威消失的软删),所以刷新页面本身会改变库里的行集合与确认状态。前端不需要额外调「同步」动作。
本接口是**读写混合**的:服务端在返回前会把库里的核单草稿与房务权威对平(缺的补、变的改、**团期权威消失的转 `GROUP_BATCH_PLAN_REVOKED` 而非软删** ——2026-09-13 订正,详见正文顶部订正段),所以刷新页面本身会改变库里的行集合与确认状态。前端不需要额外调「同步」动作。
团期订单从本次起会在结果里出现 `sourceType=GROUP_BATCH_PLAN` 的行。出现条件:该户存在有效的团期分房记录、其所属的团期订房计划已确认、且该户不在团期历史旧户冻结名单内;三者任一不满足则该户仍只有原来的行。
@@ -180,7 +214,7 @@ Authorization: Bearer <token>
- **团期行聚合**:分组键是「订单 + 入住日 + 酒店 + 房型」,一组只返回一行。房务把一条分房记录拆成两条、或把两条合成一条,只要酒店/房型/日期/总间数不变,返回的行 `id` 不变,实际成本、凭证、备注、确认状态四项也不变,只有 `hotelAssignmentId` 与 `sourceId` 这两个锚点会变。
- **事实变更即打回未确认**:团期行的酒店、房型、入住日、酒店名、房型名、间数、单价、计划成本、付款方式任一与权威不一致时,该行 `settlementConfirmStatus` 被重置为 `UNCONFIRMED`,实际成本与凭证**保留不清空**。
- **间数变化加备注前缀**:间数变化时 `remark` 前面被系统加上 `[住宿事实变更 间数 {旧}→{新},请复核实付] `(末尾含一个空格)。连续变化只保留最新一层前缀,不叠加。该前缀仅供人读,前端不要用它做任何判断。
- **权威消失即软删**:团期订房计划行被删除或改成了别的酒店/房型时,对应的核单行在本次刷新中被软删,返回结果里不再出现;手工行与 `GROUP_BATCH_PLAN_REVOKED` 行不受影响、永远原样带回。
- ✅ **(2026-09-13 订正)权威消失不软删,转 `GROUP_BATCH_PLAN_REVOKED`**:团期订房计划行被删除或改成了别的酒店/房型时,对应的核单行**仍然返回**,只是 `sourceType` 变成 `GROUP_BATCH_PLAN_REVOKED`、`remark` 被打上前缀 `[团期来源已失效] `(只加一层);**实付、凭证、确认状态与 `source_id` 锚点全部保留**。权威回归时按 `source_id` 三段认回原行(改回 `GROUP_BATCH_PLAN`、剔一层前缀),**不新建重复行**。手工行始终不受影响。
- **失败零写入**:对平过程在一个事务内,中途异常整体回滚,同时把住宿类目标记为来源同步失败。
- **兼容**:`sourceType` 的历史取值 `CUSTOM_ASSIGNMENT` / `TEMPLATE` 会被归一化为 `MANUAL` / `SYSTEM` 后再返回,前端不会读到这两个旧值。
@@ -364,7 +398,7 @@ sourceType 传了白名单以外的值时(HTTP 仍为 200):
**派生行字段以库为准说明**: 派生行的来源、来源 ID 与配房锚点三项一律取库内既有值,入参里携带的对应字段被忽略;只有手工行这三项才落 null 与 `MANUAL`。
**读接口也会写库说明**: `GET step1` 在对平阶段会新建、更新或软删住宿行——间数或单价变化会写回计划成本并把确认状态打回未确认,锚点漂移会写回新的锚点 ID。对平只在「锚点变了」或「事实变了」时才发生写入,两者都没变时读接口一行库也不写。
**读接口也会写库说明**: `GET step1` 在对平阶段会新建、更新或软删住宿行(⚠️ 2026-09-13 订正:**团期派生行的权威消失走「转 REVOKED」不走软删**,此处的软删指其它来源的行)——间数或单价变化会写回计划成本并把确认状态打回未确认,锚点漂移会写回新的锚点 ID。对平只在「锚点变了」或「事实变了」时才发生写入,两者都没变时读接口一行库也不写。
---
@@ -393,7 +427,7 @@ sourceType 传了白名单以外的值时(HTTP 仍为 200):
| `MANUAL` | 手工 | 核单员手工新增行,无权威源 |
| `SYSTEM` | 系统 | 系统生成行(历史 TEMPLATE 归一化到此值) |
| `GROUP_BATCH_PLAN` | 团期配房 | **本次新增取值**。团期订房计划派生行,按住宿事实分组聚合,一组一行 |
| `GROUP_BATCH_PLAN_REVOKED` | 团期配房(已失效) | **本次新增取值**。团期来源已失效但成本仍保留的行;**本期产生不出来**,下一期才会出现 |
| `GROUP_BATCH_PLAN_REVOKED` | 团期配房(已失效) | **本次新增取值**。团期来源已失效但成本仍保留的行。✅**(2026-09-13 订正)本期就会出现**:团期订房计划行被删/改时,对应核单行当场转成本取值并**照样返回**(`remark` 前会被加上 `[团期来源已失效] `);权威回归时按 `source_id` 三段认回、改回 `GROUP_BATCH_PLAN` |
> 该枚举的其余取值(景区 / 游玩项目 / 餐饮安排 / 车务 / 人员安排 / 订单增费)用于其他核单步骤,住宿 Step1 不会返回,住宿入参白名单也不接受它们。
@@ -437,7 +471,7 @@ sourceType 传了白名单以外的值时(HTTP 仍为 200):
| 团期订单行确认 | 无限制(因为没有团期行) | 未分平或权威已消失时返回 584129 |
| 团期行锚点漂移(房务拆/合分房) | — | 只换锚点,行 ID、实付、凭证、备注、确认状态五项不变 |
| 团期行事实变更 | — | 确认状态打回 `UNCONFIRMED`,实付与凭证保留 |
| 团期权威消失 | — | 该行在下一次 `GET step1` 中被软删 |
| 团期权威消失 | — | ✅**(2026-09-13 订正)不软删**:就地转 `GROUP_BATCH_PLAN_REVOKED` + remark 加前缀,行照样返回;权威回归时三段认回,实付/凭证不丢 |
| 逐户配房派生行与手工行 | 现有行为 | 完全不变 |
## 六.7、影响评估(修改/删除类必写)
@@ -475,8 +509,8 @@ GET step1 事实与锚点均未变 → 读路径一行库也不写 ✓
GET step1 间数 2 变 1 → 计划成本 400.00、实付 650.00 与凭证保留、状态回 UNCONFIRMED、
remark = "[住宿事实变更 间数 2→1,请复核实付] 财务备注" ✓
listHotel_roomCountChanged_keepsActualCostResetsStatusAndPrefixesRemark
GET step1 权威消失 → 派生行软删,已失效行与手工行保留 ✓
listHotel_groupAuthorityGone_softDeletesDerivedRowAndKeepsRevokedAndManual
GET step1 权威消失 → 派生行转 REVOKED(不删),已失效行与手工行保留 ✓ ← 2026-09-13 订正
listHotel_groupAuthorityGone_revokesDerivedRowAndKeepsRevokedAndManual
PUT step1 未分平置确认 → 584129 ✓ saveHotel_groupRowUnbalanced_confirmRejectedWith584129
PUT step1 已分平置确认 → 放行 ✓ saveHotel_groupRowBalanced_confirmAllowed
PUT step1 权威已消失置确认 → 584129 ✓ saveHotel_groupRowSourceIdMissingFromContract_rejectedWith584129