chore(): Reorganize modules (#7210)
**What** Move all modules to the modules directory
This commit is contained in:
committed by
GitHub
parent
7a351eef09
commit
4eae25e1ef
14
packages/modules/pricing/src/index.ts
Normal file
14
packages/modules/pricing/src/index.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import {
|
||||
moduleDefinition,
|
||||
revertMigration,
|
||||
runMigrations,
|
||||
} from "./module-definition"
|
||||
|
||||
export default moduleDefinition
|
||||
export { revertMigration, runMigrations }
|
||||
|
||||
export * from "./initialize"
|
||||
// TODO: remove export from models and services
|
||||
export * from "./models"
|
||||
export * from "./services"
|
||||
export * from "./types"
|
||||
34
packages/modules/pricing/src/initialize/index.ts
Normal file
34
packages/modules/pricing/src/initialize/index.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import {
|
||||
ExternalModuleDeclaration,
|
||||
InternalModuleDeclaration,
|
||||
MODULE_PACKAGE_NAMES,
|
||||
MedusaModule,
|
||||
Modules,
|
||||
} from "@medusajs/modules-sdk"
|
||||
import { IPricingModuleService, ModulesSdkTypes } from "@medusajs/types"
|
||||
|
||||
import { InitializeModuleInjectableDependencies } from "@types"
|
||||
import { moduleDefinition } from "../module-definition"
|
||||
|
||||
export const initialize = async (
|
||||
options?:
|
||||
| ModulesSdkTypes.ModuleServiceInitializeOptions
|
||||
| ModulesSdkTypes.ModuleServiceInitializeCustomDataLayerOptions
|
||||
| ExternalModuleDeclaration
|
||||
| InternalModuleDeclaration,
|
||||
injectedDependencies?: InitializeModuleInjectableDependencies
|
||||
): Promise<IPricingModuleService> => {
|
||||
const serviceKey = Modules.PRICING
|
||||
|
||||
const loaded = await MedusaModule.bootstrap<IPricingModuleService>({
|
||||
moduleKey: serviceKey,
|
||||
defaultPath: MODULE_PACKAGE_NAMES[Modules.PRICING],
|
||||
declaration: options as
|
||||
| InternalModuleDeclaration
|
||||
| ExternalModuleDeclaration,
|
||||
injectedDependencies,
|
||||
moduleExports: moduleDefinition,
|
||||
})
|
||||
|
||||
return loaded[serviceKey]
|
||||
}
|
||||
56
packages/modules/pricing/src/joiner-config.ts
Normal file
56
packages/modules/pricing/src/joiner-config.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import { Modules } from "@medusajs/modules-sdk"
|
||||
import { ModuleJoinerConfig } from "@medusajs/types"
|
||||
import { MapToConfig } from "@medusajs/utils"
|
||||
import { Price, PriceList, PriceSet, RuleType } from "@models"
|
||||
import schema from "./schema"
|
||||
|
||||
export const LinkableKeys = {
|
||||
price_set_id: PriceSet.name,
|
||||
price_list_id: PriceList.name,
|
||||
price_id: Price.name,
|
||||
rule_type_id: RuleType.name,
|
||||
}
|
||||
|
||||
const entityLinkableKeysMap: MapToConfig = {}
|
||||
Object.entries(LinkableKeys).forEach(([key, value]) => {
|
||||
entityLinkableKeysMap[value] ??= []
|
||||
entityLinkableKeysMap[value].push({
|
||||
mapTo: key,
|
||||
valueFrom: key.split("_").pop()!,
|
||||
})
|
||||
})
|
||||
|
||||
export const entityNameToLinkableKeysMap: MapToConfig = entityLinkableKeysMap
|
||||
|
||||
export const joinerConfig: ModuleJoinerConfig = {
|
||||
serviceName: Modules.PRICING,
|
||||
primaryKeys: ["id"],
|
||||
linkableKeys: LinkableKeys,
|
||||
schema,
|
||||
alias: [
|
||||
{
|
||||
name: ["price_set", "price_sets"],
|
||||
args: {
|
||||
entity: "PriceSet",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["price_list", "price_lists"],
|
||||
args: {
|
||||
methodSuffix: "PriceLists",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["price", "prices"],
|
||||
args: {
|
||||
methodSuffix: "Prices",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["rule_type", "rule_types"],
|
||||
args: {
|
||||
methodSuffix: "RuleTypes",
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
30
packages/modules/pricing/src/loaders/connection.ts
Normal file
30
packages/modules/pricing/src/loaders/connection.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { InternalModuleDeclaration, LoaderOptions } from "@medusajs/modules-sdk"
|
||||
import { ModulesSdkTypes } from "@medusajs/types"
|
||||
import { ModulesSdkUtils } from "@medusajs/utils"
|
||||
import { EntitySchema } from "@mikro-orm/core"
|
||||
import * as PricingModels from "../models"
|
||||
|
||||
export default async (
|
||||
{
|
||||
options,
|
||||
container,
|
||||
logger,
|
||||
}: LoaderOptions<
|
||||
| ModulesSdkTypes.ModuleServiceInitializeOptions
|
||||
| ModulesSdkTypes.ModuleServiceInitializeCustomDataLayerOptions
|
||||
>,
|
||||
moduleDeclaration?: InternalModuleDeclaration
|
||||
): Promise<void> => {
|
||||
const entities = Object.values(PricingModels) as unknown as EntitySchema[]
|
||||
const pathToMigrations = __dirname + "/../migrations"
|
||||
|
||||
await ModulesSdkUtils.mikroOrmConnectionLoader({
|
||||
moduleName: "pricing",
|
||||
entities,
|
||||
container,
|
||||
options,
|
||||
moduleDeclaration,
|
||||
logger,
|
||||
pathToMigrations,
|
||||
})
|
||||
}
|
||||
10
packages/modules/pricing/src/loaders/container.ts
Normal file
10
packages/modules/pricing/src/loaders/container.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { ModulesSdkUtils } from "@medusajs/utils"
|
||||
import * as ModuleModels from "@models"
|
||||
import * as ModuleRepositories from "@repositories"
|
||||
import * as ModuleServices from "@services"
|
||||
|
||||
export default ModulesSdkUtils.moduleContainerLoaderFactory({
|
||||
moduleModels: ModuleModels,
|
||||
moduleRepositories: ModuleRepositories,
|
||||
moduleServices: ModuleServices,
|
||||
})
|
||||
2
packages/modules/pricing/src/loaders/index.ts
Normal file
2
packages/modules/pricing/src/loaders/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from "./connection"
|
||||
export * from "./container"
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,230 @@
|
||||
import { Migration } from "@mikro-orm/migrations"
|
||||
|
||||
export class Migration20230929122253 extends Migration {
|
||||
async up(): Promise<void> {
|
||||
this.addSql(
|
||||
'create table if not exists "money_amount" ("id" text not null, "currency_code" text not null, "amount" numeric not null, "min_quantity" numeric null, "max_quantity" numeric null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "money_amount_pkey" primary key ("id"));'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'create table "price_set" ("id" text not null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "price_set_pkey" primary key ("id"));'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'create table "price" ("id" text not null, "title" text, "price_set_id" text not null, "money_amount_id" text not null, "raw_amount" jsonb not null, "rules_count" integer not null default 0, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "price_pkey" primary key ("id"));'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'alter table "price" add constraint "price_money_amount_id_unique" unique ("money_amount_id");'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'create table "rule_type" ("id" text not null, "name" text not null, "rule_attribute" text not null, "default_priority" integer not null default 0, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "rule_type_pkey" primary key ("id"));'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'create table "price_set_rule_type" ("id" text not null, "price_set_id" text not null, "rule_type_id" text not null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "price_set_rule_type_pkey" primary key ("id"));'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'create table "price_rule" ("id" text not null, "price_set_id" text not null, "rule_type_id" text not null, "value" text not null, "priority" integer not null default 0, "price_id" text not null, "price_list_id" text not null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "price_rule_pkey" primary key ("id"));'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'alter table "price" add constraint "price_price_set_id_foreign" foreign key ("price_set_id") references "price_set" ("id") on update cascade on delete cascade;'
|
||||
)
|
||||
this.addSql(
|
||||
'alter table "price" add constraint "price_money_amount_id_foreign" foreign key ("money_amount_id") references "money_amount" ("id") on update cascade on delete cascade;'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'alter table "price_set_rule_type" add constraint "price_set_rule_type_price_set_id_foreign" foreign key ("price_set_id") references "price_set" ("id") on update cascade on delete cascade;'
|
||||
)
|
||||
this.addSql(
|
||||
'alter table "price_set_rule_type" add constraint "price_set_rule_type_rule_type_id_foreign" foreign key ("rule_type_id") references "rule_type" ("id") on update cascade;'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'alter table "price_rule" add constraint "price_rule_price_set_id_foreign" foreign key ("price_set_id") references "price_set" ("id") on update cascade on delete cascade;'
|
||||
)
|
||||
this.addSql(
|
||||
'alter table "price_rule" add constraint "price_rule_rule_type_id_foreign" foreign key ("rule_type_id") references "rule_type" ("id") on update cascade;'
|
||||
)
|
||||
this.addSql(
|
||||
'alter table "price_rule" add constraint "price_rule_price_id_foreign" foreign key ("price_id") references "price" ("id") on update cascade on delete cascade;'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'create table if not exists "price_list" ("id" text not null, "status" text check ("status" in (\'active\', \'draft\')) not null default \'draft\', "starts_at" timestamptz null, "ends_at" timestamptz null, "rules_count" integer not null default 0, constraint "price_list_pkey" primary key ("id"));'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'create table "price_list_rule" ("id" text not null, "rule_type_id" text not null, "price_list_id" text not null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "price_list_rule_pkey" primary key ("id"));'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'alter table "price_list_rule" add constraint "price_list_rule_rule_type_id_foreign" foreign key ("rule_type_id") references "rule_type" ("id") on update cascade;'
|
||||
)
|
||||
this.addSql(
|
||||
'alter table "price_list_rule" add constraint "price_list_rule_price_list_id_foreign" foreign key ("price_list_id") references "price_list" ("id") on update cascade;'
|
||||
)
|
||||
|
||||
this.addSql('alter table "price" add column "price_list_id" text null;')
|
||||
|
||||
this.addSql('alter table "price_rule" drop column "price_list_id";')
|
||||
|
||||
this.addSql(
|
||||
'create table "price_list_rule_value" ("id" text not null, "value" text not null, "price_list_rule_id" text not null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "price_list_rule_value_pkey" primary key ("id"));'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'alter table "price_list_rule_value" add constraint "price_list_rule_value_price_list_rule_id_foreign" foreign key ("price_list_rule_id") references "price_list_rule" ("id") on update cascade on delete cascade;'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
`ALTER TABLE price_list
|
||||
ADD COLUMN IF NOT EXISTS rules_count integer not null default 0`
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'alter table "price_list" add column if not exists "title" text, add column if not exists "name" text, add column if not exists "description" text not null, add column if not exists "type" text check ("type" in (\'sale\', \'override\')) not null default \'sale\', add column if not exists "created_at" timestamptz not null default now(), add column if not exists "updated_at" timestamptz not null default now(), add column if not exists "deleted_at" timestamptz null;'
|
||||
)
|
||||
|
||||
this.addSql(`
|
||||
UPDATE "price_list"
|
||||
SET title = name
|
||||
`)
|
||||
|
||||
this.addSql(`alter table "price_list" alter column "title" set not null `)
|
||||
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_money_amount_currency_code" ON "money_amount" (currency_code) WHERE deleted_at IS NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_money_amount_deleted_at" ON "money_amount" (deleted_at) WHERE deleted_at IS NOT NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_price_list_deleted_at" ON "price_list" (deleted_at) WHERE deleted_at IS NOT NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_price_set_deleted_at" ON "price_set" (deleted_at) WHERE deleted_at IS NOT NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_price_price_set_id" ON "price" (price_set_id) WHERE deleted_at IS NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_price_money_amount_id" ON "price" (money_amount_id) WHERE deleted_at IS NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_price_price_list_id" ON "price" (price_list_id) WHERE deleted_at IS NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_price_deleted_at" ON "price" (deleted_at) WHERE deleted_at IS NOT NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_rule_type_rule_attribute" ON "rule_type" (rule_attribute) WHERE deleted_at IS NOT NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_rule_type_deleted_at" ON "rule_type" (deleted_at) WHERE deleted_at IS NOT NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_price_set_rule_type_price_set_id" ON "price_set_rule_type" (price_set_id) WHERE deleted_at IS NOT NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_price_set_rule_type_rule_type_id" ON "price_set_rule_type" (rule_type_id) WHERE deleted_at IS NOT NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_price_set_rule_type_deleted_at" ON "price_set_rule_type" (deleted_at) WHERE deleted_at IS NOT NULL;'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_price_rule_price_set_id" ON "price_rule" (price_set_id) WHERE deleted_at IS NOT NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_price_rule_rule_type_id" ON "price_rule" (rule_type_id) WHERE deleted_at IS NOT NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE UNIQUE INDEX IF NOT EXISTS "IDX_price_rule_price_id_unique" ON "price_rule" (price_id) WHERE deleted_at IS NOT NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_price_rule_deleted_at" ON "price_rule" (deleted_at) WHERE deleted_at IS NOT NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE UNIQUE INDEX IF NOT EXISTS "IDX_price_list_rule_rule_type_id_unique" ON "price_list_rule" (rule_type_id) WHERE deleted_at IS NOT NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_price_list_rule_price_list_id" ON "price_list_rule" (price_list_id) WHERE deleted_at IS NOT NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_price_list_rule_deleted_at" ON "price_list_rule" (deleted_at) WHERE deleted_at IS NOT NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_price_list_rule_value_price_list_rule_id" ON "price_list_rule_value" (price_list_rule_id) WHERE deleted_at IS NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_price_list_rule_value_deleted_at" ON "price_list_rule_value" (deleted_at) WHERE deleted_at IS NOT NULL;'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'alter table if exists "price_list" drop column if exists "name";'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'alter table if exists "price" add constraint "price_price_list_id_foreign" foreign key ("price_list_id") references "price_list" ("id") on update cascade on delete cascade;'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'alter table if exists "price_rule" drop constraint if exists "price_rule_rule_type_id_foreign";'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'alter table if exists "price_rule" add constraint "price_rule_rule_type_id_foreign" foreign key ("rule_type_id") references "rule_type" ("id") on update cascade on delete cascade;'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'alter table if exists "price_rule" drop constraint if exists "price_rule_rule_type_id_foreign";'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'alter table if exists "price_list_rule" drop constraint if exists "price_list_rule_price_list_id_foreign";'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'alter table if exists "price_rule" add constraint "price_rule_rule_type_id_foreign" foreign key ("rule_type_id") references "rule_type" ("id") on update cascade;'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'alter table if exists "price_list_rule" add constraint "price_list_rule_price_list_id_foreign" foreign key ("price_list_id") references "price_list" ("id") on update cascade on delete cascade;'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'alter table if exists "price_set_rule_type" drop constraint if exists "price_set_rule_type_rule_type_id_foreign";'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'alter table if exists "price_set_rule_type" add constraint "price_set_rule_type_rule_type_id_foreign" foreign key ("rule_type_id") references "rule_type" ("id") on update cascade on delete cascade;'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'alter table if exists "price" drop constraint if exists "price_money_amount_id_foreign";'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'alter table if exists "price" add column if not exists "amount" numeric not null, add column "min_quantity" numeric null, add column "max_quantity" numeric null;'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'alter table if exists "price" drop constraint if exists "price_money_amount_id_unique";'
|
||||
)
|
||||
|
||||
this.addSql('drop index if exists "IDX_price_money_amount_id";')
|
||||
|
||||
this.addSql(
|
||||
'alter table if exists "price" rename column "money_amount_id" to "currency_code";'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_price_currency_code" ON "price" (currency_code) WHERE deleted_at IS NULL;'
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import { Migration } from '@mikro-orm/migrations';
|
||||
|
||||
export class Migration20240322094407 extends Migration {
|
||||
|
||||
async up(): Promise<void> {
|
||||
this.addSql('drop table if exists "money_amount" cascade;');
|
||||
}
|
||||
|
||||
async down(): Promise<void> {
|
||||
this.addSql('create table if not exists "money_amount" ("id" text not null, "currency_code" text not null, "amount" numeric not null, "min_quantity" numeric null, "max_quantity" numeric null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "money_amount_pkey" primary key ("id"));');
|
||||
this.addSql('CREATE INDEX IF NOT EXISTS "IDX_money_amount_currency_code" ON "money_amount" (currency_code) WHERE deleted_at IS NULL;');
|
||||
this.addSql('CREATE INDEX IF NOT EXISTS "IDX_money_amount_deleted_at" ON "money_amount" (deleted_at) WHERE deleted_at IS NOT NULL;');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import { Migration } from "@mikro-orm/migrations"
|
||||
|
||||
export class Migration20240322113359 extends Migration {
|
||||
async up(): Promise<void> {
|
||||
this.addSql(
|
||||
'alter table if exists "price_rule" drop constraint if exists "price_rule_price_id_foreign";'
|
||||
)
|
||||
|
||||
this.addSql('drop index if exists "IDX_price_rule_price_id_unique";')
|
||||
this.addSql(
|
||||
'alter table if exists "price_rule" add constraint "price_rule_price_id_foreign" foreign key ("price_id") references "price" ("id") on update cascade on delete cascade;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE UNIQUE INDEX IF NOT EXISTS "IDX_price_rule_price_id_unique" ON "price_rule" (price_id) WHERE deleted_at IS NULL;'
|
||||
)
|
||||
}
|
||||
|
||||
async down(): Promise<void> {
|
||||
this.addSql(
|
||||
'alter table if exists "price_rule" drop constraint if exists "price_rule_price_id_foreign";'
|
||||
)
|
||||
|
||||
this.addSql('drop index if exists "IDX_price_rule_price_id_unique";')
|
||||
this.addSql(
|
||||
'alter table if exists "price_rule" add constraint "price_rule_price_id_foreign" foreign key ("price_id") references "price" ("id") on update cascade on delete cascade;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE UNIQUE INDEX IF NOT EXISTS "IDX_price_rule_price_id_unique" ON "price_rule" (price_id) WHERE deleted_at IS NULL;'
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import { Migration } from "@mikro-orm/migrations"
|
||||
|
||||
export class Migration20240322120125 extends Migration {
|
||||
async up(): Promise<void> {
|
||||
this.addSql('drop index if exists "IDX_price_rule_price_id_unique";')
|
||||
this.addSql(
|
||||
'CREATE UNIQUE INDEX IF NOT EXISTS "IDX_price_rule_price_id_rule_type_id_unique" ON "price_rule" (price_id, rule_type_id) WHERE deleted_at IS NULL;'
|
||||
)
|
||||
}
|
||||
|
||||
async down(): Promise<void> {
|
||||
this.addSql(
|
||||
'drop index if exists "IDX_price_rule_price_id_rule_type_id_unique";'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE UNIQUE INDEX IF NOT EXISTS "IDX_price_rule_price_id_unique" ON "price_rule" (price_id) WHERE deleted_at IS NULL;'
|
||||
)
|
||||
}
|
||||
}
|
||||
8
packages/modules/pricing/src/models/index.ts
Normal file
8
packages/modules/pricing/src/models/index.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export { default as Price } from "./price"
|
||||
export { default as PriceList } from "./price-list"
|
||||
export { default as PriceListRule } from "./price-list-rule"
|
||||
export { default as PriceListRuleValue } from "./price-list-rule-value"
|
||||
export { default as PriceRule } from "./price-rule"
|
||||
export { default as PriceSet } from "./price-set"
|
||||
export { default as PriceSetRuleType } from "./price-set-rule-type"
|
||||
export { default as RuleType } from "./rule-type"
|
||||
87
packages/modules/pricing/src/models/price-list-rule-value.ts
Normal file
87
packages/modules/pricing/src/models/price-list-rule-value.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
import { DAL } from "@medusajs/types"
|
||||
import {
|
||||
createPsqlIndexStatementHelper,
|
||||
DALUtils,
|
||||
generateEntityId,
|
||||
} from "@medusajs/utils"
|
||||
import {
|
||||
BeforeCreate,
|
||||
Entity,
|
||||
Filter,
|
||||
ManyToOne,
|
||||
OnInit,
|
||||
OptionalProps,
|
||||
PrimaryKey,
|
||||
Property,
|
||||
} from "@mikro-orm/core"
|
||||
import PriceListRule from "./price-list-rule"
|
||||
|
||||
type OptionalFields = DAL.SoftDeletableEntityDateColumns
|
||||
|
||||
const tableName = "price_list_rule_value"
|
||||
const PriceListRuleValueDeletedAtIndex = createPsqlIndexStatementHelper({
|
||||
tableName: tableName,
|
||||
columns: "deleted_at",
|
||||
where: "deleted_at IS NOT NULL",
|
||||
})
|
||||
|
||||
const PriceListPriceListRuleIdIndex = createPsqlIndexStatementHelper({
|
||||
tableName: tableName,
|
||||
columns: "price_list_rule_id",
|
||||
where: "deleted_at IS NULL",
|
||||
})
|
||||
|
||||
@Entity({ tableName })
|
||||
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
||||
export default class PriceListRuleValue {
|
||||
[OptionalProps]?: OptionalFields
|
||||
|
||||
@PrimaryKey({ columnType: "text" })
|
||||
id!: string
|
||||
|
||||
@PriceListPriceListRuleIdIndex.MikroORMIndex()
|
||||
@ManyToOne(() => PriceListRule, {
|
||||
columnType: "text",
|
||||
mapToPk: true,
|
||||
fieldName: "price_list_rule_id",
|
||||
onDelete: "cascade",
|
||||
})
|
||||
price_list_rule_id: string
|
||||
|
||||
@ManyToOne(() => PriceListRule, { persist: false })
|
||||
price_list_rule: PriceListRule
|
||||
|
||||
@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
|
||||
|
||||
@PriceListRuleValueDeletedAtIndex.MikroORMIndex()
|
||||
@Property({ columnType: "timestamptz", nullable: true })
|
||||
deleted_at: Date | null = null
|
||||
|
||||
@BeforeCreate()
|
||||
onCreate() {
|
||||
this.id = generateEntityId(this.id, "plrv")
|
||||
this.price_list_rule_id ??= this.price_list_rule?.id
|
||||
}
|
||||
|
||||
@OnInit()
|
||||
onInit() {
|
||||
this.id = generateEntityId(this.id, "plrv")
|
||||
this.price_list_rule_id ??= this.price_list_rule?.id
|
||||
}
|
||||
}
|
||||
114
packages/modules/pricing/src/models/price-list-rule.ts
Normal file
114
packages/modules/pricing/src/models/price-list-rule.ts
Normal file
@@ -0,0 +1,114 @@
|
||||
import { DAL } from "@medusajs/types"
|
||||
import {
|
||||
createPsqlIndexStatementHelper,
|
||||
DALUtils,
|
||||
generateEntityId,
|
||||
} from "@medusajs/utils"
|
||||
import {
|
||||
BeforeCreate,
|
||||
Cascade,
|
||||
Collection,
|
||||
Entity,
|
||||
Filter,
|
||||
ManyToOne,
|
||||
OneToMany,
|
||||
OnInit,
|
||||
OptionalProps,
|
||||
PrimaryKey,
|
||||
Property,
|
||||
} from "@mikro-orm/core"
|
||||
import PriceList from "./price-list"
|
||||
import PriceListRuleValue from "./price-list-rule-value"
|
||||
import RuleType from "./rule-type"
|
||||
|
||||
type OptionalFields = DAL.SoftDeletableEntityDateColumns
|
||||
|
||||
const tableName = "price_list_rule"
|
||||
const PriceListRuleDeletedAtIndex = createPsqlIndexStatementHelper({
|
||||
tableName: tableName,
|
||||
columns: "deleted_at",
|
||||
where: "deleted_at IS NOT NULL",
|
||||
})
|
||||
|
||||
const PriceListRuleRuleTypeIdIndex = createPsqlIndexStatementHelper({
|
||||
tableName: tableName,
|
||||
columns: "rule_type_id",
|
||||
where: "deleted_at IS NULL",
|
||||
unique: true,
|
||||
})
|
||||
|
||||
const PriceListRulePriceListIdIndex = createPsqlIndexStatementHelper({
|
||||
tableName: tableName,
|
||||
columns: "price_list_id",
|
||||
where: "deleted_at IS NULL",
|
||||
})
|
||||
|
||||
@Entity({ tableName })
|
||||
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
||||
export default class PriceListRule {
|
||||
[OptionalProps]: OptionalFields
|
||||
|
||||
@PrimaryKey({ columnType: "text" })
|
||||
id!: string
|
||||
|
||||
@PriceListRuleRuleTypeIdIndex.MikroORMIndex()
|
||||
@ManyToOne(() => RuleType, {
|
||||
columnType: "text",
|
||||
mapToPk: true,
|
||||
fieldName: "rule_type_id",
|
||||
})
|
||||
rule_type_id: string
|
||||
|
||||
@ManyToOne(() => RuleType, { persist: false })
|
||||
rule_type: RuleType
|
||||
|
||||
@OneToMany(() => PriceListRuleValue, (plrv) => plrv.price_list_rule, {
|
||||
cascade: [Cascade.PERSIST, "soft-remove" as Cascade],
|
||||
})
|
||||
price_list_rule_values = new Collection<PriceListRuleValue>(this)
|
||||
|
||||
@PriceListRulePriceListIdIndex.MikroORMIndex()
|
||||
@ManyToOne(() => PriceList, {
|
||||
columnType: "text",
|
||||
mapToPk: true,
|
||||
fieldName: "price_list_id",
|
||||
onDelete: "cascade",
|
||||
})
|
||||
price_list_id: string
|
||||
|
||||
@ManyToOne(() => PriceList, { persist: false })
|
||||
price_list: PriceList
|
||||
|
||||
@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
|
||||
|
||||
@PriceListRuleDeletedAtIndex.MikroORMIndex()
|
||||
@Property({ columnType: "timestamptz", nullable: true })
|
||||
deleted_at: Date | null = null
|
||||
|
||||
@BeforeCreate()
|
||||
beforeCreate() {
|
||||
this.id = generateEntityId(this.id, "plrule")
|
||||
this.price_list_id ??= this.price_list?.id!
|
||||
this.rule_type_id ??= this.rule_type?.id!
|
||||
}
|
||||
|
||||
@OnInit()
|
||||
onInit() {
|
||||
this.id = generateEntityId(this.id, "plrule")
|
||||
this.price_list_id ??= this.price_list?.id!
|
||||
this.rule_type_id ??= this.rule_type?.id!
|
||||
}
|
||||
}
|
||||
123
packages/modules/pricing/src/models/price-list.ts
Normal file
123
packages/modules/pricing/src/models/price-list.ts
Normal file
@@ -0,0 +1,123 @@
|
||||
import { DAL } from "@medusajs/types"
|
||||
import {
|
||||
createPsqlIndexStatementHelper,
|
||||
DALUtils,
|
||||
generateEntityId,
|
||||
PriceListStatus,
|
||||
PriceListType,
|
||||
Searchable,
|
||||
} from "@medusajs/utils"
|
||||
import {
|
||||
BeforeCreate,
|
||||
Cascade,
|
||||
Collection,
|
||||
Entity,
|
||||
Enum,
|
||||
Filter,
|
||||
ManyToMany,
|
||||
OneToMany,
|
||||
OnInit,
|
||||
OptionalProps,
|
||||
PrimaryKey,
|
||||
Property,
|
||||
} from "@mikro-orm/core"
|
||||
import Price from "./price"
|
||||
import PriceListRule from "./price-list-rule"
|
||||
import RuleType from "./rule-type"
|
||||
|
||||
type OptionalFields =
|
||||
| "starts_at"
|
||||
| "ends_at"
|
||||
| DAL.SoftDeletableEntityDateColumns
|
||||
|
||||
const tableName = "price_list"
|
||||
const PriceListDeletedAtIndex = createPsqlIndexStatementHelper({
|
||||
tableName: tableName,
|
||||
columns: "deleted_at",
|
||||
where: "deleted_at IS NOT NULL",
|
||||
})
|
||||
|
||||
export const PriceListIdPrefix = "plist"
|
||||
|
||||
@Entity({ tableName })
|
||||
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
||||
export default class PriceList {
|
||||
[OptionalProps]: OptionalFields
|
||||
|
||||
@PrimaryKey({ columnType: "text" })
|
||||
id!: string
|
||||
|
||||
@Searchable()
|
||||
@Property({ columnType: "text" })
|
||||
title: string
|
||||
|
||||
@Searchable()
|
||||
@Property({ columnType: "text" })
|
||||
description: string
|
||||
|
||||
@Enum({ items: () => PriceListStatus, default: PriceListStatus.DRAFT })
|
||||
status: PriceListStatus
|
||||
|
||||
@Enum({ items: () => PriceListType, default: PriceListType.SALE })
|
||||
type: PriceListType
|
||||
|
||||
@Property({
|
||||
columnType: "timestamptz",
|
||||
nullable: true,
|
||||
})
|
||||
starts_at: Date | null = null
|
||||
|
||||
@Property({
|
||||
columnType: "timestamptz",
|
||||
nullable: true,
|
||||
})
|
||||
ends_at: Date | null = null
|
||||
|
||||
@OneToMany(() => Price, (price) => price.price_list, {
|
||||
cascade: [Cascade.PERSIST, "soft-remove" as Cascade],
|
||||
})
|
||||
prices = new Collection<Price>(this)
|
||||
|
||||
@OneToMany(() => PriceListRule, (pr) => pr.price_list, {
|
||||
cascade: [Cascade.PERSIST, "soft-remove" as Cascade],
|
||||
})
|
||||
price_list_rules = new Collection<PriceListRule>(this)
|
||||
|
||||
@ManyToMany({
|
||||
entity: () => RuleType,
|
||||
pivotEntity: () => PriceListRule,
|
||||
})
|
||||
rule_types = new Collection<RuleType>(this)
|
||||
|
||||
@Property({ columnType: "integer", default: 0 })
|
||||
rules_count: number = 0
|
||||
|
||||
@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
|
||||
|
||||
@PriceListDeletedAtIndex.MikroORMIndex()
|
||||
@Property({ columnType: "timestamptz", nullable: true })
|
||||
deleted_at: Date | null = null
|
||||
|
||||
@BeforeCreate()
|
||||
onCreate() {
|
||||
this.id = generateEntityId(this.id, PriceListIdPrefix)
|
||||
}
|
||||
|
||||
@OnInit()
|
||||
onInit() {
|
||||
this.id = generateEntityId(this.id, PriceListIdPrefix)
|
||||
}
|
||||
}
|
||||
132
packages/modules/pricing/src/models/price-rule.ts
Normal file
132
packages/modules/pricing/src/models/price-rule.ts
Normal file
@@ -0,0 +1,132 @@
|
||||
import { DAL } from "@medusajs/types"
|
||||
import {
|
||||
createPsqlIndexStatementHelper,
|
||||
DALUtils,
|
||||
generateEntityId,
|
||||
} from "@medusajs/utils"
|
||||
import {
|
||||
BeforeCreate,
|
||||
Entity,
|
||||
Filter,
|
||||
ManyToOne,
|
||||
OnInit,
|
||||
OptionalProps,
|
||||
PrimaryKey,
|
||||
Property,
|
||||
} from "@mikro-orm/core"
|
||||
import Price from "./price"
|
||||
import PriceSet from "./price-set"
|
||||
import RuleType from "./rule-type"
|
||||
|
||||
type OptionalFields = DAL.SoftDeletableEntityDateColumns
|
||||
|
||||
const tableName = "price_rule"
|
||||
const PriceRuleDeletedAtIndex = createPsqlIndexStatementHelper({
|
||||
tableName: tableName,
|
||||
columns: "deleted_at",
|
||||
where: "deleted_at IS NOT NULL",
|
||||
})
|
||||
|
||||
const PriceRulePriceSetIdIndex = createPsqlIndexStatementHelper({
|
||||
tableName: tableName,
|
||||
columns: "price_set_id",
|
||||
where: "deleted_at IS NULL",
|
||||
})
|
||||
|
||||
const PriceRuleRuleTypeIdIndex = createPsqlIndexStatementHelper({
|
||||
tableName: tableName,
|
||||
columns: "rule_type_id",
|
||||
where: "deleted_at IS NULL",
|
||||
})
|
||||
|
||||
const PriceRulePriceIdIndex = createPsqlIndexStatementHelper({
|
||||
tableName: tableName,
|
||||
columns: ["price_id", "rule_type_id"],
|
||||
where: "deleted_at IS NULL",
|
||||
unique: true,
|
||||
})
|
||||
|
||||
@Entity({ tableName })
|
||||
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
||||
export default class PriceRule {
|
||||
[OptionalProps]?: OptionalFields
|
||||
|
||||
@PrimaryKey({ columnType: "text" })
|
||||
id!: string
|
||||
|
||||
@PriceRulePriceSetIdIndex.MikroORMIndex()
|
||||
@ManyToOne(() => PriceSet, {
|
||||
columnType: "text",
|
||||
mapToPk: true,
|
||||
fieldName: "price_set_id",
|
||||
onDelete: "cascade",
|
||||
})
|
||||
price_set_id: string
|
||||
|
||||
@ManyToOne(() => PriceSet, { persist: false })
|
||||
price_set: PriceSet
|
||||
|
||||
@PriceRuleRuleTypeIdIndex.MikroORMIndex()
|
||||
@ManyToOne(() => RuleType, {
|
||||
columnType: "text",
|
||||
mapToPk: true,
|
||||
fieldName: "rule_type_id",
|
||||
})
|
||||
rule_type_id: string
|
||||
|
||||
@ManyToOne(() => RuleType, { persist: false })
|
||||
rule_type: RuleType
|
||||
|
||||
@Property({ columnType: "text" })
|
||||
value: string
|
||||
|
||||
@Property({ columnType: "integer", default: 0 })
|
||||
priority: number = 0
|
||||
|
||||
@PriceRulePriceIdIndex.MikroORMIndex()
|
||||
@ManyToOne(() => Price, {
|
||||
columnType: "text",
|
||||
mapToPk: true,
|
||||
fieldName: "price_id",
|
||||
onDelete: "cascade",
|
||||
})
|
||||
price_id: string
|
||||
|
||||
@ManyToOne(() => Price, { persist: false })
|
||||
price: Price
|
||||
|
||||
@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
|
||||
|
||||
@PriceRuleDeletedAtIndex.MikroORMIndex()
|
||||
@Property({ columnType: "timestamptz", nullable: true })
|
||||
deleted_at: Date | null = null
|
||||
|
||||
@BeforeCreate()
|
||||
beforeCreate() {
|
||||
this.id = generateEntityId(this.id, "prule")
|
||||
this.rule_type_id ??= this.rule_type?.id!
|
||||
this.price_set_id ??= this.price_set?.id!
|
||||
this.price_id ??= this.price?.id!
|
||||
}
|
||||
|
||||
@OnInit()
|
||||
onInit() {
|
||||
this.id = generateEntityId(this.id, "prule")
|
||||
this.rule_type_id ??= this.rule_type?.id!
|
||||
this.price_set_id ??= this.price_set?.id!
|
||||
this.price_id ??= this.price?.id!
|
||||
}
|
||||
}
|
||||
89
packages/modules/pricing/src/models/price-set-rule-type.ts
Normal file
89
packages/modules/pricing/src/models/price-set-rule-type.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import {
|
||||
DALUtils,
|
||||
createPsqlIndexStatementHelper,
|
||||
generateEntityId,
|
||||
} from "@medusajs/utils"
|
||||
import {
|
||||
BeforeCreate,
|
||||
Entity,
|
||||
Filter,
|
||||
ManyToOne,
|
||||
OnInit,
|
||||
PrimaryKey,
|
||||
Property,
|
||||
} from "@mikro-orm/core"
|
||||
import PriceSet from "./price-set"
|
||||
import RuleType from "./rule-type"
|
||||
|
||||
const tableName = "price_set_rule_type"
|
||||
const PriceSetRuleTypeDeletedAtIndex = createPsqlIndexStatementHelper({
|
||||
tableName: tableName,
|
||||
columns: "deleted_at",
|
||||
where: "deleted_at IS NOT NULL",
|
||||
})
|
||||
|
||||
const PriceSetRuleTypePriceSetIdIndex = createPsqlIndexStatementHelper({
|
||||
tableName: tableName,
|
||||
columns: "price_set_id",
|
||||
where: "deleted_at IS NULL",
|
||||
})
|
||||
|
||||
const PriceSetRuleTypeRuleTypeIdIndex = createPsqlIndexStatementHelper({
|
||||
tableName: tableName,
|
||||
columns: "rule_type_id",
|
||||
where: "deleted_at IS NULL",
|
||||
})
|
||||
|
||||
@Entity({ tableName })
|
||||
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
||||
export default class PriceSetRuleType {
|
||||
@PrimaryKey({ columnType: "text" })
|
||||
id!: string
|
||||
|
||||
@PriceSetRuleTypePriceSetIdIndex.MikroORMIndex()
|
||||
@ManyToOne(() => PriceSet, {
|
||||
columnType: "text",
|
||||
mapToPk: true,
|
||||
fieldName: "price_set_id",
|
||||
onDelete: "cascade",
|
||||
})
|
||||
price_set_id: string
|
||||
|
||||
@PriceSetRuleTypeRuleTypeIdIndex.MikroORMIndex()
|
||||
@ManyToOne(() => RuleType, {
|
||||
columnType: "text",
|
||||
mapToPk: true,
|
||||
fieldName: "rule_type_id",
|
||||
onDelete: "cascade",
|
||||
})
|
||||
rule_type_id: 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
|
||||
|
||||
@PriceSetRuleTypeDeletedAtIndex.MikroORMIndex()
|
||||
@Property({ columnType: "timestamptz", nullable: true })
|
||||
deleted_at: Date | null = null
|
||||
|
||||
@BeforeCreate()
|
||||
onCreate() {
|
||||
this.id = generateEntityId(this.id, "psrt")
|
||||
}
|
||||
|
||||
@OnInit()
|
||||
onInit() {
|
||||
this.id = generateEntityId(this.id, "psrt")
|
||||
}
|
||||
}
|
||||
83
packages/modules/pricing/src/models/price-set.ts
Normal file
83
packages/modules/pricing/src/models/price-set.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
import {
|
||||
createPsqlIndexStatementHelper,
|
||||
DALUtils,
|
||||
generateEntityId,
|
||||
} from "@medusajs/utils"
|
||||
import {
|
||||
BeforeCreate,
|
||||
Cascade,
|
||||
Collection,
|
||||
Entity,
|
||||
Filter,
|
||||
ManyToMany,
|
||||
OneToMany,
|
||||
OnInit,
|
||||
PrimaryKey,
|
||||
Property,
|
||||
} from "@mikro-orm/core"
|
||||
import Price from "./price"
|
||||
import PriceRule from "./price-rule"
|
||||
import PriceSetRuleType from "./price-set-rule-type"
|
||||
import RuleType from "./rule-type"
|
||||
|
||||
const tableName = "price_set"
|
||||
const PriceSetDeletedAtIndex = createPsqlIndexStatementHelper({
|
||||
tableName: tableName,
|
||||
columns: "deleted_at",
|
||||
where: "deleted_at IS NOT NULL",
|
||||
})
|
||||
|
||||
export const PriceSetIdPrefix = "pset"
|
||||
|
||||
@Entity({ tableName })
|
||||
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
||||
export default class PriceSet {
|
||||
@PrimaryKey({ columnType: "text" })
|
||||
id!: string
|
||||
|
||||
@OneToMany(() => Price, (price) => price.price_set, {
|
||||
cascade: [Cascade.PERSIST, "soft-remove" as Cascade],
|
||||
})
|
||||
prices = new Collection<Price>(this)
|
||||
|
||||
@OneToMany(() => PriceRule, (pr) => pr.price_set, {
|
||||
cascade: [Cascade.PERSIST, "soft-remove" as Cascade],
|
||||
})
|
||||
price_rules = new Collection<PriceRule>(this)
|
||||
|
||||
@ManyToMany({
|
||||
entity: () => RuleType,
|
||||
pivotEntity: () => PriceSetRuleType,
|
||||
cascade: ["soft-remove" as Cascade],
|
||||
})
|
||||
rule_types = new Collection<RuleType>(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
|
||||
|
||||
@PriceSetDeletedAtIndex.MikroORMIndex()
|
||||
@Property({ columnType: "timestamptz", nullable: true })
|
||||
deleted_at: Date | null = null
|
||||
|
||||
@BeforeCreate()
|
||||
onCreate() {
|
||||
this.id = generateEntityId(this.id, PriceSetIdPrefix)
|
||||
}
|
||||
|
||||
@OnInit()
|
||||
onInit() {
|
||||
this.id = generateEntityId(this.id, PriceSetIdPrefix)
|
||||
}
|
||||
}
|
||||
147
packages/modules/pricing/src/models/price.ts
Normal file
147
packages/modules/pricing/src/models/price.ts
Normal file
@@ -0,0 +1,147 @@
|
||||
import { DAL } from "@medusajs/types"
|
||||
import {
|
||||
BigNumber,
|
||||
createPsqlIndexStatementHelper,
|
||||
DALUtils,
|
||||
generateEntityId,
|
||||
MikroOrmBigNumberProperty,
|
||||
} from "@medusajs/utils"
|
||||
import {
|
||||
BeforeCreate,
|
||||
Cascade,
|
||||
Collection,
|
||||
Entity,
|
||||
Filter,
|
||||
ManyToOne,
|
||||
OneToMany,
|
||||
OnInit,
|
||||
OptionalProps,
|
||||
PrimaryKey,
|
||||
Property,
|
||||
} from "@mikro-orm/core"
|
||||
import PriceList from "./price-list"
|
||||
import PriceRule from "./price-rule"
|
||||
import PriceSet from "./price-set"
|
||||
|
||||
type OptionalFields = DAL.SoftDeletableEntityDateColumns
|
||||
|
||||
const tableName = "price"
|
||||
const PriceDeletedAtIndex = createPsqlIndexStatementHelper({
|
||||
tableName: tableName,
|
||||
columns: "deleted_at",
|
||||
where: "deleted_at IS NOT NULL",
|
||||
})
|
||||
|
||||
const PricePriceSetIdIndex = createPsqlIndexStatementHelper({
|
||||
tableName: tableName,
|
||||
columns: "price_set_id",
|
||||
where: "deleted_at IS NULL",
|
||||
})
|
||||
|
||||
const PricePriceListIdIndex = createPsqlIndexStatementHelper({
|
||||
tableName: tableName,
|
||||
columns: "price_list_id",
|
||||
where: "deleted_at IS NULL",
|
||||
})
|
||||
|
||||
const PriceCurrencyCodeIndex = createPsqlIndexStatementHelper({
|
||||
tableName: tableName,
|
||||
columns: "currency_code",
|
||||
where: "deleted_at IS NULL",
|
||||
})
|
||||
|
||||
@Entity({ tableName })
|
||||
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
||||
export default class Price {
|
||||
[OptionalProps]?: OptionalFields
|
||||
|
||||
@PrimaryKey({ columnType: "text" })
|
||||
id!: string
|
||||
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
title: string | null = null
|
||||
|
||||
@PriceCurrencyCodeIndex.MikroORMIndex()
|
||||
@Property({ columnType: "text" })
|
||||
currency_code: string
|
||||
|
||||
@MikroOrmBigNumberProperty()
|
||||
amount: BigNumber | number
|
||||
|
||||
@Property({ columnType: "jsonb" })
|
||||
raw_amount: Record<string, unknown>
|
||||
|
||||
@Property({ columnType: "numeric", nullable: true })
|
||||
min_quantity: number | null = null
|
||||
|
||||
@Property({ columnType: "numeric", nullable: true })
|
||||
max_quantity: number | null = null
|
||||
|
||||
@PricePriceSetIdIndex.MikroORMIndex()
|
||||
@ManyToOne(() => PriceSet, {
|
||||
columnType: "text",
|
||||
mapToPk: true,
|
||||
fieldName: "price_set_id",
|
||||
onDelete: "cascade",
|
||||
})
|
||||
price_set_id: string
|
||||
|
||||
@ManyToOne(() => PriceSet, { persist: false })
|
||||
price_set?: PriceSet
|
||||
|
||||
@Property({ columnType: "integer", default: 0 })
|
||||
rules_count: number = 0
|
||||
|
||||
@OneToMany({
|
||||
entity: () => PriceRule,
|
||||
mappedBy: (pr) => pr.price,
|
||||
cascade: [Cascade.PERSIST, "soft-remove" as Cascade],
|
||||
})
|
||||
price_rules = new Collection<PriceRule>(this)
|
||||
|
||||
@PricePriceListIdIndex.MikroORMIndex()
|
||||
@ManyToOne(() => PriceList, {
|
||||
columnType: "text",
|
||||
mapToPk: true,
|
||||
nullable: true,
|
||||
fieldName: "price_list_id",
|
||||
onDelete: "cascade",
|
||||
})
|
||||
price_list_id: string | null = null
|
||||
|
||||
@ManyToOne(() => PriceList, { persist: false, nullable: true })
|
||||
price_list: PriceList | null = null
|
||||
|
||||
@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
|
||||
|
||||
@PriceDeletedAtIndex.MikroORMIndex()
|
||||
@Property({ columnType: "timestamptz", nullable: true })
|
||||
deleted_at: Date | null = null
|
||||
|
||||
@BeforeCreate()
|
||||
onCreate() {
|
||||
this.id = generateEntityId(this.id, "price")
|
||||
this.price_set_id ??= this.price_set?.id!
|
||||
this.price_list_id ??= this.price_list?.id!
|
||||
}
|
||||
|
||||
@OnInit()
|
||||
onInit() {
|
||||
this.id = generateEntityId(this.id, "price")
|
||||
this.price_set_id ??= this.price_set?.id!
|
||||
this.price_list_id ??= this.price_list?.id!
|
||||
}
|
||||
}
|
||||
85
packages/modules/pricing/src/models/rule-type.ts
Normal file
85
packages/modules/pricing/src/models/rule-type.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
import {
|
||||
DALUtils,
|
||||
createPsqlIndexStatementHelper,
|
||||
generateEntityId,
|
||||
} from "@medusajs/utils"
|
||||
import {
|
||||
BeforeCreate,
|
||||
Collection,
|
||||
Entity,
|
||||
Filter,
|
||||
ManyToMany,
|
||||
OnInit,
|
||||
OptionalProps,
|
||||
PrimaryKey,
|
||||
Property,
|
||||
} from "@mikro-orm/core"
|
||||
import PriceSet from "./price-set"
|
||||
|
||||
type OptionalFields = "default_priority"
|
||||
|
||||
const tableName = "rule_type"
|
||||
const RuleTypeDeletedAtIndex = createPsqlIndexStatementHelper({
|
||||
tableName: tableName,
|
||||
columns: "deleted_at",
|
||||
where: "deleted_at IS NOT NULL",
|
||||
})
|
||||
|
||||
const RuleTypeRuleAttributeIndex = createPsqlIndexStatementHelper({
|
||||
tableName: tableName,
|
||||
columns: "rule_attribute",
|
||||
where: "deleted_at IS NULL",
|
||||
})
|
||||
|
||||
@Entity({ tableName })
|
||||
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
||||
class RuleType {
|
||||
[OptionalProps]?: OptionalFields
|
||||
|
||||
@PrimaryKey({ columnType: "text" })
|
||||
id!: string
|
||||
|
||||
@Property({ columnType: "text" })
|
||||
name: string
|
||||
|
||||
@RuleTypeRuleAttributeIndex.MikroORMIndex()
|
||||
@Property({ columnType: "text" })
|
||||
rule_attribute: string
|
||||
|
||||
@Property({ columnType: "integer", default: 0 })
|
||||
default_priority: number
|
||||
|
||||
@ManyToMany(() => PriceSet, (priceSet) => priceSet.rule_types)
|
||||
price_sets = new Collection<PriceSet>(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
|
||||
|
||||
@RuleTypeDeletedAtIndex.MikroORMIndex()
|
||||
@Property({ columnType: "timestamptz", nullable: true })
|
||||
deleted_at: Date | null = null
|
||||
|
||||
@BeforeCreate()
|
||||
onCreate() {
|
||||
this.id = generateEntityId(this.id, "rul-typ")
|
||||
}
|
||||
|
||||
@OnInit()
|
||||
onInit() {
|
||||
this.id = generateEntityId(this.id, "rul-typ")
|
||||
}
|
||||
}
|
||||
|
||||
export default RuleType
|
||||
30
packages/modules/pricing/src/module-definition.ts
Normal file
30
packages/modules/pricing/src/module-definition.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { Modules } from "@medusajs/modules-sdk"
|
||||
import { ModuleExports } from "@medusajs/types"
|
||||
import { ModulesSdkUtils } from "@medusajs/utils"
|
||||
import * as Models from "@models"
|
||||
import { PricingModuleService } from "@services"
|
||||
import loadConnection from "./loaders/connection"
|
||||
import loadContainer from "./loaders/container"
|
||||
|
||||
const migrationScriptOptions = {
|
||||
moduleName: Modules.PRICING,
|
||||
models: Models,
|
||||
pathToMigrations: __dirname + "/migrations",
|
||||
}
|
||||
|
||||
export const runMigrations = ModulesSdkUtils.buildMigrationScript(
|
||||
migrationScriptOptions
|
||||
)
|
||||
export const revertMigration = ModulesSdkUtils.buildRevertMigrationScript(
|
||||
migrationScriptOptions
|
||||
)
|
||||
|
||||
const service = PricingModuleService
|
||||
const loaders = [loadContainer, loadConnection] as any
|
||||
|
||||
export const moduleDefinition: ModuleExports = {
|
||||
service,
|
||||
loaders,
|
||||
runMigrations,
|
||||
revertMigration,
|
||||
}
|
||||
2
packages/modules/pricing/src/repositories/index.ts
Normal file
2
packages/modules/pricing/src/repositories/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export { MikroOrmBaseRepository as BaseRepository } from "@medusajs/utils"
|
||||
export { PricingRepository } from "./pricing"
|
||||
193
packages/modules/pricing/src/repositories/pricing.ts
Normal file
193
packages/modules/pricing/src/repositories/pricing.ts
Normal file
@@ -0,0 +1,193 @@
|
||||
import { MedusaError, MikroOrmBase } from "@medusajs/utils"
|
||||
|
||||
import {
|
||||
CalculatedPriceSetDTO,
|
||||
Context,
|
||||
PricingContext,
|
||||
PricingFilters,
|
||||
PricingRepositoryService,
|
||||
} from "@medusajs/types"
|
||||
import { SqlEntityManager } from "@mikro-orm/postgresql"
|
||||
|
||||
export class PricingRepository
|
||||
extends MikroOrmBase
|
||||
implements PricingRepositoryService
|
||||
{
|
||||
constructor() {
|
||||
// @ts-ignore
|
||||
// eslint-disable-next-line prefer-rest-params
|
||||
super(...arguments)
|
||||
}
|
||||
|
||||
async calculatePrices(
|
||||
pricingFilters: PricingFilters,
|
||||
pricingContext: PricingContext = { context: {} },
|
||||
sharedContext: Context = {}
|
||||
): Promise<CalculatedPriceSetDTO[]> {
|
||||
const manager = this.getActiveManager<SqlEntityManager>(sharedContext)
|
||||
const knex = manager.getKnex()
|
||||
const context = pricingContext.context || {}
|
||||
|
||||
// Quantity is used to scope money amounts based on min_quantity and max_quantity.
|
||||
// We should potentially think of reserved words in pricingContext that can't be used in rules
|
||||
// or have a separate pricing options that accept things like quantity, price_list_id and other
|
||||
// pricing module features
|
||||
const quantity = context.quantity
|
||||
delete context.quantity
|
||||
|
||||
// Currency code here is a required param.
|
||||
const currencyCode = context.currency_code
|
||||
delete context.currency_code
|
||||
|
||||
if (!currencyCode) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
`Method calculatePrices requires currency_code in the pricing context`
|
||||
)
|
||||
}
|
||||
|
||||
const isContextPresent = Object.entries(context).length || !!currencyCode
|
||||
|
||||
// Only if the context is present do we need to query the database.
|
||||
// We don't get anything from the db otherwise.
|
||||
if (!isContextPresent) {
|
||||
return []
|
||||
}
|
||||
|
||||
const date = new Date().toISOString()
|
||||
// Gets all the price set money amounts where rules match for each of the contexts
|
||||
// that the price set is configured for
|
||||
const priceSubQueryKnex = knex({
|
||||
price: "price",
|
||||
})
|
||||
.select({
|
||||
id: "price1.id",
|
||||
amount: "price1.amount",
|
||||
min_quantity: "price1.min_quantity",
|
||||
max_quantity: "price1.max_quantity",
|
||||
currency_code: "price1.currency_code",
|
||||
price_set_id: "price1.price_set_id",
|
||||
rules_count: "price1.rules_count",
|
||||
price_list_id: "price1.price_list_id",
|
||||
pl_rules_count: "pl.rules_count",
|
||||
pl_type: "pl.type",
|
||||
has_price_list: knex.raw(
|
||||
"case when price1.price_list_id IS NULL then False else True end"
|
||||
),
|
||||
})
|
||||
.leftJoin("price as price1", "price1.id", "price1.id")
|
||||
.leftJoin("price_rule as pr", "pr.price_id", "price1.id")
|
||||
.leftJoin("price_list as pl", "pl.id", "price1.price_list_id")
|
||||
.leftJoin("price_list_rule as plr", "plr.price_list_id", "pl.id")
|
||||
.leftJoin(
|
||||
"price_list_rule_value as plrv",
|
||||
"plrv.price_list_rule_id",
|
||||
"plr.id"
|
||||
)
|
||||
.leftJoin("rule_type as plrt", "plrt.id", "plr.rule_type_id")
|
||||
.leftJoin("rule_type as rt", "rt.id", "pr.rule_type_id")
|
||||
.orderBy([
|
||||
{ column: "rules_count", order: "desc" },
|
||||
{ column: "pl.rules_count", order: "desc" },
|
||||
])
|
||||
.groupBy("price1.id", "pl.id")
|
||||
.having(
|
||||
knex.raw(
|
||||
"count(DISTINCT rt.rule_attribute) = price1.rules_count AND price1.price_list_id IS NULL"
|
||||
)
|
||||
)
|
||||
.orHaving(
|
||||
knex.raw(
|
||||
"count(DISTINCT plrt.rule_attribute) = pl.rules_count AND price1.price_list_id IS NOT NULL"
|
||||
)
|
||||
)
|
||||
|
||||
priceSubQueryKnex.orWhere((q) => {
|
||||
for (const [key, value] of Object.entries(context)) {
|
||||
q.orWhere({
|
||||
"rt.rule_attribute": key,
|
||||
"pr.value": value,
|
||||
})
|
||||
}
|
||||
q.orWhere("price1.rules_count", "=", 0)
|
||||
q.whereNull("price1.price_list_id")
|
||||
})
|
||||
|
||||
priceSubQueryKnex.orWhere((q) => {
|
||||
q.whereNotNull("price1.price_list_id")
|
||||
.andWhere(function () {
|
||||
this.whereNull("pl.starts_at").orWhere("pl.starts_at", "<=", date)
|
||||
})
|
||||
.andWhere(function () {
|
||||
this.whereNull("pl.ends_at").orWhere("pl.ends_at", ">=", date)
|
||||
})
|
||||
.andWhere(function () {
|
||||
this.andWhere(function () {
|
||||
for (const [key, value] of Object.entries(context)) {
|
||||
this.orWhere({
|
||||
"plrt.rule_attribute": key,
|
||||
})
|
||||
this.whereIn("plrv.value", [value])
|
||||
}
|
||||
|
||||
this.orWhere("pl.rules_count", "=", 0)
|
||||
})
|
||||
|
||||
this.andWhere(function () {
|
||||
this.andWhere(function () {
|
||||
for (const [key, value] of Object.entries(context)) {
|
||||
this.orWhere({
|
||||
"rt.rule_attribute": key,
|
||||
"pr.value": value,
|
||||
})
|
||||
}
|
||||
this.andWhere("price1.rules_count", ">", 0)
|
||||
})
|
||||
this.orWhere("price1.rules_count", "=", 0)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
const priceSetQueryKnex = knex({
|
||||
ps: "price_set",
|
||||
})
|
||||
.select({
|
||||
id: "price.id",
|
||||
price_set_id: "ps.id",
|
||||
amount: "price.amount",
|
||||
min_quantity: "price.min_quantity",
|
||||
max_quantity: "price.max_quantity",
|
||||
currency_code: "price.currency_code",
|
||||
default_priority: "rt.default_priority",
|
||||
rules_count: "price.rules_count",
|
||||
pl_rules_count: "price.pl_rules_count",
|
||||
price_list_type: "price.pl_type",
|
||||
price_list_id: "price.price_list_id",
|
||||
})
|
||||
.join(priceSubQueryKnex.as("price"), "price.price_set_id", "ps.id")
|
||||
.leftJoin("price_rule as pr", "pr.price_id", "price.id")
|
||||
.leftJoin("rule_type as rt", "rt.id", "pr.rule_type_id")
|
||||
.whereIn("ps.id", pricingFilters.id)
|
||||
.andWhere("price.currency_code", "=", currencyCode)
|
||||
|
||||
.orderBy([
|
||||
{ column: "price.has_price_list", order: "asc" },
|
||||
{ column: "amount", order: "asc" },
|
||||
{ column: "rules_count", order: "desc" },
|
||||
{ column: "default_priority", order: "desc" },
|
||||
])
|
||||
|
||||
if (quantity) {
|
||||
priceSetQueryKnex.where("price.min_quantity", "<=", quantity)
|
||||
priceSetQueryKnex.andWhere("price.max_quantity", ">=", quantity)
|
||||
} else {
|
||||
priceSetQueryKnex.andWhere(function () {
|
||||
this.andWhere("price.min_quantity", "<=", "1").orWhereNull(
|
||||
"price.min_quantity"
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
return await priceSetQueryKnex
|
||||
}
|
||||
}
|
||||
16
packages/modules/pricing/src/schema/index.ts
Normal file
16
packages/modules/pricing/src/schema/index.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
export const schema = `
|
||||
type PriceSet {
|
||||
id: String!
|
||||
money_amounts: [MoneyAmount]
|
||||
}
|
||||
|
||||
type MoneyAmount {
|
||||
id: String!
|
||||
currency_code: String
|
||||
amount: Float
|
||||
min_quantity: Float
|
||||
max_quantity: Float
|
||||
}
|
||||
`
|
||||
|
||||
export default schema
|
||||
19
packages/modules/pricing/src/scripts/bin/run-seed.ts
Normal file
19
packages/modules/pricing/src/scripts/bin/run-seed.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { EOL } from "os"
|
||||
import { run } from "../seed"
|
||||
|
||||
const args = process.argv
|
||||
const path = args.pop() as string
|
||||
|
||||
export default (async () => {
|
||||
const { config } = await import("dotenv")
|
||||
config()
|
||||
if (!path) {
|
||||
throw new Error(
|
||||
`filePath is required.${EOL}Example: medusa-pricing-seed <filePath>`
|
||||
)
|
||||
}
|
||||
|
||||
await run({ path })
|
||||
})()
|
||||
84
packages/modules/pricing/src/scripts/seed.ts
Normal file
84
packages/modules/pricing/src/scripts/seed.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
import { LoaderOptions, Logger, ModulesSdkTypes } from "@medusajs/types"
|
||||
import { DALUtils, ModulesSdkUtils } from "@medusajs/utils"
|
||||
import { EntitySchema, RequiredEntityData } from "@mikro-orm/core"
|
||||
import { PostgreSqlDriver, SqlEntityManager } from "@mikro-orm/postgresql"
|
||||
import * as PricingModels from "@models"
|
||||
import { EOL } from "os"
|
||||
import { resolve } from "path"
|
||||
|
||||
export async function run({
|
||||
options,
|
||||
logger,
|
||||
path,
|
||||
}: Partial<
|
||||
Pick<
|
||||
LoaderOptions<ModulesSdkTypes.ModuleServiceInitializeOptions>,
|
||||
"options" | "logger"
|
||||
>
|
||||
> & {
|
||||
path: string
|
||||
}) {
|
||||
logger ??= console as unknown as Logger
|
||||
|
||||
logger.info(`Loading seed data from ${path}...`)
|
||||
|
||||
const { priceSetsData, pricesData } = await import(
|
||||
resolve(process.cwd(), path)
|
||||
).catch((e) => {
|
||||
logger?.error(
|
||||
`Failed to load seed data from ${path}. Please, provide a relative path and check that you export the following: priceSetsData and pricesData.${EOL}${e}`
|
||||
)
|
||||
throw e
|
||||
})
|
||||
|
||||
const dbData = ModulesSdkUtils.loadDatabaseConfig("pricing", options)!
|
||||
const entities = Object.values(PricingModels) as unknown as EntitySchema[]
|
||||
const pathToMigrations = __dirname + "/../migrations"
|
||||
|
||||
const orm = await DALUtils.mikroOrmCreateConnection(
|
||||
dbData,
|
||||
entities,
|
||||
pathToMigrations
|
||||
)
|
||||
|
||||
const manager = orm.em.fork()
|
||||
|
||||
try {
|
||||
logger.info("Inserting price_sets & prices")
|
||||
|
||||
await createPriceSets(manager, priceSetsData)
|
||||
await createPrices(manager, pricesData)
|
||||
} catch (e) {
|
||||
logger.error(
|
||||
`Failed to insert the seed data in the PostgreSQL database ${dbData.clientUrl}.${EOL}${e}`
|
||||
)
|
||||
}
|
||||
|
||||
await orm.close(true)
|
||||
}
|
||||
|
||||
async function createPriceSets(
|
||||
manager: SqlEntityManager<PostgreSqlDriver>,
|
||||
data: RequiredEntityData<PricingModels.PriceSet>[]
|
||||
) {
|
||||
const priceSets = data.map((priceSetData) => {
|
||||
return manager.create(PricingModels.PriceSet, priceSetData)
|
||||
})
|
||||
|
||||
await manager.persistAndFlush(priceSets)
|
||||
|
||||
return priceSets
|
||||
}
|
||||
|
||||
async function createPrices(
|
||||
manager: SqlEntityManager<PostgreSqlDriver>,
|
||||
data: RequiredEntityData<PricingModels.Price>[]
|
||||
) {
|
||||
const prices = data.map((priceData) => {
|
||||
return manager.create(PricingModels.Price, priceData)
|
||||
})
|
||||
|
||||
await manager.persistAndFlush(prices)
|
||||
|
||||
return prices
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
it("noop", () => {})
|
||||
3
packages/modules/pricing/src/services/index.ts
Normal file
3
packages/modules/pricing/src/services/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export { default as PriceListService } from "./price-list"
|
||||
export { default as PricingModuleService } from "./pricing-module"
|
||||
export { default as RuleTypeService } from "./rule-type"
|
||||
69
packages/modules/pricing/src/services/price-list.ts
Normal file
69
packages/modules/pricing/src/services/price-list.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
import { Context, DAL } from "@medusajs/types"
|
||||
import { GetIsoStringFromDate, ModulesSdkUtils } from "@medusajs/utils"
|
||||
import { PriceList } from "@models"
|
||||
import { ServiceTypes } from "@types"
|
||||
|
||||
type InjectedDependencies = {
|
||||
priceListRepository: DAL.RepositoryService
|
||||
}
|
||||
|
||||
export default class PriceListService<
|
||||
TEntity extends PriceList = PriceList
|
||||
> extends ModulesSdkUtils.internalModuleServiceFactory<InjectedDependencies>(
|
||||
PriceList
|
||||
)<TEntity> {
|
||||
constructor(container: InjectedDependencies) {
|
||||
// @ts-ignore
|
||||
super(...arguments)
|
||||
}
|
||||
|
||||
create(
|
||||
data: ServiceTypes.CreatePriceListDTO[],
|
||||
sharedContext?: Context
|
||||
): Promise<TEntity[]>
|
||||
create(
|
||||
data: ServiceTypes.CreatePriceListDTO,
|
||||
sharedContext?: Context
|
||||
): Promise<TEntity>
|
||||
|
||||
async create(
|
||||
data: ServiceTypes.CreatePriceListDTO | ServiceTypes.CreatePriceListDTO[],
|
||||
sharedContext?: Context
|
||||
): Promise<TEntity | TEntity[]> {
|
||||
const data_ = Array.isArray(data) ? data : [data]
|
||||
const priceLists = this.normalizePriceListDate(data_)
|
||||
return await super.create(priceLists, sharedContext)
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
update(data: any[], sharedContext?: Context): Promise<TEntity[]>
|
||||
// @ts-ignore
|
||||
update(data: any, sharedContext?: Context): Promise<TEntity>
|
||||
|
||||
// TODO: Add support for selector? and then rm ts ignore
|
||||
// @ts-ignore
|
||||
async update(
|
||||
data: ServiceTypes.UpdatePriceListDTO | ServiceTypes.UpdatePriceListDTO[],
|
||||
sharedContext?: Context
|
||||
): Promise<TEntity | TEntity[]> {
|
||||
const data_ = Array.isArray(data) ? data : [data]
|
||||
const priceLists = this.normalizePriceListDate(data_)
|
||||
return await super.update(priceLists, sharedContext)
|
||||
}
|
||||
|
||||
protected normalizePriceListDate(
|
||||
data: (ServiceTypes.UpdatePriceListDTO | ServiceTypes.CreatePriceListDTO)[]
|
||||
) {
|
||||
return data.map((priceListData: any) => {
|
||||
if (!!priceListData.starts_at) {
|
||||
priceListData.starts_at = GetIsoStringFromDate(priceListData.starts_at)
|
||||
}
|
||||
|
||||
if (!!priceListData.ends_at) {
|
||||
priceListData.ends_at = GetIsoStringFromDate(priceListData.ends_at)
|
||||
}
|
||||
|
||||
return priceListData
|
||||
})
|
||||
}
|
||||
}
|
||||
1669
packages/modules/pricing/src/services/pricing-module.ts
Normal file
1669
packages/modules/pricing/src/services/pricing-module.ts
Normal file
File diff suppressed because it is too large
Load Diff
68
packages/modules/pricing/src/services/rule-type.ts
Normal file
68
packages/modules/pricing/src/services/rule-type.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { Context, DAL, PricingTypes } from "@medusajs/types"
|
||||
import {
|
||||
InjectTransactionManager,
|
||||
MedusaContext,
|
||||
ModulesSdkUtils,
|
||||
validateRuleAttributes,
|
||||
} from "@medusajs/utils"
|
||||
import { RuleType } from "@models"
|
||||
|
||||
type InjectedDependencies = {
|
||||
ruleTypeRepository: DAL.RepositoryService
|
||||
}
|
||||
|
||||
export default class RuleTypeService<
|
||||
TEntity extends RuleType = RuleType
|
||||
> extends ModulesSdkUtils.internalModuleServiceFactory<InjectedDependencies>(
|
||||
RuleType
|
||||
)<TEntity> {
|
||||
protected readonly ruleTypeRepository_: DAL.RepositoryService<TEntity>
|
||||
|
||||
constructor({ ruleTypeRepository }: InjectedDependencies) {
|
||||
// @ts-ignore
|
||||
super(...arguments)
|
||||
this.ruleTypeRepository_ = ruleTypeRepository
|
||||
}
|
||||
|
||||
create(
|
||||
data: PricingTypes.CreateRuleTypeDTO,
|
||||
sharedContext: Context
|
||||
): Promise<TEntity>
|
||||
create(
|
||||
data: PricingTypes.CreateRuleTypeDTO[],
|
||||
sharedContext: Context
|
||||
): Promise<TEntity[]>
|
||||
|
||||
@InjectTransactionManager("ruleTypeRepository_")
|
||||
async create(
|
||||
data: PricingTypes.CreateRuleTypeDTO | PricingTypes.CreateRuleTypeDTO[],
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<TEntity | TEntity[]> {
|
||||
const data_ = Array.isArray(data) ? data : [data]
|
||||
validateRuleAttributes(data_.map((d) => d.rule_attribute))
|
||||
return await super.create(data, sharedContext)
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
update(
|
||||
data: PricingTypes.UpdateRuleTypeDTO[],
|
||||
sharedContext: Context
|
||||
): Promise<TEntity[]>
|
||||
// @ts-ignore
|
||||
update(
|
||||
data: PricingTypes.UpdateRuleTypeDTO,
|
||||
sharedContext: Context
|
||||
): Promise<TEntity>
|
||||
|
||||
@InjectTransactionManager("ruleTypeRepository_")
|
||||
// TODO: add support for selector? and then rm ts ignore
|
||||
// @ts-ignore
|
||||
async update(
|
||||
data: PricingTypes.UpdateRuleTypeDTO | PricingTypes.UpdateRuleTypeDTO[],
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<TEntity | TEntity[]> {
|
||||
const data_ = Array.isArray(data) ? data : [data]
|
||||
validateRuleAttributes(data_.map((d) => d.rule_attribute))
|
||||
return await super.update(data, sharedContext)
|
||||
}
|
||||
}
|
||||
7
packages/modules/pricing/src/types/index.ts
Normal file
7
packages/modules/pricing/src/types/index.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { Logger } from "@medusajs/types"
|
||||
|
||||
export type InitializeModuleInjectableDependencies = {
|
||||
logger?: Logger
|
||||
}
|
||||
|
||||
export * as ServiceTypes from "./services"
|
||||
2
packages/modules/pricing/src/types/services/index.ts
Normal file
2
packages/modules/pricing/src/types/services/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from "./price-list"
|
||||
export * from "./price-set"
|
||||
20
packages/modules/pricing/src/types/services/price-list.ts
Normal file
20
packages/modules/pricing/src/types/services/price-list.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { PriceListStatus, PriceListType } from "@medusajs/utils"
|
||||
|
||||
export interface CreatePriceListDTO {
|
||||
title: string
|
||||
description: string
|
||||
starts_at?: string | null
|
||||
ends_at?: string | null
|
||||
status?: PriceListStatus
|
||||
type?: PriceListType
|
||||
number_rules?: number
|
||||
}
|
||||
|
||||
export interface UpdatePriceListDTO {
|
||||
id: string
|
||||
title?: string
|
||||
starts_at?: string | null
|
||||
ends_at?: string | null
|
||||
status?: PriceListStatus
|
||||
number_rules?: number
|
||||
}
|
||||
5
packages/modules/pricing/src/types/services/price-set.ts
Normal file
5
packages/modules/pricing/src/types/services/price-set.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { UpdatePriceSetDTO } from "@medusajs/types"
|
||||
|
||||
export interface UpdatePriceSetInput extends UpdatePriceSetDTO {
|
||||
id: string
|
||||
}
|
||||
1
packages/modules/pricing/src/utils/index.ts
Normal file
1
packages/modules/pricing/src/utils/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from "./validate-price-list-dates"
|
||||
@@ -0,0 +1,20 @@
|
||||
import { isDate, MedusaError } from "@medusajs/utils"
|
||||
|
||||
export const validatePriceListDates = (priceListData: {
|
||||
starts_at?: Date | string | null
|
||||
ends_at?: Date | string | null
|
||||
}) => {
|
||||
if (!!priceListData.starts_at && !isDate(priceListData.starts_at)) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
`Cannot set price list starts at with with invalid date string: ${priceListData.starts_at}`
|
||||
)
|
||||
}
|
||||
|
||||
if (!!priceListData.ends_at && !isDate(priceListData.ends_at)) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
`Cannot set price list ends at with with invalid date string: ${priceListData.ends_at}`
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user