refactor: migrate promotion module (#10410)

This commit is contained in:
Harminder Virk
2024-12-11 13:12:39 +05:30
committed by GitHub
parent 777582ac43
commit fad85a9d29
22 changed files with 682 additions and 745 deletions
+6
View File
@@ -0,0 +1,6 @@
---
"@medusajs/promotion": patch
"@medusajs/utils": patch
---
refactor: migrate promotion module
@@ -2326,7 +2326,6 @@ describe("Entity builder", () => {
reference: "1:1", reference: "1:1",
name: "email", name: "email",
entity: "Email", entity: "Email",
nullable: false,
mappedBy: "user", mappedBy: "user",
}, },
created_at: { created_at: {
@@ -2508,7 +2507,7 @@ describe("Entity builder", () => {
reference: "1:1", reference: "1:1",
name: "email", name: "email",
entity: "Email", entity: "Email",
nullable: false, onDelete: undefined,
}, },
created_at: { created_at: {
reference: "scalar", reference: "scalar",
@@ -2595,7 +2594,6 @@ describe("Entity builder", () => {
reference: "1:1", reference: "1:1",
name: "email", name: "email",
entity: "Email", entity: "Email",
nullable: false,
mappedBy: "owner", mappedBy: "owner",
}, },
created_at: { created_at: {
@@ -2687,7 +2685,6 @@ describe("Entity builder", () => {
reference: "1:1", reference: "1:1",
name: "email", name: "email",
entity: "Email", entity: "Email",
nullable: false,
mappedBy: "user", mappedBy: "user",
cascade: ["persist", "soft-remove"], cascade: ["persist", "soft-remove"],
onDelete: "cascade", onDelete: "cascade",
@@ -2851,9 +2848,7 @@ describe("Entity builder", () => {
reference: "1:1", reference: "1:1",
name: "email", name: "email",
entity: "Email", entity: "Email",
nullable: false,
mappedBy: "user", mappedBy: "user",
cascade: ["persist", "soft-remove"],
onDelete: "cascade", onDelete: "cascade",
}, },
created_at: { created_at: {
@@ -3040,7 +3035,6 @@ describe("Entity builder", () => {
reference: "1:1", reference: "1:1",
name: "email", name: "email",
entity: "Email", entity: "Email",
nullable: false,
}, },
email_id: { email_id: {
columnType: "text", columnType: "text",
@@ -3251,7 +3245,6 @@ describe("Entity builder", () => {
reference: "1:1", reference: "1:1",
name: "email", name: "email",
entity: "Email", entity: "Email",
nullable: false,
mappedBy: "owner", mappedBy: "owner",
}, },
email_id: { email_id: {
@@ -3356,7 +3349,6 @@ describe("Entity builder", () => {
reference: "1:1", reference: "1:1",
name: "email", name: "email",
entity: "Email", entity: "Email",
nullable: false,
cascade: ["persist", "soft-remove"], cascade: ["persist", "soft-remove"],
mappedBy: "user", mappedBy: "user",
}, },
@@ -3532,7 +3524,6 @@ describe("Entity builder", () => {
reference: "1:1", reference: "1:1",
name: "email", name: "email",
entity: "Email", entity: "Email",
nullable: false,
cascade: ["persist", "soft-remove"], cascade: ["persist", "soft-remove"],
mappedBy: "user", mappedBy: "user",
}, },
@@ -4493,7 +4484,6 @@ describe("Entity builder", () => {
reference: "1:1", reference: "1:1",
name: "email", name: "email",
entity: "Email", entity: "Email",
nullable: false,
mappedBy: "user", mappedBy: "user",
}, },
created_at: { created_at: {
@@ -4691,7 +4681,6 @@ describe("Entity builder", () => {
reference: "1:1", reference: "1:1",
name: "email", name: "email",
entity: "Email", entity: "Email",
nullable: false,
mappedBy: "user", mappedBy: "user",
}, },
created_at: { created_at: {
@@ -5326,7 +5315,6 @@ describe("Entity builder", () => {
reference: "1:1", reference: "1:1",
name: "email", name: "email",
entity: "Email", entity: "Email",
nullable: false,
mappedBy: "user", mappedBy: "user",
}, },
created_at: { created_at: {
@@ -5526,7 +5514,6 @@ describe("Entity builder", () => {
reference: "1:1", reference: "1:1",
name: "email", name: "email",
entity: "Email", entity: "Email",
nullable: false,
mappedBy: "user", mappedBy: "user",
}, },
created_at: { created_at: {
@@ -5838,7 +5825,6 @@ describe("Entity builder", () => {
entity: "User", entity: "User",
mappedBy: "parent", mappedBy: "parent",
name: "child", name: "child",
nullable: false,
reference: "1:1", reference: "1:1",
}, },
created_at: { created_at: {
@@ -25,6 +25,7 @@ import { HasOneWithForeignKey } from "../../relations/has-one-fk"
import { ManyToMany as DmlManyToMany } from "../../relations/many-to-many" import { ManyToMany as DmlManyToMany } from "../../relations/many-to-many"
import { applyEntityIndexes } from "../mikro-orm/apply-indexes" import { applyEntityIndexes } from "../mikro-orm/apply-indexes"
import { parseEntityName } from "./parse-entity-name" import { parseEntityName } from "./parse-entity-name"
import { BelongsTo } from "../../relations"
type Context = { type Context = {
MANY_TO_MANY_TRACKED_RELATIONS: Record<string, boolean> MANY_TO_MANY_TRACKED_RELATIONS: Record<string, boolean>
@@ -138,24 +139,32 @@ function validateManyToManyRelationshipWithoutMappedBy({
export function defineHasOneRelationship( export function defineHasOneRelationship(
MikroORMEntity: EntityConstructor<any>, MikroORMEntity: EntityConstructor<any>,
relationship: RelationshipMetadata, relationship: RelationshipMetadata,
relatedEntity: DmlEntity<
Record<string, PropertyType<any> | RelationshipType<any>>,
any
>,
{ relatedModelName }: { relatedModelName: string }, { relatedModelName }: { relatedModelName: string },
cascades: EntityCascades<string[]> cascades: EntityCascades<string[]>
) { ) {
const shouldRemoveRelated = !!cascades.delete?.includes(relationship.name) const shouldRemoveRelated = !!cascades.delete?.includes(relationship.name)
const { schema: relationSchema } = relatedEntity.parse()
let mappedBy: string | undefined = camelToSnakeCase(MikroORMEntity.name) let mappedBy: string | undefined = camelToSnakeCase(MikroORMEntity.name)
if ("mappedBy" in relationship) { if ("mappedBy" in relationship) {
mappedBy = relationship.mappedBy mappedBy = relationship.mappedBy
} }
const isOthersideBelongsTo =
!!mappedBy && BelongsTo.isBelongsTo(relationSchema[mappedBy])
const oneToOneOptions = { const oneToOneOptions = {
entity: relatedModelName, entity: relatedModelName,
nullable: relationship.nullable, ...(relationship.nullable ? { nullable: relationship.nullable } : {}),
...(mappedBy ? { mappedBy } : {}), ...(mappedBy ? { mappedBy } : {}),
onDelete: shouldRemoveRelated ? "cascade" : undefined, onDelete: shouldRemoveRelated ? "cascade" : undefined,
} as OneToOneOptions<any, any> } as OneToOneOptions<any, any>
if (shouldRemoveRelated) { if (shouldRemoveRelated && !isOthersideBelongsTo) {
oneToOneOptions.cascade = ["persist", "soft-remove"] as any oneToOneOptions.cascade = ["persist", "soft-remove"] as any
} }
@@ -182,7 +191,7 @@ export function defineHasOneWithFKRelationship(
OneToOne({ OneToOne({
entity: relatedModelName, entity: relatedModelName,
nullable: relationship.nullable, ...(relationship.nullable ? { nullable: relationship.nullable } : {}),
...(mappedBy ? { mappedBy } : {}), ...(mappedBy ? { mappedBy } : {}),
cascade: shouldRemoveRelated cascade: shouldRemoveRelated
? (["persist", "soft-remove"] as any) ? (["persist", "soft-remove"] as any)
@@ -697,6 +706,7 @@ export function defineRelationship(
defineHasOneRelationship( defineHasOneRelationship(
MikroORMEntity, MikroORMEntity,
relationship, relationship,
relatedEntity,
relatedEntityInfo, relatedEntityInfo,
cascades cascades
) )
@@ -16,6 +16,7 @@ export function applyIndexes(
) { ) {
field.indexes.forEach((index) => { field.indexes.forEach((index) => {
const providerEntityIdIndexStatement = createPsqlIndexStatementHelper({ const providerEntityIdIndexStatement = createPsqlIndexStatementHelper({
name: index.name,
tableName, tableName,
columns: [field.fieldName], columns: [field.fieldName],
unique: index.type === "unique", unique: index.type === "unique",
@@ -2,6 +2,7 @@ import { CreateCampaignDTO } from "@medusajs/framework/types"
import { SqlEntityManager } from "@mikro-orm/postgresql" import { SqlEntityManager } from "@mikro-orm/postgresql"
import { Campaign } from "@models" import { Campaign } from "@models"
import { defaultCampaignsData } from "./data" import { defaultCampaignsData } from "./data"
import { toMikroORMEntity } from "@medusajs/framework/utils"
export * from "./data" export * from "./data"
@@ -12,7 +13,7 @@ export async function createCampaigns(
const campaigns: Campaign[] = [] const campaigns: Campaign[] = []
for (let campaignData of campaignsData) { for (let campaignData of campaignsData) {
let campaign = manager.create(Campaign, campaignData) let campaign = manager.create(toMikroORMEntity(Campaign), campaignData)
manager.persist(campaign) manager.persist(campaign)
@@ -3,7 +3,7 @@ import {
IPromotionModuleService, IPromotionModuleService,
PromotionDTO, PromotionDTO,
} from "@medusajs/framework/types" } from "@medusajs/framework/types"
import { isPresent } from "@medusajs/framework/utils" import { isPresent, toMikroORMEntity } from "@medusajs/framework/utils"
import { SqlEntityManager } from "@mikro-orm/postgresql" import { SqlEntityManager } from "@mikro-orm/postgresql"
import { Promotion } from "@models" import { Promotion } from "@models"
import { defaultPromotionsData } from "./data" import { defaultPromotionsData } from "./data"
@@ -17,7 +17,7 @@ export async function createPromotions(
const promotions: Promotion[] = [] const promotions: Promotion[] = []
for (let promotionData of promotionsData) { for (let promotionData of promotionsData) {
let promotion = manager.create(Promotion, promotionData) let promotion = manager.create(toMikroORMEntity(Promotion), promotionData)
manager.persist(promotion) manager.persist(promotion)
await manager.flush() await manager.flush()
@@ -508,7 +508,7 @@ moduleIntegrationTestRunner({
) )
}) })
it("should create a buyget promotion with rules successfully", async () => { it("should create a budget promotion with rules successfully", async () => {
const createdPromotion = await createDefaultPromotion(service, { const createdPromotion = await createDefaultPromotion(service, {
type: PromotionType.BUYGET, type: PromotionType.BUYGET,
application_method: { application_method: {
@@ -638,7 +638,7 @@ moduleIntegrationTestRunner({
application_method: expect.objectContaining({ application_method: expect.objectContaining({
target_type: "order", target_type: "order",
allocation: "across", allocation: "across",
max_quantity: 0, max_quantity: null,
}), }),
}) })
) )
@@ -1,6 +1,6 @@
import * as entities from "./src/models" import * as entities from "./src/models"
import { defineMikroOrmCliConfig, Modules } from "@medusajs/framework/utils" import { defineMikroOrmCliConfig, Modules } from "@medusajs/framework/utils"
export default defineMikroOrmCliConfig(Modules.PRODUCT, { export default defineMikroOrmCliConfig(Modules.PROMOTION, {
entities: Object.values(entities), entities: Object.values(entities),
}) })
@@ -1,5 +1,7 @@
{ {
"namespaces": ["public"], "namespaces": [
"public"
],
"name": "public", "name": "public",
"tables": [ "tables": [
{ {
@@ -96,9 +98,17 @@
"name": "promotion_campaign", "name": "promotion_campaign",
"schema": "public", "schema": "public",
"indexes": [ "indexes": [
{
"keyName": "IDX_promotion_campaign_deleted_at",
"columnNames": [],
"composite": false,
"primary": false,
"unique": false,
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_promotion_campaign_deleted_at\" ON \"promotion_campaign\" (deleted_at) WHERE deleted_at IS NULL"
},
{ {
"keyName": "IDX_promotion_campaign_campaign_identifier_unique", "keyName": "IDX_promotion_campaign_campaign_identifier_unique",
"columnNames": ["campaign_identifier"], "columnNames": [],
"composite": false, "composite": false,
"primary": false, "primary": false,
"unique": false, "unique": false,
@@ -106,7 +116,9 @@
}, },
{ {
"keyName": "promotion_campaign_pkey", "keyName": "promotion_campaign_pkey",
"columnNames": ["id"], "columnNames": [
"id"
],
"composite": false, "composite": false,
"primary": true, "primary": true,
"unique": true "unique": true
@@ -133,18 +145,12 @@
"autoincrement": false, "autoincrement": false,
"primary": false, "primary": false,
"nullable": false, "nullable": false,
"enumItems": ["spend", "usage"], "enumItems": [
"spend",
"usage"
],
"mappedType": "enum" "mappedType": "enum"
}, },
"campaign_id": {
"name": "campaign_id",
"type": "text",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": false,
"mappedType": "text"
},
"currency_code": { "currency_code": {
"name": "currency_code", "name": "currency_code",
"type": "text", "type": "text",
@@ -163,15 +169,6 @@
"nullable": true, "nullable": true,
"mappedType": "decimal" "mappedType": "decimal"
}, },
"raw_limit": {
"name": "raw_limit",
"type": "jsonb",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": true,
"mappedType": "json"
},
"used": { "used": {
"name": "used", "name": "used",
"type": "numeric", "type": "numeric",
@@ -182,6 +179,24 @@
"default": "0", "default": "0",
"mappedType": "decimal" "mappedType": "decimal"
}, },
"campaign_id": {
"name": "campaign_id",
"type": "text",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": false,
"mappedType": "text"
},
"raw_limit": {
"name": "raw_limit",
"type": "jsonb",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": true,
"mappedType": "json"
},
"raw_used": { "raw_used": {
"name": "raw_used", "name": "raw_used",
"type": "jsonb", "type": "jsonb",
@@ -228,22 +243,43 @@
"schema": "public", "schema": "public",
"indexes": [ "indexes": [
{ {
"columnNames": ["type"], "columnNames": [
"composite": false, "campaign_id"
"keyName": "IDX_campaign_budget_type", ],
"primary": false,
"unique": false
},
{
"columnNames": ["campaign_id"],
"composite": false, "composite": false,
"keyName": "promotion_campaign_budget_campaign_id_unique", "keyName": "promotion_campaign_budget_campaign_id_unique",
"primary": false, "primary": false,
"unique": true "unique": true
}, },
{
"keyName": "IDX_campaign_budget_type",
"columnNames": [],
"composite": false,
"primary": false,
"unique": false,
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_campaign_budget_type\" ON \"promotion_campaign_budget\" (type) WHERE deleted_at IS NULL"
},
{
"keyName": "IDX_promotion_campaign_budget_campaign_id",
"columnNames": [],
"composite": false,
"primary": false,
"unique": false,
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_promotion_campaign_budget_campaign_id\" ON \"promotion_campaign_budget\" (campaign_id) WHERE deleted_at IS NULL"
},
{
"keyName": "IDX_promotion_campaign_budget_deleted_at",
"columnNames": [],
"composite": false,
"primary": false,
"unique": false,
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_promotion_campaign_budget_deleted_at\" ON \"promotion_campaign_budget\" (deleted_at) WHERE deleted_at IS NULL"
},
{ {
"keyName": "promotion_campaign_budget_pkey", "keyName": "promotion_campaign_budget_pkey",
"columnNames": ["id"], "columnNames": [
"id"
],
"composite": false, "composite": false,
"primary": true, "primary": true,
"unique": true "unique": true
@@ -253,10 +289,15 @@
"foreignKeys": { "foreignKeys": {
"promotion_campaign_budget_campaign_id_foreign": { "promotion_campaign_budget_campaign_id_foreign": {
"constraintName": "promotion_campaign_budget_campaign_id_foreign", "constraintName": "promotion_campaign_budget_campaign_id_foreign",
"columnNames": ["campaign_id"], "columnNames": [
"campaign_id"
],
"localTableName": "public.promotion_campaign_budget", "localTableName": "public.promotion_campaign_budget",
"referencedColumnNames": ["id"], "referencedColumnNames": [
"id"
],
"referencedTableName": "public.promotion_campaign", "referencedTableName": "public.promotion_campaign",
"deleteRule": "cascade",
"updateRule": "cascade" "updateRule": "cascade"
} }
} }
@@ -281,15 +322,6 @@
"nullable": false, "nullable": false,
"mappedType": "text" "mappedType": "text"
}, },
"campaign_id": {
"name": "campaign_id",
"type": "text",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": true,
"mappedType": "text"
},
"is_automatic": { "is_automatic": {
"name": "is_automatic", "name": "is_automatic",
"type": "boolean", "type": "boolean",
@@ -307,9 +339,21 @@
"autoincrement": false, "autoincrement": false,
"primary": false, "primary": false,
"nullable": false, "nullable": false,
"enumItems": ["standard", "buyget"], "enumItems": [
"standard",
"buyget"
],
"mappedType": "enum" "mappedType": "enum"
}, },
"campaign_id": {
"name": "campaign_id",
"type": "text",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": true,
"mappedType": "text"
},
"created_at": { "created_at": {
"name": "created_at", "name": "created_at",
"type": "timestamptz", "type": "timestamptz",
@@ -346,30 +390,51 @@
"name": "promotion", "name": "promotion",
"schema": "public", "schema": "public",
"indexes": [ "indexes": [
{
"columnNames": ["code"],
"composite": false,
"keyName": "IDX_promotion_code",
"primary": false,
"unique": false
},
{
"columnNames": ["type"],
"composite": false,
"keyName": "IDX_promotion_type",
"primary": false,
"unique": false
},
{ {
"keyName": "IDX_promotion_code_unique", "keyName": "IDX_promotion_code_unique",
"columnNames": ["code"], "columnNames": [],
"composite": false, "composite": false,
"primary": false, "primary": false,
"unique": true "unique": false,
"expression": "CREATE UNIQUE INDEX IF NOT EXISTS \"IDX_promotion_code_unique\" ON \"promotion\" (code) WHERE deleted_at IS NULL"
},
{
"keyName": "IDX_promotion_code",
"columnNames": [],
"composite": false,
"primary": false,
"unique": false,
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_promotion_code\" ON \"promotion\" (code) WHERE deleted_at IS NULL"
},
{
"keyName": "IDX_promotion_type",
"columnNames": [],
"composite": false,
"primary": false,
"unique": false,
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_promotion_type\" ON \"promotion\" (type) WHERE deleted_at IS NULL"
},
{
"keyName": "IDX_promotion_campaign_id",
"columnNames": [],
"composite": false,
"primary": false,
"unique": false,
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_promotion_campaign_id\" ON \"promotion\" (campaign_id) WHERE deleted_at IS NULL"
},
{
"keyName": "IDX_promotion_deleted_at",
"columnNames": [],
"composite": false,
"primary": false,
"unique": false,
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_promotion_deleted_at\" ON \"promotion\" (deleted_at) WHERE deleted_at IS NULL"
}, },
{ {
"keyName": "promotion_pkey", "keyName": "promotion_pkey",
"columnNames": ["id"], "columnNames": [
"id"
],
"composite": false, "composite": false,
"primary": true, "primary": true,
"unique": true "unique": true
@@ -379,9 +444,13 @@
"foreignKeys": { "foreignKeys": {
"promotion_campaign_id_foreign": { "promotion_campaign_id_foreign": {
"constraintName": "promotion_campaign_id_foreign", "constraintName": "promotion_campaign_id_foreign",
"columnNames": ["campaign_id"], "columnNames": [
"campaign_id"
],
"localTableName": "public.promotion", "localTableName": "public.promotion",
"referencedColumnNames": ["id"], "referencedColumnNames": [
"id"
],
"referencedTableName": "public.promotion_campaign", "referencedTableName": "public.promotion_campaign",
"deleteRule": "set null", "deleteRule": "set null",
"updateRule": "cascade" "updateRule": "cascade"
@@ -405,18 +474,9 @@
"unsigned": false, "unsigned": false,
"autoincrement": false, "autoincrement": false,
"primary": false, "primary": false,
"nullable": false, "nullable": true,
"mappedType": "decimal" "mappedType": "decimal"
}, },
"raw_value": {
"name": "raw_value",
"type": "jsonb",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": false,
"mappedType": "json"
},
"currency_code": { "currency_code": {
"name": "currency_code", "name": "currency_code",
"type": "text", "type": "text",
@@ -428,30 +488,30 @@
}, },
"max_quantity": { "max_quantity": {
"name": "max_quantity", "name": "max_quantity",
"type": "numeric", "type": "integer",
"unsigned": false, "unsigned": false,
"autoincrement": false, "autoincrement": false,
"primary": false, "primary": false,
"nullable": true, "nullable": true,
"mappedType": "decimal" "mappedType": "integer"
}, },
"apply_to_quantity": { "apply_to_quantity": {
"name": "apply_to_quantity", "name": "apply_to_quantity",
"type": "numeric", "type": "integer",
"unsigned": false, "unsigned": false,
"autoincrement": false, "autoincrement": false,
"primary": false, "primary": false,
"nullable": true, "nullable": true,
"mappedType": "decimal" "mappedType": "integer"
}, },
"buy_rules_min_quantity": { "buy_rules_min_quantity": {
"name": "buy_rules_min_quantity", "name": "buy_rules_min_quantity",
"type": "numeric", "type": "integer",
"unsigned": false, "unsigned": false,
"autoincrement": false, "autoincrement": false,
"primary": false, "primary": false,
"nullable": true, "nullable": true,
"mappedType": "decimal" "mappedType": "integer"
}, },
"type": { "type": {
"name": "type", "name": "type",
@@ -460,7 +520,10 @@
"autoincrement": false, "autoincrement": false,
"primary": false, "primary": false,
"nullable": false, "nullable": false,
"enumItems": ["fixed", "percentage"], "enumItems": [
"fixed",
"percentage"
],
"mappedType": "enum" "mappedType": "enum"
}, },
"target_type": { "target_type": {
@@ -470,7 +533,11 @@
"autoincrement": false, "autoincrement": false,
"primary": false, "primary": false,
"nullable": false, "nullable": false,
"enumItems": ["order", "shipping_methods", "items"], "enumItems": [
"order",
"shipping_methods",
"items"
],
"mappedType": "enum" "mappedType": "enum"
}, },
"allocation": { "allocation": {
@@ -480,7 +547,10 @@
"autoincrement": false, "autoincrement": false,
"primary": false, "primary": false,
"nullable": true, "nullable": true,
"enumItems": ["each", "across"], "enumItems": [
"each",
"across"
],
"mappedType": "enum" "mappedType": "enum"
}, },
"promotion_id": { "promotion_id": {
@@ -492,6 +562,15 @@
"nullable": false, "nullable": false,
"mappedType": "text" "mappedType": "text"
}, },
"raw_value": {
"name": "raw_value",
"type": "jsonb",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": true,
"mappedType": "json"
},
"created_at": { "created_at": {
"name": "created_at", "name": "created_at",
"type": "timestamptz", "type": "timestamptz",
@@ -529,36 +608,57 @@
"schema": "public", "schema": "public",
"indexes": [ "indexes": [
{ {
"columnNames": ["type"], "columnNames": [
"composite": false, "promotion_id"
"keyName": "IDX_application_method_type", ],
"primary": false,
"unique": false
},
{
"columnNames": ["target_type"],
"composite": false,
"keyName": "IDX_application_method_target_type",
"primary": false,
"unique": false
},
{
"columnNames": ["allocation"],
"composite": false,
"keyName": "IDX_application_method_allocation",
"primary": false,
"unique": false
},
{
"columnNames": ["promotion_id"],
"composite": false, "composite": false,
"keyName": "promotion_application_method_promotion_id_unique", "keyName": "promotion_application_method_promotion_id_unique",
"primary": false, "primary": false,
"unique": true "unique": true
}, },
{
"keyName": "IDX_application_method_type",
"columnNames": [],
"composite": false,
"primary": false,
"unique": false,
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_application_method_type\" ON \"promotion_application_method\" (type) WHERE deleted_at IS NULL"
},
{
"keyName": "IDX_application_method_target_type",
"columnNames": [],
"composite": false,
"primary": false,
"unique": false,
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_application_method_target_type\" ON \"promotion_application_method\" (target_type) WHERE deleted_at IS NULL"
},
{
"keyName": "IDX_application_method_allocation",
"columnNames": [],
"composite": false,
"primary": false,
"unique": false,
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_application_method_allocation\" ON \"promotion_application_method\" (allocation) WHERE deleted_at IS NULL"
},
{
"keyName": "IDX_promotion_application_method_promotion_id",
"columnNames": [],
"composite": false,
"primary": false,
"unique": false,
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_promotion_application_method_promotion_id\" ON \"promotion_application_method\" (promotion_id) WHERE deleted_at IS NULL"
},
{
"keyName": "IDX_promotion_application_method_deleted_at",
"columnNames": [],
"composite": false,
"primary": false,
"unique": false,
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_promotion_application_method_deleted_at\" ON \"promotion_application_method\" (deleted_at) WHERE deleted_at IS NULL"
},
{ {
"keyName": "IDX_promotion_application_method_currency_code", "keyName": "IDX_promotion_application_method_currency_code",
"columnNames": ["currency_code"], "columnNames": [],
"composite": false, "composite": false,
"primary": false, "primary": false,
"unique": false, "unique": false,
@@ -566,7 +666,9 @@
}, },
{ {
"keyName": "promotion_application_method_pkey", "keyName": "promotion_application_method_pkey",
"columnNames": ["id"], "columnNames": [
"id"
],
"composite": false, "composite": false,
"primary": true, "primary": true,
"unique": true "unique": true
@@ -576,9 +678,13 @@
"foreignKeys": { "foreignKeys": {
"promotion_application_method_promotion_id_foreign": { "promotion_application_method_promotion_id_foreign": {
"constraintName": "promotion_application_method_promotion_id_foreign", "constraintName": "promotion_application_method_promotion_id_foreign",
"columnNames": ["promotion_id"], "columnNames": [
"promotion_id"
],
"localTableName": "public.promotion_application_method", "localTableName": "public.promotion_application_method",
"referencedColumnNames": ["id"], "referencedColumnNames": [
"id"
],
"referencedTableName": "public.promotion", "referencedTableName": "public.promotion",
"deleteRule": "cascade", "deleteRule": "cascade",
"updateRule": "cascade" "updateRule": "cascade"
@@ -621,7 +727,15 @@
"autoincrement": false, "autoincrement": false,
"primary": false, "primary": false,
"nullable": false, "nullable": false,
"enumItems": ["gte", "lte", "gt", "lt", "eq", "ne", "in"], "enumItems": [
"gte",
"lte",
"gt",
"lt",
"eq",
"ne",
"in"
],
"mappedType": "enum" "mappedType": "enum"
}, },
"created_at": { "created_at": {
@@ -661,22 +775,34 @@
"schema": "public", "schema": "public",
"indexes": [ "indexes": [
{ {
"columnNames": ["attribute"],
"composite": false,
"keyName": "IDX_promotion_rule_attribute", "keyName": "IDX_promotion_rule_attribute",
"columnNames": [],
"composite": false,
"primary": false, "primary": false,
"unique": false "unique": false,
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_promotion_rule_attribute\" ON \"promotion_rule\" (attribute) WHERE deleted_at IS NULL"
}, },
{ {
"columnNames": ["operator"],
"composite": false,
"keyName": "IDX_promotion_rule_operator", "keyName": "IDX_promotion_rule_operator",
"columnNames": [],
"composite": false,
"primary": false, "primary": false,
"unique": false "unique": false,
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_promotion_rule_operator\" ON \"promotion_rule\" (operator) WHERE deleted_at IS NULL"
},
{
"keyName": "IDX_promotion_rule_deleted_at",
"columnNames": [],
"composite": false,
"primary": false,
"unique": false,
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_promotion_rule_deleted_at\" ON \"promotion_rule\" (deleted_at) WHERE deleted_at IS NULL"
}, },
{ {
"keyName": "promotion_rule_pkey", "keyName": "promotion_rule_pkey",
"columnNames": ["id"], "columnNames": [
"id"
],
"composite": false, "composite": false,
"primary": true, "primary": true,
"unique": true "unique": true
@@ -711,7 +837,10 @@
"indexes": [ "indexes": [
{ {
"keyName": "promotion_promotion_rule_pkey", "keyName": "promotion_promotion_rule_pkey",
"columnNames": ["promotion_id", "promotion_rule_id"], "columnNames": [
"promotion_id",
"promotion_rule_id"
],
"composite": true, "composite": true,
"primary": true, "primary": true,
"unique": true "unique": true
@@ -721,18 +850,26 @@
"foreignKeys": { "foreignKeys": {
"promotion_promotion_rule_promotion_id_foreign": { "promotion_promotion_rule_promotion_id_foreign": {
"constraintName": "promotion_promotion_rule_promotion_id_foreign", "constraintName": "promotion_promotion_rule_promotion_id_foreign",
"columnNames": ["promotion_id"], "columnNames": [
"promotion_id"
],
"localTableName": "public.promotion_promotion_rule", "localTableName": "public.promotion_promotion_rule",
"referencedColumnNames": ["id"], "referencedColumnNames": [
"id"
],
"referencedTableName": "public.promotion", "referencedTableName": "public.promotion",
"deleteRule": "cascade", "deleteRule": "cascade",
"updateRule": "cascade" "updateRule": "cascade"
}, },
"promotion_promotion_rule_promotion_rule_id_foreign": { "promotion_promotion_rule_promotion_rule_id_foreign": {
"constraintName": "promotion_promotion_rule_promotion_rule_id_foreign", "constraintName": "promotion_promotion_rule_promotion_rule_id_foreign",
"columnNames": ["promotion_rule_id"], "columnNames": [
"promotion_rule_id"
],
"localTableName": "public.promotion_promotion_rule", "localTableName": "public.promotion_promotion_rule",
"referencedColumnNames": ["id"], "referencedColumnNames": [
"id"
],
"referencedTableName": "public.promotion_rule", "referencedTableName": "public.promotion_rule",
"deleteRule": "cascade", "deleteRule": "cascade",
"updateRule": "cascade" "updateRule": "cascade"
@@ -765,7 +902,10 @@
"indexes": [ "indexes": [
{ {
"keyName": "application_method_target_rules_pkey", "keyName": "application_method_target_rules_pkey",
"columnNames": ["application_method_id", "promotion_rule_id"], "columnNames": [
"application_method_id",
"promotion_rule_id"
],
"composite": true, "composite": true,
"primary": true, "primary": true,
"unique": true "unique": true
@@ -775,18 +915,26 @@
"foreignKeys": { "foreignKeys": {
"application_method_target_rules_application_method_id_foreign": { "application_method_target_rules_application_method_id_foreign": {
"constraintName": "application_method_target_rules_application_method_id_foreign", "constraintName": "application_method_target_rules_application_method_id_foreign",
"columnNames": ["application_method_id"], "columnNames": [
"application_method_id"
],
"localTableName": "public.application_method_target_rules", "localTableName": "public.application_method_target_rules",
"referencedColumnNames": ["id"], "referencedColumnNames": [
"id"
],
"referencedTableName": "public.promotion_application_method", "referencedTableName": "public.promotion_application_method",
"deleteRule": "cascade", "deleteRule": "cascade",
"updateRule": "cascade" "updateRule": "cascade"
}, },
"application_method_target_rules_promotion_rule_id_foreign": { "application_method_target_rules_promotion_rule_id_foreign": {
"constraintName": "application_method_target_rules_promotion_rule_id_foreign", "constraintName": "application_method_target_rules_promotion_rule_id_foreign",
"columnNames": ["promotion_rule_id"], "columnNames": [
"promotion_rule_id"
],
"localTableName": "public.application_method_target_rules", "localTableName": "public.application_method_target_rules",
"referencedColumnNames": ["id"], "referencedColumnNames": [
"id"
],
"referencedTableName": "public.promotion_rule", "referencedTableName": "public.promotion_rule",
"deleteRule": "cascade", "deleteRule": "cascade",
"updateRule": "cascade" "updateRule": "cascade"
@@ -819,7 +967,10 @@
"indexes": [ "indexes": [
{ {
"keyName": "application_method_buy_rules_pkey", "keyName": "application_method_buy_rules_pkey",
"columnNames": ["application_method_id", "promotion_rule_id"], "columnNames": [
"application_method_id",
"promotion_rule_id"
],
"composite": true, "composite": true,
"primary": true, "primary": true,
"unique": true "unique": true
@@ -829,18 +980,26 @@
"foreignKeys": { "foreignKeys": {
"application_method_buy_rules_application_method_id_foreign": { "application_method_buy_rules_application_method_id_foreign": {
"constraintName": "application_method_buy_rules_application_method_id_foreign", "constraintName": "application_method_buy_rules_application_method_id_foreign",
"columnNames": ["application_method_id"], "columnNames": [
"application_method_id"
],
"localTableName": "public.application_method_buy_rules", "localTableName": "public.application_method_buy_rules",
"referencedColumnNames": ["id"], "referencedColumnNames": [
"id"
],
"referencedTableName": "public.promotion_application_method", "referencedTableName": "public.promotion_application_method",
"deleteRule": "cascade", "deleteRule": "cascade",
"updateRule": "cascade" "updateRule": "cascade"
}, },
"application_method_buy_rules_promotion_rule_id_foreign": { "application_method_buy_rules_promotion_rule_id_foreign": {
"constraintName": "application_method_buy_rules_promotion_rule_id_foreign", "constraintName": "application_method_buy_rules_promotion_rule_id_foreign",
"columnNames": ["promotion_rule_id"], "columnNames": [
"promotion_rule_id"
],
"localTableName": "public.application_method_buy_rules", "localTableName": "public.application_method_buy_rules",
"referencedColumnNames": ["id"], "referencedColumnNames": [
"id"
],
"referencedTableName": "public.promotion_rule", "referencedTableName": "public.promotion_rule",
"deleteRule": "cascade", "deleteRule": "cascade",
"updateRule": "cascade" "updateRule": "cascade"
@@ -858,8 +1017,8 @@
"nullable": false, "nullable": false,
"mappedType": "text" "mappedType": "text"
}, },
"promotion_rule_id": { "value": {
"name": "promotion_rule_id", "name": "value",
"type": "text", "type": "text",
"unsigned": false, "unsigned": false,
"autoincrement": false, "autoincrement": false,
@@ -867,8 +1026,8 @@
"nullable": false, "nullable": false,
"mappedType": "text" "mappedType": "text"
}, },
"value": { "promotion_rule_id": {
"name": "value", "name": "promotion_rule_id",
"type": "text", "type": "text",
"unsigned": false, "unsigned": false,
"autoincrement": false, "autoincrement": false,
@@ -913,15 +1072,26 @@
"schema": "public", "schema": "public",
"indexes": [ "indexes": [
{ {
"columnNames": ["promotion_rule_id"], "keyName": "IDX_promotion_rule_value_promotion_rule_id",
"columnNames": [],
"composite": false, "composite": false,
"keyName": "IDX_promotion_rule_promotion_rule_value_id",
"primary": false, "primary": false,
"unique": false "unique": false,
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_promotion_rule_value_promotion_rule_id\" ON \"promotion_rule_value\" (promotion_rule_id) WHERE deleted_at IS NULL"
},
{
"keyName": "IDX_promotion_rule_value_deleted_at",
"columnNames": [],
"composite": false,
"primary": false,
"unique": false,
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_promotion_rule_value_deleted_at\" ON \"promotion_rule_value\" (deleted_at) WHERE deleted_at IS NULL"
}, },
{ {
"keyName": "promotion_rule_value_pkey", "keyName": "promotion_rule_value_pkey",
"columnNames": ["id"], "columnNames": [
"id"
],
"composite": false, "composite": false,
"primary": true, "primary": true,
"unique": true "unique": true
@@ -931,9 +1101,13 @@
"foreignKeys": { "foreignKeys": {
"promotion_rule_value_promotion_rule_id_foreign": { "promotion_rule_value_promotion_rule_id_foreign": {
"constraintName": "promotion_rule_value_promotion_rule_id_foreign", "constraintName": "promotion_rule_value_promotion_rule_id_foreign",
"columnNames": ["promotion_rule_id"], "columnNames": [
"promotion_rule_id"
],
"localTableName": "public.promotion_rule_value", "localTableName": "public.promotion_rule_value",
"referencedColumnNames": ["id"], "referencedColumnNames": [
"id"
],
"referencedTableName": "public.promotion_rule", "referencedTableName": "public.promotion_rule",
"deleteRule": "cascade", "deleteRule": "cascade",
"updateRule": "cascade" "updateRule": "cascade"
@@ -0,0 +1,131 @@
import { Migration } from "@mikro-orm/migrations"
export class Migration20241211061114 extends Migration {
async up(): Promise<void> {
this.addSql(
'alter table if exists "promotion_campaign_budget" drop constraint if exists "promotion_campaign_budget_campaign_id_foreign";'
)
this.addSql(
'CREATE INDEX IF NOT EXISTS "IDX_promotion_campaign_deleted_at" ON "promotion_campaign" (deleted_at) WHERE deleted_at IS NULL;'
)
this.addSql(
'alter table if exists "promotion_campaign_budget" add constraint "promotion_campaign_budget_campaign_id_foreign" foreign key ("campaign_id") references "promotion_campaign" ("id") on update cascade on delete cascade;'
)
this.addSql(
'CREATE INDEX IF NOT EXISTS "IDX_promotion_campaign_budget_campaign_id" ON "promotion_campaign_budget" (campaign_id) WHERE deleted_at IS NULL;'
)
this.addSql(
'CREATE INDEX IF NOT EXISTS "IDX_promotion_campaign_budget_deleted_at" ON "promotion_campaign_budget" (deleted_at) WHERE deleted_at IS NULL;'
)
this.addSql(
'CREATE INDEX IF NOT EXISTS "IDX_promotion_campaign_id" ON "promotion" (campaign_id) WHERE deleted_at IS NULL;'
)
this.addSql(
'CREATE INDEX IF NOT EXISTS "IDX_promotion_deleted_at" ON "promotion" (deleted_at) WHERE deleted_at IS NULL;'
)
this.addSql(
'alter table if exists "promotion_application_method" alter column "value" type numeric using ("value"::numeric);'
)
this.addSql(
'alter table if exists "promotion_application_method" alter column "value" drop not null;'
)
this.addSql(
'alter table if exists "promotion_application_method" alter column "raw_value" type jsonb using ("raw_value"::jsonb);'
)
this.addSql(
'alter table if exists "promotion_application_method" alter column "raw_value" drop not null;'
)
this.addSql(
'alter table if exists "promotion_application_method" alter column "max_quantity" type integer using ("max_quantity"::integer);'
)
this.addSql(
'alter table if exists "promotion_application_method" alter column "apply_to_quantity" type integer using ("apply_to_quantity"::integer);'
)
this.addSql(
'alter table if exists "promotion_application_method" alter column "buy_rules_min_quantity" type integer using ("buy_rules_min_quantity"::integer);'
)
this.addSql(
'CREATE INDEX IF NOT EXISTS "IDX_promotion_application_method_promotion_id" ON "promotion_application_method" (promotion_id) WHERE deleted_at IS NULL;'
)
this.addSql(
'CREATE INDEX IF NOT EXISTS "IDX_promotion_application_method_deleted_at" ON "promotion_application_method" (deleted_at) WHERE deleted_at IS NULL;'
)
this.addSql(
'CREATE INDEX IF NOT EXISTS "IDX_promotion_rule_deleted_at" ON "promotion_rule" (deleted_at) WHERE deleted_at IS NULL;'
)
this.addSql(
'drop index if exists "IDX_promotion_rule_promotion_rule_value_id";'
)
this.addSql(
'CREATE INDEX IF NOT EXISTS "IDX_promotion_rule_value_promotion_rule_id" ON "promotion_rule_value" (promotion_rule_id) WHERE deleted_at IS NULL;'
)
this.addSql(
'CREATE INDEX IF NOT EXISTS "IDX_promotion_rule_value_deleted_at" ON "promotion_rule_value" (deleted_at) WHERE deleted_at IS NULL;'
)
}
async down(): Promise<void> {
this.addSql(
'alter table if exists "promotion_campaign_budget" drop constraint if exists "promotion_campaign_budget_campaign_id_foreign";'
)
this.addSql('drop index if exists "IDX_promotion_campaign_deleted_at";')
this.addSql(
'drop index if exists "IDX_promotion_campaign_budget_campaign_id";'
)
this.addSql(
'drop index if exists "IDX_promotion_campaign_budget_deleted_at";'
)
this.addSql(
'alter table if exists "promotion_campaign_budget" add constraint "promotion_campaign_budget_campaign_id_foreign" foreign key ("campaign_id") references "promotion_campaign" ("id") on update cascade;'
)
this.addSql('drop index if exists "IDX_promotion_campaign_id";')
this.addSql('drop index if exists "IDX_promotion_deleted_at";')
this.addSql(
'alter table if exists "promotion_application_method" alter column "value" type numeric using ("value"::numeric);'
)
this.addSql(
'alter table if exists "promotion_application_method" alter column "value" set not null;'
)
this.addSql(
'alter table if exists "promotion_application_method" alter column "max_quantity" type numeric using ("max_quantity"::numeric);'
)
this.addSql(
'alter table if exists "promotion_application_method" alter column "apply_to_quantity" type numeric using ("apply_to_quantity"::numeric);'
)
this.addSql(
'alter table if exists "promotion_application_method" alter column "buy_rules_min_quantity" type numeric using ("buy_rules_min_quantity"::numeric);'
)
this.addSql(
'alter table if exists "promotion_application_method" alter column "raw_value" type jsonb using ("raw_value"::jsonb);'
)
this.addSql(
'alter table if exists "promotion_application_method" alter column "raw_value" set not null;'
)
this.addSql(
'drop index if exists "IDX_promotion_application_method_promotion_id";'
)
this.addSql(
'drop index if exists "IDX_promotion_application_method_deleted_at";'
)
this.addSql('drop index if exists "IDX_promotion_rule_deleted_at";')
this.addSql(
'drop index if exists "IDX_promotion_rule_value_promotion_rule_id";'
)
this.addSql('drop index if exists "IDX_promotion_rule_value_deleted_at";')
this.addSql(
'create index if not exists "IDX_promotion_rule_promotion_rule_value_id" on "promotion_rule_value" ("promotion_rule_id");'
)
}
}
@@ -1,126 +1,45 @@
import { import { PromotionUtils, model } from "@medusajs/framework/utils"
ApplicationMethodAllocationValues,
ApplicationMethodTargetTypeValues,
ApplicationMethodTypeValues,
BigNumberRawValue,
} from "@medusajs/framework/types"
import {
BigNumber,
DALUtils,
MikroOrmBigNumberProperty,
PromotionUtils,
createPsqlIndexStatementHelper,
generateEntityId,
} from "@medusajs/framework/utils"
import {
BeforeCreate,
Collection,
Entity,
Enum,
Filter,
Index,
ManyToMany,
OnInit,
OneToOne,
PrimaryKey,
Property,
Rel,
} from "@mikro-orm/core"
import Promotion from "./promotion" import Promotion from "./promotion"
import PromotionRule from "./promotion-rule" import PromotionRule from "./promotion-rule"
const tableName = "promotion_application_method" const ApplicationMethod = model
const CurrencyCodeIndex = createPsqlIndexStatementHelper({ .define(
tableName, { name: "ApplicationMethod", tableName: "promotion_application_method" },
columns: "currency_code", {
where: "deleted_at IS NOT NULL", id: model.id({ prefix: "proappmet" }).primaryKey(),
}) value: model.bigNumber().nullable(),
currency_code: model.text().nullable(),
max_quantity: model.number().nullable(),
apply_to_quantity: model.number().nullable(),
buy_rules_min_quantity: model.number().nullable(),
type: model
.enum(PromotionUtils.ApplicationMethodType)
.index("IDX_application_method_type"),
target_type: model
.enum(PromotionUtils.ApplicationMethodTargetType)
.index("IDX_application_method_target_type"),
allocation: model
.enum(PromotionUtils.ApplicationMethodAllocation)
.index("IDX_application_method_allocation")
.nullable(),
promotion: model.belongsTo(() => Promotion, {
mappedBy: "application_method",
}),
target_rules: model.manyToMany(() => PromotionRule, {
pivotTable: "application_method_target_rules",
mappedBy: "method_target_rules",
}),
buy_rules: model.manyToMany(() => PromotionRule, {
pivotTable: "application_method_buy_rules",
mappedBy: "method_buy_rules",
}),
}
)
.indexes([
{
on: ["currency_code"],
where: "deleted_at IS NOT NULL",
},
])
@Entity({ tableName }) export default ApplicationMethod
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
export default class ApplicationMethod {
@PrimaryKey({ columnType: "text" })
id!: string
@MikroOrmBigNumberProperty()
value: BigNumber | number | null
@Property({ columnType: "jsonb" })
raw_value: BigNumberRawValue | null
@Property({ columnType: "text", nullable: true })
@CurrencyCodeIndex.MikroORMIndex()
currency_code: string | null = null
@Property({ columnType: "numeric", nullable: true, serializer: Number })
max_quantity?: number | null = null
@Property({ columnType: "numeric", nullable: true, serializer: Number })
apply_to_quantity?: number | null = null
@Property({ columnType: "numeric", nullable: true, serializer: Number })
buy_rules_min_quantity?: number | null = null
@Index({ name: "IDX_application_method_type" })
@Enum(() => PromotionUtils.ApplicationMethodType)
type: ApplicationMethodTypeValues
@Index({ name: "IDX_application_method_target_type" })
@Enum(() => PromotionUtils.ApplicationMethodTargetType)
target_type: ApplicationMethodTargetTypeValues
@Index({ name: "IDX_application_method_allocation" })
@Enum({
items: () => PromotionUtils.ApplicationMethodAllocation,
nullable: true,
})
allocation?: ApplicationMethodAllocationValues
@OneToOne({
entity: () => Promotion,
onDelete: "cascade",
})
promotion: Rel<Promotion>
@ManyToMany(() => PromotionRule, "method_target_rules", {
owner: true,
pivotTable: "application_method_target_rules",
cascade: ["soft-remove"] as any,
})
target_rules = new Collection<Rel<PromotionRule>>(this)
@ManyToMany(() => PromotionRule, "method_buy_rules", {
owner: true,
pivotTable: "application_method_buy_rules",
cascade: ["soft-remove"] as any,
})
buy_rules = new Collection<Rel<PromotionRule>>(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 = null
@BeforeCreate()
onCreate() {
this.id = generateEntityId(this.id, "proappmet")
}
@OnInit()
onInit() {
this.id = generateEntityId(this.id, "proappmet")
}
}
@@ -1,93 +1,20 @@
import { import { PromotionUtils, model } from "@medusajs/framework/utils"
BigNumberRawValue,
CampaignBudgetTypeValues,
DAL,
} from "@medusajs/framework/types"
import {
BigNumber,
DALUtils,
MikroOrmBigNumberProperty,
PromotionUtils,
generateEntityId,
} from "@medusajs/framework/utils"
import {
BeforeCreate,
Entity,
Enum,
Filter,
Index,
OnInit,
OneToOne,
OptionalProps,
PrimaryKey,
Property,
Rel,
} from "@mikro-orm/core"
import Campaign from "./campaign" import Campaign from "./campaign"
type OptionalFields = const CampaignBudget = model.define(
| "description" { name: "CampaignBudget", tableName: "promotion_campaign_budget" },
| "limit" {
| "used" id: model.id({ prefix: "probudg" }).primaryKey(),
| DAL.SoftDeletableModelDateColumns type: model
.enum(PromotionUtils.CampaignBudgetType)
@Entity({ tableName: "promotion_campaign_budget" }) .index("IDX_campaign_budget_type"),
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions) currency_code: model.text().nullable(),
export default class CampaignBudget { limit: model.bigNumber().nullable(),
[OptionalProps]?: OptionalFields used: model.bigNumber().default(0),
campaign: model.belongsTo(() => Campaign, {
@PrimaryKey({ columnType: "text" }) mappedBy: "budget",
id!: string }),
@Index({ name: "IDX_campaign_budget_type" })
@Enum(() => PromotionUtils.CampaignBudgetType)
type: CampaignBudgetTypeValues
@OneToOne({
entity: () => Campaign,
})
campaign: Rel<Campaign> | null = null
@Property({ columnType: "text", nullable: true })
currency_code: string | null = null
@MikroOrmBigNumberProperty({ nullable: true })
limit: BigNumber | number | null = null
@Property({ columnType: "jsonb", nullable: true })
raw_limit: BigNumberRawValue | null = null
@MikroOrmBigNumberProperty({ default: 0 })
used: BigNumber | number = 0
@Property({ columnType: "jsonb" })
raw_used: BigNumberRawValue
@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 = null
@BeforeCreate()
onCreate() {
this.id = generateEntityId(this.id, "probudg")
} }
)
@OnInit() export default CampaignBudget
onInit() {
this.id = generateEntityId(this.id, "probudg")
}
}
+31 -104
View File
@@ -1,109 +1,36 @@
import { DAL } from "@medusajs/framework/types" import { model } from "@medusajs/framework/utils"
import {
DALUtils,
Searchable,
createPsqlIndexStatementHelper,
generateEntityId,
} from "@medusajs/framework/utils"
import {
BeforeCreate,
Collection,
Entity,
Filter,
OnInit,
OneToMany,
OneToOne,
OptionalProps,
PrimaryKey,
Property,
Rel,
} from "@mikro-orm/core"
import CampaignBudget from "./campaign-budget" import CampaignBudget from "./campaign-budget"
import Promotion from "./promotion" import Promotion from "./promotion"
type OptionalRelations = "budget" const Campaign = model
type OptionalFields = .define(
| "description" { name: "Campaign", tableName: "promotion_campaign" },
| "starts_at" {
| "ends_at" id: model.id({ prefix: "procamp" }).primaryKey(),
| DAL.SoftDeletableModelDateColumns name: model.text().searchable(),
description: model.text().searchable().nullable(),
const tableName = "promotion_campaign" campaign_identifier: model.text(),
const CampaignUniqueCampaignIdentifier = createPsqlIndexStatementHelper({ starts_at: model.dateTime().nullable(),
tableName, ends_at: model.dateTime().nullable(),
columns: ["campaign_identifier"], budget: model
unique: true, .hasOne<() => typeof CampaignBudget>(() => CampaignBudget, {
where: "deleted_at IS NULL", mappedBy: "campaign",
}) })
.nullable(),
@Entity({ tableName }) promotions: model.hasMany(() => Promotion, {
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions) mappedBy: "campaign",
export default class Campaign { }),
[OptionalProps]?: OptionalFields | OptionalRelations }
)
@PrimaryKey({ columnType: "text" }) .cascades({
id!: string delete: ["budget"],
@Searchable()
@Property({ columnType: "text" })
name: string
@Searchable()
@Property({ columnType: "text", nullable: true })
description: string | null = null
@Property({ columnType: "text" })
@CampaignUniqueCampaignIdentifier.MikroORMIndex()
campaign_identifier: string
@Property({
columnType: "timestamptz",
nullable: true,
}) })
starts_at: Date | null = null .indexes([
{
on: ["campaign_identifier"],
unique: true,
where: "deleted_at IS NULL",
},
])
@Property({ export default Campaign
columnType: "timestamptz",
nullable: true,
})
ends_at: Date | null = null
@OneToOne({
entity: () => CampaignBudget,
mappedBy: (cb) => cb.campaign,
cascade: ["soft-remove"] as any,
nullable: true,
})
budget: Rel<CampaignBudget> | null = null
@OneToMany(() => Promotion, (promotion) => promotion.campaign)
promotions = new Collection<Rel<Promotion>>(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 = null
@BeforeCreate()
onCreate() {
this.id = generateEntityId(this.id, "procamp")
}
@OnInit()
onInit() {
this.id = generateEntityId(this.id, "procamp")
}
}
@@ -1,57 +1,15 @@
import { DALUtils, generateEntityId } from "@medusajs/framework/utils" import { model } from "@medusajs/framework/utils"
import {
BeforeCreate,
Entity,
Filter,
ManyToOne,
OnInit,
PrimaryKey,
Property,
Rel,
} from "@mikro-orm/core"
import PromotionRule from "./promotion-rule" import PromotionRule from "./promotion-rule"
@Entity({ tableName: "promotion_rule_value" }) const PromotionRuleValue = model.define(
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions) { name: "PromotionRuleValue", tableName: "promotion_rule_value" },
export default class PromotionRuleValue { {
@PrimaryKey({ columnType: "text" }) id: model.id({ prefix: "prorulval" }).primaryKey(),
id!: string value: model.text(),
promotion_rule: model.belongsTo(() => PromotionRule, {
@ManyToOne(() => PromotionRule, { mappedBy: "values",
onDelete: "cascade", }),
fieldName: "promotion_rule_id",
index: "IDX_promotion_rule_promotion_rule_value_id",
})
promotion_rule: Rel<PromotionRule>
@Property({ columnType: "text" })
value: string
@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 = null
@BeforeCreate()
onCreate() {
this.id = generateEntityId(this.id, "prorulval")
} }
)
@OnInit() export default PromotionRuleValue
onInit() {
this.id = generateEntityId(this.id, "prorulval")
}
}
@@ -1,96 +1,37 @@
import { DAL, PromotionRuleOperatorValues } from "@medusajs/framework/types" import { PromotionUtils, model } from "@medusajs/framework/utils"
import {
DALUtils,
PromotionUtils,
generateEntityId,
} from "@medusajs/framework/utils"
import {
BeforeCreate,
Cascade,
Collection,
Entity,
Enum,
Filter,
Index,
ManyToMany,
OnInit,
OneToMany,
OptionalProps,
PrimaryKey,
Property,
Rel,
} from "@mikro-orm/core"
import ApplicationMethod from "./application-method" import ApplicationMethod from "./application-method"
import Promotion from "./promotion" import Promotion from "./promotion"
import PromotionRuleValue from "./promotion-rule-value" import PromotionRuleValue from "./promotion-rule-value"
type OptionalFields = "description" | DAL.SoftDeletableModelDateColumns const PromotionRule = model
type OptionalRelations = "values" | "promotions" .define(
{
@Entity({ tableName: "promotion_rule" }) name: "PromotionRule",
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions) tableName: "promotion_rule",
export default class PromotionRule { },
[OptionalProps]?: OptionalFields | OptionalRelations {
id: model.id({ prefix: "prorul" }).primaryKey(),
@PrimaryKey({ columnType: "text" }) description: model.text().nullable(),
id!: string attribute: model.text().index("IDX_promotion_rule_attribute"),
operator: model
@Property({ columnType: "text", nullable: true }) .enum(PromotionUtils.PromotionRuleOperator)
description: string | null = null .index("IDX_promotion_rule_operator"),
values: model.hasMany(() => PromotionRuleValue, {
@Index({ name: "IDX_promotion_rule_attribute" }) mappedBy: "promotion_rule",
@Property({ columnType: "text" }) }),
attribute: string promotions: model.manyToMany(() => Promotion, {
mappedBy: "rules",
@Index({ name: "IDX_promotion_rule_operator" }) }),
@Enum(() => PromotionUtils.PromotionRuleOperator) method_target_rules: model.manyToMany(() => ApplicationMethod, {
operator: PromotionRuleOperatorValues mappedBy: "target_rules",
}),
@OneToMany(() => PromotionRuleValue, (prv) => prv.promotion_rule, { method_buy_rules: model.manyToMany(() => ApplicationMethod, {
cascade: [Cascade.REMOVE], mappedBy: "buy_rules",
}) }),
values = new Collection<Rel<PromotionRuleValue>>(this) }
@ManyToMany(() => Promotion, (promotion) => promotion.rules)
promotions = new Collection<Rel<Promotion>>(this)
@ManyToMany(
() => ApplicationMethod,
(applicationMethod) => applicationMethod.target_rules
) )
method_target_rules = new Collection<Rel<ApplicationMethod>>(this) .cascades({
delete: ["values"],
@ManyToMany(
() => ApplicationMethod,
(applicationMethod) => applicationMethod.buy_rules
)
method_buy_rules = new Collection<Rel<ApplicationMethod>>(this)
@Property({
onCreate: () => new Date(),
columnType: "timestamptz",
defaultRaw: "now()",
}) })
created_at: Date
@Property({ export default PromotionRule
onCreate: () => new Date(),
onUpdate: () => new Date(),
columnType: "timestamptz",
defaultRaw: "now()",
})
updated_at: Date
@Property({ columnType: "timestamptz", nullable: true })
deleted_at: Date | null = null
@BeforeCreate()
onCreate() {
this.id = generateEntityId(this.id, "prorul")
}
@OnInit()
onInit() {
this.id = generateEntityId(this.id, "prorul")
}
}
@@ -1,108 +1,35 @@
import { DAL, PromotionTypeValues } from "@medusajs/framework/types" import { PromotionUtils, model } from "@medusajs/framework/utils"
import {
DALUtils,
PromotionUtils,
Searchable,
generateEntityId,
} from "@medusajs/framework/utils"
import {
BeforeCreate,
Collection,
Entity,
Enum,
Filter,
Index,
ManyToMany,
ManyToOne,
OnInit,
OneToOne,
OptionalProps,
PrimaryKey,
Property,
Rel,
Unique,
} from "@mikro-orm/core"
import ApplicationMethod from "./application-method" import ApplicationMethod from "./application-method"
import Campaign from "./campaign" import Campaign from "./campaign"
import PromotionRule from "./promotion-rule" import PromotionRule from "./promotion-rule"
type OptionalFields = "is_automatic" | DAL.SoftDeletableModelDateColumns const Promotion = model
type OptionalRelations = "application_method" | "campaign" .define("Promotion", {
id: model.id({ prefix: "promo" }).primaryKey(),
@Entity({ tableName: "promotion" }) code: model
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions) .text()
export default class Promotion { .searchable()
[OptionalProps]?: OptionalFields | OptionalRelations .unique("IDX_promotion_code_unique")
.index("IDX_promotion_code"),
@PrimaryKey({ columnType: "text" }) is_automatic: model.boolean().default(false),
id!: string type: model.enum(PromotionUtils.PromotionType).index("IDX_promotion_type"),
campaign: model
@Searchable() .belongsTo(() => Campaign, {
@Property({ columnType: "text" }) mappedBy: "promotions",
@Index({ name: "IDX_promotion_code" }) })
@Unique({ .nullable(),
name: "IDX_promotion_code_unique", application_method: model
properties: ["code"], .hasOne<() => typeof ApplicationMethod>(() => ApplicationMethod, {
mappedBy: "promotion",
})
.nullable(),
rules: model.manyToMany<() => typeof PromotionRule>(() => PromotionRule, {
pivotTable: "promotion_promotion_rule",
mappedBy: "promotions",
}),
}) })
code: string .cascades({
delete: ["application_method"],
@ManyToOne(() => Campaign, {
columnType: "text",
fieldName: "campaign_id",
nullable: true,
mapToPk: true,
}) })
campaign_id: string | null = null
@ManyToOne(() => Campaign, { persist: false }) export default Promotion
campaign: Rel<Campaign> | null
@Property({ columnType: "boolean", default: false })
is_automatic: boolean = false
@Index({ name: "IDX_promotion_type" })
@Enum(() => PromotionUtils.PromotionType)
type: PromotionTypeValues
@OneToOne({
entity: () => ApplicationMethod,
mappedBy: (am) => am.promotion,
cascade: ["soft-remove"] as any,
})
application_method: Rel<ApplicationMethod>
@ManyToMany(() => PromotionRule, "promotions", {
owner: true,
pivotTable: "promotion_promotion_rule",
cascade: ["soft-remove"] as any,
})
rules = new Collection<Rel<PromotionRule>>(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 = null
@BeforeCreate()
onCreate() {
this.id = generateEntityId(this.id, "promo")
}
@OnInit()
onInit() {
this.id = generateEntityId(this.id, "promo")
}
}
@@ -2,6 +2,7 @@ import {
CampaignBudgetTypeValues, CampaignBudgetTypeValues,
Context, Context,
DAL, DAL,
InferEntityType,
InternalModuleDeclaration, InternalModuleDeclaration,
ModuleJoinerConfig, ModuleJoinerConfig,
ModulesSdkTypes, ModulesSdkTypes,
@@ -24,6 +25,7 @@ import {
MedusaError, MedusaError,
MedusaService, MedusaService,
PromotionType, PromotionType,
toMikroORMEntity,
transformPropertiesToBigNumber, transformPropertiesToBigNumber,
} from "@medusajs/framework/utils" } from "@medusajs/framework/utils"
import { import {
@@ -85,12 +87,24 @@ export default class PromotionModuleService
implements PromotionTypes.IPromotionModuleService implements PromotionTypes.IPromotionModuleService
{ {
protected baseRepository_: DAL.RepositoryService protected baseRepository_: DAL.RepositoryService
protected promotionService_: ModulesSdkTypes.IMedusaInternalService<Promotion> protected promotionService_: ModulesSdkTypes.IMedusaInternalService<
protected applicationMethodService_: ModulesSdkTypes.IMedusaInternalService<ApplicationMethod> InferEntityType<typeof Promotion>
protected promotionRuleService_: ModulesSdkTypes.IMedusaInternalService<PromotionRule> >
protected promotionRuleValueService_: ModulesSdkTypes.IMedusaInternalService<PromotionRuleValue> protected applicationMethodService_: ModulesSdkTypes.IMedusaInternalService<
protected campaignService_: ModulesSdkTypes.IMedusaInternalService<Campaign> InferEntityType<typeof ApplicationMethod>
protected campaignBudgetService_: ModulesSdkTypes.IMedusaInternalService<CampaignBudget> >
protected promotionRuleService_: ModulesSdkTypes.IMedusaInternalService<
InferEntityType<typeof PromotionRule>
>
protected promotionRuleValueService_: ModulesSdkTypes.IMedusaInternalService<
InferEntityType<typeof PromotionRuleValue>
>
protected campaignService_: ModulesSdkTypes.IMedusaInternalService<
InferEntityType<typeof Campaign>
>
protected campaignBudgetService_: ModulesSdkTypes.IMedusaInternalService<
InferEntityType<typeof CampaignBudget>
>
constructor( constructor(
{ {
@@ -841,9 +855,10 @@ export default class PromotionModuleService
{ relations: ["budget"] } { relations: ["budget"] }
) )
const existingPromotionsMap = new Map<string, Promotion>( const existingPromotionsMap = new Map<
existingPromotions.map((promotion) => [promotion.id, promotion]) string,
) InferEntityType<typeof Promotion>
>(existingPromotions.map((promotion) => [promotion.id, promotion]))
const promotionsData: UpdatePromotionDTO[] = [] const promotionsData: UpdatePromotionDTO[] = []
const applicationMethodsData: UpdateApplicationMethodDTO[] = [] const applicationMethodsData: UpdateApplicationMethodDTO[] = []
@@ -1099,12 +1114,17 @@ export default class PromotionModuleService
protected async createPromotionRulesAndValues_( protected async createPromotionRulesAndValues_(
rulesData: PromotionTypes.CreatePromotionRuleDTO[], rulesData: PromotionTypes.CreatePromotionRuleDTO[],
relationName: "promotions" | "method_target_rules" | "method_buy_rules", relationName: "promotions" | "method_target_rules" | "method_buy_rules",
relation: Promotion | ApplicationMethod, relation:
| InferEntityType<typeof Promotion>
| InferEntityType<typeof ApplicationMethod>,
@MedusaContext() sharedContext: Context = {} @MedusaContext() sharedContext: Context = {}
): Promise<PromotionRule[]> { ): Promise<InferEntityType<typeof PromotionRule>[]> {
const createdPromotionRules: PromotionRule[] = [] const MikroORMApplicationMethod = toMikroORMEntity(ApplicationMethod)
const createdPromotionRules: InferEntityType<typeof PromotionRule>[] = []
const promotion = const promotion =
relation instanceof ApplicationMethod ? relation.promotion : relation relation instanceof MikroORMApplicationMethod
? relation.promotion
: relation
if (!rulesData.length) { if (!rulesData.length) {
return [] return []
@@ -3,6 +3,7 @@ import {
ApplicationMethodTargetTypeValues, ApplicationMethodTargetTypeValues,
ApplicationMethodTypeValues, ApplicationMethodTypeValues,
BigNumberInput, BigNumberInput,
InferEntityType,
PromotionDTO, PromotionDTO,
} from "@medusajs/framework/types" } from "@medusajs/framework/types"
@@ -14,7 +15,7 @@ export interface CreateApplicationMethodDTO {
allocation?: ApplicationMethodAllocationValues allocation?: ApplicationMethodAllocationValues
value?: BigNumberInput value?: BigNumberInput
currency_code?: string | null currency_code?: string | null
promotion: Promotion | string | PromotionDTO promotion: InferEntityType<typeof Promotion> | string | PromotionDTO
max_quantity?: BigNumberInput | null max_quantity?: BigNumberInput | null
buy_rules_min_quantity?: BigNumberInput | null buy_rules_min_quantity?: BigNumberInput | null
apply_to_quantity?: BigNumberInput | null apply_to_quantity?: BigNumberInput | null
@@ -27,7 +28,7 @@ export interface UpdateApplicationMethodDTO {
allocation?: ApplicationMethodAllocationValues allocation?: ApplicationMethodAllocationValues
value?: BigNumberInput value?: BigNumberInput
currency_code?: string | null currency_code?: string | null
promotion?: Promotion | string | PromotionDTO promotion?: InferEntityType<typeof Promotion> | string | PromotionDTO
max_quantity?: BigNumberInput | null max_quantity?: BigNumberInput | null
buy_rules_min_quantity?: BigNumberInput | null buy_rules_min_quantity?: BigNumberInput | null
apply_to_quantity?: BigNumberInput | null apply_to_quantity?: BigNumberInput | null
@@ -1,6 +1,7 @@
import { import {
BigNumberInput, BigNumberInput,
CampaignBudgetTypeValues, CampaignBudgetTypeValues,
InferEntityType,
} from "@medusajs/framework/types" } from "@medusajs/framework/types"
import { Campaign } from "@models" import { Campaign } from "@models"
@@ -9,7 +10,7 @@ export interface CreateCampaignBudgetDTO {
limit?: BigNumberInput | null limit?: BigNumberInput | null
currency_code?: string | null currency_code?: string | null
used?: BigNumberInput used?: BigNumberInput
campaign?: Campaign | string campaign?: InferEntityType<typeof Campaign> | string
} }
export interface UpdateCampaignBudgetDTO { export interface UpdateCampaignBudgetDTO {
@@ -1,4 +1,4 @@
import { PromotionDTO } from "@medusajs/framework/types" import { InferEntityType, PromotionDTO } from "@medusajs/framework/types"
import { Promotion } from "@models" import { Promotion } from "@models"
export interface CreateCampaignDTO { export interface CreateCampaignDTO {
@@ -7,7 +7,7 @@ export interface CreateCampaignDTO {
campaign_identifier: string campaign_identifier: string
starts_at?: Date | null starts_at?: Date | null
ends_at?: Date | null ends_at?: Date | null
promotions?: (PromotionDTO | Promotion)[] promotions?: (PromotionDTO | InferEntityType<typeof Promotion>)[]
} }
export interface UpdateCampaignDTO { export interface UpdateCampaignDTO {
@@ -17,5 +17,5 @@ export interface UpdateCampaignDTO {
campaign_identifier?: string campaign_identifier?: string
starts_at?: Date | null starts_at?: Date | null
ends_at?: Date | null ends_at?: Date | null
promotions?: (PromotionDTO | Promotion)[] promotions?: (PromotionDTO | InferEntityType<typeof Promotion>)[]
} }
@@ -1,13 +1,19 @@
import { PromotionRuleDTO } from "@medusajs/framework/types" import { InferEntityType, PromotionRuleDTO } from "@medusajs/framework/types"
import { PromotionRule } from "@models" import { PromotionRule } from "@models"
export interface CreatePromotionRuleValueDTO { export interface CreatePromotionRuleValueDTO {
value: any value: any
promotion_rule: string | PromotionRuleDTO | PromotionRule promotion_rule:
| string
| PromotionRuleDTO
| InferEntityType<typeof PromotionRule>
} }
export interface UpdatePromotionRuleValueDTO { export interface UpdatePromotionRuleValueDTO {
id: string id: string
value: any value: any
promotion_rule: string | PromotionRuleDTO | PromotionRule promotion_rule:
| string
| PromotionRuleDTO
| InferEntityType<typeof PromotionRule>
} }
@@ -9,6 +9,7 @@ import {
MedusaError, MedusaError,
PromotionType, PromotionType,
} from "@medusajs/framework/utils" } from "@medusajs/framework/utils"
import { InferEntityType } from "@medusajs/types"
import { Promotion } from "@models" import { Promotion } from "@models"
import { CreateApplicationMethodDTO, UpdateApplicationMethodDTO } from "@types" import { CreateApplicationMethodDTO, UpdateApplicationMethodDTO } from "@types"
@@ -28,7 +29,7 @@ export const allowedAllocationForQuantity: string[] = [
export function validateApplicationMethodAttributes( export function validateApplicationMethodAttributes(
data: UpdateApplicationMethodDTO | CreateApplicationMethodDTO, data: UpdateApplicationMethodDTO | CreateApplicationMethodDTO,
promotion: Promotion promotion: InferEntityType<typeof Promotion>
) { ) {
const applicationMethod = promotion?.application_method || {} const applicationMethod = promotion?.application_method || {}
const buyRulesMinQuantity = const buyRulesMinQuantity =