feat(): added compute actions for buyget promotions (#6255)
what: - computes actions for buyget promotion (RESOLVES CORE-1700)
This commit is contained in:
+391
-33
@@ -38,44 +38,40 @@ describe("Promotion Service: computeActions", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe("when code is not present in database", () => {
|
describe("when code is not present in database", () => {
|
||||||
it("should throw error when code in promotions array does not exist", async () => {
|
it("should return empty array when promotion does not exist", async () => {
|
||||||
const error = await service
|
const response = await service.computeActions(["DOES_NOT_EXIST"], {
|
||||||
.computeActions(["DOES_NOT_EXIST"], {
|
customer: {
|
||||||
customer: {
|
customer_group: {
|
||||||
customer_group: {
|
id: "VIP",
|
||||||
id: "VIP",
|
},
|
||||||
|
},
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
id: "item_cotton_tshirt",
|
||||||
|
quantity: 1,
|
||||||
|
unit_price: 100,
|
||||||
|
product_category: {
|
||||||
|
id: "catg_cotton",
|
||||||
|
},
|
||||||
|
product: {
|
||||||
|
id: "prod_tshirt",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
items: [
|
{
|
||||||
{
|
id: "item_cotton_sweater",
|
||||||
id: "item_cotton_tshirt",
|
quantity: 5,
|
||||||
quantity: 1,
|
unit_price: 150,
|
||||||
unit_price: 100,
|
product_category: {
|
||||||
product_category: {
|
id: "catg_cotton",
|
||||||
id: "catg_cotton",
|
|
||||||
},
|
|
||||||
product: {
|
|
||||||
id: "prod_tshirt",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
product: {
|
||||||
id: "item_cotton_sweater",
|
id: "prod_sweater",
|
||||||
quantity: 5,
|
|
||||||
unit_price: 150,
|
|
||||||
product_category: {
|
|
||||||
id: "catg_cotton",
|
|
||||||
},
|
|
||||||
product: {
|
|
||||||
id: "prod_sweater",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
],
|
},
|
||||||
})
|
],
|
||||||
.catch((e) => e)
|
})
|
||||||
|
|
||||||
expect(error.message).toContain(
|
expect(response).toEqual([])
|
||||||
"Promotion for code (DOES_NOT_EXIST) not found"
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should throw error when code in items adjustment does not exist", async () => {
|
it("should throw error when code in items adjustment does not exist", async () => {
|
||||||
@@ -2315,4 +2311,366 @@ describe("Promotion Service: computeActions", () => {
|
|||||||
])
|
])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("when promotion of type buyget", () => {
|
||||||
|
it("should compute adjustment when target and buy rules match", async () => {
|
||||||
|
const context = {
|
||||||
|
customer: {
|
||||||
|
customer_group: {
|
||||||
|
id: "VIP",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
id: "item_cotton_tshirt",
|
||||||
|
quantity: 2,
|
||||||
|
unit_price: 500,
|
||||||
|
product_category: {
|
||||||
|
id: "catg_tshirt",
|
||||||
|
},
|
||||||
|
product: {
|
||||||
|
id: "prod_tshirt_1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "item_cotton_tshirt2",
|
||||||
|
quantity: 2,
|
||||||
|
unit_price: 1000,
|
||||||
|
product_category: {
|
||||||
|
id: "catg_tshirt",
|
||||||
|
},
|
||||||
|
product: {
|
||||||
|
id: "prod_tshirt_2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "item_cotton_sweater",
|
||||||
|
quantity: 2,
|
||||||
|
unit_price: 1000,
|
||||||
|
product_category: {
|
||||||
|
id: "catg_sweater",
|
||||||
|
},
|
||||||
|
product: {
|
||||||
|
id: "prod_sweater_1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
const [createdPromotion] = await service.create([
|
||||||
|
{
|
||||||
|
code: "PROMOTION_TEST",
|
||||||
|
type: PromotionType.BUYGET,
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
attribute: "customer.customer_group.id",
|
||||||
|
operator: "in",
|
||||||
|
values: ["VIP", "top100"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
application_method: {
|
||||||
|
type: "fixed",
|
||||||
|
target_type: "items",
|
||||||
|
allocation: "each",
|
||||||
|
max_quantity: 1,
|
||||||
|
apply_to_quantity: 1,
|
||||||
|
buy_rules_min_quantity: 1,
|
||||||
|
target_rules: [
|
||||||
|
{
|
||||||
|
attribute: "product_category.id",
|
||||||
|
operator: "eq",
|
||||||
|
values: ["catg_tshirt"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
buy_rules: [
|
||||||
|
{
|
||||||
|
attribute: "product_category.id",
|
||||||
|
operator: "eq",
|
||||||
|
values: ["catg_sweater"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const result = await service.computeActions(["PROMOTION_TEST"], context)
|
||||||
|
|
||||||
|
expect(result).toEqual([
|
||||||
|
{
|
||||||
|
action: "addItemAdjustment",
|
||||||
|
item_id: "item_cotton_tshirt2",
|
||||||
|
amount: 1000,
|
||||||
|
code: "PROMOTION_TEST",
|
||||||
|
},
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should return empty array when conditions for minimum qty aren't met", async () => {
|
||||||
|
const context = {
|
||||||
|
customer: {
|
||||||
|
customer_group: {
|
||||||
|
id: "VIP",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
id: "item_cotton_tshirt",
|
||||||
|
quantity: 2,
|
||||||
|
unit_price: 500,
|
||||||
|
product_category: {
|
||||||
|
id: "catg_tshirt",
|
||||||
|
},
|
||||||
|
product: {
|
||||||
|
id: "prod_tshirt_1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "item_cotton_tshirt2",
|
||||||
|
quantity: 2,
|
||||||
|
unit_price: 1000,
|
||||||
|
product_category: {
|
||||||
|
id: "catg_tshirt",
|
||||||
|
},
|
||||||
|
product: {
|
||||||
|
id: "prod_tshirt_2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "item_cotton_sweater",
|
||||||
|
quantity: 2,
|
||||||
|
unit_price: 1000,
|
||||||
|
product_category: {
|
||||||
|
id: "catg_sweater",
|
||||||
|
},
|
||||||
|
product: {
|
||||||
|
id: "prod_sweater_1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
const [createdPromotion] = await service.create([
|
||||||
|
{
|
||||||
|
code: "PROMOTION_TEST",
|
||||||
|
type: PromotionType.BUYGET,
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
attribute: "customer.customer_group.id",
|
||||||
|
operator: "in",
|
||||||
|
values: ["VIP", "top100"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
application_method: {
|
||||||
|
type: "fixed",
|
||||||
|
target_type: "items",
|
||||||
|
allocation: "each",
|
||||||
|
max_quantity: 1,
|
||||||
|
apply_to_quantity: 1,
|
||||||
|
buy_rules_min_quantity: 4,
|
||||||
|
target_rules: [
|
||||||
|
{
|
||||||
|
attribute: "product_category.id",
|
||||||
|
operator: "eq",
|
||||||
|
values: ["catg_tshirt"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
buy_rules: [
|
||||||
|
{
|
||||||
|
attribute: "product_category.id",
|
||||||
|
operator: "eq",
|
||||||
|
values: ["catg_sweater"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const result = await service.computeActions(["PROMOTION_TEST"], context)
|
||||||
|
|
||||||
|
expect(result).toEqual([])
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should compute actions for multiple items when conditions for target qty exceed one item", async () => {
|
||||||
|
const context = {
|
||||||
|
customer: {
|
||||||
|
customer_group: {
|
||||||
|
id: "VIP",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
id: "item_cotton_tshirt",
|
||||||
|
quantity: 2,
|
||||||
|
unit_price: 500,
|
||||||
|
product_category: {
|
||||||
|
id: "catg_tshirt",
|
||||||
|
},
|
||||||
|
product: {
|
||||||
|
id: "prod_tshirt_1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "item_cotton_tshirt2",
|
||||||
|
quantity: 2,
|
||||||
|
unit_price: 1000,
|
||||||
|
product_category: {
|
||||||
|
id: "catg_tshirt",
|
||||||
|
},
|
||||||
|
product: {
|
||||||
|
id: "prod_tshirt_2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "item_cotton_sweater",
|
||||||
|
quantity: 2,
|
||||||
|
unit_price: 1000,
|
||||||
|
product_category: {
|
||||||
|
id: "catg_sweater",
|
||||||
|
},
|
||||||
|
product: {
|
||||||
|
id: "prod_sweater_1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
const [createdPromotion] = await service.create([
|
||||||
|
{
|
||||||
|
code: "PROMOTION_TEST",
|
||||||
|
type: PromotionType.BUYGET,
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
attribute: "customer.customer_group.id",
|
||||||
|
operator: "in",
|
||||||
|
values: ["VIP", "top100"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
application_method: {
|
||||||
|
type: "fixed",
|
||||||
|
target_type: "items",
|
||||||
|
allocation: "each",
|
||||||
|
max_quantity: 1,
|
||||||
|
apply_to_quantity: 4,
|
||||||
|
buy_rules_min_quantity: 1,
|
||||||
|
target_rules: [
|
||||||
|
{
|
||||||
|
attribute: "product_category.id",
|
||||||
|
operator: "eq",
|
||||||
|
values: ["catg_tshirt"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
buy_rules: [
|
||||||
|
{
|
||||||
|
attribute: "product_category.id",
|
||||||
|
operator: "eq",
|
||||||
|
values: ["catg_sweater"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const result = await service.computeActions(["PROMOTION_TEST"], context)
|
||||||
|
|
||||||
|
expect(result).toEqual([
|
||||||
|
{
|
||||||
|
action: "addItemAdjustment",
|
||||||
|
item_id: "item_cotton_tshirt2",
|
||||||
|
amount: 2000,
|
||||||
|
code: "PROMOTION_TEST",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: "addItemAdjustment",
|
||||||
|
item_id: "item_cotton_tshirt",
|
||||||
|
amount: 1000,
|
||||||
|
code: "PROMOTION_TEST",
|
||||||
|
},
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should return empty array when target rules arent met with context", async () => {
|
||||||
|
const context = {
|
||||||
|
customer: {
|
||||||
|
customer_group: {
|
||||||
|
id: "VIP",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
id: "item_cotton_tshirt",
|
||||||
|
quantity: 2,
|
||||||
|
unit_price: 500,
|
||||||
|
product_category: {
|
||||||
|
id: "catg_tshirt",
|
||||||
|
},
|
||||||
|
product: {
|
||||||
|
id: "prod_tshirt_1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "item_cotton_tshirt2",
|
||||||
|
quantity: 2,
|
||||||
|
unit_price: 1000,
|
||||||
|
product_category: {
|
||||||
|
id: "catg_tshirt",
|
||||||
|
},
|
||||||
|
product: {
|
||||||
|
id: "prod_tshirt_2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "item_cotton_sweater",
|
||||||
|
quantity: 2,
|
||||||
|
unit_price: 1000,
|
||||||
|
product_category: {
|
||||||
|
id: "catg_sweater",
|
||||||
|
},
|
||||||
|
product: {
|
||||||
|
id: "prod_sweater_1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
const [createdPromotion] = await service.create([
|
||||||
|
{
|
||||||
|
code: "PROMOTION_TEST",
|
||||||
|
type: PromotionType.BUYGET,
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
attribute: "customer.customer_group.id",
|
||||||
|
operator: "in",
|
||||||
|
values: ["VIP", "top100"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
application_method: {
|
||||||
|
type: "fixed",
|
||||||
|
target_type: "items",
|
||||||
|
allocation: "each",
|
||||||
|
max_quantity: 1,
|
||||||
|
apply_to_quantity: 4,
|
||||||
|
buy_rules_min_quantity: 1,
|
||||||
|
target_rules: [
|
||||||
|
{
|
||||||
|
attribute: "product_category.id",
|
||||||
|
operator: "eq",
|
||||||
|
values: ["catg_not-found"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
buy_rules: [
|
||||||
|
{
|
||||||
|
attribute: "product_category.id",
|
||||||
|
operator: "eq",
|
||||||
|
values: ["catg_sweater"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const result = await service.computeActions(["PROMOTION_TEST"], context)
|
||||||
|
|
||||||
|
expect(result).toEqual([])
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -263,6 +263,8 @@ export default class PromotionModuleService<
|
|||||||
"application_method",
|
"application_method",
|
||||||
"application_method.target_rules",
|
"application_method.target_rules",
|
||||||
"application_method.target_rules.values",
|
"application_method.target_rules.values",
|
||||||
|
"application_method.buy_rules",
|
||||||
|
"application_method.buy_rules.values",
|
||||||
"rules",
|
"rules",
|
||||||
"rules.values",
|
"rules.values",
|
||||||
"campaign",
|
"campaign",
|
||||||
@@ -271,6 +273,10 @@ export default class PromotionModuleService<
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const sortedPermissionsToApply = promotions
|
||||||
|
.filter((p) => promotionCodesToApply.includes(p.code!))
|
||||||
|
.sort(ComputeActionUtils.sortByBuyGetType)
|
||||||
|
|
||||||
const existingPromotionsMap = new Map<string, PromotionTypes.PromotionDTO>(
|
const existingPromotionsMap = new Map<string, PromotionTypes.PromotionDTO>(
|
||||||
promotions.map((promotion) => [promotion.code!, promotion])
|
promotions.map((promotion) => [promotion.code!, promotion])
|
||||||
)
|
)
|
||||||
@@ -306,15 +312,8 @@ export default class PromotionModuleService<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const promotionCode of promotionCodesToApply) {
|
for (const promotionToApply of sortedPermissionsToApply) {
|
||||||
const promotion = existingPromotionsMap.get(promotionCode)
|
const promotion = existingPromotionsMap.get(promotionToApply.code!)!
|
||||||
|
|
||||||
if (!promotion) {
|
|
||||||
throw new MedusaError(
|
|
||||||
MedusaError.Types.INVALID_DATA,
|
|
||||||
`Promotion for code (${promotionCode}) not found`
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
application_method: applicationMethod,
|
application_method: applicationMethod,
|
||||||
@@ -334,20 +333,9 @@ export default class PromotionModuleService<
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if (applicationMethod.target_type === ApplicationMethodTargetType.ORDER) {
|
if (promotion.type === PromotionType.BUYGET) {
|
||||||
const computedActionsForItems =
|
const computedActionsForItems =
|
||||||
ComputeActionUtils.getComputedActionsForOrder(
|
ComputeActionUtils.getComputedActionsForBuyGet(
|
||||||
promotion,
|
|
||||||
applicationContext,
|
|
||||||
methodIdPromoValueMap
|
|
||||||
)
|
|
||||||
|
|
||||||
computedActions.push(...computedActionsForItems)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (applicationMethod.target_type === ApplicationMethodTargetType.ITEMS) {
|
|
||||||
const computedActionsForItems =
|
|
||||||
ComputeActionUtils.getComputedActionsForItems(
|
|
||||||
promotion,
|
promotion,
|
||||||
applicationContext[ApplicationMethodTargetType.ITEMS],
|
applicationContext[ApplicationMethodTargetType.ITEMS],
|
||||||
methodIdPromoValueMap
|
methodIdPromoValueMap
|
||||||
@@ -356,18 +344,46 @@ export default class PromotionModuleService<
|
|||||||
computedActions.push(...computedActionsForItems)
|
computedActions.push(...computedActionsForItems)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (promotion.type === PromotionType.STANDARD) {
|
||||||
applicationMethod.target_type ===
|
if (
|
||||||
ApplicationMethodTargetType.SHIPPING_METHODS
|
applicationMethod.target_type === ApplicationMethodTargetType.ORDER
|
||||||
) {
|
) {
|
||||||
const computedActionsForShippingMethods =
|
const computedActionsForItems =
|
||||||
ComputeActionUtils.getComputedActionsForShippingMethods(
|
ComputeActionUtils.getComputedActionsForOrder(
|
||||||
promotion,
|
promotion,
|
||||||
applicationContext[ApplicationMethodTargetType.SHIPPING_METHODS],
|
applicationContext,
|
||||||
methodIdPromoValueMap
|
methodIdPromoValueMap
|
||||||
)
|
)
|
||||||
|
|
||||||
computedActions.push(...computedActionsForShippingMethods)
|
computedActions.push(...computedActionsForItems)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
applicationMethod.target_type === ApplicationMethodTargetType.ITEMS
|
||||||
|
) {
|
||||||
|
const computedActionsForItems =
|
||||||
|
ComputeActionUtils.getComputedActionsForItems(
|
||||||
|
promotion,
|
||||||
|
applicationContext[ApplicationMethodTargetType.ITEMS],
|
||||||
|
methodIdPromoValueMap
|
||||||
|
)
|
||||||
|
|
||||||
|
computedActions.push(...computedActionsForItems)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
applicationMethod.target_type ===
|
||||||
|
ApplicationMethodTargetType.SHIPPING_METHODS
|
||||||
|
) {
|
||||||
|
const computedActionsForShippingMethods =
|
||||||
|
ComputeActionUtils.getComputedActionsForShippingMethods(
|
||||||
|
promotion,
|
||||||
|
applicationContext[ApplicationMethodTargetType.SHIPPING_METHODS],
|
||||||
|
methodIdPromoValueMap
|
||||||
|
)
|
||||||
|
|
||||||
|
computedActions.push(...computedActionsForShippingMethods)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,101 @@
|
|||||||
|
import { PromotionTypes } from "@medusajs/types"
|
||||||
|
import {
|
||||||
|
ApplicationMethodTargetType,
|
||||||
|
ComputedActions,
|
||||||
|
MedusaError,
|
||||||
|
PromotionType,
|
||||||
|
} from "@medusajs/utils"
|
||||||
|
import { areRulesValidForContext } from "../validations/promotion-rule"
|
||||||
|
import { computeActionForBudgetExceeded } from "./usage"
|
||||||
|
|
||||||
|
export function getComputedActionsForBuyGet(
|
||||||
|
promotion: PromotionTypes.PromotionDTO,
|
||||||
|
itemsContext: PromotionTypes.ComputeActionContext[ApplicationMethodTargetType.ITEMS],
|
||||||
|
methodIdPromoValueMap: Map<string, number>
|
||||||
|
): PromotionTypes.ComputeActions[] {
|
||||||
|
const buyRulesMinQuantity =
|
||||||
|
promotion.application_method?.buy_rules_min_quantity
|
||||||
|
const applyToQuantity = promotion.application_method?.apply_to_quantity
|
||||||
|
const buyRules = promotion.application_method?.buy_rules
|
||||||
|
const targetRules = promotion.application_method?.target_rules
|
||||||
|
const computedActions: PromotionTypes.ComputeActions[] = []
|
||||||
|
|
||||||
|
if (!itemsContext) {
|
||||||
|
throw new MedusaError(
|
||||||
|
MedusaError.Types.INVALID_DATA,
|
||||||
|
`"items" should be present as an array in the context to compute actions`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Array.isArray(buyRules) || !Array.isArray(targetRules)) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
const validQuantity = itemsContext
|
||||||
|
.filter((item) => areRulesValidForContext(buyRules, item))
|
||||||
|
.reduce((acc, next) => acc + next.quantity, 0)
|
||||||
|
|
||||||
|
if (
|
||||||
|
!buyRulesMinQuantity ||
|
||||||
|
!applyToQuantity ||
|
||||||
|
buyRulesMinQuantity > validQuantity
|
||||||
|
) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
const validItemsForTargetRules = itemsContext
|
||||||
|
.filter((item) => areRulesValidForContext(targetRules, item))
|
||||||
|
.sort((a, b) => {
|
||||||
|
return b.unit_price - a.unit_price
|
||||||
|
})
|
||||||
|
|
||||||
|
let remainingQtyToApply = applyToQuantity
|
||||||
|
|
||||||
|
for (const method of validItemsForTargetRules) {
|
||||||
|
const appliedPromoValue = methodIdPromoValueMap.get(method.id) || 0
|
||||||
|
const multiplier = Math.min(method.quantity, remainingQtyToApply)
|
||||||
|
const amount = method.unit_price * multiplier
|
||||||
|
const newRemainingQtyToApply = remainingQtyToApply - multiplier
|
||||||
|
|
||||||
|
if (newRemainingQtyToApply < 0 || amount <= 0) {
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
remainingQtyToApply = newRemainingQtyToApply
|
||||||
|
}
|
||||||
|
|
||||||
|
const budgetExceededAction = computeActionForBudgetExceeded(
|
||||||
|
promotion,
|
||||||
|
amount
|
||||||
|
)
|
||||||
|
|
||||||
|
if (budgetExceededAction) {
|
||||||
|
computedActions.push(budgetExceededAction)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
methodIdPromoValueMap.set(method.id, appliedPromoValue + amount)
|
||||||
|
|
||||||
|
computedActions.push({
|
||||||
|
action: ComputedActions.ADD_ITEM_ADJUSTMENT,
|
||||||
|
item_id: method.id,
|
||||||
|
amount,
|
||||||
|
code: promotion.code!,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return computedActions
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sortByBuyGetType(a, b) {
|
||||||
|
if (a.type === PromotionType.BUYGET && b.type !== PromotionType.BUYGET) {
|
||||||
|
return -1
|
||||||
|
} else if (
|
||||||
|
a.type !== PromotionType.BUYGET &&
|
||||||
|
b.type === PromotionType.BUYGET
|
||||||
|
) {
|
||||||
|
return 1
|
||||||
|
} else {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
export * from "./buy-get"
|
||||||
export * from "./items"
|
export * from "./items"
|
||||||
export * from "./order"
|
export * from "./order"
|
||||||
export * from "./shipping-methods"
|
export * from "./shipping-methods"
|
||||||
|
|||||||
Reference in New Issue
Block a user