支持结账多轮协商与按实际消耗双比例结算

允许双方最多 6 轮修改结账方案;哈夫币按实际消耗与 buyer/seller 比例计价,打超从押金扣,押金不足禁止自动完结并引导人工争议。同步收紧结账明细展示密度。
This commit is contained in:
yml2213
2026-07-18 20:35:16 +08:00
parent 98772867a7
commit 1a4776bba0
19 changed files with 713 additions and 140 deletions
@@ -123,6 +123,116 @@ func TestCalculateCheckoutSettlementAddsDepositCompensation(t *testing.T) {
}
}
func TestCalculateCheckoutSettlementAllowsOvershootFromDeposit(t *testing.T) {
// 发布 100M,实际消耗 180M;按基价线性外推,打超从押金扣
order := model.RentalOrder{
RentAmountCent: 26300, // 仅币预收(无消耗品)
OwnerRentAmountCent: 23300,
DepositAmountCent: 30000,
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
}
}
}`)),
}
settlement := calculateCheckoutSettlement(order, 0, 180, 0)
// 180/100 * 26300 = 47340
if settlement.ActualRentAmountCent != 47340 {
t.Fatalf("ActualRentAmountCent = %d, want 47340", settlement.ActualRentAmountCent)
}
if settlement.OwnerRentIncomeCent != 41940 { // 180/100 * 23300
t.Fatalf("OwnerRentIncomeCent = %d, want 41940", settlement.OwnerRentIncomeCent)
}
if settlement.OvershootAmountCent != 21040 { // 47340 - 26300
t.Fatalf("OvershootAmountCent = %d, want 21040", settlement.OvershootAmountCent)
}
if settlement.ShortfallCent != 0 {
t.Fatalf("ShortfallCent = %d, want 0", settlement.ShortfallCent)
}
if settlement.RentRefundCent != 0 {
t.Fatalf("RentRefundCent = %d, want 0", settlement.RentRefundCent)
}
// 押金 30000 - 打超 21040 = 8960
if settlement.DepositRefundCent != 8960 {
t.Fatalf("DepositRefundCent = %d, want 8960", settlement.DepositRefundCent)
}
}
func TestCalculateCheckoutSettlementShortfallWhenDepositInsufficient(t *testing.T) {
order := model.RentalOrder{
RentAmountCent: 26300,
OwnerRentAmountCent: 23300,
DepositAmountCent: 5000,
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
}
}
}`)),
}
settlement := calculateCheckoutSettlement(order, 0, 180, 0)
// overshoot 21040, deposit 5000 → shortfall 16040
if settlement.OvershootAmountCent != 21040 {
t.Fatalf("OvershootAmountCent = %d, want 21040", settlement.OvershootAmountCent)
}
if settlement.ShortfallCent != 16040 {
t.Fatalf("ShortfallCent = %d, want 16040", settlement.ShortfallCent)
}
if settlement.DepositRefundCent != 0 {
t.Fatalf("DepositRefundCent = %d, want 0", settlement.DepositRefundCent)
}
}
func TestCalculateCheckoutSettlementUsesExplicitRatiosForActualConsume(t *testing.T) {
// buyer 1:40, seller 1:45;消耗 180M
// 租客: 180*100/40 = 450 元;号主: 180*100/45 = 400 元
order := model.RentalOrder{
RentAmountCent: 25000, // 100M 预收
OwnerRentAmountCent: 22222,
DepositAmountCent: 50000,
AccountSnapshot: datatypes.JSON([]byte(`{
"haf_coin_amount": 100000000,
"asset_summary": {
"price_breakdown": {
"buyer_ratio": 40,
"seller_ratio": 45,
"buyer_coin_base_price": 250,
"seller_coin_base_price": 222.22,
"consumable_price": 0
}
}
}`)),
}
settlement := calculateCheckoutSettlement(order, 0, 180, 0)
if settlement.ActualRentAmountCent != 45000 {
t.Fatalf("ActualRentAmountCent = %d, want 45000", settlement.ActualRentAmountCent)
}
if settlement.OwnerRentIncomeCent != 40000 {
t.Fatalf("OwnerRentIncomeCent = %d, want 40000", settlement.OwnerRentIncomeCent)
}
if settlement.PlatformFeeCent != 5000 {
t.Fatalf("PlatformFeeCent = %d, want 5000", settlement.PlatformFeeCent)
}
if settlement.OvershootAmountCent != 20000 {
t.Fatalf("OvershootAmountCent = %d, want 20000", settlement.OvershootAmountCent)
}
if settlement.ShortfallCent != 0 {
t.Fatalf("ShortfallCent = %d, want 0", settlement.ShortfallCent)
}
}
func TestCalculateDepositWaiverUsesSharedRemainingQuota(t *testing.T) {
paid, waived := calculateDepositWaiver(500, 300, 0)
if paid != 200 || waived != 300 {