文件
hl-api-changelog/changelogs-v2/2026-10/01_8689_核销管理5端点-新增接口-管理后台.md
T
2026-10-02 10:34:34 +08:00

11 KiB
原始文件 Blame 文件历史

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 8689 核销管理后端落地:坏账核销/债务豁免 5 端点(#8689) admin yst(GIT) 新增接口 merged not_required implemented hl-admin(claude-opus-4-8) 01436d457302207d2684584c48c50818936fdecf v2.1 2026-10-02 核销管理(API §6.5 设计稿)本期提前落地。核销=往来账面抹债不动资金(无资金流水、不改账户结存、不过出纳),与支付本质区别:支付是钱真动了,核销只是账认了这笔损失/对冲。本期落地 SUPPLIER 债务豁免(冲减应付)+ CUSTOMER 坏账核销(冲减应收)两类;STAFF 员工·司导往来不做。新增 /admin/finance/writeoffs 5 端点(两页签列表/发起核销/提交审批/批准/驳回)。审批本期本地手工批(企微审批流留 TODO),金额≥阈值(默认 5000)落待审批、<阈值建单即入账。坏账核销只落往来台账留痕、不回改订单侧应收金额。前端已交付(用户拍板已部署立项):新建核销管理页(hiddenRoute 先行,核销审批/核销记录双页签懒加载,批准二次确认+驳回原因必填,LOG 筛选仅用契约 keyword/ledgerType/status 三参,原型类型/日期筛选与页签角标契约无入参不渲染);发起核销弹窗页内+供应商往来账行「核销」两入口共用(账套→类型一对一联动,供应商走档案弹窗带 refId、客户按名聚合不传 refId,阈值分流以响应 needApproval 为准不前端预判);submit 手工批仅守卫不暴露按钮;错误码全走拦截器透 message。页 spec 5 例+弹窗 spec 6 例+供应商往来账 wiring 1 例,21 例全绿。 2026-10-01 dev-v3

finance:核销管理后端落地(坏账核销/债务豁免 5 端点)(管理后台)

PR: #8697 | 服务: hl-order-service-v3(hl-finance 编译其中) | 更新时间: 2026-10-01

1. 接口背景

财务往来账上会有「收不回的应收(坏账)」和「不用付的应付(债务豁免)」,需要从账面轧掉认损。这就是核销。

核销与支付的本质区别:

  • 支付:钱真的动了(产生资金流水、账户结存变动、过出纳)
  • 核销:只是账面抹债——不动资金、无资金流水、不改账户结存、不过出纳,只在该对象的往来台账上记一笔反向对冲行(净额减)

本期落地两类核销:

核销类型 账套 作用
债务豁免 DEBT_WAIVER 供应商 SUPPLIER 冲减应付(不用付了的应付款轧掉)
坏账核销 BAD_DEBT 客户 CUSTOMER 冲减应收(收不回的应收款认损失)

STAFF 员工·司导往来本期不做(该账套属后续 Epic、净往来无来源)。报销冲抵不进本表(走费用域闭环)。

此前核销管理只有设计稿(API §6.5),本次后端正式落地 5 个端点。

2. 变更清单

# 接口 方法 路径 变更类型 说明
1 核销分页(两页签) GET /admin/finance/writeoffs/page 新增 PENDING 待审批 / LOG 全量记录
2 发起核销 POST /admin/finance/writeoffs 新增 建核销单,按金额阈值分流
3 提交审批 POST /admin/finance/writeoffs/{id}/submit 新增 本期本地手工批,仅守卫
4 批准核销 POST /admin/finance/writeoffs/{id}/approve 新增 入账:写台账对冲行
5 驳回核销 POST /admin/finance/writeoffs/{id}/reject 新增 驳回不动账

3. 接口详情

3.1 核销分页(两页签)

  • 使用场景:核销管理页两页签——「待审批」列待批核销单,「核销记录」列全量(已入账+已驳回)
  • 认证:需登录,财务查看权限
  • 入参(Query):
字段 类型 必填 说明
tab String ✅ 页签:PENDING 待审批 / LOG 核销记录(其他值报 596013)
ledgerType String ❌ 账套过滤:SUPPLIER / CUSTOMER
status String ❌ 状态过滤;LOG 页签仅允许 POSTED/REJECTED(传其他报 596013),PENDING 页签忽略
keyword String ❌ 核销单号 / 往来对象名 模糊
pageNo / pageSize int ✅ 分页
  • 出参:PageResult<WriteoffRowRespVO>

3.2 发起核销

  • 使用场景:财务在某往来对象上发起一笔核销
  • 入参(Body,WriteoffCreateReqVO):
字段 类型 必填 说明 校验
ledgerType String ✅ 账套:SUPPLIER / CUSTOMER
writeoffType String ✅ 核销类型:DEBT_WAIVER(SUPPLIER)/ BAD_DEBT(CUSTOMER) 与账套不匹配报 596014
refId Long 见说明 往来对象 ID(SUPPLIER 必填)
refName String ✅ 往来对象名(CUSTOMER 按客户名聚合)
amount BigDecimal ✅ 核销金额 >0(596012)、@Digits(16,2)、≤ 该对象净往来(596001)
reason String ✅ 核销原因
sourceType / sourceId / sourceNo String/Long/String ❌ 来源单据(可选追溯)
  • 分流:金额 < 阈值(默认 5000)→ 直接 POSTED 入账;≥ 阈值 → PENDING_APPROVAL 待审批
  • 出参:WriteoffCreateRespVO(writeoffId / writeoffNo / status / needApproval)

3.3 提交审批

  • 使用场景:≥阈值核销单提交走审批
  • 本期说明:审批为本地手工批(对齐费用/支付),企微审批流留 TODO 不接;submit 仅做状态守卫、状态不变,返回空串实例 ID
  • 入参:路径 id
  • 出参:WriteoffSubmitRespVO(approvalInstanceId 本期恒空串)

3.4 批准核销

  • 使用场景:批准一笔待审批核销 → 入账
  • 动作:PENDING_APPROVAL → POSTED,写一行往来台账反向对冲行(净额减),回写核销单 statement_entry_id + posted_at + 审批人快照
  • 防超额:批准时会重算该对象当前净往来,若 PENDING 期间净额已被其他入账冲减到不够核销,报 596001 不予入账
  • 入参:路径 id

3.5 驳回核销

  • 使用场景:驳回一笔待审批核销(不动账)
  • 动作:PENDING_APPROVAL → REJECTED,记驳回原因 + 审批人快照
  • 入参:路径 id + Body WriteoffRejectReqVO:
字段 类型 必填 说明
reason String ✅ 驳回原因

5. 出参(核销行 WriteoffRowRespVO)

字段 类型 说明
id Long 核销单 ID(字符串化)
writeoffNo String 核销单号(HX- 开头)
ledgerType String 账套 SUPPLIER/CUSTOMER
ledgerTypeName String 账套中文名
writeoffType String 核销类型 DEBT_WAIVER/BAD_DEBT
writeoffTypeName String 核销类型中文名
refId Long 往来对象 ID
refName String 往来对象名
amount BigDecimal 核销金额
reason String 核销原因
status String 状态 PENDING_APPROVAL/POSTED/REJECTED
statusName String 状态中文名
needApproval Integer 是否需审批 0/1
operatorName String 经办人
approverName String 审批人(本期手工批回填)
rejectReason String 驳回原因
postedAt String 入账时间
createTime String 创建时间

6. 枚举 / 数据字典

6.1 ledgerType(账套)

值 中文 说明
SUPPLIER 供应商 应付侧
CUSTOMER 客户 应收侧

6.2 writeoffType(核销类型)

值 中文 适用账套
DEBT_WAIVER 债务豁免 SUPPLIER
BAD_DEBT 坏账核销 CUSTOMER

6.3 status(核销单状态)

值 中文 说明
PENDING_APPROVAL 待审批 ≥阈值待批
POSTED 已入账 已写台账对冲行
REJECTED 已驳回 审批驳回

6.4 tab(页签)

值 中文
PENDING 待审批
LOG 核销记录

7. 错误码

code 含义 触发场景
596001 核销金额超过该对象净往来 发起 / 批准时金额 > 净往来
596002 核销单状态不允许该操作 对非待审批单做 submit/approve/reject
596004 往来对象不存在 供应商/客户查无(SUPPLIER 无任何期初与流水)
596011 核销单不存在 id 查无
596012 核销金额无效须>0 amount ≤0
596013 核销页签非法 / LOG 页签 status 非法 tab 非 PENDING/LOG;LOG 传非 POSTED/REJECTED
596014 核销类型与账套不匹配 SUPPLIER 传 BAD_DEBT / CUSTOMER 传 DEBT_WAIVER
596015 核销单号取号撞号耗尽 HX- 取号并发耗尽(极少)

8. 示例

8.1 典型成功(发起一笔供应商债务豁免,<阈值直接入账)

请求 POST /admin/finance/writeoffs

{ "ledgerType": "SUPPLIER", "writeoffType": "DEBT_WAIVER", "refId": 101, "refName": "嘉世豪酒店", "amount": 800.00, "reason": "供应商同意减免尾款" }

响应

{ "code": 0, "data": { "writeoffId": "1234567890", "writeoffNo": "HX-202610010001", "status": "POSTED", "needApproval": 0 }, "msg": "" }

8.2 边界(金额 ≥ 阈值 → 落待审批)

请求 POST /admin/finance/writeoffs

{ "ledgerType": "CUSTOMER", "writeoffType": "BAD_DEBT", "refName": "张三", "amount": 6000.00, "reason": "客户失联认损" }

响应

{ "code": 0, "data": { "writeoffId": "1234567891", "writeoffNo": "HX-202610010002", "status": "PENDING_APPROVAL", "needApproval": 1 }, "msg": "" }

8.3 业务失败(核销金额超净往来)

响应

{ "code": 596001, "msg": "核销金额超过该对象净往来", "data": null }

9. 业务边界

  • ✅ 核销只动往来账面:在该对象台账记一行反向对冲(净额减)
  • ❌ 核销不产生资金流水、不改账户结存、不过出纳
  • ❌ 坏账核销不回改订单侧应收金额——核销是财务账面认损失,订单应收仍在;CUSTOMER 按客户名聚合校验+回扣已核销防重复
  • ⚠️ 同名客户本期算一起(应收台账行无 customerId),将来补 customerId 后升级按 ID

13. 关联 / 联系人