src/billing/discount.py
+4 −2
12class DiscountEngine:
13 """Apply percentage discounts to an order total."""
14
15 def apply_discount(self, total: float, discount_pct: float) -> float:
16 return total * (1 - discount_pct / 100)
15 def apply_discount(self, total: float, discount_pct: float, is_vip: bool) -> float:
16 """Stack a 15% VIP bonus on top of any active coupon."""
17 combined_pct = discount_pct + (15 if is_vip else 0)
18 return total * (1 - combined_pct / 100)
AI review · needs acknowledgment
combined_pct has no upper bound. If a customer stacks an expired coupon (
discount_pct=90) with the VIP tier (+15), the result is total * -0.05 — a negative charge.
Suggested fix: combined_pct = min(discount_pct + (15 if is_vip else 0), 100).
19
20 def apply_coupon(self, total: float, coupon: Coupon) -> float:
21 return self.apply_discount(total, coupon.percent_off, False)
Type check — 3 errors, level 1 (blocking)
mypy --strict · ran in 4.2s
src/checkout/cart.py:44: error: Missing positional argument "is_vip" in call to "apply_discount" [call-arg]
src/checkout/cart.py:102: error: Missing positional argument "is_vip" in call to "apply_discount" [call-arg]
src/checkout/cart.py:188: error: Missing positional argument "is_vip" in call to "apply_discount" [call-arg]
Found 3 errors in 1 file (checked 1 source file)
cart.py:44 — checkout_guest()
View call site
cart.py:102 — checkout_member()
View call site
cart.py:188 — recalculate_on_refund()
View call site
Quality gate
Level 1 — blocks merge, no exceptions
SAST critical / high0
Secrets detected0
Tests passing14/14
Type check / build3 errors
Dependency critical CVE0
Level 2 — needs reviewer acknowledgment
Coverage on new code92%
AI review — logic issue1 open
Cyclomatic complexityok
Level 3 — informational only
PR size41 lines
Duplicate codenone found
SAST 0
AI review 2
Tests
No findings in this diff
Semgrep · p/owasp-top-ten, p/secrets, custom rules
Rule sets scanned3
Lines analyzed41
Scan time6.8s
Logic · discount.py:17
Unbounded
combined_pct can exceed 100, producing a negative total when an expired coupon stacks with the VIP bonus.Breaking change · discount.py:15
New required parameter
is_vip is not backward compatible — surfaced as 3 type errors in cart.py.System prompt scope: production bugs, security, unhandled edge cases only — style is left to the linter.
Coverage on new code92%
Unit tests14 passed / 14
Integration tests3 passed / 3
Mutation score81%
Flaky retries0
Reviewers
WP
worapoj requested changes
AI
ZuCodeView AI 2 comments