文件
hl-api-changelog/changelogs-v2/2026-10/09_8809_出纳付款联动司导收款账户-修改接口-管理后台.md
T
2026-10-09 15:47:24 +08:00

20 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 8809 出纳付款联动司导收款账户(选已建档账户 / 手填自动建档,报账款线) admin yst 修改接口 merged not_required implemented hl-admin(claude-opus-4-8) 1f96d87b5df0c4e56e9db65f43856b96fb849269 v2.1 2026-10-09 后端 PR #8810 已合并 dev-v3(squash e50a43b72a),含 Flyway 迁移 V20261009_136(fin_reimburse 加收款账户两列 + fin_payee_account 唯一索引),需部署 order-v3 后生效;存量报账单新字段为 null。前端已交付:付款弹窗 REIMBURSE 门控加收款账户「选已建档(list-by-payee 下拉+默认预选)/手填建档」二选一,CASH 隐藏清空,账户类型按付款方式过滤;台账加收款账户留痕列、报账详情加快照展示;checkpoint 全量通过 2026-10-09 dev-v3

出纳付款联动司导收款账户(报账款线)

面向:管理后台前端(hl-admin) 日期:2026-10-09 | 后端:hl-finance(编译进 order-v3 同进程,端口 8086) 范围:只动 REIMBURSE 报账款付款线;其余 7 条出纳付款线(advance / company-loan / expense / payment / nonbiz 等)入参壳共用但对新字段静默忽略,行为零变化。

1. 接口背景

报账款是出纳付款给司导/报账人的钱。此前出纳付款表单只有「公司出账账户」(payAccountId),没有「司导收款账户」——出纳把钱打到哪张卡/哪个收款码全靠线下沟通,系统无留痕。

本次让出纳在付款弹窗里:

  1. 选账户:下拉列出该报账人已建档的收款账户(新接口 list-by-payee 提供数据源,队列行已自动带出默认账户);
  2. 手填建档:现场登记新收款账户,付款成功同时自动落入收款账户主数据(fin_payee_account),账户名强制取服务人员档案真名,不允许手填名称。

付款成功后台账、报账详情均可回查「这单钱打给了哪个账户」。

2. 变更清单

# 接口 方法 路径 变更类型 说明
1 报账款登记付款 POST /admin/finance/cashier/reimburse/pay 修改接口 入参新增 payeeAccountId 与嵌套 newPayeeAccount(二选一);出参加 payeeAccountId / payeeAccountLabel
2 按收款方查账户全集 GET /admin/finance/payee-accounts/list-by-payee 新增接口 付款弹窗「选账户」下拉数据源,轻量不分页
3 报账款待付款队列 GET /admin/finance/cashier/reimburse/queue 修改接口 出参加 bizType / reporterAssignmentId / reporterRefId / reporterPayeeType / defaultPayeeAccountId / defaultPayeeAccountLabel
4 出纳台账 GET /admin/finance/cashier/payments/page 修改接口 出参行(仅 REIMBURSE 行)回填 payeeAccountId / payeeAccountLabel 留痕
5 报账详情 GET /admin/finance/reimburses/{id} 修改接口 出参加 payeeAccountId / payeeAccountSnapshot 留痕

其余出纳付款线(advance / company-loan / expense / payment / nonbiz 等 7 条)的 /pay 接口:入参壳上能看到 payeeAccountId / newPayeeAccount 两个字段,但传了会被静默忽略,不报错,行为与之前完全一致——前端不要在这些页签渲染收款账户控件。

3. 接口详情

3.1 报账款登记付款 POST /admin/finance/cashier/reimburse/pay

  • 使用场景:出纳在「财务出纳-报账款」页签对待付款报账单(status=APPROVED 且 direction=PAYABLE)执行付款,记资金流水 OUT + 回写 PAID。
  • 认证:需管理后台 JWT。
  • 幂等性:有。重复付款由 CAS 条件更新兜底(重复提交报 598602 状态冲突),重复手填建档由收款账户唯一索引兜底(不重复建档)。
  • 限流:无。

