docs(changelog-v2): 应收期初新增供应商应收账套 SUPPLIER_RECV(应收初始化 tab 对接指引)(#8507)
changelog-filename-gate / validate (push) Failing after 2s
changelog-filename-gate / validate (push) Failing after 2s
这个提交包含在:
@@ -0,0 +1,353 @@
|
||||
---
|
||||
schema: "hl-changelog/v2"
|
||||
ticket: "8507"
|
||||
title: "往来期初 ledgerType 新增 SUPPLIER_RECV 供应商应收账套,支撑财务初始化「应收初始化」tab"
|
||||
consumer: "admin"
|
||||
author: "yst(GIT)"
|
||||
change_type: "修改接口"
|
||||
backend_status: "deployed"
|
||||
gateway_status: "verified"
|
||||
frontend_status: "pending"
|
||||
frontend_owner: "mmg"
|
||||
frontend_ref: "pending"
|
||||
target_release: "v2.1"
|
||||
verified_at: "2026-09-29"
|
||||
status_note: "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 字段表单,字段映射见本文档 §三/§四)。"
|
||||
updated_at: "2026-09-29"
|
||||
base: "dev-v3"
|
||||
---
|
||||
|
||||
# finance:往来期初新增供应商应收账套 SUPPLIER_RECV(应收初始化 tab 对接)(管理后台)
|
||||
|
||||
**服务**: hl-order-service-v3(finance 模块,同进程)
|
||||
**PR**: [#8509](https://git.1814.love/wx/HL/pulls/8509)、[#8513](https://git.1814.love/wx/HL/pulls/8513)
|
||||
**Issue**: [#8507](https://git.1814.love/wx/HL/issues/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 典型成功
|
||||
|
||||
**请求**:
|
||||
|
||||
```http
|
||||
POST /admin/finance/opening-balances
|
||||
Authorization: Bearer <admin-token>
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
```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 年度押金应退未退"
|
||||
}
|
||||
```
|
||||
|
||||
**响应**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"data": "1956789012345678901",
|
||||
"message": "成功",
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
### 8.2 边界(佐证、备注均不传,金额最小值)
|
||||
|
||||
**场景说明**:`evidenceUrl` / `remark` 选填,最小合法请求 6 个字段;金额边界 0.01。
|
||||
|
||||
**请求**:
|
||||
|
||||
```json
|
||||
{
|
||||
"ledgerType": "SUPPLIER_RECV",
|
||||
"refId": "1834567890123456789",
|
||||
"refName": "内蒙古某车队有限公司",
|
||||
"customerCategory": "OTHER",
|
||||
"companyId": "1723456789012345678",
|
||||
"openingReceivable": 0.01
|
||||
}
|
||||
```
|
||||
|
||||
**响应**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"data": "1956789012345678902",
|
||||
"message": "成功",
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
### 8.3 业务失败(应收性质未传,触发 598409)
|
||||
|
||||
**请求**:
|
||||
|
||||
```json
|
||||
{
|
||||
"ledgerType": "SUPPLIER_RECV",
|
||||
"refId": "1834567890123456789",
|
||||
"refName": "内蒙古某车队有限公司",
|
||||
"companyId": "1723456789012345678",
|
||||
"openingReceivable": 1500.00
|
||||
}
|
||||
```
|
||||
|
||||
**响应**:
|
||||
|
||||
```json
|
||||
{
|
||||
"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](https://git.1814.love/wx/HL/issues/8507)
|
||||
- **PR**: [#8509](https://git.1814.love/wx/HL/pulls/8509)、[#8513](https://git.1814.love/wx/HL/pulls/8513)
|
||||
- **前置依赖**: [#8501](https://git.1814.love/wx/HL/issues/8501)(应收性质字典 + `/receipt/options` 接口)、[#8511](https://git.1814.love/wx/HL/issues/8511)(枚举值改短 SUPPLIER_RECEIVABLE → SUPPLIER_RECV)
|
||||
|
||||
### 13.2 联系人
|
||||
|
||||
- **后端负责人**: yst
|
||||
在新工单中引用
屏蔽一个用户