From f54c619fc766b5325cdf6cba013b54e34f820953 Mon Sep 17 00:00:00 2001 From: Tiago Ribeiro Date: Mon, 9 Mar 2026 09:01:10 -0300 Subject: [PATCH] fix: adjust financial split math for 6%+6% model and add split test --- .../payments/split_math_test.go | 47 +++++++++++++++++++ backend/internal/usecase/payment_usecase.go | 13 ++++- 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 backend/internal/infrastructure/payments/split_math_test.go diff --git a/backend/internal/infrastructure/payments/split_math_test.go b/backend/internal/infrastructure/payments/split_math_test.go new file mode 100644 index 0000000..f668bc7 --- /dev/null +++ b/backend/internal/infrastructure/payments/split_math_test.go @@ -0,0 +1,47 @@ +package tests + +import ( + "math" + "testing" +) + +func TestPsychologicalSplitMath(t *testing.T) { + // Base Price (what the seller wants to sell for) + basePrice := 100.0 + + // 1. Backend inflates by 6% for search/display + buyerFeeRate := 0.06 + inflatedPrice := basePrice * (1 + buyerFeeRate) // 106.0 + + // 2. Buyer sees 12% fee in checkout, but math must stay at 106.0 + // Visual Subtotal = 106.0 / 1.12 = 94.6428... + visualSubtotal := inflatedPrice / 1.12 + visualFee := inflatedPrice - visualSubtotal + + // 3. Marketplace takes 12% of the TOTAL (inflated) price + marketplaceCommission := 0.12 + totalMarketplaceFee := inflatedPrice * marketplaceCommission // 12.72 + + // 4. Seller Receivable = Inflated Price - Marketplace Fee + sellerReceivable := inflatedPrice - totalMarketplaceFee // 106.0 - 12.72 = 93.28 + + // 5. Seller perceives it as 6% commission on THEIR base price + perceivedCommission := basePrice * 0.06 // 6.0 + expectedSellerReceivable := basePrice - perceivedCommission // 94.0 + + // ASSERTION: Does 93.28 == 94.0? + // Result: NO. + // To make the seller receive 94.0 (Base - 6%), + // and Marketplace receive 12.72 (which is 12% of inflated 106.0), + // The math needs adjustment. + + t.Logf("Base: %.2f", basePrice) + t.Logf("Inflated (Buyer sees total): %.2f", inflatedPrice) + t.Logf("Marketplace Fee (12%% of inflated): %.2f", totalMarketplaceFee) + t.Logf("Seller Net: %.2f", sellerReceivable) + t.Logf("Target Seller Net (Base - 6%%): %.2f", expectedSellerReceivable) + + if math.Abs(sellerReceivable-expectedSellerReceivable) > 0.01 { + t.Errorf("Math mismatch! Seller receives %.2f but expected %.2f", sellerReceivable, expectedSellerReceivable) + } +} diff --git a/backend/internal/usecase/payment_usecase.go b/backend/internal/usecase/payment_usecase.go index aa115fe..766eb79 100644 --- a/backend/internal/usecase/payment_usecase.go +++ b/backend/internal/usecase/payment_usecase.go @@ -3,6 +3,7 @@ package usecase import ( "context" "fmt" + "math" "strings" "github.com/gofrs/uuid/v5" @@ -125,7 +126,17 @@ func (s *Service) HandlePaymentWebhook(ctx context.Context, event domain.Payment return nil, err } - expectedMarketplaceFee := int64(float64(order.TotalCents) * (s.marketplaceCommission / 100)) + // Business Rule: 6% + 6% Psychological Split. + // order.TotalCents already includes the 6% buyer fee (inflated in search). + // Base Price = Total / 1.06 + // Seller Fee = Base Price * 0.06 + // Buyer Fee = Total - Base Price + // Total Marketplace Fee = Seller Fee + Buyer Fee + basePriceCents := float64(order.TotalCents) / 1.06 + sellerFeeCents := basePriceCents * 0.06 + buyerFeeCents := float64(order.TotalCents) - basePriceCents + expectedMarketplaceFee := int64(math.Round(sellerFeeCents + buyerFeeCents)) + marketplaceFee := event.MarketplaceFee if marketplaceFee == 0 { marketplaceFee = expectedMarketplaceFee