feat(checkout): 修复后置损耗结算全额归号主、支持角色隔离实时试算与全流程UI重构
- fix(pricing): 后置消耗/损耗金额 100% 划归号主收益,超出预收部分平台不抽成,避免被平台费吸收 - feat(checkout): 前端新增结账实时试算预览组件 (CheckoutTrialPreview + useCheckoutSimulator),角色隔离展示(仅见自身收入/退款,屏蔽平台服务费) - refactor(admin): 重构交易全流程时间线 (ProcessTimeline.vue),将平铺挤压指标重构成4大分类仪表盘微型卡片矩阵,升级可视化业务状态流转徽章与阶段色彩主题 - style(admin): 优化支付与交接流水元信息网格布局,防止超宽屏下长单行拉伸
This commit is contained in:
@@ -528,3 +528,146 @@ func TestApplyAdminOrderFiltersSmartRouting(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCalculateCheckoutSettlement_NoPrepaidConsumable_OwnerGetsFullLoss(t *testing.T) {
|
||||
// 原订单无预收消耗品(consumable_price: 0),买家币价 263 元,卖家币价 233 元,平台加价 30 元
|
||||
order := model.RentalOrder{
|
||||
RentAmountCent: 26300,
|
||||
OwnerRentAmountCent: 23300,
|
||||
DepositAmountCent: 10000,
|
||||
AccountSnapshot: datatypes.JSON([]byte(`{
|
||||
"haf_coin_amount": 100000000,
|
||||
"asset_summary": {
|
||||
"price_breakdown": {
|
||||
"buyer_coin_base_price": 263,
|
||||
"seller_coin_base_price": 233,
|
||||
"consumable_price": 0
|
||||
}
|
||||
}
|
||||
}`)),
|
||||
}
|
||||
|
||||
// 结账时,耗币 100M(全额使用,原价 263/233),但号主后置申报了 50 元物资损耗(5000 分)
|
||||
settlement := calculateCheckoutSettlement(order, 5000, 100, 0)
|
||||
|
||||
// 1. 租客实际承担租金 = 纯币 26300 + 损耗 5000 = 31300
|
||||
if settlement.ActualRentAmountCent != 31300 {
|
||||
t.Fatalf("ActualRentAmountCent = %d, want 31300", settlement.ActualRentAmountCent)
|
||||
}
|
||||
|
||||
// 2. 号主租金收益 = 纯币 23300 + 损耗 5000(全额划归号主) = 28300
|
||||
if settlement.OwnerRentIncomeCent != 28300 {
|
||||
t.Fatalf("OwnerRentIncomeCent = %d, want 28300 (号主损耗必须全额划归号主)", settlement.OwnerRentIncomeCent)
|
||||
}
|
||||
|
||||
// 3. 号主总收入必须包含全部损耗
|
||||
if settlement.OwnerIncomeCent != 28300 {
|
||||
t.Fatalf("OwnerIncomeCent = %d, want 28300", settlement.OwnerIncomeCent)
|
||||
}
|
||||
|
||||
// 4. 平台服务费必须保持原加价 3000(30 元),绝不能把号主的 50 元损耗吞掉!
|
||||
if settlement.PlatformFeeCent != 3000 {
|
||||
t.Fatalf("PlatformFeeCent = %d, want 3000 (平台绝不能从号主损耗中抽成)", settlement.PlatformFeeCent)
|
||||
}
|
||||
|
||||
// 5. 打超金额 = 31300 - 26300 = 5000,从押金扣除
|
||||
if settlement.OvershootAmountCent != 5000 {
|
||||
t.Fatalf("OvershootAmountCent = %d, want 5000", settlement.OvershootAmountCent)
|
||||
}
|
||||
// 押金 10000 - 5000 = 5000 退给租客
|
||||
if settlement.DepositRefundCent != 5000 {
|
||||
t.Fatalf("DepositRefundCent = %d, want 5000", settlement.DepositRefundCent)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCalculateCheckoutSettlement_PrepaidConsumableOvershoot_OwnerGetsExcess(t *testing.T) {
|
||||
// 原订单有预收消耗品:买家预收 20 元,号主预收 16 元(平台抽 4 元);纯币 100 / 80
|
||||
order := model.RentalOrder{
|
||||
RentAmountCent: 12000,
|
||||
OwnerRentAmountCent: 9600,
|
||||
DepositAmountCent: 5000,
|
||||
AccountSnapshot: datatypes.JSON([]byte(`{
|
||||
"haf_coin_amount": 100000000,
|
||||
"asset_summary": {
|
||||
"price_breakdown": {
|
||||
"buyer_coin_base_price": 100,
|
||||
"seller_coin_base_price": 80,
|
||||
"consumable_price": 20
|
||||
}
|
||||
}
|
||||
}`)),
|
||||
}
|
||||
|
||||
// 实际消耗品达到 50 元(5000 分),超出预收 30 元(3000 分)
|
||||
settlement := calculateCheckoutSettlement(order, 5000, 100, 0)
|
||||
|
||||
// 号主预收部分 1600 + 超额损耗部分 3000 = 4600;纯币 8000;总号主租金 12600
|
||||
if settlement.OwnerRentIncomeCent != 12600 {
|
||||
t.Fatalf("OwnerRentIncomeCent = %d, want 12600 (超出预收部分必须全额划归号主)", settlement.OwnerRentIncomeCent)
|
||||
}
|
||||
|
||||
// 平台服务费仍为初始纯币差额 2000 + 预收消耗品差额 400 = 2400
|
||||
if settlement.PlatformFeeCent != 2400 {
|
||||
t.Fatalf("PlatformFeeCent = %d, want 2400 (超额部分平台不抽成)", settlement.PlatformFeeCent)
|
||||
}
|
||||
}
|
||||
|
||||
func TestApplyCheckoutPriceView_RoleIsolationAndPlatformFeeHidden(t *testing.T) {
|
||||
order := model.RentalOrder{
|
||||
ID: 1,
|
||||
OwnerID: 100,
|
||||
RenterID: 200,
|
||||
RentAmountCent: 30000,
|
||||
OwnerRentAmountCent: 25000,
|
||||
DepositAmountCent: 10000,
|
||||
}
|
||||
rentCent := int64(30000)
|
||||
ownerRentCent := int64(25000)
|
||||
platformCent := int64(5000)
|
||||
renterRefundCent := int64(8000)
|
||||
ownerIncomeCent := int64(27000)
|
||||
|
||||
checkout := model.OrderCheckout{
|
||||
ID: 10,
|
||||
OrderID: 1,
|
||||
RentAmountCent: rentCent,
|
||||
OwnerRentAmountCent: ownerRentCent,
|
||||
PlatformFeeCent: platformCent,
|
||||
RenterRefundAmountCent: renterRefundCent,
|
||||
OwnerIncomeAmountCent: ownerIncomeCent,
|
||||
DepositDeductAmountCent: 2000,
|
||||
}
|
||||
|
||||
// 1. 号主视角
|
||||
ownerDTO := toCheckoutAdminDTO(checkout)
|
||||
applyCheckoutPriceView(&ownerDTO, order, 100)
|
||||
if ownerDTO.PlatformFeeCent != nil {
|
||||
t.Fatalf("号主视角必须屏蔽 PlatformFeeCent, 实际为: %v", *ownerDTO.PlatformFeeCent)
|
||||
}
|
||||
if ownerDTO.RenterRefundAmountCent != nil {
|
||||
t.Fatalf("号主视角必须屏蔽 RenterRefundAmountCent, 实际为: %v", *ownerDTO.RenterRefundAmountCent)
|
||||
}
|
||||
if ownerDTO.RentAmountCent != nil {
|
||||
t.Fatalf("号主视角必须屏蔽 RentAmountCent, 实际为: %v", *ownerDTO.RentAmountCent)
|
||||
}
|
||||
if ownerDTO.OwnerIncomeAmountCent == nil || *ownerDTO.OwnerIncomeAmountCent != 27000 {
|
||||
t.Fatalf("号主视角必须展示 OwnerIncomeAmountCent, 实际为: %v", ownerDTO.OwnerIncomeAmountCent)
|
||||
}
|
||||
|
||||
// 2. 租客视角
|
||||
renterDTO := toCheckoutAdminDTO(checkout)
|
||||
applyCheckoutPriceView(&renterDTO, order, 200)
|
||||
if renterDTO.PlatformFeeCent != nil {
|
||||
t.Fatalf("租客视角必须屏蔽 PlatformFeeCent, 实际为: %v", *renterDTO.PlatformFeeCent)
|
||||
}
|
||||
if renterDTO.OwnerRentAmountCent != nil {
|
||||
t.Fatalf("租客视角必须屏蔽 OwnerRentAmountCent, 实际为: %v", *renterDTO.OwnerRentAmountCent)
|
||||
}
|
||||
if renterDTO.OwnerIncomeAmountCent != nil {
|
||||
t.Fatalf("租客视角必须屏蔽 OwnerIncomeAmountCent, 实际为: %v", *renterDTO.OwnerIncomeAmountCent)
|
||||
}
|
||||
if renterDTO.RenterRefundAmountCent == nil || *renterDTO.RenterRefundAmountCent != 8000 {
|
||||
t.Fatalf("租客视角必须展示 RenterRefundAmountCent, 实际为: %v", renterDTO.RenterRefundAmountCent)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user