chore(promotion): big number calc (#7537)
This commit is contained in:
1 parent
61977bd392
commit
096372463e
12 files changed
+193
-147
No files matched your search
@@ -1,3 +1,5 @@
|
|||||||
|
import { BigNumberInput } from "../../totals"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A compute action informs you what adjustment must be made to a cart item or shipping method.
|
* A compute action informs you what adjustment must be made to a cart item or shipping method.
|
||||||
*/
|
*/
|
||||||
@@ -48,7 +50,7 @@ export interface AddItemAdjustmentAction {
|
|||||||
/**
|
/**
|
||||||
* The amount to remove off the item's total.
|
* The amount to remove off the item's total.
|
||||||
*/
|
*/
|
||||||
amount: number
|
amount: BigNumberInput
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The promotion's code.
|
* The promotion's code.
|
||||||
@@ -103,7 +105,7 @@ export interface AddShippingMethodAdjustment {
|
|||||||
/**
|
/**
|
||||||
* The amount to remove off the shipping method's total.
|
* The amount to remove off the shipping method's total.
|
||||||
*/
|
*/
|
||||||
amount: number
|
amount: BigNumberInput
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The promotion's code.
|
* The promotion's code.
|
||||||
@@ -163,12 +165,12 @@ export interface ComputeActionItemLine extends Record<string, unknown> {
|
|||||||
/**
|
/**
|
||||||
* The quantity of the line item.
|
* The quantity of the line item.
|
||||||
*/
|
*/
|
||||||
quantity: number
|
quantity: BigNumberInput
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The subtotal of the line item.
|
* The subtotal of the line item.
|
||||||
*/
|
*/
|
||||||
subtotal: number
|
subtotal: BigNumberInput
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The adjustments applied before on the line item.
|
* The adjustments applied before on the line item.
|
||||||
@@ -188,7 +190,7 @@ export interface ComputeActionShippingLine extends Record<string, unknown> {
|
|||||||
/**
|
/**
|
||||||
* The subtotal of the shipping method.
|
* The subtotal of the shipping method.
|
||||||
*/
|
*/
|
||||||
subtotal: number
|
subtotal: BigNumberInput
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The adjustments applied before on the shipping method.
|
* The adjustments applied before on the shipping method.
|
||||||
|
|||||||
@@ -1,15 +1,20 @@
|
|||||||
|
import { BigNumberInput } from "@medusajs/types"
|
||||||
import {
|
import {
|
||||||
ApplicationMethodAllocation,
|
ApplicationMethodAllocation,
|
||||||
ApplicationMethodType,
|
ApplicationMethodType,
|
||||||
} from "../../promotion"
|
} from "../../promotion"
|
||||||
|
import { MathBN } from "../math"
|
||||||
|
|
||||||
function getPromotionValueForPercentage(promotion, lineItemTotal) {
|
function getPromotionValueForPercentage(promotion, lineItemTotal) {
|
||||||
return (promotion.value / 100) * lineItemTotal
|
return MathBN.mult(MathBN.div(promotion.value, 100), lineItemTotal)
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPromotionValueForFixed(promotion, lineItemTotal, lineItemsTotal) {
|
function getPromotionValueForFixed(promotion, lineItemTotal, lineItemsTotal) {
|
||||||
if (promotion.allocation === ApplicationMethodAllocation.ACROSS) {
|
if (promotion.allocation === ApplicationMethodAllocation.ACROSS) {
|
||||||
return (lineItemTotal / lineItemsTotal) * promotion.value
|
return MathBN.mult(
|
||||||
|
MathBN.div(lineItemTotal, lineItemsTotal),
|
||||||
|
promotion.value
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return promotion.value
|
return promotion.value
|
||||||
@@ -25,26 +30,26 @@ export function getPromotionValue(promotion, lineItemTotal, lineItemsTotal) {
|
|||||||
|
|
||||||
export function getApplicableQuantity(lineItem, maxQuantity) {
|
export function getApplicableQuantity(lineItem, maxQuantity) {
|
||||||
if (maxQuantity && lineItem.quantity) {
|
if (maxQuantity && lineItem.quantity) {
|
||||||
return Math.min(lineItem.quantity, maxQuantity)
|
return MathBN.min(lineItem.quantity, maxQuantity)
|
||||||
}
|
}
|
||||||
|
|
||||||
return lineItem.quantity
|
return lineItem.quantity
|
||||||
}
|
}
|
||||||
|
|
||||||
function getLineItemUnitPrice(lineItem) {
|
function getLineItemUnitPrice(lineItem) {
|
||||||
return lineItem.subtotal / lineItem.quantity
|
return MathBN.div(lineItem.subtotal, lineItem.quantity)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function calculateAdjustmentAmountFromPromotion(
|
export function calculateAdjustmentAmountFromPromotion(
|
||||||
lineItem,
|
lineItem,
|
||||||
promotion,
|
promotion,
|
||||||
lineItemsTotal = 0
|
lineItemsTotal: BigNumberInput = 0
|
||||||
) {
|
) {
|
||||||
const quantity = getApplicableQuantity(lineItem, promotion.max_quantity)
|
const quantity = getApplicableQuantity(lineItem, promotion.max_quantity)
|
||||||
const lineItemTotal = getLineItemUnitPrice(lineItem) * quantity
|
const lineItemTotal = MathBN.mult(getLineItemUnitPrice(lineItem), quantity)
|
||||||
const applicableTotal = lineItemTotal - promotion.applied_value
|
const applicableTotal = MathBN.sub(lineItemTotal, promotion.applied_value)
|
||||||
|
|
||||||
if (applicableTotal <= 0) {
|
if (MathBN.lte(applicableTotal, 0)) {
|
||||||
return applicableTotal
|
return applicableTotal
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,5 +59,5 @@ export function calculateAdjustmentAmountFromPromotion(
|
|||||||
lineItemsTotal
|
lineItemsTotal
|
||||||
)
|
)
|
||||||
|
|
||||||
return Math.min(promotionValue, applicableTotal)
|
return MathBN.min(promotionValue, applicableTotal)
|
||||||
}
|
}
|
||||||
+67
-67
@@ -1,7 +1,7 @@
|
|||||||
import { Modules } from "@medusajs/modules-sdk"
|
import { Modules } from "@medusajs/modules-sdk"
|
||||||
import { IPromotionModuleService } from "@medusajs/types"
|
import { IPromotionModuleService } from "@medusajs/types"
|
||||||
import { ApplicationMethodType, PromotionType } from "@medusajs/utils"
|
import { ApplicationMethodType, PromotionType } from "@medusajs/utils"
|
||||||
import { moduleIntegrationTestRunner, SuiteOptions } from "medusa-test-utils"
|
import { SuiteOptions, moduleIntegrationTestRunner } from "medusa-test-utils"
|
||||||
import { createCampaigns } from "../../../__fixtures__/campaigns"
|
import { createCampaigns } from "../../../__fixtures__/campaigns"
|
||||||
import { createDefaultPromotion } from "../../../__fixtures__/promotion"
|
import { createDefaultPromotion } from "../../../__fixtures__/promotion"
|
||||||
|
|
||||||
@@ -177,7 +177,7 @@ moduleIntegrationTestRunner({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addItemAdjustment",
|
action: "addItemAdjustment",
|
||||||
item_id: "item_cotton_tshirt",
|
item_id: "item_cotton_tshirt",
|
||||||
@@ -278,7 +278,7 @@ moduleIntegrationTestRunner({
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addItemAdjustment",
|
action: "addItemAdjustment",
|
||||||
item_id: "item_cotton_tshirt",
|
item_id: "item_cotton_tshirt",
|
||||||
@@ -391,7 +391,7 @@ moduleIntegrationTestRunner({
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addItemAdjustment",
|
action: "addItemAdjustment",
|
||||||
item_id: "item_cotton_tshirt",
|
item_id: "item_cotton_tshirt",
|
||||||
@@ -453,7 +453,7 @@ moduleIntegrationTestRunner({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addItemAdjustment",
|
action: "addItemAdjustment",
|
||||||
item_id: "item_cotton_tshirt",
|
item_id: "item_cotton_tshirt",
|
||||||
@@ -514,7 +514,7 @@ moduleIntegrationTestRunner({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{ action: "campaignBudgetExceeded", code: "PROMOTION_TEST" },
|
{ action: "campaignBudgetExceeded", code: "PROMOTION_TEST" },
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
@@ -578,7 +578,7 @@ moduleIntegrationTestRunner({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addItemAdjustment",
|
action: "addItemAdjustment",
|
||||||
item_id: "item_cotton_tshirt",
|
item_id: "item_cotton_tshirt",
|
||||||
@@ -679,7 +679,7 @@ moduleIntegrationTestRunner({
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addItemAdjustment",
|
action: "addItemAdjustment",
|
||||||
item_id: "item_cotton_tshirt",
|
item_id: "item_cotton_tshirt",
|
||||||
@@ -792,7 +792,7 @@ moduleIntegrationTestRunner({
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addItemAdjustment",
|
action: "addItemAdjustment",
|
||||||
item_id: "item_cotton_tshirt",
|
item_id: "item_cotton_tshirt",
|
||||||
@@ -854,7 +854,7 @@ moduleIntegrationTestRunner({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{ action: "campaignBudgetExceeded", code: "PROMOTION_TEST" },
|
{ action: "campaignBudgetExceeded", code: "PROMOTION_TEST" },
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
@@ -911,7 +911,7 @@ moduleIntegrationTestRunner({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{ action: "campaignBudgetExceeded", code: "PROMOTION_TEST" },
|
{ action: "campaignBudgetExceeded", code: "PROMOTION_TEST" },
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
@@ -977,7 +977,7 @@ moduleIntegrationTestRunner({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addItemAdjustment",
|
action: "addItemAdjustment",
|
||||||
item_id: "item_cotton_tshirt",
|
item_id: "item_cotton_tshirt",
|
||||||
@@ -1050,7 +1050,7 @@ moduleIntegrationTestRunner({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addItemAdjustment",
|
action: "addItemAdjustment",
|
||||||
item_id: "item_cotton_tshirt",
|
item_id: "item_cotton_tshirt",
|
||||||
@@ -1150,7 +1150,7 @@ moduleIntegrationTestRunner({
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addItemAdjustment",
|
action: "addItemAdjustment",
|
||||||
item_id: "item_cotton_tshirt",
|
item_id: "item_cotton_tshirt",
|
||||||
@@ -1262,7 +1262,7 @@ moduleIntegrationTestRunner({
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addItemAdjustment",
|
action: "addItemAdjustment",
|
||||||
item_id: "item_cotton_tshirt",
|
item_id: "item_cotton_tshirt",
|
||||||
@@ -1323,7 +1323,7 @@ moduleIntegrationTestRunner({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{ action: "campaignBudgetExceeded", code: "PROMOTION_TEST" },
|
{ action: "campaignBudgetExceeded", code: "PROMOTION_TEST" },
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
@@ -1379,7 +1379,7 @@ moduleIntegrationTestRunner({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{ action: "campaignBudgetExceeded", code: "PROMOTION_TEST" },
|
{ action: "campaignBudgetExceeded", code: "PROMOTION_TEST" },
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
@@ -1442,7 +1442,7 @@ moduleIntegrationTestRunner({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addItemAdjustment",
|
action: "addItemAdjustment",
|
||||||
item_id: "item_cotton_tshirt",
|
item_id: "item_cotton_tshirt",
|
||||||
@@ -1515,7 +1515,7 @@ moduleIntegrationTestRunner({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addItemAdjustment",
|
action: "addItemAdjustment",
|
||||||
item_id: "item_cotton_tshirt",
|
item_id: "item_cotton_tshirt",
|
||||||
@@ -1614,7 +1614,7 @@ moduleIntegrationTestRunner({
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addItemAdjustment",
|
action: "addItemAdjustment",
|
||||||
item_id: "item_cotton_tshirt",
|
item_id: "item_cotton_tshirt",
|
||||||
@@ -1725,7 +1725,7 @@ moduleIntegrationTestRunner({
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addItemAdjustment",
|
action: "addItemAdjustment",
|
||||||
item_id: "item_cotton_tshirt",
|
item_id: "item_cotton_tshirt",
|
||||||
@@ -1798,7 +1798,7 @@ moduleIntegrationTestRunner({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{ action: "campaignBudgetExceeded", code: "PROMOTION_TEST" },
|
{ action: "campaignBudgetExceeded", code: "PROMOTION_TEST" },
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
@@ -1854,7 +1854,7 @@ moduleIntegrationTestRunner({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{ action: "campaignBudgetExceeded", code: "PROMOTION_TEST" },
|
{ action: "campaignBudgetExceeded", code: "PROMOTION_TEST" },
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
@@ -1919,7 +1919,7 @@ moduleIntegrationTestRunner({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addShippingMethodAdjustment",
|
action: "addShippingMethodAdjustment",
|
||||||
shipping_method_id: "shipping_method_express",
|
shipping_method_id: "shipping_method_express",
|
||||||
@@ -1992,7 +1992,7 @@ moduleIntegrationTestRunner({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addShippingMethodAdjustment",
|
action: "addShippingMethodAdjustment",
|
||||||
shipping_method_id: "shipping_method_express",
|
shipping_method_id: "shipping_method_express",
|
||||||
@@ -2069,7 +2069,7 @@ moduleIntegrationTestRunner({
|
|||||||
{ prevent_auto_promotions: true }
|
{ prevent_auto_promotions: true }
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(result).toEqual([])
|
expect(JSON.parse(JSON.stringify(result))).toEqual([])
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should compute the correct item amendments when there are multiple promotions to apply", async () => {
|
it("should compute the correct item amendments when there are multiple promotions to apply", async () => {
|
||||||
@@ -2156,7 +2156,7 @@ moduleIntegrationTestRunner({
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addShippingMethodAdjustment",
|
action: "addShippingMethodAdjustment",
|
||||||
shipping_method_id: "shipping_method_express",
|
shipping_method_id: "shipping_method_express",
|
||||||
@@ -2262,7 +2262,7 @@ moduleIntegrationTestRunner({
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addShippingMethodAdjustment",
|
action: "addShippingMethodAdjustment",
|
||||||
shipping_method_id: "shipping_method_express",
|
shipping_method_id: "shipping_method_express",
|
||||||
@@ -2320,7 +2320,7 @@ moduleIntegrationTestRunner({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{ action: "campaignBudgetExceeded", code: "PROMOTION_TEST" },
|
{ action: "campaignBudgetExceeded", code: "PROMOTION_TEST" },
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
@@ -2373,7 +2373,7 @@ moduleIntegrationTestRunner({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{ action: "campaignBudgetExceeded", code: "PROMOTION_TEST" },
|
{ action: "campaignBudgetExceeded", code: "PROMOTION_TEST" },
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
@@ -2436,7 +2436,7 @@ moduleIntegrationTestRunner({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addShippingMethodAdjustment",
|
action: "addShippingMethodAdjustment",
|
||||||
shipping_method_id: "shipping_method_express",
|
shipping_method_id: "shipping_method_express",
|
||||||
@@ -2509,7 +2509,7 @@ moduleIntegrationTestRunner({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addShippingMethodAdjustment",
|
action: "addShippingMethodAdjustment",
|
||||||
shipping_method_id: "shipping_method_express",
|
shipping_method_id: "shipping_method_express",
|
||||||
@@ -2586,7 +2586,7 @@ moduleIntegrationTestRunner({
|
|||||||
{ prevent_auto_promotions: true }
|
{ prevent_auto_promotions: true }
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(result).toEqual([])
|
expect(JSON.parse(JSON.stringify(result))).toEqual([])
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should compute the correct item amendments when there are multiple promotions to apply", async () => {
|
it("should compute the correct item amendments when there are multiple promotions to apply", async () => {
|
||||||
@@ -2674,7 +2674,7 @@ moduleIntegrationTestRunner({
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addShippingMethodAdjustment",
|
action: "addShippingMethodAdjustment",
|
||||||
shipping_method_id: "shipping_method_express",
|
shipping_method_id: "shipping_method_express",
|
||||||
@@ -2786,7 +2786,7 @@ moduleIntegrationTestRunner({
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addShippingMethodAdjustment",
|
action: "addShippingMethodAdjustment",
|
||||||
shipping_method_id: "shipping_method_express",
|
shipping_method_id: "shipping_method_express",
|
||||||
@@ -2856,7 +2856,7 @@ moduleIntegrationTestRunner({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{ action: "campaignBudgetExceeded", code: "PROMOTION_TEST" },
|
{ action: "campaignBudgetExceeded", code: "PROMOTION_TEST" },
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
@@ -2909,7 +2909,7 @@ moduleIntegrationTestRunner({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{ action: "campaignBudgetExceeded", code: "PROMOTION_TEST" },
|
{ action: "campaignBudgetExceeded", code: "PROMOTION_TEST" },
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
@@ -2973,17 +2973,17 @@ moduleIntegrationTestRunner({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addShippingMethodAdjustment",
|
action: "addShippingMethodAdjustment",
|
||||||
shipping_method_id: "shipping_method_express",
|
shipping_method_id: "shipping_method_express",
|
||||||
amount: 166.66666666666669,
|
amount: 166.66666666666666,
|
||||||
code: "PROMOTION_TEST",
|
code: "PROMOTION_TEST",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
action: "addShippingMethodAdjustment",
|
action: "addShippingMethodAdjustment",
|
||||||
shipping_method_id: "shipping_method_standard",
|
shipping_method_id: "shipping_method_standard",
|
||||||
amount: 33.33333333333333,
|
amount: 33.333333333333336,
|
||||||
code: "PROMOTION_TEST",
|
code: "PROMOTION_TEST",
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
@@ -3045,17 +3045,17 @@ moduleIntegrationTestRunner({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addShippingMethodAdjustment",
|
action: "addShippingMethodAdjustment",
|
||||||
shipping_method_id: "shipping_method_express",
|
shipping_method_id: "shipping_method_express",
|
||||||
amount: 166.66666666666669,
|
amount: 166.66666666666666,
|
||||||
code: "PROMOTION_TEST",
|
code: "PROMOTION_TEST",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
action: "addShippingMethodAdjustment",
|
action: "addShippingMethodAdjustment",
|
||||||
shipping_method_id: "shipping_method_standard",
|
shipping_method_id: "shipping_method_standard",
|
||||||
amount: 33.33333333333333,
|
amount: 33.333333333333336,
|
||||||
code: "PROMOTION_TEST",
|
code: "PROMOTION_TEST",
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
@@ -3143,17 +3143,17 @@ moduleIntegrationTestRunner({
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addShippingMethodAdjustment",
|
action: "addShippingMethodAdjustment",
|
||||||
shipping_method_id: "shipping_method_express",
|
shipping_method_id: "shipping_method_express",
|
||||||
amount: 166.66666666666669,
|
amount: 166.66666666666666,
|
||||||
code: "PROMOTION_TEST",
|
code: "PROMOTION_TEST",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
action: "addShippingMethodAdjustment",
|
action: "addShippingMethodAdjustment",
|
||||||
shipping_method_id: "shipping_method_standard",
|
shipping_method_id: "shipping_method_standard",
|
||||||
amount: 33.33333333333333,
|
amount: 33.333333333333336,
|
||||||
code: "PROMOTION_TEST",
|
code: "PROMOTION_TEST",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -3253,7 +3253,7 @@ moduleIntegrationTestRunner({
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addShippingMethodAdjustment",
|
action: "addShippingMethodAdjustment",
|
||||||
shipping_method_id: "shipping_method_express",
|
shipping_method_id: "shipping_method_express",
|
||||||
@@ -3310,7 +3310,7 @@ moduleIntegrationTestRunner({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{ action: "campaignBudgetExceeded", code: "PROMOTION_TEST" },
|
{ action: "campaignBudgetExceeded", code: "PROMOTION_TEST" },
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
@@ -3362,7 +3362,7 @@ moduleIntegrationTestRunner({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{ action: "campaignBudgetExceeded", code: "PROMOTION_TEST" },
|
{ action: "campaignBudgetExceeded", code: "PROMOTION_TEST" },
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
@@ -3424,7 +3424,7 @@ moduleIntegrationTestRunner({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addShippingMethodAdjustment",
|
action: "addShippingMethodAdjustment",
|
||||||
shipping_method_id: "shipping_method_express",
|
shipping_method_id: "shipping_method_express",
|
||||||
@@ -3496,7 +3496,7 @@ moduleIntegrationTestRunner({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addShippingMethodAdjustment",
|
action: "addShippingMethodAdjustment",
|
||||||
shipping_method_id: "shipping_method_express",
|
shipping_method_id: "shipping_method_express",
|
||||||
@@ -3594,7 +3594,7 @@ moduleIntegrationTestRunner({
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addShippingMethodAdjustment",
|
action: "addShippingMethodAdjustment",
|
||||||
shipping_method_id: "shipping_method_express",
|
shipping_method_id: "shipping_method_express",
|
||||||
@@ -3704,7 +3704,7 @@ moduleIntegrationTestRunner({
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addShippingMethodAdjustment",
|
action: "addShippingMethodAdjustment",
|
||||||
shipping_method_id: "shipping_method_express",
|
shipping_method_id: "shipping_method_express",
|
||||||
@@ -3767,7 +3767,7 @@ moduleIntegrationTestRunner({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{ action: "campaignBudgetExceeded", code: "PROMOTION_TEST" },
|
{ action: "campaignBudgetExceeded", code: "PROMOTION_TEST" },
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
@@ -3819,7 +3819,7 @@ moduleIntegrationTestRunner({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{ action: "campaignBudgetExceeded", code: "PROMOTION_TEST" },
|
{ action: "campaignBudgetExceeded", code: "PROMOTION_TEST" },
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
@@ -3877,7 +3877,7 @@ moduleIntegrationTestRunner({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addItemAdjustment",
|
action: "addItemAdjustment",
|
||||||
item_id: "item_cotton_tshirt",
|
item_id: "item_cotton_tshirt",
|
||||||
@@ -3944,7 +3944,7 @@ moduleIntegrationTestRunner({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addItemAdjustment",
|
action: "addItemAdjustment",
|
||||||
item_id: "item_cotton_tshirt",
|
item_id: "item_cotton_tshirt",
|
||||||
@@ -4031,7 +4031,7 @@ moduleIntegrationTestRunner({
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addItemAdjustment",
|
action: "addItemAdjustment",
|
||||||
item_id: "item_cotton_tshirt",
|
item_id: "item_cotton_tshirt",
|
||||||
@@ -4130,7 +4130,7 @@ moduleIntegrationTestRunner({
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addItemAdjustment",
|
action: "addItemAdjustment",
|
||||||
item_id: "item_cotton_tshirt",
|
item_id: "item_cotton_tshirt",
|
||||||
@@ -4215,7 +4215,7 @@ moduleIntegrationTestRunner({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "removeItemAdjustment",
|
action: "removeItemAdjustment",
|
||||||
adjustment_id: "test-adjustment",
|
adjustment_id: "test-adjustment",
|
||||||
@@ -4302,7 +4302,7 @@ moduleIntegrationTestRunner({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "removeShippingMethodAdjustment",
|
action: "removeShippingMethodAdjustment",
|
||||||
adjustment_id: "test-adjustment",
|
adjustment_id: "test-adjustment",
|
||||||
@@ -4311,13 +4311,13 @@ moduleIntegrationTestRunner({
|
|||||||
{
|
{
|
||||||
action: "addShippingMethodAdjustment",
|
action: "addShippingMethodAdjustment",
|
||||||
shipping_method_id: "shipping_method_express",
|
shipping_method_id: "shipping_method_express",
|
||||||
amount: 166.66666666666669,
|
amount: 166.66666666666666,
|
||||||
code: "PROMOTION_TEST",
|
code: "PROMOTION_TEST",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
action: "addShippingMethodAdjustment",
|
action: "addShippingMethodAdjustment",
|
||||||
shipping_method_id: "shipping_method_standard",
|
shipping_method_id: "shipping_method_standard",
|
||||||
amount: 33.33333333333333,
|
amount: 33.333333333333336,
|
||||||
code: "PROMOTION_TEST",
|
code: "PROMOTION_TEST",
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
@@ -4408,7 +4408,7 @@ moduleIntegrationTestRunner({
|
|||||||
context
|
context
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addItemAdjustment",
|
action: "addItemAdjustment",
|
||||||
item_id: "item_cotton_tshirt2",
|
item_id: "item_cotton_tshirt2",
|
||||||
@@ -4501,7 +4501,7 @@ moduleIntegrationTestRunner({
|
|||||||
context
|
context
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(result).toEqual([])
|
expect(JSON.parse(JSON.stringify(result))).toEqual([])
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should compute actions for multiple items when conditions for target qty exceed one item", async () => {
|
it("should compute actions for multiple items when conditions for target qty exceed one item", async () => {
|
||||||
@@ -4588,7 +4588,7 @@ moduleIntegrationTestRunner({
|
|||||||
context
|
context
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(JSON.parse(JSON.stringify(result))).toEqual([
|
||||||
{
|
{
|
||||||
action: "addItemAdjustment",
|
action: "addItemAdjustment",
|
||||||
item_id: "item_cotton_tshirt2",
|
item_id: "item_cotton_tshirt2",
|
||||||
@@ -4688,7 +4688,7 @@ moduleIntegrationTestRunner({
|
|||||||
context
|
context
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(result).toEqual([])
|
expect(JSON.parse(JSON.stringify(result))).toEqual([])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import {
|
|||||||
ComputedActions,
|
ComputedActions,
|
||||||
InjectManager,
|
InjectManager,
|
||||||
InjectTransactionManager,
|
InjectTransactionManager,
|
||||||
|
MathBN,
|
||||||
MedusaContext,
|
MedusaContext,
|
||||||
MedusaError,
|
MedusaError,
|
||||||
ModulesSdkUtils,
|
ModulesSdkUtils,
|
||||||
@@ -23,6 +24,7 @@ import {
|
|||||||
isDefined,
|
isDefined,
|
||||||
isPresent,
|
isPresent,
|
||||||
isString,
|
isString,
|
||||||
|
transformPropertiesToBigNumber,
|
||||||
} from "@medusajs/utils"
|
} from "@medusajs/utils"
|
||||||
import {
|
import {
|
||||||
ApplicationMethod,
|
ApplicationMethod,
|
||||||
@@ -176,12 +178,14 @@ export default class PromotionModuleService<
|
|||||||
campaignBudget.id
|
campaignBudget.id
|
||||||
) || { id: campaignBudget.id, used: campaignBudget.used ?? 0 }
|
) || { id: campaignBudget.id, used: campaignBudget.used ?? 0 }
|
||||||
|
|
||||||
campaignBudgetData.used =
|
campaignBudgetData.used = MathBN.add(
|
||||||
(campaignBudgetData.used ?? 0) + computedAction.amount
|
campaignBudgetData.used ?? 0,
|
||||||
|
computedAction.amount
|
||||||
|
)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
campaignBudget.limit &&
|
campaignBudget.limit &&
|
||||||
campaignBudgetData.used > campaignBudget.limit
|
MathBN.gt(campaignBudgetData.used, campaignBudget.limit)
|
||||||
) {
|
) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -202,12 +206,12 @@ export default class PromotionModuleService<
|
|||||||
|
|
||||||
const campaignBudgetData = {
|
const campaignBudgetData = {
|
||||||
id: campaignBudget.id,
|
id: campaignBudget.id,
|
||||||
used: (campaignBudget.used ?? 0) + 1,
|
used: MathBN.add(campaignBudget.used ?? 0, 1),
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
campaignBudget.limit &&
|
campaignBudget.limit &&
|
||||||
campaignBudgetData.used > campaignBudget.limit
|
MathBN.gt(campaignBudgetData.used, campaignBudget.limit)
|
||||||
) {
|
) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -424,6 +428,8 @@ export default class PromotionModuleService<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
transformPropertiesToBigNumber(computedActions, { include: ["amount"] })
|
||||||
|
|
||||||
return computedActions
|
return computedActions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import {
|
|||||||
ApplicationMethodAllocationValues,
|
ApplicationMethodAllocationValues,
|
||||||
ApplicationMethodTargetTypeValues,
|
ApplicationMethodTargetTypeValues,
|
||||||
ApplicationMethodTypeValues,
|
ApplicationMethodTypeValues,
|
||||||
|
BigNumberInput,
|
||||||
PromotionDTO,
|
PromotionDTO,
|
||||||
} from "@medusajs/types"
|
} from "@medusajs/types"
|
||||||
|
|
||||||
@@ -11,12 +12,12 @@ export interface CreateApplicationMethodDTO {
|
|||||||
type: ApplicationMethodTypeValues
|
type: ApplicationMethodTypeValues
|
||||||
target_type: ApplicationMethodTargetTypeValues
|
target_type: ApplicationMethodTargetTypeValues
|
||||||
allocation?: ApplicationMethodAllocationValues
|
allocation?: ApplicationMethodAllocationValues
|
||||||
value?: number
|
value?: BigNumberInput
|
||||||
currency_code: string
|
currency_code: string
|
||||||
promotion: Promotion | string | PromotionDTO
|
promotion: Promotion | string | PromotionDTO
|
||||||
max_quantity?: number | null
|
max_quantity?: BigNumberInput | null
|
||||||
buy_rules_min_quantity?: number | null
|
buy_rules_min_quantity?: BigNumberInput | null
|
||||||
apply_to_quantity?: number | null
|
apply_to_quantity?: BigNumberInput | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UpdateApplicationMethodDTO {
|
export interface UpdateApplicationMethodDTO {
|
||||||
@@ -24,10 +25,10 @@ export interface UpdateApplicationMethodDTO {
|
|||||||
type?: ApplicationMethodTypeValues
|
type?: ApplicationMethodTypeValues
|
||||||
target_type?: ApplicationMethodTargetTypeValues
|
target_type?: ApplicationMethodTargetTypeValues
|
||||||
allocation?: ApplicationMethodAllocationValues
|
allocation?: ApplicationMethodAllocationValues
|
||||||
value?: number
|
value?: BigNumberInput
|
||||||
currency_code?: string
|
currency_code?: string
|
||||||
promotion?: Promotion | string | PromotionDTO
|
promotion?: Promotion | string | PromotionDTO
|
||||||
max_quantity?: number | null
|
max_quantity?: BigNumberInput | null
|
||||||
buy_rules_min_quantity?: number | null
|
buy_rules_min_quantity?: BigNumberInput | null
|
||||||
apply_to_quantity?: number | null
|
apply_to_quantity?: BigNumberInput | null
|
||||||
}
|
}
|
||||||
@@ -1,18 +1,18 @@
|
|||||||
import { CampaignBudgetTypeValues } from "@medusajs/types"
|
import { BigNumberInput, CampaignBudgetTypeValues } from "@medusajs/types"
|
||||||
import { Campaign } from "@models"
|
import { Campaign } from "@models"
|
||||||
|
|
||||||
export interface CreateCampaignBudgetDTO {
|
export interface CreateCampaignBudgetDTO {
|
||||||
type?: CampaignBudgetTypeValues
|
type?: CampaignBudgetTypeValues
|
||||||
limit?: number | null
|
limit?: BigNumberInput | null
|
||||||
currency_code?: string | null
|
currency_code?: string | null
|
||||||
used?: number
|
used?: BigNumberInput
|
||||||
campaign?: Campaign | string
|
campaign?: Campaign | string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UpdateCampaignBudgetDTO {
|
export interface UpdateCampaignBudgetDTO {
|
||||||
id: string
|
id: string
|
||||||
type?: CampaignBudgetTypeValues
|
type?: CampaignBudgetTypeValues
|
||||||
limit?: number | null
|
limit?: BigNumberInput | null
|
||||||
currency_code?: string | null
|
currency_code?: string | null
|
||||||
used?: number
|
used?: BigNumberInput
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
import { PromotionTypes } from "@medusajs/types"
|
import { BigNumberInput, PromotionTypes } from "@medusajs/types"
|
||||||
import {
|
import {
|
||||||
ApplicationMethodTargetType,
|
ApplicationMethodTargetType,
|
||||||
ComputedActions,
|
ComputedActions,
|
||||||
|
MathBN,
|
||||||
MedusaError,
|
MedusaError,
|
||||||
PromotionType,
|
PromotionType,
|
||||||
isPresent,
|
isPresent,
|
||||||
@@ -13,7 +14,7 @@ import { computeActionForBudgetExceeded } from "./usage"
|
|||||||
export function getComputedActionsForBuyGet(
|
export function getComputedActionsForBuyGet(
|
||||||
promotion: PromotionTypes.PromotionDTO,
|
promotion: PromotionTypes.PromotionDTO,
|
||||||
itemsContext: PromotionTypes.ComputeActionContext[ApplicationMethodTargetType.ITEMS],
|
itemsContext: PromotionTypes.ComputeActionContext[ApplicationMethodTargetType.ITEMS],
|
||||||
methodIdPromoValueMap: Map<string, number>
|
methodIdPromoValueMap: Map<string, BigNumberInput>
|
||||||
): PromotionTypes.ComputeActions[] {
|
): PromotionTypes.ComputeActions[] {
|
||||||
const buyRulesMinQuantity =
|
const buyRulesMinQuantity =
|
||||||
promotion.application_method?.buy_rules_min_quantity
|
promotion.application_method?.buy_rules_min_quantity
|
||||||
@@ -33,14 +34,16 @@ export function getComputedActionsForBuyGet(
|
|||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
const validQuantity = itemsContext
|
const validQuantity = MathBN.sum(
|
||||||
|
...itemsContext
|
||||||
.filter((item) => areRulesValidForContext(buyRules, item))
|
.filter((item) => areRulesValidForContext(buyRules, item))
|
||||||
.reduce((acc, next) => acc + next.quantity, 0)
|
.map((item) => item.quantity)
|
||||||
|
)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!buyRulesMinQuantity ||
|
!buyRulesMinQuantity ||
|
||||||
!applyToQuantity ||
|
!applyToQuantity ||
|
||||||
buyRulesMinQuantity > validQuantity
|
MathBN.gt(buyRulesMinQuantity, validQuantity)
|
||||||
) {
|
) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
@@ -49,21 +52,24 @@ export function getComputedActionsForBuyGet(
|
|||||||
.filter((item) => areRulesValidForContext(targetRules, item))
|
.filter((item) => areRulesValidForContext(targetRules, item))
|
||||||
.filter((item) => isPresent(item.subtotal) && isPresent(item.quantity))
|
.filter((item) => isPresent(item.subtotal) && isPresent(item.quantity))
|
||||||
.sort((a, b) => {
|
.sort((a, b) => {
|
||||||
const aPrice = a.subtotal / a.quantity
|
const aPrice = MathBN.div(a.subtotal, a.quantity)
|
||||||
const bPrice = b.subtotal / b.quantity
|
const bPrice = MathBN.div(b.subtotal, b.quantity)
|
||||||
|
|
||||||
return bPrice - aPrice
|
return MathBN.lt(bPrice, aPrice) ? -1 : 1
|
||||||
})
|
})
|
||||||
|
|
||||||
let remainingQtyToApply = applyToQuantity
|
let remainingQtyToApply = MathBN.convert(applyToQuantity)
|
||||||
|
|
||||||
for (const method of validItemsForTargetRules) {
|
for (const method of validItemsForTargetRules) {
|
||||||
const appliedPromoValue = methodIdPromoValueMap.get(method.id) ?? 0
|
const appliedPromoValue = methodIdPromoValueMap.get(method.id) ?? 0
|
||||||
const multiplier = Math.min(method.quantity, remainingQtyToApply)
|
const multiplier = MathBN.min(method.quantity, remainingQtyToApply)
|
||||||
const amount = (method.subtotal / method.quantity) * multiplier
|
const amount = MathBN.mult(
|
||||||
const newRemainingQtyToApply = remainingQtyToApply - multiplier
|
MathBN.div(method.subtotal, method.quantity),
|
||||||
|
multiplier
|
||||||
|
)
|
||||||
|
const newRemainingQtyToApply = MathBN.sub(remainingQtyToApply, multiplier)
|
||||||
|
|
||||||
if (newRemainingQtyToApply < 0 || amount <= 0) {
|
if (MathBN.lt(newRemainingQtyToApply, 0) || MathBN.lte(amount, 0)) {
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
remainingQtyToApply = newRemainingQtyToApply
|
remainingQtyToApply = newRemainingQtyToApply
|
||||||
@@ -80,7 +86,7 @@ export function getComputedActionsForBuyGet(
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
methodIdPromoValueMap.set(method.id, appliedPromoValue + amount)
|
methodIdPromoValueMap.set(method.id, MathBN.add(appliedPromoValue, amount))
|
||||||
|
|
||||||
computedActions.push({
|
computedActions.push({
|
||||||
action: ComputedActions.ADD_ITEM_ADJUSTMENT,
|
action: ComputedActions.ADD_ITEM_ADJUSTMENT,
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import {
|
import {
|
||||||
ApplicationMethodAllocationValues,
|
ApplicationMethodAllocationValues,
|
||||||
|
BigNumberInput,
|
||||||
PromotionTypes,
|
PromotionTypes,
|
||||||
} from "@medusajs/types"
|
} from "@medusajs/types"
|
||||||
import {
|
import {
|
||||||
ApplicationMethodAllocation,
|
ApplicationMethodAllocation,
|
||||||
ComputedActions,
|
ComputedActions,
|
||||||
|
MathBN,
|
||||||
MedusaError,
|
MedusaError,
|
||||||
ApplicationMethodTargetType as TargetType,
|
ApplicationMethodTargetType as TargetType,
|
||||||
calculateAdjustmentAmountFromPromotion,
|
calculateAdjustmentAmountFromPromotion,
|
||||||
@@ -68,7 +70,7 @@ function applyPromotionToItems(
|
|||||||
items:
|
items:
|
||||||
| PromotionTypes.ComputeActionContext[TargetType.ITEMS]
|
| PromotionTypes.ComputeActionContext[TargetType.ITEMS]
|
||||||
| PromotionTypes.ComputeActionContext[TargetType.SHIPPING_METHODS],
|
| PromotionTypes.ComputeActionContext[TargetType.SHIPPING_METHODS],
|
||||||
appliedPromotionsMap: Map<string, number>,
|
appliedPromotionsMap: Map<string, BigNumberInput>,
|
||||||
allocationOverride?: ApplicationMethodAllocationValues
|
allocationOverride?: ApplicationMethodAllocationValues
|
||||||
): PromotionTypes.ComputeActions[] {
|
): PromotionTypes.ComputeActions[] {
|
||||||
const { application_method: applicationMethod } = promotion
|
const { application_method: applicationMethod } = promotion
|
||||||
@@ -81,13 +83,16 @@ function applyPromotionToItems(
|
|||||||
const isTargetLineItems = target === TargetType.ITEMS
|
const isTargetLineItems = target === TargetType.ITEMS
|
||||||
const isTargetOrder = target === TargetType.ORDER
|
const isTargetOrder = target === TargetType.ORDER
|
||||||
|
|
||||||
let lineItemsTotal = 0
|
let lineItemsTotal = MathBN.convert(0)
|
||||||
|
|
||||||
if (allocation === ApplicationMethodAllocation.ACROSS) {
|
if (allocation === ApplicationMethodAllocation.ACROSS) {
|
||||||
lineItemsTotal = applicableItems.reduce(
|
lineItemsTotal = applicableItems.reduce(
|
||||||
(acc, item) =>
|
(acc, item) =>
|
||||||
acc + item.subtotal - (appliedPromotionsMap.get(item.id) ?? 0),
|
MathBN.sub(
|
||||||
0
|
MathBN.add(acc, item.subtotal),
|
||||||
|
appliedPromotionsMap.get(item.id) ?? 0
|
||||||
|
),
|
||||||
|
MathBN.convert(0)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,7 +118,7 @@ function applyPromotionToItems(
|
|||||||
lineItemsTotal
|
lineItemsTotal
|
||||||
)
|
)
|
||||||
|
|
||||||
if (amount <= 0) {
|
if (MathBN.lte(amount, 0)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,7 +133,7 @@ function applyPromotionToItems(
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
appliedPromotionsMap.set(item.id, appliedPromoValue + amount)
|
appliedPromotionsMap.set(item.id, MathBN.add(appliedPromoValue, amount))
|
||||||
|
|
||||||
if (isTargetLineItems || isTargetOrder) {
|
if (isTargetLineItems || isTargetOrder) {
|
||||||
computedActions.push({
|
computedActions.push({
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import { PromotionTypes } from "@medusajs/types"
|
import { BigNumberInput, PromotionTypes } from "@medusajs/types"
|
||||||
import {
|
import {
|
||||||
ApplicationMethodAllocation,
|
ApplicationMethodAllocation,
|
||||||
ApplicationMethodTargetType,
|
ApplicationMethodTargetType,
|
||||||
ApplicationMethodType,
|
ApplicationMethodType,
|
||||||
ComputedActions,
|
ComputedActions,
|
||||||
|
MathBN,
|
||||||
MedusaError,
|
MedusaError,
|
||||||
} from "@medusajs/utils"
|
} from "@medusajs/utils"
|
||||||
import { areRulesValidForContext } from "../validations"
|
import { areRulesValidForContext } from "../validations"
|
||||||
@@ -47,7 +48,7 @@ export function getComputedActionsForShippingMethods(
|
|||||||
export function applyPromotionToShippingMethods(
|
export function applyPromotionToShippingMethods(
|
||||||
promotion: PromotionTypes.PromotionDTO,
|
promotion: PromotionTypes.PromotionDTO,
|
||||||
shippingMethods: PromotionTypes.ComputeActionContext[ApplicationMethodTargetType.SHIPPING_METHODS],
|
shippingMethods: PromotionTypes.ComputeActionContext[ApplicationMethodTargetType.SHIPPING_METHODS],
|
||||||
methodIdPromoValueMap: Map<string, number>
|
methodIdPromoValueMap: Map<string, BigNumberInput>
|
||||||
): PromotionTypes.ComputeActions[] {
|
): PromotionTypes.ComputeActions[] {
|
||||||
const { application_method: applicationMethod } = promotion
|
const { application_method: applicationMethod } = promotion
|
||||||
const allocation = applicationMethod?.allocation!
|
const allocation = applicationMethod?.allocation!
|
||||||
@@ -60,16 +61,19 @@ export function applyPromotionToShippingMethods(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const appliedPromoValue = methodIdPromoValueMap.get(method.id) ?? 0
|
const appliedPromoValue = methodIdPromoValueMap.get(method.id) ?? 0
|
||||||
let promotionValue = applicationMethod?.value ?? 0
|
let promotionValue = MathBN.convert(applicationMethod?.value ?? 0)
|
||||||
const applicableTotal = method.subtotal - appliedPromoValue
|
const applicableTotal = MathBN.sub(method.subtotal, appliedPromoValue)
|
||||||
|
|
||||||
if (applicationMethod?.type === ApplicationMethodType.PERCENTAGE) {
|
if (applicationMethod?.type === ApplicationMethodType.PERCENTAGE) {
|
||||||
promotionValue = (promotionValue / 100) * applicableTotal
|
promotionValue = MathBN.mult(
|
||||||
|
MathBN.div(promotionValue, 100),
|
||||||
|
applicableTotal
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const amount = Math.min(promotionValue, applicableTotal)
|
const amount = MathBN.min(promotionValue, applicableTotal)
|
||||||
|
|
||||||
if (amount <= 0) {
|
if (MathBN.lte(amount, 0)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,7 +88,10 @@ export function applyPromotionToShippingMethods(
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
methodIdPromoValueMap.set(method.id, appliedPromoValue + amount)
|
methodIdPromoValueMap.set(
|
||||||
|
method.id,
|
||||||
|
MathBN.add(appliedPromoValue, amount)
|
||||||
|
)
|
||||||
|
|
||||||
computedActions.push({
|
computedActions.push({
|
||||||
action: ComputedActions.ADD_SHIPPING_METHOD_ADJUSTMENT,
|
action: ComputedActions.ADD_SHIPPING_METHOD_ADJUSTMENT,
|
||||||
@@ -99,10 +106,13 @@ export function applyPromotionToShippingMethods(
|
|||||||
const totalApplicableValue = shippingMethods!.reduce((acc, method) => {
|
const totalApplicableValue = shippingMethods!.reduce((acc, method) => {
|
||||||
const appliedPromoValue = methodIdPromoValueMap.get(method.id) ?? 0
|
const appliedPromoValue = methodIdPromoValueMap.get(method.id) ?? 0
|
||||||
|
|
||||||
return acc + (method.subtotal ?? 0) - appliedPromoValue
|
return MathBN.add(
|
||||||
}, 0)
|
acc,
|
||||||
|
MathBN.sub(method.subtotal ?? 0, appliedPromoValue)
|
||||||
|
)
|
||||||
|
}, MathBN.convert(0))
|
||||||
|
|
||||||
if (totalApplicableValue <= 0) {
|
if (MathBN.lte(totalApplicableValue, 0)) {
|
||||||
return computedActions
|
return computedActions
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,19 +125,24 @@ export function applyPromotionToShippingMethods(
|
|||||||
const applicableTotal = method.subtotal
|
const applicableTotal = method.subtotal
|
||||||
const appliedPromoValue = methodIdPromoValueMap.get(method.id) ?? 0
|
const appliedPromoValue = methodIdPromoValueMap.get(method.id) ?? 0
|
||||||
|
|
||||||
// TODO: should we worry about precision here?
|
let applicablePromotionValue = MathBN.sub(
|
||||||
let applicablePromotionValue =
|
MathBN.mult(
|
||||||
(applicableTotal / totalApplicableValue) * promotionValue -
|
MathBN.div(applicableTotal, totalApplicableValue),
|
||||||
|
promotionValue
|
||||||
|
),
|
||||||
appliedPromoValue
|
appliedPromoValue
|
||||||
|
)
|
||||||
|
|
||||||
if (applicationMethod?.type === ApplicationMethodType.PERCENTAGE) {
|
if (applicationMethod?.type === ApplicationMethodType.PERCENTAGE) {
|
||||||
applicablePromotionValue =
|
applicablePromotionValue = MathBN.sub(
|
||||||
(promotionValue / 100) * (applicableTotal - appliedPromoValue)
|
MathBN.mult(MathBN.div(promotionValue, 100), applicableTotal),
|
||||||
|
appliedPromoValue
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const amount = Math.min(applicablePromotionValue, applicableTotal)
|
const amount = MathBN.min(applicablePromotionValue, applicableTotal)
|
||||||
|
|
||||||
if (amount <= 0) {
|
if (MathBN.lte(amount, 0)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,7 +157,10 @@ export function applyPromotionToShippingMethods(
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
methodIdPromoValueMap.set(method.id, appliedPromoValue + amount)
|
methodIdPromoValueMap.set(
|
||||||
|
method.id,
|
||||||
|
MathBN.add(appliedPromoValue, amount)
|
||||||
|
)
|
||||||
|
|
||||||
computedActions.push({
|
computedActions.push({
|
||||||
action: ComputedActions.ADD_SHIPPING_METHOD_ADJUSTMENT,
|
action: ComputedActions.ADD_SHIPPING_METHOD_ADJUSTMENT,
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import {
|
import {
|
||||||
|
BigNumberInput,
|
||||||
CampaignBudgetExceededAction,
|
CampaignBudgetExceededAction,
|
||||||
ComputeActions,
|
ComputeActions,
|
||||||
PromotionDTO,
|
PromotionDTO,
|
||||||
} from "@medusajs/types"
|
} from "@medusajs/types"
|
||||||
import { CampaignBudgetType, ComputedActions } from "@medusajs/utils"
|
import { CampaignBudgetType, ComputedActions, MathBN } from "@medusajs/utils"
|
||||||
|
|
||||||
export function canRegisterUsage(computedAction: ComputeActions): boolean {
|
export function canRegisterUsage(computedAction: ComputeActions): boolean {
|
||||||
return (
|
return (
|
||||||
@@ -16,7 +17,7 @@ export function canRegisterUsage(computedAction: ComputeActions): boolean {
|
|||||||
|
|
||||||
export function computeActionForBudgetExceeded(
|
export function computeActionForBudgetExceeded(
|
||||||
promotion: PromotionDTO,
|
promotion: PromotionDTO,
|
||||||
amount: number
|
amount: BigNumberInput
|
||||||
): CampaignBudgetExceededAction | void {
|
): CampaignBudgetExceededAction | void {
|
||||||
const campaignBudget = promotion.campaign?.budget
|
const campaignBudget = promotion.campaign?.budget
|
||||||
|
|
||||||
@@ -27,10 +28,10 @@ export function computeActionForBudgetExceeded(
|
|||||||
const campaignBudgetUsed = campaignBudget.used ?? 0
|
const campaignBudgetUsed = campaignBudget.used ?? 0
|
||||||
const totalUsed =
|
const totalUsed =
|
||||||
campaignBudget.type === CampaignBudgetType.SPEND
|
campaignBudget.type === CampaignBudgetType.SPEND
|
||||||
? campaignBudgetUsed + amount
|
? MathBN.add(campaignBudgetUsed, amount)
|
||||||
: campaignBudgetUsed + 1
|
: MathBN.add(campaignBudgetUsed, 1)
|
||||||
|
|
||||||
if (campaignBudget.limit && totalUsed > campaignBudget.limit) {
|
if (campaignBudget.limit && MathBN.gt(totalUsed, campaignBudget.limit)) {
|
||||||
return {
|
return {
|
||||||
action: ComputedActions.CAMPAIGN_BUDGET_EXCEEDED,
|
action: ComputedActions.CAMPAIGN_BUDGET_EXCEEDED,
|
||||||
code: promotion.code!,
|
code: promotion.code!,
|
||||||
|
|||||||
@@ -2,8 +2,10 @@ import {
|
|||||||
ApplicationMethodAllocation,
|
ApplicationMethodAllocation,
|
||||||
ApplicationMethodTargetType,
|
ApplicationMethodTargetType,
|
||||||
ApplicationMethodType,
|
ApplicationMethodType,
|
||||||
|
BigNumber,
|
||||||
isDefined,
|
isDefined,
|
||||||
isPresent,
|
isPresent,
|
||||||
|
MathBN,
|
||||||
MedusaError,
|
MedusaError,
|
||||||
PromotionType,
|
PromotionType,
|
||||||
} from "@medusajs/utils"
|
} from "@medusajs/utils"
|
||||||
@@ -36,14 +38,14 @@ export function validateApplicationMethodAttributes(
|
|||||||
const targetType = data.target_type || applicationMethod?.target_type
|
const targetType = data.target_type || applicationMethod?.target_type
|
||||||
const type = data.type || applicationMethod?.type
|
const type = data.type || applicationMethod?.type
|
||||||
const applicationMethodType = data.type || applicationMethod?.type
|
const applicationMethodType = data.type || applicationMethod?.type
|
||||||
const value = data.value || applicationMethod.value
|
const value = new BigNumber(data.value ?? applicationMethod.value ?? 0)
|
||||||
const maxQuantity = data.max_quantity || applicationMethod.max_quantity
|
const maxQuantity = data.max_quantity || applicationMethod.max_quantity
|
||||||
const allocation = data.allocation || applicationMethod.allocation
|
const allocation = data.allocation || applicationMethod.allocation
|
||||||
const allTargetTypes: string[] = Object.values(ApplicationMethodTargetType)
|
const allTargetTypes: string[] = Object.values(ApplicationMethodTargetType)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
type === ApplicationMethodType.PERCENTAGE &&
|
type === ApplicationMethodType.PERCENTAGE &&
|
||||||
(typeof value !== "number" || value <= 0 || value > 100)
|
(MathBN.lte(value, 0) || MathBN.gt(value, 100))
|
||||||
) {
|
) {
|
||||||
throw new MedusaError(
|
throw new MedusaError(
|
||||||
MedusaError.Types.INVALID_DATA,
|
MedusaError.Types.INVALID_DATA,
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { PromotionRuleDTO, PromotionRuleOperatorValues } from "@medusajs/types"
|
import { PromotionRuleDTO, PromotionRuleOperatorValues } from "@medusajs/types"
|
||||||
import {
|
import {
|
||||||
|
MedusaError,
|
||||||
|
PromotionRuleOperator,
|
||||||
isPresent,
|
isPresent,
|
||||||
isString,
|
isString,
|
||||||
MedusaError,
|
|
||||||
pickValueFromObject,
|
pickValueFromObject,
|
||||||
PromotionRuleOperator,
|
|
||||||
} from "@medusajs/utils"
|
} from "@medusajs/utils"
|
||||||
import { CreatePromotionRuleDTO } from "@types"
|
import { CreatePromotionRuleDTO } from "@types"
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user