all the refactor
This commit is contained in:
+22
-19
@@ -6,6 +6,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"git.k6n.net/mats/go-cart-actor/pkg/cart"
|
||||
"git.k6n.net/mats/platform/money"
|
||||
)
|
||||
|
||||
// ----------------------------
|
||||
@@ -161,7 +162,7 @@ func (tieredDiscountEffect) Progress(s *PromotionService, rule PromotionRule, a
|
||||
currentPct, _ := selectTier(tiers, total) // 0 when below the first tier
|
||||
|
||||
// Find the nearest tier whose floor is still above the current total.
|
||||
nextMin := int64(0)
|
||||
nextMin := money.Cents(0)
|
||||
nextPct := 0.0
|
||||
found := false
|
||||
for _, t := range tiers {
|
||||
@@ -177,8 +178,10 @@ func (tieredDiscountEffect) Progress(s *PromotionService, rule PromotionRule, a
|
||||
return nil, false
|
||||
}
|
||||
return map[string]any{
|
||||
"remaining": nextMin - total,
|
||||
"threshold": nextMin,
|
||||
// Untyped JSON-presentation map: emit raw minor-unit int64 so consumers
|
||||
// (and JSON) see a plain number, not money.Cents.
|
||||
"remaining": (nextMin - total).Int64(),
|
||||
"threshold": nextMin.Int64(),
|
||||
"currentPercent": currentPct,
|
||||
"nextPercent": nextPct,
|
||||
}, true
|
||||
@@ -201,13 +204,13 @@ func (s *PromotionService) cartTotalProgress(rule PromotionRule, ctx *PromotionE
|
||||
if remaining <= 0 || !s.withinReach(rule, ctx, threshold) {
|
||||
return nil, false
|
||||
}
|
||||
return map[string]any{"remaining": remaining, "threshold": threshold}, true
|
||||
return map[string]any{"remaining": remaining.Int64(), "threshold": threshold.Int64()}, true
|
||||
}
|
||||
|
||||
// withinReach reports whether the rule would apply if the cart total were
|
||||
// atTotal — i.e. whether the cart-total threshold is the only thing holding it
|
||||
// back. Cheap: it re-runs evaluation against a copy of the context.
|
||||
func (s *PromotionService) withinReach(rule PromotionRule, ctx *PromotionEvalContext, atTotal int64) bool {
|
||||
func (s *PromotionService) withinReach(rule PromotionRule, ctx *PromotionEvalContext, atTotal money.Cents) bool {
|
||||
probe := *ctx
|
||||
probe.CartTotalIncVat = atTotal
|
||||
return s.EvaluateRule(rule, &probe).Applicable
|
||||
@@ -216,7 +219,7 @@ func (s *PromotionService) withinReach(rule PromotionRule, ctx *PromotionEvalCon
|
||||
// cartTotalThreshold finds the lowest cart-total floor a rule requires (a
|
||||
// cart_total >= / > condition), walking nested groups. Returns false when the
|
||||
// rule has no such condition.
|
||||
func cartTotalThreshold(rule PromotionRule) (int64, bool) {
|
||||
func cartTotalThreshold(rule PromotionRule) (money.Cents, bool) {
|
||||
var threshold int64
|
||||
found := false
|
||||
var walk func(conds Conditions)
|
||||
@@ -248,7 +251,7 @@ func cartTotalThreshold(rule PromotionRule) (int64, bool) {
|
||||
}
|
||||
}
|
||||
walk(rule.Conditions)
|
||||
return threshold, found
|
||||
return money.Cents(threshold), found
|
||||
}
|
||||
|
||||
// ----------------------------
|
||||
@@ -264,8 +267,8 @@ func cartTotalThreshold(rule PromotionRule) (int64, bool) {
|
||||
// when a total lands exactly on a shared boundary the higher tier wins, since
|
||||
// selectTier keeps the last match while scanning in order.
|
||||
type DiscountTier struct {
|
||||
MinTotal int64
|
||||
MaxTotal int64
|
||||
MinTotal money.Cents
|
||||
MaxTotal money.Cents
|
||||
Percent float64
|
||||
}
|
||||
|
||||
@@ -304,7 +307,7 @@ func applyPercentageDiscount(g *cart.CartGrain, pct float64) *cart.Price {
|
||||
// selectTier returns the discount percent for the band the total falls into.
|
||||
// Scans in declared order and keeps the last match so shared boundaries favour
|
||||
// the higher tier.
|
||||
func selectTier(tiers []DiscountTier, total int64) (float64, bool) {
|
||||
func selectTier(tiers []DiscountTier, total money.Cents) (float64, bool) {
|
||||
pct := 0.0
|
||||
found := false
|
||||
for _, t := range tiers {
|
||||
@@ -327,8 +330,8 @@ func scalePrice(p *cart.Price, pct float64) *cart.Price {
|
||||
return out
|
||||
}
|
||||
|
||||
func scale(v int64, pct float64) int64 {
|
||||
return int64(math.Round(float64(v) * pct / 100.0))
|
||||
func scale(v money.Cents, pct float64) money.Cents {
|
||||
return money.Cents(math.Round(float64(v.Int64()) * pct / 100.0))
|
||||
}
|
||||
|
||||
// parseTiers reads the "tiers" array out of an Action.Config. Because configs
|
||||
@@ -347,8 +350,8 @@ func parseTiers(config map[string]interface{}) []DiscountTier {
|
||||
continue
|
||||
}
|
||||
tiers = append(tiers, DiscountTier{
|
||||
MinTotal: int64(firstNum(m, "minTotal", "min_total")),
|
||||
MaxTotal: int64(firstNum(m, "maxTotal", "max_total")),
|
||||
MinTotal: money.Cents(int64(firstNum(m, "minTotal", "min_total"))),
|
||||
MaxTotal: money.Cents(int64(firstNum(m, "maxTotal", "max_total"))),
|
||||
Percent: firstNum(m, "percent", "discount_percent"),
|
||||
})
|
||||
}
|
||||
@@ -381,7 +384,7 @@ func (buyXGetYEffect) Type() ActionType { return ActionBuyXGetY }
|
||||
|
||||
type unitItem struct {
|
||||
item *cart.CartItem
|
||||
price int64
|
||||
price money.Cents
|
||||
}
|
||||
|
||||
func (buyXGetYEffect) Apply(g *cart.CartGrain, rule PromotionRule, a Action) (*cart.Price, bool) {
|
||||
@@ -561,16 +564,16 @@ func (bundleDiscountEffect) Apply(g *cart.CartGrain, _ PromotionRule, a Action)
|
||||
var bundleDiscount *cart.Price
|
||||
switch a.BundleConfig.Pricing.Type {
|
||||
case "fixed_price":
|
||||
targetPriceOre := int64(math.Round(a.BundleConfig.Pricing.Value * 100))
|
||||
targetPriceOre := money.FromFloatMajor(a.BundleConfig.Pricing.Value)
|
||||
if bundlePrice.IncVat > targetPriceOre {
|
||||
pct := float64(bundlePrice.IncVat-targetPriceOre) / float64(bundlePrice.IncVat) * 100
|
||||
pct := float64((bundlePrice.IncVat-targetPriceOre).Int64()) / float64(bundlePrice.IncVat.Int64()) * 100
|
||||
bundleDiscount = scalePrice(bundlePrice, pct)
|
||||
}
|
||||
case "percentage_discount":
|
||||
bundleDiscount = scalePrice(bundlePrice, a.BundleConfig.Pricing.Value)
|
||||
case "fixed_discount":
|
||||
discountOre := int64(math.Round(a.BundleConfig.Pricing.Value * 100))
|
||||
pct := float64(discountOre) / float64(bundlePrice.IncVat) * 100
|
||||
discountOre := money.FromFloatMajor(a.BundleConfig.Pricing.Value)
|
||||
pct := float64(discountOre.Int64()) / float64(bundlePrice.IncVat.Int64()) * 100
|
||||
bundleDiscount = scalePrice(bundlePrice, pct)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user