feat(core-flows,medusa,types,utils): add rules to promotion endpoints + workflow (#6692)

* feat(core-flows,medusa,types,utils): add rules to promotion endpoints + workflow

* chore: fix specs

* chore: move input type to types package
This commit is contained in:
Riqwan Thamir authored and GitHub committed 2024-03-13 21:19:24 +01:00
1 parent 02e784ce78
commit 640eccd5dd
23 files changed
+777 -179

No files matched your search

@@ -1084,8 +1084,8 @@ describe("Promotion Service", () => {
expect(error.message).toEqual("promotion - id must be defined")
})
it("should successfully create rules for a promotion", async () => {
promotion = await service.addPromotionRules(promotion.id, [
it("should successfully add rules to a promotion", async () => {
const promotionRules = await service.addPromotionRules(promotion.id, [
{
attribute: "customer_group_id",
operator: "in",
@@ -1093,21 +1093,17 @@ describe("Promotion Service", () => {
},
])
expect(promotion).toEqual(
expect(promotionRules).toEqual([
expect.objectContaining({
id: promotion.id,
rules: [
expect.objectContaining({
attribute: "customer_group_id",
operator: "in",
values: [
expect.objectContaining({ value: "VIP" }),
expect.objectContaining({ value: "top100" }),
],
}),
],
})
)
id: promotionRules[0].id,
attribute: "customer_group_id",
operator: "in",
values: expect.arrayContaining([
expect.objectContaining({ value: "VIP" }),
expect.objectContaining({ value: "top100" }),
]),
}),
])
})
})
@@ -1160,31 +1156,28 @@ describe("Promotion Service", () => {
})
it("should successfully create target rules for a promotion", async () => {
promotion = await service.addPromotionTargetRules(promotion.id, [
{
const promotionRules = await service.addPromotionTargetRules(
promotion.id,
[
{
attribute: "customer_group_id",
operator: "in",
values: ["VIP", "top100"],
},
]
)
expect(promotionRules).toEqual([
expect.objectContaining({
id: promotionRules[0].id,
attribute: "customer_group_id",
operator: "in",
values: ["VIP", "top100"],
},
values: expect.arrayContaining([
expect.objectContaining({ value: "VIP" }),
expect.objectContaining({ value: "top100" }),
]),
}),
])
expect(promotion).toEqual(
expect.objectContaining({
id: promotion.id,
application_method: expect.objectContaining({
target_rules: [
expect.objectContaining({
attribute: "customer_group_id",
operator: "in",
values: [
expect.objectContaining({ value: "VIP" }),
expect.objectContaining({ value: "top100" }),
],
}),
],
}),
})
)
})
})
@@ -1250,7 +1243,7 @@ describe("Promotion Service", () => {
})
it("should successfully create buy rules for a buyget promotion", async () => {
promotion = await service.addPromotionBuyRules(promotion.id, [
const promotionRules = await service.addPromotionBuyRules(promotion.id, [
{
attribute: "product.id",
operator: "in",
@@ -1258,30 +1251,17 @@ describe("Promotion Service", () => {
},
])
expect(promotion).toEqual(
expect(promotionRules).toEqual([
expect.objectContaining({
id: promotion.id,
application_method: expect.objectContaining({
buy_rules: expect.arrayContaining([
expect.objectContaining({
attribute: "product_collection.id",
operator: "eq",
values: expect.arrayContaining([
expect.objectContaining({ value: "pcol_towel" }),
]),
}),
expect.objectContaining({
attribute: "product.id",
operator: "in",
values: expect.arrayContaining([
expect.objectContaining({ value: "prod_3" }),
expect.objectContaining({ value: "prod_4" }),
]),
}),
]),
}),
})
)
id: promotionRules[0].id,
attribute: "product.id",
operator: "in",
values: expect.arrayContaining([
expect.objectContaining({ value: "prod_3" }),
expect.objectContaining({ value: "prod_4" }),
]),
}),
])
})
})
@@ -1337,14 +1317,16 @@ describe("Promotion Service", () => {
expect(error.message).toEqual("promotion - id must be defined")
})
it("should successfully create rules for a promotion", async () => {
it("should successfully remove rules for a promotion", async () => {
const [ruleId] = promotion.rules.map((rule) => rule.id)
promotion = await service.removePromotionRules(promotion.id, [
{ id: ruleId },
])
await service.removePromotionRules(promotion.id, [{ id: ruleId }])
expect(promotion).toEqual(
const updatedPromotion = await service.retrieve(promotion.id, {
relations: ["rules", "rules.values"],
})
expect(updatedPromotion).toEqual(
expect.objectContaining({
id: promotion.id,
rules: [],
@@ -1413,11 +1395,13 @@ describe("Promotion Service", () => {
(rule) => rule.id
)
promotion = await service.removePromotionTargetRules(promotion.id, [
{ id: ruleId },
])
await service.removePromotionTargetRules(promotion.id, [{ id: ruleId }])
expect(promotion).toEqual(
const updatedPromotion = await service.retrieve(promotion.id, {
relations: ["application_method.target_rules.values"],
})
expect(updatedPromotion).toEqual(
expect.objectContaining({
id: promotion.id,
application_method: expect.objectContaining({
@@ -1497,11 +1481,13 @@ describe("Promotion Service", () => {
(rule) => rule.id
)
promotion = await service.removePromotionBuyRules(promotion.id, [
{ id: ruleId },
])
await service.removePromotionBuyRules(promotion.id, [{ id: ruleId }])
expect(promotion).toEqual(
const updatedPromotion = await service.retrieve(promotion.id, {
relations: ["application_method.buy_rules.values"],
})
expect(updatedPromotion).toEqual(
expect.objectContaining({
id: promotion.id,
application_method: expect.objectContaining({
@@ -755,19 +755,19 @@ export default class PromotionModuleService<
promotionId: string,
rulesData: PromotionTypes.CreatePromotionRuleDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<PromotionTypes.PromotionDTO> {
): Promise<PromotionTypes.PromotionRuleDTO[]> {
const promotion = await this.promotionService_.retrieve(promotionId)
await this.createPromotionRulesAndValues_(
const createdPromotionRules = await this.createPromotionRulesAndValues_(
rulesData,
"promotions",
promotion,
sharedContext
)
return await this.retrieve(
promotionId,
{ relations: ["rules", "rules.values"] },
return this.listPromotionRules(
{ id: createdPromotionRules.map((r) => r.id) },
{ relations: ["values"] },
sharedContext
)
}
@@ -777,7 +777,7 @@ export default class PromotionModuleService<
promotionId: string,
rulesData: PromotionTypes.CreatePromotionRuleDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<PromotionTypes.PromotionDTO> {
): Promise<PromotionTypes.PromotionRuleDTO[]> {
const promotion = await this.promotionService_.retrieve(promotionId, {
relations: ["application_method"],
})
@@ -791,24 +791,16 @@ export default class PromotionModuleService<
)
}
await this.createPromotionRulesAndValues_(
const createdPromotionRules = await this.createPromotionRulesAndValues_(
rulesData,
"method_target_rules",
applicationMethod,
sharedContext
)
return await this.retrieve(
promotionId,
{
relations: [
"rules",
"rules.values",
"application_method",
"application_method.target_rules",
"application_method.target_rules.values",
],
},
return await this.listPromotionRules(
{ id: createdPromotionRules.map((pr) => pr.id) },
{ relations: ["values"] },
sharedContext
)
}
@@ -818,7 +810,7 @@ export default class PromotionModuleService<
promotionId: string,
rulesData: PromotionTypes.CreatePromotionRuleDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<PromotionTypes.PromotionDTO> {
): Promise<PromotionTypes.PromotionRuleDTO[]> {
const promotion = await this.promotionService_.retrieve(promotionId, {
relations: ["application_method"],
})
@@ -832,24 +824,16 @@ export default class PromotionModuleService<
)
}
await this.createPromotionRulesAndValues_(
const createdPromotionRules = await this.createPromotionRulesAndValues_(
rulesData,
"method_buy_rules",
applicationMethod,
sharedContext
)
return await this.retrieve(
promotionId,
{
relations: [
"rules",
"rules.values",
"application_method",
"application_method.buy_rules",
"application_method.buy_rules.values",
],
},
return await this.listPromotionRules(
{ id: createdPromotionRules.map((pr) => pr.id) },
{ relations: ["values"] },
sharedContext
)
}
@@ -860,7 +844,25 @@ export default class PromotionModuleService<
relationName: "promotions" | "method_target_rules" | "method_buy_rules",
relation: Promotion | ApplicationMethod,
@MedusaContext() sharedContext: Context = {}
) {
): Promise<TPromotionRule[]> {
const createdPromotionRules: TPromotionRule[] = []
const promotion =
relation instanceof ApplicationMethod ? relation.promotion : relation
if (!rulesData.length) {
return []
}
if (
relationName === "method_buy_rules" &&
promotion.type === PromotionType.STANDARD
) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`Can't add buy rules to a ${PromotionType.STANDARD} promotion`
)
}
validatePromotionRuleAttributes(rulesData)
for (const ruleData of rulesData) {
@@ -875,6 +877,8 @@ export default class PromotionModuleService<
sharedContext
)
createdPromotionRules.push(createdPromotionRule)
const ruleValues = Array.isArray(values) ? values : [values]
const promotionRuleValuesData = ruleValues.map((ruleValue) => ({
value: ruleValue,
@@ -886,6 +890,8 @@ export default class PromotionModuleService<
sharedContext
)
}
return createdPromotionRules
}
@InjectManager("baseRepository_")
@@ -893,14 +899,8 @@ export default class PromotionModuleService<
promotionId: string,
rulesData: PromotionTypes.RemovePromotionRuleDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<PromotionTypes.PromotionDTO> {
): Promise<void> {
await this.removePromotionRules_(promotionId, rulesData, sharedContext)
return await this.retrieve(
promotionId,
{ relations: ["rules", "rules.values"] },
sharedContext
)
}
@InjectTransactionManager("baseRepository_")
@@ -932,27 +932,13 @@ export default class PromotionModuleService<
promotionId: string,
rulesData: PromotionTypes.RemovePromotionRuleDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<PromotionTypes.PromotionDTO> {
): Promise<void> {
await this.removeApplicationMethodRules_(
promotionId,
rulesData,
ApplicationMethodRuleTypes.TARGET_RULES,
sharedContext
)
return await this.retrieve(
promotionId,
{
relations: [
"rules",
"rules.values",
"application_method",
"application_method.target_rules",
"application_method.target_rules.values",
],
},
sharedContext
)
}
@InjectManager("baseRepository_")
@@ -960,27 +946,13 @@ export default class PromotionModuleService<
promotionId: string,
rulesData: PromotionTypes.RemovePromotionRuleDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<PromotionTypes.PromotionDTO> {
): Promise<void> {
await this.removeApplicationMethodRules_(
promotionId,
rulesData,
ApplicationMethodRuleTypes.BUY_RULES,
sharedContext
)
return await this.retrieve(
promotionId,
{
relations: [
"rules",
"rules.values",
"application_method",
"application_method.buy_rules",
"application_method.buy_rules.values",
],
},
sharedContext
)
}
@InjectTransactionManager("baseRepository_")