16 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 | 8507 | 往来期初 ledgerType 新增 SUPPLIER_RECV 供应商应收账套,支撑财务初始化「应收初始化」tab | admin | yst(GIT) | 修改接口 | deployed | verified | implemented | mmg | cdfaf7932a9bf3008760a4b728f2d9fe0ffff421 | v2.1 | 2026-09-29 | POST /admin/finance/opening-balances 的 ledgerType 枚举新增 SUPPLIER_RECV(供应商应收:他欠我们的杂项应收,如押金退还/赔偿款/口车费),配套应收性质字典 fin_recv_nature(DEPOSIT_REFUND/COMPENSATION/CAR_FEE/OTHER)+ 错误码 598409/598410;同时收紧金额方向:SUPPLIER 只认 openingPayable>0,CUSTOMER/SUPPLIER_RECV 只认 openingReceivable>0。测试环境已部署并行为验证通过。前端需新增财务初始化「应收初始化」tab(7 字段表单,字段映射见本文档 §三/§四)。;前端 2026-09-29 已交付:fin-init 新增「供应商应收」tab(7 元素表单,应收性质走 recvNatures 字典不写死,isPrimary=1 默认选中,记账日期只读不传参),CUSTOMER 同步收紧为单应收框,STAFF 维持双向;fin-init spec 21 例全绿 | 2026-09-29 | dev-v3 |
finance:往来期初新增供应商应收账套 SUPPLIER_RECV(应收初始化 tab 对接)(管理后台)
服务: hl-order-service-v3(finance 模块,同进程) PR: #8509、#8513 Issue: #8507
一、接口背景
管理后台「财务初始化」要新增一个**「应收初始化」tab**:记录供应商欠我们的杂项应收(押金退还、赔偿款、口车费等,不走订单流水的零散应收)。
支撑这个 tab,往来期初接口 POST /admin/finance/opening-balances 的账套枚举 ledgerType 新增第三个值 SUPPLIER_RECV(供应商应收)。
原有账套语义不变:
| 账套值 | 中文 | 方向 | 谁欠谁 |
|---|---|---|---|
SUPPLIER |
供应商应付 | 应付 | 我们欠供应商 |
CUSTOMER |
客户应收 | 应收 | 客户欠我们 |
SUPPLIER_RECV ✨ |
供应商应收 | 应收 | 供应商欠我们(本次新增) |
⚠️ 枚举值是
SUPPLIER_RECV(13 字符),不是SUPPLIER_RECEIVABLE(18 字符超列宽,#8511 已改短)。前端写常量时别用长名。
二、变更清单
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|---|---|---|---|---|
| 1 | 往来期初一次录入 | POST | /admin/finance/opening-balances |
修改接口 | ledgerType 新增 SUPPLIER_RECV;金额方向校验收紧(见 §十) |
配套数据源接口(均早已上线,无变更,仅列出供新 tab 对接):供应商下拉 GET /admin/supplier/items/list、应收性质下拉 GET /admin/finance/receipt/options、所属公司下拉 GET /v3/admin/travel-agency/enabled,详见 §4.3 ~ §4.5。
三、接口详情
- 路径:
POST /admin/finance/opening-balances - 认证:网关 JWT(admin)
- 幂等性:否。但同一往来对象同一账套仅可录一次初始期初,重复提交被 598401 拦截(要改金额走「期初调整」),不会产生脏数据
- 限流:无特殊限流
应收初始化(SUPPLIER_RECV)表单最终形态(7 个元素):
| # | 表单元素 | 控件 | 必填 | 提交字段 |
|---|---|---|---|---|
| 1 | 供应商 | 下拉(可搜索) | ✅ | refId + refName |
| 2 | 应收性质 | 下拉 | ✅ | customerCategory(复用此字段存应收性质码值) |
| 3 | 应收金额 | 数字输入 | ✅ | openingReceivable |
| 4 | 所属公司 | 下拉 | ✅ | companyId |
| 5 | 记账日期 | 只读展示 | — | 后端取,前端不传 |
| 6 | 佐证材料 | 图片上传 | ❌ 选填 | evidenceUrl |
| 7 | 备注 | 文本域 | ❌ 选填 | remark(≤ 200 字) |
本 tab 表单上不要出现的元素:
| 不要出现 | 原因 |
|---|---|
| 应付金额框 | 供应商应收账套只有应收方向,openingPayable 不传 |
| 供应商 ID / 名称手填框 | 必须走下拉,ID 与名称由选项带出 |
| 记账日期输入框 | 只读展示,后端取当前未封账账期 startDate 落库 |
四、接口入参
4.1 路径参数 / Query 参数
无。
4.2 请求体字段(SUPPLIER_RECV 账套)
| 字段 | 类型 | 必填 | 说明 | 校验规则 |
|---|---|---|---|---|
ledgerType |
String | ✅ | 账套类型。本 tab 固定传 SUPPLIER_RECV |
枚举,见 §6.1 |
refId |
String | ✅ | 供应商 ID(取下拉项的 supplierId) |
必须是存在的供应商 |
refName |
String | ✅ | 供应商名称(取下拉项的 fullName) |
≤ 128 字 |
customerCategory |
String | ✅ | 应收性质码值(复用该字段,取应收性质下拉的 value) |
必须是应收性质字典 fin_recv_nature 的值,见 §6.2;缺失 → 598409,取值非法 → 598410 |
companyId |
String | ✅ | 所属公司主体 ID(取下拉项的 agencyId) |
必须是启用中的公司主体,否则 598407 |
openingReceivable |
Number | ✅ | 应收期初金额(元) | 必填且 > 0,否则 598405 |
evidenceUrl |
String | ❌ | 佐证材料图片 URL | 可空 / 不传 |
remark |
String | ❌ | 备注 | ≤ 200 字 |
不要传的字段:
| 字段 | 说明 |
|---|---|
openingPayable |
应付期初金额,应收账套(CUSTOMER / SUPPLIER_RECV)不传 |
| 记账日期相关字段 | 请求体里没有记账日期字段,后端自动取当前未封账账期 startDate |
⚠️
refId/companyId后端是 Long 大数(雪花 ID),JSON 序列化为字符串下发;前端 JS 一律当字符串处理,不要Number()转换,防精度丢失。
4.3 供应商下拉数据源
- 路径:
GET /admin/supplier/items/list(资源服务,已上线) - 认证:网关 JWT(admin)
Query 参数(全部选填):
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
status |
String | ❌ | 本表单固定传 ACTIVE(只在用供应商可录期初) |
keyword |
String | ❌ | 名称 / 编号模糊搜索 |
limit |
Integer | ❌ | 默认 50,最大 200 |
响应 data 为数组,每项字段:
| 字段 | 类型 | 说明 |
|---|---|---|
supplierId |
String | 供应商 ID(Long 序列化字符串) |
fullName |
String | 供应商全称(下拉显示用) |
shortName |
String | 简称 |
supplierNo |
String | 供应商编号 |
statusName |
String | 状态中文名 |
取值映射:下拉显示 fullName;选中后提交 refId = supplierId、refName = fullName。
4.4 应收性质下拉数据源
- 路径:
GET /admin/finance/receipt/options(#8501 已上线) - 认证:网关 JWT(admin)
- 入参:无
- 取数:取响应
data.recvNatures数组(每项value/label) - 取值映射:下拉显示
label;选中后提交customerCategory = value。字典fin_recv_nature值见 §6.2
4.5 所属公司下拉数据源
- 路径:
GET /v3/admin/travel-agency/enabled(order-v3,已上线) - 认证:网关 JWT(admin)
- 入参:无
响应 data 为数组,每项字段:
| 字段 | 类型 | 说明 |
|---|---|---|
agencyId |
String | 公司主体 ID(Long 序列化字符串) |
agencyName |
String | 公司名称(下拉显示用) |
isPrimary |
Integer | 是否主体公司:1 = 是,0 = 否 |
取值映射:下拉显示 agencyName;isPrimary = 1 的主体公司默认选中;选中后提交 companyId = agencyId。公司名称由后端自取快照,前端不用传。
4.6 记账日期展示值来源(只读,不入参)
记账日期 = 当前未封账账期的 startDate,后端落库时自动取,前端不传。若表单上要展示该值:
- 路径:
GET /admin/finance/account-periods/page - 取数:取返回列表中
isClosed = 0(未封账)那一行的startDate展示即可
五、出参
| 字段 | 类型 | 说明 |
|---|---|---|
data |
String | 新建期初行 ID(Long 序列化字符串,JS 当字符串处理) |
外层为标准响应包:code / data / message / success。
六、枚举 / 数据字典
6.1 ledgerType(账套类型)
所属字段:请求体 ledgerType | 类型:String | 必填:✅
| 值 | 中文 | 说明 |
|---|---|---|
SUPPLIER |
供应商应付 | 我们欠供应商;只传 openingPayable |
CUSTOMER |
客户应收 | 客户欠我们;只传 openingReceivable |
SUPPLIER_RECV ✨ |
供应商应收 | 供应商欠我们(杂项应收);只传 openingReceivable,且 customerCategory 必填 |
6.2 customerCategory(应收性质,字典 fin_recv_nature)
所属字段:请求体 customerCategory | 类型:String | 必填:✅(SUPPLIER_RECV 账套必填)
| 值 | 中文 | 说明 |
|---|---|---|
DEPOSIT_REFUND |
押金退还 | 供应商应退未退的押金 |
COMPENSATION |
赔偿款 | 供应商应赔付的款项 |
CAR_FEE |
口车费 | 供应商应付的口车费用 |
OTHER |
其他应收 | 其他杂项应收 |
数据源是 §4.4 的
/admin/finance/receipt/options(recvNatures数组),前端不要写死这 4 个值,后端字典加值时下拉自动多一项。
七、错误码
| code | 含义 | 触发场景 | 前端 toast 建议文案 |
|---|---|---|---|
| 598409 | 应收性质必填 | SUPPLIER_RECV 账套未传 customerCategory |
请选择应收性质 |
| 598410 | 应收性质取值非法 | customerCategory 不在应收性质字典内 |
应收性质无效 |
| 598405 | 期初金额未填或 ≤ 0 | openingReceivable 缺失 / 为 0 / 负数 |
请填写正确的应收金额 |
| 598401 | 该往来对象期初已录过 | 同一供应商同账套重复提交(要改走「期初调整」) | 该供应商期初已录入,要改走「期初调整」 |
| 598407 | 所属公司非法或已停用 | companyId 不存在或公司主体已停用 |
所属公司无效 |
| 598403 | 无未封账账期 | 当前没有 isClosed = 0 的账期,无法落记账日期 |
当前无进行中账期 |
| 598406 | 账套非法 | ledgerType 不是 SUPPLIER / CUSTOMER / SUPPLIER_RECV 之一 |
账套须为 SUPPLIER/CUSTOMER/SUPPLIER_RECV |
八、示例
8.1 典型成功
请求:
POST /admin/finance/opening-balances
Authorization: Bearer <admin-token>
Content-Type: application/json
{
"ledgerType": "SUPPLIER_RECV",
"refId": "1834567890123456789",
"refName": "内蒙古某车队有限公司",
"customerCategory": "DEPOSIT_REFUND",
"companyId": "1723456789012345678",
"openingReceivable": 1500.00,
"evidenceUrl": "https://oss.example.com/finance/evidence/x.jpg",
"remark": "2025 年度押金应退未退"
}
响应:
{
"code": 200,
"data": "1956789012345678901",
"message": "成功",
"success": true
}
8.2 边界(佐证、备注均不传,金额最小值)
场景说明:evidenceUrl / remark 选填,最小合法请求 6 个字段;金额边界 0.01。
请求:
{
"ledgerType": "SUPPLIER_RECV",
"refId": "1834567890123456789",
"refName": "内蒙古某车队有限公司",
"customerCategory": "OTHER",
"companyId": "1723456789012345678",
"openingReceivable": 0.01
}
响应:
{
"code": 200,
"data": "1956789012345678902",
"message": "成功",
"success": true
}
8.3 业务失败(应收性质未传,触发 598409)
请求:
{
"ledgerType": "SUPPLIER_RECV",
"refId": "1834567890123456789",
"refName": "内蒙古某车队有限公司",
"companyId": "1723456789012345678",
"openingReceivable": 1500.00
}
响应:
{
"code": 598409,
"data": null,
"message": "应收性质必填",
"success": false
}
其他常见失败:重复提交同一供应商 →
598401;ledgerType拼错(如SUPPLIER_RECEIVABLE长名)→598406。
九、业务边界
- ✅ 适用场景:供应商存在杂项应收(押金退还 / 赔偿款 / 口车费 / 其他)首次录期初,且当前存在未封账账期、所属公司主体启用中。
- ❌ 不适用场景:
- 该供应商已录过本账套期初 → 598401,改金额请走「期初调整」,不要重复提交;
- 无未封账账期 → 598403;
- 所属公司已停用 → 598407。
- ⚠️ 特殊边界:
- 记账日期恒等于当前未封账账期 startDate(后端落库),不可指定历史 / 未来日期;
- 一账套一方向:SUPPLIER_RECV 只录应收,录应付请切「应付初始化」tab(
SUPPLIER账套)。
十、修改前后对比
10.1 字段 / 枚举级对比
| 字段 | 改前 | 改后 |
|---|---|---|
ledgerType |
2 个值:SUPPLIER / CUSTOMER |
3 个值:新增 SUPPLIER_RECV(供应商应收) |
customerCategory |
仅 CUSTOMER 账套使用 | SUPPLIER_RECV 账套复用此字段存应收性质码值(必填,字典 fin_recv_nature) |
10.2 行为级对比(金额方向收紧,本次同步生效)
| 账套 | 改前 | 改后 |
|---|---|---|
SUPPLIER |
应收 / 应付金额校验相对宽松 | 只认 openingPayable > 0,应收方向不传 |
CUSTOMER |
同上 | 只认 openingReceivable > 0,应付方向不传 |
SUPPLIER_RECV |
(不存在) | 只认 openingReceivable > 0,且 customerCategory 必填 |
十一、影响评估 / 回滚
- 是否破坏向后兼容:基本否。
SUPPLIER/CUSTOMER已有表单若本来就按「一账套一方向」正确提交(只传一个方向金额),不受金额方向收紧影响;SUPPLIER_RECV是纯新增枚举值,老代码不传它即可。 - 前端是否必须同步上线:是(针对「应收初始化」tab)。该 tab 未上线前后端能力空转无影响;tab 上线时必须按本文档字段映射对接。
- 影响已有数据:无(无需前端配合的数据迁移)。
- 回滚方案:后端 revert 两个 PR 即可;前端 tab 未上线则无需回滚。
十二、注意事项
- ⚠️ 枚举值是
SUPPLIER_RECV(13 字符),不是SUPPLIER_RECEIVABLE(18 字符超列宽,#8511 已改短)。拼错会触发 598406。 - ⚠️
refId/companyId/ 响应data均为 Long 大数序列化的字符串,JS 全程当字符串处理,禁止Number()转换。 - ⚠️
customerCategory字段在 SUPPLIER_RECV 账套下语义是「应收性质」,值必须来自 §4.4 下拉(字典fin_recv_nature),不要写死 4 个码值。 - ⚠️ 记账日期前端不传;如需展示,查
GET /admin/finance/account-periods/page取isClosed = 0行的startDate。 - ⚠️ 佐证材料
evidenceUrl是选填,不要加必填校验拦截提交。 - 本次已部署测试服并行为验证通过,前端可立即联调。
十三、关联 / 联系人
13.1 链接
- Issue: #8507
- PR: #8509、#8513
- 前置依赖: #8501(应收性质字典 +
/receipt/options接口)、#8511(枚举值改短 SUPPLIER_RECEIVABLE → SUPPLIER_RECV)
13.2 联系人
- 后端负责人: yst