diff --git a/.changeset/fifty-gorillas-lie.md b/.changeset/fifty-gorillas-lie.md new file mode 100644 index 0000000000..db02dd5b69 --- /dev/null +++ b/.changeset/fifty-gorillas-lie.md @@ -0,0 +1,7 @@ +--- +"@medusajs/core-flows": patch +"@medusajs/medusa": patch +"@medusajs/types": patch +--- + +feat(core-flows,medusa,types): remove rules from promotion endpoints + workflows diff --git a/integration-tests/modules/__tests__/promotion/admin/promotion-rules.spec.ts b/integration-tests/modules/__tests__/promotion/admin/promotion-rules.spec.ts index 6de28b5195..9b9419ed52 100644 --- a/integration-tests/modules/__tests__/promotion/admin/promotion-rules.spec.ts +++ b/integration-tests/modules/__tests__/promotion/admin/promotion-rules.spec.ts @@ -342,6 +342,194 @@ medusaIntegrationTestRunner({ ) }) }) + + describe("DELETE /admin/promotions/:id/rules", () => { + it("should throw error when required params are missing", async () => { + const { response } = await api + .delete(`/admin/promotions/${standardPromotion.id}/rules`, { + ...adminHeaders, + data: {}, + }) + .catch((e) => e) + + expect(response.status).toEqual(400) + expect(response.data).toEqual({ + type: "invalid_data", + message: + "each value in rule_ids must be a string, rule_ids should not be empty", + }) + }) + + it("should throw error when promotion does not exist", async () => { + const { response } = await api + .delete(`/admin/promotions/does-not-exist/rules`, { + ...adminHeaders, + data: { rule_ids: ["test-rule-id"] }, + }) + .catch((e) => e) + + expect(response.status).toEqual(404) + expect(response.data).toEqual({ + type: "not_found", + message: "Promotion with id: does-not-exist was not found", + }) + }) + + it("should remove rules from a promotion successfully", async () => { + const response = await api.delete( + `/admin/promotions/${standardPromotion.id}/rules`, + { + ...adminHeaders, + data: { rule_ids: [standardPromotion.rules[0].id] }, + } + ) + + expect(response.status).toEqual(200) + expect(response.data).toEqual({ + ids: [standardPromotion.rules[0].id], + object: "promotion-rule", + deleted: true, + }) + + const promotion = await promotionModule.retrieve( + standardPromotion.id, + { relations: ["rules"] } + ) + + expect(promotion.rules!.length).toEqual(0) + }) + }) + + describe("DELETE /admin/promotions/:id/target-rules", () => { + it("should throw error when required params are missing", async () => { + const { response } = await api + .delete(`/admin/promotions/${standardPromotion.id}/target-rules`, { + ...adminHeaders, + data: {}, + }) + .catch((e) => e) + + expect(response.status).toEqual(400) + expect(response.data).toEqual({ + type: "invalid_data", + message: + "each value in rule_ids must be a string, rule_ids should not be empty", + }) + }) + + it("should throw error when promotion does not exist", async () => { + const { response } = await api + .delete(`/admin/promotions/does-not-exist/target-rules`, { + ...adminHeaders, + data: { rule_ids: ["test-rule-id"] }, + }) + .catch((e) => e) + + expect(response.status).toEqual(404) + expect(response.data).toEqual({ + type: "not_found", + message: "Promotion with id: does-not-exist was not found", + }) + }) + + it("should remove target rules from a promotion successfully", async () => { + const ruleId = standardPromotion.application_method.target_rules[0].id + const response = await api.delete( + `/admin/promotions/${standardPromotion.id}/target-rules`, + { + ...adminHeaders, + data: { rule_ids: [ruleId] }, + } + ) + + expect(response.status).toEqual(200) + expect(response.data).toEqual({ + ids: [ruleId], + object: "promotion-rule", + deleted: true, + }) + + const promotion = await promotionModule.retrieve( + standardPromotion.id, + { relations: ["application_method.target_rules"] } + ) + + expect(promotion.application_method!.target_rules!.length).toEqual(0) + }) + }) + + describe("DELETE /admin/promotions/:id/buy-rules", () => { + it("should throw error when required params are missing", async () => { + const { response } = await api + .delete(`/admin/promotions/${standardPromotion.id}/buy-rules`, { + ...adminHeaders, + data: {}, + }) + .catch((e) => e) + + expect(response.status).toEqual(400) + expect(response.data).toEqual({ + type: "invalid_data", + message: + "each value in rule_ids must be a string, rule_ids should not be empty", + }) + }) + + it("should throw error when promotion does not exist", async () => { + const { response } = await api + .delete(`/admin/promotions/does-not-exist/buy-rules`, { + ...adminHeaders, + data: { rule_ids: ["test-rule-id"] }, + }) + .catch((e) => e) + + expect(response.status).toEqual(404) + expect(response.data).toEqual({ + type: "not_found", + message: "Promotion with id: does-not-exist was not found", + }) + }) + + it("should remove buy rules from a promotion successfully", async () => { + const buyGetPromotion = await promotionModule.create({ + code: "TEST_BUYGET", + type: PromotionType.BUYGET, + application_method: { + type: "fixed", + target_type: "items", + allocation: "across", + value: 100, + apply_to_quantity: 1, + buy_rules_min_quantity: 1, + buy_rules: [promotionRule], + target_rules: [promotionRule], + }, + rules: [promotionRule], + }) + + const ruleId = buyGetPromotion!.application_method!.buy_rules![0].id + const response = await api.delete( + `/admin/promotions/${buyGetPromotion.id}/buy-rules`, + { + ...adminHeaders, + data: { rule_ids: [ruleId] }, + } + ) + + expect(response.status).toEqual(200) + expect(response.data).toEqual({ + ids: [ruleId], + object: "promotion-rule", + deleted: true, + }) + + const promotion = await promotionModule.retrieve(buyGetPromotion.id, { + relations: ["application_method.buy_rules"], + }) + + expect(promotion.application_method!.buy_rules!.length).toEqual(0) + }) + }) }) }, }) diff --git a/packages/core-flows/src/promotion/steps/add-rules-to-promotions.ts b/packages/core-flows/src/promotion/steps/add-rules-to-promotions.ts index c188bd879e..54cf22f4b6 100644 --- a/packages/core-flows/src/promotion/steps/add-rules-to-promotions.ts +++ b/packages/core-flows/src/promotion/steps/add-rules-to-promotions.ts @@ -39,7 +39,7 @@ export const addRulesToPromotionsStep = createStep( return new StepResponse(promotionRules, { id: data.id, - ruleIds: createdPromotionRules.map((pr) => pr.id), + promotionRuleIds: createdPromotionRules.map((pr) => pr.id), buyRuleIds: createdPromotionBuyRules.map((pr) => pr.id), targetRuleIds: createdPromotionBuyRules.map((pr) => pr.id), }) @@ -49,28 +49,24 @@ export const addRulesToPromotionsStep = createStep( return } - const { id, ruleIds = [], buyRuleIds = [], targetRuleIds = [] } = data + const { + id, + promotionRuleIds = [], + buyRuleIds = [], + targetRuleIds = [], + } = data const promotionModule = container.resolve( ModuleRegistrationName.PROMOTION ) - ruleIds.length && - (await promotionModule.removePromotionRules( - id, - ruleIds.map((id) => ({ id })) - )) + promotionRuleIds.length && + (await promotionModule.removePromotionRules(id, promotionRuleIds)) buyRuleIds.length && - (await promotionModule.removePromotionBuyRules( - id, - buyRuleIds.map((id) => ({ id })) - )) + (await promotionModule.removePromotionBuyRules(id, buyRuleIds)) targetRuleIds.length && - (await promotionModule.removePromotionBuyRules( - id, - targetRuleIds.map((id) => ({ id })) - )) + (await promotionModule.removePromotionBuyRules(id, targetRuleIds)) } ) diff --git a/packages/core-flows/src/promotion/steps/index.ts b/packages/core-flows/src/promotion/steps/index.ts index f2f0ef311d..a385e72d6d 100644 --- a/packages/core-flows/src/promotion/steps/index.ts +++ b/packages/core-flows/src/promotion/steps/index.ts @@ -3,5 +3,6 @@ export * from "./create-campaigns" export * from "./create-promotions" export * from "./delete-campaigns" export * from "./delete-promotions" +export * from "./remove-rules-from-promotions" export * from "./update-campaigns" export * from "./update-promotions" diff --git a/packages/core-flows/src/promotion/steps/remove-rules-from-promotions.ts b/packages/core-flows/src/promotion/steps/remove-rules-from-promotions.ts new file mode 100644 index 0000000000..f7be51109f --- /dev/null +++ b/packages/core-flows/src/promotion/steps/remove-rules-from-promotions.ts @@ -0,0 +1,95 @@ +import { ModuleRegistrationName } from "@medusajs/modules-sdk" +import { + CreatePromotionRuleDTO, + IPromotionModuleService, + PromotionRuleDTO, + RemovePromotionRulesWorkflowDTO, +} from "@medusajs/types" +import { RuleType } from "@medusajs/utils" +import { StepResponse, createStep } from "@medusajs/workflows-sdk" + +export const removeRulesFromPromotionsStepId = "remove-rules-from-promotions" +export const removeRulesFromPromotionsStep = createStep( + removeRulesFromPromotionsStepId, + async (input: RemovePromotionRulesWorkflowDTO, { container }) => { + const { data, rule_type: ruleType } = input + + const promotionModule = container.resolve( + ModuleRegistrationName.PROMOTION + ) + + const promotion = await promotionModule.retrieve(data.id, { + relations: [ + "rules.values", + "application_method.target_rules.values", + "application_method.buy_rules.values", + ], + }) + + const promotionRulesToCreate: CreatePromotionRuleDTO[] = [] + const buyRulesToCreate: CreatePromotionRuleDTO[] = [] + const targetRulesToCreate: CreatePromotionRuleDTO[] = [] + + if (ruleType === RuleType.RULES) { + const rules = promotion.rules! + promotionRulesToCreate.push(...promotionRuleAttribute(rules)) + + await promotionModule.removePromotionRules(data.id, data.rule_ids) + } + + if (ruleType === RuleType.BUY_RULES) { + const rules = promotion.application_method?.buy_rules! + buyRulesToCreate.push(...promotionRuleAttribute(rules)) + + await promotionModule.removePromotionBuyRules(data.id, data.rule_ids) + } + + if (ruleType === RuleType.TARGET_RULES) { + const rules = promotion.application_method?.target_rules! + targetRulesToCreate.push(...promotionRuleAttribute(rules)) + + await promotionModule.removePromotionTargetRules(data.id, data.rule_ids) + } + + return new StepResponse(null, { + id: data.id, + promotionRulesToCreate, + buyRulesToCreate, + targetRulesToCreate, + }) + }, + async (data, { container }) => { + if (!data) { + return + } + + const { + id, + promotionRulesToCreate = [], + buyRulesToCreate = [], + targetRulesToCreate = [], + } = data + + const promotionModule = container.resolve( + ModuleRegistrationName.PROMOTION + ) + + promotionRulesToCreate.length && + (await promotionModule.addPromotionRules(id, promotionRulesToCreate)) + + buyRulesToCreate.length && + (await promotionModule.addPromotionBuyRules(id, buyRulesToCreate)) + + targetRulesToCreate.length && + (await promotionModule.addPromotionBuyRules(id, targetRulesToCreate)) + } +) + +function promotionRuleAttribute(rules: PromotionRuleDTO[]) { + return rules.map((rule) => ({ + description: rule.description!, + attribute: rule.attribute!, + operator: rule.operator!, + values: rule.values!.map((val) => val.value!), + })) +} diff --git a/packages/core-flows/src/promotion/workflows/index.ts b/packages/core-flows/src/promotion/workflows/index.ts index f2f0ef311d..a385e72d6d 100644 --- a/packages/core-flows/src/promotion/workflows/index.ts +++ b/packages/core-flows/src/promotion/workflows/index.ts @@ -3,5 +3,6 @@ export * from "./create-campaigns" export * from "./create-promotions" export * from "./delete-campaigns" export * from "./delete-promotions" +export * from "./remove-rules-from-promotions" export * from "./update-campaigns" export * from "./update-promotions" diff --git a/packages/core-flows/src/promotion/workflows/remove-rules-from-promotions.ts b/packages/core-flows/src/promotion/workflows/remove-rules-from-promotions.ts new file mode 100644 index 0000000000..07eb8fccea --- /dev/null +++ b/packages/core-flows/src/promotion/workflows/remove-rules-from-promotions.ts @@ -0,0 +1,14 @@ +import { RemovePromotionRulesWorkflowDTO } from "@medusajs/types" +import { WorkflowData, createWorkflow } from "@medusajs/workflows-sdk" +import { removeRulesFromPromotionsStep } from "../steps" + +export const removeRulesFromPromotionsWorkflowId = + "remove-rules-from-promotions-workflow" +export const removeRulesFromPromotionsWorkflow = createWorkflow( + removeRulesFromPromotionsWorkflowId, + ( + input: WorkflowData + ): WorkflowData => { + removeRulesFromPromotionsStep(input) + } +) diff --git a/packages/medusa/src/api-v2/admin/promotions/[id]/buy-rules/route.ts b/packages/medusa/src/api-v2/admin/promotions/[id]/buy-rules/route.ts index bd506451f6..8383c94904 100644 --- a/packages/medusa/src/api-v2/admin/promotions/[id]/buy-rules/route.ts +++ b/packages/medusa/src/api-v2/admin/promotions/[id]/buy-rules/route.ts @@ -1,4 +1,7 @@ -import { addRulesToPromotionsWorkflow } from "@medusajs/core-flows" +import { + addRulesToPromotionsWorkflow, + removeRulesFromPromotionsWorkflow, +} from "@medusajs/core-flows" import { ModuleRegistrationName } from "@medusajs/modules-sdk" import { IPromotionModuleService } from "@medusajs/types" import { RuleType } from "@medusajs/utils" @@ -10,7 +13,10 @@ import { defaultAdminPromotionFields, defaultAdminPromotionRelations, } from "../../query-config" -import { AdminPostPromotionsPromotionRulesReq } from "../../validators" +import { + AdminDeletePromotionsPromotionRulesReq, + AdminPostPromotionsPromotionRulesReq, +} from "../../validators" export const POST = async ( req: AuthenticatedMedusaRequest, @@ -22,7 +28,7 @@ export const POST = async ( input: { rule_type: RuleType.BUY_RULES, data: { - id: req.params.id, + id, ...req.validatedBody, }, }, @@ -44,3 +50,33 @@ export const POST = async ( res.status(200).json({ promotion }) } + +export const DELETE = async ( + req: AuthenticatedMedusaRequest, + res: MedusaResponse +) => { + const id = req.params.id + const workflow = removeRulesFromPromotionsWorkflow(req.scope) + const validatedBody = req.validatedBody + + const { errors } = await workflow.run({ + input: { + rule_type: RuleType.BUY_RULES, + data: { + id, + ...validatedBody, + }, + }, + throwOnError: false, + }) + + if (Array.isArray(errors) && errors[0]) { + throw errors[0].error + } + + res.status(200).json({ + ids: validatedBody.rule_ids, + object: "promotion-rule", + deleted: true, + }) +} diff --git a/packages/medusa/src/api-v2/admin/promotions/[id]/rules/route.ts b/packages/medusa/src/api-v2/admin/promotions/[id]/rules/route.ts index 6d75f3d2b0..ae0b5589ab 100644 --- a/packages/medusa/src/api-v2/admin/promotions/[id]/rules/route.ts +++ b/packages/medusa/src/api-v2/admin/promotions/[id]/rules/route.ts @@ -1,4 +1,7 @@ -import { addRulesToPromotionsWorkflow } from "@medusajs/core-flows" +import { + addRulesToPromotionsWorkflow, + removeRulesFromPromotionsWorkflow, +} from "@medusajs/core-flows" import { ModuleRegistrationName } from "@medusajs/modules-sdk" import { IPromotionModuleService } from "@medusajs/types" import { RuleType } from "@medusajs/utils" @@ -10,7 +13,10 @@ import { defaultAdminPromotionFields, defaultAdminPromotionRelations, } from "../../query-config" -import { AdminPostPromotionsPromotionRulesReq } from "../../validators" +import { + AdminDeletePromotionsPromotionRulesReq, + AdminPostPromotionsPromotionRulesReq, +} from "../../validators" export const POST = async ( req: AuthenticatedMedusaRequest, @@ -23,7 +29,7 @@ export const POST = async ( input: { rule_type: RuleType.RULES, data: { - id: req.params.id, + id, ...req.validatedBody, }, }, @@ -45,3 +51,33 @@ export const POST = async ( res.status(200).json({ promotion }) } + +export const DELETE = async ( + req: AuthenticatedMedusaRequest, + res: MedusaResponse +) => { + const id = req.params.id + const workflow = removeRulesFromPromotionsWorkflow(req.scope) + const validatedBody = req.validatedBody + + const { errors } = await workflow.run({ + input: { + rule_type: RuleType.RULES, + data: { + id, + ...validatedBody, + }, + }, + throwOnError: false, + }) + + if (Array.isArray(errors) && errors[0]) { + throw errors[0].error + } + + res.status(200).json({ + ids: validatedBody.rule_ids, + object: "promotion-rule", + deleted: true, + }) +} diff --git a/packages/medusa/src/api-v2/admin/promotions/[id]/target-rules/route.ts b/packages/medusa/src/api-v2/admin/promotions/[id]/target-rules/route.ts index 10b6a8a735..d673beb7aa 100644 --- a/packages/medusa/src/api-v2/admin/promotions/[id]/target-rules/route.ts +++ b/packages/medusa/src/api-v2/admin/promotions/[id]/target-rules/route.ts @@ -1,4 +1,7 @@ -import { addRulesToPromotionsWorkflow } from "@medusajs/core-flows" +import { + addRulesToPromotionsWorkflow, + removeRulesFromPromotionsWorkflow, +} from "@medusajs/core-flows" import { ModuleRegistrationName } from "@medusajs/modules-sdk" import { IPromotionModuleService } from "@medusajs/types" import { RuleType } from "@medusajs/utils" @@ -10,7 +13,10 @@ import { defaultAdminPromotionFields, defaultAdminPromotionRelations, } from "../../query-config" -import { AdminPostPromotionsPromotionRulesReq } from "../../validators" +import { + AdminDeletePromotionsPromotionRulesReq, + AdminPostPromotionsPromotionRulesReq, +} from "../../validators" export const POST = async ( req: AuthenticatedMedusaRequest, @@ -22,7 +28,7 @@ export const POST = async ( input: { rule_type: RuleType.TARGET_RULES, data: { - id: req.params.id, + id, ...req.validatedBody, }, }, @@ -44,3 +50,33 @@ export const POST = async ( res.status(200).json({ promotion }) } + +export const DELETE = async ( + req: AuthenticatedMedusaRequest, + res: MedusaResponse +) => { + const id = req.params.id + const workflow = removeRulesFromPromotionsWorkflow(req.scope) + const validatedBody = req.validatedBody + + const { errors } = await workflow.run({ + input: { + rule_type: RuleType.TARGET_RULES, + data: { + id, + ...validatedBody, + }, + }, + throwOnError: false, + }) + + if (Array.isArray(errors) && errors[0]) { + throw errors[0].error + } + + res.status(200).json({ + ids: validatedBody.rule_ids, + object: "promotion-rule", + deleted: true, + }) +} diff --git a/packages/medusa/src/api-v2/admin/promotions/middlewares.ts b/packages/medusa/src/api-v2/admin/promotions/middlewares.ts index b52910f0dd..16b5381db0 100644 --- a/packages/medusa/src/api-v2/admin/promotions/middlewares.ts +++ b/packages/medusa/src/api-v2/admin/promotions/middlewares.ts @@ -2,6 +2,7 @@ import * as QueryConfig from "./query-config" import { transformBody, transformQuery } from "../../../api/middlewares" import { + AdminDeletePromotionsPromotionRulesReq, AdminGetPromotionsParams, AdminGetPromotionsPromotionParams, AdminPostPromotionsPromotionReq, @@ -62,4 +63,19 @@ export const adminPromotionRoutesMiddlewares: MiddlewareRoute[] = [ matcher: "/admin/promotions/:id/buy-rules", middlewares: [transformBody(AdminPostPromotionsPromotionRulesReq)], }, + { + method: ["DELETE"], + matcher: "/admin/promotions/:id/rules", + middlewares: [transformBody(AdminDeletePromotionsPromotionRulesReq)], + }, + { + method: ["DELETE"], + matcher: "/admin/promotions/:id/target-rules", + middlewares: [transformBody(AdminDeletePromotionsPromotionRulesReq)], + }, + { + method: ["DELETE"], + matcher: "/admin/promotions/:id/buy-rules", + middlewares: [transformBody(AdminDeletePromotionsPromotionRulesReq)], + }, ] diff --git a/packages/medusa/src/api-v2/admin/promotions/validators.ts b/packages/medusa/src/api-v2/admin/promotions/validators.ts index 1e22d2af76..4bdf8a5bfe 100644 --- a/packages/medusa/src/api-v2/admin/promotions/validators.ts +++ b/packages/medusa/src/api-v2/admin/promotions/validators.ts @@ -8,6 +8,7 @@ import { } from "@medusajs/utils" import { Type } from "class-transformer" import { + ArrayNotEmpty, IsArray, IsBoolean, IsEnum, @@ -221,3 +222,9 @@ export class AdminPostPromotionsPromotionRulesReq { @Type(() => PromotionRule) rules: PromotionRule[] } + +export class AdminDeletePromotionsPromotionRulesReq { + @ArrayNotEmpty() + @IsString({ each: true }) + rule_ids: string[] +} diff --git a/packages/promotion/integration-tests/__tests__/services/promotion-module/promotion.spec.ts b/packages/promotion/integration-tests/__tests__/services/promotion-module/promotion.spec.ts index 1f632c758f..755afaa96a 100644 --- a/packages/promotion/integration-tests/__tests__/services/promotion-module/promotion.spec.ts +++ b/packages/promotion/integration-tests/__tests__/services/promotion-module/promotion.spec.ts @@ -1318,9 +1318,9 @@ describe("Promotion Service", () => { }) it("should successfully remove rules for a promotion", async () => { - const [ruleId] = promotion.rules.map((rule) => rule.id) + const ruleIds = promotion.rules.map((rule) => rule.id) - await service.removePromotionRules(promotion.id, [{ id: ruleId }]) + await service.removePromotionRules(promotion.id, ruleIds) const updatedPromotion = await service.retrieve(promotion.id, { relations: ["rules", "rules.values"], @@ -1391,11 +1391,11 @@ describe("Promotion Service", () => { }) it("should successfully create rules for a promotion", async () => { - const [ruleId] = promotion.application_method.target_rules.map( + const ruleIds = promotion.application_method.target_rules.map( (rule) => rule.id ) - await service.removePromotionTargetRules(promotion.id, [{ id: ruleId }]) + await service.removePromotionTargetRules(promotion.id, ruleIds) const updatedPromotion = await service.retrieve(promotion.id, { relations: ["application_method.target_rules.values"], @@ -1477,11 +1477,11 @@ describe("Promotion Service", () => { }) it("should successfully remove rules for a promotion", async () => { - const [ruleId] = promotion.application_method.buy_rules.map( + const ruleIds = promotion.application_method.buy_rules.map( (rule) => rule.id ) - await service.removePromotionBuyRules(promotion.id, [{ id: ruleId }]) + await service.removePromotionBuyRules(promotion.id, ruleIds) const updatedPromotion = await service.retrieve(promotion.id, { relations: ["application_method.buy_rules.values"], diff --git a/packages/promotion/src/services/promotion-module.ts b/packages/promotion/src/services/promotion-module.ts index 46a20d555c..bb675f03fb 100644 --- a/packages/promotion/src/services/promotion-module.ts +++ b/packages/promotion/src/services/promotion-module.ts @@ -897,32 +897,26 @@ export default class PromotionModuleService< @InjectManager("baseRepository_") async removePromotionRules( promotionId: string, - rulesData: PromotionTypes.RemovePromotionRuleDTO[], + ruleIds: string[], @MedusaContext() sharedContext: Context = {} ): Promise { - await this.removePromotionRules_(promotionId, rulesData, sharedContext) + await this.removePromotionRules_(promotionId, ruleIds, sharedContext) } @InjectTransactionManager("baseRepository_") protected async removePromotionRules_( promotionId: string, - rulesData: PromotionTypes.RemovePromotionRuleDTO[], + ruleIds: string[], @MedusaContext() sharedContext: Context = {} ): Promise { - const promotionRuleIdsToRemove = rulesData.map((ruleData) => ruleData.id) const promotion = await this.promotionService_.retrieve( promotionId, { relations: ["rules"] }, sharedContext ) - const existingPromotionRuleIds = promotion.rules - .toArray() - .map((rule) => rule.id) - - const idsToRemove = promotionRuleIdsToRemove.filter((ruleId) => - existingPromotionRuleIds.includes(ruleId) - ) + const existingRuleIds = promotion.rules.map((rule) => rule.id) + const idsToRemove = ruleIds.filter((id) => existingRuleIds.includes(id)) await this.promotionRuleService_.delete(idsToRemove, sharedContext) } @@ -930,12 +924,12 @@ export default class PromotionModuleService< @InjectManager("baseRepository_") async removePromotionTargetRules( promotionId: string, - rulesData: PromotionTypes.RemovePromotionRuleDTO[], + ruleIds: string[], @MedusaContext() sharedContext: Context = {} ): Promise { await this.removeApplicationMethodRules_( promotionId, - rulesData, + ruleIds, ApplicationMethodRuleTypes.TARGET_RULES, sharedContext ) @@ -944,12 +938,12 @@ export default class PromotionModuleService< @InjectManager("baseRepository_") async removePromotionBuyRules( promotionId: string, - rulesData: PromotionTypes.RemovePromotionRuleDTO[], + ruleIds: string[], @MedusaContext() sharedContext: Context = {} ): Promise { await this.removeApplicationMethodRules_( promotionId, - rulesData, + ruleIds, ApplicationMethodRuleTypes.BUY_RULES, sharedContext ) @@ -958,13 +952,12 @@ export default class PromotionModuleService< @InjectTransactionManager("baseRepository_") protected async removeApplicationMethodRules_( promotionId: string, - rulesData: PromotionTypes.RemovePromotionRuleDTO[], + ruleIds: string[], relation: | ApplicationMethodRuleTypes.TARGET_RULES | ApplicationMethodRuleTypes.BUY_RULES, @MedusaContext() sharedContext: Context = {} ): Promise { - const promotionRuleIds = rulesData.map((ruleData) => ruleData.id) const promotion = await this.promotionService_.retrieve( promotionId, { relations: [`application_method.${relation}`] }, @@ -981,8 +974,7 @@ export default class PromotionModuleService< } const targetRuleIdsToRemove = applicationMethod[relation] - .toArray() - .filter((rule) => promotionRuleIds.includes(rule.id)) + .filter((rule) => ruleIds.includes(rule.id)) .map((rule) => rule.id) await this.promotionRuleService_.delete( diff --git a/packages/types/src/promotion/service.ts b/packages/types/src/promotion/service.ts index 905331cd55..effcb80195 100644 --- a/packages/types/src/promotion/service.ts +++ b/packages/types/src/promotion/service.ts @@ -12,7 +12,6 @@ import { FilterablePromotionProps, PromotionDTO, PromotionRuleDTO, - RemovePromotionRuleDTO, UpdatePromotionDTO, } from "./common" import { CreateCampaignDTO, UpdateCampaignDTO } from "./mutations" @@ -99,19 +98,19 @@ export interface IPromotionModuleService extends IModuleService { removePromotionRules( promotionId: string, - rulesData: RemovePromotionRuleDTO[], + ruleIds: string[], sharedContext?: Context ): Promise removePromotionTargetRules( promotionId: string, - rulesData: RemovePromotionRuleDTO[], + ruleIds: string[], sharedContext?: Context ): Promise removePromotionBuyRules( promotionId: string, - rulesData: RemovePromotionRuleDTO[], + ruleIds: string[], sharedContext?: Context ): Promise diff --git a/packages/types/src/promotion/workflows.ts b/packages/types/src/promotion/workflows.ts index 512e19298f..c516e45c7d 100644 --- a/packages/types/src/promotion/workflows.ts +++ b/packages/types/src/promotion/workflows.ts @@ -7,3 +7,11 @@ export type AddPromotionRulesWorkflowDTO = { rules: CreatePromotionRuleDTO[] } } + +export type RemovePromotionRulesWorkflowDTO = { + rule_type: PromotionRuleTypes + data: { + id: string + rule_ids: string[] + } +}