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
7398
应付款已付超额冲正(供应商退回):申请 / 分次确认到账 / 撤销剩余额度 / 分页
admin
jw(GIT)
新增接口
deployed
verified
verified
mmg
0fa6574f9cceb2f41f5e4208424ce64190da2014
2026-09-17
后端交付(hl-finance,随 hl-order-service-v3 部署)。新增 4 个冲正接口与错误码 598814/598815/598816/598817/598818;付款明细新增 REVERSAL 负明细语义;资金流水新增 bizType=PAYMENT_REVERSAL。网关前缀 /admin/finance/** 已存在,无需新路由。前端需新增冲正申请与出纳确认到账两个界面。[mmg 2026-09-17 交付] 原型无冲正 UI,以后端契约为准嵌入应付款模块:①payable.js 冲正节 4 端点+四态字典(分页路径无 /page 后缀,598814-818 等拦截器透 message);②可冲正额=reversibleAmount(netPaidAmount− amount 2dp,非 − diffAmount,unpaidAmount 不参与,≥0.01 才显入口);③ReversalApplyModal 申请弹窗(sourceRefKey 原样回传、amount 预填可冲正额、reason 必填,文案明示确认到账后生效);④PaymentReversalPanel 冲正管理(orderId/supplierId/status 筛选分页,PENDING/PARTIAL 出确认到账/撤销,确认六字段含 ACTIVE 公司户下拉+默认今天+凭证号必填);⑤三处申请入口(ap-detail 构成明细+两建单面板超额行),统计页头部「冲正管理」进新视图返回强制刷新。api spec +5 例+组件 spec 11 例,scoped checkpoint 13 项全绿。
2026-09-17
dev-v3
finance: 应付款已付超额冲正(供应商退回)
存放目录 : changelogs-v2/{YYYY-MM}/(管理后台,二期 finance)
服务 : hl-order-service-v3( hl-finance 模块同进程)
PR : #7889
Issue : #7398
日期 : 2026-09-17
影响范围 : 应付款团期住宿付款身份的「已付超出当前应付」处置(申请冲正 → 出纳登记到账 → 统计与建议自动对平)
关键变化(给前端 mmg 的一句话)
598812 有出口了 :团期住宿某付款身份「已付 > 当前应付」时(统计 status=OVERPAID、建议行 netPaidAmount > amount),财务可发起冲正申请 ,额度 ≤ netPaidAmount − amount。
申请不改任何金额 :申请后统计、建议、再建单的结果都与申请前一样;只有出纳确认到账后 才生效。
确认到账可分次 :酒店分几次退就登记几次,每次一条入账流水 + 一条负明细;剩下不再退的额度可以撤销 ,已登记的部分保留。
确认到账不看当前应付 :钱已经到了就必须能记进来,哪怕房又加回来、应付回升;应付回升产生的新欠付照常在建议里以差额行出现。
统计读法不变 : paidAmount(原始已付,不减少)/ refundedAmount(已确认退款)/ netPaidAmount(净已付)三字段 #7396 已有,冲正确认后自动变化。
凭证号必填且在同一申请内唯一 :重复提交同一次确认返回 598802,账户只入账一次。
一、背景
#7396 让团期住宿按付款身份 {orderId}:{stayDate}:{hotelId}:{roomTypeId} 做金额对账,但「钱已付出、应付降到已付之下」只能报 598812,没有处理终态。本次补上「供应商退回」形态:申请 = 批准冲正额度,出纳每登记一次真实到账,就记一条资金流水(入账)和一条挂在原付款单下的负明细,原付款单不做任何修改。「抵扣下次付款」形态依赖预付域,本次不做。
二、变更接口清单
#
接口
方法
路径
变更类型
说明
1
申请冲正
POST
/admin/finance/payment-reversals
新增
对已付超额的团期住宿付款身份申请退回额度,落 PENDING
2
确认本次到账
PUT
/admin/finance/payment-reversals/{id}/confirm
新增
出纳登记一次真实到账(可分次),记入账流水 + 负明细
3
撤销剩余额度
PUT
/admin/finance/payment-reversals/{id}/cancel
新增
作废未到账的剩余额度,已确认部分保留
4
冲正申请分页
GET
/admin/finance/payment-reversals
新增
按订单 / 供应商 / 状态过滤
三、接口详情
1. 申请冲正 POST /admin/finance/payment-reversals
VO : PaymentReversalCreateReqVO → Result<PaymentReversalIdRespVO>
使用场景
建议行或按团统计显示某团期住宿付款身份已付超出当前应付(status=OVERPAID / netPaidAmount > amount),财务与酒店协商退回后发起申请。sourceRefKey 取建议行的 sourceRefKey,orderId 取建议行 / 统计行的 orderId。
入参字段表
字段
位置
类型
必填
约束
说明
sourceRefType
Body
String
是
本期仅 GROUP_BATCH_STAY
来源类型
sourceRefKey
Body
String
是
≤96;格式 {orderId}:{yyyy-MM-dd}:{hotelId}:{roomTypeId},其中订单须等于 orderId
付款身份业务键
orderId
Body
Long
是
-
来源订单 ID
amount
Body
BigDecimal
是
≥0.01,两位小数,≤ 净已付 − 当前应付
申请冲正额度
reason
Body
String
是
≤512,非空白
冲正原因
出参字段表
字段
类型
说明
data.id
String
新冲正申请 ID(雪花 ID,字符串输出)
请求示例
响应示例
空数据 / 降级响应
无查询数据。申请成功后不产生资金流水、不写付款明细;统计、建议、再建单的结果与申请前逐字段相同(再建单仍 598812)。
错误响应
code
触发
400
必填缺失 / amount ≤ 0 / 长度超限
598808
sourceRefType 不是 GROUP_BATCH_STAY,或 sourceRefKey 格式非法 / 与 orderId 不一致
598814
amount > 净已付 − 当前应付(未超额时可冲正额为 0;已全额退回后再申请同样命中)
598815
同一付款身份已有未完结申请(PENDING / PARTIAL)
100503
同订单付款写操作正在进行,稍后重试
业务边界
只处理「已付 > 当前应付」;「未付占用超额」仍走 #7396 的删除 / 驳回 / 撤销批准(598813)。
冲正挂在该付款身份下最近一次付讫的原付款单上;原付款单金额、状态、付款时间不变。
同一付款身份同时只允许一张未完结申请。
与付款单创建 / 编辑共用同一把订单锁,并发时串行执行。
2. 确认本次到账 PUT /admin/finance/payment-reversals/{id}/confirm
VO : PaymentReversalConfirmReqVO → Result<Boolean>
使用场景
出纳收到酒店退款回单后登记。酒店分几次退就调几次,每次填本次实际到账金额与入账的公司账户。
入参字段表
字段
位置
类型
必填
约束
说明
id
Path
Long
是
-
冲正申请 ID
amount
Body
BigDecimal
是
≥0.01,两位小数
本次实际到账金额
fundAccountId
Body
Long
是
须为启用中的公司资金账户
入账账户(不会用原付款账户兜底)
receivedDate
Body
String
是
yyyy-MM-dd
到账日期(写入流水备注)
voucherNo
Body
String
是
≤64,非空白;同一申请内唯一
银行回单 / 凭证号
voucherUrl
Body
String
否
≤500
凭证影像 URL(写入流水)
remark
Body
String
否
≤200
备注(写入流水备注)
出参字段表
字段
类型
说明
data
Boolean
恒 true
请求示例
响应示例
空数据 / 降级响应
无查询数据。成功后:申请 confirmedAmount 累加、状态变 PARTIAL(未满额)或 CONFIRMED(满额);资金流水新增一条 direction=IN、bizType=PAYMENT_REVERSAL、bizId=冲正申请ID;付款明细新增一条 itemKind=REVERSAL、金额为负的明细。
错误响应
code
触发
400
必填缺失(含 fundAccountId / voucherNo / receivedDate) / amount ≤ 0
598818
冲正申请不存在
598802
申请已撤销;或同一申请下该凭证号已登记(重复提交);或并发下状态已被推进
598817
累计到账超过申请额度(含已全额确认后再确认)
598816
本次到账超过该付款身份当前净已付
595001 / 595006
入账账户不存在 / 已停用
100503
同订单付款写操作正在进行,稍后重试
业务边界
不复核当前应付 :房务把房加回、应付回升后仍可登记到账;由此产生的欠付在建议里 diffAmount > 0,按 #7396 规则再建单。
任一校验失败整体回滚:不入账、不写明细、不累加额度。
两次不同凭证号的到账并发提交会先后成功;同凭证号只会成功一次。
入账账户余额按本次金额增加,原付款账户不变。
3. 撤销剩余额度 PUT /admin/finance/payment-reversals/{id}/cancel
VO : PaymentReversalCancelReqVO → Result<Boolean>
使用场景
酒店明确不再退款(或应付已恢复、钱没有退)时,作废申请剩余未到账的额度。
入参字段表
字段
位置
类型
必填
约束
说明
id
Path
Long
是
-
冲正申请 ID
reason
Body
String
是
≤512,非空白
撤销原因
出参字段表
字段
类型
说明
data
Boolean
恒 true
请求示例
响应示例
空数据 / 降级响应
无查询数据。成功后状态变 CANCELLED,confirmedAmount 不变,已登记的流水与负明细不变。
错误响应
code
触发
400
reason 缺失或空白
598818
冲正申请不存在
598802
申请已 CONFIRMED 或已 CANCELLED;或与确认并发时确认先完成
业务边界
仅 PENDING / PARTIAL 可撤销;已全额确认的申请不能撤销(已发生的资金事实只能另行红冲,本期不提供)。
与确认并发时只有一个成功。
4. 冲正申请分页 GET /admin/finance/payment-reversals
VO : PaymentReversalPageReqVO → Result<PageResult<PaymentReversalRespVO>>
使用场景
冲正申请列表 / 出纳待确认列表(status=PENDING 或 PARTIAL)。
入参字段表
字段
位置
类型
必填
约束
说明
orderId
Query
Long
否
-
订单 ID
supplierId
Query
Long
否
-
供应商 ID
status
Query
String
否
PENDING / PARTIAL / CONFIRMED / CANCELLED
状态
page
Query
Integer
否
≥1,默认 1
页码
pageSize
Query
Integer
否
1~100,默认 20
每页条数
出参字段表
字段
类型
说明
records[].reversalId
String
冲正申请 ID
records[].reversalNo
String
冲正单号(RF-yyyyMMdd####)
records[].sourceRefType
String
来源类型
records[].sourceRefKey
String
付款身份业务键
records[].orderId
String
订单 ID
records[].teamNo
String
团号快照
records[].supplierId
String
供应商 ID
records[].supplierName
String
供应商全称快照
records[].paymentId
String
被冲的原付款单 ID
records[].amount
BigDecimal
申请额度
records[].confirmedAmount
BigDecimal
累计已确认到账
records[].remainingAmount
BigDecimal
剩余可确认额度(CANCELLED / CONFIRMED 为 0)
records[].status
String
PENDING / PARTIAL / CONFIRMED / CANCELLED
records[].reason
String
冲正原因
records[].appliedBy
String
申请人 ID
records[].appliedByName
String
申请人姓名
records[].cancelReason
String
撤销原因
records[].cancelledBy
String
撤销人 ID
records[].cancelledAt
String
撤销时间
records[].createTime
String
申请时间
total / page / pageSize
Long / Integer / Integer
分页信息
请求示例
响应示例
空数据 / 降级响应
错误响应
业务边界
按申请 ID 倒序(最新在前)。
单次到账明细(入账账户、金额、时间、凭证、经办人)在资金流水查询中按 bizType=PAYMENT_REVERSAL、bizId=reversalId 查看。
四、契约约束与正确调用方式
申请的 sourceRefKey / orderId 必须原样取自建议行或统计行,不要前端拼接。
可冲正额 = 建议行 netPaidAmount − amount(≤0 时不应展示申请入口)。
确认到账时 amount 填本次 实际到账金额,不是申请额;分次到账逐次调用,每次换一个凭证号。
所有 ID 按字符串处理,避免精度丢失。
统计与建议无需新接口:确认后 refundedAmount 增加、netPaidAmount 减少,paidAmount 不变。
五、数据库行为
表
� � � 作
说明
fin_payment_reversal
新建表(V20260917_114)
冲正申请:amount 额度、confirmed_amount 累计到账、status 四态;申请 INSERT,确认 / 撤销按旧值条件更新
fin_payment_item
新增列 reversal_id + 索引 idx_reversal( V20260917_114)
确认时 INSERT 一条 item_kind=REVERSAL、金额为负、payment_id=原付款单、reversal_id=申请、remark=凭证号
fin_fund_flow
INSERT
确认时一条 direction=IN、biz_type=PAYMENT_REVERSAL、biz_id=申请 ID
fin_fund_account
UPDATE balance
入账账户余额 + 本次金额
fin_payment
不变
原付款单任何字段不改
六、边界行为
申请后、到账前:金额口径完全不变,再建单仍 598812。
到账后应付回升:确认照常成功,建议 diffAmount 出现正差额,按 #7396 建单。
部分到账后剩余不退:调撤销;统计中已退部分保留。
合并付款单(一张付多户):冲正只作用于申请的那一户,负明细 orderId 为该户,挂在合并付款单下;另一户统计不变。
已全额确认后不可撤销、不可再确认(598802 / 598817)。
六.5、枚举
冲正申请状态(status)
值
含义
PENDING
待到账
PARTIAL
部分到账
CONFIRMED
全额到账
CANCELLED
已撤销剩余额度
新增取值
字段
新值
含义
付款明细 itemKind
REVERSAL
冲正负明细(金额为负)
资金流水 bizType
PAYMENT_REVERSAL
应付款冲正入账
七、不影响范围
付款单创建 / 编辑 / 提交 / 批准 / 驳回 / 撤销批准 / 出纳付款的入参出参与判据不变。
建议与统计接口结构不变(相关字段 #7396 已提供)。
非团期住宿来源(行程节点 / 配房 / 手工)不支持冲正。
前端:新增「冲正申请」(统计 / 建议超额行入口)与「出纳确认到账」两个界面,由 mmg 承接。
八、测试环境已验证
TEST( https://api.test.1814.love:9443,hl-order-service-v3 = dev-v3@977257515 合并提交之后的构建;真实网关 + 管理员 token),2026-09-17:
场景
结果
迁移
V20260917_114 执行成功;fin_payment_item.reversal_id 与 idx_reversal 存在;新表不含账户 / 到账日 / 凭证列
真实取消户闭环
已付 800、订单已取消应付 0:申请前后建单均 598812;申请 800 → 确认 800 → 入账流水 800、负明细 −800、Σ=0、统计 PAID、建议 overpaid 归零;原付款单逐字段不变
申请不生效
申请后付款明细零新增,建议 / 统计 / 再建单结果与申请前逐字段相同
入账账户
入 Y:Y +800、原付款账户 X 不变;fundAccountId 为空 → 400;停用账户 → 595006 且零流水零明细;重复提交同凭证 → 598802、余额只加一次
上界
超额申请 598814;重复申请 598815;全额确认后再申请 598814、再确认 598817;净已付不足时确认 598816(零流水零明细);已确认 400 再确认 400 → 200
分次到账
800 分两次 400: PARTIAL → CONFIRMED,两条流水两条负明细,统计 800/400/400 → 800/800/0
应付回升
申请后未到账、应付恢复 → 撤销 200、零流水、再建单 598809;已到账、应付恢复 → 确认 200、统计 OWED 欠付 800、差额单 800 → 200;部分到账叠加回升同样可确认,剩余可撤销
退后再建
退完后应付变 400 → 四入口差额 400 → 建单提交后统计欠付 400、在途 400、OWED → 再建 598809 → 付款后 PAID
合并付款
1600 合并单只退户 1:户 1 800/800/0、户 2 800/0/800;负明细挂 1600 主单、订单为户 1;供应商统计已退 +800
并发
同申请并发两次确认 400 均成功、流水恰 2;三次并发恰 2 成功 1 次 598817;并发确认与申请 → 申请 598815;撤销与确认并发 8 轮均恰一方成功(PENDING / PARTIAL 两个分支、CANCELLED / CONFIRMED 两个终态都出现),撤销后已确认部分保留
逐条验收记录见工单 #7398 验收评论。
十、相关文档
关联 / 联系人
链接
Issue : #7398
PR : #7889
关联 : #7396( 598812 的来源)、#7325(团期单户退团 / 取消)
联系人