refactor(distribution): 重写分销迁移并落地利润百分比分成与货架比例
将 000064-000078 合并为 064/065/066,默认规则改为收号 35%、卖出 40%、服务费 25%。 货架调价改为增加分站 1 元兑换哈夫币比例。sql-guard 仅保护 main 已发布迁移。
This commit is contained in:
@@ -7,13 +7,13 @@ func TestDefaultRules(t *testing.T) {
|
||||
mode string
|
||||
check func(Rule) bool
|
||||
}{
|
||||
{ModeTwoPartyDistributorReceive, func(r Rule) bool { return r.DistributorReceiveRatio == 3.5 && r.PlatformSellRatio == 4 }},
|
||||
{ModeTwoPartyPlatformReceive, func(r Rule) bool { return r.PlatformReceiveRatio == 3.5 && r.DistributorSellRatio == 4 }},
|
||||
{ModeThreeParty, func(r Rule) bool { return r.DistributorARatio == 3.5 && r.DistributorBRatio == 4 }},
|
||||
{ModeTwoPartyDistributorReceive, func(r Rule) bool { return r.DistributorReceiveRatio == 35 && r.PlatformSellRatio == 40 }},
|
||||
{ModeTwoPartyPlatformReceive, func(r Rule) bool { return r.PlatformReceiveRatio == 35 && r.DistributorSellRatio == 40 }},
|
||||
{ModeThreeParty, func(r Rule) bool { return r.DistributorARatio == 35 && r.DistributorBRatio == 40 }},
|
||||
}
|
||||
for _, item := range cases {
|
||||
rule, err := DefaultRule(item.mode)
|
||||
if err != nil || !item.check(rule) || rule.ServiceFeeValue != 2.5 || rule.PaymentFeeBPS != 50 {
|
||||
if err != nil || !item.check(rule) || rule.ServiceFeeValue != 25 || rule.ServiceFeeUnit != ServiceFeeUnitPercent || rule.PaymentFeeBPS != 50 {
|
||||
t.Fatalf("default rule %s = %#v, err=%v", item.mode, rule, err)
|
||||
}
|
||||
}
|
||||
@@ -22,13 +22,29 @@ func TestDefaultRules(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCalculateSettlementDeductsFeeBeforeSplit(t *testing.T) {
|
||||
rule := Rule{ServiceFeeValue: 0, ServiceFeeUnit: ServiceFeeUnitFixedAmount, PaymentFeeBPS: 50}
|
||||
got, err := CalculateSettlement(rule, SettlementInput{GrossPaidAmountCent: 10001, RefundAmountCent: 1000, MarkupAmountCent: 300})
|
||||
func TestNormalizeSplitPercent(t *testing.T) {
|
||||
if got := NormalizeSplitPercent(3.5); got != 35 {
|
||||
t.Fatalf("3.5 -> %v, want 35", got)
|
||||
}
|
||||
if got := NormalizeSplitPercent(4); got != 40 {
|
||||
t.Fatalf("4 -> %v, want 40", got)
|
||||
}
|
||||
if got := NormalizeSplitPercent(2.5); got != 25 {
|
||||
t.Fatalf("2.5 -> %v, want 25", got)
|
||||
}
|
||||
if got := NormalizeSplitPercent(35); got != 35 {
|
||||
t.Fatalf("35 stays %v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCalculateSettlementSplitsProfitAfterOwnerAndFee(t *testing.T) {
|
||||
rule := Rule{ServiceFeeValue: 25, ServiceFeeUnit: ServiceFeeUnitPercent, PaymentFeeBPS: 50}
|
||||
got, err := CalculateSettlement(rule, SettlementInput{GrossPaidAmountCent: 10000, OwnerRentAmountCent: 6000})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got.NetPaidAmountCent != 9001 || got.PaymentFeeCent != 45 || got.SplitBaseAmountCent != 8956 {
|
||||
// 通道费 50,利润 10000-6000-50=3950,服务费 25%=988
|
||||
if got.NetPaidAmountCent != 10000 || got.PaymentFeeCent != 50 || got.SplitBaseAmountCent != 3950 || got.ServiceFeeCent != 988 {
|
||||
t.Fatalf("unexpected settlement: %#v", got)
|
||||
}
|
||||
}
|
||||
@@ -58,48 +74,37 @@ func TestCalculateSettlementRejectsRefundOverPayment(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSplitSettlementTwoPartyDistributorReceive(t *testing.T) {
|
||||
rule := Rule{Mode: ModeTwoPartyDistributorReceive, DistributorReceiveRatio: 3.5, PlatformSellRatio: 4}
|
||||
splits := SplitSettlement(rule, 10000, 0)
|
||||
rule := Rule{Mode: ModeTwoPartyDistributorReceive, DistributorReceiveRatio: 35, PlatformSellRatio: 40}
|
||||
splits := SplitSettlement(rule, 3950)
|
||||
if len(splits) != 2 {
|
||||
t.Fatalf("splits = %#v", splits)
|
||||
}
|
||||
if splits[0].PartyRole != "distributor_receive" || splits[0].AmountCent != 350 {
|
||||
if splits[0].PartyRole != "distributor_receive" || splits[0].AmountCent != 1383 {
|
||||
t.Fatalf("distributor split = %#v", splits[0])
|
||||
}
|
||||
if splits[1].PartyRole != "platform_sell" || splits[1].AmountCent != 400 {
|
||||
if splits[1].PartyRole != "platform_sell" || splits[1].AmountCent != 1580 {
|
||||
t.Fatalf("platform split = %#v", splits[1])
|
||||
}
|
||||
if got := SplitRemainderCent(10000, splits); got != 9250 {
|
||||
t.Fatalf("remainder = %d, want 9250", got)
|
||||
if got := SplitRoundingCent(3950, 988, splits); got != -1 {
|
||||
t.Fatalf("rounding = %d, want -1", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSplitSettlementMarkupGoesToSeller(t *testing.T) {
|
||||
// 两方-分销收号模式:卖出方是主站(platform_sell)。
|
||||
rule := Rule{Mode: ModeTwoPartyDistributorReceive, DistributorReceiveRatio: 3.5, PlatformSellRatio: 4}
|
||||
splits := SplitSettlement(rule, 10000, 300)
|
||||
if splits[1].AmountCent != 700 {
|
||||
t.Fatalf("platform split with markup = %d, want 700", splits[1].AmountCent)
|
||||
func TestSplitSettlementDoesNotAddYuanMarkup(t *testing.T) {
|
||||
rule := Rule{Mode: ModeTwoPartyPlatformReceive, DistributorSellRatio: 40, PlatformReceiveRatio: 35}
|
||||
splits := SplitSettlement(rule, 10000)
|
||||
if splits[0].PartyRole != "distributor_sell" || splits[0].AmountCent != 4000 {
|
||||
t.Fatalf("distributor sell = %#v", splits[0])
|
||||
}
|
||||
// 两方-分销卖出模式:卖出方是分销网(distributor_sell)。
|
||||
ruleSell := Rule{Mode: ModeTwoPartyPlatformReceive, DistributorSellRatio: 4, PlatformReceiveRatio: 3.5}
|
||||
splitsSell := SplitSettlement(ruleSell, 10000, 300)
|
||||
if splitsSell[0].PartyRole != "distributor_sell" || splitsSell[0].AmountCent != 700 {
|
||||
t.Fatalf("distributor sell split with markup = %#v", splitsSell[0])
|
||||
}
|
||||
if got := SplitRemainderCent(10000, splitsSell); got != 8950 {
|
||||
t.Fatalf("remainder = %d, want 8950", got)
|
||||
if splits[1].AmountCent != 3500 {
|
||||
t.Fatalf("platform receive = %#v", splits[1])
|
||||
}
|
||||
}
|
||||
|
||||
func TestSplitSettlementThreeParty(t *testing.T) {
|
||||
rule := Rule{Mode: ModeThreeParty, DistributorARatio: 3.5, DistributorBRatio: 4}
|
||||
splits := SplitSettlement(rule, 10001, 0)
|
||||
if len(splits) != 2 || splits[0].AmountCent != 350 || splits[1].AmountCent != 400 {
|
||||
rule := Rule{Mode: ModeThreeParty, DistributorARatio: 35, DistributorBRatio: 40}
|
||||
splits := SplitSettlement(rule, 10000)
|
||||
if len(splits) != 2 || splits[0].AmountCent != 3500 || splits[1].AmountCent != 4000 {
|
||||
t.Fatalf("splits = %#v", splits)
|
||||
}
|
||||
// 尾差归平台:10001 - 750 = 9251。
|
||||
if got := SplitRemainderCent(10001, splits); got != 9251 {
|
||||
t.Fatalf("remainder = %d, want 9251", got)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user