3.2 按收款方查账户全集 GET /admin/finance/payee-accounts/list-by-payee

  • 使用场景:付款弹窗打开时,用队列行的 reporterPayeeType + reporterRefId 拉该报账人全部收款账户,渲染「选账户」下拉。
  • 认证:需管理后台 JWT。
  • 幂等性:只读。
  • 限流:无。

3.3 报账款待付款队列 GET /admin/finance/cashier/reimburse/queue

  • 使用场景:报账款页签列表;行数据现在直接带主报账人档案信息与默认收款账户,前端打开付款弹窗时无需二次查询即可预选默认账户。
  • 认证 / 幂等 / 限流:同上,只读。

4. 接口入参

4.1 付款入参 CashierPayFormReqVO(变化后全量,仅报账款线语义)

字段 类型 必填 说明
bizId String(Long) 是 业务单据ID(报账单ID)
payAccountId String(Long) 是 出账公司账户ID(fin_fund_account)
payMethod String 否 付款方式(字典 fin_pay_way:CASH 现金 / BANK 银行转账 / THIRD_PARTY 三方支付)
payChannel String 条件 付款渠道(WXPAY / ALIPAY;仅 payMethod=THIRD_PARTY 时传,不超过 20 字符)
amount Number 是 付款金额(大于 0,须等于单据结算金额,不一致 598610 硬拦)
fee Number 否 手续费(不小于 0)
voucherNo String 否 付款凭证号
voucherUrl String 否 付款凭证影像 URL
payDate Date 是 付款日期(yyyy-MM-dd,可回溯补录)
payeeAccountId String(Long) 条件必填 新增:已建档收款账户ID。payMethod=BANK/THIRD_PARTY 时与 newPayeeAccount 二选一必填;CASH 时禁传(598612)
newPayeeAccount Object 条件必填 新增:手填建档对象,与 payeeAccountId 互斥(同传 598612),子字段见 4.2

4.2 newPayeeAccount 子字段(手填建档)

字段 类型 必填 说明
payeeRefId String(Long) 是 服务人员档案ID(司机=driverId,其余角色=staffId)。强制挂档案,不允许纯手填名称
accountType String 是 账户类型:WECHAT_QR / ALIPAY_QR / BANK_CARD(对公 CORP_ACCOUNT 在报账款线被拦,见 §6)
qrUrl String 条件 收款码图 URL(QR 类账户必填)
bankAccount String 条件 银行卡号(BANK_CARD 必填)
bankName String 否 开户行

不传 payeeName:账户名一律以服务人员档案真名覆盖,出纳手填的名称不生效(防止同名串账)。

4.3 list-by-payee 查询参数

字段 类型 必填 说明
payeeType String 是 收款方类型:DRIVER / GUIDE / PHOTOGRAPHER / LEADER(直接取队列行 reporterPayeeType)
payeeRefId Long 是 关联ID(司机=driverId,其余=staffId;直接取队列行 reporterRefId)

4.4 队列入参

无变化:仅分页参数 page / pageSize。

5. 出参字段

统一 Result 包装;分页为 PageResult(records / total / page / pageSize)。Long 主键一律以 JSON 字符串返回。

5.1 付款响应 CashierPayRespVO(变化后)

字段 类型 说明
flowId String(Long) 资金流水ID
flowNo String 资金流水单号
balanceAfter Number 出账账户付后余额
bizId String(Long) 业务单据ID(已回写 PAID)
payeeAccountId String(Long),可空 新增:实际落账的收款账户ID(手填建档场景返回新建ID);现金付款为 null
payeeAccountLabel String,可空 新增:收款账户快照(类型+脱敏尾号+收款人名,如「银行卡 ****0123 巴特尔」);现金付款为 null

5.2 list-by-payee 响应(PayeeAccountRowRespVO 数组)

字段 类型 说明
id String(Long) 收款账户ID
payeeType String 收款方类型
payeeRefId String(Long) 关联ID
payeeName String 收款方名称(档案真名快照)
accountType String 账户类型:WECHAT_QR / ALIPAY_QR / BANK_CARD / CORP_ACCOUNT
qrUrl String 收款码图 URL
bankAccount String 银行卡号/对公账号(展示层脱敏)
bankName String 开户行
isDefault Integer 是否默认账户:0 否 / 1 是

