feat: implement invisible 12% buyer fee
Business model: - Seller registers R$10,00 → Seller sees R$10,00 → Seller receives R$10,00 - Buyer searches → sees R$11,20 (+12%) → pays R$11,20 - Marketplace keeps R$1,20 (12%) Changes: - config.go: Add BuyerFeeRate (default 0.12) - handler.go: Add buyerFeeRate field to Handler struct - product_handler.go: SearchProducts inflates prices for buyers - server.go: Pass cfg.BuyerFeeRate to handler.New() - handler_test.go: Fix 3 New() calls with fee rate Env var: BUYER_FEE_RATE (default: 0.12)
This commit is contained in:
parent
285f586371
commit
12e2503244
5 changed files with 21 additions and 7 deletions
|
|
@ -17,6 +17,7 @@ type Config struct {
|
|||
DatabaseURL string
|
||||
MercadoPagoBaseURL string
|
||||
MarketplaceCommission float64
|
||||
BuyerFeeRate float64 // Fee rate applied to buyer prices (e.g., 0.12 = 12%)
|
||||
JWTSecret string
|
||||
JWTExpiresIn time.Duration
|
||||
PasswordPepper string
|
||||
|
|
@ -40,6 +41,7 @@ func Load() Config {
|
|||
DatabaseURL: getEnv("DATABASE_URL", "postgres://postgres:postgres@localhost:5432/saveinmed?sslmode=disable"),
|
||||
MercadoPagoBaseURL: getEnv("MERCADOPAGO_BASE_URL", "https://api.mercadopago.com"),
|
||||
MarketplaceCommission: getEnvFloat("MARKETPLACE_COMMISSION", 2.5),
|
||||
BuyerFeeRate: getEnvFloat("BUYER_FEE_RATE", 0.12), // 12% invisible fee
|
||||
JWTSecret: getEnv("JWT_SECRET", "dev-secret"),
|
||||
JWTExpiresIn: getEnvDuration("JWT_EXPIRES_IN", 24*time.Hour),
|
||||
PasswordPepper: getEnv("PASSWORD_PEPPER", ""),
|
||||
|
|
|
|||
|
|
@ -16,11 +16,12 @@ import (
|
|||
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||
|
||||
type Handler struct {
|
||||
svc *usecase.Service
|
||||
svc *usecase.Service
|
||||
buyerFeeRate float64 // Rate to inflate prices for buyers (e.g., 0.12 = 12%)
|
||||
}
|
||||
|
||||
func New(svc *usecase.Service) *Handler {
|
||||
return &Handler{svc: svc}
|
||||
func New(svc *usecase.Service, buyerFeeRate float64) *Handler {
|
||||
return &Handler{svc: svc, buyerFeeRate: buyerFeeRate}
|
||||
}
|
||||
|
||||
// Register godoc
|
||||
|
|
|
|||
|
|
@ -312,7 +312,7 @@ func newTestHandler() *Handler {
|
|||
repo := NewMockRepository()
|
||||
gateway := &MockPaymentGateway{}
|
||||
svc := usecase.NewService(repo, gateway, 0.05, "test-secret", time.Hour, "test-pepper")
|
||||
return New(svc)
|
||||
return New(svc, 0.12) // 12% buyer fee rate for testing
|
||||
}
|
||||
|
||||
func TestListProducts(t *testing.T) {
|
||||
|
|
@ -398,7 +398,7 @@ func TestAdminLogin_Success(t *testing.T) {
|
|||
repo := NewMockRepository()
|
||||
gateway := &MockPaymentGateway{}
|
||||
svc := usecase.NewService(repo, gateway, 0.05, "test-secret", time.Hour, "test-pepper")
|
||||
h := New(svc)
|
||||
h := New(svc, 0.12)
|
||||
|
||||
// Create admin user through service (which hashes password)
|
||||
companyID, _ := uuid.NewV7()
|
||||
|
|
@ -442,7 +442,7 @@ func TestAdminLogin_WrongPassword(t *testing.T) {
|
|||
repo := NewMockRepository()
|
||||
gateway := &MockPaymentGateway{}
|
||||
svc := usecase.NewService(repo, gateway, 0.05, "test-secret", time.Hour, "test-pepper")
|
||||
h := New(svc)
|
||||
h := New(svc, 0.12)
|
||||
|
||||
// Create admin user
|
||||
companyID, _ := uuid.NewV7()
|
||||
|
|
|
|||
|
|
@ -142,6 +142,17 @@ func (h *Handler) SearchProducts(w http.ResponseWriter, r *http.Request) {
|
|||
writeError(w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
// Apply invisible buyer fee: inflate prices by buyerFeeRate (e.g., 12%)
|
||||
// The buyer sees inflated prices, but the DB stores the original seller price
|
||||
if h.buyerFeeRate > 0 {
|
||||
for i := range result.Products {
|
||||
originalPrice := result.Products[i].PriceCents
|
||||
inflatedPrice := int64(float64(originalPrice) * (1 + h.buyerFeeRate))
|
||||
result.Products[i].PriceCents = inflatedPrice
|
||||
}
|
||||
}
|
||||
|
||||
writeJSON(w, http.StatusOK, result)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ func New(cfg config.Config) (*Server, error) {
|
|||
repo := postgres.New(db)
|
||||
gateway := payments.NewMercadoPagoGateway(cfg.MercadoPagoBaseURL, cfg.MarketplaceCommission)
|
||||
svc := usecase.NewService(repo, gateway, cfg.MarketplaceCommission, cfg.JWTSecret, cfg.JWTExpiresIn, cfg.PasswordPepper)
|
||||
h := handler.New(svc)
|
||||
h := handler.New(svc, cfg.BuyerFeeRate)
|
||||
|
||||
mux := http.NewServeMux()
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue