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/fulfillment/src/index.ts
Normal file
14
packages/modules/fulfillment/src/index.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { moduleDefinition } from "./module-definition"
|
||||
import { initializeFactory, Modules } from "@medusajs/modules-sdk"
|
||||
|
||||
export * from "./types"
|
||||
export * from "./models"
|
||||
export * from "./services"
|
||||
|
||||
export const initialize = initializeFactory({
|
||||
moduleName: Modules.FULFILLMENT,
|
||||
moduleDefinition,
|
||||
})
|
||||
export const runMigrations = moduleDefinition.runMigrations
|
||||
export const revertMigration = moduleDefinition.revertMigration
|
||||
export default moduleDefinition
|
||||
94
packages/modules/fulfillment/src/joiner-config.ts
Normal file
94
packages/modules/fulfillment/src/joiner-config.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
import { Modules } from "@medusajs/modules-sdk"
|
||||
import { ModuleJoinerConfig } from "@medusajs/types"
|
||||
import { MapToConfig } from "@medusajs/utils"
|
||||
import {
|
||||
Fulfillment,
|
||||
FulfillmentProvider,
|
||||
FulfillmentSet,
|
||||
GeoZone,
|
||||
ServiceZone,
|
||||
ShippingOption,
|
||||
ShippingOptionRule,
|
||||
ShippingProfile,
|
||||
} from "@models"
|
||||
|
||||
export const LinkableKeys: Record<string, string> = {
|
||||
fulfillment_id: Fulfillment.name,
|
||||
fulfillment_set_id: FulfillmentSet.name,
|
||||
shipping_option_id: ShippingOption.name,
|
||||
shipping_option_rule_id: ShippingOptionRule.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.FULFILLMENT,
|
||||
primaryKeys: ["id"],
|
||||
linkableKeys: LinkableKeys,
|
||||
alias: [
|
||||
{
|
||||
name: ["fulfillment_set", "fulfillment_sets"],
|
||||
args: {
|
||||
entity: FulfillmentSet.name,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["shipping_option", "shipping_options"],
|
||||
args: {
|
||||
entity: ShippingOption.name,
|
||||
methodSuffix: "ShippingOptions",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["shipping_profile", "shipping_profiles"],
|
||||
args: {
|
||||
entity: ShippingProfile.name,
|
||||
methodSuffix: "ShippingProfiles",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["fulfillment", "fulfillments"],
|
||||
args: {
|
||||
entity: Fulfillment.name,
|
||||
methodSuffix: "Fulfillments",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["fulfillment_provider", "fulfillment_providers"],
|
||||
args: {
|
||||
entity: FulfillmentProvider.name,
|
||||
methodSuffix: "FulfillmentProviders",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["service_zone", "service_zones"],
|
||||
args: {
|
||||
entity: ServiceZone.name,
|
||||
methodSuffix: "ServiceZones",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["geo_zone", "geo_zones"],
|
||||
args: {
|
||||
entity: GeoZone.name,
|
||||
methodSuffix: "GeoZones",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["shipping_option_rule", "shipping_option_rules"],
|
||||
args: {
|
||||
entity: ShippingOptionRule.name,
|
||||
methodSuffix: "ShippingOptionRules",
|
||||
},
|
||||
},
|
||||
],
|
||||
} as ModuleJoinerConfig
|
||||
113
packages/modules/fulfillment/src/loaders/providers.ts
Normal file
113
packages/modules/fulfillment/src/loaders/providers.ts
Normal file
@@ -0,0 +1,113 @@
|
||||
import { moduleProviderLoader } from "@medusajs/modules-sdk"
|
||||
import { LoaderOptions, ModuleProvider, ModulesSdkTypes } from "@medusajs/types"
|
||||
import {
|
||||
ContainerRegistrationKeys,
|
||||
lowerCaseFirst,
|
||||
promiseAll,
|
||||
} from "@medusajs/utils"
|
||||
import { FulfillmentProviderService } from "@services"
|
||||
import { FulfillmentIdentifiersRegistrationName } from "@types"
|
||||
import { Lifetime, asFunction, asValue } from "awilix"
|
||||
|
||||
const registrationFn = async (klass, container, pluginOptions) => {
|
||||
Object.entries(pluginOptions.config || []).map(([name, config]) => {
|
||||
const key = FulfillmentProviderService.getRegistrationIdentifier(
|
||||
klass,
|
||||
name
|
||||
)
|
||||
|
||||
container.register({
|
||||
["fp_" + key]: asFunction((cradle) => new klass(cradle, config), {
|
||||
lifetime: klass.LIFE_TIME || Lifetime.SINGLETON,
|
||||
}),
|
||||
})
|
||||
|
||||
container.registerAdd(FulfillmentIdentifiersRegistrationName, asValue(key))
|
||||
})
|
||||
}
|
||||
|
||||
export default async ({
|
||||
container,
|
||||
options,
|
||||
}: LoaderOptions<
|
||||
(
|
||||
| ModulesSdkTypes.ModuleServiceInitializeOptions
|
||||
| ModulesSdkTypes.ModuleServiceInitializeCustomDataLayerOptions
|
||||
) & { providers: ModuleProvider[] }
|
||||
>): Promise<void> => {
|
||||
container.registerAdd(
|
||||
FulfillmentIdentifiersRegistrationName,
|
||||
asValue(undefined)
|
||||
)
|
||||
|
||||
// Local providers
|
||||
// TODO
|
||||
|
||||
await moduleProviderLoader({
|
||||
container,
|
||||
providers: options?.providers || [],
|
||||
registerServiceFn: registrationFn,
|
||||
})
|
||||
|
||||
await syncDatabaseProviders({
|
||||
container,
|
||||
})
|
||||
}
|
||||
|
||||
async function syncDatabaseProviders({ container }) {
|
||||
const providerServiceRegistrationKey = lowerCaseFirst(
|
||||
FulfillmentProviderService.name
|
||||
)
|
||||
|
||||
const logger = container.resolve(ContainerRegistrationKeys.LOGGER) ?? console
|
||||
|
||||
try {
|
||||
const providerIdentifiers: string[] = (
|
||||
container.resolve(FulfillmentIdentifiersRegistrationName) ?? []
|
||||
).filter(Boolean)
|
||||
|
||||
const providerService: ModulesSdkTypes.InternalModuleService<any> =
|
||||
container.resolve(providerServiceRegistrationKey)
|
||||
|
||||
const providers = await providerService.list({})
|
||||
const loadedProvidersMap = new Map(providers.map((p) => [p.id, p]))
|
||||
|
||||
const providersToCreate = providerIdentifiers.filter(
|
||||
(id) => !loadedProvidersMap.has(id)
|
||||
)
|
||||
const providersToEnabled = providerIdentifiers.filter((id) =>
|
||||
loadedProvidersMap.has(id)
|
||||
)
|
||||
const providersToDisable = providers.filter(
|
||||
(p) => !providerIdentifiers.includes(p.id)
|
||||
)
|
||||
|
||||
const promises: Promise<any>[] = []
|
||||
|
||||
if (providersToCreate.length) {
|
||||
promises.push(
|
||||
providerService.create(providersToCreate.map((id) => ({ id })))
|
||||
)
|
||||
}
|
||||
|
||||
if (providersToEnabled.length) {
|
||||
promises.push(
|
||||
providerService.update(
|
||||
providersToEnabled.map((id) => ({ id, is_enabled: true }))
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
if (providersToDisable.length) {
|
||||
promises.push(
|
||||
providerService.update(
|
||||
providersToDisable.map((p) => ({ id: p.id, is_enabled: false }))
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
await promiseAll(promises)
|
||||
} catch (error) {
|
||||
logger.error(`Error syncing the fulfillment providers: ${error.message}`)
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,603 @@
|
||||
import { Migration } from "@mikro-orm/migrations"
|
||||
|
||||
export class Migration20240311145700_InitialSetupMigration extends Migration {
|
||||
async up(): Promise<void> {
|
||||
const shippingOptionTable = await this.execute(
|
||||
`SELECT * FROM information_schema.tables where table_name = 'shipping_option' and table_schema = 'public';`
|
||||
)
|
||||
|
||||
if (!shippingOptionTable.length) {
|
||||
await migrateUpModuleMigration.call(this)
|
||||
} else {
|
||||
await migrateUpBackwardCompatibility.call(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This migration is for the initial setup of the fulfillment module in the case of
|
||||
* an already existing database. It will check if the `shipping_option` table exists and in that case
|
||||
* assume that all other associated tables exists and will migrate them all.
|
||||
*
|
||||
* This migration does not take into account the data migration part which
|
||||
* should be handled separately. Also, after the data migration
|
||||
* the tables should be cleaned up from the old columns.
|
||||
**/
|
||||
async function migrateUpBackwardCompatibility(
|
||||
this: Migration20240311145700_InitialSetupMigration
|
||||
) {
|
||||
this.addSql(
|
||||
'create table if not exists "fulfillment_address" ("id" text not null, "company" text null, "first_name" text null, "last_name" text null, "address_1" text null, "address_2" text null, "city" text null, "country_code" text null, "province" text null, "postal_code" text null, "phone" text null, "metadata" jsonb null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "fulfillment_address_pkey" primary key ("id"));'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_fulfillment_address_deleted_at" ON "fulfillment_address" (deleted_at) WHERE deleted_at IS NOT NULL;'
|
||||
)
|
||||
|
||||
this.addSql(`
|
||||
alter table fulfillment_provider
|
||||
alter column id type text using id::text;
|
||||
|
||||
alter table fulfillment_provider
|
||||
add is_enabled boolean default true not null;
|
||||
`)
|
||||
|
||||
this.addSql(
|
||||
'create table if not exists "fulfillment_set" ("id" text not null, "name" text not null, "type" text not null, "metadata" jsonb null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "fulfillment_set_pkey" primary key ("id"));'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE UNIQUE INDEX IF NOT EXISTS "IDX_fulfillment_set_name_unique" ON "fulfillment_set" (name) WHERE deleted_at IS NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_fulfillment_set_deleted_at" ON "fulfillment_set" (deleted_at) WHERE deleted_at IS NOT NULL;'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'create table if not exists "service_zone" ("id" text not null, "name" text not null, "metadata" jsonb null, "fulfillment_set_id" text not null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "service_zone_pkey" primary key ("id"));'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE UNIQUE INDEX IF NOT EXISTS "IDX_service_zone_name_unique" ON "service_zone" (name) WHERE deleted_at IS NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_service_zone_fulfillment_set_id" ON "service_zone" (fulfillment_set_id) WHERE deleted_at IS NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_service_zone_deleted_at" ON "service_zone" (deleted_at) WHERE deleted_at IS NOT NULL;'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'create table if not exists "geo_zone" ("id" text not null, "type" text check ("type" in (\'country\', \'province\', \'city\', \'zip\')) not null default \'country\', "country_code" text not null, "province_code" text null, "city" text null, "service_zone_id" text not null, "postal_expression" jsonb null, "metadata" jsonb null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "geo_zone_pkey" primary key ("id"));'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_geo_zone_country_code" ON "geo_zone" (country_code) WHERE deleted_at IS NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_geo_zone_province_code" ON "geo_zone" (province_code) WHERE deleted_at IS NULL AND province_code IS NOT NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_geo_zone_city" ON "geo_zone" (city) WHERE deleted_at IS NULL AND city IS NOT NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_geo_zone_service_zone_id" ON "geo_zone" (service_zone_id) WHERE deleted_at IS NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_geo_zone_deleted_at" ON "geo_zone" (deleted_at) WHERE deleted_at IS NOT NULL;'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'create table if not exists "shipping_option_type" ("id" text not null, "label" text not null, "description" text null, "code" text not null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "shipping_option_type_pkey" primary key ("id"));'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_shipping_option_type_deleted_at" ON "shipping_option_type" (deleted_at) WHERE deleted_at IS NOT NULL;'
|
||||
)
|
||||
|
||||
this.addSql(`
|
||||
alter table shipping_profile
|
||||
alter column id type text using id::text;
|
||||
|
||||
alter table shipping_profile
|
||||
alter column name type text using name::text;
|
||||
|
||||
alter table shipping_profile
|
||||
alter column type type text using type::text;
|
||||
|
||||
create unique index if not exists "IDX_shipping_profile_name_unique"
|
||||
on shipping_profile (name)
|
||||
where (deleted_at IS NULL);
|
||||
|
||||
create index if not exists "IDX_shipping_profile_deleted_at"
|
||||
on shipping_profile (deleted_at)
|
||||
where (deleted_at IS NOT NULL);
|
||||
`)
|
||||
|
||||
this.addSql(`
|
||||
alter table shipping_option
|
||||
alter column id type text using id::text;
|
||||
|
||||
alter table shipping_option
|
||||
alter column name type text using name::text;
|
||||
|
||||
alter table shipping_option
|
||||
add service_zone_id text not null;
|
||||
|
||||
alter table shipping_option
|
||||
RENAME profile_id TO shipping_profile_id;
|
||||
|
||||
alter table shipping_option
|
||||
alter column region_id drop not null;
|
||||
|
||||
alter table shipping_option
|
||||
alter column price_type type text using price_type::text;
|
||||
|
||||
alter table shipping_option
|
||||
alter column price_type set default 'calculated'::text;
|
||||
|
||||
alter table shipping_option
|
||||
alter column data drop not null;
|
||||
|
||||
alter table shipping_option
|
||||
add shipping_option_type_id text not null;
|
||||
|
||||
drop index if exists "IDX_5c58105f1752fca0f4ce69f466";
|
||||
|
||||
drop index if exists "IDX_c951439af4c98bf2bd7fb8726c";
|
||||
|
||||
drop index if exists "IDX_a0e206bfaed3cb63c186091734";
|
||||
|
||||
create index if not exists "IDX_shipping_option_service_zone_id"
|
||||
on shipping_option (service_zone_id)
|
||||
where (deleted_at IS NULL);
|
||||
|
||||
create index if not exists "IDX_shipping_option_shipping_profile_id"
|
||||
on shipping_option (shipping_profile_id)
|
||||
where (deleted_at IS NULL);
|
||||
|
||||
create index if not exists "IDX_shipping_option_provider_id"
|
||||
on shipping_option (provider_id)
|
||||
where (deleted_at IS NULL);
|
||||
|
||||
create index if not exists "IDX_shipping_option_shipping_option_type_id"
|
||||
on shipping_option (shipping_option_type_id)
|
||||
where (deleted_at IS NULL);
|
||||
|
||||
create index if not exists "IDX_shipping_option_deleted_at"
|
||||
on shipping_option (deleted_at)
|
||||
where (deleted_at IS NOT NULL);
|
||||
|
||||
alter table shipping_option
|
||||
add constraint shipping_option_shipping_option_type_id_unique
|
||||
unique (shipping_option_type_id);
|
||||
|
||||
alter table shipping_option
|
||||
drop constraint "FK_5c58105f1752fca0f4ce69f4663";
|
||||
|
||||
alter table shipping_option
|
||||
drop constraint "FK_c951439af4c98bf2bd7fb8726cd";
|
||||
|
||||
alter table shipping_option
|
||||
drop constraint "FK_a0e206bfaed3cb63c1860917347";
|
||||
|
||||
alter table shipping_option
|
||||
add constraint shipping_option_service_zone_id_foreign
|
||||
foreign key (service_zone_id) references service_zone
|
||||
on update cascade on delete cascade;
|
||||
|
||||
alter table shipping_option
|
||||
add constraint shipping_option_shipping_profile_id_foreign
|
||||
foreign key (shipping_profile_id) references shipping_profile
|
||||
on update cascade on delete set null;
|
||||
|
||||
alter table shipping_option
|
||||
add constraint shipping_option_provider_id_foreign
|
||||
foreign key (provider_id) references fulfillment_provider
|
||||
on update cascade on delete set null;
|
||||
|
||||
alter table shipping_option
|
||||
add constraint shipping_option_shipping_option_type_id_foreign
|
||||
foreign key (shipping_option_type_id) references shipping_option_type
|
||||
on update cascade on delete cascade;
|
||||
|
||||
alter table shipping_option
|
||||
drop constraint "CHK_7a367f5901ae0a5b0df75aee38";
|
||||
|
||||
alter table shipping_option
|
||||
add constraint shipping_option_price_type_check
|
||||
check (price_type = ANY (ARRAY ['calculated'::text, 'flat'::text]));
|
||||
`)
|
||||
|
||||
this.addSql(
|
||||
'create table if not exists "shipping_option_rule" ("id" text not null, "attribute" text not null, "operator" text check ("operator" in (\'in\', \'eq\', \'ne\', \'gt\', \'gte\', \'lt\', \'lte\', \'nin\')) not null, "value" jsonb null, "shipping_option_id" text not null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "shipping_option_rule_pkey" primary key ("id"));'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_shipping_option_rule_shipping_option_id" ON "shipping_option_rule" (shipping_option_id) WHERE deleted_at IS NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_shipping_option_rule_deleted_at" ON "shipping_option_rule" (deleted_at) WHERE deleted_at IS NOT NULL;'
|
||||
)
|
||||
|
||||
this.addSql(`
|
||||
alter table fulfillment
|
||||
alter
|
||||
column id type text using id::text;
|
||||
|
||||
alter table fulfillment
|
||||
add packed_at timestamp with time zone;
|
||||
|
||||
alter table fulfillment
|
||||
alter column data drop not null;
|
||||
|
||||
alter table fulfillment
|
||||
add delivered_at timestamp with time zone;
|
||||
|
||||
alter table fulfillment
|
||||
add shipping_option_id text;
|
||||
|
||||
alter table fulfillment
|
||||
add delivery_address_id text;
|
||||
|
||||
alter table fulfillment
|
||||
alter
|
||||
column provider_id type text using provider_id::text;
|
||||
|
||||
alter table fulfillment
|
||||
add deleted_at timestamp with time zone;
|
||||
|
||||
alter table fulfillment
|
||||
alter
|
||||
column location_id type text using location_id::text;
|
||||
|
||||
alter table fulfillment
|
||||
alter column location_id set not null;
|
||||
|
||||
drop index if exists "IDX_d73e55964e0ff2db8f03807d52";
|
||||
|
||||
drop index if exists "IDX_a52e234f729db789cf473297a5";
|
||||
|
||||
drop index if exists "IDX_f129acc85e346a10eed12b86fc";
|
||||
|
||||
drop index if exists "IDX_beb35a6de60a6c4f91d5ae57e4";
|
||||
|
||||
create index if not exists "IDX_fulfillment_location_id"
|
||||
on fulfillment (location_id) where (deleted_at IS NULL);
|
||||
|
||||
create index if not exists"IDX_fulfillment_provider_id"
|
||||
on fulfillment (provider_id) where (deleted_at IS NULL);
|
||||
|
||||
create index if not exists"IDX_fulfillment_shipping_option_id"
|
||||
on fulfillment (shipping_option_id) where (deleted_at IS NULL);
|
||||
|
||||
create index if not exists"IDX_fulfillment_deleted_at"
|
||||
on fulfillment (deleted_at) where (deleted_at IS NOT NULL);
|
||||
|
||||
alter table fulfillment
|
||||
add constraint fulfillment_delivery_address_id_unique
|
||||
unique (delivery_address_id);
|
||||
|
||||
alter table fulfillment
|
||||
drop
|
||||
constraint "FK_a52e234f729db789cf473297a5c"; /* swap id */
|
||||
|
||||
alter table fulfillment
|
||||
drop
|
||||
constraint "FK_f129acc85e346a10eed12b86fca"; /* order id */
|
||||
|
||||
alter table fulfillment
|
||||
drop
|
||||
constraint "FK_beb35a6de60a6c4f91d5ae57e44"; /* provider id */
|
||||
|
||||
alter table fulfillment
|
||||
drop
|
||||
constraint "FK_d73e55964e0ff2db8f03807d52e"; /* claim id */
|
||||
|
||||
alter table fulfillment
|
||||
add constraint fulfillment_provider_id_foreign
|
||||
foreign key (provider_id) references fulfillment_provider
|
||||
on update cascade on delete set null;
|
||||
|
||||
alter table fulfillment
|
||||
add constraint fulfillment_shipping_option_id_foreign
|
||||
foreign key (shipping_option_id) references shipping_option
|
||||
on update cascade on delete set null;
|
||||
|
||||
alter table fulfillment
|
||||
add constraint fulfillment_delivery_address_id_foreign
|
||||
foreign key (delivery_address_id) references fulfillment_address
|
||||
on update cascade on delete cascade;
|
||||
`)
|
||||
|
||||
this.addSql(
|
||||
'create table if not exists "fulfillment_label" ("id" text not null, "tracking_number" text not null, "tracking_url" text not null, "label_url" text not null, "fulfillment_id" text not null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "fulfillment_label_pkey" primary key ("id"));'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_fulfillment_label_fulfillment_id" ON "fulfillment_label" (fulfillment_id) WHERE deleted_at IS NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_fulfillment_label_deleted_at" ON "fulfillment_label" (deleted_at) WHERE deleted_at IS NOT NULL;'
|
||||
)
|
||||
|
||||
this.addSql(`
|
||||
alter table fulfillment_item
|
||||
add id text not null;
|
||||
|
||||
alter table fulfillment_item
|
||||
add title text not null;
|
||||
|
||||
alter table fulfillment_item
|
||||
add sku text not null;
|
||||
|
||||
alter table fulfillment_item
|
||||
add barcode text not null;
|
||||
|
||||
alter table fulfillment_item
|
||||
alter column quantity type numeric using quantity::numeric;
|
||||
|
||||
alter table fulfillment_item
|
||||
add raw_quantity jsonb not null;
|
||||
|
||||
alter table fulfillment_item
|
||||
add line_item_id text;
|
||||
|
||||
alter table fulfillment_item
|
||||
add inventory_item_id text;
|
||||
|
||||
alter table fulfillment_item
|
||||
alter column fulfillment_id type text using fulfillment_id::text;
|
||||
|
||||
alter table fulfillment_item
|
||||
add created_at timestamp with time zone default now() not null;
|
||||
|
||||
alter table fulfillment_item
|
||||
add updated_at timestamp with time zone default now() not null;
|
||||
|
||||
alter table fulfillment_item
|
||||
add deleted_at timestamp with time zone;
|
||||
|
||||
create index if not exists "IDX_fulfillment_item_line_item_id"
|
||||
on fulfillment_item (line_item_id)
|
||||
where (deleted_at IS NULL);
|
||||
|
||||
create index if not exists "IDX_fulfillment_item_inventory_item_id"
|
||||
on fulfillment_item (inventory_item_id)
|
||||
where (deleted_at IS NULL);
|
||||
|
||||
create index if not exists "IDX_fulfillment_item_fulfillment_id"
|
||||
on fulfillment_item (fulfillment_id)
|
||||
where (deleted_at IS NULL);
|
||||
|
||||
create index if not exists "IDX_fulfillment_item_deleted_at"
|
||||
on fulfillment_item (deleted_at)
|
||||
where (deleted_at IS NOT NULL);
|
||||
|
||||
alter table fulfillment_item
|
||||
drop constraint "FK_a033f83cc6bd7701a5687ab4b38"; /* fulfillment id */
|
||||
|
||||
alter table fulfillment_item
|
||||
drop constraint "FK_e13ff60e74206b747a1896212d1"; /* item id */
|
||||
|
||||
alter table fulfillment_item
|
||||
drop constraint "PK_bc3e8a388de75db146a249922e0"; /* item id + fulfillment id PK */
|
||||
|
||||
alter table fulfillment_item
|
||||
alter column item_id drop not null;
|
||||
|
||||
alter table fulfillment_item
|
||||
add constraint fulfillment_item_fulfillment_id_foreign
|
||||
foreign key (fulfillment_id) references fulfillment
|
||||
on update cascade on delete cascade;
|
||||
|
||||
alter table "fulfillment_item" add primary key ("id");
|
||||
`)
|
||||
|
||||
this.addSql(
|
||||
'alter table if exists "service_zone" add constraint "service_zone_fulfillment_set_id_foreign" foreign key ("fulfillment_set_id") references "fulfillment_set" ("id") on update cascade on delete cascade;'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'alter table if exists "geo_zone" add constraint "geo_zone_service_zone_id_foreign" foreign key ("service_zone_id") references "service_zone" ("id") on update cascade on delete cascade;'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'alter table if exists "shipping_option_rule" add constraint "shipping_option_rule_shipping_option_id_foreign" foreign key ("shipping_option_id") references "shipping_option" ("id") on update cascade on delete cascade;'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'alter table if exists "fulfillment_label" add constraint "fulfillment_label_fulfillment_id_foreign" foreign key ("fulfillment_id") references "fulfillment" ("id") on update cascade on delete cascade;'
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* This migration is for be initial setup of the fulfillment module in the case of
|
||||
* a new database. It will create all the necessary tables and indexes.
|
||||
*/
|
||||
async function migrateUpModuleMigration(
|
||||
this: Migration20240311145700_InitialSetupMigration
|
||||
) {
|
||||
this.addSql(
|
||||
'create table if not exists "fulfillment_address" ("id" text not null, "company" text null, "first_name" text null, "last_name" text null, "address_1" text null, "address_2" text null, "city" text null, "country_code" text null, "province" text null, "postal_code" text null, "phone" text null, "metadata" jsonb null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "fulfillment_address_pkey" primary key ("id"));'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_fulfillment_address_deleted_at" ON "fulfillment_address" (deleted_at) WHERE deleted_at IS NOT NULL;'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'create table if not exists "fulfillment_provider" ("id" text not null, "is_enabled" boolean not null default true, constraint "fulfillment_provider_pkey" primary key ("id"));'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'create table if not exists "fulfillment_set" ("id" text not null, "name" text not null, "type" text not null, "metadata" jsonb null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "fulfillment_set_pkey" primary key ("id"));'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE UNIQUE INDEX IF NOT EXISTS "IDX_fulfillment_set_name_unique" ON "fulfillment_set" (name) WHERE deleted_at IS NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_fulfillment_set_deleted_at" ON "fulfillment_set" (deleted_at) WHERE deleted_at IS NOT NULL;'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'create table if not exists "service_zone" ("id" text not null, "name" text not null, "metadata" jsonb null, "fulfillment_set_id" text not null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "service_zone_pkey" primary key ("id"));'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE UNIQUE INDEX IF NOT EXISTS "IDX_service_zone_name_unique" ON "service_zone" (name) WHERE deleted_at IS NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_service_zone_fulfillment_set_id" ON "service_zone" (fulfillment_set_id) WHERE deleted_at IS NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_service_zone_deleted_at" ON "service_zone" (deleted_at) WHERE deleted_at IS NOT NULL;'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'create table if not exists "geo_zone" ("id" text not null, "type" text check ("type" in (\'country\', \'province\', \'city\', \'zip\')) not null default \'country\', "country_code" text not null, "province_code" text null, "city" text null, "service_zone_id" text not null, "postal_expression" jsonb null, "metadata" jsonb null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "geo_zone_pkey" primary key ("id"));'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_geo_zone_country_code" ON "geo_zone" (country_code) WHERE deleted_at IS NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_geo_zone_province_code" ON "geo_zone" (province_code) WHERE deleted_at IS NULL AND province_code IS NOT NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_geo_zone_city" ON "geo_zone" (city) WHERE deleted_at IS NULL AND city IS NOT NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_geo_zone_service_zone_id" ON "geo_zone" (service_zone_id) WHERE deleted_at IS NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_geo_zone_deleted_at" ON "geo_zone" (deleted_at) WHERE deleted_at IS NOT NULL;'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'create table if not exists "shipping_option_type" ("id" text not null, "label" text not null, "description" text null, "code" text not null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "shipping_option_type_pkey" primary key ("id"));'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_shipping_option_type_deleted_at" ON "shipping_option_type" (deleted_at) WHERE deleted_at IS NOT NULL;'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'create table if not exists "shipping_profile" ("id" text not null, "name" text not null, "type" text not null, "metadata" jsonb null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "shipping_profile_pkey" primary key ("id"));'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE UNIQUE INDEX IF NOT EXISTS "IDX_shipping_profile_name_unique" ON "shipping_profile" (name) WHERE deleted_at IS NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_shipping_profile_deleted_at" ON "shipping_profile" (deleted_at) WHERE deleted_at IS NOT NULL;'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'create table if not exists "shipping_option" ("id" text not null, "name" text not null, "price_type" text check ("price_type" in (\'calculated\', \'flat\')) not null default \'flat\', "service_zone_id" text not null, "shipping_profile_id" text null, "provider_id" text null, "data" jsonb null, "metadata" jsonb null, "shipping_option_type_id" text not null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "shipping_option_pkey" primary key ("id"));'
|
||||
)
|
||||
this.addSql(
|
||||
'alter table if exists "shipping_option" add constraint "shipping_option_shipping_option_type_id_unique" unique ("shipping_option_type_id");'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_shipping_option_service_zone_id" ON "shipping_option" (service_zone_id) WHERE deleted_at IS NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_shipping_option_shipping_profile_id" ON "shipping_option" (shipping_profile_id) WHERE deleted_at IS NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_shipping_option_provider_id" ON "shipping_option" (provider_id) WHERE deleted_at IS NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_shipping_option_shipping_option_type_id" ON "shipping_option" (shipping_option_type_id) WHERE deleted_at IS NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_shipping_option_deleted_at" ON "shipping_option" (deleted_at) WHERE deleted_at IS NOT NULL;'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'create table if not exists "shipping_option_rule" ("id" text not null, "attribute" text not null, "operator" text check ("operator" in (\'in\', \'eq\', \'ne\', \'gt\', \'gte\', \'lt\', \'lte\', \'nin\')) not null, "value" jsonb null, "shipping_option_id" text not null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "shipping_option_rule_pkey" primary key ("id"));'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_shipping_option_rule_shipping_option_id" ON "shipping_option_rule" (shipping_option_id) WHERE deleted_at IS NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_shipping_option_rule_deleted_at" ON "shipping_option_rule" (deleted_at) WHERE deleted_at IS NOT NULL;'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'create table if not exists "fulfillment" ("id" text not null, "location_id" text not null, "packed_at" timestamptz null, "shipped_at" timestamptz null, "delivered_at" timestamptz null, "canceled_at" timestamptz null, "data" jsonb null, "provider_id" text null, "shipping_option_id" text null, "metadata" jsonb null, "delivery_address_id" text null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "fulfillment_pkey" primary key ("id"));'
|
||||
)
|
||||
this.addSql(
|
||||
'alter table if exists "fulfillment" add constraint "fulfillment_delivery_address_id_unique" unique ("delivery_address_id");'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_fulfillment_location_id" ON "fulfillment" (location_id) WHERE deleted_at IS NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_fulfillment_provider_id" ON "fulfillment" (provider_id) WHERE deleted_at IS NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_fulfillment_shipping_option_id" ON "fulfillment" (shipping_option_id) WHERE deleted_at IS NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_fulfillment_deleted_at" ON "fulfillment" (deleted_at) WHERE deleted_at IS NOT NULL;'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'create table if not exists "fulfillment_label" ("id" text not null, "tracking_number" text not null, "tracking_url" text not null, "label_url" text not null, "fulfillment_id" text not null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "fulfillment_label_pkey" primary key ("id"));'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_fulfillment_label_fulfillment_id" ON "fulfillment_label" (fulfillment_id) WHERE deleted_at IS NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_fulfillment_label_deleted_at" ON "fulfillment_label" (deleted_at) WHERE deleted_at IS NOT NULL;'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'create table if not exists "fulfillment_item" ("id" text not null, "title" text not null, "sku" text not null, "barcode" text not null, "quantity" numeric not null, "raw_quantity" jsonb not null, "line_item_id" text null, "inventory_item_id" text null, "fulfillment_id" text not null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "fulfillment_item_pkey" primary key ("id"));'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_fulfillment_item_line_item_id" ON "fulfillment_item" (line_item_id) WHERE deleted_at IS NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_fulfillment_item_inventory_item_id" ON "fulfillment_item" (inventory_item_id) WHERE deleted_at IS NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_fulfillment_item_fulfillment_id" ON "fulfillment_item" (fulfillment_id) WHERE deleted_at IS NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_fulfillment_item_deleted_at" ON "fulfillment_item" (deleted_at) WHERE deleted_at IS NOT NULL;'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'alter table if exists "service_zone" add constraint "service_zone_fulfillment_set_id_foreign" foreign key ("fulfillment_set_id") references "fulfillment_set" ("id") on update cascade on delete cascade;'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'alter table if exists "geo_zone" add constraint "geo_zone_service_zone_id_foreign" foreign key ("service_zone_id") references "service_zone" ("id") on update cascade on delete cascade;'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'alter table if exists "shipping_option" add constraint "shipping_option_service_zone_id_foreign" foreign key ("service_zone_id") references "service_zone" ("id") on update cascade on delete cascade;'
|
||||
)
|
||||
this.addSql(
|
||||
'alter table if exists "shipping_option" add constraint "shipping_option_shipping_profile_id_foreign" foreign key ("shipping_profile_id") references "shipping_profile" ("id") on update cascade on delete set null;'
|
||||
)
|
||||
this.addSql(
|
||||
'alter table if exists "shipping_option" add constraint "shipping_option_provider_id_foreign" foreign key ("provider_id") references "fulfillment_provider" ("id") on update cascade on delete set null;'
|
||||
)
|
||||
this.addSql(
|
||||
'alter table if exists "shipping_option" add constraint "shipping_option_shipping_option_type_id_foreign" foreign key ("shipping_option_type_id") references "shipping_option_type" ("id") on update cascade on delete cascade;'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'alter table if exists "shipping_option_rule" add constraint "shipping_option_rule_shipping_option_id_foreign" foreign key ("shipping_option_id") references "shipping_option" ("id") on update cascade on delete cascade;'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'alter table if exists "fulfillment" add constraint "fulfillment_provider_id_foreign" foreign key ("provider_id") references "fulfillment_provider" ("id") on update cascade on delete set null;'
|
||||
)
|
||||
this.addSql(
|
||||
'alter table if exists "fulfillment" add constraint "fulfillment_shipping_option_id_foreign" foreign key ("shipping_option_id") references "shipping_option" ("id") on update cascade on delete set null;'
|
||||
)
|
||||
this.addSql(
|
||||
'alter table if exists "fulfillment" add constraint "fulfillment_delivery_address_id_foreign" foreign key ("delivery_address_id") references "fulfillment_address" ("id") on update cascade on delete cascade;'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'alter table if exists "fulfillment_label" add constraint "fulfillment_label_fulfillment_id_foreign" foreign key ("fulfillment_id") references "fulfillment" ("id") on update cascade on delete cascade;'
|
||||
)
|
||||
|
||||
this.addSql(
|
||||
'alter table if exists "fulfillment_item" add constraint "fulfillment_item_fulfillment_id_foreign" foreign key ("fulfillment_id") references "fulfillment" ("id") on update cascade on delete cascade;'
|
||||
)
|
||||
}
|
||||
91
packages/modules/fulfillment/src/models/address.ts
Normal file
91
packages/modules/fulfillment/src/models/address.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
import { DAL } from "@medusajs/types"
|
||||
import {
|
||||
createPsqlIndexStatementHelper,
|
||||
generateEntityId,
|
||||
} from "@medusajs/utils"
|
||||
import {
|
||||
BeforeCreate,
|
||||
Entity,
|
||||
OnInit,
|
||||
OptionalProps,
|
||||
PrimaryKey,
|
||||
Property,
|
||||
} from "@mikro-orm/core"
|
||||
|
||||
type OptionalAddressProps = DAL.SoftDeletableEntityDateColumns
|
||||
|
||||
const FulfillmentDeletedAtIndex = createPsqlIndexStatementHelper({
|
||||
tableName: "fulfillment_address",
|
||||
columns: "deleted_at",
|
||||
where: "deleted_at IS NOT NULL",
|
||||
})
|
||||
|
||||
@Entity({ tableName: "fulfillment_address" })
|
||||
export default class Address {
|
||||
[OptionalProps]: OptionalAddressProps
|
||||
|
||||
@PrimaryKey({ columnType: "text" })
|
||||
id!: string
|
||||
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
company: string | null = null
|
||||
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
first_name: string | null = null
|
||||
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
last_name: string | null = null
|
||||
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
address_1: string | null = null
|
||||
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
address_2: string | null = null
|
||||
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
city: string | null = null
|
||||
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
country_code: string | null = null
|
||||
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
province: string | null = null
|
||||
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
postal_code: string | null = null
|
||||
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
phone: string | null = null
|
||||
|
||||
@Property({ columnType: "jsonb", nullable: true })
|
||||
metadata: Record<string, unknown> | 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
|
||||
|
||||
@Property({ columnType: "timestamptz", nullable: true })
|
||||
@FulfillmentDeletedAtIndex.MikroORMIndex()
|
||||
deleted_at: Date | null = null
|
||||
|
||||
@BeforeCreate()
|
||||
onCreate() {
|
||||
this.id = generateEntityId(this.id, "fuladdr")
|
||||
}
|
||||
|
||||
@OnInit()
|
||||
onInit() {
|
||||
this.id = generateEntityId(this.id, "fuladdr")
|
||||
}
|
||||
}
|
||||
121
packages/modules/fulfillment/src/models/fulfillment-item.ts
Normal file
121
packages/modules/fulfillment/src/models/fulfillment-item.ts
Normal file
@@ -0,0 +1,121 @@
|
||||
import {
|
||||
BigNumber,
|
||||
createPsqlIndexStatementHelper,
|
||||
DALUtils,
|
||||
generateEntityId,
|
||||
MikroOrmBigNumberProperty,
|
||||
} from "@medusajs/utils"
|
||||
|
||||
import { BigNumberRawValue, DAL } from "@medusajs/types"
|
||||
import {
|
||||
BeforeCreate,
|
||||
Entity,
|
||||
Filter,
|
||||
ManyToOne,
|
||||
OnInit,
|
||||
OptionalProps,
|
||||
PrimaryKey,
|
||||
Property,
|
||||
} from "@mikro-orm/core"
|
||||
import Fulfillment from "./fulfillment"
|
||||
|
||||
type FulfillmentItemOptionalProps = DAL.SoftDeletableEntityDateColumns
|
||||
|
||||
const FulfillmentIdIndex = createPsqlIndexStatementHelper({
|
||||
tableName: "fulfillment_item",
|
||||
columns: "fulfillment_id",
|
||||
where: "deleted_at IS NULL",
|
||||
})
|
||||
|
||||
const LineItemIdIndex = createPsqlIndexStatementHelper({
|
||||
tableName: "fulfillment_item",
|
||||
columns: "line_item_id",
|
||||
where: "deleted_at IS NULL",
|
||||
})
|
||||
|
||||
const InventoryItemIdIndex = createPsqlIndexStatementHelper({
|
||||
tableName: "fulfillment_item",
|
||||
columns: "inventory_item_id",
|
||||
where: "deleted_at IS NULL",
|
||||
})
|
||||
|
||||
const FulfillmentItemDeletedAtIndex = createPsqlIndexStatementHelper({
|
||||
tableName: "fulfillment_item",
|
||||
columns: "deleted_at",
|
||||
where: "deleted_at IS NOT NULL",
|
||||
})
|
||||
|
||||
@Entity()
|
||||
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
||||
export default class FulfillmentItem {
|
||||
[OptionalProps]?: FulfillmentItemOptionalProps
|
||||
|
||||
@PrimaryKey({ columnType: "text" })
|
||||
id: string
|
||||
|
||||
@Property({ columnType: "text" })
|
||||
title: string
|
||||
|
||||
@Property({ columnType: "text" })
|
||||
sku: string
|
||||
|
||||
@Property({ columnType: "text" })
|
||||
barcode: string
|
||||
|
||||
@MikroOrmBigNumberProperty()
|
||||
quantity: BigNumber | number
|
||||
|
||||
@Property({ columnType: "jsonb" })
|
||||
raw_quantity: BigNumberRawValue
|
||||
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
@LineItemIdIndex.MikroORMIndex()
|
||||
line_item_id: string | null = null
|
||||
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
@InventoryItemIdIndex.MikroORMIndex()
|
||||
inventory_item_id: string | null = null
|
||||
|
||||
@ManyToOne(() => Fulfillment, {
|
||||
columnType: "text",
|
||||
mapToPk: true,
|
||||
fieldName: "fulfillment_id",
|
||||
onDelete: "cascade",
|
||||
})
|
||||
@FulfillmentIdIndex.MikroORMIndex()
|
||||
fulfillment_id: string
|
||||
|
||||
@ManyToOne(() => Fulfillment, { persist: false })
|
||||
fulfillment: Fulfillment
|
||||
|
||||
@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
|
||||
|
||||
@FulfillmentItemDeletedAtIndex.MikroORMIndex()
|
||||
@Property({ columnType: "timestamptz", nullable: true })
|
||||
deleted_at: Date | null = null
|
||||
|
||||
@BeforeCreate()
|
||||
onCreate() {
|
||||
this.id = generateEntityId(this.id, "fulit")
|
||||
this.fulfillment_id ??= this.fulfillment.id
|
||||
}
|
||||
|
||||
@OnInit()
|
||||
onInit() {
|
||||
this.id = generateEntityId(this.id, "fulit")
|
||||
this.fulfillment_id ??= this.fulfillment.id
|
||||
}
|
||||
}
|
||||
93
packages/modules/fulfillment/src/models/fulfillment-label.ts
Normal file
93
packages/modules/fulfillment/src/models/fulfillment-label.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
import {
|
||||
createPsqlIndexStatementHelper,
|
||||
DALUtils,
|
||||
generateEntityId,
|
||||
} from "@medusajs/utils"
|
||||
|
||||
import { DAL } from "@medusajs/types"
|
||||
import {
|
||||
BeforeCreate,
|
||||
Entity,
|
||||
Filter,
|
||||
ManyToOne,
|
||||
OnInit,
|
||||
OptionalProps,
|
||||
PrimaryKey,
|
||||
Property,
|
||||
} from "@mikro-orm/core"
|
||||
import Fulfillment from "./fulfillment"
|
||||
|
||||
type FulfillmentLabelOptionalProps = DAL.SoftDeletableEntityDateColumns
|
||||
|
||||
const FulfillmentIdIndex = createPsqlIndexStatementHelper({
|
||||
tableName: "fulfillment_label",
|
||||
columns: "fulfillment_id",
|
||||
where: "deleted_at IS NULL",
|
||||
})
|
||||
|
||||
const DeletedAtIndex = createPsqlIndexStatementHelper({
|
||||
tableName: "fulfillment_label",
|
||||
columns: "deleted_at",
|
||||
where: "deleted_at IS NOT NULL",
|
||||
})
|
||||
|
||||
@Entity()
|
||||
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
||||
export default class FulfillmentLabel {
|
||||
[OptionalProps]?: FulfillmentLabelOptionalProps
|
||||
|
||||
@PrimaryKey({ columnType: "text" })
|
||||
id: string
|
||||
|
||||
@Property({ columnType: "text" })
|
||||
tracking_number: string
|
||||
|
||||
@Property({ columnType: "text" })
|
||||
tracking_url: string
|
||||
|
||||
@Property({ columnType: "text" })
|
||||
label_url: string
|
||||
|
||||
@ManyToOne(() => Fulfillment, {
|
||||
columnType: "text",
|
||||
mapToPk: true,
|
||||
fieldName: "fulfillment_id",
|
||||
onDelete: "cascade",
|
||||
})
|
||||
@FulfillmentIdIndex.MikroORMIndex()
|
||||
fulfillment_id: string
|
||||
|
||||
@ManyToOne(() => Fulfillment, { persist: false })
|
||||
fulfillment: Fulfillment
|
||||
|
||||
@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 })
|
||||
@DeletedAtIndex.MikroORMIndex()
|
||||
deleted_at: Date | null = null
|
||||
|
||||
@BeforeCreate()
|
||||
onCreate() {
|
||||
this.id = generateEntityId(this.id, "fulla")
|
||||
this.fulfillment_id ??= this.fulfillment.id
|
||||
}
|
||||
|
||||
@OnInit()
|
||||
onInit() {
|
||||
this.id = generateEntityId(this.id, "fulla")
|
||||
this.fulfillment_id ??= this.fulfillment.id
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import { generateEntityId } from "@medusajs/utils"
|
||||
import {
|
||||
BeforeCreate,
|
||||
Entity,
|
||||
OnInit,
|
||||
PrimaryKey,
|
||||
Property,
|
||||
} from "@mikro-orm/core"
|
||||
|
||||
@Entity()
|
||||
export default class FulfillmentProvider {
|
||||
@PrimaryKey({ columnType: "text" })
|
||||
id: string
|
||||
|
||||
@Property({ columnType: "boolean", defaultRaw: "true" })
|
||||
is_enabled: boolean = true
|
||||
|
||||
@BeforeCreate()
|
||||
onCreate() {
|
||||
this.id = generateEntityId(this.id, "serpro")
|
||||
}
|
||||
|
||||
@OnInit()
|
||||
onInit() {
|
||||
this.id = generateEntityId(this.id, "serpro")
|
||||
}
|
||||
}
|
||||
89
packages/modules/fulfillment/src/models/fulfillment-set.ts
Normal file
89
packages/modules/fulfillment/src/models/fulfillment-set.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import {
|
||||
createPsqlIndexStatementHelper,
|
||||
DALUtils,
|
||||
generateEntityId,
|
||||
} from "@medusajs/utils"
|
||||
|
||||
import { DAL } from "@medusajs/types"
|
||||
import {
|
||||
BeforeCreate,
|
||||
Cascade,
|
||||
Collection,
|
||||
Entity,
|
||||
Filter,
|
||||
OneToMany,
|
||||
OnInit,
|
||||
OptionalProps,
|
||||
PrimaryKey,
|
||||
Property,
|
||||
} from "@mikro-orm/core"
|
||||
import ServiceZone from "./service-zone"
|
||||
|
||||
type FulfillmentSetOptionalProps = DAL.SoftDeletableEntityDateColumns
|
||||
|
||||
const DeletedAtIndex = createPsqlIndexStatementHelper({
|
||||
tableName: "fulfillment_set",
|
||||
columns: "deleted_at",
|
||||
where: "deleted_at IS NOT NULL",
|
||||
})
|
||||
|
||||
const NameIndex = createPsqlIndexStatementHelper({
|
||||
tableName: "fulfillment_set",
|
||||
columns: "name",
|
||||
unique: true,
|
||||
where: "deleted_at IS NULL",
|
||||
})
|
||||
|
||||
@Entity()
|
||||
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
||||
export default class FulfillmentSet {
|
||||
[OptionalProps]?: FulfillmentSetOptionalProps
|
||||
|
||||
@PrimaryKey({ columnType: "text" })
|
||||
id: string
|
||||
|
||||
@Property({ columnType: "text" })
|
||||
@NameIndex.MikroORMIndex()
|
||||
name: string
|
||||
|
||||
@Property({ columnType: "text" })
|
||||
type: string
|
||||
|
||||
@Property({ columnType: "jsonb", nullable: true })
|
||||
metadata: Record<string, unknown> | null = null
|
||||
|
||||
@OneToMany(() => ServiceZone, "fulfillment_set", {
|
||||
cascade: [Cascade.PERSIST, "soft-remove"] as any,
|
||||
orphanRemoval: true,
|
||||
})
|
||||
service_zones = new Collection<ServiceZone>(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 })
|
||||
@DeletedAtIndex.MikroORMIndex()
|
||||
deleted_at: Date | null = null
|
||||
|
||||
@BeforeCreate()
|
||||
onCreate() {
|
||||
this.id = generateEntityId(this.id, "fuset")
|
||||
}
|
||||
|
||||
@OnInit()
|
||||
onInit() {
|
||||
this.id = generateEntityId(this.id, "fuset")
|
||||
}
|
||||
}
|
||||
173
packages/modules/fulfillment/src/models/fulfillment.ts
Normal file
173
packages/modules/fulfillment/src/models/fulfillment.ts
Normal file
@@ -0,0 +1,173 @@
|
||||
import {
|
||||
createPsqlIndexStatementHelper,
|
||||
DALUtils,
|
||||
generateEntityId,
|
||||
} from "@medusajs/utils"
|
||||
|
||||
import { DAL } from "@medusajs/types"
|
||||
import {
|
||||
BeforeCreate,
|
||||
Cascade,
|
||||
Collection,
|
||||
Entity,
|
||||
Filter,
|
||||
ManyToOne,
|
||||
OneToMany,
|
||||
OneToOne,
|
||||
OnInit,
|
||||
OptionalProps,
|
||||
PrimaryKey,
|
||||
Property,
|
||||
} from "@mikro-orm/core"
|
||||
import Address from "./address"
|
||||
import FulfillmentItem from "./fulfillment-item"
|
||||
import FulfillmentLabel from "./fulfillment-label"
|
||||
import FulfillmentProvider from "./fulfillment-provider"
|
||||
import ShippingOption from "./shipping-option"
|
||||
|
||||
type FulfillmentOptionalProps = DAL.SoftDeletableEntityDateColumns
|
||||
|
||||
const FulfillmentDeletedAtIndex = createPsqlIndexStatementHelper({
|
||||
tableName: "fulfillment",
|
||||
columns: "deleted_at",
|
||||
where: "deleted_at IS NOT NULL",
|
||||
})
|
||||
|
||||
const FulfillmentProviderIdIndex = createPsqlIndexStatementHelper({
|
||||
tableName: "fulfillment",
|
||||
columns: "provider_id",
|
||||
where: "deleted_at IS NULL",
|
||||
})
|
||||
|
||||
const FulfillmentLocationIdIndex = createPsqlIndexStatementHelper({
|
||||
tableName: "fulfillment",
|
||||
columns: "location_id",
|
||||
where: "deleted_at IS NULL",
|
||||
})
|
||||
|
||||
const FulfillmentShippingOptionIdIndex = createPsqlIndexStatementHelper({
|
||||
tableName: "fulfillment",
|
||||
columns: "shipping_option_id",
|
||||
where: "deleted_at IS NULL",
|
||||
})
|
||||
|
||||
@Entity()
|
||||
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
||||
export default class Fulfillment {
|
||||
[OptionalProps]?: FulfillmentOptionalProps
|
||||
|
||||
@PrimaryKey({ columnType: "text" })
|
||||
id: string
|
||||
|
||||
@Property({ columnType: "text" })
|
||||
@FulfillmentLocationIdIndex.MikroORMIndex()
|
||||
location_id: string
|
||||
|
||||
@Property({
|
||||
columnType: "timestamptz",
|
||||
nullable: true,
|
||||
})
|
||||
packed_at: Date | null = null
|
||||
|
||||
@Property({
|
||||
columnType: "timestamptz",
|
||||
nullable: true,
|
||||
})
|
||||
shipped_at: Date | null = null
|
||||
|
||||
@Property({
|
||||
columnType: "timestamptz",
|
||||
nullable: true,
|
||||
})
|
||||
delivered_at: Date | null = null
|
||||
|
||||
@Property({
|
||||
columnType: "timestamptz",
|
||||
nullable: true,
|
||||
})
|
||||
canceled_at: Date | null = null
|
||||
|
||||
@Property({ columnType: "jsonb", nullable: true })
|
||||
data: Record<string, unknown> | null = null
|
||||
|
||||
@ManyToOne(() => FulfillmentProvider, {
|
||||
columnType: "text",
|
||||
fieldName: "provider_id",
|
||||
mapToPk: true,
|
||||
nullable: true,
|
||||
onDelete: "set null",
|
||||
})
|
||||
@FulfillmentProviderIdIndex.MikroORMIndex()
|
||||
provider_id: string
|
||||
|
||||
@ManyToOne(() => ShippingOption, {
|
||||
columnType: "text",
|
||||
fieldName: "shipping_option_id",
|
||||
nullable: true,
|
||||
mapToPk: true,
|
||||
onDelete: "set null",
|
||||
})
|
||||
@FulfillmentShippingOptionIdIndex.MikroORMIndex()
|
||||
shipping_option_id: string | null = null
|
||||
|
||||
@Property({ columnType: "jsonb", nullable: true })
|
||||
metadata: Record<string, unknown> | null = null
|
||||
|
||||
@ManyToOne(() => ShippingOption, { persist: false })
|
||||
shipping_option: ShippingOption | null
|
||||
|
||||
@ManyToOne(() => FulfillmentProvider, { persist: false })
|
||||
provider: FulfillmentProvider
|
||||
|
||||
@OneToOne({
|
||||
entity: () => Address,
|
||||
owner: true,
|
||||
cascade: [Cascade.PERSIST, "soft-remove"] as any,
|
||||
nullable: true,
|
||||
onDelete: "cascade",
|
||||
})
|
||||
delivery_address!: Address
|
||||
|
||||
@OneToMany(() => FulfillmentItem, (item) => item.fulfillment, {
|
||||
cascade: [Cascade.PERSIST, "soft-remove"] as any,
|
||||
orphanRemoval: true,
|
||||
})
|
||||
items = new Collection<FulfillmentItem>(this)
|
||||
|
||||
@OneToMany(() => FulfillmentLabel, (label) => label.fulfillment, {
|
||||
cascade: [Cascade.PERSIST, "soft-remove"] as any,
|
||||
orphanRemoval: true,
|
||||
})
|
||||
labels = new Collection<FulfillmentLabel>(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
|
||||
|
||||
@FulfillmentDeletedAtIndex.MikroORMIndex()
|
||||
@Property({ columnType: "timestamptz", nullable: true })
|
||||
deleted_at: Date | null = null
|
||||
|
||||
@BeforeCreate()
|
||||
onCreate() {
|
||||
this.id = generateEntityId(this.id, "ful")
|
||||
this.provider_id ??= this.provider_id ?? this.provider?.id
|
||||
}
|
||||
|
||||
@OnInit()
|
||||
onInit() {
|
||||
this.id = generateEntityId(this.id, "ful")
|
||||
this.provider_id ??= this.provider_id ?? this.provider?.id
|
||||
}
|
||||
}
|
||||
127
packages/modules/fulfillment/src/models/geo-zone.ts
Normal file
127
packages/modules/fulfillment/src/models/geo-zone.ts
Normal file
@@ -0,0 +1,127 @@
|
||||
import {
|
||||
createPsqlIndexStatementHelper,
|
||||
DALUtils,
|
||||
generateEntityId,
|
||||
GeoZoneType,
|
||||
} from "@medusajs/utils"
|
||||
|
||||
import { DAL } from "@medusajs/types"
|
||||
import {
|
||||
BeforeCreate,
|
||||
Entity,
|
||||
Enum,
|
||||
Filter,
|
||||
ManyToOne,
|
||||
OnInit,
|
||||
OptionalProps,
|
||||
PrimaryKey,
|
||||
Property,
|
||||
} from "@mikro-orm/core"
|
||||
import ServiceZone from "./service-zone"
|
||||
|
||||
type GeoZoneOptionalProps = DAL.SoftDeletableEntityDateColumns
|
||||
|
||||
const DeletedAtIndex = createPsqlIndexStatementHelper({
|
||||
tableName: "geo_zone",
|
||||
columns: "deleted_at",
|
||||
where: "deleted_at IS NOT NULL",
|
||||
})
|
||||
|
||||
const CountryCodeIndex = createPsqlIndexStatementHelper({
|
||||
tableName: "geo_zone",
|
||||
columns: "country_code",
|
||||
where: "deleted_at IS NULL",
|
||||
})
|
||||
|
||||
const ProvinceCodeIndex = createPsqlIndexStatementHelper({
|
||||
tableName: "geo_zone",
|
||||
columns: "province_code",
|
||||
where: "deleted_at IS NULL AND province_code IS NOT NULL",
|
||||
})
|
||||
|
||||
const CityIndex = createPsqlIndexStatementHelper({
|
||||
tableName: "geo_zone",
|
||||
columns: "city",
|
||||
where: "deleted_at IS NULL AND city IS NOT NULL",
|
||||
})
|
||||
|
||||
const ServiceZoneIdIndex = createPsqlIndexStatementHelper({
|
||||
tableName: "geo_zone",
|
||||
columns: "service_zone_id",
|
||||
where: "deleted_at IS NULL",
|
||||
})
|
||||
|
||||
@Entity()
|
||||
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
||||
export default class GeoZone {
|
||||
[OptionalProps]?: GeoZoneOptionalProps
|
||||
|
||||
@PrimaryKey({ columnType: "text" })
|
||||
id: string
|
||||
|
||||
@Enum({ items: () => GeoZoneType, default: GeoZoneType.COUNTRY })
|
||||
type: GeoZoneType
|
||||
|
||||
@CountryCodeIndex.MikroORMIndex()
|
||||
@Property({ columnType: "text" })
|
||||
country_code: string
|
||||
|
||||
@ProvinceCodeIndex.MikroORMIndex()
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
province_code: string | null = null
|
||||
|
||||
@CityIndex.MikroORMIndex()
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
city: string | null = null
|
||||
|
||||
@ManyToOne(() => ServiceZone, {
|
||||
type: "text",
|
||||
mapToPk: true,
|
||||
fieldName: "service_zone_id",
|
||||
onDelete: "cascade",
|
||||
})
|
||||
@ServiceZoneIdIndex.MikroORMIndex()
|
||||
service_zone_id: string
|
||||
|
||||
@Property({ columnType: "jsonb", nullable: true })
|
||||
postal_expression: Record<string, unknown> | null = null
|
||||
|
||||
@Property({ columnType: "jsonb", nullable: true })
|
||||
metadata: Record<string, unknown> | null = null
|
||||
|
||||
@ManyToOne(() => ServiceZone, {
|
||||
persist: false,
|
||||
})
|
||||
service_zone: ServiceZone
|
||||
|
||||
@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
|
||||
|
||||
@DeletedAtIndex.MikroORMIndex()
|
||||
@Property({ columnType: "timestamptz", nullable: true })
|
||||
deleted_at: Date | null = null
|
||||
|
||||
@BeforeCreate()
|
||||
onCreate() {
|
||||
this.id = generateEntityId(this.id, " fgz")
|
||||
this.service_zone_id ??= this.service_zone?.id
|
||||
}
|
||||
|
||||
@OnInit()
|
||||
onInit() {
|
||||
this.id = generateEntityId(this.id, "fgz")
|
||||
this.service_zone_id ??= this.service_zone?.id
|
||||
}
|
||||
}
|
||||
13
packages/modules/fulfillment/src/models/index.ts
Normal file
13
packages/modules/fulfillment/src/models/index.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
export { default as Address } from "./address"
|
||||
export { default as Fulfillment } from "./fulfillment"
|
||||
export { default as FulfillmentItem } from "./fulfillment-item"
|
||||
export { default as FulfillmentLabel } from "./fulfillment-label"
|
||||
export { default as FulfillmentProvider } from "./fulfillment-provider"
|
||||
export { default as FulfillmentSet } from "./fulfillment-set"
|
||||
export { default as GeoZone } from "./geo-zone"
|
||||
export { default as ServiceZone } from "./service-zone"
|
||||
export { default as ShippingOption } from "./shipping-option"
|
||||
export { default as ShippingOptionRule } from "./shipping-option-rule"
|
||||
export { default as ShippingOptionType } from "./shipping-option-type"
|
||||
export { default as ShippingProfile } from "./shipping-profile"
|
||||
|
||||
125
packages/modules/fulfillment/src/models/service-zone.ts
Normal file
125
packages/modules/fulfillment/src/models/service-zone.ts
Normal file
@@ -0,0 +1,125 @@
|
||||
import {
|
||||
createPsqlIndexStatementHelper,
|
||||
DALUtils,
|
||||
generateEntityId,
|
||||
} from "@medusajs/utils"
|
||||
|
||||
import { DAL } from "@medusajs/types"
|
||||
import {
|
||||
BeforeCreate,
|
||||
Cascade,
|
||||
Collection,
|
||||
Entity,
|
||||
Filter,
|
||||
Index,
|
||||
ManyToOne,
|
||||
OneToMany,
|
||||
OnInit,
|
||||
OptionalProps,
|
||||
PrimaryKey,
|
||||
Property,
|
||||
} from "@mikro-orm/core"
|
||||
import FulfillmentSet from "./fulfillment-set"
|
||||
import GeoZone from "./geo-zone"
|
||||
import ShippingOption from "./shipping-option"
|
||||
|
||||
type ServiceZoneOptionalProps = DAL.SoftDeletableEntityDateColumns
|
||||
|
||||
const deletedAtIndexName = "IDX_service_zone_deleted_at"
|
||||
const deletedAtIndexStatement = createPsqlIndexStatementHelper({
|
||||
name: deletedAtIndexName,
|
||||
tableName: "service_zone",
|
||||
columns: "deleted_at",
|
||||
where: "deleted_at IS NOT NULL",
|
||||
}).expression
|
||||
|
||||
const NameIndex = createPsqlIndexStatementHelper({
|
||||
tableName: "service_zone",
|
||||
columns: "name",
|
||||
unique: true,
|
||||
where: "deleted_at IS NULL",
|
||||
})
|
||||
|
||||
const FulfillmentSetIdIndex = createPsqlIndexStatementHelper({
|
||||
tableName: "service_zone",
|
||||
columns: "fulfillment_set_id",
|
||||
where: "deleted_at IS NULL",
|
||||
})
|
||||
|
||||
@Entity()
|
||||
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
||||
export default class ServiceZone {
|
||||
[OptionalProps]?: ServiceZoneOptionalProps
|
||||
|
||||
@PrimaryKey({ columnType: "text" })
|
||||
id: string
|
||||
|
||||
@Property({ columnType: "text" })
|
||||
@NameIndex.MikroORMIndex()
|
||||
name: string
|
||||
|
||||
@Property({ columnType: "jsonb", nullable: true })
|
||||
metadata: Record<string, unknown> | null = null
|
||||
|
||||
@ManyToOne(() => FulfillmentSet, {
|
||||
type: "text",
|
||||
mapToPk: true,
|
||||
fieldName: "fulfillment_set_id",
|
||||
onDelete: "cascade",
|
||||
})
|
||||
@FulfillmentSetIdIndex.MikroORMIndex()
|
||||
fulfillment_set_id: string
|
||||
|
||||
@ManyToOne(() => FulfillmentSet, { persist: false })
|
||||
fulfillment_set: FulfillmentSet
|
||||
|
||||
@OneToMany(() => GeoZone, "service_zone", {
|
||||
cascade: [Cascade.PERSIST, "soft-remove"] as any,
|
||||
orphanRemoval: true,
|
||||
})
|
||||
geo_zones = new Collection<GeoZone>(this)
|
||||
|
||||
@OneToMany(
|
||||
() => ShippingOption,
|
||||
(shippingOption) => shippingOption.service_zone,
|
||||
{
|
||||
cascade: [Cascade.PERSIST, "soft-remove"] as any,
|
||||
orphanRemoval: true,
|
||||
}
|
||||
)
|
||||
shipping_options = new Collection<ShippingOption>(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
|
||||
|
||||
@Index({
|
||||
name: deletedAtIndexName,
|
||||
expression: deletedAtIndexStatement,
|
||||
})
|
||||
@Property({ columnType: "timestamptz", nullable: true })
|
||||
deleted_at: Date | null = null
|
||||
|
||||
@BeforeCreate()
|
||||
onCreate() {
|
||||
this.id = generateEntityId(this.id, "serzo")
|
||||
this.fulfillment_set_id ??= this.fulfillment_set?.id
|
||||
}
|
||||
|
||||
@OnInit()
|
||||
onInit() {
|
||||
this.id = generateEntityId(this.id, "serzo")
|
||||
this.fulfillment_set_id ??= this.fulfillment_set?.id
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
import { DAL } from "@medusajs/types"
|
||||
import {
|
||||
createPsqlIndexStatementHelper,
|
||||
DALUtils,
|
||||
generateEntityId,
|
||||
RuleOperator,
|
||||
} from "@medusajs/utils"
|
||||
import {
|
||||
BeforeCreate,
|
||||
Entity,
|
||||
Enum,
|
||||
Filter,
|
||||
ManyToOne,
|
||||
OnInit,
|
||||
OptionalProps,
|
||||
PrimaryKey,
|
||||
Property,
|
||||
} from "@mikro-orm/core"
|
||||
import ShippingOption from "./shipping-option"
|
||||
|
||||
type ShippingOptionRuleOptionalProps = DAL.SoftDeletableEntityDateColumns
|
||||
|
||||
const DeletedAtIndex = createPsqlIndexStatementHelper({
|
||||
tableName: "shipping_option_rule",
|
||||
columns: "deleted_at",
|
||||
where: "deleted_at IS NOT NULL",
|
||||
})
|
||||
|
||||
const ShippingOptionIdIndex = createPsqlIndexStatementHelper({
|
||||
tableName: "shipping_option_rule",
|
||||
columns: "shipping_option_id",
|
||||
where: "deleted_at IS NULL",
|
||||
})
|
||||
|
||||
@Entity()
|
||||
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
||||
export default class ShippingOptionRule {
|
||||
[OptionalProps]?: ShippingOptionRuleOptionalProps
|
||||
|
||||
@PrimaryKey({ columnType: "text" })
|
||||
id: string
|
||||
|
||||
@Property({ columnType: "text" })
|
||||
attribute: string
|
||||
|
||||
@Enum({
|
||||
items: () => Object.values(RuleOperator),
|
||||
columnType: "text",
|
||||
})
|
||||
operator: Lowercase<keyof typeof RuleOperator>
|
||||
|
||||
@Property({ columnType: "jsonb", nullable: true })
|
||||
value: string | string[] | null = null
|
||||
|
||||
@ManyToOne(() => ShippingOption, {
|
||||
type: "text",
|
||||
mapToPk: true,
|
||||
fieldName: "shipping_option_id",
|
||||
onDelete: "cascade",
|
||||
})
|
||||
@ShippingOptionIdIndex.MikroORMIndex()
|
||||
shipping_option_id: string
|
||||
|
||||
@ManyToOne(() => ShippingOption, {
|
||||
persist: false,
|
||||
})
|
||||
shipping_option: ShippingOption
|
||||
|
||||
@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
|
||||
|
||||
@DeletedAtIndex.MikroORMIndex()
|
||||
@Property({ columnType: "timestamptz", nullable: true })
|
||||
deleted_at: Date | null = null
|
||||
|
||||
@BeforeCreate()
|
||||
onCreate() {
|
||||
this.id = generateEntityId(this.id, "sorul")
|
||||
this.shipping_option_id ??= this.shipping_option?.id
|
||||
}
|
||||
|
||||
@OnInit()
|
||||
onInit() {
|
||||
this.id = generateEntityId(this.id, "sorul")
|
||||
this.shipping_option_id ??= this.shipping_option?.id
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
import {
|
||||
createPsqlIndexStatementHelper,
|
||||
DALUtils,
|
||||
generateEntityId,
|
||||
} from "@medusajs/utils"
|
||||
|
||||
import { DAL } from "@medusajs/types"
|
||||
import {
|
||||
BeforeCreate,
|
||||
Entity,
|
||||
Filter,
|
||||
OneToOne,
|
||||
OnInit,
|
||||
OptionalProps,
|
||||
PrimaryKey,
|
||||
Property,
|
||||
} from "@mikro-orm/core"
|
||||
import ShippingOption from "./shipping-option"
|
||||
|
||||
type ShippingOptionTypeOptionalProps = DAL.SoftDeletableEntityDateColumns
|
||||
|
||||
const DeletedAtIndex = createPsqlIndexStatementHelper({
|
||||
tableName: "shipping_option_type",
|
||||
columns: "deleted_at",
|
||||
where: "deleted_at IS NOT NULL",
|
||||
})
|
||||
|
||||
const ShippingOptionIdIndex = createPsqlIndexStatementHelper({
|
||||
tableName: "shipping_option_type",
|
||||
columns: "shipping_option_id",
|
||||
where: "deleted_at IS NULL",
|
||||
})
|
||||
|
||||
@Entity()
|
||||
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
||||
export default class ShippingOptionType {
|
||||
[OptionalProps]?: ShippingOptionTypeOptionalProps
|
||||
|
||||
@PrimaryKey({ columnType: "text" })
|
||||
id: string
|
||||
|
||||
@Property({ columnType: "text" })
|
||||
label: string
|
||||
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
description: string | null = null
|
||||
|
||||
@Property({ columnType: "text" })
|
||||
code: string
|
||||
|
||||
@OneToOne(() => ShippingOption, (so) => so.type, {
|
||||
type: "text",
|
||||
onDelete: "cascade",
|
||||
})
|
||||
shipping_option: ShippingOption
|
||||
|
||||
@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
|
||||
|
||||
@DeletedAtIndex.MikroORMIndex()
|
||||
@Property({ columnType: "timestamptz", nullable: true })
|
||||
deleted_at: Date | null = null
|
||||
|
||||
@BeforeCreate()
|
||||
onCreate() {
|
||||
this.id = generateEntityId(this.id, "sotype")
|
||||
}
|
||||
|
||||
@OnInit()
|
||||
onInit() {
|
||||
this.id = generateEntityId(this.id, "sotype")
|
||||
}
|
||||
}
|
||||
179
packages/modules/fulfillment/src/models/shipping-option.ts
Normal file
179
packages/modules/fulfillment/src/models/shipping-option.ts
Normal file
@@ -0,0 +1,179 @@
|
||||
import {
|
||||
createPsqlIndexStatementHelper,
|
||||
DALUtils,
|
||||
generateEntityId,
|
||||
ShippingOptionPriceType,
|
||||
} from "@medusajs/utils"
|
||||
|
||||
import { DAL } from "@medusajs/types"
|
||||
import {
|
||||
BeforeCreate,
|
||||
Cascade,
|
||||
Collection,
|
||||
Entity,
|
||||
Enum,
|
||||
Filter,
|
||||
ManyToOne,
|
||||
OneToMany,
|
||||
OneToOne,
|
||||
OnInit,
|
||||
OptionalProps,
|
||||
PrimaryKey,
|
||||
Property,
|
||||
} from "@mikro-orm/core"
|
||||
import Fulfillment from "./fulfillment"
|
||||
import FulfillmentProvider from "./fulfillment-provider"
|
||||
import ServiceZone from "./service-zone"
|
||||
import ShippingOptionRule from "./shipping-option-rule"
|
||||
import ShippingOptionType from "./shipping-option-type"
|
||||
import ShippingProfile from "./shipping-profile"
|
||||
|
||||
type ShippingOptionOptionalProps = DAL.SoftDeletableEntityDateColumns
|
||||
|
||||
const DeletedAtIndex = createPsqlIndexStatementHelper({
|
||||
tableName: "shipping_option",
|
||||
columns: "deleted_at",
|
||||
where: "deleted_at IS NOT NULL",
|
||||
})
|
||||
|
||||
const ServiceZoneIdIndex = createPsqlIndexStatementHelper({
|
||||
tableName: "shipping_option",
|
||||
columns: "service_zone_id",
|
||||
where: "deleted_at IS NULL",
|
||||
})
|
||||
|
||||
const ShippingProfileIdIndex = createPsqlIndexStatementHelper({
|
||||
tableName: "shipping_option",
|
||||
columns: "shipping_profile_id",
|
||||
where: "deleted_at IS NULL",
|
||||
})
|
||||
|
||||
const FulfillmentProviderIdIndex = createPsqlIndexStatementHelper({
|
||||
tableName: "shipping_option",
|
||||
columns: "provider_id",
|
||||
where: "deleted_at IS NULL",
|
||||
})
|
||||
|
||||
const ShippingOptionTypeIdIndex = createPsqlIndexStatementHelper({
|
||||
tableName: "shipping_option",
|
||||
columns: "shipping_option_type_id",
|
||||
where: "deleted_at IS NULL",
|
||||
})
|
||||
|
||||
@Entity()
|
||||
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
||||
export default class ShippingOption {
|
||||
[OptionalProps]?: ShippingOptionOptionalProps
|
||||
|
||||
@PrimaryKey({ columnType: "text" })
|
||||
id: string
|
||||
|
||||
@Property({ columnType: "text" })
|
||||
name: string
|
||||
|
||||
@Enum({
|
||||
items: () => ShippingOptionPriceType,
|
||||
default: ShippingOptionPriceType.FLAT,
|
||||
})
|
||||
price_type: ShippingOptionPriceType
|
||||
|
||||
@ManyToOne(() => ServiceZone, {
|
||||
type: "text",
|
||||
fieldName: "service_zone_id",
|
||||
mapToPk: true,
|
||||
onDelete: "cascade",
|
||||
})
|
||||
@ServiceZoneIdIndex.MikroORMIndex()
|
||||
service_zone_id: string
|
||||
|
||||
@ManyToOne(() => ShippingProfile, {
|
||||
type: "text",
|
||||
fieldName: "shipping_profile_id",
|
||||
mapToPk: true,
|
||||
nullable: true,
|
||||
onDelete: "set null",
|
||||
})
|
||||
@ShippingProfileIdIndex.MikroORMIndex()
|
||||
shipping_profile_id: string | null
|
||||
|
||||
@ManyToOne(() => FulfillmentProvider, {
|
||||
type: "text",
|
||||
fieldName: "provider_id",
|
||||
mapToPk: true,
|
||||
nullable: true,
|
||||
})
|
||||
@FulfillmentProviderIdIndex.MikroORMIndex()
|
||||
provider_id: string
|
||||
|
||||
@Property({ columnType: "text", persist: false })
|
||||
@ShippingOptionTypeIdIndex.MikroORMIndex()
|
||||
shipping_option_type_id: string | null = null
|
||||
|
||||
@Property({ columnType: "jsonb", nullable: true })
|
||||
data: Record<string, unknown> | null = null
|
||||
|
||||
@Property({ columnType: "jsonb", nullable: true })
|
||||
metadata: Record<string, unknown> | null = null
|
||||
|
||||
@ManyToOne(() => ServiceZone, { persist: false })
|
||||
service_zone: ServiceZone
|
||||
|
||||
@ManyToOne(() => ShippingProfile, {
|
||||
persist: false,
|
||||
})
|
||||
shipping_profile: ShippingProfile | null
|
||||
|
||||
@ManyToOne(() => FulfillmentProvider, {
|
||||
persist: false,
|
||||
})
|
||||
provider: FulfillmentProvider | null
|
||||
|
||||
@OneToOne(() => ShippingOptionType, (so) => so.shipping_option, {
|
||||
owner: true,
|
||||
cascade: [Cascade.PERSIST, "soft-remove"] as any,
|
||||
orphanRemoval: true,
|
||||
fieldName: "shipping_option_type_id",
|
||||
onDelete: "cascade",
|
||||
})
|
||||
type: ShippingOptionType
|
||||
|
||||
@OneToMany(() => ShippingOptionRule, "shipping_option", {
|
||||
cascade: [Cascade.PERSIST, "soft-remove"] as any,
|
||||
orphanRemoval: true,
|
||||
})
|
||||
rules = new Collection<ShippingOptionRule>(this)
|
||||
|
||||
@OneToMany(() => Fulfillment, (fulfillment) => fulfillment.shipping_option)
|
||||
fulfillments = new Collection<Fulfillment>(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
|
||||
|
||||
@DeletedAtIndex.MikroORMIndex()
|
||||
@Property({ columnType: "timestamptz", nullable: true })
|
||||
deleted_at: Date | null = null
|
||||
|
||||
@BeforeCreate()
|
||||
onCreate() {
|
||||
this.id = generateEntityId(this.id, "so")
|
||||
this.shipping_option_type_id ??= this.type?.id
|
||||
}
|
||||
|
||||
@OnInit()
|
||||
onInit() {
|
||||
this.id = generateEntityId(this.id, "so")
|
||||
this.shipping_option_type_id ??= this.type?.id
|
||||
}
|
||||
}
|
||||
91
packages/modules/fulfillment/src/models/shipping-profile.ts
Normal file
91
packages/modules/fulfillment/src/models/shipping-profile.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
import {
|
||||
createPsqlIndexStatementHelper,
|
||||
DALUtils,
|
||||
generateEntityId,
|
||||
Searchable,
|
||||
} from "@medusajs/utils"
|
||||
|
||||
import { DAL } from "@medusajs/types"
|
||||
import {
|
||||
BeforeCreate,
|
||||
Collection,
|
||||
Entity,
|
||||
Filter,
|
||||
OneToMany,
|
||||
OnInit,
|
||||
OptionalProps,
|
||||
PrimaryKey,
|
||||
Property,
|
||||
} from "@mikro-orm/core"
|
||||
import ShippingOption from "./shipping-option"
|
||||
|
||||
type ShippingProfileOptionalProps = DAL.SoftDeletableEntityDateColumns
|
||||
|
||||
const DeletedAtIndex = createPsqlIndexStatementHelper({
|
||||
tableName: "shipping_profile",
|
||||
columns: "deleted_at",
|
||||
where: "deleted_at IS NOT NULL",
|
||||
})
|
||||
|
||||
const ShippingProfileTypeIndex = createPsqlIndexStatementHelper({
|
||||
tableName: "shipping_profile",
|
||||
columns: "name",
|
||||
unique: true,
|
||||
where: "deleted_at IS NULL",
|
||||
})
|
||||
|
||||
@Entity()
|
||||
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
||||
export default class ShippingProfile {
|
||||
[OptionalProps]?: ShippingProfileOptionalProps
|
||||
|
||||
@PrimaryKey({ columnType: "text" })
|
||||
id: string
|
||||
|
||||
@Searchable()
|
||||
@Property({ columnType: "text" })
|
||||
@ShippingProfileTypeIndex.MikroORMIndex()
|
||||
name: string
|
||||
|
||||
@Searchable()
|
||||
@Property({ columnType: "text" })
|
||||
type: string
|
||||
|
||||
@OneToMany(
|
||||
() => ShippingOption,
|
||||
(shippingOption) => shippingOption.shipping_profile
|
||||
)
|
||||
shipping_options = new Collection<ShippingOption>(this)
|
||||
|
||||
@Property({ columnType: "jsonb", nullable: true })
|
||||
metadata: Record<string, unknown> | 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
|
||||
|
||||
@DeletedAtIndex.MikroORMIndex()
|
||||
@Property({ columnType: "timestamptz", nullable: true })
|
||||
deleted_at: Date | null = null
|
||||
|
||||
@BeforeCreate()
|
||||
onCreate() {
|
||||
this.id = generateEntityId(this.id, "sp")
|
||||
}
|
||||
|
||||
@OnInit()
|
||||
onInit() {
|
||||
this.id = generateEntityId(this.id, "sp")
|
||||
}
|
||||
}
|
||||
44
packages/modules/fulfillment/src/module-definition.ts
Normal file
44
packages/modules/fulfillment/src/module-definition.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { ModuleExports } from "@medusajs/types"
|
||||
import * as ModuleServices from "@services"
|
||||
import { FulfillmentModuleService } from "@services"
|
||||
import { Modules } from "@medusajs/modules-sdk"
|
||||
import * as ModuleModels from "@models"
|
||||
import { ModulesSdkUtils } from "@medusajs/utils"
|
||||
import * as ModuleRepositories from "@repositories"
|
||||
import loadProviders from "./loaders/providers"
|
||||
|
||||
const migrationScriptOptions = {
|
||||
moduleName: Modules.FULFILLMENT,
|
||||
models: ModuleModels,
|
||||
pathToMigrations: __dirname + "/migrations",
|
||||
}
|
||||
|
||||
const runMigrations = ModulesSdkUtils.buildMigrationScript(
|
||||
migrationScriptOptions
|
||||
)
|
||||
|
||||
const revertMigration = ModulesSdkUtils.buildRevertMigrationScript(
|
||||
migrationScriptOptions
|
||||
)
|
||||
|
||||
const containerLoader = ModulesSdkUtils.moduleContainerLoaderFactory({
|
||||
moduleModels: ModuleModels,
|
||||
moduleRepositories: ModuleRepositories,
|
||||
moduleServices: ModuleServices,
|
||||
})
|
||||
|
||||
const connectionLoader = ModulesSdkUtils.mikroOrmConnectionLoaderFactory({
|
||||
moduleName: Modules.FULFILLMENT,
|
||||
moduleModels: Object.values(ModuleModels),
|
||||
migrationsPath: __dirname + "/migrations",
|
||||
})
|
||||
|
||||
const service = FulfillmentModuleService
|
||||
const loaders = [containerLoader, connectionLoader, loadProviders]
|
||||
|
||||
export const moduleDefinition: ModuleExports = {
|
||||
service,
|
||||
loaders,
|
||||
revertMigration,
|
||||
runMigrations,
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
import { Context, FulfillmentTypes } from "@medusajs/types"
|
||||
import { DALUtils, promiseAll } from "@medusajs/utils"
|
||||
import { FulfillmentSet, ServiceZone } from "@models"
|
||||
import { SqlEntityManager } from "@mikro-orm/postgresql"
|
||||
|
||||
interface CreateFulfillmentSetDTO
|
||||
extends FulfillmentTypes.CreateFulfillmentSetDTO {
|
||||
service_zones: { id: string; name: string }[]
|
||||
}
|
||||
|
||||
export class FulfillmentSetRepository extends DALUtils.mikroOrmBaseRepositoryFactory<FulfillmentSet>(
|
||||
FulfillmentSet
|
||||
) {
|
||||
async update(
|
||||
data: {
|
||||
entity: FulfillmentSet
|
||||
update: FulfillmentTypes.FulfillmentSetDTO
|
||||
}[],
|
||||
context?: Context
|
||||
): Promise<FulfillmentSet[]> {
|
||||
const manager = this.getActiveManager<SqlEntityManager>(context)
|
||||
|
||||
// init all service zones collections
|
||||
await promiseAll(
|
||||
data.map(async ({ entity }) => {
|
||||
return await entity.service_zones.init()
|
||||
})
|
||||
)
|
||||
|
||||
const flfillmentSetsToUpdate = data.map(({ entity, update }) => {
|
||||
const { service_zones, ...restToUpdate } = update
|
||||
|
||||
const currentServiceZones = entity.service_zones.getItems()
|
||||
const serviceZonesToDetach = currentServiceZones.filter(
|
||||
(serviceZone) =>
|
||||
!update.service_zones.find(
|
||||
(newServiceZone) => newServiceZone.id === serviceZone.id
|
||||
)
|
||||
)
|
||||
const serviceZonesToAttach = update.service_zones.filter(
|
||||
(newServiceZone) =>
|
||||
!currentServiceZones.find(
|
||||
(serviceZone) => serviceZone.id === newServiceZone.id
|
||||
)
|
||||
)
|
||||
|
||||
entity.service_zones.remove(serviceZonesToDetach)
|
||||
entity.service_zones.add(serviceZonesToAttach as unknown as ServiceZone[])
|
||||
|
||||
return manager.assign(entity, restToUpdate)
|
||||
})
|
||||
|
||||
manager.persist(flfillmentSetsToUpdate)
|
||||
|
||||
return flfillmentSetsToUpdate
|
||||
}
|
||||
}
|
||||
*/
|
||||
1
packages/modules/fulfillment/src/repositories/index.ts
Normal file
1
packages/modules/fulfillment/src/repositories/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { MikroOrmBaseRepository as BaseRepository } from "@medusajs/utils"
|
||||
29
packages/modules/fulfillment/src/scripts/bin/run-seed.ts
Normal file
29
packages/modules/fulfillment/src/scripts/bin/run-seed.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { ModulesSdkUtils } from "@medusajs/utils"
|
||||
import { Modules } from "@medusajs/modules-sdk"
|
||||
import * as Models from "@models"
|
||||
import { EOL } from "os"
|
||||
|
||||
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-fulfillment-seed <filePath>`
|
||||
)
|
||||
}
|
||||
|
||||
const run = ModulesSdkUtils.buildSeedScript({
|
||||
moduleName: Modules.FULFILLMENT,
|
||||
models: Models,
|
||||
pathToMigrations: __dirname + "/../../migrations",
|
||||
seedHandler: async ({ manager, data }) => {
|
||||
// TODO: Add seed logic
|
||||
},
|
||||
})
|
||||
await run({ path })
|
||||
})()
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,104 @@
|
||||
import {
|
||||
Constructor,
|
||||
DAL,
|
||||
FulfillmentTypes,
|
||||
IFulfillmentProvider,
|
||||
} from "@medusajs/types"
|
||||
import { ModulesSdkUtils, promiseAll } from "@medusajs/utils"
|
||||
import { MedusaError } from "medusa-core-utils"
|
||||
import { FulfillmentProvider } from "@models"
|
||||
|
||||
type InjectedDependencies = {
|
||||
fulfillmentProviderRepository: DAL.RepositoryService
|
||||
[key: `fp_${string}`]: FulfillmentTypes.IFulfillmentProvider
|
||||
}
|
||||
|
||||
// TODO rework DTO's
|
||||
|
||||
export default class FulfillmentProviderService extends ModulesSdkUtils.internalModuleServiceFactory<InjectedDependencies>(
|
||||
FulfillmentProvider
|
||||
) {
|
||||
protected readonly fulfillmentProviderRepository_: DAL.RepositoryService
|
||||
|
||||
constructor(container: InjectedDependencies) {
|
||||
super(container)
|
||||
this.fulfillmentProviderRepository_ =
|
||||
container.fulfillmentProviderRepository
|
||||
}
|
||||
|
||||
static getRegistrationIdentifier(
|
||||
providerClass: Constructor<IFulfillmentProvider>,
|
||||
optionName?: string
|
||||
) {
|
||||
return `${(providerClass as any).identifier}_${optionName}`
|
||||
}
|
||||
|
||||
protected retrieveProviderRegistration(
|
||||
providerId: string
|
||||
): FulfillmentTypes.IFulfillmentProvider {
|
||||
try {
|
||||
return this.__container__[`fp_${providerId}`]
|
||||
} catch (err) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.NOT_FOUND,
|
||||
`Could not find a fulfillment provider with id: ${providerId}`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
async listFulfillmentOptions(providerIds: string[]): Promise<any[]> {
|
||||
return await promiseAll(
|
||||
providerIds.map(async (p) => {
|
||||
const provider = this.retrieveProviderRegistration(p)
|
||||
return {
|
||||
provider_id: p,
|
||||
options: (await provider.getFulfillmentOptions()) as Record<
|
||||
string,
|
||||
unknown
|
||||
>[],
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
async getFulfillmentOptions(
|
||||
providerId: string
|
||||
): Promise<Record<string, unknown>[]> {
|
||||
const provider = this.retrieveProviderRegistration(providerId)
|
||||
return await provider.getFulfillmentOptions()
|
||||
}
|
||||
|
||||
async validateFulfillmentData(
|
||||
providerId: string,
|
||||
optionData: Record<string, unknown>,
|
||||
data: Record<string, unknown>,
|
||||
context: Record<string, unknown>
|
||||
) {
|
||||
const provider = this.retrieveProviderRegistration(providerId)
|
||||
return await provider.validateFulfillmentData(optionData, data, context)
|
||||
}
|
||||
|
||||
async validateOption(providerId: string, data: Record<string, unknown>) {
|
||||
const provider = this.retrieveProviderRegistration(providerId)
|
||||
return await provider.validateOption(data)
|
||||
}
|
||||
|
||||
async createFulfillment(
|
||||
providerId: string,
|
||||
data: object,
|
||||
items: object[],
|
||||
order: object,
|
||||
fulfillment: Record<string, unknown>
|
||||
): Promise<Record<string, unknown>> {
|
||||
const provider = this.retrieveProviderRegistration(providerId)
|
||||
return await provider.createFulfillment(data, items, order, fulfillment)
|
||||
}
|
||||
|
||||
async cancelFulfillment(
|
||||
providerId: string,
|
||||
fulfillment: Record<string, unknown>
|
||||
): Promise<any> {
|
||||
const provider = this.retrieveProviderRegistration(providerId)
|
||||
return await provider.cancelFulfillment(fulfillment)
|
||||
}
|
||||
}
|
||||
2
packages/modules/fulfillment/src/services/index.ts
Normal file
2
packages/modules/fulfillment/src/services/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export { default as FulfillmentModuleService } from "./fulfillment-module-service"
|
||||
export { default as FulfillmentProviderService } from "./fulfillment-provider"
|
||||
33
packages/modules/fulfillment/src/types/index.ts
Normal file
33
packages/modules/fulfillment/src/types/index.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import {
|
||||
IEventBusModuleService,
|
||||
Logger,
|
||||
ModuleProviderExports,
|
||||
ModuleServiceInitializeOptions,
|
||||
} from "@medusajs/types"
|
||||
|
||||
export type InitializeModuleInjectableDependencies = {
|
||||
logger?: Logger
|
||||
eventBusService?: IEventBusModuleService
|
||||
}
|
||||
|
||||
export const FulfillmentIdentifiersRegistrationName =
|
||||
"fulfillment_providers_identifier"
|
||||
|
||||
export type FulfillmentModuleOptions =
|
||||
Partial<ModuleServiceInitializeOptions> & {
|
||||
/**
|
||||
* Providers to be registered
|
||||
*/
|
||||
providers?: {
|
||||
/**
|
||||
* The module provider to be registered
|
||||
*/
|
||||
resolve: string | ModuleProviderExports
|
||||
options: {
|
||||
/**
|
||||
* key value pair of the provider name and the configuration to be passed to the provider constructor
|
||||
*/
|
||||
config: Record<string, unknown>
|
||||
}
|
||||
}[]
|
||||
}
|
||||
6
packages/modules/fulfillment/src/types/service.ts
Normal file
6
packages/modules/fulfillment/src/types/service.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { FulfillmentTypes } from "@medusajs/types"
|
||||
|
||||
export type UpdateShippingOptionsInput = Required<
|
||||
Pick<FulfillmentTypes.UpdateShippingOptionDTO, "id">
|
||||
> &
|
||||
FulfillmentTypes.UpdateShippingOptionDTO
|
||||
249
packages/modules/fulfillment/src/utils/__tests__/utils.spec.ts
Normal file
249
packages/modules/fulfillment/src/utils/__tests__/utils.spec.ts
Normal file
@@ -0,0 +1,249 @@
|
||||
import { RuleOperator } from "@medusajs/utils"
|
||||
import { isContextValid } from "../utils"
|
||||
|
||||
describe("isContextValidForRules", () => {
|
||||
const context = {
|
||||
attribute1: "value1",
|
||||
attribute2: "value2",
|
||||
attribute3: "value3",
|
||||
}
|
||||
|
||||
const validRule = {
|
||||
attribute: "attribute1",
|
||||
operator: RuleOperator.EQ,
|
||||
value: "value1",
|
||||
}
|
||||
|
||||
const invalidRule = {
|
||||
attribute: "attribute2",
|
||||
operator: RuleOperator.EQ,
|
||||
value: "wrongValue",
|
||||
}
|
||||
|
||||
it("returns true when all rules are valid", () => {
|
||||
const rules = [validRule, validRule]
|
||||
expect(isContextValid(context, rules)).toBe(true)
|
||||
})
|
||||
|
||||
it("returns true when some rules are valid", () => {
|
||||
const rules = [validRule, validRule]
|
||||
const options = { someAreValid: true }
|
||||
expect(isContextValid(context, rules, options)).toBe(true)
|
||||
})
|
||||
|
||||
it("returns true when some rules are valid and someAreValid is true", () => {
|
||||
const rules = [validRule, invalidRule]
|
||||
const options = { someAreValid: true }
|
||||
expect(isContextValid(context, rules, options)).toBe(true)
|
||||
})
|
||||
|
||||
it("returns false when some rules are valid", () => {
|
||||
const rules = [validRule, invalidRule]
|
||||
expect(isContextValid(context, rules)).toBe(false)
|
||||
})
|
||||
|
||||
it("returns false when no rules are valid and someAreValid is true", () => {
|
||||
const rules = [invalidRule, invalidRule]
|
||||
const options = { someAreValid: true }
|
||||
expect(isContextValid(context, rules, options)).toBe(false)
|
||||
})
|
||||
|
||||
it("returns false when no rules are valid", () => {
|
||||
const rules = [invalidRule, invalidRule]
|
||||
expect(isContextValid(context, rules)).toBe(false)
|
||||
})
|
||||
|
||||
it("returns true when the 'gt' operator is valid", () => {
|
||||
const rules = [
|
||||
{
|
||||
attribute: "attribute1",
|
||||
operator: RuleOperator.GT,
|
||||
value: "1", // 2 > 1
|
||||
},
|
||||
]
|
||||
const context = { attribute1: "2" }
|
||||
expect(isContextValid(context, rules)).toBe(true)
|
||||
})
|
||||
|
||||
it("returns false when the 'gt' operator is invalid", () => {
|
||||
const rules = [
|
||||
{
|
||||
attribute: "attribute1",
|
||||
operator: RuleOperator.GT,
|
||||
value: "0", // 0 > 0
|
||||
},
|
||||
]
|
||||
const context = { attribute1: "0" }
|
||||
expect(isContextValid(context, rules)).toBe(false)
|
||||
})
|
||||
|
||||
it("returns true when the 'gte' operator is valid", () => {
|
||||
const rules = [
|
||||
{
|
||||
attribute: "attribute1",
|
||||
operator: RuleOperator.GTE,
|
||||
value: "2", // 2 >= 2
|
||||
},
|
||||
]
|
||||
const context = { attribute1: "2" }
|
||||
expect(isContextValid(context, rules)).toBe(true)
|
||||
})
|
||||
|
||||
it("returns false when the 'gte' operator is invalid", () => {
|
||||
const rules = [
|
||||
{
|
||||
attribute: "attribute1",
|
||||
operator: RuleOperator.GTE,
|
||||
value: "3", // 2 >= 3
|
||||
},
|
||||
]
|
||||
const context = { attribute1: "2" }
|
||||
expect(isContextValid(context, rules)).toBe(false)
|
||||
})
|
||||
|
||||
it("returns true when the 'lt' operator is valid", () => {
|
||||
const rules = [
|
||||
{
|
||||
attribute: "attribute1",
|
||||
operator: RuleOperator.LT,
|
||||
value: "3", // 2 < 3
|
||||
},
|
||||
]
|
||||
const context = { attribute1: "2" }
|
||||
expect(isContextValid(context, rules)).toBe(true)
|
||||
})
|
||||
|
||||
it("returns false when the 'lt' operator is invalid", () => {
|
||||
const rules = [
|
||||
{
|
||||
attribute: "attribute1",
|
||||
operator: RuleOperator.LT,
|
||||
value: "2", // 2 < 2
|
||||
},
|
||||
]
|
||||
const context = { attribute1: "2" }
|
||||
expect(isContextValid(context, rules)).toBe(false)
|
||||
})
|
||||
|
||||
it("returns true when the 'lte' operator is valid", () => {
|
||||
const rules = [
|
||||
{
|
||||
attribute: "attribute1",
|
||||
operator: RuleOperator.LTE,
|
||||
value: "2", // 2 <= 2
|
||||
},
|
||||
]
|
||||
const context = { attribute1: "2" }
|
||||
expect(isContextValid(context, rules)).toBe(true)
|
||||
})
|
||||
|
||||
// ... existing tests ...
|
||||
|
||||
it("returns false when the 'lte' operator is invalid", () => {
|
||||
const rules = [
|
||||
{
|
||||
attribute: "attribute1",
|
||||
operator: RuleOperator.LTE,
|
||||
value: "1", // 2 <= 1
|
||||
},
|
||||
]
|
||||
const context = { attribute1: "2" }
|
||||
expect(isContextValid(context, rules)).toBe(false)
|
||||
})
|
||||
|
||||
it("returns true when the 'in' operator is valid", () => {
|
||||
const rules = [
|
||||
{
|
||||
attribute: "attribute1",
|
||||
operator: RuleOperator.IN,
|
||||
value: ["1", "2", "3"], // 2 in [1, 2, 3]
|
||||
},
|
||||
]
|
||||
const context = { attribute1: "2" }
|
||||
expect(isContextValid(context, rules)).toBe(true)
|
||||
})
|
||||
|
||||
it("returns false when the 'in' operator is invalid", () => {
|
||||
const rules = [
|
||||
{
|
||||
attribute: "attribute1",
|
||||
operator: RuleOperator.IN,
|
||||
value: ["1", "3", "4"], // 2 in [1, 3, 4]
|
||||
},
|
||||
]
|
||||
const context = { attribute1: "2" }
|
||||
expect(isContextValid(context, rules)).toBe(false)
|
||||
})
|
||||
|
||||
it("returns true when the 'nin' operator is valid", () => {
|
||||
const rules = [
|
||||
{
|
||||
attribute: "attribute1",
|
||||
operator: RuleOperator.NIN,
|
||||
value: ["1", "3", "4"], // 2 not in [1, 3, 4]
|
||||
},
|
||||
]
|
||||
const context = { attribute1: "2" }
|
||||
expect(isContextValid(context, rules)).toBe(true)
|
||||
})
|
||||
|
||||
it("returns false when the 'nin' operator is invalid", () => {
|
||||
const rules = [
|
||||
{
|
||||
attribute: "attribute1",
|
||||
operator: RuleOperator.NIN,
|
||||
value: ["1", "2", "3"], // 2 not in [1, 2, 3]
|
||||
},
|
||||
]
|
||||
const context = { attribute1: "2" }
|
||||
expect(isContextValid(context, rules)).toBe(false)
|
||||
})
|
||||
|
||||
it("returns true when the 'ne' operator is valid", () => {
|
||||
const rules = [
|
||||
{
|
||||
attribute: "attribute1",
|
||||
operator: RuleOperator.NE,
|
||||
value: "1", // 2 != 1
|
||||
},
|
||||
]
|
||||
const context = { attribute1: "2" }
|
||||
expect(isContextValid(context, rules)).toBe(true)
|
||||
})
|
||||
|
||||
it("returns false when the 'ne' operator is invalid", () => {
|
||||
const rules = [
|
||||
{
|
||||
attribute: "attribute1",
|
||||
operator: RuleOperator.NE,
|
||||
value: "2", // 2 != 2
|
||||
},
|
||||
]
|
||||
const context = { attribute1: "2" }
|
||||
expect(isContextValid(context, rules)).toBe(false)
|
||||
})
|
||||
|
||||
it("returns true when the 'eq' operator is valid", () => {
|
||||
const rules = [
|
||||
{
|
||||
attribute: "attribute1",
|
||||
operator: RuleOperator.EQ,
|
||||
value: "2", // 2 == 2
|
||||
},
|
||||
]
|
||||
const context = { attribute1: "2" }
|
||||
expect(isContextValid(context, rules)).toBe(true)
|
||||
})
|
||||
|
||||
it("returns false when the 'eq' operator is invalid", () => {
|
||||
const rules = [
|
||||
{
|
||||
attribute: "attribute1",
|
||||
operator: RuleOperator.EQ,
|
||||
value: "1", // 2 == 1
|
||||
},
|
||||
]
|
||||
const context = { attribute1: "2" }
|
||||
expect(isContextValid(context, rules)).toBe(false)
|
||||
})
|
||||
})
|
||||
1
packages/modules/fulfillment/src/utils/index.ts
Normal file
1
packages/modules/fulfillment/src/utils/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './utils'
|
||||
172
packages/modules/fulfillment/src/utils/utils.ts
Normal file
172
packages/modules/fulfillment/src/utils/utils.ts
Normal file
@@ -0,0 +1,172 @@
|
||||
import {
|
||||
isObject,
|
||||
isString,
|
||||
MedusaError,
|
||||
pickValueFromObject,
|
||||
RuleOperator,
|
||||
} from "@medusajs/utils"
|
||||
|
||||
/**
|
||||
* The rule engine here is kept inside the module as of now, but it could be moved
|
||||
* to the utils package and be used across the different modules that provides context
|
||||
* based rule filtering.
|
||||
*
|
||||
* TODO: discussion around that should happen at some point
|
||||
*/
|
||||
|
||||
export type Rule = {
|
||||
attribute: string
|
||||
operator: Lowercase<keyof typeof RuleOperator>
|
||||
value: string | string[] | null
|
||||
}
|
||||
|
||||
export const availableOperators = Object.values(RuleOperator)
|
||||
|
||||
const isDate = (str: string) => {
|
||||
return !isNaN(Date.parse(str))
|
||||
}
|
||||
|
||||
const operatorsPredicate = {
|
||||
in: (contextValue: string, ruleValue: string[]) =>
|
||||
ruleValue.includes(contextValue),
|
||||
nin: (contextValue: string, ruleValue: string[]) =>
|
||||
!ruleValue.includes(contextValue),
|
||||
eq: (contextValue: string, ruleValue: string) => contextValue === ruleValue,
|
||||
ne: (contextValue: string, ruleValue: string) => contextValue !== ruleValue,
|
||||
gt: (contextValue: string, ruleValue: string) => {
|
||||
if (isDate(contextValue) && isDate(ruleValue)) {
|
||||
return new Date(contextValue) > new Date(ruleValue)
|
||||
}
|
||||
return Number(contextValue) > Number(ruleValue)
|
||||
},
|
||||
gte: (contextValue: string, ruleValue: string) => {
|
||||
if (isDate(contextValue) && isDate(ruleValue)) {
|
||||
return new Date(contextValue) >= new Date(ruleValue)
|
||||
}
|
||||
return Number(contextValue) >= Number(ruleValue)
|
||||
},
|
||||
lt: (contextValue: string, ruleValue: string) => {
|
||||
if (isDate(contextValue) && isDate(ruleValue)) {
|
||||
return new Date(contextValue) < new Date(ruleValue)
|
||||
}
|
||||
return Number(contextValue) < Number(ruleValue)
|
||||
},
|
||||
lte: (contextValue: string, ruleValue: string) => {
|
||||
if (isDate(contextValue) && isDate(ruleValue)) {
|
||||
return new Date(contextValue) <= new Date(ruleValue)
|
||||
}
|
||||
return Number(contextValue) <= Number(ruleValue)
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate contextValue context object from contextValue set of rules.
|
||||
* By default, all rules must be valid to return true unless the option atLeastOneValidRule is set to true.
|
||||
* @param context
|
||||
* @param rules
|
||||
* @param options
|
||||
*/
|
||||
export function isContextValid(
|
||||
context: Record<string, any>,
|
||||
rules: Rule[],
|
||||
options: {
|
||||
someAreValid: boolean
|
||||
} = {
|
||||
someAreValid: false,
|
||||
}
|
||||
): boolean {
|
||||
const { someAreValid } = options
|
||||
|
||||
const loopComparator = someAreValid ? rules.some : rules.every
|
||||
const predicate = (rule) => {
|
||||
const { attribute, operator, value } = rule
|
||||
const contextValue = pickValueFromObject(attribute, context)
|
||||
return operatorsPredicate[operator](
|
||||
contextValue,
|
||||
value as string & string[]
|
||||
)
|
||||
}
|
||||
|
||||
return loopComparator.apply(rules, [predicate])
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate contextValue rule object
|
||||
* @param rule
|
||||
*/
|
||||
export function validateRule(rule: Record<string, unknown>): boolean {
|
||||
if (!rule.attribute || !rule.operator || !rule.value) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
"Rule must have an attribute, an operator and a value"
|
||||
)
|
||||
}
|
||||
|
||||
if (!isString(rule.attribute)) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
"Rule attribute must be a string"
|
||||
)
|
||||
}
|
||||
|
||||
if (!isString(rule.operator)) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
"Rule operator must be a string"
|
||||
)
|
||||
}
|
||||
|
||||
if (!availableOperators.includes(rule.operator as RuleOperator)) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
`Rule operator ${
|
||||
rule.operator
|
||||
} is not supported. Must be one of ${availableOperators.join(", ")}`
|
||||
)
|
||||
}
|
||||
|
||||
if (rule.operator === RuleOperator.IN || rule.operator === RuleOperator.NIN) {
|
||||
if (!Array.isArray(rule.value)) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
"Rule value must be an array for in/nin operators"
|
||||
)
|
||||
}
|
||||
} else {
|
||||
if (Array.isArray(rule.value) || isObject(rule.value)) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
`Rule value must be a string, bool, number value for the selected operator ${rule.operator}`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
export function normalizeRulesValue<T extends Partial<Rule>>(rules: T[]): void {
|
||||
rules.forEach((rule) => {
|
||||
/**
|
||||
* If a string is provided, then we don't want jsonb to convert to the primitive value based on the RFC
|
||||
*/
|
||||
if (rule.value === "true" || rule.value === "false") {
|
||||
rule.value = rule.value === "true" ? '"true"' : '"false"'
|
||||
}
|
||||
|
||||
return rule
|
||||
})
|
||||
}
|
||||
|
||||
export function validateAndNormalizeRules<T extends Partial<Rule>>(rules: T[]) {
|
||||
rules.forEach(validateRule)
|
||||
normalizeRulesValue(rules)
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate contextValue set of rules
|
||||
* @param rules
|
||||
*/
|
||||
export function validateRules(rules: Record<string, unknown>[]): boolean {
|
||||
rules.forEach(validateRule)
|
||||
return true
|
||||
}
|
||||
Reference in New Issue
Block a user