promotions
Build and Publish / BuildAndDeployArm64 (push) Failing after 6s
Build and Publish / BuildAndDeployAmd64 (push) Has been cancelled

This commit is contained in:
2026-06-18 11:32:19 +02:00
parent 2545be4315
commit 2443fd8b49
9 changed files with 583 additions and 55 deletions
+67 -3
View File
@@ -48,7 +48,6 @@ func cartWithTotal(incVat int64) *cart.CartGrain {
}
func TestVolymrabattTiers(t *testing.T) {
svc := NewPromotionService(nil)
rules := []PromotionRule{volymrabattRule()}
cases := []struct {
@@ -69,9 +68,11 @@ func TestVolymrabattTiers(t *testing.T) {
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
svc := NewPromotionService(nil)
g := cartWithTotal(c.total)
_, actions := svc.EvaluateAll(rules, NewContextFromCart(g, WithNow(timeZero())))
ApplyActions(g, actions)
results, _ := svc.EvaluateAll(rules, NewContextFromCart(g, WithNow(timeZero())))
ctx := NewContextFromCart(g, WithNow(timeZero()))
svc.ApplyResults(g, results, ctx)
if got := g.TotalDiscount.IncVat; got != c.wantDiscount {
t.Errorf("discount = %d, want %d", got, c.wantDiscount)
@@ -82,3 +83,66 @@ func TestVolymrabattTiers(t *testing.T) {
})
}
}
// findApplied returns the first appliedPromotions entry for ruleID.
func findApplied(g *cart.CartGrain, ruleID string) (cart.AppliedPromotion, bool) {
for _, ap := range g.AppliedPromotions {
if ap.PromotionId == ruleID {
return ap, true
}
}
return cart.AppliedPromotion{}, false
}
// TestApplyResultsRecordsEffects covers the applied/pending breakdown the result
// now exposes: an applied effect attributed to its rule, a pending nudge with
// progress when below the threshold, and progress-toward-the-next-tier on an
// already-applied tiered discount.
func TestApplyResultsRecordsEffects(t *testing.T) {
rules := []PromotionRule{volymrabattRule()}
apply := func(total int64) *cart.CartGrain {
svc := NewPromotionService(nil)
g := cartWithTotal(total)
results, _ := svc.EvaluateAll(rules, NewContextFromCart(g, WithNow(timeZero())))
svc.ApplyResults(g, results, NewContextFromCart(g, WithNow(timeZero())))
return g
}
t.Run("applied effect records discount + next-tier progress", func(t *testing.T) {
g := apply(5000000) // qualifies at the 9% tier
ap, ok := findApplied(g, "volymrabatt")
if !ok {
t.Fatal("no volymrabatt entry recorded")
}
if ap.Pending {
t.Error("applied effect should not be pending")
}
if ap.Discount == nil || ap.Discount.IncVat != 450000 {
t.Errorf("discount = %v, want IncVat 450000", ap.Discount)
}
// 50 000 kr sits in the 9% tier; the next tier (14%) starts at 60 000 kr.
if got := ap.Progress["remaining"]; got != int64(1000000) {
t.Errorf("progress remaining = %v, want 1000000", got)
}
if got := ap.Progress["nextPercent"]; got != 14.0 {
t.Errorf("progress nextPercent = %v, want 14", got)
}
})
t.Run("pending nudge below threshold", func(t *testing.T) {
g := apply(1500000) // below the 20 000 kr entry tier
if g.TotalDiscount.IncVat != 0 {
t.Errorf("nothing should be applied, discount = %d", g.TotalDiscount.IncVat)
}
ap, ok := findApplied(g, "volymrabatt")
if !ok {
t.Fatal("expected a pending volymrabatt nudge")
}
if !ap.Pending || ap.Discount != nil {
t.Errorf("expected pending with no discount, got pending=%v discount=%v", ap.Pending, ap.Discount)
}
if got := ap.Progress["remaining"]; got != int64(500000) {
t.Errorf("progress remaining = %v, want 500000", got)
}
})
}