feat(core-flows,types,promotion): register promotion campaign usage upon cart completion (#8970)
* feat(core-flows,types,promotion): register promotion campaign usage upon cart completion * Apply suggestions from code review Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com> --------- Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>
This commit is contained in:
co-authored by
Oli Juhl
parent
2a055b71ef
commit
5d7179b7d0
@@ -123,33 +123,39 @@ export default class PromotionModuleService
|
||||
@InjectManager("baseRepository_")
|
||||
async registerUsage(
|
||||
computedActions: PromotionTypes.UsageComputedActions[],
|
||||
@MedusaContext()
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<void> {
|
||||
const promotionCodes = computedActions
|
||||
.map((computedAction) => computedAction.code)
|
||||
.filter(Boolean)
|
||||
|
||||
const promotionCodeCampaignBudgetMap = new Map<
|
||||
string,
|
||||
UpdateCampaignBudgetDTO
|
||||
>()
|
||||
const campaignBudgetMap = new Map<string, UpdateCampaignBudgetDTO>()
|
||||
const promotionCodeUsageMap = new Map<string, boolean>()
|
||||
|
||||
const existingPromotions = await this.listPromotions(
|
||||
{ code: promotionCodes },
|
||||
{ relations: ["application_method", "campaign", "campaign.budget"] },
|
||||
{
|
||||
relations: ["campaign", "campaign.budget"],
|
||||
take: null,
|
||||
},
|
||||
sharedContext
|
||||
)
|
||||
|
||||
for (const promotion of existingPromotions) {
|
||||
if (promotion.campaign?.budget) {
|
||||
campaignBudgetMap.set(
|
||||
promotion.campaign?.budget.id,
|
||||
promotion.campaign?.budget
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const existingPromotionsMap = new Map<string, PromotionTypes.PromotionDTO>(
|
||||
existingPromotions.map((promotion) => [promotion.code!, promotion])
|
||||
)
|
||||
|
||||
for (let computedAction of computedActions) {
|
||||
if (!ComputeActionUtils.canRegisterUsage(computedAction)) {
|
||||
continue
|
||||
}
|
||||
|
||||
const promotion = existingPromotionsMap.get(computedAction.code)
|
||||
|
||||
if (!promotion) {
|
||||
@@ -163,9 +169,11 @@ export default class PromotionModuleService
|
||||
}
|
||||
|
||||
if (campaignBudget.type === CampaignBudgetType.SPEND) {
|
||||
const campaignBudgetData = promotionCodeCampaignBudgetMap.get(
|
||||
campaignBudget.id
|
||||
) || { id: campaignBudget.id, used: campaignBudget.used ?? 0 }
|
||||
const campaignBudgetData = campaignBudgetMap.get(campaignBudget.id)
|
||||
|
||||
if (!campaignBudgetData) {
|
||||
continue
|
||||
}
|
||||
|
||||
campaignBudgetData.used = MathBN.add(
|
||||
campaignBudgetData.used ?? 0,
|
||||
@@ -179,10 +187,7 @@ export default class PromotionModuleService
|
||||
continue
|
||||
}
|
||||
|
||||
promotionCodeCampaignBudgetMap.set(
|
||||
campaignBudget.id,
|
||||
campaignBudgetData
|
||||
)
|
||||
campaignBudgetMap.set(campaignBudget.id, campaignBudgetData)
|
||||
}
|
||||
|
||||
if (campaignBudget.type === CampaignBudgetType.USAGE) {
|
||||
@@ -205,17 +210,105 @@ export default class PromotionModuleService
|
||||
continue
|
||||
}
|
||||
|
||||
promotionCodeCampaignBudgetMap.set(
|
||||
campaignBudget.id,
|
||||
campaignBudgetData
|
||||
)
|
||||
campaignBudgetMap.set(campaignBudget.id, campaignBudgetData)
|
||||
|
||||
promotionCodeUsageMap.set(promotion.code!, true)
|
||||
}
|
||||
|
||||
const campaignBudgetsData: UpdateCampaignBudgetDTO[] = []
|
||||
|
||||
for (const [_, campaignBudgetData] of promotionCodeCampaignBudgetMap) {
|
||||
for (const [_, campaignBudgetData] of campaignBudgetMap) {
|
||||
campaignBudgetsData.push(campaignBudgetData)
|
||||
}
|
||||
|
||||
await this.campaignBudgetService_.update(
|
||||
campaignBudgetsData,
|
||||
sharedContext
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@InjectManager("baseRepository_")
|
||||
async revertUsage(
|
||||
computedActions: PromotionTypes.UsageComputedActions[],
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<void> {
|
||||
const promotionCodeUsageMap = new Map<string, boolean>()
|
||||
const campaignBudgetMap = new Map<string, UpdateCampaignBudgetDTO>()
|
||||
|
||||
const existingPromotions = await this.listPromotions(
|
||||
{
|
||||
code: computedActions
|
||||
.map((computedAction) => computedAction.code)
|
||||
.filter(Boolean),
|
||||
},
|
||||
{
|
||||
relations: ["campaign", "campaign.budget"],
|
||||
take: null,
|
||||
},
|
||||
sharedContext
|
||||
)
|
||||
|
||||
for (const promotion of existingPromotions) {
|
||||
if (promotion.campaign?.budget) {
|
||||
campaignBudgetMap.set(
|
||||
promotion.campaign?.budget.id,
|
||||
promotion.campaign?.budget
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const existingPromotionsMap = new Map<string, PromotionTypes.PromotionDTO>(
|
||||
existingPromotions.map((promotion) => [promotion.code!, promotion])
|
||||
)
|
||||
|
||||
for (let computedAction of computedActions) {
|
||||
const promotion = existingPromotionsMap.get(computedAction.code)
|
||||
|
||||
if (!promotion) {
|
||||
continue
|
||||
}
|
||||
|
||||
const campaignBudget = promotion.campaign?.budget
|
||||
|
||||
if (!campaignBudget) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (campaignBudget.type === CampaignBudgetType.SPEND) {
|
||||
const campaignBudgetData = campaignBudgetMap.get(campaignBudget.id)
|
||||
|
||||
if (!campaignBudgetData) {
|
||||
continue
|
||||
}
|
||||
|
||||
campaignBudgetData.used = MathBN.sub(
|
||||
campaignBudgetData.used ?? 0,
|
||||
computedAction.amount
|
||||
)
|
||||
|
||||
campaignBudgetMap.set(campaignBudget.id, campaignBudgetData)
|
||||
}
|
||||
|
||||
if (campaignBudget.type === CampaignBudgetType.USAGE) {
|
||||
const promotionAlreadyUsed =
|
||||
promotionCodeUsageMap.get(promotion.code!) || false
|
||||
|
||||
if (promotionAlreadyUsed) {
|
||||
continue
|
||||
}
|
||||
|
||||
campaignBudgetMap.set(campaignBudget.id, {
|
||||
id: campaignBudget.id,
|
||||
used: MathBN.sub(campaignBudget.used ?? 0, 1),
|
||||
})
|
||||
|
||||
promotionCodeUsageMap.set(promotion.code!, true)
|
||||
}
|
||||
|
||||
const campaignBudgetsData: UpdateCampaignBudgetDTO[] = []
|
||||
|
||||
for (const [_, campaignBudgetData] of campaignBudgetMap) {
|
||||
campaignBudgetsData.push(campaignBudgetData)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,20 +1,10 @@
|
||||
import {
|
||||
BigNumberInput,
|
||||
CampaignBudgetExceededAction,
|
||||
ComputeActions,
|
||||
PromotionDTO,
|
||||
} from "@medusajs/types"
|
||||
import { CampaignBudgetType, ComputedActions, MathBN } 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: BigNumberInput
|
||||
|
||||
Reference in New Issue
Block a user