feat(types,utils): added promotion create with rules and application target rules (#5957)
* feat(types,utils): added promotion create with rules * chore: add rules to promotion and application method * chore: use common code for rule and values * chore: address pr reviews * chore: fix test
This commit is contained in:
1 parent
d16d10619d
commit
42cc8ae3f8
33 files changed
+1552
-114
No files matched your search
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
"@medusajs/types": patch
|
||||||
|
"@medusajs/utils": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
feat(types,utils): added promotion create with rules
|
||||||
+220
-2
@@ -75,15 +75,82 @@ describe("Promotion Service", () => {
|
|||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
const [promotion] = await service.list({
|
const [promotion] = await service.list(
|
||||||
|
{
|
||||||
id: [createdPromotion.id],
|
id: [createdPromotion.id],
|
||||||
})
|
},
|
||||||
|
{
|
||||||
|
relations: ["application_method"],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
expect(promotion).toEqual(
|
expect(promotion).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
code: "PROMOTION_TEST",
|
code: "PROMOTION_TEST",
|
||||||
is_automatic: false,
|
is_automatic: false,
|
||||||
type: "standard",
|
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",
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@@ -128,5 +195,156 @@ describe("Promotion Service", () => {
|
|||||||
"application_method.max_quantity is required when application_method.allocation is 'each'"
|
"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 gte, lte, gt, lt, eq, ne, in"
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -19,6 +19,12 @@ export default async ({
|
|||||||
|
|
||||||
container.register({
|
container.register({
|
||||||
promotionService: asClass(defaultServices.PromotionService).singleton(),
|
promotionService: asClass(defaultServices.PromotionService).singleton(),
|
||||||
|
promotionRuleService: asClass(
|
||||||
|
defaultServices.PromotionRuleService
|
||||||
|
).singleton(),
|
||||||
|
promotionRuleValueService: asClass(
|
||||||
|
defaultServices.PromotionRuleValueService
|
||||||
|
).singleton(),
|
||||||
applicationMethodService: asClass(
|
applicationMethodService: asClass(
|
||||||
defaultServices.ApplicationMethodService
|
defaultServices.ApplicationMethodService
|
||||||
).singleton(),
|
).singleton(),
|
||||||
@@ -44,5 +50,11 @@ function loadDefaultRepositories({ container }) {
|
|||||||
promotionRepository: asClass(
|
promotionRepository: asClass(
|
||||||
defaultRepositories.PromotionRepository
|
defaultRepositories.PromotionRepository
|
||||||
).singleton(),
|
).singleton(),
|
||||||
|
promotionRuleRepository: asClass(
|
||||||
|
defaultRepositories.PromotionRuleRepository
|
||||||
|
).singleton(),
|
||||||
|
promotionRuleValueRepository: asClass(
|
||||||
|
defaultRepositories.PromotionRuleValueRepository
|
||||||
|
).singleton(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
{
|
{
|
||||||
"namespaces": [
|
"namespaces": ["public"],
|
||||||
"public"
|
|
||||||
],
|
|
||||||
"name": "public",
|
"name": "public",
|
||||||
"tables": [
|
"tables": [
|
||||||
{
|
{
|
||||||
@@ -41,10 +39,7 @@
|
|||||||
"autoincrement": false,
|
"autoincrement": false,
|
||||||
"primary": false,
|
"primary": false,
|
||||||
"nullable": false,
|
"nullable": false,
|
||||||
"enumItems": [
|
"enumItems": ["standard", "buyget"],
|
||||||
"standard",
|
|
||||||
"buyget"
|
|
||||||
],
|
|
||||||
"mappedType": "enum"
|
"mappedType": "enum"
|
||||||
},
|
},
|
||||||
"created_at": {
|
"created_at": {
|
||||||
@@ -84,18 +79,14 @@
|
|||||||
"schema": "public",
|
"schema": "public",
|
||||||
"indexes": [
|
"indexes": [
|
||||||
{
|
{
|
||||||
"columnNames": [
|
"columnNames": ["code"],
|
||||||
"code"
|
|
||||||
],
|
|
||||||
"composite": false,
|
"composite": false,
|
||||||
"keyName": "IDX_promotion_code",
|
"keyName": "IDX_promotion_code",
|
||||||
"primary": false,
|
"primary": false,
|
||||||
"unique": false
|
"unique": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"columnNames": [
|
"columnNames": ["type"],
|
||||||
"type"
|
|
||||||
],
|
|
||||||
"composite": false,
|
"composite": false,
|
||||||
"keyName": "IDX_promotion_type",
|
"keyName": "IDX_promotion_type",
|
||||||
"primary": false,
|
"primary": false,
|
||||||
@@ -103,18 +94,14 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"keyName": "IDX_promotion_code_unique",
|
"keyName": "IDX_promotion_code_unique",
|
||||||
"columnNames": [
|
"columnNames": ["code"],
|
||||||
"code"
|
|
||||||
],
|
|
||||||
"composite": false,
|
"composite": false,
|
||||||
"primary": false,
|
"primary": false,
|
||||||
"unique": true
|
"unique": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"keyName": "promotion_pkey",
|
"keyName": "promotion_pkey",
|
||||||
"columnNames": [
|
"columnNames": ["id"],
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"composite": false,
|
"composite": false,
|
||||||
"primary": true,
|
"primary": true,
|
||||||
"unique": true
|
"unique": true
|
||||||
@@ -159,10 +146,7 @@
|
|||||||
"autoincrement": false,
|
"autoincrement": false,
|
||||||
"primary": false,
|
"primary": false,
|
||||||
"nullable": false,
|
"nullable": false,
|
||||||
"enumItems": [
|
"enumItems": ["fixed", "percentage"],
|
||||||
"fixed",
|
|
||||||
"percentage"
|
|
||||||
],
|
|
||||||
"mappedType": "enum"
|
"mappedType": "enum"
|
||||||
},
|
},
|
||||||
"target_type": {
|
"target_type": {
|
||||||
@@ -172,11 +156,7 @@
|
|||||||
"autoincrement": false,
|
"autoincrement": false,
|
||||||
"primary": false,
|
"primary": false,
|
||||||
"nullable": false,
|
"nullable": false,
|
||||||
"enumItems": [
|
"enumItems": ["order", "shipping", "item"],
|
||||||
"order",
|
|
||||||
"shipping",
|
|
||||||
"item"
|
|
||||||
],
|
|
||||||
"mappedType": "enum"
|
"mappedType": "enum"
|
||||||
},
|
},
|
||||||
"allocation": {
|
"allocation": {
|
||||||
@@ -186,10 +166,7 @@
|
|||||||
"autoincrement": false,
|
"autoincrement": false,
|
||||||
"primary": false,
|
"primary": false,
|
||||||
"nullable": true,
|
"nullable": true,
|
||||||
"enumItems": [
|
"enumItems": ["each", "across"],
|
||||||
"each",
|
|
||||||
"across"
|
|
||||||
],
|
|
||||||
"mappedType": "enum"
|
"mappedType": "enum"
|
||||||
},
|
},
|
||||||
"promotion_id": {
|
"promotion_id": {
|
||||||
@@ -238,36 +215,28 @@
|
|||||||
"schema": "public",
|
"schema": "public",
|
||||||
"indexes": [
|
"indexes": [
|
||||||
{
|
{
|
||||||
"columnNames": [
|
"columnNames": ["type"],
|
||||||
"type"
|
|
||||||
],
|
|
||||||
"composite": false,
|
"composite": false,
|
||||||
"keyName": "IDX_application_method_type",
|
"keyName": "IDX_application_method_type",
|
||||||
"primary": false,
|
"primary": false,
|
||||||
"unique": false
|
"unique": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"columnNames": [
|
"columnNames": ["target_type"],
|
||||||
"target_type"
|
|
||||||
],
|
|
||||||
"composite": false,
|
"composite": false,
|
||||||
"keyName": "IDX_application_method_target_type",
|
"keyName": "IDX_application_method_target_type",
|
||||||
"primary": false,
|
"primary": false,
|
||||||
"unique": false
|
"unique": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"columnNames": [
|
"columnNames": ["allocation"],
|
||||||
"allocation"
|
|
||||||
],
|
|
||||||
"composite": false,
|
"composite": false,
|
||||||
"keyName": "IDX_application_method_allocation",
|
"keyName": "IDX_application_method_allocation",
|
||||||
"primary": false,
|
"primary": false,
|
||||||
"unique": false
|
"unique": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"columnNames": [
|
"columnNames": ["promotion_id"],
|
||||||
"promotion_id"
|
|
||||||
],
|
|
||||||
"composite": false,
|
"composite": false,
|
||||||
"keyName": "application_method_promotion_id_unique",
|
"keyName": "application_method_promotion_id_unique",
|
||||||
"primary": false,
|
"primary": false,
|
||||||
@@ -275,9 +244,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"keyName": "application_method_pkey",
|
"keyName": "application_method_pkey",
|
||||||
"columnNames": [
|
"columnNames": ["id"],
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"composite": false,
|
"composite": false,
|
||||||
"primary": true,
|
"primary": true,
|
||||||
"unique": true
|
"unique": true
|
||||||
@@ -287,17 +254,282 @@
|
|||||||
"foreignKeys": {
|
"foreignKeys": {
|
||||||
"application_method_promotion_id_foreign": {
|
"application_method_promotion_id_foreign": {
|
||||||
"constraintName": "application_method_promotion_id_foreign",
|
"constraintName": "application_method_promotion_id_foreign",
|
||||||
"columnNames": [
|
"columnNames": ["promotion_id"],
|
||||||
"promotion_id"
|
|
||||||
],
|
|
||||||
"localTableName": "public.application_method",
|
"localTableName": "public.application_method",
|
||||||
"referencedColumnNames": [
|
"referencedColumnNames": ["id"],
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"referencedTableName": "public.promotion",
|
"referencedTableName": "public.promotion",
|
||||||
"updateRule": "cascade"
|
"updateRule": "cascade"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"unsigned": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"primary": false,
|
||||||
|
"nullable": false,
|
||||||
|
"mappedType": "text"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"name": "description",
|
||||||
|
"type": "text",
|
||||||
|
"unsigned": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"primary": false,
|
||||||
|
"nullable": true,
|
||||||
|
"mappedType": "text"
|
||||||
|
},
|
||||||
|
"attribute": {
|
||||||
|
"name": "attribute",
|
||||||
|
"type": "text",
|
||||||
|
"unsigned": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"primary": false,
|
||||||
|
"nullable": false,
|
||||||
|
"mappedType": "text"
|
||||||
|
},
|
||||||
|
"operator": {
|
||||||
|
"name": "operator",
|
||||||
|
"type": "text",
|
||||||
|
"unsigned": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"primary": false,
|
||||||
|
"nullable": false,
|
||||||
|
"enumItems": ["gte", "lte", "gt", "lt", "eq", "ne", "in"],
|
||||||
|
"mappedType": "enum"
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "timestamptz",
|
||||||
|
"unsigned": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"primary": false,
|
||||||
|
"nullable": false,
|
||||||
|
"length": 6,
|
||||||
|
"default": "now()",
|
||||||
|
"mappedType": "datetime"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"name": "updated_at",
|
||||||
|
"type": "timestamptz",
|
||||||
|
"unsigned": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"primary": false,
|
||||||
|
"nullable": false,
|
||||||
|
"length": 6,
|
||||||
|
"default": "now()",
|
||||||
|
"mappedType": "datetime"
|
||||||
|
},
|
||||||
|
"deleted_at": {
|
||||||
|
"name": "deleted_at",
|
||||||
|
"type": "timestamptz",
|
||||||
|
"unsigned": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"primary": false,
|
||||||
|
"nullable": true,
|
||||||
|
"length": 6,
|
||||||
|
"mappedType": "datetime"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": "promotion_rule",
|
||||||
|
"schema": "public",
|
||||||
|
"indexes": [
|
||||||
|
{
|
||||||
|
"columnNames": ["attribute"],
|
||||||
|
"composite": false,
|
||||||
|
"keyName": "IDX_promotion_rule_attribute",
|
||||||
|
"primary": false,
|
||||||
|
"unique": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"columnNames": ["operator"],
|
||||||
|
"composite": false,
|
||||||
|
"keyName": "IDX_promotion_rule_operator",
|
||||||
|
"primary": false,
|
||||||
|
"unique": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"keyName": "promotion_rule_pkey",
|
||||||
|
"columnNames": ["id"],
|
||||||
|
"composite": false,
|
||||||
|
"primary": true,
|
||||||
|
"unique": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"checks": [],
|
||||||
|
"foreignKeys": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"columns": {
|
||||||
|
"promotion_id": {
|
||||||
|
"name": "promotion_id",
|
||||||
|
"type": "text",
|
||||||
|
"unsigned": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"primary": false,
|
||||||
|
"nullable": false,
|
||||||
|
"mappedType": "text"
|
||||||
|
},
|
||||||
|
"promotion_rule_id": {
|
||||||
|
"name": "promotion_rule_id",
|
||||||
|
"type": "text",
|
||||||
|
"unsigned": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"primary": false,
|
||||||
|
"nullable": false,
|
||||||
|
"mappedType": "text"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": "promotion_promotion_rule",
|
||||||
|
"schema": "public",
|
||||||
|
"indexes": [
|
||||||
|
{
|
||||||
|
"keyName": "promotion_promotion_rule_pkey",
|
||||||
|
"columnNames": ["promotion_id", "promotion_rule_id"],
|
||||||
|
"composite": true,
|
||||||
|
"primary": true,
|
||||||
|
"unique": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"checks": [],
|
||||||
|
"foreignKeys": {
|
||||||
|
"promotion_promotion_rule_promotion_id_foreign": {
|
||||||
|
"constraintName": "promotion_promotion_rule_promotion_id_foreign",
|
||||||
|
"columnNames": ["promotion_id"],
|
||||||
|
"localTableName": "public.promotion_promotion_rule",
|
||||||
|
"referencedColumnNames": ["id"],
|
||||||
|
"referencedTableName": "public.promotion",
|
||||||
|
"deleteRule": "cascade",
|
||||||
|
"updateRule": "cascade"
|
||||||
|
},
|
||||||
|
"promotion_promotion_rule_promotion_rule_id_foreign": {
|
||||||
|
"constraintName": "promotion_promotion_rule_promotion_rule_id_foreign",
|
||||||
|
"columnNames": ["promotion_rule_id"],
|
||||||
|
"localTableName": "public.promotion_promotion_rule",
|
||||||
|
"referencedColumnNames": ["id"],
|
||||||
|
"referencedTableName": "public.promotion_rule",
|
||||||
|
"deleteRule": "cascade",
|
||||||
|
"updateRule": "cascade"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"columns": {
|
||||||
|
"application_method_id": {
|
||||||
|
"name": "application_method_id",
|
||||||
|
"type": "text",
|
||||||
|
"unsigned": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"primary": false,
|
||||||
|
"nullable": false,
|
||||||
|
"mappedType": "text"
|
||||||
|
},
|
||||||
|
"promotion_rule_id": {
|
||||||
|
"name": "promotion_rule_id",
|
||||||
|
"type": "text",
|
||||||
|
"unsigned": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"primary": false,
|
||||||
|
"nullable": false,
|
||||||
|
"mappedType": "text"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": "application_method_promotion_rule",
|
||||||
|
"schema": "public",
|
||||||
|
"indexes": [
|
||||||
|
{
|
||||||
|
"keyName": "application_method_promotion_rule_pkey",
|
||||||
|
"columnNames": ["application_method_id", "promotion_rule_id"],
|
||||||
|
"composite": true,
|
||||||
|
"primary": true,
|
||||||
|
"unique": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"checks": [],
|
||||||
|
"foreignKeys": {
|
||||||
|
"application_method_promotion_rule_application_method_id_foreign": {
|
||||||
|
"constraintName": "application_method_promotion_rule_application_method_id_foreign",
|
||||||
|
"columnNames": ["application_method_id"],
|
||||||
|
"localTableName": "public.application_method_promotion_rule",
|
||||||
|
"referencedColumnNames": ["id"],
|
||||||
|
"referencedTableName": "public.application_method",
|
||||||
|
"deleteRule": "cascade",
|
||||||
|
"updateRule": "cascade"
|
||||||
|
},
|
||||||
|
"application_method_promotion_rule_promotion_rule_id_foreign": {
|
||||||
|
"constraintName": "application_method_promotion_rule_promotion_rule_id_foreign",
|
||||||
|
"columnNames": ["promotion_rule_id"],
|
||||||
|
"localTableName": "public.application_method_promotion_rule",
|
||||||
|
"referencedColumnNames": ["id"],
|
||||||
|
"referencedTableName": "public.promotion_rule",
|
||||||
|
"deleteRule": "cascade",
|
||||||
|
"updateRule": "cascade"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"unsigned": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"primary": false,
|
||||||
|
"nullable": false,
|
||||||
|
"mappedType": "text"
|
||||||
|
},
|
||||||
|
"promotion_rule_id": {
|
||||||
|
"name": "promotion_rule_id",
|
||||||
|
"type": "text",
|
||||||
|
"unsigned": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"primary": false,
|
||||||
|
"nullable": false,
|
||||||
|
"mappedType": "text"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"name": "value",
|
||||||
|
"type": "text",
|
||||||
|
"unsigned": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"primary": false,
|
||||||
|
"nullable": false,
|
||||||
|
"mappedType": "text"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": "promotion_rule_value",
|
||||||
|
"schema": "public",
|
||||||
|
"indexes": [
|
||||||
|
{
|
||||||
|
"columnNames": ["promotion_rule_id"],
|
||||||
|
"composite": false,
|
||||||
|
"keyName": "IDX_promotion_rule_promotion_rule_value_id",
|
||||||
|
"primary": false,
|
||||||
|
"unique": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"keyName": "promotion_rule_value_pkey",
|
||||||
|
"columnNames": ["id"],
|
||||||
|
"composite": false,
|
||||||
|
"primary": true,
|
||||||
|
"unique": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"checks": [],
|
||||||
|
"foreignKeys": {
|
||||||
|
"promotion_rule_value_promotion_rule_id_foreign": {
|
||||||
|
"constraintName": "promotion_rule_value_promotion_rule_id_foreign",
|
||||||
|
"columnNames": ["promotion_rule_id"],
|
||||||
|
"localTableName": "public.promotion_rule_value",
|
||||||
|
"referencedColumnNames": ["id"],
|
||||||
|
"referencedTableName": "public.promotion_rule",
|
||||||
|
"deleteRule": "cascade",
|
||||||
|
"updateRule": "cascade"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
import { Migration } from "@mikro-orm/migrations"
|
|
||||||
|
|
||||||
export class Migration20231221104256 extends Migration {
|
|
||||||
async up(): Promise<void> {
|
|
||||||
this.addSql(
|
|
||||||
'create table "promotion" ("id" text not null, "code" text not null, "is_automatic" boolean not null default false, "type" text check ("type" in (\'standard\', \'buyget\')) not null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "promotion_pkey" primary key ("id"));'
|
|
||||||
)
|
|
||||||
this.addSql('create index "IDX_promotion_code" on "promotion" ("code");')
|
|
||||||
this.addSql('create index "IDX_promotion_type" on "promotion" ("type");')
|
|
||||||
this.addSql(
|
|
||||||
'alter table "promotion" add constraint "IDX_promotion_code_unique" unique ("code");'
|
|
||||||
)
|
|
||||||
|
|
||||||
this.addSql(
|
|
||||||
'create table "application_method" ("id" text not null, "value" numeric null, "max_quantity" numeric null, "type" text check ("type" in (\'fixed\', \'percentage\')) not null, "target_type" text check ("target_type" in (\'order\', \'shipping\', \'item\')) not null, "allocation" text check ("allocation" in (\'each\', \'across\')) null, "promotion_id" text not null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "application_method_pkey" primary key ("id"));'
|
|
||||||
)
|
|
||||||
this.addSql(
|
|
||||||
'create index "IDX_application_method_type" on "application_method" ("type");'
|
|
||||||
)
|
|
||||||
this.addSql(
|
|
||||||
'create index "IDX_application_method_target_type" on "application_method" ("target_type");'
|
|
||||||
)
|
|
||||||
this.addSql(
|
|
||||||
'create index "IDX_application_method_allocation" on "application_method" ("allocation");'
|
|
||||||
)
|
|
||||||
this.addSql(
|
|
||||||
'alter table "application_method" add constraint "application_method_promotion_id_unique" unique ("promotion_id");'
|
|
||||||
)
|
|
||||||
|
|
||||||
this.addSql(
|
|
||||||
'alter table "application_method" add constraint "application_method_promotion_id_foreign" foreign key ("promotion_id") references "promotion" ("id") on update cascade;'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
import { Migration } from "@mikro-orm/migrations"
|
||||||
|
|
||||||
|
export class Migration20240102130345 extends Migration {
|
||||||
|
async up(): Promise<void> {
|
||||||
|
this.addSql(
|
||||||
|
'create table "promotion" ("id" text not null, "code" text not null, "is_automatic" boolean not null default false, "type" text check ("type" in (\'standard\', \'buyget\')) not null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "promotion_pkey" primary key ("id"));'
|
||||||
|
)
|
||||||
|
this.addSql('create index "IDX_promotion_code" on "promotion" ("code");')
|
||||||
|
this.addSql('create index "IDX_promotion_type" on "promotion" ("type");')
|
||||||
|
this.addSql(
|
||||||
|
'alter table "promotion" add constraint "IDX_promotion_code_unique" unique ("code");'
|
||||||
|
)
|
||||||
|
|
||||||
|
this.addSql(
|
||||||
|
'create table "application_method" ("id" text not null, "value" numeric null, "max_quantity" numeric null, "type" text check ("type" in (\'fixed\', \'percentage\')) not null, "target_type" text check ("target_type" in (\'order\', \'shipping\', \'item\')) not null, "allocation" text check ("allocation" in (\'each\', \'across\')) null, "promotion_id" text not null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "application_method_pkey" primary key ("id"));'
|
||||||
|
)
|
||||||
|
this.addSql(
|
||||||
|
'create index "IDX_application_method_type" on "application_method" ("type");'
|
||||||
|
)
|
||||||
|
this.addSql(
|
||||||
|
'create index "IDX_application_method_target_type" on "application_method" ("target_type");'
|
||||||
|
)
|
||||||
|
this.addSql(
|
||||||
|
'create index "IDX_application_method_allocation" on "application_method" ("allocation");'
|
||||||
|
)
|
||||||
|
this.addSql(
|
||||||
|
'alter table "application_method" add constraint "application_method_promotion_id_unique" unique ("promotion_id");'
|
||||||
|
)
|
||||||
|
|
||||||
|
this.addSql(
|
||||||
|
'create table "promotion_rule" ("id" text not null, "description" text null, "attribute" text not null, "operator" text check ("operator" in (\'gte\', \'lte\', \'gt\', \'lt\', \'eq\', \'ne\', \'in\')) not null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "promotion_rule_pkey" primary key ("id"));'
|
||||||
|
)
|
||||||
|
this.addSql(
|
||||||
|
'create index "IDX_promotion_rule_attribute" on "promotion_rule" ("attribute");'
|
||||||
|
)
|
||||||
|
this.addSql(
|
||||||
|
'create index "IDX_promotion_rule_operator" on "promotion_rule" ("operator");'
|
||||||
|
)
|
||||||
|
|
||||||
|
this.addSql(
|
||||||
|
'create table "promotion_promotion_rule" ("promotion_id" text not null, "promotion_rule_id" text not null, constraint "promotion_promotion_rule_pkey" primary key ("promotion_id", "promotion_rule_id"));'
|
||||||
|
)
|
||||||
|
|
||||||
|
this.addSql(
|
||||||
|
'create table "application_method_promotion_rule" ("application_method_id" text not null, "promotion_rule_id" text not null, constraint "application_method_promotion_rule_pkey" primary key ("application_method_id", "promotion_rule_id"));'
|
||||||
|
)
|
||||||
|
|
||||||
|
this.addSql(
|
||||||
|
'create table "promotion_rule_value" ("id" text not null, "promotion_rule_id" text not null, "value" text not null, constraint "promotion_rule_value_pkey" primary key ("id"));'
|
||||||
|
)
|
||||||
|
this.addSql(
|
||||||
|
'create index "IDX_promotion_rule_promotion_rule_value_id" on "promotion_rule_value" ("promotion_rule_id");'
|
||||||
|
)
|
||||||
|
|
||||||
|
this.addSql(
|
||||||
|
'alter table "application_method" add constraint "application_method_promotion_id_foreign" foreign key ("promotion_id") references "promotion" ("id") on update cascade;'
|
||||||
|
)
|
||||||
|
|
||||||
|
this.addSql(
|
||||||
|
'alter table "promotion_promotion_rule" add constraint "promotion_promotion_rule_promotion_id_foreign" foreign key ("promotion_id") references "promotion" ("id") on update cascade on delete cascade;'
|
||||||
|
)
|
||||||
|
this.addSql(
|
||||||
|
'alter table "promotion_promotion_rule" add constraint "promotion_promotion_rule_promotion_rule_id_foreign" foreign key ("promotion_rule_id") references "promotion_rule" ("id") on update cascade on delete cascade;'
|
||||||
|
)
|
||||||
|
|
||||||
|
this.addSql(
|
||||||
|
'alter table "application_method_promotion_rule" add constraint "application_method_promotion_rule_application_method_id_foreign" foreign key ("application_method_id") references "application_method" ("id") on update cascade on delete cascade;'
|
||||||
|
)
|
||||||
|
this.addSql(
|
||||||
|
'alter table "application_method_promotion_rule" add constraint "application_method_promotion_rule_promotion_rule_id_foreign" foreign key ("promotion_rule_id") references "promotion_rule" ("id") on update cascade on delete cascade;'
|
||||||
|
)
|
||||||
|
|
||||||
|
this.addSql(
|
||||||
|
'alter table "promotion_rule_value" add constraint "promotion_rule_value_promotion_rule_id_foreign" foreign key ("promotion_rule_id") references "promotion_rule" ("id") on update cascade on delete cascade;'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,9 +6,11 @@ import {
|
|||||||
import { PromotionUtils, generateEntityId } from "@medusajs/utils"
|
import { PromotionUtils, generateEntityId } from "@medusajs/utils"
|
||||||
import {
|
import {
|
||||||
BeforeCreate,
|
BeforeCreate,
|
||||||
|
Collection,
|
||||||
Entity,
|
Entity,
|
||||||
Enum,
|
Enum,
|
||||||
Index,
|
Index,
|
||||||
|
ManyToMany,
|
||||||
OnInit,
|
OnInit,
|
||||||
OneToOne,
|
OneToOne,
|
||||||
OptionalProps,
|
OptionalProps,
|
||||||
@@ -16,8 +18,15 @@ import {
|
|||||||
Property,
|
Property,
|
||||||
} from "@mikro-orm/core"
|
} from "@mikro-orm/core"
|
||||||
import Promotion from "./promotion"
|
import Promotion from "./promotion"
|
||||||
|
import PromotionRule from "./promotion-rule"
|
||||||
|
|
||||||
type OptionalFields = "value" | "max_quantity" | "allocation"
|
type OptionalFields =
|
||||||
|
| "value"
|
||||||
|
| "max_quantity"
|
||||||
|
| "allocation"
|
||||||
|
| "created_at"
|
||||||
|
| "updated_at"
|
||||||
|
| "deleted_at"
|
||||||
@Entity()
|
@Entity()
|
||||||
export default class ApplicationMethod {
|
export default class ApplicationMethod {
|
||||||
[OptionalProps]?: OptionalFields
|
[OptionalProps]?: OptionalFields
|
||||||
@@ -26,10 +35,10 @@ export default class ApplicationMethod {
|
|||||||
id!: string
|
id!: string
|
||||||
|
|
||||||
@Property({ columnType: "numeric", nullable: true, serializer: Number })
|
@Property({ columnType: "numeric", nullable: true, serializer: Number })
|
||||||
value?: number
|
value?: number | null
|
||||||
|
|
||||||
@Property({ columnType: "numeric", nullable: true, serializer: Number })
|
@Property({ columnType: "numeric", nullable: true, serializer: Number })
|
||||||
max_quantity?: number
|
max_quantity?: number | null
|
||||||
|
|
||||||
@Index({ name: "IDX_application_method_type" })
|
@Index({ name: "IDX_application_method_type" })
|
||||||
@Enum(() => PromotionUtils.ApplicationMethodType)
|
@Enum(() => PromotionUtils.ApplicationMethodType)
|
||||||
@@ -51,12 +60,19 @@ export default class ApplicationMethod {
|
|||||||
})
|
})
|
||||||
promotion: Promotion
|
promotion: Promotion
|
||||||
|
|
||||||
|
@ManyToMany(() => PromotionRule, "application_methods", {
|
||||||
|
owner: true,
|
||||||
|
pivotTable: "application_method_promotion_rule",
|
||||||
|
cascade: ["soft-remove"] as any,
|
||||||
|
})
|
||||||
|
target_rules = new Collection<PromotionRule>(this)
|
||||||
|
|
||||||
@Property({
|
@Property({
|
||||||
onCreate: () => new Date(),
|
onCreate: () => new Date(),
|
||||||
columnType: "timestamptz",
|
columnType: "timestamptz",
|
||||||
defaultRaw: "now()",
|
defaultRaw: "now()",
|
||||||
})
|
})
|
||||||
created_at?: Date
|
created_at: Date
|
||||||
|
|
||||||
@Property({
|
@Property({
|
||||||
onCreate: () => new Date(),
|
onCreate: () => new Date(),
|
||||||
@@ -64,18 +80,18 @@ export default class ApplicationMethod {
|
|||||||
columnType: "timestamptz",
|
columnType: "timestamptz",
|
||||||
defaultRaw: "now()",
|
defaultRaw: "now()",
|
||||||
})
|
})
|
||||||
updated_at?: Date
|
updated_at: Date
|
||||||
|
|
||||||
@Property({ columnType: "timestamptz", nullable: true })
|
@Property({ columnType: "timestamptz", nullable: true })
|
||||||
deleted_at?: Date
|
deleted_at: Date | null
|
||||||
|
|
||||||
@BeforeCreate()
|
@BeforeCreate()
|
||||||
onCreate() {
|
onCreate() {
|
||||||
this.id = generateEntityId(this.id, "app_method")
|
this.id = generateEntityId(this.id, "proappmet")
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnInit()
|
@OnInit()
|
||||||
onInit() {
|
onInit() {
|
||||||
this.id = generateEntityId(this.id, "promo")
|
this.id = generateEntityId(this.id, "proappmet")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,2 +1,4 @@
|
|||||||
export { default as ApplicationMethod } from "./application-method"
|
export { default as ApplicationMethod } from "./application-method"
|
||||||
export { default as Promotion } from "./promotion"
|
export { default as Promotion } from "./promotion"
|
||||||
|
export { default as PromotionRule } from "./promotion-rule"
|
||||||
|
export { default as PromotionRuleValue } from "./promotion-rule-value"
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
import {
|
||||||
|
BeforeCreate,
|
||||||
|
Entity,
|
||||||
|
ManyToOne,
|
||||||
|
OnInit,
|
||||||
|
PrimaryKey,
|
||||||
|
Property,
|
||||||
|
} from "@mikro-orm/core"
|
||||||
|
|
||||||
|
import { generateEntityId } from "@medusajs/utils"
|
||||||
|
import PromotionRule from "./promotion-rule"
|
||||||
|
|
||||||
|
@Entity()
|
||||||
|
export default class PromotionRuleValue {
|
||||||
|
@PrimaryKey({ columnType: "text" })
|
||||||
|
id!: string
|
||||||
|
|
||||||
|
@ManyToOne(() => PromotionRule, {
|
||||||
|
onDelete: "cascade",
|
||||||
|
fieldName: "promotion_rule_id",
|
||||||
|
index: "IDX_promotion_rule_promotion_rule_value_id",
|
||||||
|
})
|
||||||
|
promotion_rule: PromotionRule
|
||||||
|
|
||||||
|
@Property({ columnType: "text" })
|
||||||
|
value: string
|
||||||
|
|
||||||
|
@BeforeCreate()
|
||||||
|
onCreate() {
|
||||||
|
this.id = generateEntityId(this.id, "prorulval")
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnInit()
|
||||||
|
onInit() {
|
||||||
|
this.id = generateEntityId(this.id, "prorulval")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
import { PromotionRuleOperatorValues } from "@medusajs/types"
|
||||||
|
import { PromotionUtils, generateEntityId } from "@medusajs/utils"
|
||||||
|
import {
|
||||||
|
BeforeCreate,
|
||||||
|
Cascade,
|
||||||
|
Collection,
|
||||||
|
Entity,
|
||||||
|
Enum,
|
||||||
|
Index,
|
||||||
|
ManyToMany,
|
||||||
|
OnInit,
|
||||||
|
OneToMany,
|
||||||
|
OptionalProps,
|
||||||
|
PrimaryKey,
|
||||||
|
Property,
|
||||||
|
} from "@mikro-orm/core"
|
||||||
|
import ApplicationMethod from "./application-method"
|
||||||
|
import Promotion from "./promotion"
|
||||||
|
import PromotionRuleValue from "./promotion-rule-value"
|
||||||
|
|
||||||
|
type OptionalFields = "description" | "created_at" | "updated_at" | "deleted_at"
|
||||||
|
type OptionalRelations = "values" | "promotions"
|
||||||
|
|
||||||
|
@Entity()
|
||||||
|
export default class PromotionRule {
|
||||||
|
[OptionalProps]?: OptionalFields | OptionalRelations
|
||||||
|
|
||||||
|
@PrimaryKey({ columnType: "text" })
|
||||||
|
id!: string
|
||||||
|
|
||||||
|
@Property({ columnType: "text", nullable: true })
|
||||||
|
description: string | null
|
||||||
|
|
||||||
|
@Index({ name: "IDX_promotion_rule_attribute" })
|
||||||
|
@Property({ columnType: "text" })
|
||||||
|
attribute: string
|
||||||
|
|
||||||
|
@Index({ name: "IDX_promotion_rule_operator" })
|
||||||
|
@Enum(() => PromotionUtils.PromotionRuleOperator)
|
||||||
|
operator: PromotionRuleOperatorValues
|
||||||
|
|
||||||
|
@OneToMany(() => PromotionRuleValue, (prv) => prv.promotion_rule, {
|
||||||
|
cascade: [Cascade.REMOVE],
|
||||||
|
})
|
||||||
|
values = new Collection<PromotionRuleValue>(this)
|
||||||
|
|
||||||
|
@ManyToMany(() => Promotion, (promotion) => promotion.rules)
|
||||||
|
promotions = new Collection<Promotion>(this)
|
||||||
|
|
||||||
|
@ManyToMany(
|
||||||
|
() => ApplicationMethod,
|
||||||
|
(applicationMethod) => applicationMethod.target_rules
|
||||||
|
)
|
||||||
|
application_methods = new Collection<ApplicationMethod>(this)
|
||||||
|
|
||||||
|
@Property({
|
||||||
|
onCreate: () => new Date(),
|
||||||
|
columnType: "timestamptz",
|
||||||
|
defaultRaw: "now()",
|
||||||
|
})
|
||||||
|
created_at: Date
|
||||||
|
|
||||||
|
@Property({
|
||||||
|
onCreate: () => new Date(),
|
||||||
|
onUpdate: () => new Date(),
|
||||||
|
columnType: "timestamptz",
|
||||||
|
defaultRaw: "now()",
|
||||||
|
})
|
||||||
|
updated_at: Date
|
||||||
|
|
||||||
|
@Property({ columnType: "timestamptz", nullable: true })
|
||||||
|
deleted_at: Date | null
|
||||||
|
|
||||||
|
@BeforeCreate()
|
||||||
|
onCreate() {
|
||||||
|
this.id = generateEntityId(this.id, "prorul")
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnInit()
|
||||||
|
onInit() {
|
||||||
|
this.id = generateEntityId(this.id, "prorul")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,9 +2,11 @@ import { PromotionType } from "@medusajs/types"
|
|||||||
import { PromotionUtils, generateEntityId } from "@medusajs/utils"
|
import { PromotionUtils, generateEntityId } from "@medusajs/utils"
|
||||||
import {
|
import {
|
||||||
BeforeCreate,
|
BeforeCreate,
|
||||||
|
Collection,
|
||||||
Entity,
|
Entity,
|
||||||
Enum,
|
Enum,
|
||||||
Index,
|
Index,
|
||||||
|
ManyToMany,
|
||||||
OnInit,
|
OnInit,
|
||||||
OneToOne,
|
OneToOne,
|
||||||
OptionalProps,
|
OptionalProps,
|
||||||
@@ -13,8 +15,13 @@ import {
|
|||||||
Unique,
|
Unique,
|
||||||
} from "@mikro-orm/core"
|
} from "@mikro-orm/core"
|
||||||
import ApplicationMethod from "./application-method"
|
import ApplicationMethod from "./application-method"
|
||||||
|
import PromotionRule from "./promotion-rule"
|
||||||
|
|
||||||
type OptionalFields = "is_automatic"
|
type OptionalFields =
|
||||||
|
| "is_automatic"
|
||||||
|
| "created_at"
|
||||||
|
| "updated_at"
|
||||||
|
| "deleted_at"
|
||||||
type OptionalRelations = "application_method"
|
type OptionalRelations = "application_method"
|
||||||
@Entity()
|
@Entity()
|
||||||
export default class Promotion {
|
export default class Promotion {
|
||||||
@@ -44,12 +51,19 @@ export default class Promotion {
|
|||||||
})
|
})
|
||||||
application_method: ApplicationMethod
|
application_method: ApplicationMethod
|
||||||
|
|
||||||
|
@ManyToMany(() => PromotionRule, "promotions", {
|
||||||
|
owner: true,
|
||||||
|
pivotTable: "promotion_promotion_rule",
|
||||||
|
cascade: ["soft-remove"] as any,
|
||||||
|
})
|
||||||
|
rules = new Collection<PromotionRule>(this)
|
||||||
|
|
||||||
@Property({
|
@Property({
|
||||||
onCreate: () => new Date(),
|
onCreate: () => new Date(),
|
||||||
columnType: "timestamptz",
|
columnType: "timestamptz",
|
||||||
defaultRaw: "now()",
|
defaultRaw: "now()",
|
||||||
})
|
})
|
||||||
created_at?: Date
|
created_at: Date
|
||||||
|
|
||||||
@Property({
|
@Property({
|
||||||
onCreate: () => new Date(),
|
onCreate: () => new Date(),
|
||||||
@@ -57,10 +71,10 @@ export default class Promotion {
|
|||||||
columnType: "timestamptz",
|
columnType: "timestamptz",
|
||||||
defaultRaw: "now()",
|
defaultRaw: "now()",
|
||||||
})
|
})
|
||||||
updated_at?: Date
|
updated_at: Date
|
||||||
|
|
||||||
@Property({ columnType: "timestamptz", nullable: true })
|
@Property({ columnType: "timestamptz", nullable: true })
|
||||||
deleted_at?: Date
|
deleted_at: Date | null
|
||||||
|
|
||||||
@BeforeCreate()
|
@BeforeCreate()
|
||||||
onCreate() {
|
onCreate() {
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
export { MikroOrmBaseRepository as BaseRepository } from "@medusajs/utils"
|
export { MikroOrmBaseRepository as BaseRepository } from "@medusajs/utils"
|
||||||
export { ApplicationMethodRepository } from "./application-method"
|
export { ApplicationMethodRepository } from "./application-method"
|
||||||
export { PromotionRepository } from "./promotion"
|
export { PromotionRepository } from "./promotion"
|
||||||
|
export { PromotionRuleRepository } from "./promotion-rule"
|
||||||
|
export { PromotionRuleValueRepository } from "./promotion-rule-value"
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
import { Context, DAL } from "@medusajs/types"
|
||||||
|
import { DALUtils, MedusaError, arrayDifference } from "@medusajs/utils"
|
||||||
|
import {
|
||||||
|
FilterQuery as MikroFilterQuery,
|
||||||
|
FindOptions as MikroOptions,
|
||||||
|
} from "@mikro-orm/core"
|
||||||
|
|
||||||
|
import { SqlEntityManager } from "@mikro-orm/postgresql"
|
||||||
|
import { PromotionRuleValue } from "@models"
|
||||||
|
import {
|
||||||
|
CreatePromotionRuleValueDTO,
|
||||||
|
UpdatePromotionRuleValueDTO,
|
||||||
|
} from "@types"
|
||||||
|
|
||||||
|
export class PromotionRuleValueRepository extends DALUtils.MikroOrmBaseRepository {
|
||||||
|
protected readonly manager_: SqlEntityManager
|
||||||
|
|
||||||
|
constructor({ manager }: { manager: SqlEntityManager }) {
|
||||||
|
// @ts-ignore
|
||||||
|
// eslint-disable-next-line prefer-rest-params
|
||||||
|
super(...arguments)
|
||||||
|
this.manager_ = manager
|
||||||
|
}
|
||||||
|
|
||||||
|
async find(
|
||||||
|
findOptions: DAL.FindOptions<PromotionRuleValue> = { where: {} },
|
||||||
|
context: Context = {}
|
||||||
|
): Promise<PromotionRuleValue[]> {
|
||||||
|
const manager = this.getActiveManager<SqlEntityManager>(context)
|
||||||
|
|
||||||
|
const findOptions_ = { ...findOptions }
|
||||||
|
findOptions_.options ??= {}
|
||||||
|
|
||||||
|
return await manager.find(
|
||||||
|
PromotionRuleValue,
|
||||||
|
findOptions_.where as MikroFilterQuery<PromotionRuleValue>,
|
||||||
|
findOptions_.options as MikroOptions<PromotionRuleValue>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
async findAndCount(
|
||||||
|
findOptions: DAL.FindOptions<PromotionRuleValue> = { where: {} },
|
||||||
|
context: Context = {}
|
||||||
|
): Promise<[PromotionRuleValue[], number]> {
|
||||||
|
const manager = this.getActiveManager<SqlEntityManager>(context)
|
||||||
|
|
||||||
|
const findOptions_ = { ...findOptions }
|
||||||
|
findOptions_.options ??= {}
|
||||||
|
|
||||||
|
return await manager.findAndCount(
|
||||||
|
PromotionRuleValue,
|
||||||
|
findOptions_.where as MikroFilterQuery<PromotionRuleValue>,
|
||||||
|
findOptions_.options as MikroOptions<PromotionRuleValue>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
async delete(ids: string[], context: Context = {}): Promise<void> {
|
||||||
|
const manager = this.getActiveManager<SqlEntityManager>(context)
|
||||||
|
await manager.nativeDelete(PromotionRuleValue, { id: { $in: ids } }, {})
|
||||||
|
}
|
||||||
|
|
||||||
|
async create(
|
||||||
|
data: CreatePromotionRuleValueDTO[],
|
||||||
|
context: Context = {}
|
||||||
|
): Promise<PromotionRuleValue[]> {
|
||||||
|
const manager = this.getActiveManager<SqlEntityManager>(context)
|
||||||
|
|
||||||
|
const promotionRuleValue = data.map((promotionRuleValue) => {
|
||||||
|
return manager.create(PromotionRuleValue, promotionRuleValue)
|
||||||
|
})
|
||||||
|
|
||||||
|
manager.persist(promotionRuleValue)
|
||||||
|
|
||||||
|
return promotionRuleValue
|
||||||
|
}
|
||||||
|
|
||||||
|
async update(
|
||||||
|
data: UpdatePromotionRuleValueDTO[],
|
||||||
|
context: Context = {}
|
||||||
|
): Promise<PromotionRuleValue[]> {
|
||||||
|
const manager = this.getActiveManager<SqlEntityManager>(context)
|
||||||
|
const promotionRuleValueIds = data.map(
|
||||||
|
(promotionRuleValue) => promotionRuleValue.id
|
||||||
|
)
|
||||||
|
const existingPromotionRuleValues = await this.find(
|
||||||
|
{
|
||||||
|
where: {
|
||||||
|
id: {
|
||||||
|
$in: promotionRuleValueIds,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
context
|
||||||
|
)
|
||||||
|
|
||||||
|
const dataAndExistingIdDifference = arrayDifference(
|
||||||
|
data.map((d) => d.id),
|
||||||
|
existingPromotionRuleValues.map((plr) => plr.id)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (dataAndExistingIdDifference.length) {
|
||||||
|
throw new MedusaError(
|
||||||
|
MedusaError.Types.NOT_FOUND,
|
||||||
|
`PromotionRuleValue with id(s) "${dataAndExistingIdDifference.join(
|
||||||
|
", "
|
||||||
|
)}" not found`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const existingPromotionRuleValueMap = new Map(
|
||||||
|
existingPromotionRuleValues.map<[string, PromotionRuleValue]>(
|
||||||
|
(promotionRuleValue) => [promotionRuleValue.id, promotionRuleValue]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
const promotionRuleValue = data.map((promotionRuleValueData) => {
|
||||||
|
const existingPromotionRuleValue = existingPromotionRuleValueMap.get(
|
||||||
|
promotionRuleValueData.id
|
||||||
|
)!
|
||||||
|
|
||||||
|
return manager.assign(existingPromotionRuleValue, promotionRuleValueData)
|
||||||
|
})
|
||||||
|
|
||||||
|
manager.persist(promotionRuleValue)
|
||||||
|
|
||||||
|
return promotionRuleValue
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
import { Context, DAL } from "@medusajs/types"
|
||||||
|
import { DALUtils, MedusaError, arrayDifference } from "@medusajs/utils"
|
||||||
|
import {
|
||||||
|
FilterQuery as MikroFilterQuery,
|
||||||
|
FindOptions as MikroOptions,
|
||||||
|
} from "@mikro-orm/core"
|
||||||
|
|
||||||
|
import { SqlEntityManager } from "@mikro-orm/postgresql"
|
||||||
|
import { PromotionRule } from "@models"
|
||||||
|
import { CreatePromotionRuleDTO, UpdatePromotionRuleDTO } from "@types"
|
||||||
|
|
||||||
|
export class PromotionRuleRepository extends DALUtils.MikroOrmBaseRepository {
|
||||||
|
protected readonly manager_: SqlEntityManager
|
||||||
|
|
||||||
|
constructor({ manager }: { manager: SqlEntityManager }) {
|
||||||
|
// @ts-ignore
|
||||||
|
// eslint-disable-next-line prefer-rest-params
|
||||||
|
super(...arguments)
|
||||||
|
this.manager_ = manager
|
||||||
|
}
|
||||||
|
|
||||||
|
async find(
|
||||||
|
findOptions: DAL.FindOptions<PromotionRule> = { where: {} },
|
||||||
|
context: Context = {}
|
||||||
|
): Promise<PromotionRule[]> {
|
||||||
|
const manager = this.getActiveManager<SqlEntityManager>(context)
|
||||||
|
|
||||||
|
const findOptions_ = { ...findOptions }
|
||||||
|
findOptions_.options ??= {}
|
||||||
|
|
||||||
|
return await manager.find(
|
||||||
|
PromotionRule,
|
||||||
|
findOptions_.where as MikroFilterQuery<PromotionRule>,
|
||||||
|
findOptions_.options as MikroOptions<PromotionRule>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
async findAndCount(
|
||||||
|
findOptions: DAL.FindOptions<PromotionRule> = { where: {} },
|
||||||
|
context: Context = {}
|
||||||
|
): Promise<[PromotionRule[], number]> {
|
||||||
|
const manager = this.getActiveManager<SqlEntityManager>(context)
|
||||||
|
|
||||||
|
const findOptions_ = { ...findOptions }
|
||||||
|
findOptions_.options ??= {}
|
||||||
|
|
||||||
|
return await manager.findAndCount(
|
||||||
|
PromotionRule,
|
||||||
|
findOptions_.where as MikroFilterQuery<PromotionRule>,
|
||||||
|
findOptions_.options as MikroOptions<PromotionRule>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
async delete(ids: string[], context: Context = {}): Promise<void> {
|
||||||
|
const manager = this.getActiveManager<SqlEntityManager>(context)
|
||||||
|
await manager.nativeDelete(PromotionRule, { id: { $in: ids } }, {})
|
||||||
|
}
|
||||||
|
|
||||||
|
async create(
|
||||||
|
data: CreatePromotionRuleDTO[],
|
||||||
|
context: Context = {}
|
||||||
|
): Promise<PromotionRule[]> {
|
||||||
|
const manager = this.getActiveManager<SqlEntityManager>(context)
|
||||||
|
|
||||||
|
const promotionRule = data.map((promotionRule) => {
|
||||||
|
return manager.create(PromotionRule, promotionRule)
|
||||||
|
})
|
||||||
|
|
||||||
|
manager.persist(promotionRule)
|
||||||
|
|
||||||
|
return promotionRule
|
||||||
|
}
|
||||||
|
|
||||||
|
async update(
|
||||||
|
data: UpdatePromotionRuleDTO[],
|
||||||
|
context: Context = {}
|
||||||
|
): Promise<PromotionRule[]> {
|
||||||
|
const manager = this.getActiveManager<SqlEntityManager>(context)
|
||||||
|
const promotionRuleIds = data.map((promotionRule) => promotionRule.id)
|
||||||
|
const existingPromotionRules = await this.find(
|
||||||
|
{
|
||||||
|
where: {
|
||||||
|
id: {
|
||||||
|
$in: promotionRuleIds,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
context
|
||||||
|
)
|
||||||
|
|
||||||
|
const dataAndExistingIdDifference = arrayDifference(
|
||||||
|
data.map((d) => d.id),
|
||||||
|
existingPromotionRules.map((plr) => plr.id)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (dataAndExistingIdDifference.length) {
|
||||||
|
throw new MedusaError(
|
||||||
|
MedusaError.Types.NOT_FOUND,
|
||||||
|
`PromotionRule with id(s) "${dataAndExistingIdDifference.join(
|
||||||
|
", "
|
||||||
|
)}" not found`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const existingPromotionRuleMap = new Map(
|
||||||
|
existingPromotionRules.map<[string, PromotionRule]>((promotionRule) => [
|
||||||
|
promotionRule.id,
|
||||||
|
promotionRule,
|
||||||
|
])
|
||||||
|
)
|
||||||
|
|
||||||
|
const promotionRule = data.map((promotionRuleData) => {
|
||||||
|
const existingPromotionRule = existingPromotionRuleMap.get(
|
||||||
|
promotionRuleData.id
|
||||||
|
)!
|
||||||
|
|
||||||
|
return manager.assign(existingPromotionRule, promotionRuleData)
|
||||||
|
})
|
||||||
|
|
||||||
|
manager.persist(promotionRule)
|
||||||
|
|
||||||
|
return promotionRule
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
export { default as ApplicationMethodService } from "./application-method"
|
export { default as ApplicationMethodService } from "./application-method"
|
||||||
export { default as PromotionService } from "./promotion"
|
export { default as PromotionService } from "./promotion"
|
||||||
export { default as PromotionModuleService } from "./promotion-module"
|
export { default as PromotionModuleService } from "./promotion-module"
|
||||||
|
export { default as PromotionRuleService } from "./promotion-rule"
|
||||||
|
export { default as PromotionRuleValueService } from "./promotion-rule-value"
|
||||||
@@ -11,16 +11,26 @@ import {
|
|||||||
InjectTransactionManager,
|
InjectTransactionManager,
|
||||||
MedusaContext,
|
MedusaContext,
|
||||||
} from "@medusajs/utils"
|
} from "@medusajs/utils"
|
||||||
import { Promotion } from "@models"
|
import { ApplicationMethod, Promotion } from "@models"
|
||||||
import { ApplicationMethodService, PromotionService } from "@services"
|
import {
|
||||||
|
ApplicationMethodService,
|
||||||
|
PromotionRuleService,
|
||||||
|
PromotionRuleValueService,
|
||||||
|
PromotionService,
|
||||||
|
} from "@services"
|
||||||
import { joinerConfig } from "../joiner-config"
|
import { joinerConfig } from "../joiner-config"
|
||||||
import { CreateApplicationMethodDTO, CreatePromotionDTO } from "../types"
|
import { CreateApplicationMethodDTO, CreatePromotionDTO } from "../types"
|
||||||
import { validateApplicationMethodAttributes } from "../utils"
|
import {
|
||||||
|
validateApplicationMethodAttributes,
|
||||||
|
validatePromotionRuleAttributes,
|
||||||
|
} from "../utils"
|
||||||
|
|
||||||
type InjectedDependencies = {
|
type InjectedDependencies = {
|
||||||
baseRepository: DAL.RepositoryService
|
baseRepository: DAL.RepositoryService
|
||||||
promotionService: PromotionService
|
promotionService: PromotionService
|
||||||
applicationMethodService: ApplicationMethodService
|
applicationMethodService: ApplicationMethodService
|
||||||
|
promotionRuleService: PromotionRuleService
|
||||||
|
promotionRuleValueService: PromotionRuleValueService
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class PromotionModuleService<
|
export default class PromotionModuleService<
|
||||||
@@ -30,18 +40,24 @@ export default class PromotionModuleService<
|
|||||||
protected baseRepository_: DAL.RepositoryService
|
protected baseRepository_: DAL.RepositoryService
|
||||||
protected promotionService_: PromotionService
|
protected promotionService_: PromotionService
|
||||||
protected applicationMethodService_: ApplicationMethodService
|
protected applicationMethodService_: ApplicationMethodService
|
||||||
|
protected promotionRuleService_: PromotionRuleService
|
||||||
|
protected promotionRuleValueService_: PromotionRuleValueService
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
{
|
{
|
||||||
baseRepository,
|
baseRepository,
|
||||||
promotionService,
|
promotionService,
|
||||||
applicationMethodService,
|
applicationMethodService,
|
||||||
|
promotionRuleService,
|
||||||
|
promotionRuleValueService,
|
||||||
}: InjectedDependencies,
|
}: InjectedDependencies,
|
||||||
protected readonly moduleDeclaration: InternalModuleDeclaration
|
protected readonly moduleDeclaration: InternalModuleDeclaration
|
||||||
) {
|
) {
|
||||||
this.baseRepository_ = baseRepository
|
this.baseRepository_ = baseRepository
|
||||||
this.promotionService_ = promotionService
|
this.promotionService_ = promotionService
|
||||||
this.applicationMethodService_ = applicationMethodService
|
this.applicationMethodService_ = applicationMethodService
|
||||||
|
this.promotionRuleService_ = promotionRuleService
|
||||||
|
this.promotionRuleValueService_ = promotionRuleValueService
|
||||||
}
|
}
|
||||||
|
|
||||||
__joinerConfig(): ModuleJoinerConfig {
|
__joinerConfig(): ModuleJoinerConfig {
|
||||||
@@ -78,7 +94,7 @@ export default class PromotionModuleService<
|
|||||||
return await this.list(
|
return await this.list(
|
||||||
{ id: promotions.map((p) => p!.id) },
|
{ id: promotions.map((p) => p!.id) },
|
||||||
{
|
{
|
||||||
relations: ["application_method"],
|
relations: ["application_method", "rules", "rules.values"],
|
||||||
},
|
},
|
||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
@@ -89,15 +105,26 @@ export default class PromotionModuleService<
|
|||||||
data: PromotionTypes.CreatePromotionDTO[],
|
data: PromotionTypes.CreatePromotionDTO[],
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@MedusaContext() sharedContext: Context = {}
|
||||||
) {
|
) {
|
||||||
|
const promotionsData: CreatePromotionDTO[] = []
|
||||||
|
const applicationMethodsData: CreateApplicationMethodDTO[] = []
|
||||||
|
|
||||||
const promotionCodeApplicationMethodDataMap = new Map<
|
const promotionCodeApplicationMethodDataMap = new Map<
|
||||||
string,
|
string,
|
||||||
PromotionTypes.CreateApplicationMethodDTO
|
PromotionTypes.CreateApplicationMethodDTO
|
||||||
>()
|
>()
|
||||||
const promotionsData: CreatePromotionDTO[] = []
|
|
||||||
const applicationMethodsData: CreateApplicationMethodDTO[] = []
|
const promotionCodeRulesDataMap = new Map<
|
||||||
|
string,
|
||||||
|
PromotionTypes.CreatePromotionRuleDTO[]
|
||||||
|
>()
|
||||||
|
const applicationMethodRuleMap = new Map<
|
||||||
|
string,
|
||||||
|
PromotionTypes.CreatePromotionRuleDTO[]
|
||||||
|
>()
|
||||||
|
|
||||||
for (const {
|
for (const {
|
||||||
application_method: applicationMethodData,
|
application_method: applicationMethodData,
|
||||||
|
rules: rulesData,
|
||||||
...promotionData
|
...promotionData
|
||||||
} of data) {
|
} of data) {
|
||||||
if (applicationMethodData) {
|
if (applicationMethodData) {
|
||||||
@@ -107,33 +134,94 @@ export default class PromotionModuleService<
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rulesData) {
|
||||||
|
promotionCodeRulesDataMap.set(promotionData.code, rulesData)
|
||||||
|
}
|
||||||
|
|
||||||
promotionsData.push(promotionData)
|
promotionsData.push(promotionData)
|
||||||
}
|
}
|
||||||
|
|
||||||
const createdPromotions = await this.promotionService_.create(
|
const createdPromotions = await this.promotionService_.create(
|
||||||
data,
|
promotionsData,
|
||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
for (const promotion of createdPromotions) {
|
for (const promotion of createdPromotions) {
|
||||||
const data = promotionCodeApplicationMethodDataMap.get(promotion.code)
|
const applMethodData = promotionCodeApplicationMethodDataMap.get(
|
||||||
|
promotion.code
|
||||||
if (!data) continue
|
)
|
||||||
|
|
||||||
|
if (applMethodData) {
|
||||||
|
const {
|
||||||
|
target_rules: targetRulesData = [],
|
||||||
|
...applicationMethodWithoutRules
|
||||||
|
} = applMethodData
|
||||||
const applicationMethodData = {
|
const applicationMethodData = {
|
||||||
...data,
|
...applicationMethodWithoutRules,
|
||||||
promotion,
|
promotion,
|
||||||
}
|
}
|
||||||
|
|
||||||
validateApplicationMethodAttributes(applicationMethodData)
|
validateApplicationMethodAttributes(applicationMethodData)
|
||||||
applicationMethodsData.push(applicationMethodData)
|
applicationMethodsData.push(applicationMethodData)
|
||||||
|
|
||||||
|
if (targetRulesData.length) {
|
||||||
|
applicationMethodRuleMap.set(promotion.id, targetRulesData)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await this.createPromotionRulesAndValues(
|
||||||
|
promotionCodeRulesDataMap.get(promotion.code) || [],
|
||||||
|
"promotions",
|
||||||
|
promotion,
|
||||||
|
sharedContext
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const createdApplicationMethods =
|
||||||
await this.applicationMethodService_.create(
|
await this.applicationMethodService_.create(
|
||||||
applicationMethodsData,
|
applicationMethodsData,
|
||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
|
for (const applicationMethod of createdApplicationMethods) {
|
||||||
|
await this.createPromotionRulesAndValues(
|
||||||
|
applicationMethodRuleMap.get(applicationMethod.promotion.id) || [],
|
||||||
|
"application_methods",
|
||||||
|
applicationMethod,
|
||||||
|
sharedContext
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return createdPromotions
|
return createdPromotions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected async createPromotionRulesAndValues(
|
||||||
|
rulesData: PromotionTypes.CreatePromotionRuleDTO[],
|
||||||
|
relationName: "promotions" | "application_methods",
|
||||||
|
relation: Promotion | ApplicationMethod,
|
||||||
|
sharedContext: Context
|
||||||
|
) {
|
||||||
|
validatePromotionRuleAttributes(rulesData)
|
||||||
|
|
||||||
|
for (const ruleData of rulesData) {
|
||||||
|
const { values, ...rest } = ruleData
|
||||||
|
const promotionRuleData = {
|
||||||
|
...rest,
|
||||||
|
[relationName]: [relation],
|
||||||
|
}
|
||||||
|
|
||||||
|
const [createdPromotionRule] = await this.promotionRuleService_.create(
|
||||||
|
[promotionRuleData],
|
||||||
|
sharedContext
|
||||||
|
)
|
||||||
|
|
||||||
|
const ruleValues = Array.isArray(values) ? values : [values]
|
||||||
|
const promotionRuleValuesData = ruleValues.map((ruleValue) => ({
|
||||||
|
value: ruleValue,
|
||||||
|
promotion_rule: createdPromotionRule,
|
||||||
|
}))
|
||||||
|
|
||||||
|
await this.promotionRuleValueService_.create(promotionRuleValuesData)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
import { Context, DAL, FindConfig, PromotionTypes } from "@medusajs/types"
|
||||||
|
import {
|
||||||
|
InjectManager,
|
||||||
|
InjectTransactionManager,
|
||||||
|
MedusaContext,
|
||||||
|
ModulesSdkUtils,
|
||||||
|
retrieveEntity,
|
||||||
|
} from "@medusajs/utils"
|
||||||
|
import { PromotionRuleValue } from "@models"
|
||||||
|
import { PromotionRuleValueRepository } from "@repositories"
|
||||||
|
import {
|
||||||
|
CreatePromotionRuleValueDTO,
|
||||||
|
UpdatePromotionRuleValueDTO,
|
||||||
|
} from "../types"
|
||||||
|
|
||||||
|
type InjectedDependencies = {
|
||||||
|
promotionRuleValueRepository: DAL.RepositoryService
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class PromotionRuleValueService<
|
||||||
|
TEntity extends PromotionRuleValue = PromotionRuleValue
|
||||||
|
> {
|
||||||
|
protected readonly promotionRuleValueRepository_: DAL.RepositoryService
|
||||||
|
|
||||||
|
constructor({ promotionRuleValueRepository }: InjectedDependencies) {
|
||||||
|
this.promotionRuleValueRepository_ = promotionRuleValueRepository
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectManager("promotionRuleValueRepository_")
|
||||||
|
async retrieve(
|
||||||
|
promotionRuleValueId: string,
|
||||||
|
config: FindConfig<PromotionTypes.PromotionRuleValueDTO> = {},
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<TEntity> {
|
||||||
|
return (await retrieveEntity<
|
||||||
|
PromotionRuleValue,
|
||||||
|
PromotionTypes.PromotionRuleValueDTO
|
||||||
|
>({
|
||||||
|
id: promotionRuleValueId,
|
||||||
|
entityName: PromotionRuleValue.name,
|
||||||
|
repository: this.promotionRuleValueRepository_,
|
||||||
|
config,
|
||||||
|
sharedContext,
|
||||||
|
})) as TEntity
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectManager("promotionRuleValueRepository_")
|
||||||
|
async list(
|
||||||
|
filters: PromotionTypes.FilterablePromotionRuleValueProps = {},
|
||||||
|
config: FindConfig<PromotionTypes.PromotionRuleValueDTO> = {},
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<TEntity[]> {
|
||||||
|
const queryOptions = ModulesSdkUtils.buildQuery<PromotionRuleValue>(
|
||||||
|
filters,
|
||||||
|
config
|
||||||
|
)
|
||||||
|
|
||||||
|
return (await this.promotionRuleValueRepository_.find(
|
||||||
|
queryOptions,
|
||||||
|
sharedContext
|
||||||
|
)) as TEntity[]
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectManager("promotionRuleValueRepository_")
|
||||||
|
async listAndCount(
|
||||||
|
filters: PromotionTypes.FilterablePromotionRuleValueProps = {},
|
||||||
|
config: FindConfig<PromotionTypes.PromotionRuleValueDTO> = {},
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<[TEntity[], number]> {
|
||||||
|
const queryOptions = ModulesSdkUtils.buildQuery<PromotionRuleValue>(
|
||||||
|
filters,
|
||||||
|
config
|
||||||
|
)
|
||||||
|
|
||||||
|
return (await this.promotionRuleValueRepository_.findAndCount(
|
||||||
|
queryOptions,
|
||||||
|
sharedContext
|
||||||
|
)) as [TEntity[], number]
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager("promotionRuleValueRepository_")
|
||||||
|
async create(
|
||||||
|
data: CreatePromotionRuleValueDTO[],
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<TEntity[]> {
|
||||||
|
return (await (
|
||||||
|
this.promotionRuleValueRepository_ as PromotionRuleValueRepository
|
||||||
|
).create(data, sharedContext)) as TEntity[]
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager("promotionRuleValueRepository_")
|
||||||
|
async update(
|
||||||
|
data: UpdatePromotionRuleValueDTO[],
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<TEntity[]> {
|
||||||
|
return (await (
|
||||||
|
this.promotionRuleValueRepository_ as PromotionRuleValueRepository
|
||||||
|
).update(data, sharedContext)) as TEntity[]
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager("promotionRuleValueRepository_")
|
||||||
|
async delete(
|
||||||
|
ids: string[],
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<void> {
|
||||||
|
await this.promotionRuleValueRepository_.delete(ids, sharedContext)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
import { Context, DAL, FindConfig, PromotionTypes } from "@medusajs/types"
|
||||||
|
import {
|
||||||
|
InjectManager,
|
||||||
|
InjectTransactionManager,
|
||||||
|
MedusaContext,
|
||||||
|
ModulesSdkUtils,
|
||||||
|
retrieveEntity,
|
||||||
|
} from "@medusajs/utils"
|
||||||
|
import { PromotionRule } from "@models"
|
||||||
|
import { PromotionRuleRepository } from "@repositories"
|
||||||
|
import { CreatePromotionRuleDTO, UpdatePromotionRuleDTO } from "../types"
|
||||||
|
|
||||||
|
type InjectedDependencies = {
|
||||||
|
promotionRuleRepository: DAL.RepositoryService
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class PromotionRuleService<
|
||||||
|
TEntity extends PromotionRule = PromotionRule
|
||||||
|
> {
|
||||||
|
protected readonly promotionRuleRepository_: DAL.RepositoryService
|
||||||
|
|
||||||
|
constructor({ promotionRuleRepository }: InjectedDependencies) {
|
||||||
|
this.promotionRuleRepository_ = promotionRuleRepository
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectManager("promotionRuleRepository_")
|
||||||
|
async retrieve(
|
||||||
|
promotionRuleId: string,
|
||||||
|
config: FindConfig<PromotionTypes.PromotionRuleDTO> = {},
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<TEntity> {
|
||||||
|
return (await retrieveEntity<
|
||||||
|
PromotionRule,
|
||||||
|
PromotionTypes.PromotionRuleDTO
|
||||||
|
>({
|
||||||
|
id: promotionRuleId,
|
||||||
|
entityName: PromotionRule.name,
|
||||||
|
repository: this.promotionRuleRepository_,
|
||||||
|
config,
|
||||||
|
sharedContext,
|
||||||
|
})) as TEntity
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectManager("promotionRuleRepository_")
|
||||||
|
async list(
|
||||||
|
filters: PromotionTypes.FilterablePromotionRuleProps = {},
|
||||||
|
config: FindConfig<PromotionTypes.PromotionRuleDTO> = {},
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<TEntity[]> {
|
||||||
|
const queryOptions = ModulesSdkUtils.buildQuery<PromotionRule>(
|
||||||
|
filters,
|
||||||
|
config
|
||||||
|
)
|
||||||
|
|
||||||
|
return (await this.promotionRuleRepository_.find(
|
||||||
|
queryOptions,
|
||||||
|
sharedContext
|
||||||
|
)) as TEntity[]
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectManager("promotionRuleRepository_")
|
||||||
|
async listAndCount(
|
||||||
|
filters: PromotionTypes.FilterablePromotionRuleProps = {},
|
||||||
|
config: FindConfig<PromotionTypes.PromotionRuleDTO> = {},
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<[TEntity[], number]> {
|
||||||
|
const queryOptions = ModulesSdkUtils.buildQuery<PromotionRule>(
|
||||||
|
filters,
|
||||||
|
config
|
||||||
|
)
|
||||||
|
|
||||||
|
return (await this.promotionRuleRepository_.findAndCount(
|
||||||
|
queryOptions,
|
||||||
|
sharedContext
|
||||||
|
)) as [TEntity[], number]
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager("promotionRuleRepository_")
|
||||||
|
async create(
|
||||||
|
data: CreatePromotionRuleDTO[],
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<TEntity[]> {
|
||||||
|
return (await (
|
||||||
|
this.promotionRuleRepository_ as PromotionRuleRepository
|
||||||
|
).create(data, sharedContext)) as TEntity[]
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager("promotionRuleRepository_")
|
||||||
|
async update(
|
||||||
|
data: UpdatePromotionRuleDTO[],
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<TEntity[]> {
|
||||||
|
return (await (
|
||||||
|
this.promotionRuleRepository_ as PromotionRuleRepository
|
||||||
|
).update(data, sharedContext)) as TEntity[]
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager("promotionRuleRepository_")
|
||||||
|
async delete(
|
||||||
|
ids: string[],
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<void> {
|
||||||
|
await this.promotionRuleRepository_.delete(ids, sharedContext)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,3 +6,5 @@ export type InitializeModuleInjectableDependencies = {
|
|||||||
|
|
||||||
export * from "./application-method"
|
export * from "./application-method"
|
||||||
export * from "./promotion"
|
export * from "./promotion"
|
||||||
|
export * from "./promotion-rule"
|
||||||
|
export * from "./promotion-rule-value"
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { PromotionRuleDTO } from "@medusajs/types"
|
||||||
|
|
||||||
|
export interface CreatePromotionRuleValueDTO {
|
||||||
|
value: any
|
||||||
|
promotion_rule: string | PromotionRuleDTO
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdatePromotionRuleValueDTO {
|
||||||
|
id: string
|
||||||
|
value: any
|
||||||
|
promotion_rule: string | PromotionRuleDTO
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import { PromotionRuleOperatorValues } from "@medusajs/types"
|
||||||
|
|
||||||
|
export interface CreatePromotionRuleDTO {
|
||||||
|
description?: string
|
||||||
|
attribute: string
|
||||||
|
operator: PromotionRuleOperatorValues
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdatePromotionRuleDTO {
|
||||||
|
id: string
|
||||||
|
}
|
||||||
@@ -1 +1,2 @@
|
|||||||
export * from "./application-method"
|
export * from "./application-method"
|
||||||
|
export * from "./promotion-rule"
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
import { PromotionRuleOperatorValues } from "@medusajs/types"
|
||||||
|
import { MedusaError, PromotionRuleOperator, isPresent } from "@medusajs/utils"
|
||||||
|
import { CreatePromotionRuleDTO } from "../../types"
|
||||||
|
|
||||||
|
export function validatePromotionRuleAttributes(
|
||||||
|
promotionRulesData: CreatePromotionRuleDTO[]
|
||||||
|
) {
|
||||||
|
const errors: string[] = []
|
||||||
|
|
||||||
|
for (const promotionRuleData of promotionRulesData) {
|
||||||
|
if (!isPresent(promotionRuleData.attribute)) {
|
||||||
|
errors.push("rules[].attribute is a required field")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isPresent(promotionRuleData.operator)) {
|
||||||
|
errors.push("rules[].operator is a required field")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isPresent(promotionRuleData.operator)) {
|
||||||
|
const allowedOperators: PromotionRuleOperatorValues[] = Object.values(
|
||||||
|
PromotionRuleOperator
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!allowedOperators.includes(promotionRuleData.operator)) {
|
||||||
|
errors.push(
|
||||||
|
`rules[].operator (${
|
||||||
|
promotionRuleData.operator
|
||||||
|
}) is invalid. It should be one of ${allowedOperators.join(", ")}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
errors.push("rules[].operator is a required field")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!errors.length) return
|
||||||
|
|
||||||
|
throw new MedusaError(MedusaError.Types.INVALID_DATA, errors.join(", "))
|
||||||
|
}
|
||||||
@@ -23,7 +23,9 @@
|
|||||||
"paths": {
|
"paths": {
|
||||||
"@models": ["./src/models"],
|
"@models": ["./src/models"],
|
||||||
"@services": ["./src/services"],
|
"@services": ["./src/services"],
|
||||||
"@repositories": ["./src/repositories"]
|
"@repositories": ["./src/repositories"],
|
||||||
|
"@types": ["./src/types"],
|
||||||
|
"@utils": ["./src/utils"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": ["src"],
|
"include": ["src"],
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { BaseFilterable } from "../../dal"
|
import { BaseFilterable } from "../../dal"
|
||||||
import { PromotionDTO } from "./promotion"
|
import { PromotionDTO } from "./promotion"
|
||||||
|
import { CreatePromotionRuleDTO } from "./promotion-rule"
|
||||||
|
|
||||||
export type ApplicationMethodType = "fixed" | "percentage"
|
export type ApplicationMethodType = "fixed" | "percentage"
|
||||||
export type ApplicationMethodTargetType = "order" | "shipping" | "item"
|
export type ApplicationMethodTargetType = "order" | "shipping" | "item"
|
||||||
@@ -16,6 +17,7 @@ export interface CreateApplicationMethodDTO {
|
|||||||
value?: number
|
value?: number
|
||||||
max_quantity?: number
|
max_quantity?: number
|
||||||
promotion?: PromotionDTO | string
|
promotion?: PromotionDTO | string
|
||||||
|
target_rules?: CreatePromotionRuleDTO[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UpdateApplicationMethodDTO {
|
export interface UpdateApplicationMethodDTO {
|
||||||
|
|||||||
@@ -1,2 +1,4 @@
|
|||||||
export * from "./application-method"
|
export * from "./application-method"
|
||||||
export * from "./promotion"
|
export * from "./promotion"
|
||||||
|
export * from "./promotion-rule"
|
||||||
|
export * from "./promotion-rule-value"
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import { BaseFilterable } from "../../dal"
|
||||||
|
import { PromotionRuleDTO } from "./promotion-rule"
|
||||||
|
|
||||||
|
export interface PromotionRuleValueDTO {
|
||||||
|
id: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CreatePromotionRuleValueDTO {
|
||||||
|
value: any
|
||||||
|
promotion_rule: PromotionRuleDTO
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdatePromotionRuleValueDTO {
|
||||||
|
id: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FilterablePromotionRuleValueProps
|
||||||
|
extends BaseFilterable<FilterablePromotionRuleValueProps> {
|
||||||
|
id?: string[]
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import { BaseFilterable } from "../../dal"
|
||||||
|
|
||||||
|
export type PromotionRuleOperatorValues =
|
||||||
|
| "gt"
|
||||||
|
| "lt"
|
||||||
|
| "eq"
|
||||||
|
| "ne"
|
||||||
|
| "in"
|
||||||
|
| "lte"
|
||||||
|
| "gte"
|
||||||
|
|
||||||
|
export interface PromotionRuleDTO {
|
||||||
|
id: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CreatePromotionRuleDTO {
|
||||||
|
description?: string
|
||||||
|
attribute: string
|
||||||
|
operator: PromotionRuleOperatorValues
|
||||||
|
values: string[] | string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdatePromotionRuleDTO {
|
||||||
|
id: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FilterablePromotionRuleProps
|
||||||
|
extends BaseFilterable<FilterablePromotionRuleProps> {
|
||||||
|
id?: string[]
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import { BaseFilterable } from "../../dal"
|
import { BaseFilterable } from "../../dal"
|
||||||
import { CreateApplicationMethodDTO } from "./application-method"
|
import { CreateApplicationMethodDTO } from "./application-method"
|
||||||
|
import { CreatePromotionRuleDTO } from "./promotion-rule"
|
||||||
|
|
||||||
export type PromotionType = "standard" | "buyget"
|
export type PromotionType = "standard" | "buyget"
|
||||||
|
|
||||||
@@ -12,6 +13,7 @@ export interface CreatePromotionDTO {
|
|||||||
type: PromotionType
|
type: PromotionType
|
||||||
is_automatic?: boolean
|
is_automatic?: boolean
|
||||||
application_method?: CreateApplicationMethodDTO
|
application_method?: CreateApplicationMethodDTO
|
||||||
|
rules?: CreatePromotionRuleDTO[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UpdatePromotionDTO {
|
export interface UpdatePromotionDTO {
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
import { isPresent } from "../is-present"
|
||||||
|
|
||||||
|
describe("isPresent", function () {
|
||||||
|
it("should return true or false for different types of data", function () {
|
||||||
|
const expectations = [
|
||||||
|
{
|
||||||
|
input: null,
|
||||||
|
output: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: undefined,
|
||||||
|
output: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "Testing",
|
||||||
|
output: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "",
|
||||||
|
output: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: {},
|
||||||
|
output: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: { test: 1 },
|
||||||
|
output: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: [],
|
||||||
|
output: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: [{ test: 1 }],
|
||||||
|
output: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: new Map([["test", "test"]]),
|
||||||
|
output: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: new Map([]),
|
||||||
|
output: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
input: new Set(["test"]),
|
||||||
|
output: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: new Set([]),
|
||||||
|
output: false,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
expectations.forEach((expectation) => {
|
||||||
|
expect(isPresent(expectation.input)).toEqual(expectation.output)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -8,14 +8,15 @@ export * from "./deep-equal-obj"
|
|||||||
export * from "./errors"
|
export * from "./errors"
|
||||||
export * from "./generate-entity-id"
|
export * from "./generate-entity-id"
|
||||||
export * from "./get-config-file"
|
export * from "./get-config-file"
|
||||||
|
export * from "./get-iso-string-from-date"
|
||||||
export * from "./group-by"
|
export * from "./group-by"
|
||||||
export * from "./handle-postgres-database-error"
|
export * from "./handle-postgres-database-error"
|
||||||
export * from "./is-date"
|
export * from "./is-date"
|
||||||
export * from "./is-defined"
|
export * from "./is-defined"
|
||||||
export * from "./is-email"
|
export * from "./is-email"
|
||||||
export * from "./is-object"
|
export * from "./is-object"
|
||||||
|
export * from "./is-present"
|
||||||
export * from "./is-string"
|
export * from "./is-string"
|
||||||
export * from "./get-iso-string-from-date"
|
|
||||||
export * from "./lower-case-first"
|
export * from "./lower-case-first"
|
||||||
export * from "./map-object-to"
|
export * from "./map-object-to"
|
||||||
export * from "./medusa-container"
|
export * from "./medusa-container"
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { isDefined } from "./is-defined"
|
||||||
|
import { isObject } from "./is-object"
|
||||||
|
import { isString } from "./is-string"
|
||||||
|
|
||||||
|
export function isPresent(value: any): boolean {
|
||||||
|
if (!isDefined(value) || value === null) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isString(value) || Array.isArray(value)) {
|
||||||
|
return value.length > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value instanceof Map || value instanceof Set) {
|
||||||
|
return value.size > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isObject(value)) {
|
||||||
|
return Object.keys(value).length > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
@@ -18,3 +18,13 @@ export enum ApplicationMethodAllocation {
|
|||||||
EACH = "each",
|
EACH = "each",
|
||||||
ACROSS = "across",
|
ACROSS = "across",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum PromotionRuleOperator {
|
||||||
|
GTE = "gte",
|
||||||
|
LTE = "lte",
|
||||||
|
GT = "gt",
|
||||||
|
LT = "lt",
|
||||||
|
EQ = "eq",
|
||||||
|
NE = "ne",
|
||||||
|
IN = "in",
|
||||||
|
}
|
||||||
Reference in new issue
Block a user