143 lines
3.6 KiB
Go
143 lines
3.6 KiB
Go
package pricing_test
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
|
|
"github.com/google/uuid"
|
|
|
|
"backend/internal/modules/pricing"
|
|
)
|
|
|
|
// fakeRepository is an in-memory pricing.Repository used to unit-test
|
|
// pricing.Service without a real database.
|
|
type fakeRepository struct {
|
|
tiers map[uuid.UUID]*pricing.PriceTier
|
|
}
|
|
|
|
func newFakeRepository() *fakeRepository {
|
|
return &fakeRepository{tiers: map[uuid.UUID]*pricing.PriceTier{}}
|
|
}
|
|
|
|
func (r *fakeRepository) Create(_ context.Context, t *pricing.PriceTier) error {
|
|
cp := *t
|
|
r.tiers[t.ID] = &cp
|
|
return nil
|
|
}
|
|
|
|
func (r *fakeRepository) FindByID(_ context.Context, id uuid.UUID) (*pricing.PriceTier, error) {
|
|
t, ok := r.tiers[id]
|
|
if !ok {
|
|
return nil, pricing.ErrNotFound
|
|
}
|
|
cp := *t
|
|
return &cp, nil
|
|
}
|
|
|
|
func (r *fakeRepository) ListByProduct(_ context.Context, productID uuid.UUID) ([]*pricing.PriceTier, error) {
|
|
var list []*pricing.PriceTier
|
|
for _, t := range r.tiers {
|
|
if t.ProductID == productID {
|
|
cp := *t
|
|
list = append(list, &cp)
|
|
}
|
|
}
|
|
return list, nil
|
|
}
|
|
|
|
func (r *fakeRepository) Update(_ context.Context, t *pricing.PriceTier) error {
|
|
if _, ok := r.tiers[t.ID]; !ok {
|
|
return pricing.ErrNotFound
|
|
}
|
|
cp := *t
|
|
r.tiers[t.ID] = &cp
|
|
return nil
|
|
}
|
|
|
|
func (r *fakeRepository) Delete(_ context.Context, id uuid.UUID) error {
|
|
if _, ok := r.tiers[id]; !ok {
|
|
return pricing.ErrNotFound
|
|
}
|
|
delete(r.tiers, id)
|
|
return nil
|
|
}
|
|
|
|
func TestService_PriceForQuantity_MultipliesTierPrice(t *testing.T) {
|
|
repo := newFakeRepository()
|
|
svc := pricing.NewService(repo)
|
|
ctx := context.Background()
|
|
|
|
productID := uuid.New()
|
|
unitID := uuid.New()
|
|
|
|
// "5 kg -> 45.00" tier, spec section 16 example.
|
|
tier, err := svc.Create(ctx, productID, unitID, 5, 4500, 0)
|
|
if err != nil {
|
|
t.Fatalf("Create() error = %v", err)
|
|
}
|
|
|
|
total, gotTier, err := svc.PriceForQuantity(ctx, tier.ID, 2)
|
|
if err != nil {
|
|
t.Fatalf("PriceForQuantity() error = %v", err)
|
|
}
|
|
if total != 9000 {
|
|
t.Fatalf("PriceForQuantity() total = %d, want 9000 (2x 4500)", total)
|
|
}
|
|
if gotTier.ID != tier.ID {
|
|
t.Fatalf("PriceForQuantity() returned tier %s, want %s", gotTier.ID, tier.ID)
|
|
}
|
|
}
|
|
|
|
func TestService_PriceForQuantity_ZeroOrNegativeMultiplierTreatedAsOne(t *testing.T) {
|
|
repo := newFakeRepository()
|
|
svc := pricing.NewService(repo)
|
|
ctx := context.Background()
|
|
|
|
tier, err := svc.Create(ctx, uuid.New(), uuid.New(), 1, 1000, 0)
|
|
if err != nil {
|
|
t.Fatalf("Create() error = %v", err)
|
|
}
|
|
|
|
total, _, err := svc.PriceForQuantity(ctx, tier.ID, 0)
|
|
if err != nil {
|
|
t.Fatalf("PriceForQuantity() error = %v", err)
|
|
}
|
|
if total != 1000 {
|
|
t.Fatalf("PriceForQuantity() with multiplier=0 total = %d, want 1000 (treated as 1x)", total)
|
|
}
|
|
}
|
|
|
|
func TestService_PriceForQuantity_UnknownTierRejected(t *testing.T) {
|
|
svc := pricing.NewService(newFakeRepository())
|
|
_, _, err := svc.PriceForQuantity(context.Background(), uuid.New(), 1)
|
|
if !errors.Is(err, pricing.ErrNotFound) {
|
|
t.Fatalf("PriceForQuantity() error = %v, want ErrNotFound", err)
|
|
}
|
|
}
|
|
|
|
func TestService_ListByProduct_FiltersByProduct(t *testing.T) {
|
|
repo := newFakeRepository()
|
|
svc := pricing.NewService(repo)
|
|
ctx := context.Background()
|
|
|
|
productA := uuid.New()
|
|
productB := uuid.New()
|
|
unitID := uuid.New()
|
|
|
|
if _, err := svc.Create(ctx, productA, unitID, 1, 1000, 0); err != nil {
|
|
t.Fatalf("Create() error = %v", err)
|
|
}
|
|
if _, err := svc.Create(ctx, productB, unitID, 1, 2000, 0); err != nil {
|
|
t.Fatalf("Create() error = %v", err)
|
|
}
|
|
|
|
list, err := svc.ListByProduct(ctx, productA)
|
|
if err != nil {
|
|
t.Fatalf("ListByProduct() error = %v", err)
|
|
}
|
|
if len(list) != 1 || list[0].ProductID != productA {
|
|
t.Fatalf("ListByProduct(productA) = %+v, want exactly one tier for productA", list)
|
|
}
|
|
}
|