chore(core-flows): throw error on invalid promo code (#13140)

* chore(core-flows): throw error on invalid promo code

* add changelog

* better error handling in test

---------

Co-authored-by: william bouchard <williambouchard@williams-MacBook-Pro.local>
Co-authored-by: Carlos R. L. Rodrigues <37986729+carlos-r-l-rodrigues@users.noreply.github.com>
This commit is contained in:
William Bouchard
2025-08-05 09:01:41 -04:00
committed by GitHub
parent ee0b873f82
commit acf6bbc2ec
3 changed files with 57 additions and 11 deletions

View File

@@ -0,0 +1,5 @@
---
"@medusajs/core-flows": minor
---
chore(code-flows): throw error on invalid promo code

View File

@@ -2815,6 +2815,24 @@ medusaIntegrationTestRunner({
)
})
it("should throw an error when adding a promotion that does not exist", async () => {
const invalidPromoCode = "SOME_INVALID_PROMO_CODE"
const { response } = await api
.post(
`/store/carts/${cart.id}/promotions`,
{ promo_codes: [invalidPromoCode] },
storeHeaders
)
.catch((e) => e)
expect(response.status).toEqual(400)
expect(response.data.type).toEqual("invalid_data")
expect(response.data.message).toEqual(
`The promotion code ${invalidPromoCode} is invalid`
)
})
it("should remove promotion adjustments when promotion is deleted", async () => {
let cartBeforeRemovingPromotion = (
await api.get(`/store/carts/${cart.id}`, storeHeaders)

View File

@@ -1,6 +1,10 @@
import { IPromotionModuleService } from "@medusajs/framework/types"
import { Modules, PromotionActions } from "@medusajs/framework/utils"
import { StepResponse, createStep } from "@medusajs/framework/workflows-sdk"
import {
MedusaError,
Modules,
PromotionActions,
} from "@medusajs/framework/utils"
import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"
/**
* The details of the promotion codes to apply on a cart.
@@ -68,14 +72,12 @@ export const getPromotionCodesToApply = createStep(
async (data: GetPromotionCodesToApplyStepInput, { container }) => {
const { promo_codes = [], cart, action = PromotionActions.ADD } = data
const { items = [], shipping_methods = [] } = cart
const adjustmentCodes: string[] = []
const promotionService = container.resolve<IPromotionModuleService>(
Modules.PROMOTION
)
const objects = items.concat(shipping_methods)
objects.forEach((object) => {
const adjustmentCodes: string[] = []
items.concat(shipping_methods).forEach((object) => {
object.adjustments?.forEach((adjustment) => {
if (adjustment.code && !adjustmentCodes.includes(adjustment.code)) {
adjustmentCodes.push(adjustment.code)
@@ -94,17 +96,38 @@ export const getPromotionCodesToApply = createStep(
: []
)
if (action === PromotionActions.ADD) {
promo_codes.forEach((code) => promotionCodesToApply.add(code))
}
if (action === PromotionActions.REMOVE) {
promo_codes.forEach((code) => promotionCodesToApply.delete(code))
}
if (action === PromotionActions.REPLACE) {
promotionCodesToApply.clear()
promo_codes.forEach((code) => promotionCodesToApply.add(code))
}
if (
action === PromotionActions.ADD ||
action === PromotionActions.REPLACE
) {
const validPromoCodes: Set<string> = new Set(
promo_codes.length
? (
await promotionService.listPromotions(
{ code: promo_codes },
{ select: ["code"] }
)
).map((p) => p.code!)
: []
)
promo_codes.forEach((code) => {
if (!validPromoCodes.has(code)) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`The promotion code ${code} is invalid`
)
}
promotionCodesToApply.add(code)
})
}
return new StepResponse(