--- schema: "hl-changelog/v2" ticket: "7165" title: "业务外收支流水(收入 IN / 支出 OUT 同表两入口)" consumer: "admin" author: "yst" change_type: "新增接口" backend_status: "deployed" gateway_status: "verified" frontend_status: "pending" frontend_owner: "hl-admin" frontend_ref: "" target_release: "" verified_at: "2026-09-06" status_note: "后端已合 dev-v3(hl-finance nonbiz 域)并部署测试服,E2E 验证通过。本期状态机只落 PENDING 草稿;提交/审批端点在 PR #7221 补齐,勾稽联动留 TODO。" updated_at: "2026-09-06" base: "dev-v3" --- # 业务外收支流水 ## 1. 接口背景 财务域「业务外收支」:记录与订单业务无关的公司收支(如利息收入、罚款支出、押金退回等),收入(IN)与支出(OUT)同表同接口、靠 direction 区分,管理后台拆成「业务外收入」「业务外支出」两个菜单页签。单据落库为 PENDING 草稿,本期草稿可编辑/删除;提交与审批流转在后续 PR #7221 补齐。 - 路径前缀:/admin/finance/nonbiz-flows(5 个新端点) - 服务:hl-finance(财务服务) ## 2. 变更清单 | 类型 | 接口 | 说明 | |---|---|---| | 新增 | GET /admin/finance/nonbiz-flows/page | 业务外收支分页(direction 必填区分收入/支出页签) | | 新增 | POST /admin/finance/nonbiz-flows | 业务外收支申请(收入/支出同接口,落 PENDING 草稿) | | 新增 | GET /admin/finance/nonbiz-flows/{id} | 收支单详情(收入/支出通用全字段) | | 新增 | PUT /admin/finance/nonbiz-flows/{id} | 编辑收支草稿(仅 PENDING;direction 不可改) | | 新增 | DELETE /admin/finance/nonbiz-flows/{id} | 删除收支草稿(仅 PENDING,软删) | ## 3. 接口详情 ### 3.1 分页 GET /page - 使用场景:管理后台「业务外收入」「业务外支出」两个菜单共用一个接口,菜单切换 = 换 direction(IN/OUT)。 - 认证:管理后台管理员 Token(Authorization: Bearer admin-token),未登录返 401。 - 幂等性:查询接口,天然幂等。限流:网关默认。 ### 3.2 申请 POST / - 使用场景:财务录入一笔业务外收入或支出,落 PENDING 草稿。 - 认证:同上。幂等性:非幂等(每次创建生成新单据,前端提交后应禁用按钮)。限流:网关默认。 ### 3.3 详情 GET /{id} - 使用场景:列表行点击进详情抽屉/页。 - 认证:同上。幂等:查询接口。限流:网关默认。 ### 3.4 编辑 PUT /{id} - 使用场景:修改 PENDING 草稿的类别/单位/金额/凭证等字段;方向不可改(收入单不能改成支出单)。 - 认证:同上。幂等性:同参数重复提交效果一致。限流:网关默认。 ### 3.5 删除 DELETE /{id} - 使用场景:作废 PENDING 草稿(软删,单据从所有列表消失)。 - 认证:同上。幂等性:重复删除返 598504。限流:网关默认。 ## 4. 接口入参 ### 4.1 分页 Query(NonbizFlowPageReqVO) | 字段 | 类型 | 必填 | 约束 | 说明 | |---|---|---:|---|---| | direction | String | 是 | IN/OUT | 方向:IN 业务外收入 / OUT 业务外支出 | | category | String | 否 | — | 收支类别码(fin_nonbiz_category,按方向分组);空=不限 | | unitId | Number | 否 | — | 外部单位 ID;空=不限 | | status | String | 否 | 见状态枚举 | 单据状态;空=全部 | | occurDateStart | String | 否 | yyyy-MM-dd | 发生日期起 | | occurDateEnd | String | 否 | yyyy-MM-dd | 发生日期止 | | page | Number | 否 | 默认 1 | 页码 | | pageSize | Number | 否 | 默认 20 | 每页条数 | ### 4.2 申请 Body(NonbizFlowCreateReqVO) | 字段 | 类型 | 必填 | 约束 | 说明 | |---|---|---:|---|---| | direction | String | 是 | IN/OUT | 方向 | | category | String | 是 | 不超64字 | 收支类别码,须为 fin_nonbiz_category 同方向组的正常项(598502) | | unitId | Number | 是 | — | 外部单位 ID(本期仅非空校验,存在性校验待往来账域接缝) | | unitName | String | 是 | 不超128字 | 外部单位名(冗余快照) | | amount | Number | 是 | 大于0 | 收支金额(598501) | | feeRate | Number | 否 | 千分率 | 手续费率(默认 0;收入页改动自动重算 fee) | | fee | Number | 否 | 不小于0 | 手续费(收入缺省按费率算、可手改;支出手填;actualAmount 联动重算) | | fundAccountId | Number | 否 | — | 入/出账公司账户 ID(空=批准时仅入账不联动资金结存) | | occurDate | String | 是 | yyyy-MM-dd | 发生日期 | | payMethod | String | 否 | 不超32字 | 收付方式(字典 fin_pay_way 码值) | | deptId | Number | 否 | — | 归属部门 ID(公司主体;用户域部门树) | | voucherNo | String | 否 | 不超64字 | 凭证号 | | voucherUrl | String | 否 | 不超500字 | 凭证影像 URL | | remark | String | 否 | 不超200字 | 备注 | ### 4.3 编辑 Body(NonbizFlowUpdateReqVO) 字段与申请 Body 完全一致,唯不含 direction(方向由单据自身决定,编辑不换方向),见 4.2 表。 ### 4.4 路径参数 | 接口 | 字段 | 类型 | 说明 | |---|---|---|---| | GET/PUT/DELETE /{id} | id | Number | 收支单 ID(路径传数字即可,响应中为字符串) | ## 5. 出参字段 ### 5.1 分页行(NonbizFlowRowRespVO) | 字段 | 类型 | 说明 | |---|---|---| | id | String | 收支单 ID(雪花字符串) | | direction | String | 方向:IN / OUT | | category | String | 收支类别码 | | categoryName | String | 收支类别中文名(取自 fin_nonbiz_category;类别停用不影响历史单据回显) | | unitId | String | 外部单位 ID(雪花字符串) | | unitName | String | 外部单位名快照 | | amount | Number | 收支金额 | | fee | Number | 手续费(挂本单) | | actualAmount | Number | 实收/实付 = amount − fee | | deptId | String | 归属部门 ID(雪花字符串) | | operatorName | String | 经办人姓名快照 | | occurDate | String | 发生日期(yyyy-MM-dd) | | status | String | 单据状态码 | | payMethod | String | 收付方式码值(字典 fin_pay_way) | | payMethodName | String | 收付方式中文名(字典标签,字典缺失时为空) | ### 5.2 详情(NonbizFlowDetailRespVO) 列表行全字段 + 以下增量字段: | 字段 | 类型 | 说明 | |---|---|---| | feeRate | Number | 手续费率(千分率) | | fundAccountId | String | 入/出账公司账户 ID(空=批准时仅入账不联动结存) | | operatorId | String | 经办人 ID(雪花字符串) | | voucherNo | String | 凭证号 | | voucherUrl | String | 凭证影像 URL | | remark | String | 备注 | | createTime | String | 创建时间(yyyy-MM-dd HH:mm:ss) | ### 5.3 申请响应(NonbizFlowIdRespVO) | 字段 | 类型 | 说明 | |---|---|---| | id | String | 新建收支单 ID(PENDING 草稿) | ### 5.4 编辑 / 删除响应 data 为 null(Result),code=200 即成功。 ## 6. 枚举 / 数据字典 ### direction(方向,代码枚举) | 值 | 中文 | |---|---| | IN | 业务外收入 | | OUT | 业务外支出 | ### status(单据状态,代码枚举) | 值 | 中文 | 说明 | |---|---|---| | PENDING | 草稿 | 可编辑可删除(本期创建后唯一状态) | | SUBMITTED | 审批中 | 提交后锁定(流转端点在 PR #7221 补齐) | | APPROVED | 已批准 | 待出纳收付(流转端点在 PR #7221 补齐) | | REJECTED | 已驳回 | 审批驳回 | | PAID | 已收付讫 | 出纳执行完成,终态 | ### category(收支类别,基础数据表 fin_nonbiz_category) - 按类别码传值;类别按方向分组(IN 组 / OUT 组),跨组传值报 598502。 - 类别维护走「业务外收支分类」管理接口(见 09_7052 changelog)。 ### payMethod(收付方式,数据字典 fin_pay_way,dict_type_id=10157) | 码值 | 中文 | |---|---| | CASH | 现金 | | BANK_TRANSFER | 银行转账 | | WECHAT | 微信 | | ALIPAY | 支付宝 | 字典标签由后端回显为 payMethodName,前端列表/详情直接展示,无需自行映射。 ## 7. 错误码(段位 598500-598599) | 错误码 | 含义 | 触发场景 | |---|---|---| | 598501 | 金额无效(收支金额须大于0,且实收/实付不得为负) | amount≤0、fee<0 或 amount−fee<0 | | 598502 | 收支类别不存在或不属于该方向组 | category 不存在 / 跨方向组 / 已停用 | | 598503 | 当前状态不允许此操作,仅草稿可编辑或删除 | 非 PENDING 状态调 PUT/DELETE | | 598504 | 收支单不存在 | 详情/编辑/删除传错 ID(或已软删) | | 598505 | 状态流转非法(提交须草稿态,批准须审批中) | 状态机推进校验(流转端点见 PR #7221 changelog) | | 598506 | 方向非法,须为 IN 或 OUT | direction 传其他值 | ## 8. 示例 ### 8.1 典型成功(录一笔业务外支出) ```http POST /admin/finance/nonbiz-flows Authorization: Bearer Content-Type: application/json { "direction": "OUT", "category": "DEPOSIT_REFUND", "unitId": 2094001122334455667, "unitName": "市文旅局", "amount": 2000.00, "fee": 0, "fundAccountId": 2097009988776655443, "occurDate": "2026-09-05", "payMethod": "BANK_TRANSFER", "deptId": 10086, "voucherNo": "PZ-20260905-01", "voucherUrl": "https://oss.example.com/voucher/pz01.jpg", "remark": "质保金退回" } ``` ```json {"code":200,"message":"成功","success":true,"data":{"id":"2094311122233344455"}} ``` 收入页签分页: ```http GET /admin/finance/nonbiz-flows/page?direction=IN&page=1&pageSize=20&status=PENDING ``` ```json {"code":200,"success":true,"data":{"records":[{"id":"2094311000000000001","direction":"IN","category":"INTEREST","categoryName":"利息收入","unitId":"2094001122334455667","unitName":"某银行","amount":500.00,"fee":0,"actualAmount":500.00,"deptId":"10086","operatorName":"腰苏图","occurDate":"2026-09-01","status":"PENDING","payMethod":"BANK_TRANSFER","payMethodName":"银行转账"}],"total":1,"page":1,"pageSize":20}} ``` ### 8.2 边界情况(可选项全空 / 最小金额) ```json { "direction": "OUT", "category": "FINE", "unitId": 2094001122334455667, "unitName": "交管局", "amount": 0.01, "occurDate": "2026-09-06" } ``` 最小金额 0.01、可选项(feeRate/fee/fundAccountId/payMethod/deptId/voucher*/remark)全省略也可创建;actualAmount 后端按 amount − fee(默认0) 算好返回。空分页:records=[]、total=0,HTTP 200,前端正常渲染空列表。 ### 8.3 业务失败(类别跨方向组 / 编辑非草稿) direction=IN 但传了 OUT 组的类别码: ```json {"code":598502,"message":"收支类别不存在或不属于该方向组","success":false,"data":null} ``` 对非 PENDING 单据调 PUT/DELETE: ```json {"code":598503,"message":"当前状态不允许此操作,仅草稿可编辑或删除","success":false,"data":null} ``` amount=0 时:{"code":598501,"message":"金额无效(收支金额须大于0,且实收/实付不得为负)"}。 ## 9. 业务边界 适用: - 与订单无关的公司收支记账(利息、罚款、押金、捐赠等)。 不适用 / 限制: - 本期(PR #7179)只落 PENDING 草稿 + 草稿编辑/删除;提交/审批流转端点在 PR #7221 补齐(submit/approve),状态机走到 PAID 依赖出纳域 cashier 端点。 - 勾稽联动(批准后联动资金结存、进出纳队列、企微审批)本期未接通(方案 A,留 TODO 接缝);fundAccountId 传了也只是记账引用,不会在批准时自动动账——动账由出纳域执行。 - unitId 本期仅非空校验,不校验外部单位真实存在(待往来账域接缝,Epic #7163)。 - direction 创建后不可改;改方向 = 删草稿重新录。 特殊边界: - fee 收入单缺省按 feeRate(千分率)自动算、可手改覆盖;支出单手填。改 amount/feeRate/fee 后端联动重算 actualAmount。 - 类别停用不删,历史单据 categoryName 正常回显。 ## 10. 注意事项 - 所有雪花 ID 均为字符串,前端按 String 处理,勿转 Number。 - 两个菜单(收入/支出)共用接口,direction 必填,建议菜单切换即重置筛选重新查询。 - payMethodName / categoryName 由后端字典回显,前端不要自己维护码表。 - 新表 fin_nonbiz_flow(Flyway V20260906_102)+ 新字典 fin_pay_way(user-service V20260906_003,dict_type_id=10157),部署顺序先 user-service 后 finance,均部署自动执行。 - 提交/审批端点(PUT /{id}/submit、/{id}/approve)与出纳付款能力见「07_7217_支付管理出纳」changelog。 ## 11. 关联 / 联系人 - Issue:https://git.1814.love:8443/wx/HL/issues/7165 - PR:https://git.1814.love:8443/wx/HL/pulls/7179 - Commit:https://git.1814.love:8443/wx/HL/commit/dc3b306f73 - Epic:https://git.1814.love:8443/wx/HL/issues/7163 - 负责人:腰苏图(yst)