34 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-company-loan-module-onboarding | 公司借款域全量上线(12 接口:登记/详情/借入到账/收回收银台/归还收银台/还款流水/操作流水 + 出纳 COMPANY_LOAN 新付款线) | admin | yst(GIT) | 新增接口 | deployed | verified | verified | mmg | 15e3d7dd906e5e738e70c279360caf8ac03e509d | 2026-09-17 | 财务域公司借款模块首次整模块交付:双向 OUT 借出 / IN 借入,登记制四态(APPROVED 已登记 → PAID 已收付 → SETTLING 核销中 → SETTLED 已核销,无独立审批)。含登记、详情、借入到账确认、按单位聚合收回(OUT,支持部分收回)、整笔归还(IN)、还款流水分页、操作流水 12 个新端点;出纳侧新增 COMPANY_LOAN 付款类型(借出放款进待付款队列,金额锁死=借款金额)。后端 4 PR 已合并 dev-v3 并部署测试服,E2E 已真实跑通。前端此前无公司借款任何页面,按本文一次对接即可。 前端 hl-admin 2026-09-17 done:api 12 端点封装+公司借款页(列表/登记/详情/确认到账)+收回/归还收银台抽屉+出纳 COMPANY_LOAN 页签薄壳,ReviewLogPane 词表并集扩本域五码;菜单待后端 sys_menu 落地后可见。 | 2026-09-17 | dev-v3 |
公司借款域全量上线(管理后台)
服务: hl-order-service-v3(hl-finance 模块) 类型: 🆕 整模块新增(本期新交付,前端首次对接) 日期: 2026-09-17 影响范围: 管理后台财务域「公司借款」菜单 + 出纳支付管理「公司借款」页签 覆盖 Epic: #7845(PR-1 #7846 地基+登记链 / PR-2 #7848 出纳放款+借入到账 / PR-3 #7850 收回·归还收银台 / PR-4 #7851 操作流水+文档)
一、接口背景
公司借款 = 公司与外部往来单位(本期恒为供应商)之间的资金拆借。两个方向:
- OUT 借出:公司把钱借给单位 → 出纳放款 → 到期按单位聚合收回(可部分多次)
- IN 借入:公司向单位借钱 → 财务确认借入到账 → 到期按单位整笔归还(勾选即还欠还全额)
业务闭环(登记制,无独立审批,登记即生效 APPROVED):
登记 POST /admin/finance/company-loans ──▶ APPROVED(已登记)
│
├─ OUT 借出:出纳支付管理队列放款 POST /admin/finance/cashier/pay (bizType=COMPANY_LOAN)
│ APPROVED → PAID(落 CASHIER_PAY 操作流水 + 资金流水 OUT)
└─ IN 借入:借款详情页确认到账 POST /{id}/confirm-inbound
APPROVED → PAID(落 CONFIRM_INBOUND 操作流水 + 资金流水 IN)
│
├─ OUT 收回:收回收银台 单位聚合 → 勾选填额 → POST /recover/settle(支持部分收回)
└─ IN 归还:归还收银台 单位聚合 → 勾选整笔 → POST /repay-cashier/settle(每笔还欠还全额)
│
按 SUM(repay) 现算状态:0 < 已收/还 < 借款金额 → SETTLING(核销中)
已收/还 ≥ 借款金额 → SETTLED(已核销,终态)
二、变更清单
| # | 变更 | 类型 | 说明 |
|---|---|---|---|
| 1 | GET /admin/finance/company-loans/page |
✨ 新增 | 公司借款分页(状态/方向/单位/关键字筛选) |
| 2 | POST /admin/finance/company-loans |
✨ 新增 | 登记借款(登记即 APPROVED) |
| 3 | GET /admin/finance/company-loans/{id} |
✨ 新增 | 借款单详情(全字段 + 还款流水 + 余额现算) |
| 4 | POST /admin/finance/company-loans/{id}/confirm-inbound |
✨ 新增 | 借入到账确认(仅 IN 单) |
| 5 | GET /admin/finance/company-loans/{id}/review-logs |
✨ 新增 | 操作流水(登记/到账/放款/收回/归还留痕) |
| 6 | GET /admin/finance/company-loans/recover/units |
✨ 新增 | 收回收银台-单位聚合(OUT) |
| 7 | GET /admin/finance/company-loans/recover/units/{unitId} |
✨ 新增 | 收回收银台-单位待收回明细 |
| 8 | POST /admin/finance/company-loans/recover/settle |
✨ 新增 | 合并收款(收回,仅 OUT,支持部分) |
| 9 | GET /admin/finance/company-loans/repay-cashier/units |
✨ 新增 | 归还收银台-单位聚合(IN) |
| 10 | GET /admin/finance/company-loans/repay-cashier/units/{unitId} |
✨ 新增 | 归还收银台-单位待归还明细 |
| 11 | POST /admin/finance/company-loans/repay-cashier/settle |
✨ 新增 | 整笔归还(仅 IN,每笔还欠还全额) |
| 12 | GET /admin/finance/company-loans/repays/page |
✨ 新增 | 还款流水分页(收回/归还共用) |
| 13 | GET /admin/finance/cashier/queue?payType=COMPANY_LOAN |
🔧 修改 | 出纳待付款队列新增 COMPANY_LOAN 付款类型(仅 OUT 借出且 APPROVED 单进队列) |
| 14 | POST /admin/finance/cashier/pay(bizType=COMPANY_LOAN) |
🔧 修改 | 出纳登记付款新增公司借款借出放款业务线,金额锁死=借款金额 |
| 15 | 资金流水 bizType 枚举 |
✨ 新增值 | 新增 COMPANY_LOAN(资金流水按 bizType=COMPANY_LOAN&bizId 可串联借款单) |
三、接口详情
| 项 | 说明 |
|---|---|
| 使用场景 | 管理后台财务域「公司借款」模块(列表/详情/登记/收银台)+ 出纳支付管理「公司借款」页签 |
| 认证 | 管理后台 JWT(网关统一鉴权),需财务域菜单权限 |
| 幂等性 | 登记/收付/收回/归还均非幂等写:重复提交由状态机守卫拦截——登记靠单号 uk 撞号重试;收付后状态已非 APPROVED,重试被 599302 拦;收回/归还对 SETTLED 单重试被 599308 拦、超额被 599309 拦(锁内现算余额,整体回滚不留半截) |
| 限流 | 走网关统一限流,无模块特殊限流 |
| 单号规则 | 借款单号 GS- + yyyyMMdd + 4 位序号(OUT/IN 共用前缀,靠 direction 徽标区分);还款流水号 GH- + yyyyMMdd + 4 位序号 |
| ID 序列化 | 所有 Long 型 ID(id / unitId / handlerStaffId / fundAccountId / repayIds 等)序列化为 String,防 JS 精度丢失 |
四、接口入参
4.1 GET /admin/finance/company-loans/page 公司借款分页
Query 入参(继承 PageParam:pageNo / pageSize 必填):
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
status |
String | 否 | 单据状态单值:APPROVED / PAID / SETTLING / SETTLED;空=全部 |
statuses |
String[] | 否 | 状态多值 IN 查询(如 statuses=APPROVED&statuses=PAID);非空时优先于 status |
direction |
String | 否 | 方向:OUT 借出 / IN 借入;空=不限 |
unitId |
Long | 否 | 往来单位ID 精确;空=不限 |
keyword |
String | 否 | 关键字(借款单号 / 往来单位名称模糊);空=不限 |
4.2 POST /admin/finance/company-loans 登记借款
请求体 CompanyLoanCreateReqVO:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
direction |
String | ✅ | 方向:OUT 借出 / IN 借入(其他值 → 599302) |
unitType |
String | 否 | 往来单位类型(字典 fin_unit_type;本期恒 SUPPLIER,空按 SUPPLIER 处理,其他值 → 599304) |
unitId |
Long | ✅ | 往来单位ID(供应商;后端反查可付款性并落全称快照,查不到/不可选 → 599304) |
unitName |
String | 否 | 契约兼容字段,服务端反查覆盖,前端传值不生效(≤200 字) |
handlerStaffId |
Long | ✅ | 经办人 adminId(后端反查 wechatName 落姓名快照;查不到/无真名/用户域降级 → 599305) |
handlerStaffName |
String | 否 | 契约兼容字段,服务端反查覆盖,前端传值不生效(≤64 字) |
amount |
BigDecimal | ✅ | 借款金额(>0,否则 599303;不计息) |
feeRate |
BigDecimal | 否 | 手续费率‰(登记参考值,空按 0;实际手续费在收付环节定) |
loanDate |
Date | 否 | 借款日期(yyyy-MM-dd) |
dueDate |
Date | ✅ | 约定归还日期(yyyy-MM-dd) |
purpose |
String | ✅ | 借款用途(≤200 字) |
4.3 GET /admin/finance/company-loans/{id} 借款单详情
路径参数:id(Long,借款单ID,必填)。不存在(含已软删)→ 599301。
4.4 POST /admin/finance/company-loans/{id}/confirm-inbound 借入到账确认
路径参数:id(必填)。仅 direction=IN 单可调(OUT 单 → 599310);状态须 APPROVED(否则 599302)。
请求体 CompanyLoanInboundConfirmReqVO:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
fundAccountId |
Long | ✅ | 入账资金账户ID(fin_fund_account;不存在 595001 / 已停用 595006) |
actualAmount |
BigDecimal | ✅ | 实际到账金额(>0 且 ≤ 借款金额,否则 599311;与借款金额差额 = 到账手续费) |
本端点不收到账凭证影像(契约无 voucherUrl)。
4.5 GET /admin/finance/company-loans/{id}/review-logs 操作流水
路径参数:id(必填,不存在 → 599301)。无 Query 入参。按操作发生时间升序返回,无记录返回空数组 []。
4.6 GET /admin/finance/company-loans/recover/units 收回收银台-单位聚合
Query 入参:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
unitName |
String | 否 | 单位名模糊;空=全部 |
只聚合 direction=OUT 且状态 PAID/SETTLING(未核销)的借出单。
4.7 GET /admin/finance/company-loans/recover/units/{unitId} 单位待收回明细
路径参数:unitId(Long,必填)。返回该单位名下全部未核销借出单(余额现算 + 逾期标记),供勾选合并收款。
4.8 POST /admin/finance/company-loans/recover/settle 合并收款(收回)
请求体 CompanyLoanRecoverSettleReqVO:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
unitId |
Long | ✅ | 往来单位ID(勾选单须全部属该单位,否则 599312 整体回滚) |
items |
Item[] | ✅ | 勾选明细(≥1 条) |
items[].loanId |
Long | ✅ | 借款单ID |
items[].amount |
BigDecimal | ✅ | 本次收回金额(>0 且 ≤ 该单余额,超额 → 599309 整体回滚) |
fundAccountId |
Long | ✅ | 入账资金账户ID(595001/595006) |
feeRate |
BigDecimal | 否 | 手续费率‰(默认 0,负值 → 599303) |
voucherUrl |
String | 否 | 收款凭证影像URL |
金额口径:fee = Σ勾选填额 × feeRate / 1000;实收 = Σ − fee。资金流水合并单笔 IN(amount=实收,biz_id=首笔还款流水ID)。
4.9 GET /admin/finance/company-loans/repay-cashier/units 归还收银台-单位聚合
Query 入参同 4.6(unitName 模糊,可空)。只聚合 direction=IN 且 PAID/SETTLING 的借入单。
4.10 GET /admin/finance/company-loans/repay-cashier/units/{unitId} 单位待归还明细
路径参数:unitId(必填)。返回该单位名下未核销借入单,勾选即整笔还 outstandingAmount 全额(不支持部分归还)。
4.11 POST /admin/finance/company-loans/repay-cashier/settle 整笔归还
请求体 CompanyLoanRepaySettleReqVO:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
unitId |
Long | ✅ | 往来单位ID(勾选单须全部属该单位,否则 599312) |
loanIds |
Long[] | ✅ | 勾选整笔归还的借入单ID列表(≥1;每笔还其欠还全额,不填金额) |
fundAccountId |
Long | ✅ | 出账资金账户ID(595001/595006;余额不足透支闸 595103) |
feeRate |
BigDecimal | 否 | 手续费率‰(默认 0,负值 → 599303) |
voucherUrl |
String | 否 | 付款凭证影像URL |
金额口径:fee = Σ欠还全额 × feeRate / 1000;实付 = Σ + fee(注意:归还侧手续费是外加,与收回侧内扣相反)。资金流水合并单笔 OUT(结存 −Σ−fee)。
4.12 GET /admin/finance/company-loans/repays/page 还款流水分页
Query 入参(继承 PageParam:pageNo / pageSize 必填):
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
loanId |
Long | 否 | 借款单ID 精确;空=不限 |
unitId |
Long | 否 | 往来单位ID;空=不限 |
direction |
String | 否 | OUT 借出(行=收回)/ IN 借入(行=归还);空=不限 |
repaidAtStart |
Date | 否 | 收/还日期起(含,yyyy-MM-dd) |
repaidAtEnd |
Date | 否 | 收/还日期止(含,yyyy-MM-dd) |
4.13 出纳既有接口(COMPANY_LOAN 调用方式)
队列:GET /admin/finance/cashier/queue?payType=COMPANY_LOAN&pageNo=1&pageSize=10(出参结构不变,见 §五.13)。
放款:POST /admin/finance/cashier/pay,请求体 CashierPayReqVO(既有结构):
| 字段 | 必填 | 公司借款场景取值 |
|---|---|---|
bizType |
✅ | 固定 COMPANY_LOAN |
bizId |
✅ | 借款单ID(仅 direction=OUT 且 status=APPROVED;IN 单 → 599310) |
payAccountId |
✅ | 出账公司账户ID |
payMethod |
否 | 字典 fin_pay_way:CASH / BANK / THIRD_PARTY |
payChannel |
否 | WXPAY / ALIPAY(仅 payMethod=THIRD_PARTY 时传) |
amount |
✅ | 金额锁死 = 借款金额,不等 → 598610 |
fee |
否 | 手续费(≥0,挂出账流水) |
voucherNo / voucherUrl |
否 | 付款凭证号 / 凭证影像 URL |
payDate |
✅ | 付款日期(yyyy-MM-dd,可回溯补录) |
operatorName |
否 | 后端忽略,统一取当前登录人快照 |
五、出参字段
5.1 分页行 CompanyLoanRowRespVO(接口 1,Result<PageResult<行>>)
| 字段 | 类型 | 说明 |
|---|---|---|
id |
String | 借款单ID |
loanNo |
String | 借款单号(GS- 前缀) |
direction |
String | OUT 借出 / IN 借入 |
unitType |
String | 往来单位类型(本期恒 SUPPLIER) |
unitId |
String | 往来单位ID |
unitName |
String | 往来单位名称快照 |
handlerStaffId |
String | 经办人 adminId |
handlerStaffName |
String | 经办人姓名快照 |
amount |
BigDecimal | 借款金额 |
repaidAmount |
BigDecimal | 已收/还金额(repay 汇总现算) |
outstandingAmount |
BigDecimal | 待收/还余额 = amount − repaidAmount |
purpose |
String | 借款用途 |
loanDate |
Date | 借款日期 |
dueDate |
Date | 约定归还日期 |
status |
String | APPROVED / PAID / SETTLING / SETTLED |
operatorId |
String | 登记人 adminId(created_by 反查) |
operatorName |
String | 登记人真名(反查降级可为 null,仅展示) |
createTime |
DateTime | 创建时间 |
5.2 登记响应 CompanyLoanCreateRespVO(接口 2)
| 字段 | 类型 | 说明 |
|---|---|---|
id |
String | 新借款单ID(状态 APPROVED) |
loanNo |
String | 借款单号(GS-) |
5.3 详情 CompanyLoanDetailRespVO(接口 3)
在 5.1 全部字段基础上增加:
| 字段 | 类型 | 说明 |
|---|---|---|
feeRate |
BigDecimal | 手续费率‰(登记参考值) |
fundAccountId |
String | 出/入账资金账户ID(仅 PAID 及之后有值) |
paidAt |
DateTime | 收付讫业务时间(仅 PAID 及之后有值) |
approvalInstanceId |
String | 审批实例ID(登记制无审批,恒 null) |
repays |
RepayItem[] | 还款流水(按收/还时间倒序;未发生收还前空数组) |
repays[] 子项 CompanyLoanRepayItem:
| 字段 | 类型 | 说明 |
|---|---|---|
id |
String | 还款流水ID |
repayNo |
String | 还款单号(GH- 前缀) |
direction |
String | 随主单:OUT(本行=收回)/ IN(本行=归还) |
amount |
BigDecimal | 本次收/还金额 |
fundAccountId |
String | 收/付资金账户ID |
voucherUrl |
String | 收/还凭证影像URL |
repaidAt |
DateTime | 收/还时间 |
5.4 借入到账确认(接口 4)
Result<Void>,成功无返回体(data=null)。
5.5 操作流水行 FinReviewLogRespVO(接口 5,Result<List<行>>,升序)
| 字段 | 类型 | 说明 |
|---|---|---|
logId |
String | 流水ID |
action |
String | 操作动作:REGISTER 登记 / CONFIRM_INBOUND 借入到账 / CASHIER_PAY 出纳放款 / RECOVER 收回 / REPAY 归还(公司借款词表,与 #7801 六域审核词表 APPROVE/REJECT/RETURN/UN_APPROVE 不同) |
operatorId |
String | 操作人ID(无登录上下文快照可为空) |
operatorName |
String | 操作人姓名快照 |
opinion |
String | 操作意见/备注(可空) |
fromStatus |
String | 操作前状态(登记 REGISTER 时为 null) |
toStatus |
String | 操作后状态 |
createTime |
DateTime | 操作发生时间 |
5.6 收回单位聚合行 CompanyLoanRecoverUnitRespVO(接口 6,Result<List<行>>)
| 字段 | 类型 | 说明 |
|---|---|---|
unitId |
String | 往来单位ID |
unitName |
String | 往来单位名称快照 |
loanCount |
Integer | 未核销借出单笔数 |
totalOutstanding |
BigDecimal | 待收回余额合计 |
nearestDueDate |
Date | 最近到期日(MIN(due_date)) |
5.7 单位待收回明细行 CompanyLoanRecoverItemRespVO(接口 7)
| 字段 | 类型 | 说明 |
|---|---|---|
loanId |
String | 借款单ID |
loanNo |
String | 借款单号 |
amount |
BigDecimal | 借款金额 |
repaidAmount |
BigDecimal | 已收回合计(现算) |
outstandingAmount |
BigDecimal | 待收回余额(填额上限) |
dueDate |
Date | 约定归还日期 |
overdue |
Boolean | 是否已逾期(dueDate < 今日且未核销) |
5.8 合并收款响应 CompanyLoanRecoverSettleRespVO(接口 8)
| 字段 | 类型 | 说明 |
|---|---|---|
totalAmount |
BigDecimal | 本次收回合计(Σ 勾选填额) |
actualAmount |
BigDecimal | 实收 = totalAmount − fee |
fee |
BigDecimal | 手续费(= totalAmount × feeRate/1000) |
repayIds |
String[] | 生成的还款流水ID(逐笔) |
settledLoanIds |
String[] | 本次余额归零转 SETTLED 的借款单ID(前端可据此局部刷新行状态) |
5.9 归还单位聚合行 CompanyLoanRepayUnitRespVO(接口 9)
字段与 5.6 完全对称(unitId / unitName / loanCount / totalOutstanding / nearestDueDate),仅语义为「待归还」。
5.10 单位待归还明细行 CompanyLoanRepayCashierItemRespVO(接口 10)
字段与 5.7 完全对称(loanId / loanNo / amount / repaidAmount / outstandingAmount / dueDate / overdue);outstandingAmount = 勾选后整笔还的全额。
5.11 整笔归还响应 CompanyLoanRepaySettleRespVO(接口 11)
| 字段 | 类型 | 说明 |
|---|---|---|
totalAmount |
BigDecimal | 本次归还合计(Σ 勾选单欠还全额) |
actualPayAmount |
BigDecimal | 实付 = totalAmount + fee(手续费外加) |
fee |
BigDecimal | 手续费(= totalAmount × feeRate/1000) |
repayIds |
String[] | 生成的还款流水ID(逐笔) |
settledLoanIds |
String[] | 余额归零转 SETTLED 的借款单ID |
5.12 还款流水行 CompanyLoanRepayRowRespVO(接口 12,Result<PageResult<行>>)
| 字段 | 类型 | 说明 |
|---|---|---|
id |
String | 还款流水ID |
repayNo |
String | 归还/收回单号(GH- 前缀) |
loanId |
String | 关联借款单ID |
loanNo |
String | 关联借款单号 |
direction |
String | 随主单:OUT(本行=收回)/ IN(本行=归还) |
unitName |
String | 往来单位名称快照 |
amount |
BigDecimal | 本次归还/收回金额 |
fundAccountId |
String | 收/付资金账户ID |
repaidAt |
DateTime | 归还/收回时间 |
voucherUrl |
String | 凭证影像URL |
5.13 出纳队列行 CashierQueueRowRespVO(接口 13,既有结构)
COMPANY_LOAN 行的关键取值(其余字段沿用既有定义):
| 字段 | COMPANY_LOAN 取值 |
|---|---|
id / bizNo |
借款单ID / 借款单号(GS-) |
payType |
COMPANY_LOAN |
payTypeName |
公司借款 |
unitId / unitName |
往来单位ID / 名称快照 |
category |
固定值 公司借款 |
categoryName |
同 category(公司借款) |
amount |
借款金额(放款金额锁死基准) |
fee |
0(放款手续费在 pay 时登记) |
actualAmount |
= amount − fee |
operatorName |
经办人姓名快照 |
status |
队列内恒 APPROVED |
occurDate / remark |
借款日期 / 借款用途 |
六、枚举 / 数据字典
6.1 方向 direction
| 值 | 中文 | 说明 |
|---|---|---|
OUT |
借出 | 公司借钱给单位;出纳队列放款;收回走 recover 收银台 |
IN |
借入 | 公司向单位借钱;confirm-inbound 确认到账;归还走 repay-cashier 收银台 |
6.2 单据状态 status(四态,登记制无审批)
| 值 | 中文 | 进入条件 |
|---|---|---|
APPROVED |
已登记 | 登记成功即此态(无独立审批) |
PAID |
已收付 | OUT=出纳放款完成 / IN=借入到账确认完成 |
SETTLING |
核销中 | 0 < SUM(repay) < amount(部分收/还) |
SETTLED |
已核销 | SUM(repay) ≥ amount(终态,一次还满则 PAID→SETTLED 直达) |
6.3 操作流水动作 action(公司借款词表)
| 值 | 中文 | fromStatus → toStatus |
|---|---|---|
REGISTER |
登记 | null → APPROVED |
CONFIRM_INBOUND |
借入到账 | APPROVED → PAID(仅 IN) |
CASHIER_PAY |
出纳放款 | APPROVED → PAID(仅 OUT) |
RECOVER |
收回 | PAID/SETTLING → SETTLING/SETTLED(仅 OUT) |
REPAY |
归还 | PAID/SETTLING → SETTLING/SETTLED(仅 IN) |
6.4 出纳付款类型 FinCashierPayTypeEnum(本次新增值)
| 值 | 中文 | 单号前缀 | 进付款队列 |
|---|---|---|---|
COMPANY_LOAN 🆕 |
公司借款 | GS- | ✅(仅 direction=OUT 且 APPROVED 单) |
(既有值 NONBIZ / EXPENSE / PAYMENT / PREPAY / STAFF_LOAN / REIMBURSE / ADVANCE 不变;ADVANCE 仍 queueVisible=false 不进队列。)
6.5 资金流水 bizType 新增值
COMPANY_LOAN —— 公司借款相关的全部真金白银落点(放款 OUT / 到账 IN / 收回 IN / 归还 OUT)均以此 bizType + bizId 串联,资金流水列表可按 bizType=COMPANY_LOAN 过滤。
6.6 数据字典
| 字典 | 用途 |
|---|---|
fin_unit_type |
往来单位类型(本期恒 SUPPLIER 供应商) |
fin_pay_way |
付款方式(出纳 pay:CASH / BANK / THIRD_PARTY) |
七、错误码
7.1 公司借款新段位 599301-599312(owner=hl-finance)
| 码 | 常量 | 消息 | 触发场景 |
|---|---|---|---|
| 599301 | COMPANY_LOAN_NOT_FOUND | 借款单不存在 | 详情/流水/收付/收回/归还操作的借款单不存在(含已软删) |
| 599302 | COMPANY_LOAN_STATUS_ILLEGAL | 借款单状态或方向不允许此操作 | 状态机守卫:如对 PAID 单再次 confirm-inbound、对 APPROVED 单收回 |
| 599303 | COMPANY_LOAN_AMOUNT_INVALID | 借款金额无效(须大于0) | 登记 amount≤0;settle feeRate 为负 |
| 599304 | COMPANY_LOAN_UNIT_INVALID | 往来单位不存在或不可选 | unitId 查不到/不可付款/资源域降级/unitType 非 SUPPLIER |
| 599305 | COMPANY_LOAN_HANDLER_INVALID | 经办人非法(不存在或未登记真名) | handlerStaffId 查不到/wechatName 空/用户域降级 |
| 599306 | COMPANY_LOAN_NO_CONFLICT | 借款单号生成冲突,请重试 | GS- 取号撞号重试 3 次耗尽 |
| 599307 | COMPANY_LOAN_REPAY_NO_CONFLICT | 还款单号生成冲突,请重试 | GH- 取号撞号重试 3 次耗尽 |
| 599308 | COMPANY_LOAN_ALREADY_SETTLED | 借款单已核销,不允许再收/还 | 对 SETTLED 终态单收回/归还 |
| 599309 | COMPANY_LOAN_REPAY_EXCEED | 收/还金额超过借款剩余余额 | 收回填额 > 该单锁内现算余额(整体回滚,不静默截断) |
| 599310 | COMPANY_LOAN_DIRECTION_ILLEGAL | 借款单方向与该操作不匹配 | IN 单走出纳放款 / OUT 单 confirm-inbound / IN 单收回 / OUT 单归还 |
| 599311 | COMPANY_LOAN_INBOUND_AMOUNT_INVALID | 到账金额须大于0且不超过借款金额 | confirm-inbound actualAmount 越界 |
| 599312 | COMPANY_LOAN_UNIT_MISMATCH | 勾选借款单与所选单位不一致 | settle 勾选单含其他单位的单(整体回滚) |
7.2 复用既有码
| 码 | 消息 | 触发场景 |
|---|---|---|
| 598601 | 业务单不存在 | 出纳 pay 的 bizId 查不到借款单 |
| 598602 | 业务单状态非已批准,不可付款 | 出纳 pay 时单据已非 APPROVED(含并发推进) |
| 598604 | 账户余额不足且不允许透支 | 出纳放款出账账户余额不足(595103 在出纳域边界的翻译) |
| 598610 | 付款金额与单据应付金额不一致(出纳付款须严格按审批应付金额,不得修改) | 出纳 pay amount ≠ 借款金额(金额锁死) |
| 595001 | 账户不存在 | fundAccountId/payAccountId 查不到 |
| 595006 | 账户已停用 | 资金账户状态非 ACTIVE |
| 595103 | 账户余额不足且不允许透支 | 归还 settle 出账账户余额不足(本域直接透出,不翻译) |
八、示例
8.1 典型成功:IN 借入全链路(登记 → 到账 → 整笔归还)
① 登记 POST /admin/finance/company-loans
{
"direction": "IN",
"unitId": 8801,
"handlerStaffId": 12,
"amount": 50000.00,
"dueDate": "2026-12-31",
"purpose": "旺季房费周转",
"loanDate": "2026-09-17",
"feeRate": 0
}
响应:
{ "code": 0, "data": { "id": "1932700112233445567", "loanNo": "GS-202609170001" }, "msg": "" }
② 借入到账确认 POST /admin/finance/company-loans/1932700112233445567/confirm-inbound
{ "fundAccountId": 101, "actualAmount": 50000.00 }
响应 { "code": 0, "data": null };状态 APPROVED→PAID,落 CONFIRM_INBOUND 操作流水。
③ 归还收银台单位明细 GET /admin/finance/company-loans/repay-cashier/units/8801
{
"code": 0,
"data": [
{
"loanId": "1932700112233445567",
"loanNo": "GS-202609170001",
"amount": 50000.00,
"repaidAmount": 0.00,
"outstandingAmount": 50000.00,
"dueDate": "2026-12-31",
"overdue": false
}
]
}
④ 整笔归还 POST /admin/finance/company-loans/repay-cashier/settle
{
"unitId": 8801,
"loanIds": [1932700112233445567],
"fundAccountId": 101,
"feeRate": 1,
"voucherUrl": "https://oss.example.com/voucher/gh001.png"
}
响应(fee = 50000 × 1/1000 = 50,实付 50050):
{
"code": 0,
"data": {
"totalAmount": 50000.00,
"actualPayAmount": 50050.00,
"fee": 50.00,
"repayIds": ["1932700998877665544"],
"settledLoanIds": ["1932700112233445567"]
}
}
状态 PAID→SETTLED(一次还满直达终态)。
8.2 边界情况:OUT 借出部分收回 + 到账金额小于借款额 + 空流水
① 借入到账差额(到账手续费):借款 50000,实际到账 49800(差额 200 视为到账手续费,合法):
{ "fundAccountId": 101, "actualAmount": 49800.00 }
→ 200 OK,资金流水 IN 记 49800。
② OUT 单部分收回(借款 50000,先收 20000):POST /admin/finance/company-loans/recover/settle
{
"unitId": 8801,
"items": [{ "loanId": 1932700112233445566, "amount": 20000.00 }],
"fundAccountId": 101,
"feeRate": 0
}
响应:totalAmount=20000 / actualAmount=20000 / fee=0 / settledLoanIds=[],状态 PAID→SETTLING(余额 30000 未清)。
③ 无操作流水(异常空态):GET /admin/finance/company-loans/{id}/review-logs 无记录时返回空数组:
{ "code": 0, "data": [] }
(正常单据至少有 REGISTER 一条。)
④ 详情未收付前:fundAccountId=null / paidAt=null / repays=[] / approvalInstanceId=null。
8.3 业务失败:最小复现
① 方向不匹配(599310):对 OUT 借出单调借入到账:
POST /admin/finance/company-loans/{OUT单id}/confirm-inbound
Content-Type: application/json
{ "fundAccountId": 101, "actualAmount": 100.00 }
{ "code": 599310, "data": null, "msg": "借款单方向与该操作不匹配" }
② 收回超额(599309):余额 30000 的单填 30001:
{ "unitId": 8801, "items": [{ "loanId": 1932700112233445566, "amount": 30001.00 }], "fundAccountId": 101 }
{ "code": 599309, "data": null, "msg": "收/还金额超过借款剩余余额" }
③ 出纳放款金额未锁死(598610):借款 50000 的单按 49999 付款:
{ "bizType": "COMPANY_LOAN", "bizId": 1932700112233445566, "payAccountId": 101, "amount": 49999.00, "payDate": "2026-09-17" }
{ "code": 598610, "data": null, "msg": "付款金额与单据应付金额不一致(出纳付款须严格按审批应付金额,不得修改)" }
九、业务边界
适用场景
- 公司与供应商之间的资金拆借登记与核销(借出收回 / 借入归还)
- 收回支持部分多次(同一单位多笔单可合并一次收款,逐笔填额)
- 归还为整笔(勾选即还该单欠还全额,不支持部分归还——这是产品设计,非缺陷)
不适用场景
- 员工个人借款 → 走「员工借款」模块(fin_staff_loan,接口前缀
/admin/finance/staff-loans),不要混用 - 需要审批流的借款 → 本域登记制无审批,登记即生效
- 跨单位合并结算 → 一次 settle 只能勾同一 unitId 的单(599312)
特殊边界
- SETTLED 为终态:已核销单不再出现在收回/归还收银台(聚合与明细接口都只出 PAID/SETTLING 单)
- 一次还满直达 SETTLED:PAID 单一次收/还满额时状态 PAID→SETTLED,不经 SETTLING
- 方向锁死动作:OUT 单只进出纳付款队列 + recover 收银台;IN 单只走 confirm-inbound + repay-cashier 收银台,交叉一律 599310
- 逾期仅展示:overdue=true 不阻断收回/归还,仅列表标记
- 余额现算不存列:repaidAmount/outstandingAmount 由 fin_company_loan_repay 实时 SUM,页面刷新即最新
十、修改前后对比(出纳既有接口)
10.1 GET /admin/finance/cashier/queue 出参变化
| 项 | 原来 | 现在 |
|---|---|---|
payType 枚举值 |
NONBIZ / EXPENSE / PAYMENT / PREPAY / STAFF_LOAN / REIMBURSE / ADVANCE(预留) | 新增 COMPANY_LOAN(公司借款,queueVisible=true) |
category 固定值映射 |
PREPAY=「预付款」/ STAFF_LOAN=「员工借款」/ REIMBURSE=「报账款」 | 新增 COMPANY_LOAN=固定值「公司借款」 |
| 队列数据源 | 6 条已接通业务线 | +1 条:fin_company_loan(direction=OUT 且 status=APPROVED) |
字段零增删,仅枚举值扩充——前端按 payType 建字典/页签的需补 COMPANY_LOAN 一项。
10.2 POST /admin/finance/cashier/pay 行为变化
| 项 | 原来 | 现在 |
|---|---|---|
bizType 可选值 |
NONBIZ / EXPENSE / PAYMENT / PREPAY / STAFF_LOAN / REIMBURSE | +COMPANY_LOAN |
| COMPANY_LOAN 金额基准 | ——(不存在) | 锁死 = 借款金额 amount(不等 → 598610) |
| COMPANY_LOAN 方向红线 | —— | 仅 direction=OUT;IN 单 → 599310(借入到账走本域 confirm-inbound,不进出纳) |
10.3 资金流水 bizType 枚举
| 原来 | 现在 |
|---|---|
| NONBIZ / EXPENSE / PAYMENT / PREPAY / STAFF_LOAN / REIMBURSE 等 | +COMPANY_LOAN(放款/到账/收回/归还四种资金动作共用) |
十一、影响评估 / 回滚
| 项 | 评估 |
|---|---|
| 破坏兼容 | 否。12 个端点全部新增;出纳侧仅枚举值扩充 + 新路由分支,既有 payType 行为零变化 |
| 前端同步上线 | 无需同步——前端无公司借款页面时不影响任何既有功能;新页面按本文对接后上线即可 |
| 数据库 | 新建 3 表(fin_company_loan / fin_company_loan_repay / fin_company_loan_review_log),无存量表/存量数据变更,Flyway V20260917_108 部署自动执行 |
| 菜单配置 | 后端需配 sys_menu:财务域「公司借款」页 + 出纳支付管理「公司借款」页签(以后端菜单 SQL 落地为准) |
| 回滚方案 | 代码回滚到 PR-1 前即可(新端点 404、队列不再出 COMPANY_LOAN 行);3 张新表为增量,无存量依赖时可 DROP TABLE fin_company_loan_review_log, fin_company_loan_repay, fin_company_loan; 并清理 flyway_schema_history 对应行(需 DBA 操作,正常不需要) |
十二、注意事项
- unitName / handlerStaffName 前端传值不生效:登记时服务端按 unitId / handlerStaffId 反查覆盖快照(防乱传),前端只需传 ID;展示用快照名,单位/人员改名不追溯。
- 收回与归还手续费方向相反:收回 fee 内扣(实收=合计−fee);归还 fee 外加(实付=合计+fee)。前端金额预览区不要套错公式。
- action 词表勿复用六域审核字典:公司借款操作流水是 REGISTER/CONFIRM_INBOUND/CASHIER_PAY/RECOVER/REPAY,与 #7801 六域(APPROVE/REJECT/RETURN/UN_APPROVE)是两套词表,VO 虽同为 FinReviewLogRespVO,action 展示字典要分开。
- GS- 单号 OUT/IN 共用:列表/详情必须用 direction 徽标区分方向,不能只凭单号前缀判断。
- Long ID 全部 String 序列化:前端按字符串处理,勿转 Number(精度丢失)。
- 金额锁死:出纳放款 amount 必须等于借款金额,前端付款弹窗金额框应只读回填队列行 amount。
- settledLoanIds 局部刷新:settle 响应已给出本次转 SETTLED 的单ID,收银台明细列表可据此直接移除对应行,不必整表重查。
- confirm-inbound 不收凭证:借入到账确认无 voucherUrl 字段,凭证在后续归还环节才登记。
十三、关联 / 联系人
- 父 Issue: https://git.1814.love:8443/wx/HL/issues/7845
- PR-1 地基+登记链: https://git.1814.love:8443/wx/HL/pulls/7846 | commit https://git.1814.love:8443/wx/HL/commit/f2ed775962
- PR-2 出纳放款+借入到账: https://git.1814.love:8443/wx/HL/pulls/7848 | commit https://git.1814.love:8443/wx/HL/commit/c5c0c0672e
- PR-3 收回/归还收银台: https://git.1814.love:8443/wx/HL/pulls/7850 | commit https://git.1814.love:8443/wx/HL/commit/7e238c211f
- PR-4 操作流水+文档: https://git.1814.love:8443/wx/HL/pulls/7851 | commit https://git.1814.love:8443/wx/HL/commit/d2fbfd0846
- 后端负责人: 腰苏图(yst)