Support stacking multiple discount codes #2
@@ -0,0 +1,10 @@
|
||||
import type { Discount } from './cart'
|
||||
|
||||
/** Combine multiple discount codes into one effective factor. */
|
||||
export function applyDiscounts(subtotalCents: number, discounts: Discount[]): number {
|
||||
let totalPercentOff = 0
|
||||
for (const discount of discounts) {
|
||||
totalPercentOff += discount.percentOff
|
||||
}
|
||||
return Math.round(subtotalCents * (1 - totalPercentOff / 100))
|
||||
|
|
||||
}
|
||||
|
greptile-bot
commented
When <a href="#"><img alt="P2" src="https://greptile-static-assets.s3.amazonaws.com/badges/p2.svg?v=9" align="top"></a> **No guard against an empty discount list**
When `discounts` is an empty array, `totalPercentOff` stays `0` and the function returns `subtotalCents` unchanged — which is mathematically correct. However, there is also no guard against individual `percentOff` values that are negative (a negative discount would _increase_ the price) or individually greater than 100. The `Discount` interface places no constraint on `percentOff`, so a caller could pass `{ code: "BAD", percentOff: -20 }` and silently inflate the total. Consider validating each entry or documenting the expected range.
|
||||
Reference in New Issue
Block a user
If two or more discount codes sum to more than 100%,
(1 - totalPercentOff / 100)becomes negative andMath.roundreturns a negative cents value — effectively charging the customer. For example, two 60%-off codes produce a factor of-0.2, turning a $10 subtotal into-$2. ClampingtotalPercentOffto100prevents this.