5.3 队列行 ReimburseQueueRowRespVO(新增字段)

字段 类型 说明
bizType String 新增:业务对象类型(ORDER 订单 / GROUP_BATCH 团期批次)
reporterAssignmentId String(Long),可空 新增:主报账人人员分配ID(多态口径,无主报账人为空)。注意:这是分配行ID,不能直接当 payeeRefId 用
reporterRefId String(Long),可空 新增:主报账人档案ID(司机=driverId,其余=staffId),后端已按 bizType 反查好,前端直接用
reporterPayeeType String,可空 新增:主报账人收款方类型(DRIVER/GUIDE/PHOTOGRAPHER/LEADER;不可映射角色为空)
defaultPayeeAccountId String(Long),可空 新增:该报账人默认收款账户ID(无默认账户为空)
defaultPayeeAccountLabel String,可空 新增:默认账户标签(类型+脱敏尾号,如「银行卡 ****0123」;无默认账户为空)

其余既有字段(reimburseId / bizNo / reporterName / settleAmount / status 等)无变化。

5.4 台账行 / 报账详情(留痕字段)

  • 台账 GET /admin/finance/cashier/payments/page 行(CashierPaymentRowRespVO)新增 payeeAccountId(String 可空)+ payeeAccountLabel(String 可空),仅 REIMBURSE 报账款行有值,其余付款线恒 null。
  • 报账详情 GET /admin/finance/reimburses/{id} 新增 payeeAccountId(String 可空)+ payeeAccountSnapshot(String 可空,类型+脱敏尾号+收款人名)。现金付款两字段为 null。

6. 枚举 / 数据字典

6.1 账户类型 accountType(PayeeAccountTypeEnum)

码值 中文 报账款线可用
WECHAT_QR 微信收款码 可用
ALIPAY_QR 支付宝收款码 可用
BANK_CARD 银行卡 可用
CORP_ACCOUNT 对公账户 不可用(报账款对私,手填传对公被拦 595202)

6.2 收款方类型 payeeType / reporterPayeeType

DRIVER 司机 / GUIDE 导游 / PHOTOGRAPHER 摄影师 / LEADER 领队。角色映射:GUIDE_ASSISTANT(副导游)归并为 GUIDE;其余不可映射角色 reporterPayeeType 为空,付款时选账户会被归属校验拦(598614)。

6.3 付款方式 payMethod(字典 fin_pay_way,无变化)

CASH 现金 / BANK 银行转账 / THIRD_PARTY 三方支付。

6.4 账户类型与付款方式强校验(已拍板硬拦)

payMethod 允许的账户类型 错位报错
BANK BANK_CARD 598615
THIRD_PARTY WECHAT_QR / ALIPAY_QR 598615
CASH 不允许传任何收款账户 598612

7. 错误码

7.1 新增(出纳域 5986 段顺延)

码 常量 文案 触发场景
598612 CASHIER_PAYEE_ACCOUNT_CONFLICT 收款账户参数非法(现金付款无需收款账户;选账户与手填建档二选一) CASH 传了 payeeAccountId/newPayeeAccount;或两者同传
598613 CASHIER_PAYEE_ACCOUNT_REQUIRED 该付款方式须选择或登记报账人收款账户 BANK/THIRD_PARTY 但两者皆空
598614 CASHIER_PAYEE_ACCOUNT_NOT_MATCH 收款账户不属于本报账人 所选账户的 payeeRefId 不等于报账单主报账人档案ID
598615 CASHIER_PAYEE_ACCOUNT_TYPE_MISMATCH 收款账户类型与付款方式不匹配(银行转账须选银行卡账户,三方支付须选收款码账户) 如 payMethod=BANK 却选了微信收款码账户

7.2 复用(收款账户域 5952xx,手填建档链抛出)

码 说明
595201 收款账户不存在或已停用(选了已被删除/停用的账户)
595202 账户要素组合校验失败(QR 类缺 qrUrl / BANK_CARD 缺 bankAccount / 报账款线传 CORP_ACCOUNT 等)
595204 服务人员档案不存在或不在册(手填建档 payeeRefId 校验 fail-fast)

7.3 既有(本次不变)

