222 行
13 KiB
Markdown
222 行
13 KiB
Markdown
---
|
||
schema: "hl-changelog/v2"
|
||
ticket: "7612"
|
||
title: "业务外收支:外部单位接供应商、经办人改选员工、支出裁剪凭证字段、列表关键词、新增业务单号"
|
||
consumer: "admin"
|
||
author: "yst"
|
||
change_type: "修改接口"
|
||
backend_status: "deployed"
|
||
gateway_status: "not_required"
|
||
frontend_status: "verified"
|
||
frontend_owner: "mmg"
|
||
frontend_ref: "8a9eae337077a3406ffe7d67db0b55e8c40dba0a"
|
||
target_release: ""
|
||
verified_at: "2026-09-13"
|
||
status_note: "⚠️ 破坏性变更:入参删 unitName、加 operatorId 必填、支出(OUT)忽略 6 字段;出参加 flowNo。前端业务外收入/业务外支出两个页面须同迭代联动,否则旧前端提交 400。【前端 2026-09-13 交付 verified】同迭代消费并联动 #7625:外部单位换 SupplierPickerModal 单选可付款供应商(unitName 入参删除改只读回显,后端自动落全称快照);新增 operatorId 必填+员工选择器(与部门树联动过滤本部门员工);部门手录改部门树选择器(deptId 供 598509 属部门校验);OUT 表单/详情裁剪 feeRate/fee/fundAccountId/payMethod/voucherNo/voucherUrl 六字段,列表加 keyword 筛选+flowNo 单号列,IN/OUT 列口径对齐原型(OUT 去手续费/实收/收付方式)。payload 删 unitName 加 operatorId、OUT 不上送六字段。雪花 ID 全程字符串。finance 全域+user 157/157,checkpoint high 13 项(含生产构建)全绿。"
|
||
updated_at: "2026-09-13"
|
||
base: "dev-v3"
|
||
---
|
||
|
||
# 业务外收支 —— 接供应商 + 经办人选员工 + 支出裁剪 + 关键词 + 业务单号
|
||
|
||
> **服务**: hl-order-service-v3(hl-finance 财务模块)
|
||
> **端**: 管理后台
|
||
> **类型**: ⚠️ 修改接口(含破坏性入参变更,前端须同迭代联动)
|
||
> **日期**: 2026-09-13
|
||
> **关联**: Issue #7612 / PR #7619(已合并 dev-v3,已部署测试服)
|
||
|
||
## 一、接口背景
|
||
|
||
业务外收入(IN) / 业务外支出(OUT) 同表同接口、按 `direction` 区分,前端拆两个菜单页签(收款管理/业务外收入、付款管理/业务外支出)。本次把两个原本"手填"的主数据接成真关联,对齐原型裁剪支出字段、补业务单号、加列表关键词。
|
||
|
||
## 二、变更清单
|
||
|
||
1. **外部单位接供应商**:`unitId` 后端硬校验"可付款供应商"(不可付款/不存在 → 598507);`unitName` 改后端自动取供应商全称落快照,**入参 unitName 删除**(前端免填)。
|
||
2. **经办人改选员工**:入参**新增 `operatorId` 必填**(员工 adminId),后端校验存在/在职(598508) + 属于所选部门(598509);不再取登录人自动留痕。
|
||
3. **支出(OUT)裁剪字段**:`payMethod/voucherNo/voucherUrl/feeRate/fee/fundAccountId` 后端强制置 null(对齐原型支出无凭证类字段);IN 保留全字段。
|
||
4. **列表关键词**:page 新增 `keyword`(模糊 单位名 / 业务单号)。
|
||
5. **业务单号**:出参新增 `flowNo`(格式 `WS-yyyyMMdd-XXXX`,创建生成、全局唯一)。
|
||
|
||
## 三、接口详情(路径不变)
|
||
|
||
- 创建 `POST /admin/finance/nonbiz-flows`
|
||
- 编辑 `PUT /admin/finance/nonbiz-flows/{id}`(仅 PENDING;unitId 变化才重新校验供应商)
|
||
- 详情 `GET /admin/finance/nonbiz-flows/{id}`
|
||
- 分页 `GET /admin/finance/nonbiz-flows/page`
|
||
- 提交 `PUT /admin/finance/nonbiz-flows/{id}/submit` | 审批 `PUT /admin/finance/nonbiz-flows/{id}/approve` | 删除 `DELETE /admin/finance/nonbiz-flows/{id}`(仅 PENDING)
|
||
|
||
## 四、入参(一套接口,两个页签)
|
||
|
||
**收入和支出是同一套接口、同一张表,靠 `direction` 区分;前端两个页签(收款管理/业务外收入、付款管理/业务外支出)调的是同一批 URL,只是 `direction` 传不同值、且两个页签的表单字段不一样。** 列出的"收支分类"也按 direction 各自独立一组。
|
||
|
||
| 页签 | direction | 列表/创建调用 |
|
||
|---|---|---|
|
||
| 业务外收入 | `IN` | `GET .../page?direction=IN` | `POST` body 带 `"direction":"IN"` |
|
||
| 业务外支出 | `OUT` | `GET .../page?direction=OUT` | `POST` body 带 `"direction":"OUT"` |
|
||
|
||
> 详情 / 提交 / 审批 / 删除 不带 direction(按 id 操作),两个页签共用。
|
||
|
||
### 4.1 业务外收入(IN)表单字段
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| direction | String | ✅ | 固定 `IN` |
|
||
| category | String | ✅ | 收款分类码(关联接口④ `?direction=IN` 组) |
|
||
| **unitId** | Long(String) | ✅ | 付款单位 = 供应商 ID(供应商弹窗选,关联接口①) |
|
||
| **operatorId** | Long(String) | ✅🆕 | 经办人 = 员工 adminId(员工选择器选,关联接口③) |
|
||
| amount | BigDecimal | ✅ | 本次收款 >0 |
|
||
| occurDate | Date | ✅ | 收款日期 yyyy-MM-dd |
|
||
| deptId | Long(String) | 推荐 | 所属公司/部门(部门树选,关联接口②;供经办人"属部门"校验) |
|
||
| payMethod | String | 否 | 收款方式(字典 fin_pay_way,关联接口⑤) |
|
||
| fundAccountId | Long(String) | 否 | 收款账号(公司资金账户) |
|
||
| feeRate | BigDecimal | 否 | 手续费率 ‰(改动联动重算 fee) |
|
||
| fee | BigDecimal | 否 | 手续费(缺省按费率算,可手改;actualAmount=amount−fee 自动算) |
|
||
| voucherNo | String | 否 | 凭证号 |
|
||
| voucherUrl | String | 否 | 凭证影像 URL |
|
||
| remark | String≤200 | 否 | 备注 |
|
||
|
||
### 4.2 业务外支出(OUT)表单字段
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| direction | String | ✅ | 固定 `OUT` |
|
||
| category | String | ✅ | 付款分类码(关联接口④ `?direction=OUT` 组) |
|
||
| **unitId** | Long(String) | ✅ | 收款单位 = 供应商 ID(供应商弹窗选,关联接口①) |
|
||
| **operatorId** | Long(String) | ✅🆕 | 经办人 = 员工 adminId(员工选择器选,关联接口③) |
|
||
| amount | BigDecimal | ✅ | 本次付款 >0 |
|
||
| occurDate | Date | ✅ | 申请日期 yyyy-MM-dd |
|
||
| deptId | Long(String) | 推荐 | 所属部门(部门树选,关联接口②;供经办人"属部门"校验) |
|
||
| remark | String≤200 | 否 | 付款说明 |
|
||
|
||
> ⚠️ **支出(OUT)没有也不收这些字段**:`payMethod / voucherNo / voucherUrl / feeRate / fee / fundAccountId`——传了后端也强制置 null。**支出表单(对齐原型)只有上表 8 个字段,不要渲染凭证/手续费/账户类字段。**
|
||
|
||
### 通用说明
|
||
|
||
- ❌ **已删除入参**:`unitName`(两个方向都由后端自动落供应商全称快照,前端不要再传)。
|
||
- PUT 编辑入参与 Create 同构、仅少 `direction`(编辑不可换向)。
|
||
- `unitId` 两个方向都接供应商(客户域未就绪,本期 IN/OUT 统一供应商口径)。
|
||
|
||
## 五、出参
|
||
|
||
**Row(分页)**:id、**flowNo🆕**、direction、category、categoryName、unitId、unitName、amount、fee、actualAmount、deptId、operatorName、occurDate、status、payMethod、payMethodName
|
||
|
||
**Detail(详情)** = Row 全字段 + feeRate、fundAccountId、operatorId、voucherNo、voucherUrl、remark、createTime
|
||
|
||
> unitName / operatorName 仍返回(快照值),来源改为后端自动落;`flowNo` 为新增业务单号。出参向后兼容(只增 flowNo,不删字段)。
|
||
|
||
## 六、枚举 / 数据字典
|
||
|
||
| 字段 | 来源 | 取值 |
|
||
|---|---|---|
|
||
| direction | 后端枚举 | IN 业务外收入 / OUT 业务外支出 |
|
||
| status | 后端枚举 | PENDING 草稿 / SUBMITTED 审批中 / APPROVED 已批准 / REJECTED 已驳回 / PAID 已收付讫 |
|
||
| category | 类别接口 | 见关联接口④(IN/OUT 各自一组,取 status=NORMAL) |
|
||
| payMethod | 字典 fin_pay_way | CASH 现金 / BANK_TRANSFER 银行转账 / WECHAT 微信 / ALIPAY 支付宝(仅 IN 用;列表/详情 `payMethodName` 后端已回填中文,**仅下拉**才需调字典接口⑤) |
|
||
|
||
## 七、错误码(HTTP 恒 200,判 code,按 message 原样提示即可)
|
||
|
||
| code | message | 触发 |
|
||
|---|---|---|
|
||
| 598507 | 外部单位不存在或非可付款供应商 | unitId 非可付款供应商 |
|
||
| 598508 | 经办人不存在或非在职状态 | operatorId 非法 / 非 ACTIVE |
|
||
| 598509 | 经办人不属于所选部门 | operatorId 不在 deptId 部门成员内 |
|
||
| 598510 | 业务单号生成冲突,请重试 | 单号并发撞号(前端重试即可) |
|
||
| 598501 / 598502 / 598506 | 金额 / 类别 / 方向 校验(原有) | 见原有定义 |
|
||
|
||
## 八、示例
|
||
|
||
### 典型·新建业务外支出(OUT,无凭证字段)
|
||
|
||
```json
|
||
POST /admin/finance/nonbiz-flows
|
||
{
|
||
"direction": "OUT", "category": "DONATION",
|
||
"unitId": "2098964648031109121", "operatorId": "2083457702519873537",
|
||
"amount": 1000.00, "occurDate": "2026-09-13", "deptId": "35", "remark": "公益活动捐赠"
|
||
}
|
||
→ 200 { "code":200, "message":"成功", "data":{ "id":"2098980881711403010" } }
|
||
详情出参含:flowNo="WS-20260913-0001"、unitName="XX供应商全称"、operatorName="金卫"
|
||
```
|
||
|
||
### 典型·新建业务外收入(IN,含手续费/收付方式)
|
||
|
||
```json
|
||
POST /admin/finance/nonbiz-flows
|
||
{
|
||
"direction": "IN", "category": "RENT",
|
||
"unitId": "2098964648031109121", "operatorId": "2083457702519873537",
|
||
"amount": 5000.00, "feeRate": 6, "fee": 30.00, "fundAccountId": "2095340438490583041",
|
||
"payMethod": "BANK_TRANSFER", "occurDate": "2026-09-13", "voucherNo": "PZ20260913"
|
||
}
|
||
→ 实收 actualAmount = amount − fee = 4970.00(后端联动重算)
|
||
```
|
||
|
||
### 边界·OUT 误传凭证字段(被忽略置 null)
|
||
|
||
```json
|
||
{ "direction":"OUT", ..., "payMethod":"CASH", "voucherNo":"V1", "fee":5 }
|
||
→ 创建成功,但库内 payMethod/voucherNo/fee/fundAccountId 均为 null(前端支出表单不应有这些字段)
|
||
```
|
||
|
||
### 异常·非法供应商 / 经办人不属部门
|
||
|
||
```json
|
||
{ "unitId":"9999999999999999999", ... } → { "code":598507, "message":"外部单位不存在或非可付款供应商" }
|
||
{ "operatorId":"<非本部门员工>", "deptId":"35", ... } → { "code":598509, "message":"经办人不属于所选部门" }
|
||
```
|
||
|
||
## 九、业务边界
|
||
|
||
- 供应商校验口径 = "可付款"(主体 ACTIVE + 有生效账户 + 无资质/协议到期),与应付款同口径;停用/黑名单供应商选不中。
|
||
- 编辑(PUT)仅 PENDING 可改;**unitId 未变不重新校验供应商**(防供应商状态漂移卡死存量草稿),变了才按新供应商硬校验。
|
||
- 经办人 `deptId` 为空时跳过"属部门"校验(宽松,避免误拦无部门账号);传了 deptId 则 operatorId 必须是该部门成员,否则 598509。
|
||
- 业务单号 `flowNo` 创建即定、编辑不重取;格式 `WS-yyyyMMdd-XXXX`(当日序列)。
|
||
|
||
## 十、修改前后对比
|
||
|
||
| 项 | 改前 | 改后 |
|
||
|---|---|---|
|
||
| 外部单位 | 手填 unitId + unitName,不验存在 | 选供应商,后端硬校验 + 自动落 unitName 快照 |
|
||
| 经办人 | 后端自动取登录人 | 入参 operatorId 选员工,校验存在/在职/属部门 |
|
||
| 支出字段 | 含凭证/手续费/账户(超原型) | OUT 忽略 6 字段,对齐原型 |
|
||
| 业务单号 | 无 | flowNo(WS-yyyyMMdd-XXXX) |
|
||
| 列表搜索 | 仅 unitId 精确 | 新增 keyword(单位名/单号模糊) |
|
||
|
||
## 十一、影响评估 / 回滚
|
||
|
||
- **破坏性**:旧前端不传 operatorId → 400;传 unitName → 被忽略;OUT 传凭证字段 → 被忽略。**前端两个页面必须同迭代联动**。
|
||
- 回滚:接口层回退 dev-v3 即可;DDL(fin_nonbiz_flow.flow_no 列)保留无影响。
|
||
|
||
## 十二、关联接口(前端对接数据源,均现成可用)
|
||
|
||
> ③经办人下拉用本期**新增的** `GET /admin/user/employee-options`(见 PR #7627 / changelog `13_7625`),**任何登录操作员都能调**;不要用旧的 `GET /admin/user`(限 SUPER_ADMIN/ADMIN 角色,不可用)。
|
||
|
||
**① 供应商下拉/弹窗** — `GET /admin/supplier/items/page`
|
||
- 入参:page / pageSize / keyword(模糊全称/简称/编码)/ status / typeCode / creditLevel
|
||
- 推荐:`?status=ACTIVE&pageSize=20&keyword=`,选中取 `supplierId` 传 nonbiz `unitId`
|
||
- 出参项:supplierId、supplierNo、fullName、shortName、types、status、statusName、creditLevel、activeAccountCount、contactPhone
|
||
|
||
**② 部门树** — `GET /admin/wechat/departments/tree`
|
||
- 无入参(需登录)。出参树节点:id(String)、label、parentId(根=0)、children
|
||
- 选中节点 `id` 传 nonbiz `deptId`
|
||
|
||
**③ 经办人下拉** — `GET /admin/user/employee-options`(🆕 本期新增,Issue #7625)
|
||
- 入参:deptId(选) / keyword(选,姓名/企微名/用户名模糊) / page / pageSize
|
||
- 出参项:**adminId(String)**、username、enterpriseWechatName(姓名)、deptNames
|
||
- 选中取 `adminId` 传 nonbiz `operatorId`
|
||
- 鉴权:**只要求登录,不限制角色**
|
||
- 建议联动:先选部门(②) → 用该 deptId 调本接口过滤本部门员工 → 选经办人
|
||
|
||
**④ 收支类别下拉** — `GET /admin/finance/nonbiz-categories?direction=IN|OUT`(direction 必填)
|
||
- 出参:code、name、direction、status(NORMAL/DISABLED)、sort;前端取 status=NORMAL
|
||
|
||
**⑤ 收付方式字典** — `GET /admin/dict/data/fin_pay_way`(仅 IN 下拉用)
|
||
- 出参:dictLabel(中文)、dictValue(码)、sortOrder、status;取 status=ACTIVE
|
||
|
||
## 十三、关联 / 联系人
|
||
|
||
- Issue:https://git.1814.love:8443/wx/HL/issues/7612
|
||
- PR:https://git.1814.love:8443/wx/HL/pulls/7619
|
||
- 配套(经办人下拉接口):Issue #7625 / PR #7627 / changelog `13_7625_员工选择器接口-新增接口-管理后台.md`
|
||
- 负责人:yst(腰苏图)
|