feat(changelog): 业务外收支接供应商与经办人(#7612) + 员工选择器接口(#7625)
changelog-filename-gate / validate (push) Failing after 2s
changelog-filename-gate / validate (push) Failing after 2s
- 13_7612:业务外收支修改接口(破坏性:删 unitName/加 operatorId 必填/OUT 裁剪 6 字段;出参加 flowNo;含供应商弹窗/部门树/员工选择器/类别/收付方式字典 5 个关联接口对接指引) - 13_7625:新增员工选择器 GET /admin/user/employee-options(不限角色,供经办人下拉)
这个提交包含在:
@@ -0,0 +1,192 @@
|
|||||||
|
---
|
||||||
|
schema: "hl-changelog/v2"
|
||||||
|
ticket: "7612"
|
||||||
|
title: "业务外收支:外部单位接供应商、经办人改选员工、支出裁剪凭证字段、列表关键词、新增业务单号"
|
||||||
|
consumer: "admin"
|
||||||
|
author: "yst"
|
||||||
|
change_type: "修改接口"
|
||||||
|
backend_status: "deployed"
|
||||||
|
gateway_status: "not_required"
|
||||||
|
frontend_status: "required"
|
||||||
|
frontend_owner: ""
|
||||||
|
frontend_ref: ""
|
||||||
|
target_release: ""
|
||||||
|
verified_at: ""
|
||||||
|
status_note: "⚠️ 破坏性变更:入参删 unitName、加 operatorId 必填、支出(OUT)忽略 6 字段;出参加 flowNo。前端业务外收入/业务外支出两个页面须同迭代联动,否则旧前端提交 400。"
|
||||||
|
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)
|
||||||
|
|
||||||
|
## 四、入参(Create;PUT 同构、少 direction)
|
||||||
|
|
||||||
|
| 字段 | 类型 | 必填 | 说明 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| direction | String | ✅ | IN 业务外收入 / OUT 业务外支出(编辑不可改) |
|
||||||
|
| category | String | ✅ | 收支类别码(见关联接口④,按 direction 分组) |
|
||||||
|
| **unitId** | Long(String) | ✅ | 外部单位 = 供应商 ID(供应商弹窗选,见关联接口①) |
|
||||||
|
| **operatorId** | Long(String) | ✅🆕 | 经办人 = 员工 adminId(员工选择器选,见关联接口③) |
|
||||||
|
| amount | BigDecimal | ✅ | 收支金额 >0 |
|
||||||
|
| occurDate | Date | ✅ | 发生日期 yyyy-MM-dd |
|
||||||
|
| deptId | Long(String) | 推荐 | 所属部门(部门树选,见关联接口②;供经办人"属部门"校验) |
|
||||||
|
| feeRate | BigDecimal | 仅 IN | 手续费率 ‰(OUT 忽略) |
|
||||||
|
| fee | BigDecimal | 仅 IN | 手续费(OUT 忽略) |
|
||||||
|
| fundAccountId | Long(String) | 仅 IN | 入/出账公司账户(OUT 忽略) |
|
||||||
|
| payMethod | String | 仅 IN | 收付方式(字典 fin_pay_way,OUT 忽略) |
|
||||||
|
| voucherNo | String | 仅 IN | 凭证号(OUT 忽略) |
|
||||||
|
| voucherUrl | String | 仅 IN | 凭证影像 URL(OUT 忽略) |
|
||||||
|
| remark | String≤200 | 否 | 备注 |
|
||||||
|
|
||||||
|
> ❌ **已删除入参**:`unitName`(后端自动落供应商全称快照,前端不要再传)。
|
||||||
|
> ⚠️ **OUT 方向**:payMethod / voucherNo / voucherUrl / feeRate / fee / fundAccountId 传了也被忽略置 null,前端**支出表单不要渲染这些字段**。
|
||||||
|
|
||||||
|
## 五、出参
|
||||||
|
|
||||||
|
**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(腰苏图)
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
---
|
||||||
|
schema: "hl-changelog/v2"
|
||||||
|
ticket: "7625"
|
||||||
|
title: "员工选择器轻量接口:按部门+关键词查员工 adminId/姓名,不限角色,供业务表单经办人下拉"
|
||||||
|
consumer: "admin"
|
||||||
|
author: "yst"
|
||||||
|
change_type: "新增接口"
|
||||||
|
backend_status: "deployed"
|
||||||
|
gateway_status: "not_required"
|
||||||
|
frontend_status: "required"
|
||||||
|
frontend_owner: ""
|
||||||
|
frontend_ref: ""
|
||||||
|
target_release: ""
|
||||||
|
verified_at: ""
|
||||||
|
status_note: "新增只读接口 GET /admin/user/employee-options,只要求登录、不限制角色(任何登录操作员可用),供财务等业务表单\"经办人/员工选择器\"下拉。替代有角色限制的 GET /admin/user。"
|
||||||
|
updated_at: "2026-09-13"
|
||||||
|
base: "dev-v3"
|
||||||
|
---
|
||||||
|
|
||||||
|
# 员工选择器轻量接口 —— GET /admin/user/employee-options
|
||||||
|
|
||||||
|
> **服务**: hl-user-service
|
||||||
|
> **端**: 管理后台
|
||||||
|
> **类型**: 🆕 新增接口(只读)
|
||||||
|
> **日期**: 2026-09-13
|
||||||
|
> **关联**: Issue #7625 / PR #7627(已合并 dev-v3,已部署测试服)
|
||||||
|
|
||||||
|
## 一、接口背景
|
||||||
|
|
||||||
|
业务表单(如财务"业务外收支/经办人")需要一个"员工选择器"下拉:按部门过滤 + 关键词模糊,返回员工 **adminId + 姓名**,供选定经办人。现有接口都不合适:
|
||||||
|
|
||||||
|
- `GET /admin/user`(管理员列表)**限 SUPER_ADMIN/ADMIN 角色**,其他角色 403,普通操作员不可用。
|
||||||
|
- `GET /admin/wechat/users` 返回的是企微 userid(String),**不含 adminId**。
|
||||||
|
|
||||||
|
故新增本接口:**任何登录操作员都可用**,直接返回业务要用的 adminId + 姓名。
|
||||||
|
|
||||||
|
## 二、接口详情
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /admin/user/employee-options
|
||||||
|
```
|
||||||
|
|
||||||
|
- **鉴权**:只要求登录(网关 token),**不限制角色**(任何登录 admin 可用)。
|
||||||
|
- **性质**:只读查询。
|
||||||
|
|
||||||
|
## 三、入参(Query)
|
||||||
|
|
||||||
|
| 字段 | 类型 | 必填 | 说明 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| deptId | Long(String) | 否 | 部门过滤(传部门树节点 id;员工任一部门命中即返回) |
|
||||||
|
| keyword | String | 否 | 关键词模糊(用户名 / 企微姓名) |
|
||||||
|
| page | Integer | 否 | 页码,默认 1(钳制 [1,100]) |
|
||||||
|
| pageSize | Integer | 否 | 每页条数,默认 20 |
|
||||||
|
|
||||||
|
## 四、出参
|
||||||
|
|
||||||
|
`Result<PageResult<EmployeeOptionRespVO>>`,`records` 项字段:
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|---|---|---|
|
||||||
|
| adminId | String | 员工 adminId(Long 已转 String 防 JS 精度丢失)——业务用它做关联值 |
|
||||||
|
| username | String | 登录名 |
|
||||||
|
| enterpriseWechatName | String | 姓名(企微真名;未绑企微时为 null,可回落 username 显示) |
|
||||||
|
| deptNames | String | 所属部门名(如 "运营部";未绑部门为 null) |
|
||||||
|
|
||||||
|
`PageResult` 含 `total` + `records`。
|
||||||
|
|
||||||
|
## 五、示例
|
||||||
|
|
||||||
|
### 典型·查运营部员工
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /admin/user/employee-options?deptId=35&page=1&pageSize=20
|
||||||
|
→ 200 { "code":200, "message":"成功", "data":{ "total":1, "records":[
|
||||||
|
{ "adminId":"2083457702519873537", "username":"jinwei", "enterpriseWechatName":"金卫", "deptNames":"运营部" } ] } }
|
||||||
|
```
|
||||||
|
|
||||||
|
### 典型·关键词搜姓名
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /admin/user/employee-options?keyword=金&page=1&pageSize=20
|
||||||
|
→ 200 { "code":200, "data":{ "total":1, "records":[ { "adminId":"...", "enterpriseWechatName":"金卫", ... } ] } }
|
||||||
|
```
|
||||||
|
|
||||||
|
### 边界·无该部门员工 / 越界页
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /admin/user/employee-options?deptId=999 → 200 { "code":200, "data":{ "total":0, "records":[] } }
|
||||||
|
GET /admin/user/employee-options?page=999 → 200 { "code":200, "data":{ "total":<总数>, "records":[] } }(越界返空 records,total 保留)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 六、业务边界 / 注意事项
|
||||||
|
|
||||||
|
1. **不限角色**:任何登录操作员可调用,无需 SUPER_ADMIN/ADMIN。
|
||||||
|
2. **按 deptId 筛会漏未绑企微的员工**(其部门归属来自企微同步,未绑企微则无部门数据);如需全员,不传 deptId 用 keyword 搜。
|
||||||
|
3. 出参**不含手机号/敏感信息**,仅 adminId/username/姓名/部门名,属后台内部通讯录性质。
|
||||||
|
4. **典型用法**(经办人下拉):先选部门(部门树 `GET /admin/wechat/departments/tree`)→ 用该 deptId 调本接口过滤本部门员工 → 选中取 `adminId` 传给业务接口(如 nonbiz `operatorId`)。
|
||||||
|
|
||||||
|
## 七、关联 / 联系人
|
||||||
|
|
||||||
|
- Issue:https://git.1814.love:8443/wx/HL/issues/7625
|
||||||
|
- PR:https://git.1814.love:8443/wx/HL/pulls/7627
|
||||||
|
- 消费方示例:业务外收支经办人下拉(changelog `13_7612_业务外收支接供应商与经办人-修改接口-管理后台.md`)
|
||||||
|
- 负责人:yst(腰苏图)
|
||||||
在新工单中引用
屏蔽一个用户