598602 状态冲突(重复付款)/ 598610 金额与单据应付不一致 / 598604 账户余额不足 等沿用。

8. 示例

8.1 典型成功(银行转账 + 手填建档银行卡)

请求:

POST /admin/finance/cashier/reimburse/pay
{
  "bizId": "88010001",
  "payAccountId": "3101",
  "payMethod": "BANK",
  "amount": 1500.00,
  "payDate": "2026-10-09",
  "newPayeeAccount": {
    "payeeRefId": "6601",
    "accountType": "BANK_CARD",
    "bankAccount": "6222021234567890123",
    "bankName": "工商银行呼和浩特支行"
  }
}

响应:

{
  "code": 0,
  "data": {
    "flowId": "990001",
    "flowNo": "FL2026100912300001",
    "balanceAfter": 48500.00,
    "bizId": "88010001",
    "payeeAccountId": "7701",
    "payeeAccountLabel": "银行卡 ****0123 巴特尔"
  },
  "msg": ""
}

队列行带默认账户(付款弹窗直接预选):

{
  "reimburseId": "88010001",
  "bizNo": "BX202610090001",
  "reporterName": "巴特尔",
  "bizType": "ORDER",
  "reporterAssignmentId": "5501",
  "reporterRefId": "6601",
  "reporterPayeeType": "DRIVER",
  "defaultPayeeAccountId": "7701",
  "defaultPayeeAccountLabel": "银行卡 ****0123",
  "settleAmount": 1500.00
}

list-by-payee 下拉数据源:

GET /admin/finance/payee-accounts/list-by-payee?payeeType=DRIVER&payeeRefId=6601
{
  "code": 0,
  "data": [
    {
      "id": "7701",
      "payeeType": "DRIVER",
      "payeeRefId": "6601",
      "payeeName": "巴特尔",
      "accountType": "BANK_CARD",
      "qrUrl": null,
      "bankAccount": "****0123",
      "bankName": "工商银行呼和浩特支行",
      "isDefault": 1
    }
  ]
}

8.2 边界情况

8.2a 现金付款(不带收款账户,两新字段回 null):

{
  "bizId": "88010002",
  "payAccountId": "3101",
  "payMethod": "CASH",
  "amount": 300.00,
  "payDate": "2026-10-09"
}
{
  "code": 0,
  "data": {
    "flowId": "990002",
    "flowNo": "FL2026100912300002",
    "balanceAfter": 48200.00,
    "bizId": "88010002",
    "payeeAccountId": null,
    "payeeAccountLabel": null
  }
}

8.2b 报账人无默认账户 / 角色不可映射:队列行 defaultPayeeAccountId / defaultPayeeAccountLabel / reporterPayeeType 为 null,下拉为空数组,出纳须手填建档。

8.3 业务失败

8.3a 银行转账不传收款账户(598613):

{
  "bizId": "88010001",
  "payAccountId": "3101",
  "payMethod": "BANK",
  "amount": 1500.00,
  "payDate": "2026-10-09"
}
{ "code": 598613, "msg": "该付款方式须选择或登记报账人收款账户", "data": null }

8.3b 银行转账选了微信收款码账户(598615):

请求体同上但改为传 "payeeAccountId": "7702"(7702 是该报账人的 WECHAT_QR 账户)。

{ "code": 598615, "msg": "收款账户类型与付款方式不匹配(银行转账须选银行卡账户,三方支付须选收款码账户)", "data": null }

8.3c 选了别的报账人的账户(598614):

{ "code": 598614, "msg": "收款账户不属于本报账人", "data": null }

8.3d 现金付款传了收款账户 / 选账户与手填同传(598612):

{ "code": 598612, "msg": "收款账户参数非法(现金付款无需收款账户;选账户与手填建档二选一)", "data": null }

