///|
pub fn discount_rule(
code~ : String,
percent_bp~ : Int,
cap~ : Money,
) -> DiscountRule {
{ code, percent_bp, cap }
}
///|
pub fn apply_discounts(
original : Money,
rules : Array[DiscountRule],
) -> DiscountResult {
let mut discount = Money::zero()
let applied : Array[String] = []
for rule in rules {
let candidate = original
.percent_bp(rule.percent_bp.max(0))
.min(rule.cap.max(Money::zero()))
discount = discount.add(candidate)
if candidate.is_positive() {
applied.push(rule.code)
}
}
let payable = original.sub(discount).max(Money::zero())
{ original, discount, payable, applied }
}
///|
pub fn DiscountRule::valid(self : DiscountRule) -> Bool {
self.code.length() > 0 &&
self.percent_bp >= 0 &&
self.percent_bp <= 10000 &&
self.cap.cents >= 0
}
///|
pub fn DiscountResult::effective_rate_bp(self : DiscountResult) -> Int {
if self.original.cents <= 0 {
0
} else {
self.discount.cents * 10000 / self.original.cents
}
}
///|
pub fn combine_discount_rules(
groups : Array[Array[DiscountRule]],
) -> Array[DiscountRule] {
let result : Array[DiscountRule] = []
for group in groups {
for rule in group {
result.push(rule)
}
}
result
}