19 KiB
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 | finance-reimburse-module-onboarding | 报账款模块整模块接入指引(复核管理 5 接口 + 出纳执行 3 接口,含详情支出行明细与退回重推护栏) | admin | yst(GIT) | 新增接口 | deployed | verified | verified | mmg | 0aa4ec7a962205edf8b1e02664b8c2807b28ed02 | 2026-09-16 | 报账款(核单→复核→出纳打款/回款)整模块首次对接指引,覆盖 Epic #7721 全链路 + Epic #7764 改进(详情内嵌核单支出行明细 lines、核单反确认加报账单执行护栏 584330、退回可重推)。8 个管理后台接口全部为本期新交付,前端此前无任何报账款文档,按本文一次对接即可。金额口径、状态机、错误码、勾稽勾稽区语义均以内联最终态给出。mmg 2026-09-16 前端已交付:api/finance/reimburse.js 复核 5 接口 + finance/reimburse 复核管理页(列表/详情勾稽区/lines 垫付明细/批准/退回/反审)+ CashierQueuePage REIMBURSE 外部单位线(金额锁死=settleAmount)+ ReimburseConfirmInModal(RECEIVABLE 走 confirm-in 无 amount)+ finance/pay/reimburse 薄壳;错误码透 message 不建字典;spec 22 例、checkpoint 13 项全绿。待后端配菜单行:财务域「报账款」component=finance/reimburse、出纳支付管理「报账款」component=finance/pay/reimburse。2026-09-16 后端 sys_menu 已配但落在「付款管理→报账复核」component=/finance/payable/reimburse,前端当日迁址对齐(复核页 git mv finance/reimburse→finance/payable/reimburse,commit 0aa4ec7a);支付行 finance/pay/reimburse 与配置一致。 | 2026-09-16 | dev-v3 |
报账款模块整模块接入指引(复核管理 + 出纳执行)
服务: hl-order-service-v3(hl-finance 模块) 类型: 🆕 整模块新增(本期新交付,前端首次对接) 日期: 2026-09-16 影响范围: 管理后台财务域「报账款」菜单 + 出纳支付管理「报账款」页签 覆盖 Epic: #7721(报账款全链路)+ #7764(详情明细 / reopen 护栏 / 退回重推)
一、模块定位 & 业务闭环
报账款 = 司机/导游等一线人员的行程费用报账。一条订单核单(settlement)完成后,系统自动生成一张报账单,走「财务复核 → 出纳执行」两段:
核单 confirmSettlement ──推送──▶ 报账单(PENDING)
│
财务复核(本模块复核管理 5 接口)
├─ 批准 approve PENDING→APPROVED(净额=0 两清单直通 CLOSED)
├─ 退回 return PENDING→RETURNED(终态留痕,可重推,见 §六)
└─ 反审 un-approve APPROVED→PENDING(已付讫/已回款不可反审)
│ APPROVED
出纳执行(出纳支付管理,按净额方向二选一)
├─ 净额<0 PAYABLE 公司补司机 → 出纳 pay → PAID(OUT 流水,余额减)
├─ 净额>0 RECEIVABLE 司机回款公司 → 出纳 confirm-in → RECEIVED(IN 流水,余额加)
└─ 净额=0 BALANCED 两清 → 复核批准直通 CLOSED(无支付、无流水)
单据来源唯一:报账单只由核单推送生成,不提供新建/编辑/删除接口。前端只做「复核 + 出纳执行 + 查询」。
二、金额口径(核心,前端展示勾稽区必读)
报账单金额全部由后端快照算出,前端只读展示,不参与计算:
| 字段 | 含义 | 说明 |
|---|---|---|
collectableAmount |
应代收 | 核单总额 − 客户线上已付(剔除司机代收 DRIVER_CASH) |
actualCollectedAmount |
实收代收 | 司机实际代收到的现金(勾稽快照) |
underCollectAmount |
欠收额 | = 应代收 − 实收代收(勾稽留痕,不阻断,供复核判断) |
advanceAmount |
预支合计 | 该单已预支给报账人的总额 |
cashPaidAmount |
现付垫付合计 | 报账人现付垫付总额(= 详情 lines 明细加总,见 §五) |
netAmount |
净额 | = 应代收 − 预支 − 现付垫付(有符号,正负定方向) |
settleAmount |
结算金额 | = |净额|(BALANCED 两清为 0),出纳执行金额锁死=此值 |
direction |
方向 | PAYABLE 公司应付报账人 / RECEIVABLE 报账人应回款 / BALANCED 两清 |
勾稽区(
actualCollectedAmount/underCollectAmount)是复核依据:实收 ≠ 应代收时欠收额非 0,复核据此判断是否退回,但系统不强制拦。
三、复核管理接口(5 个,/admin/finance/reimburses)
3.1 报账款分页 GET /admin/finance/reimburses/page
复核视角列表,支持状态/方向筛选 + 订单号/报账人姓名模糊。
Query 入参(继承 PageParam:pageNo / pageSize 必填):
| 参数 | 必填 | 说明 |
|---|---|---|
status |
否 | 单据状态:PENDING/APPROVED/PAID/RECEIVED/CLOSED/RETURNED;空=全部 |
direction |
否 | 方向:PAYABLE/RECEIVABLE/BALANCED;空=全部 |
orderNo |
否 | 订单号(模糊) |
reporterName |
否 | 报账人姓名(模糊) |
出参行 ReimburseRowRespVO(金额=JSON number;Long ID=string):
id / reimburseNo(BZ-前缀) / orderId / orderNo / reporterName / reporterRole(GUIDE/DRIVER/PHOTOGRAPHER) / direction / collectableAmount / actualCollectedAmount / underCollectAmount / advanceAmount / cashPaidAmount / netAmount / settleAmount / status / reviewByName / reviewTime / createTime
3.2 报账详情 GET /admin/finance/reimburses/{id}
全字段快照 + 勾稽 + 流水回执 + 核单支出行明细 lines。
出参在分页行字段基础上追加:
| 字段 | 说明 |
|---|---|
settlementId / versionNo |
关联核单 ID / 同核单推送版本号(本期恒 1) |
reporterAssignmentId |
主报账人人员分配 ID |
reviewBy / reviewRemark |
复核人 ID / 复核意见(退回原因落此列) |
fundAccountId / payFlowId / paidAt |
出纳执行账户 / 资金流水 ID(一单一流水)/ 付讫到账时间 |
flowNo / flowDirection / balanceAfter |
流水回执(payFlowId 反查回填;未付款/未回款时三字段均 null) |
lines |
核单可报账支出行明细(见 §五);无垫付固定返回 [] |
remark / updateTime |
备注 / 更新时间 |
3.3 复核批准 PUT /admin/finance/reimburses/{id}/approve
PENDING → APPROVED;净额=0 两清单直通 CLOSED(不进出纳队列)。
入参 body(可空整 body):{ "remark": "复核意见,可空,≤512字" }
3.4 退回 PUT /admin/finance/reimburses/{id}/return
PENDING → RETURNED(终态留痕;退回后可到核单反确认重推,见 §六)。
入参 body(必填):{ "reason": "退回原因,必填,≤512字" }
3.5 反审 PUT /admin/finance/reimburses/{id}/un-approve
APPROVED → PENDING,清复核快照。已付讫(PAID)/已回款(RECEIVED) 不可反审。无 body。
四、出纳执行接口(/admin/finance/cashier,复用出纳统一出口)
报账款进出纳后复用出纳支付管理既有 4 接口,靠 payType/bizType = REIMBURSE 路由。报账款的执行动作按方向二选一:
4.1 待付款队列 GET /admin/finance/cashier/queue?payType=REIMBURSE
拉「公司欠司机(PAYABLE)已批准待打款」的报账单。
| Query | 必填 | 说明 |
|---|---|---|
payType |
是 | 报账款传 REIMBURSE(页签下拉值) |
pageNo/pageSize |
是 | 分页 |
队列只含
direction=PAYABLE 且 status=APPROVED的报账单;RECEIVABLE(司机回款)不进待付款队列,走下 §4.3。
出参行 CashierQueueRowRespVO:id / bizNo(BZ-单号) / payType=REIMBURSE / payTypeName=报账款 / unitId / unitName / category=报账款(固定) / amount(=settleAmount) / fee / actualAmount / operatorName / createTime / occurDate / status=APPROVED / remark
4.2 登记付款(公司补司机)POST /admin/finance/cashier/pay
净额<0(PAYABLE)时,出纳打款给报账人 → 记 OUT 流水 + 回写报账单 PAID + 重算账户结存。
| body 字段 | 必填 | 说明 |
|---|---|---|
bizType |
✅ | 传 REIMBURSE |
bizId |
✅ | 报账单 ID |
payAccountId |
✅ | 出账公司账户 ID(fin_fund_account) |
payMethod |
否 | 付款方式字典 fin_pay_way:CASH/BANK/THIRD_PARTY |
payChannel |
条件 | 仅 payMethod=THIRD_PARTY 时传 WXPAY/ALIPAY,其余不传 |
amount |
✅ | 付款金额,必须=settleAmount,不等抛 598610 |
fee |
否 | 手续费(≥0,挂出账流水) |
voucherNo/voucherUrl |
否 | 付款凭证号 / 凭证影像 URL |
payDate |
✅ | 付款日期 yyyy-MM-dd(可回溯补录) |
前端金额框建议只读回填 settleAmount(后端已锁死,改了必报 598610)。
4.3 收款确认入账(司机回款)POST /admin/finance/cashier/confirm-in
净额>0(RECEIVABLE)时,司机把多收尾款交回公司 → 记 IN 流水 + 回写报账单 RECEIVED。入账金额 = settleAmount。
| body 字段 | 必填 | 说明 |
|---|---|---|
bizType |
✅ | 传 REIMBURSE(空默认 NONBIZ 业务外收入,报账回款必须显式传) |
bizId |
✅ | 报账单 ID(须 direction=RECEIVABLE 且 status=APPROVED) |
payAccountId |
✅ | 入账公司账户 ID |
payMethod |
否 | 收款方式字典 fin_pay_way:CASH/BANK/THIRD_PARTY |
payChannel |
条件 | 仅 THIRD_PARTY 时传 WXPAY/ALIPAY |
voucherNo/voucherUrl |
否 | 收款凭证 |
payDate |
✅ | 收款日期 yyyy-MM-dd |
confirm-in入参无 amount 字段——金额后端取单据 settle_amount,前端不传。方向不符(如给 PAYABLE 单调 confirm-in)抛 599207。
4.4 已付款流水台账 GET /admin/finance/cashier/payments/page
出纳已付款流水(fin_fund_flow OUT),可按 bizType=REIMBURSE 过滤报账款打款记录。入参 bizType/pageNo/pageSize 等,出参与资金流水台账一致。
pay / confirm-in 统一出参 CashierPayRespVO:flowId / flowNo(LS+yyyyMMdd+4位序号) / balanceAfter(本笔记完后结存) / bizId(已回写终态)
五、详情支出行明细 lines(Epic #7766,复核依据)
报账详情出参 lines = 主报账人 CASH_PAID 现付垫付支出行,供复核看「垫付明细构成」。只含可报账行,口径与 cashPaidAmount 严格一致(明细加总 == cashPaidAmount)。
SettlementLineItemVO 字段:
| 字段 | 类型 | 说明 |
|---|---|---|
category / categoryName |
string | 费用类别码 / 中文名(HOTEL/TICKET/MEAL/GUIDE/PHOTOGRAPHER/OTHER_EXPENSE/SERVICE 等) |
itemName |
string | 项目名(住宿=酒店-房型,门票=景区-规格,人员=姓名,车辆=车牌 车型/司机,其他=项目名) |
unitPrice / quantity |
number | 单价 / 数量(可空) |
amount |
number | 实际金额 |
reimburseAmount |
number | 报账金额(加总此列 == cashPaidAmount) |
paymentMethod / paymentMethodName |
string | 付款方式(本接口恒 CASH_PAID 现付垫付)/ 中文名 |
date |
string | 业务日期 yyyy-MM-dd(可空) |
remark |
string | 备注(可空) |
口径说明(前端无需处理,了解即可):人员行(GUIDE/PHOTOGRAPHER)按 staffId 精确匹配主报账人;车辆现金行(VEHICLE)不计入可报账口径故不进
lines。无垫付时lines固定返回[],不是 null。
六、退回可重推 + 核单反确认护栏(Epic #7764/#7765)
6.1 退回可重推(前端只需知流程,无新接口)
复核退回(RETURNED)是终态留痕,但金额错误可纠正:财务退回 → 核单员到订单侧「反确认核单」调整 → 重 confirm 产生新 settlement_id → 系统推新报账单(BZ 单号递增),旧 RETURNED 单不动。前端在退回提示里告知「退回后可到核单反确认重推」即可。
6.2 核单反确认护栏(错误码 584330,跨服务)
为防止「钱已动但核单又改」的资金不一致,订单侧反确认核单接口加了护栏:
- 接口:
POST /v3/admin/order/{orderId}/settlement/final-snapshots/reopen(在 order-v3 核单域,非本模块接口) - 护栏:该订单报账单已进入出纳执行(status ∈ PENDING/APPROVED/PAID/RECEIVED)→ 抛 584330,禁止反确认
- 放行:无报账单 / 仅 RETURNED / CLOSED(净额0两清无流水)
前端调核单反确认时若收到 584330,提示「该订单报账单已进入出纳执行,禁止反确认核单;如需调整请先退回报账单」。
七、状态机 & 数据字典
7.1 报账单状态 status
| 值 | 中文 | 含义 / 可达动作 |
|---|---|---|
PENDING |
待复核 | 可 approve / return |
APPROVED |
已批准 | 可 un-approve;PAYABLE 进出纳队列待 pay;RECEIVABLE 待 confirm-in |
PAID |
已付讫 | 终态(公司已打款);不可反审 |
RECEIVED |
已回款 | 终态(司机已回款);不可反审 |
CLOSED |
两清 | 终态(净额0直通,无流水) |
RETURNED |
已退回 | 终态留痕;可核单反确认重推新单 |
7.2 方向 direction
PAYABLE 公司应付报账人 / RECEIVABLE 报账人应回款 / BALANCED 两清
7.3 出纳付款类型 payType(队列页签)
REIMBURSE 报账款(单号前缀 BZ-)。其余页签值:NONBIZ 业务外支出 / EXPENSE 费用报销 / PAYMENT 应付款 / PREPAY 预付款 / STAFF_LOAN 员工借款。
7.4 收付方式 payMethod(字典 fin_pay_way)
CASH 现金 / BANK 银行转账 / THIRD_PARTY 三方支付(须配 payChannel=WXPAY/ALIPAY)
7.5 流水方向 flowDirection
OUT 出账 / IN 入账
八、错误码
8.1 报账域(段位 599200-599299)
| 码 | 含义 | 触发场景 |
|---|---|---|
| 599201 | 报账执行单不存在 | 详情/操作 id 无效或已删 |
| 599202 | 报账单状态非法 | 当前状态不允许此操作(如对 PAID 单 approve) |
| 599203 | 报账单状态流转非法 | 并发推进,条件更新 0 行兜底 |
| 599204 | 该核单已生成报账单 | 幂等命中(重推接缝预留) |
| 599205 | 报账单推送快照数据非法 | 脏数据 fail-fast |
| 599206 | 报账单号生成冲突 | 取号并发撞号,请重试 |
| 599207 | 报账单方向与操作不匹配 | RECEIVABLE 走 pay / PAYABLE 走 confirm-in / BALANCED 进队列 |
| 599208 | 退回原因必填 | return 未传 reason |
8.2 出纳域(段位 598600-598699,报账相关)
| 码 | 含义 | 触发场景 |
|---|---|---|
| 598601 | 业务单不存在 | bizId 无效 |
| 598602 | 业务单状态非已批准不可付款 | 对非 APPROVED 单 pay |
| 598603 | 出账/入账账户不存在或已停用 | payAccountId 无效 |
| 598604 | 账户余额不足且不允许透支 | 透支闸拦截 |
| 598605 | 付款金额无效 | amount≤0 或 fee<0 |
| 598606 | 收款确认单状态非法 | confirm-in 单非已批准可入账 |
| 598607 | 付款类型非法 | payType/bizType 非已接通枚举 |
| 598608 | 收付方式与渠道不匹配 | THIRD_PARTY 未传渠道 / CASH,BANK 传了渠道 |
| 598609 | 收付账户与方式不匹配 | 现金方式选银行账户等两级校验 |
| 598610 | 付款金额与单据应付金额不一致 | pay 的 amount ≠ settleAmount(金额锁死) |
8.3 核单域(跨服务,reopen 护栏)
| 码 | 含义 | 触发接口 |
|---|---|---|
| 584330 | 报账单已进入出纳执行,禁止反确认核单 | POST /v3/admin/order/{orderId}/settlement/final-snapshots/reopen(order-v3) |
九、示例
9.1 复核列表(筛选待复核 + PAYABLE)
GET /admin/finance/reimburses/page?status=PENDING&direction=PAYABLE&pageNo=1&pageSize=20
9.2 批准 → 出纳打款(PAYABLE 公司补司机)
PUT /admin/finance/reimburses/{id}/approve
{ "remark": "复核无误" }
# 待付款队列取单
GET /admin/finance/cashier/queue?payType=REIMBURSE&pageNo=1&pageSize=20
# 出纳打款(金额锁死=settleAmount)
POST /admin/finance/cashier/pay
{ "bizType":"REIMBURSE", "bizId":"<报账单ID>", "payAccountId":"<账户ID>",
"payMethod":"BANK", "amount":975.00, "payDate":"2026-09-16" }
9.3 司机回款(RECEIVABLE)
POST /admin/finance/cashier/confirm-in
{ "bizType":"REIMBURSE", "bizId":"<报账单ID>", "payAccountId":"<账户ID>",
"payMethod":"CASH", "payDate":"2026-09-16" }
9.4 边界:金额不符 / 方向不符 / 反确认被拦
# amount≠settleAmount → 598610
POST /admin/finance/cashier/pay {..."amount":999.00...} → 598610 付款金额与单据应付金额不一致
# PAYABLE 单调 confirm-in → 599207
POST /admin/finance/cashier/confirm-in {..."bizId":"<PAYABLE单>"...} → 599207 方向与操作不匹配
# 报账单已进执行 → 核单反确认 584330
POST /v3/admin/order/{orderId}/settlement/final-snapshots/reopen → 584330 禁止反确认核单
十、影响评估 / 回滚
- 纯新增模块,前端首次对接,无存量调用方,无回滚负担。
- 复核/出纳接口均已部署测试服并行为级验证通过。
- 若前端暂不上报账款页面,后端模块独立运行不受影响(报账单仍由核单推送正常生成)。
十一、注意事项
- 金额一律只读:报账单所有金额(含勾稽区、settleAmount、lines)由后端快照算出,前端展示即可,不要本地重算。
- 出纳金额锁死:pay 的
amount必须 =settleAmount;confirm-in 不传 amount。建议前端金额框只读回填。 - Long ID 是 string:所有 ID(id/orderId/settlementId/bizId/payFlowId 等)序列化为 string,前端按字符串处理防精度丢失。
- 方向决定动作:一张报账单面前只有一个可点按钮——PAYABLE 显示「付款」(pay)、RECEIVABLE 显示「收款入账」(confirm-in)、BALANCED/PAID/RECEIVED/CLOSED/RETURNED 均不进出纳。
- 流水回执可空:详情的
flowNo/flowDirection/balanceAfter在未付款/未回款时为 null,前端做好空态。
十二、关联 / 联系人
- Epic #7721 报账款全链路:Issue #7721
- Epic #7764 报账款改进:Issue #7764(详情明细 #7766 / reopen 护栏 #7765)
- 合并 PR:#7771(护栏+明细)、#7774(文档+原型)
- 负责人:腰苏图(yst)| 反馈:财务域后端对接群 / 直接 @yst