Files
hfb_sys/backend/internal/modules/payment/refund_cumulative_test.go
T
yml2213 36ebe7a5f1 fix(distribution): 结算幂等与退款口径加固,补关单释放与回归测试
- 结算明细加唯一键 (order_id, party_id):自动释放与手工批次并发时以唯一键冲突为准跳过该参与方,不再重复入账
- 自动释放先无锁筛出本站未入账参与方,收敛加锁范围;手工批次建批次后先锁周期内财务快照,与自动释放串行化
- 累计退款额改为「本次回调金额与已退款成功流水合计取较大值」,多笔退款与退款结果重复回调不再把口径写小
- 关单三路径(AdminClose / AdminRejectRefund 的 close 分支 / AdminSeal)补写 release_at,接线原死代码 EnsureCompletedReleaseAtTx
- 仲裁分销重算改用实际退款额(扣除押金暂扣),避免站点被多扣
- 订单列表与详情的提价分成取 min(收入, 货架加价),退款压缩加价后不再显示负数
- 新增迁移 000070(结算明细唯一键)、000071(补回填 closed 订单释放时间)
- 新增 5 个测试文件:结算幂等与展示钳制、结算 job 幂等、累计退款、关单补写释放时间、仲裁押金暂扣口径
2026-09-10 19:13:39 +08:00

97 lines
3.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package payment
import (
"testing"
"time"
"hfb_sys/backend/internal/model"
"hfb_sys/backend/internal/modules/distribution"
)
// TestUpdateOrderRefundStatusUsesCumulativeRefundedAmount 断言同一订单多笔退款时,
// 单笔回调传入的金额不会把订单累计退款额写小,分销财务快照按合计口径重算。
func TestUpdateOrderRefundStatusUsesCumulativeRefundedAmount(t *testing.T) {
db := setupPaymentTestDB(t)
repo := NewRepository(db, nil, nil)
now := time.Now()
site := model.DistributionSite{
SiteCode: "cum_site", SiteName: "累计退款站", Domain: "cum.dist.com",
Status: "active", DisplayAccountEnabled: true,
}
if err := db.Create(&site).Error; err != nil {
t.Fatal(err)
}
rule := model.DistributionRuleVersion{
SiteID: &site.ID, Mode: distribution.ModeTwoPartyPlatformReceive, Version: 1, Status: "active",
PlatformReceiveRatio: 35, DistributorSellRatio: 40, ServiceFeeValue: 0,
ServiceFeeUnit: distribution.ServiceFeeUnitFixedAmount, PaymentFeeBPS: 0,
EffectiveFrom: now.Add(-time.Hour),
}
if err := db.Create(&rule).Error; err != nil {
t.Fatal(err)
}
order := model.RentalOrder{
OrderNo: "ORD-CUM-REFUND", ListingID: 1, AccountID: 1, OwnerID: 1, RenterID: 2,
Status: "completed", RentAmountCent: 10000, OwnerRentAmountCent: 6000,
DistributionSiteID: &site.ID, DistributionRuleVersionID: &rule.ID,
}
if err := db.Create(&order).Error; err != nil {
t.Fatal(err)
}
if err := distribution.SnapshotPaidOrderTx(db, order.ID, 10000); err != nil {
t.Fatal(err)
}
// 两笔已退款成功流水:300 + 700 = 1000。
refunds := []model.PaymentOrder{
{PaymentNo: "REF-CUM-1", OrderID: order.ID, OrderNo: order.OrderNo, UserID: order.RenterID, Provider: "mock", ThirdOrderID: "REF-CUM-1", AmountCent: 300, BizType: "admin_refund", Status: "refunded"},
{PaymentNo: "REF-CUM-2", OrderID: order.ID, OrderNo: order.OrderNo, UserID: order.RenterID, Provider: "mock", ThirdOrderID: "REF-CUM-2", AmountCent: 700, BizType: "rent_refund", Status: "refunded"},
}
if err := db.Create(&refunds).Error; err != nil {
t.Fatal(err)
}
// 只传其中一笔金额调用:累计口径应取两笔合计 1000。
if err := repo.updateOrderRefundStatus(t.Context(), order.ID, 300, "admin_refund"); err != nil {
t.Fatal(err)
}
var saved model.RentalOrder
if err := db.First(&saved, order.ID).Error; err != nil {
t.Fatal(err)
}
if saved.RefundAmountCent != 1000 {
t.Fatalf("order.RefundAmountCent = %d, want 1000(两笔退款合计)", saved.RefundAmountCent)
}
if saved.RefundStatus != "refunded" {
t.Fatalf("order.RefundStatus = %s, want refunded", saved.RefundStatus)
}
var financial model.DistributionOrderFinancial
if err := db.Where("order_id = ?", order.ID).First(&financial).Error; err != nil {
t.Fatal(err)
}
if financial.RefundAmountCent != 1000 || financial.NetPaidAmountCent != 9000 || financial.SplitBaseAmountCent != 3000 {
t.Fatalf("分销快照未按累计退款重算:refund=%d netPaid=%d splitBase=%d",
financial.RefundAmountCent, financial.NetPaidAmountCent, financial.SplitBaseAmountCent)
}
var party model.DistributionOrderParty
if err := db.Where("order_id = ? AND party_role = ?", order.ID, "distributor_sell").First(&party).Error; err != nil {
t.Fatal(err)
}
if party.IncomeAmountCent != 1200 {
t.Fatalf("分站份额 = %d, want 1200(利润 3000 的 40%%)", party.IncomeAmountCent)
}
// 退款结果查询重复回调不应把累计额写小。
if err := repo.updateOrderRefundStatus(t.Context(), order.ID, 300, "admin_refund"); err != nil {
t.Fatal(err)
}
if err := db.First(&saved, order.ID).Error; err != nil {
t.Fatal(err)
}
if saved.RefundAmountCent != 1000 {
t.Fatalf("重复回调后 order.RefundAmountCent = %d, want 1000(单调不回退)", saved.RefundAmountCent)
}
}