用户改拍「团期核单归财务域(免原型对齐),finance/settlement 团期产品 tab 即预留位」。order-v2/batch/detail 旧 Tab 随 081966ff 下线,财务域落地 9a28a7a8:团期产品 tab 改走 GB-ADM-001 /v3/admin/order/group-batch, 行弹层挂 GroupSettlementPanel 读 reports/group+finalize/confirm。 status_note 补迁移说明,updated_at 翻 2026-09-28。
30 KiB
schema: "hl-changelog/v2" ticket: "8361" title: "团期报销核单「一团一张报账单」——团期核单 finalize/confirm/reports 三端点新增 + 台账应收整团聚合一行 + 报账单 biz 三字段 + 搜索兼容团号 + 核单 summary 新增 SETTLED" consumer: "admin" author: "yst" change_type: "新增接口" backend_status: "merged" gateway_status: "pending" frontend_status: "verified" frontend_owner: "mmg" frontend_ref: "9a28a7a8dc12a0c041c616ac3b1000c53847b8a6" target_release: "v2.1" verified_at: "2026-09-27" status_note: "Epic #8361 五 PR(#8366/#8367/#8368/#8400/#8406)已全部合并 dev-v3,尚未部署测试服、网关未实测。前端需动三处:①应收台账行按 rowType 分流(GROUP_BATCH 行 id 是团期批次 ID,按订单详情跳转必 404);②报账单列表按 bizType 分流展示(GROUP_BATCH 行展示 bizNo 团号);③新增团期核单页(finalize/confirm/reports 三端点 + settlementStatus 新增 SETTLED 态)。【2026-09-27 mmg】①应收台账 rowType 分流 + ②报账单 bizType 分流已交付(276de5f1):GROUP_BATCH 行跳团期详情不跳订单详情、详情「团号」取 bizNo(行快照兜底)、搜索兼容团号文案对齐;receivable/reimburse 两 spec 18 例全绿。③团期核单页 defer——原型快照 Sep 17 早于本 Epic 无其设计(prototype fidelity 不可无原型建财务新页),后端 §11 明说可随后迭代不阻塞,待原型刷新后续做,故 frontend_status 保持 pending。【2026-09-27 mmg ③】团期核单页已交付(1c555f54):用户拍板不算财务域不等原型,详情页「核单结算」后新增「团期核单」tab——reports/group 空壳范式先判 finalized、finalize 节点门 TRIP_FINISHED/REVIEWING 置灰内联、confirm 仅「FINALIZED+待复核」、SETTLED 无人工结清口、金额/ID 全字符串 null 显 —;新建 api/order-v3/groupSettlement.js+GroupSettlementTab.vue,API spec 4 例+组件 spec 10 例+详情页 spec 共 28 例全绿,checkpoint 全绿。Epic ①②③全部闭环,翻 verified。【2026-09-28 mmg ③迁】用户改拍「团期核单归财务域(免原型对齐),finance/settlement 团期产品 tab 即预留位」:先把 order-v2/batch/detail 的「团期核单」Tab 下线(081966ff),再落地财务域(9a28a7a8)——团期产品 tab 数据源由空调常规 /v3/admin/order-settlement/tasks(仅常规 CORE 无团期批次,即"接口不对"根因)改走 GB-ADM-001 /v3/admin/order/group-batch(订单域接口财务只读,pageNo/departFrom/departTo/opsStage 七桶),行弹层挂 GroupSettlementPanel(原 GroupSettlementTab 迁入)读 reports/group+finalize/confirm;应收/已收权威字段直显不反算,未建团行(groupBatchId=null)不放入口。恢复 api/order-v3/groupSettlement.js,新增 index.spec 锁双 tab 数据源+参数名+列 render+弹层入参,三 spec 22 例全绿,checkpoint 全绿。ref 由 1c555f54 改指 9a28a7a8。" updated_at: "2026-09-28" base: "dev-v3"
团期报销核单「一团一张报账单」(管理后台)
服务: hl-order-service-v3(团期核单三端点)+ hl-finance(台账应收 / 报账单列表) Epic: #8361 PR: #8366(G1 多态 DDL)+ #8367(G2 三端点)+ #8368(G3 一团一张推送)+ #8400(G4 台账整团聚合/搜索/反向联动)+ #8406(biz 三字段 + keyword 团号)
1. 接口背景
原核单链路只有「一户一张报账单」(按订单 orderId 聚合)。团期(出团批次)场景下,财务需要按整团做核单、复核、回款跟踪。本次 Epic 把核单与报账单从「一户一张」泛化为「一个业务对象一张」:
- 团期维度新增「一团一核单」三端点(finalize 核单 → confirm 财务复核并推一团一张报账单 → reports/group 读核单表),快照落库一团一行。
- 报账单 fin_reimburse 改 biz_type + biz_id 多态关联:ORDER(一户一张,不变)/ GROUP_BATCH(一团一张,新增)。
- 应收台账对团期批次整团聚合一行(不按户拆),行上补 rowType/groupBatchId 鉴别字段。
- 报账单列表补 bizType/bizId/bizNo 三字段;报账单搜索与台账 keyword 均兼容团号。
- 一团一张报账单 RECEIVABLE 全收后,自动反向把团期核单快照 settlementStatus 回写 SETTLED(已结清)。
2. 变更清单
| # | 变更 | 方法 | 路径 | 类型 | 摘要 |
|---|---|---|---|---|---|
| 1 | 完成团期核单 | POST | /v3/admin/order/group-batch/{groupBatchId}/settlement/finalize | 新增接口 | 按团聚合落核单快照,幂等 |
| 2 | 团期核单财务复核 | POST | /v3/admin/order/group-batch/{groupBatchId}/settlement/confirm | 新增接口 | 复核通过 + 同事务推一团一张报账单 |
| 3 | 查询团期核单表 | GET | /v3/admin/order/group-batch/{groupBatchId}/settlement/reports/group | 新增接口 | 读 active 快照;未核单返回 finalized=false 空壳 |
| 4 | 应收台账分页 | GET | /admin/finance/receipt/receivable/page | 修改接口 | 行新增 rowType/groupBatchId;团期整团聚合一行;keyword 兼容团号 |
| 5 | 报账单分页 | GET | /admin/finance/reimburses/page | 修改接口 | 行新增 bizType/bizId/bizNo;orderNo 入参扩为同时匹配团号 biz_no |
| 6 | 团期核单 summary | — | (端点 1/2/3 的出参 GroupSettlementRespVO) | 修改接口 | settlementStatus 新增枚举值 SETTLED(全收自动回写,非人工触发) |
3. 接口详情
| 端点 | 使用场景 | 认证 | 幂等性 | 限流 |
|---|---|---|---|---|
| POST finalize | 团期出行完毕后,核单员按团聚合落核单快照 | 网关 JWT;角色须 SUPER_ADMIN / ADMIN / FINANCE(缺 589507) | 幂等:重复提交返回既有 active 快照,不重复落库 | 网关统一限流 |
| POST confirm | 财务复核团期核单,通过后推一团一张报账单 | 同 finalize | 状态门 + CAS 挡重复复核;推送侧 uk_biz_version(biz_type,biz_id,version_no) 撞号重查兜底返回既有单;推送失败整单回滚(review_status 停 PENDING),可安全重试 | 网关统一限流 |
| GET reports/group | 团期核单表展示(核单前/后都调) | 网关 JWT;须 group-batch:finance:view 权限码(缺 589507) | 只读 | 网关统一限流 |
| GET receivable/page | 财务收款-应收台账 | 网关 JWT(finance 域先例,无方法级权限注解) | 只读 | 网关统一限流 |
| GET reimburses/page | 报账款列表(复核视角) | 网关 JWT | 只读 | 网关统一限流 |
金额/ID 序列化约定:GroupSettlementRespVO 的所有 BigDecimal 金额字段与 Long ID 字段均序列化为 JSON 字符串(防精度丢失);台账行/报账单行的 Long ID 为字符串,BigDecimal 金额为 JSON number。
4. 接口入参
4.1 路径 / Query 参数
团期核单三端点(均无请求体):
| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| groupBatchId | path | Long | 是 | 团期 ID,必须 ≥ 1(否则 400「团期 ID 必须大于 0」) |
应收台账分页 GET /admin/finance/receipt/receivable/page(query):
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| page | int | 是 | 页码,从 1 起 |
| pageSize | int | 是 | 每页条数 |
| keyword | string | 否 | 搜索关键字(团号 batch_no / 客户姓名 / 产品名 / 订单号 模糊,任一命中);空=不限。注:只模糊匹配团号本身,不匹配团期名称/期次 |
| receivableStatus | string | 否 | UNPAID 待收款 / PARTIAL 部分收款 / DONE 已收讫;空或非法值=不按收款状态过滤 |
报账单分页 GET /admin/finance/reimburses/page(query):
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| page | int | 是 | 页码 |
| pageSize | int | 是 | 每页条数 |
| status | string | 否 | 单据状态(枚举见 §6);空=全部 |
| direction | string | 否 | PAYABLE 公司应付报账人 / RECEIVABLE 报账人应回款 / BALANCED 两清;空=全部 |
| orderNo | string | 否 | 订单号/团号(模糊,同时匹配 order_no 与 biz_no——团期报账单 order_no 为空,按团号 biz_no 也能搜到);空=不限 |
| reporterName | string | 否 | 报账人姓名(模糊);空=不限 |
4.2 请求体字段
三端点均无请求体;两个分页接口均为 GET query 传参,无请求体。
5. 出参字段
5.1 GroupSettlementRespVO(finalize / confirm / reports/group 三端点共用)
外层统一包装 {"code":200,"success":true,"data":{...}},下表为 data 结构:
| 字段 | 类型 | 说明 |
|---|---|---|
| finalized | boolean | 是否已有核单快照;false=尚未核单,快照字段全 null,只填团期基本信息段(batchNo/productName/departDate/batchStatus),不抛 404 |
| groupSettlementId | string(Long) | 团期核单快照 ID |
| groupBatchId | string(Long) | 团期 ID |
| batchNo | string | 团期号,例 20261001-01 |
| productName | string | 产品名称快照 |
| departDate | string(date) | 出发日期 yyyy-MM-dd |
| batchStatus | string | 团期状态(GroupBatchStatus 码,见 §6) |
| settledOrderCount | int | 已核单子订单户数 |
| totalActiveOrderCount | int | 在团子订单总户数(仅排除已取消) |
| subOrderTotalActualCost | string(BigDecimal) | 子订单实际成本合计 |
| subOrderTotalProfit | string(BigDecimal) | 子订单毛利合计 |
| sharedCostTotal | string(BigDecimal) | 团期共享成本合计 |
| sharedCostByType | array | 共享成本按类型汇总,元素见下表 |
| grandTotalCost | string(BigDecimal) | 团期总成本(子订单成本合计 + 共享成本合计) |
| actualTravelerCount | int | 实际出行人数 |
| perPersonSharedCost | string(BigDecimal) 或 null | 人均共享成本;出行人数为 0 时为 null |
| groupAdvanceApproved | string(BigDecimal) | 整团预支已批合计(scope=GROUP_BATCH;资金拨付提示,不计入 grandTotalCost) |
| groupAdvancePending | string(BigDecimal) | 整团预支待批合计(仅提示,不参与成本/毛利公式) |
| groupTotalAmount | string(BigDecimal) | 全团应收总额(一团一张报账单净额输入) |
| groupPaidAmount | string(BigDecimal) | 全团已付总额 |
| reviewStatus | string | 复核状态:PENDING 待复核 / APPROVED 已复核 / RETURNED 已退回 |
| settlementStatus | string | 核单状态:PENDING 待核单 / FINALIZED 已核单 / SETTLED 已结清(新增,见 §6) |
| flowStatus | string | 团期流程状态快照:TRIP_FINISHED / REVIEWING / SETTLED(confirm 通过后翻 SETTLED;独立于团期本体状态机,不动 order_group_batch.batch_status) |
| settledBy | string(Long) | 核单人 ID |
| settledByName | string | 核单人姓名快照 |
| settledAt | string(datetime) | 团核单完成时间 yyyy-MM-dd HH:mm:ss |
| remark | string | 备注 |
| createTime | string(datetime) | 快照创建时间 |
sharedCostByType[] 元素(SharedCostByTypeVO):
| 字段 | 类型 | 说明 |
|---|---|---|
| costType | string | 成本类型码:BUS 整团大巴 / LEADER 领队 / PHOTOGRAPHER 摄影 / OTHER 其他 |
| costTypeDesc | string | 成本类型中文标签 |
| total | string(BigDecimal) | 该类型成本合计 |
5.2 应收台账行 ReceiptReceivableRowRespVO(receivable/page 的 data.records[])
| 字段 | 类型 | 说明 |
|---|---|---|
| rowType | string | 新增。ORDER 订单行 / GROUP_BATCH 团期整团聚合行。行点击/跳转策略必须按本字段分流 |
| id | string(Long) | rowType=ORDER 时为订单 ID(可跳订单详情);rowType=GROUP_BATCH 时挂团期批次 ID(与 groupBatchId 同值),按订单 ID 跳详情必 404 |
| groupBatchId | string(Long) 或 null | 新增。rowType=GROUP_BATCH 时有值;ORDER 行恒 null |
| orderNo | string | rowType=ORDER 为订单号;GROUP_BATCH 行挂团号 batch_no |
| teamNo | string | 团号;GROUP_BATCH 行同为团号 batch_no |
| productName | string | 产品名(GROUP_BATCH 行为团期名) |
| customerName | string 或 null | 客户姓名;GROUP_BATCH 团行恒 null(整团无单一客户) |
| customerPhone | string 或 null | 客户手机号(明文,内部财务对账用);GROUP_BATCH 团行恒 null |
| orderStatus | string | rowType=ORDER 为 OrderStatus 枚举值;rowType=GROUP_BATCH 为 GroupBatchStatus 码——两套枚举空间按 rowType 分流 |
| orderStatusName | string | 上述状态的中文名 |
| receivableStatus | string | UNPAID 待收款 / PARTIAL 部分收款 / DONE 已收讫 |
| receivableStatusName | string | 收款状态中文名 |
| receivableAmount | number | 应收总额(取消单归 0)。团行:已核单团读快照全团应收;未核单团按在团子订单实时求和 |
| paidAmount | number | 已收金额(毛额,退款不回减)。团行结清(SETTLED)后顶满应收 |
| collectedAmount | number | 代收金额。已核单团的未结清欠收挂本列(一团一张报账单已推送,全团尾款=主报账人代收口径);未核单团恒 0 |
| balanceAmount | number | 欠收金额。与 collectedAmount 互斥、合计恒等于实时待收尾款;团行结清后归 0 |
团期整团聚合行为(新增):页内命中的团期子订单按 groupBatchId 折叠——每团只出一行台账,同团其余子订单行丢弃,total 按页内折叠数修正。已知近似(后端拍板接受):折叠在页内做,同团子订单跨页时该团在每页各出一行;DONE 筛选视图下 total 为近似值,跨页行数/total 可能有偏差。
5.3 报账单行 ReimburseRowRespVO(reimburses/page 的 data.records[])
只列本次新增三字段(其余字段不变:id/reimburseNo/reporterName/reporterRole/direction/collectableAmount/actualCollectedAmount/underCollectAmount/advanceAmount/cashPaidAmount/netAmount/settleAmount/receivedAmount/remainingAmount/status/reviewByName/reviewTime/createTime):
| 字段 | 类型 | 说明 |
|---|---|---|
| bizType | string | 新增。ORDER 订单单(一户一张)/ GROUP_BATCH 团期单(一团一张);前端按本字段分流展示——GROUP_BATCH 行展示 bizNo(团号) |
| bizId | string(Long) | 新增。bizType=ORDER 为订单 ID;GROUP_BATCH 为团期批次 ID(勿按订单 ID 跳详情) |
| bizNo | string | 新增。bizType=ORDER 为订单号;GROUP_BATCH 为团号 batch_no |
既有字段语义修订:
| 字段 | 修订 |
|---|---|
| orderId | bizType=GROUP_BATCH 团期单恒 null |
| orderNo | bizType=GROUP_BATCH 团期单恒 null,团号看 bizNo |
6. 枚举 / 数据字典
rowType(台账行类型,新增):ORDER 订单行 / GROUP_BATCH 团期整团聚合行。
bizType(报账单业务对象类型,新增):ORDER 订单单(一户一张)/ GROUP_BATCH 团期单(一团一张)。
settlementStatus(团期核单状态,本次新增 SETTLED):
| 值 | 中文 | 说明 |
|---|---|---|
| PENDING | 待核单 | 快照未 finalize(reports/group 空壳态不出现本值,看 finalized=false) |
| FINALIZED | 已核单 | finalize 完成,待财务复核 |
| SETTLED | 已结清 | 新增。一团一张报账单 RECEIVABLE 全收后由后端监听端自动回写(FINALIZED→SETTLED),非任何人工端点触发;confirm 不会把 settlementStatus 翻成 SETTLED(confirm 翻的是 reviewStatus 与 flowStatus) |
reviewStatus(复核状态):PENDING 待复核 / APPROVED 已复核 / RETURNED 已退回。
flowStatus(快照内流程状态):TRIP_FINISHED / REVIEWING / SETTLED。
GroupBatchStatus(团期状态,GROUP_BATCH 台账行的 orderStatus 与核单快照 batchStatus 用):RECRUITING 招募中 / RESOURCE_PREPARING 资源准备中 / MATERIAL_PREPARING 物料准备中 / PENDING_DEPARTURE 待出发 / TRAVELLING 出行中 / TRIP_FINISHED 出行完毕 / REVIEWING 核单中 / SETTLED 已结算 / CANCELLED 已取消。
OrderStatus(订单粗状态,ORDER 台账行的 orderStatus 用):PENDING_PAY 待支付 / CUSTOMIZING 定制中 / PENDING_DEPARTURE 待出行 / TRAVELLING 出行中 / COMPLETED 已完成 / CANCELLED 已取消。
receivableStatus(收款状态):UNPAID 待收款 / PARTIAL 部分收款 / DONE 已收讫。
报账单 status:PENDING 待复核 / APPROVED 已批准 / PARTIAL_RECEIVED 部分收讫 / PAID 已付讫 / RECEIVED 已回款 / CLOSED 两清 / RETURNED 已退回。
direction(报账方向):PAYABLE 公司应付报账人 / RECEIVABLE 报账人应回款 / BALANCED 两清。
costType(共享成本类型):BUS 整团大巴 / LEADER 领队 / PHOTOGRAPHER 摄影 / OTHER 其他。
7. 错误码
外层结构 {"code":错误码,"message":"文案","data":null,"success":false}。
| 错误码 | 触发端点 | 文案({0} 为占位) | 处置建议 |
|---|---|---|---|
| 400 | 三端点 | 团期 ID 必须大于 0 | 参数校验失败 |
| 589500 | 三端点 | 团期不存在 | 检查 groupBatchId |
| 589507 | 三端点 | 无操作权限(当前角色未授予团期权限,或该团期不在您名下) | finalize/confirm 需 SUPER_ADMIN/ADMIN/FINANCE;reports/group 需 group-batch:finance:view |
| 584133 | finalize | 该团期未配置主报账人,请先在团期人员配置中设置主报账人后再核单 | 去团期人员配置设主 |
| 584134 | finalize | 该团期存在 {0} 个主报账人,一团只能有一个主报账人,请先去重后再核单 | 去重主报账人 |
| 584135 | finalize | 团期子订单 {0} 尚未确认行程,请全团子订单都确认行程后再核单({0}=子订单 ID) | 催该户确认行程 |
| 584136 | confirm | 该团期尚未完成核单,请先完成核单后再做财务复核 | 先 finalize |
| 584137 | confirm | 当前团期核单状态不允许财务复核(须为已核单且待复核),操作已回滚 | 刷新快照状态;并发复核败者也会命中 |
| 584138 | finalize | 团期当前状态为「{0}」,未到核单节点(需出行完毕或核单中),不允许核单({0}=当前 batchStatus) | 等团期到 TRIP_FINISHED/REVIEWING |
8. 示例
8.1 典型成功——finalize 后读团期核单表
POST /v3/admin/order/group-batch/2097250563497385985/settlement/finalize(无请求体)→ 响应与 GET reports/group 同构:
{
"code": 200,
"success": true,
"data": {
"finalized": true,
"groupSettlementId": "9101234567890123456",
"groupBatchId": "2097250563497385985",
"batchNo": "20261001-01",
"productName": "呼伦贝尔草原 5 日游",
"departDate": "2026-10-01",
"batchStatus": "REVIEWING",
"settledOrderCount": 5,
"totalActiveOrderCount": 6,
"subOrderTotalActualCost": "45600.00",
"subOrderTotalProfit": "8400.00",
"sharedCostTotal": "3200.00",
"sharedCostByType": [
{"costType": "BUS", "costTypeDesc": "整团大巴", "total": "2000.00"},
{"costType": "LEADER", "costTypeDesc": "领队", "total": "1200.00"}
],
"grandTotalCost": "48800.00",
"actualTravelerCount": 18,
"perPersonSharedCost": "177.78",
"groupAdvanceApproved": "5000.00",
"groupAdvancePending": "0.00",
"groupTotalAmount": "54000.00",
"groupPaidAmount": "48000.00",
"reviewStatus": "PENDING",
"settlementStatus": "FINALIZED",
"flowStatus": "REVIEWING",
"settledBy": "40001",
"settledByName": "王财务",
"settledAt": "2026-09-27 12:00:00",
"remark": "团核单",
"createTime": "2026-09-27 12:00:00"
}
}
台账分页典型响应(GET /admin/finance/receipt/receivable/page?page=1&pageSize=20&keyword=20261001):
{
"code": 200,
"success": true,
"data": {
"records": [
{
"rowType": "ORDER",
"id": "2097000000000000001",
"groupBatchId": null,
"orderNo": "HL20260920001",
"teamNo": "T-0920-01",
"productName": "阿尔山 3 日游",
"customerName": "张三",
"customerPhone": "13800001111",
"orderStatus": "COMPLETED",
"orderStatusName": "已完成",
"receivableStatus": "PARTIAL",
"receivableStatusName": "部分收款",
"receivableAmount": 6000.00,
"paidAmount": 3000.00,
"collectedAmount": 0,
"balanceAmount": 3000.00
},
{
"rowType": "GROUP_BATCH",
"id": "2097250563497385985",
"groupBatchId": "2097250563497385985",
"orderNo": "20261001-01",
"teamNo": "20261001-01",
"productName": "呼伦贝尔草原 5 日游",
"customerName": null,
"customerPhone": null,
"orderStatus": "SETTLED",
"orderStatusName": "已结算",
"receivableStatus": "DONE",
"receivableStatusName": "已收讫",
"receivableAmount": 54000.00,
"paidAmount": 54000.00,
"collectedAmount": 0,
"balanceAmount": 0
}
],
"total": 2,
"page": 1,
"pageSize": 20
}
}
8.2 边界——未核单团读核单表(finalized=false 空壳)+ 报账单 GROUP_BATCH 行
GET reports/group(该团尚未 finalize)——不抛 404,快照字段全 null,前端展示「尚未核单」占位:
{
"code": 200,
"success": true,
"data": {
"finalized": false,
"groupSettlementId": null,
"groupBatchId": "2097250563497385985",
"batchNo": "20261001-01",
"productName": "呼伦贝尔草原 5 日游",
"departDate": "2026-10-01",
"batchStatus": "TRIP_FINISHED",
"settledOrderCount": null,
"totalActiveOrderCount": null,
"subOrderTotalActualCost": null,
"subOrderTotalProfit": null,
"sharedCostTotal": null,
"sharedCostByType": null,
"grandTotalCost": null,
"actualTravelerCount": null,
"perPersonSharedCost": null,
"groupAdvanceApproved": null,
"groupAdvancePending": null,
"groupTotalAmount": null,
"groupPaidAmount": null,
"reviewStatus": null,
"settlementStatus": null,
"flowStatus": null,
"settledBy": null,
"settledByName": null,
"settledAt": null,
"remark": null,
"createTime": null
}
}
报账单列表中的团期单(GET /admin/finance/reimburses/page?page=1&pageSize=20&orderNo=20261001,按团号搜到)——orderId/orderNo 恒 null,团号看 bizNo:
{
"code": 200,
"success": true,
"data": {
"records": [
{
"id": "9123456789012345678",
"reimburseNo": "BZ-20260927-0001",
"orderId": null,
"orderNo": null,
"bizType": "GROUP_BATCH",
"bizId": "2097250563497385985",
"bizNo": "20261001-01",
"reporterName": "李领队",
"reporterRole": "GUIDE",
"direction": "RECEIVABLE",
"collectableAmount": 54000.00,
"actualCollectedAmount": 48000.00,
"underCollectAmount": 6000.00,
"advanceAmount": 0,
"cashPaidAmount": 0,
"netAmount": 6000.00,
"settleAmount": 6000.00,
"receivedAmount": 0,
"remainingAmount": 6000.00,
"status": "APPROVED",
"reviewByName": "王财务",
"reviewTime": "2026-09-27 12:30:00",
"createTime": "2026-09-27 12:30:00"
}
],
"total": 1,
"page": 1,
"pageSize": 20
}
}
8.3 业务失败——confirm 时团期未核单(584136)
POST confirm(该团尚未 finalize):
{"code": 584136, "message": "该团期尚未完成核单,请先完成核单后再做财务复核", "data": null, "success": false}
finalize 时团期状态未到核单节点(584138,{0} 透出当前状态):
{"code": 584138, "message": "团期当前状态为「TRAVELLING」,未到核单节点(需出行完毕或核单中),不允许核单", "data": null, "success": false}
9. 业务边界
适用:
- finalize:团期状态须为 TRIP_FINISHED(出行完毕)或 REVIEWING(核单中);全团恰好 1 个 PRIMARY 主报账人;全团在团子订单(不含已取消)均已确认行程。
- confirm:须已存在 active 核单快照且为「FINALIZED + 待复核 PENDING」。
- 台账/报账单列表的 GROUP_BATCH 行:仅团期批次订单(有 groupBatchId 关联)才会聚合/出现;散单(ORDER 行)行为完全不变。
不适用:
- 招募中~出行中的团期不允许 finalize(584138)——共享成本未录、子订单成本未发生,快照无意义。
- 未 finalize 的团期不允许 confirm(584136)。
- SETTLED / CANCELLED 团期同样不允许 finalize(584138,fail-closed 闭集)。
特殊边界:
- 重复 finalize:幂等返回既有快照,不重复落库、不报错。
- 并发 confirm:CAS 败者报 584137,不静默成功。
- confirm 推送报账单失败:整单回滚(review_status 停 PENDING),可安全重试;推送幂等由 uk_biz_version 兜底。
- settlementStatus=SETTLED 只能由「一团一张报账单 RECEIVABLE 全收」自动回写,无人工端点能置该态;部分回款不触发。
- 团期回款不回写子订单 paid_amount:台账团行已核单后金额读团快照,子订单级欠收停留在订金态属预期,全团回款进度由报账单承接。
10. 修改前后对比
字段级
| 接口 | 字段 | 原来 | 现在 |
|---|---|---|---|
| receivable/page 行 | rowType | 无此字段 | 新增,ORDER / GROUP_BATCH |
| receivable/page 行 | groupBatchId | 无此字段 | 新增;GROUP_BATCH 行有值,ORDER 行恒 null |
| receivable/page 行 | id | 恒为订单 ID | GROUP_BATCH 行挂团期批次 ID(勿跳订单详情) |
| receivable/page 行 | customerName / customerPhone | 恒有值 | GROUP_BATCH 行恒 null |
| receivable/page 行 | orderStatus / orderStatusName | 恒为 OrderStatus 枚举 | GROUP_BATCH 行为 GroupBatchStatus 码(两套枚举按 rowType 分流) |
| receivable/page 入参 | keyword | 团号(散团 team_no)/客户姓名/产品名/订单号 四字段模糊 | 追加兼容团期团号 batch_no(命中的团整团进入结果集并折叠成 GROUP_BATCH 行) |
| reimburses/page 行 | bizType / bizId / bizNo | 无此三字段 | 新增;GROUP_BATCH 行 orderId/orderNo 恒 null |
| reimburses/page 入参 | orderNo | 仅模糊匹配 order_no | 同时模糊匹配 order_no 与 biz_no(团号可搜到团期单) |
| GroupSettlementRespVO | settlementStatus | PENDING / FINALIZED | 追加 SETTLED(全收自动回写) |
行为级
| 行为 | 原来 | 现在 |
|---|---|---|
| 台账团期订单展示 | 逐户一行(团期子订单每户一行台账) | 整团聚合一行(页内折叠,total 按折叠数修正) |
| 台账行数/total | 订单粒度精确计数 | 团折叠后 total 为近似值(跨页折叠 + DONE 视图粗筛假阳性剔除,后端拍板接受) |
| 报账单生成 | 只有订单核单「一户一张」 | 团期 confirm 追加「一团一张」(biz_type=GROUP_BATCH,单号同为 BZ- 前缀) |
| 报账单 biz 关联 | order_id 单列 | biz_type + biz_id 多态(ORDER 单 biz 三字段与旧 order 字段同值) |
11. 影响评估 / 回滚
破坏兼容评估:
- 新增端点(finalize/confirm/reports/group):纯新增,无兼容风险。
- 台账/报账单列表新增字段:纯追加,旧前端忽略新字段可继续工作。
- 行为级不兼容(唯一必须前端同步的点):台账对团期子订单不再逐户出行。旧前端若把每行当订单、按 id 跳订单详情,GROUP_BATCH 行会 404;且团期子订单行数变少。旧前端没有团期入口时感知为「团期订单从台账消失、多了一个点不开的行」。
前端同步上线建议:台账 rowType 分流与报账单 bizType 分流随后端同窗口上线;团期核单页(三端点)可随后迭代,不阻塞。
回滚方案:后端回滚 #8406/#8400/#8368/#8367/#8366 五个合并提交(逆序)。回滚后台账恢复逐户一行、新增字段消失;已落库的 GROUP_BATCH 报账单与团期核单快照保留在库但不再被读写。前端对新增字段若做了「有则展示」的容错,回滚零改动;若强依赖 rowType 分流,回滚后分流逻辑永不命中 GROUP_BATCH 分支,自然降级为 ORDER 行为。
12. 注意事项
- rowType 分流是硬要求:GROUP_BATCH 行的 id 是团期批次 ID(与 groupBatchId 同值),严禁当订单 ID 跳订单详情(必 404)。
- 两套状态枚举空间:台账行 orderStatus 在 GROUP_BATCH 行是 GroupBatchStatus 码(9 态)、ORDER 行是 OrderStatus 码(6 态),翻译展示必须按 rowType 选字典,不可混用(两边都有 TRAVELLING/SETTLED/CANCELLED 等同名值但语义层级不同)。
- 金额与 ID 序列化:GroupSettlementRespVO 的 BigDecimal 金额与 Long ID 全是 JSON 字符串;台账行/报账单行 Long ID 是字符串、金额是 number。
- keyword 只匹配团号本身(batch_no LIKE),不匹配团期名称/期次;台账团行上的标识就是团号(orderNo/teamNo 同挂 batch_no)。
- SETTLED 无人工触发口:settlementStatus=SETTLED 只由回款全收自动回写;前端不要提供「手动结清」按钮,也不要在 confirm 后期望 settlementStatus 立即变 SETTLED(confirm 翻的是 reviewStatus/flowStatus)。
- 空壳范式:reports/group 用 finalized=false + 全 null 表示未核单,不是 404;前端先判 finalized 再渲染快照区。
- 报账单列表 GROUP_BATCH 行 orderId/orderNo 恒 null,展示层一律取 bizNo;报账单详情接口 GET /admin/finance/reimburses/{id} 路径不变、按报账单 id 查,两种 bizType 通用。
- 团期回款不回写子订单 paid_amount,勿因「子订单仍显示欠收」报 bug——全团回款进度看报账单与台账团行。
13. 关联 / 联系人
- Epic:wx/HL#8361
- 子 Issue:wx/HL#8362(G1)/ wx/HL#8363(G2)/ wx/HL#8364(G3)/ wx/HL#8365(G4)/ wx/HL#8402(biz 三字段 + keyword 团号)
- PR:wx/HL#8366 / wx/HL#8367 / wx/HL#8368 / wx/HL#8400 / wx/HL#8406
- Commit:https://git.1814.love/wx/HL/commit/97e1736ca6 / https://git.1814.love/wx/HL/commit/355c578d1b / https://git.1814.love/wx/HL/commit/1f65d78941 / https://git.1814.love/wx/HL/commit/a7d41a3b22 / https://git.1814.love/wx/HL/commit/811f3a2fc4
- 后端负责人:腰苏图(yst)