9. 业务边界

  • 适用:报账款(REIMBURSE)页签、direction=PAYABLE(付给司导)的付款单。
  • 不适用:
    • 反向收款(confirm-in,司导向公司上交余款)零改动,不涉及收款账户。
    • 其余 7 条出纳付款线不接联动,壳入参上的两个新字段传了静默忽略。
  • 强制挂档案:手填建档必须选服务人员档案(payeeRefId 必填),账户名=档案真名,出纳不能手填收款人姓名。
  • 例外通道:收款人不是司导本人(如家属代收)时,不走付款弹窗手填,先去「收款账户管理」用组织类/手填入口建档,再回到付款弹窗选择(归属校验口径:账户须挂到该报账人档案下,否则 598614)。
  • 首个账户自动置默认:手填建档的账户若是该收款方名下首个账户,自动成为默认;已有账户时不抢既有默认。
  • 重复提交安全:双击/重试不会产生重复账户(唯一索引兜底),也不会重复扣款(598602)。

10. 修改前后对比

10.1 字段级

位置 原来 现在
付款入参 只有出账账户 payAccountId 新增 payeeAccountId / newPayeeAccount(BANK/THIRD_PARTY 二选一必填,CASH 禁传)
付款响应 flowId/flowNo/balanceAfter/bizId 新增 payeeAccountId / payeeAccountLabel(CASH 为 null)
队列行 无报账人档案/账户信息 新增 bizType / reporterAssignmentId / reporterRefId / reporterPayeeType / defaultPayeeAccountId / defaultPayeeAccountLabel
台账行 无收款账户留痕 REIMBURSE 行回填 payeeAccountId / payeeAccountLabel,其余线 null
报账详情 无收款账户留痕 新增 payeeAccountId / payeeAccountSnapshot
选账户下拉数据源 不存在 新增 GET /admin/finance/payee-accounts/list-by-payee

10.2 行为级

项 原来 现在
BANK/THIRD_PARTY 付款 只填出账账户即可 必须选收款账户或手填建档,否则 598613
CASH 付款 不变 传收款账户参数会被 598612 拦(前端应禁用控件)
账户与付款方式 无校验 错位强拦 598615(银行转账须银行卡,三方须收款码)
账户归属 无校验 只能选/建本报账人名下账户,否则 598614

11. 影响评估 / 回滚

  • 破坏性:有(行为级)。报账款 BANK/THIRD_PARTY 付款从「不填收款账户也能付」变为「必填」,前端付款弹窗必须同步改造(加选账户下拉 + 手填建档表单 + CASH 时禁用),否则出纳付款会被 598613 全量拦截。
  • 前端同步上线:要求。后端部署后旧版前端的报账款银行/三方付款会全部报 598613,前端改版须与后端部署同步或紧随。
  • 回滚方案:后端回退到 #8810 之前版本即可恢复旧行为;前端新版代码对旧后端兼容(新字段不传即走旧链路)。DB 新增两列可空,保留无害;fin_payee_account 唯一索引不影响既有数据。

12. 注意事项

  1. 金额/ID 一律字符串:所有 Long ID(bizId / payeeAccountId / payeeRefId / defaultPayeeAccountId 等)JSON 序列化为字符串,前端按 string 处理。
  2. CASH 禁用收款账户控件:payMethod 切到 CASH 时隐藏/禁用选账户与手填入口,并清空已填值,避免 598612。
  3. 下拉数据源用队列行字段:打开付款弹窗时直接拿 reporterPayeeType + reporterRefId 调 list-by-payee,不要用 reporterAssignmentId(那是分配行ID,口径不同)。
  4. 默认账户预选:队列行 defaultPayeeAccountId 非空时直接预选,出纳可改选或改手填。
  5. 新字段全部可空:存量报账单、现金付款、其余付款线场景下 payeeAccountId/Label 均为 null,渲染一律判空。
  6. 部署时序:依赖 Flyway 迁移 V20261009_136__fin_reimburse_payee_account_link.sql(fin_reimburse 加两列 + fin_payee_account 加唯一索引),order-v3 部署时自动执行;未部署前新字段不生效(598613 不会触发,行为同旧版)。
  7. 手填建档幂等:同一报账人同一账户要素重复提交不会重复建档,返回已有账户ID,前端无需防重逻辑(但仍建议提交后禁用按钮)。

13. 关联 / 联系人

  • Issue:wx/HL#8809
  • PR:wx/HL#8810
  • Commit:e50a43b72a
  • 关联:#8679(收款账户关联服务人员档案基建)
  • 后端负责人:腰苏图(yst)