fix(utils): fix promotion case of each allocation not applying its total amount (#13199)

* fix(utils): fix promotion case of each allocation not applying its amount

* chore: fixed tests

---------

Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>
This commit is contained in:
Riqwan Thamir
2025-08-17 19:11:16 +02:00
committed by GitHub
parent 0128ed314c
commit 3cc512ef39
4 changed files with 150 additions and 12 deletions

View File

@@ -9,7 +9,12 @@ function getPromotionValueForPercentage(promotion, lineItemAmount) {
return MathBN.mult(MathBN.div(promotion.value, 100), lineItemAmount)
}
function getPromotionValueForFixed(promotion, lineItemAmount, lineItemsAmount) {
function getPromotionValueForFixed(
promotion,
lineItemAmount,
lineItemsAmount,
lineItem
) {
if (promotion.allocation === ApplicationMethodAllocation.ACROSS) {
const promotionValueForItem = MathBN.mult(
MathBN.div(lineItemAmount, lineItemsAmount),
@@ -27,15 +32,37 @@ function getPromotionValueForFixed(promotion, lineItemAmount, lineItemsAmount) {
return MathBN.mult(promotionValueForItem, MathBN.div(percentage, 100))
}
return promotion.value
// For each allocation, promotion is applied in the scope of the line item.
// lineItemAmount will be the total applicable amount for the line item
// maximumPromotionAmount is the maximum amount that can be applied to the line item
// We need to return the minimum of the two
const maximumQuantity = MathBN.min(
lineItem.quantity,
promotion.max_quantity ?? MathBN.convert(1)
)
const maximumPromotionAmount = MathBN.mult(promotion.value, maximumQuantity)
return MathBN.min(maximumPromotionAmount, lineItemAmount)
}
export function getPromotionValue(promotion, lineItemAmount, lineItemsAmount) {
export function getPromotionValue(
promotion,
lineItemAmount,
lineItemsAmount,
lineItem
) {
if (promotion.type === ApplicationMethodType.PERCENTAGE) {
return getPromotionValueForPercentage(promotion, lineItemAmount)
}
return getPromotionValueForFixed(promotion, lineItemAmount, lineItemsAmount)
return getPromotionValueForFixed(
promotion,
lineItemAmount,
lineItemsAmount,
lineItem
)
}
export function getApplicableQuantity(lineItem, maxQuantity) {
@@ -105,7 +132,8 @@ export function calculateAdjustmentAmountFromPromotion(
const promotionValue = getPromotionValue(
promotion,
applicableAmount,
lineItemsAmount
lineItemsAmount,
lineItem
)
const returnValue = MathBN.min(promotionValue, applicableAmount)
@@ -139,14 +167,17 @@ export function calculateAdjustmentAmountFromPromotion(
promotion.is_tax_inclusive ? lineItem.original_total : lineItem.subtotal,
promotion.applied_value
)
const itemAmount = MathBN.div(
promotion.is_tax_inclusive ? lineItem.original_total : lineItem.subtotal,
lineItem.quantity
)
const maximumPromotionAmount = MathBN.mult(
itemAmount,
promotion.max_quantity ?? MathBN.convert(1)
)
const applicableAmount = MathBN.min(
remainingItemAmount,
maximumPromotionAmount
@@ -159,7 +190,8 @@ export function calculateAdjustmentAmountFromPromotion(
const promotionValue = getPromotionValue(
promotion,
applicableAmount,
lineItemsAmount
lineItemsAmount,
lineItem
)
const returnValue = MathBN.min(promotionValue, applicableAmount)