文件
hl-api-changelog/changelogs-v2/2026-09/24_8339_团期确认联动子订单确认行程与团期单禁单户确认581065-修改接口-管理后台.md
T
2026-09-24 18:02:08 +08:00

32 KiB
原始文件 Blame 文件历史

schema, ticket, title, consumer, author, change_type, backend_status, gateway_status, frontend_status, frontend_owner, frontend_ref, target_release, verified_at, status_note, updated_at, base
schema ticket title consumer author change_type backend_status gateway_status frontend_status frontend_owner frontend_ref target_release verified_at status_note updated_at base
hl-changelog/v2 8339 团期人工确认联动子订单确认行程:确认门加逐户预检(589556 逐户列订单号 + 未满足项);团期单在团期确认前单户确认行程返新码 581065;时间线新增 BATCH_SUB_ORDER_CONFIRM_FAILED;合同保险出具门补出行完毕 admin jw(GIT) 修改接口 deployed verified verified mmg 65ce203dc20e5b475d52ce6797ec1b069f52cfff v2.1 2026-09-24 六节点定案(SRS §0.27.7):团期人工确认时,团期单子订单一并确认行程(定制中 → 待出行),团期单不再允许单户自行确认,合同保险只由逐户确认链路出具。POST /v3/admin/order/group-batch/{groupBatchId}/confirm 的确认门在四项 ready + 物资已确认之外加逐户预检(待支付 / 定制中的活跃户须已付订金、出行人齐全且有成人手机号、户级房车完成、合同模板已设、有主报账人),不满足仍返 589556,message 由「、」连接的团期级清单改为「;」分段:首段团期级未满足项(有才出现),其后每户一段「订单 {订单号}:{未满足项}」;确认成功后事务提交后系统异步逐户确认行程,合同保险由逐户链路出具(#8268 的确认后全团补发下线),单户失败不回滚团期确认,写团期时间线新事件 BATCH_SUB_ORDER_CONFIRM_FAILED(extra 带 orderId / orderNo / reason)。POST /v3/admin/order/{id}/confirm-itinerary 与 POST /v3/admin/order/{id}/transition(eventCode=CONFIRM)对团期单在团期确认前返新码 581065「团期单随团期确认,不可单独确认」,团期确认后仍在定制中的户放行作补确认,散客单不受影响。合同保险出具门可出具状态集补 TRIP_FINISHED(出行完毕):GET .../contracts 的 issuable 在出行完毕为 true,contracts/issue、contracts/reissue 在出行完毕不再返 589548。前端需:589556 按「;」分段逐户展示;团期单订单详情在团期确认前隐藏或置灰「确认行程」并处理 581065;时间线显示新事件(eventTypeName 后端已给)。 前端已交付并验证(hl-admin@65ce203d):订单详情底栏「确认订单」团期单+团期未确认置灰+NTooltip 说明(isGroupConfirmBlocked 共享判据,六态集与合同保险出具门同源,null fail-open/非空未知 fail-closed),openLockConfirmModal 同源防御闸拦旁路入口;团期详情 confirm 文案改逐户确认行程链路,589556 改 silentError+dialog 按「;」分段逐行展示(不按「、」切碎/不解析订单号),其余码直弹 message;StatusLogsPanel 新事件 eventTypeName 直显零改动;contract.js 出具门补 TRIP_FINISHED JSDoc。4 个定向 spec 58 例全绿,新增 #8339 用例 25 例。 2026-09-24 dev-v3

团期确认: 确认门加逐户预检、子订单随团期确认行程、团期单禁单户确认(管理后台)

服务: hl-order-service-v3(端口 8086/8186) PR: #8346(主体)、#8349(TEST 验收缺陷修复:主报账人副本补齐、逐户确认失败留痕) Issue: #8339 日期: 2026-09-24 影响范围: 管理后台团期详情页「确认」按钮的 589556 提示、团期时间线、「合同保险」页签的可出具判断;订单详情页「确认行程」按钮(团期单)


⚠️ 关键变化

  1. 团期确认会连带确认子订单行程。确认成功后,系统在后台逐户把「定制中」的户推到「待出行」,每户的合同与保险随之自动出具;前端不需要再逐户点「确认行程」。
  2. 589556 的 message 格式变了:由「、」连接的一串,变成「;」分隔的若干段,每个不满足的户一段「订单 {订单号}:{未满足项}」。
  3. 团期单在团期确认前不能单独「确认行程」:订单详情 confirm-itinerary 与通用 transition(CONFIRM)返新码 581065。团期确认之后仍在定制中的户(逐户确认失败 / 确认后加入的户)可以单户补确认。
  4. 团期时间线新增事件 BATCH_SUB_ORDER_CONFIRM_FAILED(子订单确认行程失败),逐户确认失败时写入,带订单号与原因。
  5. 出行完毕(TRIP_FINISHED)也可出具合同保险:面板 issuable=true,手动开 / 重开不再返 589548。

一、背景

#8268 把「配置 → 确认」改成人工确认,但子订单仍需运营逐户点「确认行程」,而合同保险由团期确认后的「全团补发」与逐户确认链路两条路出具,存在并发重复出具风险。SRS §0.27.7 定案:

项 改前 改后
子订单确认行程 运营逐户点 团期确认提交后系统逐户确认(每户独立事务,单户失败隔离)
团期确认门 四项 ready + 物资已确认 另加逐户预检,任一户不满足整团不可确认
合同保险出具 确认后全团补发 + 逐户确认链路 只剩逐户确认链路
团期单单户确认 可以 团期确认前 581065;确认后可补确认

二、变更接口清单

# 接口 方法 路径 变更类型 说明
1 团期确认 POST /v3/admin/order/group-batch/{groupBatchId}/confirm 修改(门条件 + 错误 message + 副作用) 逐户预检;589556 逐户列订单号与未满足项;成功后逐户确认行程
2 确认行程 POST /v3/admin/order/{id}/confirm-itinerary 修改(新增错误码) 团期单在团期确认前 581065
3 状态变更操作(内部通用) POST /v3/admin/order/{id}/transition 修改(新增错误码) eventCode=CONFIRM 与 #2 同一守卫,581065
4 团期状态流水 GET /v3/admin/order/group-batch/{groupBatchId}/status-logs 修改(枚举新增值) 新事件 BATCH_SUB_ORDER_CONFIRM_FAILED
5 合同保险面板(GB-ADM-030) GET /v3/admin/order/group-batch/{groupBatchId}/contracts 修改(出参取值) issuable 在 TRIP_FINISHED 为 true
6 手动开合同 / 保险(GB-ADM-031) POST /v3/admin/order/group-batch/{groupBatchId}/contracts/issue 修改(前置门放宽) TRIP_FINISHED 不再 589548
7 作废重开合同 / 保险(GB-ADM-031) POST /v3/admin/order/group-batch/{groupBatchId}/contracts/reissue 修改(前置门放宽) 同上

网关无改动(均在既有 /v3/admin/order 前缀下);无新增权限码;无 DB schema 变更。


三、接口详情

1. 团期确认 POST /v3/admin/order/group-batch/{groupBatchId}/confirm

VO: Result<Void>(无请求体)

使用场景

团期详情页「配置」节点的「确认」按钮。本次起点一次确认 = 团期进入「确认」+ 全团定制中的户确认行程 + 逐户出合同保险。门不满足时,运营从 589556 的 message 里直接看到是哪几户、差什么。

入参

字段 位置 类型 必填 约束 说明
groupBatchId Path Long ✅ 团期主键 不存在返 589500(不变)

无请求体(不变)。

出参

字段 类型 说明
data Void 成功返回 null(不变);团期进入 MATERIAL_PREPARING,子订单逐户确认在后台异步进行

请求示例

POST /v3/admin/order/group-batch/2097250563497385985/confirm HTTP/1.1
Host: api.test.1814.love:9443
Authorization: Bearer <admin token>

响应示例

{
  "code": 200,
  "message": "成功",
  "data": null,
  "success": true
}

空数据 / 降级响应

接口立即返回 200,不等逐户确认完成。逐户确认在团期确认事务提交后异步执行、每户独立事务:

  • 单户失败(如出具外的副作用异常)不回滚团期确认、不影响其他户,该户留在「定制中」;
  • 失败户写团期时间线 BATCH_SUB_ORDER_CONFIRM_FAILED(见接口 4),可在订单详情单户补确认;
  • 已是待出行 / 出行中的户跳过,不重复确认、不重复出具。
{ "code": 200, "message": "成功", "data": null, "success": true }

错误响应

门不满足(团期级 + 逐户,「;」分段):

{
  "code": 589556,
  "message": "团期尚不满足确认条件:物资未确认;订单 HL2609240001:未付订金、未指定主报账人;订单 HL2609240002:未提交用车需求",
  "success": false,
  "data": null
}

只有逐户不满足时,没有团期级那一段:

{
  "code": 589556,
  "message": "团期尚不满足确认条件:订单 HL2609240003:待支付(须先付订金或取消)",
  "success": false,
  "data": null
}

状态不是「配置」(含重复确认):

{
  "code": 589501,
  "message": "团期状态不允许当前操作",
  "success": false,
  "data": null
}

业务边界

  • 判定顺序不变:589500 → 589501 → 确认门 589556 → CAS 推进;权限码 group-batch:confirm(不变,589507)。
  • 团期级与逐户预检一并求值、一次列全,不会改一项点一次。
  • 逐户预检范围:待支付、定制中的活跃户(已取消不在内);待出行 / 出行中 / 已完成的户跳过。
  • 逐户未满足项(同一户内以「、」连接):
    • 待支付(须先付订金或取消):订单仍在待支付;
    • 未付订金:付款项未过——团期口径付订金即可,DEPOSIT_PAID / FULLY_PAID 都算满足;
    • 出行人:未添加出行人 / 出行人信息未完善 {已完成}/{总数}(部分待补全) / 至少需要一名成人出行人填写手机号用于合同签署;
    • 户级房:未提交用房需求 / 用房需求未完成(当前: {状态});
    • 户级车:未提交用车需求 或用车清单项给出的原因(整团免车 / 团车完成来源视为满足);
    • 产品未配置合同方案;
    • 未指定主报账人(与单户确认 581062 同一判据)。
  • 预检前系统会按团期人员配置补齐各户的团期人员副本(PR #8349),先设主报账人后下单的户不会再被误报「未指定主报账人」。
  • 团期级未满足项取值不变:房未配齐 / 车未配齐 / 导游领队未配齐 / 摄影未配齐 / 物资未确认。
  • 任一户不满足整团不可确认,团期与子订单状态均不变。

2. 确认行程 POST /v3/admin/order/{id}/confirm-itinerary

VO: ConfirmItineraryReqVO → OrderTransitionRespVO

使用场景

订单详情页「确认行程」按钮(定制中 → 待出行)。散客单用法不变;团期单改为随团期确认,只在团期确认后作为补确认入口使用。

入参

字段 位置 类型 必填 约束 说明
id Path Long ✅ 订单主键 不变
reporterAssignmentId Body Long 否 本单人员 assignmentId 新的主报账人;不传沿用当前主报账人(不变);请求体整体可省略

出参

字段 类型 说明
success Boolean 是否成功(不变)
oldStatus / newStatus String 变更前 / 后粗状态,如 CUSTOMIZING → PENDING_DEPARTURE(不变)
oldFlowStatus / newFlowStatus String 变更前 / 后细状态(不变)
triggeredEvents List<String> 副作用事件,如 ASYNC_CONTRACT_GENERATE / ASYNC_INSURANCE_ISSUE(不变)

请求示例

{
  "reporterAssignmentId": "2072930844657283074"
}

响应示例

{
  "code": 200,
  "message": "成功",
  "data": {
    "success": true,
    "oldStatus": "CUSTOMIZING",
    "newStatus": "PENDING_DEPARTURE",
    "oldFlowStatus": "待确认",
    "newFlowStatus": "待出行",
    "triggeredEvents": ["ASYNC_CONTRACT_GENERATE", "ASYNC_INSURANCE_ISSUE"]
  },
  "success": true
}

空数据 / 降级响应

无列表出参。请求体可整体不传(不变):

{}

错误响应

团期单、所属团期尚未确认(招募中 / 配置 / 已流团等):

{
  "code": 581065,
  "message": "团期单随团期确认,不可单独确认",
  "success": false,
  "data": null
}

其余既有码不变,例如清单未通过:

{
  "code": 581036,
  "message": "确认订单前置校验未通过,请先补全所有必填项",
  "success": false,
  "data": null
}

业务边界

  • 581065 只在「定制中 + CONFIRM」这一跳判,且在五项清单(581036)、主报账人(581062)之前;散客单不判。
  • 判「团期单」走统一归团解析(group_batch_id 或按 product_batch_id 反查),与团期详情口径一致。
  • 团期已确认(MATERIAL_PREPARING 及之后,与合同保险出具门同一状态集)时放行:用于逐户确认失败后的重试、确认后转入 / 加入的户。
  • 团期管理员角色(GROUP_BATCH_MANAGER)调本接口仍被既有写守卫 581008「无权查看此订单」拒绝(不变),补确认需由有订单写权限的角色操作。
  • CONFIRM 落库改为带原状态条件的 CAS:团期驱动的逐户确认与人工补确认同时打到同一户时只有一个成功,输家报错回滚,不会重复出具合同保险。

3. 状态变更操作(内部通用) POST /v3/admin/order/{id}/transition

VO: OrderTransitionReqVO → OrderTransitionRespVO

使用场景

通用状态机入口(Swagger 隐藏)。本次只影响 eventCode=CONFIRM:与「确认行程」落到同一道 Service 层守卫,团期单在团期确认前 581065。其它事件不变。

入参

字段 位置 类型 必填 约束 说明
id Path Long ✅ 订单主键 不变
eventCode Body String ✅ PAY_DEPOSIT / PAY_FULL / CANCEL / CONFIRM / DEPART / FINISH / TERMINATE 本次只有 CONFIRM 行为变化
reason Body String 否 - 操作原因(不变)
payload Body Map 否 - CONFIRM 可传 reporterAssignmentId(不变)

出参

字段 类型 说明
success Boolean 不变
oldStatus / newStatus / oldFlowStatus / newFlowStatus String 不变
triggeredEvents List<String> 不变

请求示例

{
  "eventCode": "CONFIRM",
  "reason": "定制师确认所有前置条件已完成"
}

响应示例

{
  "code": 200,
  "message": "成功",
  "data": {
    "success": true,
    "oldStatus": "CUSTOMIZING",
    "newStatus": "PENDING_DEPARTURE",
    "oldFlowStatus": "待确认",
    "newFlowStatus": "待出行",
    "triggeredEvents": ["ASYNC_CONTRACT_GENERATE", "ASYNC_INSURANCE_ISSUE"]
  },
  "success": true
}

空数据 / 降级响应

无列表出参;非 CONFIRM 事件行为不变。

{ "code": 200, "message": "成功", "data": { "success": true }, "success": true }

错误响应

{
  "code": 581065,
  "message": "团期单随团期确认,不可单独确认",
  "success": false,
  "data": null
}

业务边界

  • 与接口 2 完全同一判据与放行条件;散客单不受影响。
  • 非 CONFIRM 事件的落库仍是原写法;CONFIRM 落库改为 CAS(同接口 2)。

4. 团期状态流水 GET /v3/admin/order/group-batch/{groupBatchId}/status-logs

VO: List<GroupBatchStatusLogItemVO>

使用场景

团期详情「操作记录 / 时间线」。本次新增一个事件值:团期确认后逐户确认行程失败时每户一条。

入参

字段 位置 类型 必填 约束 说明
groupBatchId Path Long ✅ 团期主键 不变

出参

字段 类型 说明
[].eventType String 新增取值 BATCH_SUB_ORDER_CONFIRM_FAILED
[].eventTypeName String 新值对应「子订单确认行程失败」
[].changeType String 新事件为 DATA(团期状态不变,fromStatus == toStatus)
[].content String 「订单 {订单号} 随团期确认行程失败:{原因}(该户留在定制中,可在订单详情单户补确认)」,原因最长 300 字截断
[].operatorType String 新事件为 SYSTEM,operatorId 为 null
[].extra Object 新事件带 orderId / orderNo / reason

请求示例

GET /v3/admin/order/group-batch/2097250563497385985/status-logs HTTP/1.1
Host: api.test.1814.love:9443
Authorization: Bearer <admin token>

无请求体。

响应示例

{
  "code": 200,
  "message": "成功",
  "data": [
    {
      "changeType": "DATA",
      "eventType": "BATCH_SUB_ORDER_CONFIRM_FAILED",
      "eventTypeName": "子订单确认行程失败",
      "fromStatus": "MATERIAL_PREPARING",
      "toStatus": "MATERIAL_PREPARING",
      "content": "订单 HL2609240001 随团期确认行程失败:[581062] 请先指定本单主报账人(尾款代收人)(该户留在定制中,可在订单详情单户补确认)",
      "operatorType": "SYSTEM",
      "operatorId": null,
      "extra": {
        "orderId": "2103023889187799042",
        "orderNo": "HL2609240001",
        "reason": "[581062] 请先指定本单主报账人(尾款代收人)"
      }
    }
  ],
  "success": true
}

空数据 / 降级响应

逐户全部成功时不写这类事件;无流水返回空数组(不变):

{ "code": 200, "message": "成功", "data": [], "success": true }

错误响应

{
  "code": 589500,
  "message": "团期不存在",
  "success": false,
  "data": null
}

业务边界

  • eventTypeName 由后端给,前端直接显示即可(不变的约定)。
  • reason 是原始失败信息:业务异常为「[错误码] 文案」,非业务异常为「异常类名: 消息」,可能含技术细节。
  • 同一原因同时写入该户 order_main.last_confirm_error(最长 500 字),单户补确认成功后清空;该列当前没有接口出参。
  • 同一户多次失败会各写一条,不去重。

5. 合同保险面板 GET /v3/admin/order/group-batch/{groupBatchId}/contracts

VO: GroupBatchContractBoardVO

使用场景

「合同保险」页签首屏;issuable 决定出具按钮是否可点。本次只补 TRIP_FINISHED(出行完毕)为可出具。

入参

字段 位置 类型 必填 约束 说明
groupBatchId Path Long ✅ 团期主键 不变

出参

字段 类型 说明
issuable Boolean 取值变化:TRIP_FINISHED 由 false 改为 true;其余状态不变
batchStatus String 团期状态存储值(不变)
totalCount / contractIssuedCount / contractSignedCount / insuranceIssuedCount Integer 不变
items List 逐户明细(不变)

请求示例

GET /v3/admin/order/group-batch/2097250563497385985/contracts HTTP/1.1
Host: api.test.1814.love:9443
Authorization: Bearer <admin token>

无请求体。

响应示例

{
  "code": 200,
  "message": "成功",
  "data": {
    "groupBatchId": "2097250563497385985",
    "issuable": true,
    "batchStatus": "TRIP_FINISHED",
    "totalCount": 4,
    "contractIssuedCount": 4,
    "contractSignedCount": 3,
    "insuranceIssuedCount": 4,
    "items": []
  },
  "success": true
}

空数据 / 降级响应

无活跃子订单时 totalCount=0、items 为空数组(不变):

{ "code": 200, "message": "成功", "data": { "issuable": true, "batchStatus": "TRIP_FINISHED", "totalCount": 0, "items": [] }, "success": true }

错误响应

{
  "code": 589500,
  "message": "团期不存在",
  "success": false,
  "data": null
}

业务边界

  • 可出具状态集:MATERIAL_PREPARING / PENDING_DEPARTURE / TRAVELLING / TRIP_FINISHED(新增) / REVIEWING / SETTLED。
  • 同一状态集也用于接口 2 / 3 的「团期已确认、放行补确认」判断,保证确认得了的户也出具得了。

6. 手动开合同 / 保险 POST /v3/admin/order/group-batch/{groupBatchId}/contracts/issue

VO: GroupBatchContractIssueReqVO → GroupBatchIssueResultVO

使用场景

「合同保险」页签逐户开合同 / 保险。本次只放宽前置门:出行完毕的团(返团当天补签 / 补开)不再被 589548 挡住。入参出参结构不变。

入参

字段 位置 类型 必填 约束 说明
groupBatchId Path Long ✅ 团期主键 不变
orderIds Body List<Long> 否 - 为空 = 本期全部尚未出具的户(不变)
target Body String ✅ CONTRACT / INSURANCE / BOTH 不变

出参

字段 类型 说明
totalCount / successCount / failCount / skipCount Integer 不变
results[].orderId / target / outcome / message String 不变

请求示例

{ "orderIds": ["2103023889187799042"], "target": "CONTRACT" }

响应示例

{
  "code": 200,
  "message": "成功",
  "data": {
    "totalCount": 1,
    "successCount": 1,
    "failCount": 0,
    "skipCount": 0,
    "results": [
      { "orderId": "2103023889187799042", "target": "CONTRACT", "outcome": "SUCCESS", "message": null }
    ]
  },
  "success": true
}

空数据 / 降级响应

已出具的户逐项 SKIPPED(不变):

{ "code": 200, "message": "成功", "data": { "totalCount": 1, "successCount": 0, "failCount": 0, "skipCount": 1, "results": [] }, "success": true }

错误响应

团期尚未确认(RECRUITING / RESOURCE_PREPARING 等,不变):

{
  "code": 589548,
  "message": "团期确认后才能出具合同与保险",
  "success": false,
  "data": null
}

业务边界

  • TRIP_FINISHED 改前 589548,改后放行;其余状态口径不变。
  • 自动出具只剩逐户确认链路;本接口仍是人工补出的通路(逐户确认失败户补确认后会自动出,一般无需手动)。

7. 作废重开合同 / 保险 POST /v3/admin/order/group-batch/{groupBatchId}/contracts/reissue

VO: GroupBatchContractIssueReqVO → GroupBatchIssueResultVO

使用场景

「开错」态的补救通路。前置门与手动开一致,本次同样放宽到出行完毕。

入参

字段 位置 类型 必填 约束 说明
groupBatchId Path Long ✅ 团期主键 不变
orderIds Body List<Long> 否 - 不变
target Body String ✅ CONTRACT / INSURANCE / BOTH 不变
reason Body String 否 - 作废原因(不变)

出参

字段 类型 说明
totalCount / successCount / failCount / skipCount Integer 不变
results[] List 逐户结果(不变)

请求示例

{ "orderIds": ["2103023889187799042"], "target": "CONTRACT", "reason": "方案选错" }

响应示例

{
  "code": 200,
  "message": "成功",
  "data": {
    "totalCount": 1,
    "successCount": 1,
    "failCount": 0,
    "skipCount": 0,
    "results": [
      { "orderId": "2103023889187799042", "target": "CONTRACT", "outcome": "SUCCESS", "message": null }
    ]
  },
  "success": true
}

空数据 / 降级响应

作废失败的户记 FAILED,不影响其他户(不变):

{ "code": 200, "message": "成功", "data": { "totalCount": 1, "successCount": 0, "failCount": 1, "skipCount": 0, "results": [] }, "success": true }

错误响应

{
  "code": 589548,
  "message": "团期确认后才能出具合同与保险",
  "success": false,
  "data": null
}

业务边界

  • 与手动开共用同一出具门;TRIP_FINISHED 放行。

四、契约约束与正确调用方式

✅ 正确 / ❌ 错误调用对照

场景 调用
✅ 团期单确认行程 补齐各户资料 → 团期 confirm → 系统逐户确认,合同保险自动出
❌ 团期确认前逐户点确认行程 confirm-itinerary → 581065
✅ 团期确认后某户失败 看时间线 BATCH_SUB_ORDER_CONFIRM_FAILED 的原因 → 补资料 → 订单详情 confirm-itinerary 补确认
❌ 确认后等「全团补发」合同 已下线;合同保险只随逐户确认自动出具

589556 的解析

message 冒号之后按「;」切段:不以「订单 」开头的是团期级(「、」分隔的五种之一),以「订单 {订单号}:」开头的是逐户段,冒号后按「、」切出未满足项。可直接逐段展示,无需解析。

581065 的处理

提示「请到团期详情点确认」,不要引导运营去补本单资料(那是 581036 的出路)。


五、数据库行为

前端动作 外部可观察的写入
confirm 被拒(589556 等) 零写入(预检前的人员副本补齐随事务一并回滚)
confirm 成功(团期事务) 团期状态 CAS 推进 + 时间线 BATCH_CONFIRM;各户团期人员副本(order_staff_assignment)按团期配置补齐
confirm 成功(提交后逐户,每户独立事务) 子订单 CUSTOMIZING → PENDING_DEPARTURE、写 confirmed_at、订单日志 CONFIRM「随团期确认行程」、应付台账推送;随后逐户生成合同 / 保单
逐户确认失败 该户不变;团期时间线 BATCH_SUB_ORDER_CONFIRM_FAILED + order_main.last_confirm_error
单户补确认成功 同上逐户写入,并清空 last_confirm_error
confirm-itinerary / transition 被 581065 拒 零写入

无 schema 变更(last_confirm_error 为既有列)。


六、边界行为

  • 未登录 → 401(网关拦截);团期不存在 → 589500。
  • 待支付户、未付订金户会挡住整团确认:须先付订金或取消该户。
  • 已是待出行 / 出行中的户在团期确认时跳过,不重复确认、不重复出具。
  • 逐户确认使用系统身份,订单日志 / 合同创建人为 SYSTEM;确认人记在团期时间线 BATCH_CONFIRM。
  • 定案前已单独确认但未出合同的存量户,需在「合同保险」页签手动补出。
  • 建单时团期人员副本连同报账人等级一起抄(PR #8349),后挂团的户订单层主报账人不再停在 NONE。

六.5、枚举 / 数据字典

时间线事件(GroupBatchLogEventType,新增一值)

所属字段: 团期状态流水 eventType / eventTypeName | 类型: String

值 中文 说明
BATCH_SUB_ORDER_CONFIRM_FAILED 子订单确认行程失败 本次新增;changeType=DATA,operatorType=SYSTEM,extra 带 orderId / orderNo / reason

错误码

码 文案 说明
581065 团期单随团期确认,不可单独确认 本次新增
589556 团期尚不满足确认条件:{0} 码值不变,{0} 改为「;」分段、含逐户段

六.6、修改前后对比

字段级对比

字段 改前 改后
589556 message {0} 团期级未满足项,「、」连接 「;」分段:团期级一段(有才出现)+ 每户一段「订单 {订单号}:{未满足项}」
confirm-itinerary / transition(CONFIRM) 错误码 无 581065 团期单在团期确认前 581065
时间线 eventType 无该值 新增 BATCH_SUB_ORDER_CONFIRM_FAILED
合同保险面板 issuable(TRIP_FINISHED) false true
contracts/issue / reissue(TRIP_FINISHED) 589548 放行

行为级对比

行为 改前 改后
团期确认后子订单 仍在定制中,需逐户点确认行程 系统逐户确认 → 待出行
合同保险出具 确认后全团补发 + 逐户确认链路 只剩逐户确认链路
团期确认门 四项 ready + 物资 另加逐户预检(付订金即可)
子订单 CONFIRM 落库 按主键更新 带原状态条件 CAS

六.7、影响评估

  • 是否破坏向后兼容: 是。按「、」切 589556 message 的前端会把逐户段切碎;团期单的「确认行程」在团期确认前会收到 581065。
  • 前端是否必须同步上线: 建议同步。后端不依赖前端即可工作(团期确认即完成子订单确认);前端未改时只是提示不友好、按钮可点但报 581065。
  • 前端 workaround 清理点: 团期单订单详情「确认行程」按钮在团期确认前隐藏或置灰;589556 改按「;」分段展示;时间线对新事件无需映射(后端给中文名)。

七、不影响范围

  • 仅影响: 团期确认门与确认后的子订单联动、团期单 CONFIRM 守卫、团期时间线新事件、合同保险出具门的状态集。
  • 零影响:
    • 散客单的确认行程与 transition 各事件
    • 团期确认的权限码、路径、入参、成功出参
    • GET /v3/admin/order/{id}/confirm-checklist 的入参出参(逐户预检复用其判据,接口本身不变)
    • 进入待出发的七项硬门
    • 小程序端

八、测试环境已验证

部署:hl-order-service-v3 = dev-v3 @ f55840cb5(PR #8346,第一轮 2026-09-24 15:30–16:16),复验 dev-v3 @ 9ffb3c2de(PR #8349,2026-09-24)的 TEST 环境实测(证据见工单 #8339 验收评论);工单 #8339 已验收关单。

# 场景 结果
1 全户满足,调团期 confirm 200;子订单 定制中 → 待出行,写 confirmed_at,订单日志 CONFIRM「随团期确认行程」;合同 1 份 SIGNED、保险 2 条 INSURED / 户,无重复(两轮均验)
2 某户仅付订金(DEPOSIT_PAID) 视为满足付款项
3 待支付 / 户级房未完成 / 无主报账人(第一轮);产品未配置合同方案 / 成人出行人无手机号 / 未提交用车需求(复验,SQL 构造已恢复) 589556 整团拒,逐户列订单号 + 未满足项,团期与子订单状态不变
4 已待出行户 跳过,不重复确认、不重复出具
5 CHECK 约束注入使一户逐户确认失败 团期确认不回滚、其他户正常;时间线 BATCH_SUB_ORDER_CONFIRM_FAILED(含订单号 + 原因),last_confirm_error 有值;删约束后单户补确认成功,last_confirm_error 清空
6 团期单 confirm-itinerary / transition CONFIRM(团期未确认) 581065;散客单不受影响
7 TRIP_FINISHED(附带 REVIEWING)调 GET /contracts issuable=true
8 先设 PRIMARY 后下单的户 / 存量 NONE 副本(PR #8349) 建单即抄为 PRIMARY;确认预检前补齐,不再误报「未指定主报账人」

本地:788 例 + 合入后 606 例(含 6 个 Docker IT,唯一红为 dev-v3 既有基线 ConfirmChecklistGuardIT 581062);PR #8349 相关 360 例(含 Docker IT)0 失败。


九、相关历史 PR

PR Issue 说明 是否仍有效
#8302 #8268 团期人工确认端点;确认后全团补发合同保险 ⚠️ 确认端点有效;「确认后全团补发」被本单下线
本 PR #8346 #8339 确认门逐户预检、子订单随团期确认、581065 ✅ 最新
本 PR #8349 #8339 人员副本补齐、逐户确认失败留痕 ✅ 最新

十、相关文档

  • 关联 Issue: wx/HL#8339
  • 关联 PR: wx/HL#8346、wx/HL#8349
  • 定案文档:SRS §0.27.7(PR #8338)
  • 同批条目:团期核单 / 结算 / 反结算同步子订单(#8341);团期人工确认端点(#8268)

关联 / 联系人

链接

联系人

  • 后端负责人: @jw