Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(types,utils): added promotion create with rules and application target rules #5957

Merged
merged 10 commits into from
Jan 3, 2024
6 changes: 6 additions & 0 deletions .changeset/breezy-horses-destroy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@medusajs/types": patch
"@medusajs/utils": patch
---

feat(types,utils): added promotion create with rules
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,82 @@ describe("Promotion Service", () => {
},
])

const [promotion] = await service.list({
id: [createdPromotion.id],
})
const [promotion] = await service.list(
{
id: [createdPromotion.id],
},
{
relations: ["application_method"],
}
)

expect(promotion).toEqual(
expect.objectContaining({
code: "PROMOTION_TEST",
is_automatic: false,
type: "standard",
application_method: expect.objectContaining({
type: "fixed",
target_type: "order",
value: 100,
}),
})
)
})

it("should create a promotion with order application method with rules successfully", async () => {
const [createdPromotion] = await service.create([
{
code: "PROMOTION_TEST",
type: PromotionType.STANDARD,
application_method: {
type: "fixed",
target_type: "order",
value: 100,
target_rules: [
{
attribute: "product_id",
operator: "eq",
values: ["prod_tshirt"],
},
],
},
},
])

const [promotion] = await service.list(
{
id: [createdPromotion.id],
},
{
relations: [
"application_method",
"application_method.target_rules.values",
],
}
)

expect(promotion).toEqual(
expect.objectContaining({
code: "PROMOTION_TEST",
is_automatic: false,
type: "standard",
application_method: expect.objectContaining({
type: "fixed",
target_type: "order",
value: 100,
target_rules: [
expect.objectContaining({
attribute: "product_id",
operator: "eq",
values: expect.arrayContaining([
expect.objectContaining({
value: "prod_tshirt",
}),
]),
}),
],
}),
})
)
})
Expand Down Expand Up @@ -128,5 +195,156 @@ describe("Promotion Service", () => {
"application_method.max_quantity is required when application_method.allocation is 'each'"
)
})

it("should create a promotion with rules successfully", async () => {
const [createdPromotion] = await service.create([
{
code: "PROMOTION_TEST",
type: PromotionType.STANDARD,
rules: [
{
attribute: "customer_group_id",
operator: "in",
values: ["VIP", "top100"],
},
],
},
])

const [promotion] = await service.list(
{
id: [createdPromotion.id],
},
{
relations: ["rules", "rules.values"],
}
)

expect(promotion).toEqual(
expect.objectContaining({
code: "PROMOTION_TEST",
is_automatic: false,
type: "standard",
rules: [
expect.objectContaining({
attribute: "customer_group_id",
operator: "in",
values: expect.arrayContaining([
expect.objectContaining({
value: "VIP",
}),
expect.objectContaining({
value: "top100",
}),
]),
}),
],
})
)
})

it("should create a promotion with rules with single value successfully", async () => {
const [createdPromotion] = await service.create([
{
code: "PROMOTION_TEST",
type: PromotionType.STANDARD,
rules: [
{
attribute: "customer_group_id",
operator: "eq",
values: "VIP",
},
],
},
])

const [promotion] = await service.list(
{
id: [createdPromotion.id],
},
{
relations: ["rules", "rules.values"],
}
)

expect(promotion).toEqual(
expect.objectContaining({
code: "PROMOTION_TEST",
is_automatic: false,
type: "standard",
rules: [
expect.objectContaining({
attribute: "customer_group_id",
operator: "eq",
values: expect.arrayContaining([
expect.objectContaining({
value: "VIP",
}),
]),
}),
],
})
)
})

it("should throw an error when rule attribute is invalid", async () => {
const error = await service
.create([
{
code: "PROMOTION_TEST",
type: PromotionType.STANDARD,
rules: [
{
attribute: "",
operator: "eq",
values: "VIP",
} as any,
],
},
])
.catch((e) => e)

expect(error.message).toContain("rules[].attribute is a required field")
})

it("should throw an error when rule operator is invalid", async () => {
let error = await service
.create([
{
code: "PROMOTION_TEST",
type: PromotionType.STANDARD,
rules: [
{
attribute: "customer_group",
operator: "",
values: "VIP",
} as any,
],
},
])
.catch((e) => e)

expect(error.message).toContain("rules[].operator is a required field")

error = await service
.create([
{
code: "PROMOTION_TEST",
type: PromotionType.STANDARD,
rules: [
{
attribute: "customer_group",
operator: "doesnotexist",
values: "VIP",
} as any,
],
},
])
.catch((e) => e)

expect(error.message).toContain(
"rules[].operator (doesnotexist) is invalid. It should be one of gt, lt, eq, ne, in"
)
})
})
})
12 changes: 12 additions & 0 deletions packages/promotion/src/loaders/container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ export default async ({

container.register({
promotionService: asClass(defaultServices.PromotionService).singleton(),
promotionRuleService: asClass(
defaultServices.PromotionRuleService
).singleton(),
promotionRuleValueService: asClass(
defaultServices.PromotionRuleValueService
).singleton(),
applicationMethodService: asClass(
defaultServices.ApplicationMethodService
).singleton(),
Expand All @@ -44,5 +50,11 @@ function loadDefaultRepositories({ container }) {
promotionRepository: asClass(
defaultRepositories.PromotionRepository
).singleton(),
promotionRuleRepository: asClass(
defaultRepositories.PromotionRuleRepository
).singleton(),
promotionRuleValueRepository: asClass(
defaultRepositories.PromotionRuleValueRepository
).singleton(),
})
}
Loading