Skip to content

Commit

Permalink
feat(core-flows,medusa,types): remove rules from promotion endpoints …
Browse files Browse the repository at this point in the history
…+ workflows (#6696)
  • Loading branch information
riqwan authored Mar 14, 2024
1 parent 640eccd commit 04a532e
Show file tree
Hide file tree
Showing 16 changed files with 485 additions and 53 deletions.
7 changes: 7 additions & 0 deletions .changeset/fifty-gorillas-lie.md
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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)
})
})
})
},
})
26 changes: 11 additions & 15 deletions packages/core-flows/src/promotion/steps/add-rules-to-promotions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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),
})
Expand All @@ -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<IPromotionModuleService>(
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))
}
)
1 change: 1 addition & 0 deletions packages/core-flows/src/promotion/steps/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Original file line number Diff line number Diff line change
@@ -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<IPromotionModuleService>(
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<IPromotionModuleService>(
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!),
}))
}
1 change: 1 addition & 0 deletions packages/core-flows/src/promotion/workflows/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Original file line number Diff line number Diff line change
@@ -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<RemovePromotionRulesWorkflowDTO>
): WorkflowData<void> => {
removeRulesFromPromotionsStep(input)
}
)
Loading

0 comments on commit 04a532e

Please sign in to comment.