diff --git a/changelogs-v2/2026-09/21_7105_团期合同保险出具门已打通撤销恒失败说明-修复-管理后台.md b/changelogs-v2/2026-09/21_7105_团期合同保险出具门已打通撤销恒失败说明-修复-管理后台.md new file mode 100644 index 00000000..704a4a30 --- /dev/null +++ b/changelogs-v2/2026-09/21_7105_团期合同保险出具门已打通撤销恒失败说明-修复-管理后台.md @@ -0,0 +1,166 @@ +--- +schema: "hl-changelog/v2" +ticket: "7105" +title: "团期合同保险出具门已打通,撤销上一版「按钮恒失败」的说明" +consumer: "admin" +author: "jw(GIT)" +change_type: "修复" +backend_status: "deployed" +gateway_status: "verified" +frontend_status: "pending" +frontend_owner: "" +frontend_ref: "" +target_release: "" +verified_at: "" +status_note: "更正 2026-09-07 那条 #7105 的首段警告。彼时说「酒店 ready 线上无写入方(#4132),故 issuable 恒 false、手动开/作废重开恒返 589548」——两个前提现已都不成立:#7248/PR#7249 把出具门从「判团期状态」改成「资源准备中+四项 ready 全 true 即放行」;house 域已有三处回填 hotel_ready。2026-09-21 TEST 实测:RESOURCE_PREPARING 团期 issuable=true,issue 端点返 200 逐户结果而非整单 589548,四项配齐团期里 40 户已确认行程的子订单合同全 SIGNED、保险全 INSURED。前端需调整:不要再把出具按钮按恒失败处理,失败语义从整单 BusinessException 改为 200+逐户 outcome=FAILED+message。接口契约零变更,无需改调用代码。" +updated_at: "2026-09-21" +base: "dev-v3" +--- + +# 团期「合同保险」:出具门已打通,撤销上一版的「按钮恒失败」说明 + +> **服务**: hl-order-service-v3 (端口 8086/8186) +> **Issue**: #7105(本条更正)、#7248 / PR #7249(实际修复) +> **日期**: 2026-09-21 +> **影响范围**: 管理后台「团期详情 → 合同保险」Tab 的按钮可用性判断与失败处理分支。 + +--- + +## ⚠️ 关键变化 + +上一版 `2026-09/07_7105_团期合同保险面板与逐户出具-新增接口-管理后台.md` 开头那段 +「**当前不可用的部分(重要)**」说: + +> 酒店 ready 线上**没有**写入方(HL#4132)→ `issuable` **恒为 false**、 +> 手动开 / 作废重开 **恒返 589548**、团期单合同与保险**不会自动出具**。 + +**这段话现已失效,本条予以撤销。** 实际现在是: + +- `issuable` **会返 true**,团期停在「资源准备中」也能返 true +- 手动开 / 作废重开 **不再整单返 589548** +- 团期单的合同与保险 **会自动出具** + +**接口契约(路径、入参、出参字段、返回值结构)零变更**,前端不必改调用代码, +但**要改按钮可用性与失败处理这两处判断**,详见第三节。 + +--- + +## 一、上一版为什么会写错 + +两条前提当时都成立,之后各自被改掉了: + +| 前提 | 当时 | 现在 | +|---|---|---| +| 出具门怎么判 | 判「团期状态已进入 MATERIAL_PREPARING 及之后」 | #7248 / PR #7249(`9f47f620f`,2026-09-07)改判四个 ready 标志:**资源准备中 + 四项 ready 全 true 即放行** | +| `hotel_ready` 有没有写入方 | 没有,挂在一个从未发出的事件上(#4132) | 有,house 域三处在回填 | + +当时那个判法和 #7023 的进阶门首尾相接,构成完全死锁: + +``` +要出合同 → 需 MATERIAL_PREPARING → 需合同全部已签 → 需先出过合同 +``` + +`hotel_ready` 现有的三处写入方: + +| 写入点 | 文件 | +|---|---| +| 团期逐日房态确认 | `house/groupbatch/manager/GroupBatchRoomDayConfirmManager.java:457` | +| 同上(另一条分支) | `house/groupbatch/manager/GroupBatchRoomDayConfirmManager.java:767` | +| 团期整团配房 | `house/service/HouseGroupBatchAssignmentService.java:201` | + +> ℹ️ #4132 工单本身在 Gitea 上仍是 open / 待处理,**光看工单状态会以为还堵着**。 +> 它描述的那条 baseline 事件链路确实还没做,但 `hotel_ready` 的回填已由上面三处覆盖, +> 出具门不再依赖 #4132。 + +--- + +## 二、现在的实际行为 + +### 出具门判定(`GroupBatchContractResolver.issuable`) + +| 团期状态 | 是否放行 | +|---|---| +| 招募中 RECRUITING | ❌ 不放行(未成团,四项必不全) | +| **资源准备中 RESOURCE_PREPARING** | ✅ **四项 ready 全 true 就放行**(原死锁点,本次变化就在这一行) | +| 物资准备中 MATERIAL_PREPARING 及之后(待出行 / 出行中 / 核验中 / 已结算) | ✅ 放行(必然已配齐过,不依赖存量标志是否回填) | +| 已流团 CANCELLED | ❌ 不放行 | + +### 失败语义(前端最需要注意的一点) + +`589548`(四项未配齐)现在只在**整单**层面出现,且只在团期真的没配齐时出现。 +门过了之后,**逐户的失败不再是 589548,而是 HTTP 200 + 逐户 `outcome=FAILED` + `message`**: + +```json +{ + "code": 200, "message": "成功", "success": true, + "data": { + "totalCount": 1, "successCount": 0, "failCount": 1, "skipCount": 0, + "results": [ + { "orderId": "2099947354713993217", "target": "CONTRACT", + "outcome": "FAILED", "message": "请先确认行程后再创建合同" } + ] + } +} +``` + +最常见的一条逐户失败是 **`请先确认行程后再创建合同`**(合同域 `510220`): +合同只能在子订单处于 `PENDING_DEPARTURE` 或 `TRAVELLING` 时创建 +(`ContractCreateService.CONTRACT_CREATABLE_ORDER_STATUSES`)。 +也就是说,**团期四项配齐只是开了团期这道门,子订单自己还没确认行程的户依然出不了合同**, +这是两道独立的前置,页面上要能把这条 `message` 原样显示给操作人,不要吞掉。 + +--- + +## 三、前端要改的两处 + +| # | 改前(按上一版说明写的) | 改后 | +|---|---|---| +| 1 | 出具类按钮按「反正恒失败」处理(常驻置灰 / 挂提示 / 干脆不接) | **按 `issuable` 字段置灰**。它现在会真的返 true,按钮要能点 | +| 2 | 失败一律当 589548 整单报错 | 先看 HTTP 层 `code`:`589548` 仍是整单拒绝(四项未配齐);`code=200` 时要**逐户读 `results[].outcome`**,`FAILED` 的户把 `message` 原样展示 | + +其余不用动:三态徽标继续用后端 `contractStateText` / `insuranceStateText`, +不要自己映射;权限码仍是读 `group-batch:view`、写 `group-batch:contract:issue`。 + +--- + +## 四、TEST 实测记录(2026-09-21) + +均经真实网关 `api.test.1814.love`,非单测。 + +| # | 验证项 | 结果 | +|---|---|---| +| 1 | `GET .../group-batch/2100129355043627009/contracts` | `issuable=true`,`batchStatus=RESOURCE_PREPARING`。**旧实现在此状态下必为 false**,这条直接证明门已改 | +| 2 | `GET .../group-batch/2099947334803632130/contracts` | 同上,`issuable=true`,3 户明细正常返回 | +| 3 | `POST .../contracts/issue`(`target=CONTRACT`) | 返 `code=200` + 逐户结果,**不再是整单 589548**;该户因自身未确认行程返 `outcome=FAILED` / `请先确认行程后再创建合同` | +| 4 | TEST 库 `order_group_batch` 四项 ready 全 1 的团期 | 共 28 个(物资准备中 17、资源准备中 5、核验中 2、待出行 2、出行中 1、行程结束 1);`hotel_ready=1` 的记录共 52 条 | +| 5 | 上述团期下**已确认行程**的子订单合同 / 保险状态 | 40 户(已完成 23 + 出行中 10 + 待出行 7)**合同全部 SIGNED、保险全部 INSURED**,无一户卡在「已确认行程但合同未出」,最新一条更新时间 2026-09-21 15:31 | + +第 5 条是自动出具链路当前工作正常的证据:如果门还锁着,这些户会全部停在「未出」。 + +**未实测**:单次「手动开 → 合同真的开出来」的正向成功路径。TEST 上四项配齐的团期里, +已确认行程的户合同都已由自动链路出过(无可补开的户),未确认行程的户被 `510220` 挡住, +现成数据里没有可打的靶子;造一个需要先补该订单的酒店供应商字段。 +门已通的结论由第 1、3、5 条支撑,不依赖这一条。 + +**取证范围仅 TEST**。正式环境本机无查询通道,上一版原文里的「线上」二字本条不予断言。 + +--- + +## 五、不影响范围 + +- **接口契约零变更**:四个端点的路径、方法、入参、出参字段、错误码全部未动 +- **散客单不受影响**:`productBatchId` 为空的订单在出具门上恒放行,从头到尾没被这个问题波及 +- **零影响**:小程序端、订单侧合同 / 保险接口(`create-by-scheme` / `purchase-by-scheme` 等)、网关配置、权限码 + +--- + +## 六、相关文档 + +- 被本条更正的条目:`changelogs-v2/2026-09/07_7105_团期合同保险面板与逐户出具-新增接口-管理后台.md` +- 修复提交:`9f47f620f`(`fix(group): 合同出具门改判四项 ready,解开与 #7023 的死锁 Closes #7248`) +- 接口文档:`docs/group/团期模块接口文档-v2.0.html` GB-ADM-030 / GB-ADM-031 章节 + +## 关联 / 联系人 + +- 后端:jw +- 相关工单:#7105(原交付)、#7248 / PR #7249(门锁修复)、#7023(进阶门)、#4132(仍 open,但已不阻塞本功能)