9.1 KiB
schema, ticket, title, consumer, author, change_type, backend_status, gateway_status, frontend_status, frontend_owner, frontend_ref, target_release, verified_at, base, updated_at, status_note
| schema | ticket | title | consumer | author | change_type | backend_status | gateway_status | frontend_status | frontend_owner | frontend_ref | target_release | verified_at | base | updated_at | status_note |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| hl-changelog/v2 | 8664 | 公司借款收回新增单笔形态:POST /admin/finance/company-loans/{id}/recover | admin | yst(GIT) | 新增接口 | merged | verified | implemented | hl-admin(claude-opus-4-8) | c32b35c9527dde6bdc21386e1c6d47ad1f33bb96 | v2.1 | 2026-10-01 | dev-v3 | 2026-10-01 | 公司借款「借出方向」的收回(借出的钱到期收回)新增单笔形态——已付款借出单按单笔收款,与既有按单位合并收款(§1.4.3 recover/settle)共用 settle 核心。原型收回入口并入「支付管理/公司借款支付」已付款台账行「收款登记」;原「收款管理/公司借款收回」按单位汇总收银台原型入口下线(合并收款三端点后端保留可用)。前端已交付:入口挂「支付管理/公司借款支付」已付款台账行「收款登记」,弹窗拉详情默认欠收全额可改部分,fee 内扣预览,提交即禁按钮防连点,SETTLED 禁提交,收齐按 settledLoanIds 提示核销并刷台账;unitId/unitType 不入参。(此前 frontmatter 误标 implemented 无 ref,本次实证交付后补齐。) |
【新增接口·管理后台】公司借款单笔收回 POST /admin/finance/company-loans/{id}/recover (#8664)
PR: #8670 | 服务: hl-order-service-v3(hl-finance 模块,8086) | 更新时间: 2026-09-30
1. 接口背景
公司借款「借出方向」(direction=OUT,公司借钱给供应商/员工)的到期收回,原只有「按单位汇总收银台」一种形态(勾选同一单位多笔借款单合并收款,§1.4.1-1.4.3)。本次按业务拍板新增单笔形态:在「支付管理 / 公司借款支付」的已付款台账行上对单笔借出单直接「收款登记」——已付款的借出单逐笔收回,无需按单位聚合勾选。
只写"为什么",不涉及实现:收回动作的入口从「按单位汇总收银台」下沉到「已付款借出单行」,更符合"只有已付款的台账才能收回"的业务直觉,也避免跨单位合并的复杂度(用户明确不需要跨单位合并收款,单笔即可)。
2. 变更清单
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|---|---|---|---|---|
| 1 | 公司借款单笔收回 | POST | /admin/finance/company-loans/{id}/recover |
新增接口 | 按单笔借款单收回,与合并收款共用 settle 核心 |
合并收款三端点(§1.4.1 可选借款单 / §1.4.2 手续费试算 / §1.4.3 合并收款提交)保留可用,本次仅新增单笔便捷形态。
3. 接口详情
3.1 公司借款单笔收回
- 使用场景:出纳在「支付管理 / 公司借款支付」的已付款台账,对某笔 direction=OUT(借出)且未收齐的借款单做收回登记(收欠收全额或部分金额)。
- 认证:需管理后台 JWT。
- 幂等性:否(每次调用产生一笔还款流水 GH- + 一笔资金流水 IN + 一条 RECOVER 操作流水;重复提交会重复入账,前端提交后应禁用按钮防连点)。
- 限流:无。
行为:按本单收回指定金额 → 写还款流水(GH- 取号)+ 资金流水单笔 IN(bizType=COMPANY_LOAN)+ RECOVER 操作流水 + CAS 状态重算(收齐转已核销)+ 联动入账账户结存。与合并收款 §1.4.3 共用 recoverSettle settle 核心,守卫完全一致。
4. 接口入参
4.1 路径参数
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id |
Long | ✅ | 借款单ID(path) |
4.2 请求体字段
| 字段 | 类型 | 必填 | 说明 | 校验规则 |
|---|---|---|---|---|
amount |
BigDecimal | ✅ | 本次收回金额 | >0 且 ≤ 该单剩余余额,否则 599309 |
fundAccountId |
Long | ✅ | 入账资金账户ID | 须存在且 ACTIVE(fin_fund_account) |
feeRate |
BigDecimal | ❌ | 手续费率(‰) | 默认 0;fee = amount × feeRate / 1000,实收 = amount − fee |
voucherUrl |
String | ❌ | 收款凭证影像URL | — |
⚠️
unitId/unitType不入参——后端从借款单反查归属单位,前端无需也不应传(防传错串单)。
5. 出参(响应)
复用合并收款 CompanyLoanRecoverSettleRespVO:
| 字段 | 类型 | 说明 |
|---|---|---|
totalAmount |
BigDecimal | 本次收回金额(=入参 amount) |
actualAmount |
BigDecimal | 实收(= totalAmount − fee) |
fee |
BigDecimal | 手续费 |
repayIds |
Long[] | 还款流水ID列表(单笔恒单元素) |
settledLoanIds |
Long[] | 本次收齐转已核销的借款单ID(收齐时含本单 id,未收齐为空) |
6. 枚举 / 数据字典
本接口入参/出参无枚举字段。相关业务方向(由后端从借款单反查,前端不传):
6.1 direction(借款方向,借款单自身字段)
| 值 | 中文 | 说明 |
|---|---|---|
OUT |
借出 | 公司借钱给单位/员工,到期收回(本接口只收 OUT 单) |
IN |
借入 | 公司向单位/员工借钱,到期归还(走归还链路,非本接口) |
7. 错误码
| code | 含义 | 触发场景 |
|---|---|---|
| 599301 | 借款单不存在 | id 查无此单 |
| 599310 | 借款方向不匹配 | 该单非 OUT(借出),借入单不能走收回 |
| 599308 | 借款单已核销 | 已收齐核销的单不可再收 |
| 599302 | 借款单状态不可收 | 非可收回状态(如待付款未放款) |
| 599309 | 收回金额超剩余余额 | amount > 该单剩余余额 |
| 599303 | 手续费率非法 | feeRate < 0 或 ≥ 1000 |
| 599307 | 还款单号取号耗尽 | GH- 单号序列耗尽(极少) |
| 595001 | 资金账户不存在 | fundAccountId 查无此账户 |
| 595006 | 资金账户不可用 | 账户非 ACTIVE |
8. 示例
8.1 典型成功(足额收齐,无手续费)
请求:
POST /admin/finance/company-loans/101234/recover
Authorization: Bearer <token>
Content-Type: application/json
{
"amount": 5000.00,
"fundAccountId": 88
}
响应(收齐转已核销):
{
"code": 0,
"data": {
"totalAmount": 5000.00,
"actualAmount": 5000.00,
"fee": 0.00,
"repayIds": [900001],
"settledLoanIds": [101234]
},
"msg": ""
}
8.2 边界(部分收回 + 含手续费)
请求:
{
"amount": 2000.00,
"fundAccountId": 88,
"feeRate": 5,
"voucherUrl": "https://oss.example.com/voucher/x.jpg"
}
响应(部分收回,settledLoanIds 为空;fee=2000×5/1000=10,实收 1990):
{
"code": 0,
"data": {
"totalAmount": 2000.00,
"actualAmount": 1990.00,
"fee": 10.00,
"repayIds": [900002],
"settledLoanIds": []
},
"msg": ""
}
8.3 业务失败(超额收回)
请求:
{ "amount": 99999.00, "fundAccountId": 88 }
响应:
{ "code": 599309, "msg": "收回金额超剩余余额", "data": null }
9. 业务边界
- ✅ 适用:direction=OUT(借出)、未收齐(核销中 / 部分核销)的借款单。
- ❌ 不适用:借入单(IN,走归还链路)→ 599310;已收齐核销单 → 599308;待付款未放款单 → 599302。
- ⚠️ 特殊:amount 收齐该单余额时本单转已核销(
settledLoanIds含本单 id);未收齐则保持核销中(settledLoanIds为空),可再次调用收回剩余。
10. 修改前后对比
新增接口,无修改前版本。与原「按单位合并收款」的关系:
| 维度 | 按单位合并收款(§1.4.3) | 单笔收回(本接口) |
|---|---|---|
| 入口 | 勾选同单位多笔合并 | 单笔直接收 |
| 入参 | unitId + items[](多单填额) | path id + 单 amount |
| 还款流水 | 多单逐笔 | 单笔一条 |
| 共用 | — | 与本接口共用 settle 核心,守卫一致 |
11. 影响评估 / 回滚
- 是否破坏向后兼容:否(纯新增端点)。
- 前端是否必须同步上线:否(前端可在「公司借款支付」已付款行接入本接口实现单笔收款登记;不接入不影响既有合并收款)。
- 回滚方式:revert PR #8670 即可下线本端点,无数据迁移、无缓存清理。
12. 注意事项
- 原型/菜单侧:收回原型入口已并入「支付管理 / 公司借款支付」已付款台账行「收款登记」;原「收款管理 / 公司借款收回」按单位汇总收银台原型入口已下线。前端实现管理后台时,单笔收款登记建议挂在已付款借出单行(只有已付款台账能收回)。
- 提交后请禁用按钮防连点(非幂等,重复提交会重复入账)。
- 合并收款三端点后端保留可用,如未来仍提供按单位合并入口可继续用 §1.4.1-1.4.3。
13. 关联 / 联系人
- Issue: #8664
- PR: #8670
- Merge commit: 11a61d3739
- 后端负责人: @yst