feat(utils,types): add registerUsages for promotions + computeActions consider usage (#6094)

RESOLVES CORE-1639
RESOLVES CORE-1640
RESOLVES CORE-1634
This commit is contained in:
Riqwan Thamir
2024-01-16 20:06:06 +00:00
committed by GitHub
parent 90328ca02b
commit 68ddd866a5
15 changed files with 943 additions and 54 deletions
@@ -1,3 +1,4 @@
export * from "./items"
export * from "./order"
export * from "./shipping-methods"
export * from "./usage"
@@ -5,9 +5,11 @@ import {
import {
ApplicationMethodAllocation,
ApplicationMethodTargetType,
ComputedActions,
MedusaError,
} from "@medusajs/utils"
import { areRulesValidForContext } from "../validations"
import { computeActionForBudgetExceeded } from "./usage"
export function getComputedActionsForItems(
promotion: PromotionTypes.PromotionDTO,
@@ -61,22 +63,35 @@ export function applyPromotionToItems(
) {
for (const method of items!) {
const appliedPromoValue = methodIdPromoValueMap.get(method.id) || 0
const promotionValue = parseFloat(applicationMethod!.value!)
const quantityMultiplier = Math.min(
method.quantity,
applicationMethod?.max_quantity!
)
const promotionValue =
parseFloat(applicationMethod!.value!) * quantityMultiplier
const applicableTotal =
method.unit_price *
Math.min(method.quantity, applicationMethod?.max_quantity!) -
appliedPromoValue
method.unit_price * quantityMultiplier - appliedPromoValue
const amount = Math.min(promotionValue, applicableTotal)
if (amount <= 0) {
continue
}
const budgetExceededAction = computeActionForBudgetExceeded(
promotion,
amount
)
if (budgetExceededAction) {
computedActions.push(budgetExceededAction)
continue
}
methodIdPromoValueMap.set(method.id, appliedPromoValue + amount)
computedActions.push({
action: "addItemAdjustment",
action: ComputedActions.ADD_ITEM_ADJUSTMENT,
item_id: method.id,
amount,
code: promotion.code!,
@@ -91,35 +106,37 @@ export function applyPromotionToItems(
) {
const totalApplicableValue = items!.reduce((acc, method) => {
const appliedPromoValue = methodIdPromoValueMap.get(method.id) || 0
return (
acc +
method.unit_price *
Math.min(method.quantity, applicationMethod?.max_quantity!) -
appliedPromoValue
)
return acc + method.unit_price * method.quantity - appliedPromoValue
}, 0)
for (const method of items!) {
const promotionValue = parseFloat(applicationMethod!.value!)
const appliedPromoValue = methodIdPromoValueMap.get(method.id) || 0
const applicableTotal =
method.unit_price *
Math.min(method.quantity, applicationMethod?.max_quantity!) -
appliedPromoValue
method.unit_price * method.quantity - appliedPromoValue
// TODO: should we worry about precision here?
const applicablePromotionValue =
(applicableTotal / totalApplicableValue) * promotionValue
const amount = Math.min(applicablePromotionValue, applicableTotal)
if (amount <= 0) {
continue
}
const budgetExceededAction = computeActionForBudgetExceeded(
promotion,
amount
)
if (budgetExceededAction) {
computedActions.push(budgetExceededAction)
continue
}
computedActions.push({
action: "addItemAdjustment",
action: ComputedActions.ADD_ITEM_ADJUSTMENT,
item_id: method.id,
amount,
code: promotion.code!,
@@ -2,9 +2,11 @@ import { PromotionTypes } from "@medusajs/types"
import {
ApplicationMethodAllocation,
ApplicationMethodTargetType,
ComputedActions,
MedusaError,
} from "@medusajs/utils"
import { areRulesValidForContext } from "../validations"
import { computeActionForBudgetExceeded } from "./usage"
export function getComputedActionsForShippingMethods(
promotion: PromotionTypes.PromotionDTO,
@@ -61,10 +63,21 @@ export function applyPromotionToShippingMethods(
continue
}
const budgetExceededAction = computeActionForBudgetExceeded(
promotion,
amount
)
if (budgetExceededAction) {
computedActions.push(budgetExceededAction)
continue
}
methodIdPromoValueMap.set(method.id, appliedPromoValue + amount)
computedActions.push({
action: "addShippingMethodAdjustment",
action: ComputedActions.ADD_SHIPPING_METHOD_ADJUSTMENT,
shipping_method_id: method.id,
amount,
code: promotion.code!,
@@ -99,10 +112,21 @@ export function applyPromotionToShippingMethods(
continue
}
const budgetExceededAction = computeActionForBudgetExceeded(
promotion,
amount
)
if (budgetExceededAction) {
computedActions.push(budgetExceededAction)
continue
}
methodIdPromoValueMap.set(method.id, appliedPromoValue + amount)
computedActions.push({
action: "addShippingMethodAdjustment",
action: ComputedActions.ADD_SHIPPING_METHOD_ADJUSTMENT,
shipping_method_id: method.id,
amount,
code: promotion.code!,
@@ -0,0 +1,39 @@
import {
CampaignBudgetExceededAction,
ComputeActions,
PromotionDTO,
} from "@medusajs/types"
import { CampaignBudgetType, ComputedActions } from "@medusajs/utils"
export function canRegisterUsage(computedAction: ComputeActions): boolean {
return (
[
ComputedActions.ADD_ITEM_ADJUSTMENT,
ComputedActions.ADD_SHIPPING_METHOD_ADJUSTMENT,
] as string[]
).includes(computedAction.action)
}
export function computeActionForBudgetExceeded(
promotion: PromotionDTO,
amount: number
): CampaignBudgetExceededAction | void {
const campaignBudget = promotion.campaign?.budget
if (!campaignBudget) {
return
}
const campaignBudgetUsed = campaignBudget.used || 0
const totalUsed =
campaignBudget.type === CampaignBudgetType.SPEND
? campaignBudgetUsed + amount
: campaignBudgetUsed + 1
if (campaignBudget.limit && totalUsed > campaignBudget.limit) {
return {
action: ComputedActions.CAMPAIGN_BUDGET_EXCEEDED,
code: promotion.code!,
}
}
}
@@ -9,6 +9,7 @@ import {
ApplicationMethodType,
MedusaError,
isDefined,
isPresent,
} from "@medusajs/utils"
export const allowedAllocationTargetTypes: string[] = [
@@ -33,6 +34,16 @@ export function validateApplicationMethodAttributes(data: {
}) {
const allTargetTypes: string[] = Object.values(ApplicationMethodTargetType)
if (
data.allocation === ApplicationMethodAllocation.ACROSS &&
isPresent(data.max_quantity)
) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`application_method.max_quantity is not allowed to be set for allocation (${ApplicationMethodAllocation.ACROSS})`
)
}
if (!allTargetTypes.includes(data.target_type)) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,