feat(fulfillment): Module service implementation first iteration (#6381)
This commit is contained in:
committed by
GitHub
parent
02c53ec93f
commit
fafde4f54d
5
.changeset/nine-nails-end.md
Normal file
5
.changeset/nine-nails-end.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@medusajs/types": patch
|
||||
---
|
||||
|
||||
feat(fulfillment): Module service implementation first iteration
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +0,0 @@
|
||||
describe("noop", function () {
|
||||
it("should run", function () {
|
||||
expect(true).toBe(true)
|
||||
})
|
||||
})
|
||||
@@ -2,17 +2,12 @@ import { TestDatabaseUtils } from "medusa-test-utils"
|
||||
|
||||
import * as Models from "@models"
|
||||
|
||||
const pathToMigrations = "../../src/migrations"
|
||||
const mikroOrmEntities = Models as unknown as any[]
|
||||
|
||||
export const MikroOrmWrapper = TestDatabaseUtils.getMikroOrmWrapper(
|
||||
mikroOrmEntities,
|
||||
pathToMigrations
|
||||
)
|
||||
|
||||
export const MikroOrmConfig = TestDatabaseUtils.getMikroOrmConfig(
|
||||
mikroOrmEntities,
|
||||
pathToMigrations
|
||||
null,
|
||||
process.env.MEDUSA_FULFILLMENT_DB_SCHEMA
|
||||
)
|
||||
|
||||
export const DB_URL = TestDatabaseUtils.getDatabaseURL()
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
export * from "./database"
|
||||
export * from "./get-init-module-config"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,84 @@
|
||||
import { Migration } from '@mikro-orm/migrations';
|
||||
|
||||
export class Migration20240214103108 extends Migration {
|
||||
|
||||
async up(): Promise<void> {
|
||||
this.addSql('create table if not exists "fulfillment_address" ("id" text not null, "fulfillment_id" text 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_fulfillment_id" ON "fulfillment_address" (fulfillment_id) WHERE deleted_at IS NULL;');
|
||||
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_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_provider" ("id" 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 "service_provider_pkey" primary key ("id"));');
|
||||
this.addSql('CREATE INDEX IF NOT EXISTS "IDX_service_provider_deleted_at" ON "service_provider" (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, "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_type_pkey" primary key ("id"));');
|
||||
this.addSql('CREATE INDEX IF NOT EXISTS "IDX_shipping_option_type_shipping_option_id" ON "shipping_option_type" (shipping_option_id) WHERE deleted_at IS NULL;');
|
||||
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, "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 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 \'calculated\', "service_zone_id" text not null, "shipping_profile_id" text not null, "service_provider_id" text not null, "shipping_option_type_id" text null, "data" jsonb null, "metadata" jsonb 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_service_provider_id" ON "shipping_option" (service_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 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_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 not null, "shipping_option_id" text null, "metadata" jsonb null, "delivery_address_id" text not null, "items_id" text not 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('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, "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_fulfillment_id" ON "fulfillment_item" (line_item_id) WHERE deleted_at IS NULL;');
|
||||
this.addSql('CREATE INDEX IF NOT EXISTS "IDX_fulfillment_item_fulfillment_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;');
|
||||
|
||||
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;');
|
||||
|
||||
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;');
|
||||
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;');
|
||||
this.addSql('alter table if exists "shipping_option" add constraint "shipping_option_service_provider_id_foreign" foreign key ("service_provider_id") references "service_provider" ("id") on update cascade;');
|
||||
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;');
|
||||
|
||||
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;');
|
||||
|
||||
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_provider_id_foreign" foreign key ("provider_id") references "service_provider" ("id") on update cascade;');
|
||||
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;');
|
||||
this.addSql('alter table if exists "fulfillment" add constraint "fulfillment_items_id_foreign" foreign key ("items_id") references "fulfillment_item" ("id") on update 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;');
|
||||
|
||||
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;');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -6,11 +6,12 @@ import {
|
||||
|
||||
import {
|
||||
BeforeCreate,
|
||||
Cascade,
|
||||
Collection,
|
||||
Entity,
|
||||
Filter,
|
||||
Index,
|
||||
ManyToMany,
|
||||
OneToMany,
|
||||
OnInit,
|
||||
OptionalProps,
|
||||
PrimaryKey,
|
||||
@@ -29,6 +30,15 @@ const deletedAtIndexStatement = createPsqlIndexStatementHelper({
|
||||
where: "deleted_at IS NOT NULL",
|
||||
})
|
||||
|
||||
const nameIndexName = "IDX_fulfillment_set_name_unique"
|
||||
const nameIndexStatement = createPsqlIndexStatementHelper({
|
||||
name: nameIndexName,
|
||||
tableName: "fulfillment_set",
|
||||
columns: "name",
|
||||
unique: true,
|
||||
where: "deleted_at IS NULL",
|
||||
})
|
||||
|
||||
@Entity()
|
||||
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
||||
export default class FulfillmentSet {
|
||||
@@ -38,6 +48,10 @@ export default class FulfillmentSet {
|
||||
id: string
|
||||
|
||||
@Property({ columnType: "text" })
|
||||
@Index({
|
||||
name: nameIndexName,
|
||||
expression: nameIndexStatement,
|
||||
})
|
||||
name: string
|
||||
|
||||
@Property({ columnType: "text" })
|
||||
@@ -46,11 +60,9 @@ export default class FulfillmentSet {
|
||||
@Property({ columnType: "jsonb", nullable: true })
|
||||
metadata: Record<string, unknown> | null = null
|
||||
|
||||
@ManyToMany(() => ServiceZone, "fulfillment_sets", {
|
||||
owner: true,
|
||||
pivotTable: "fulfillment_set_service_zones",
|
||||
joinColumn: "fulfillment_set_id",
|
||||
inverseJoinColumn: "service_zone_id",
|
||||
@OneToMany(() => ServiceZone, "fulfillment_set", {
|
||||
cascade: [Cascade.PERSIST, "soft-remove"] as any,
|
||||
orphanRemoval: true,
|
||||
})
|
||||
service_zones = new Collection<ServiceZone>(this)
|
||||
|
||||
|
||||
@@ -7,12 +7,11 @@ import {
|
||||
|
||||
import {
|
||||
BeforeCreate,
|
||||
Collection,
|
||||
Entity,
|
||||
Enum,
|
||||
Filter,
|
||||
Index,
|
||||
ManyToMany,
|
||||
ManyToOne,
|
||||
OnInit,
|
||||
OptionalProps,
|
||||
PrimaryKey,
|
||||
@@ -55,6 +54,14 @@ const cityIndexStatement = createPsqlIndexStatementHelper({
|
||||
where: "deleted_at IS NULL AND city IS NOT NULL",
|
||||
})
|
||||
|
||||
const serviceZoneIdIndexName = "IDX_geo_zone_service_zone_id"
|
||||
const serviceZoneIdStatement = createPsqlIndexStatementHelper({
|
||||
name: serviceZoneIdIndexName,
|
||||
tableName: "geo_zone",
|
||||
columns: "service_zone_id",
|
||||
where: "deleted_at IS NULL",
|
||||
})
|
||||
|
||||
@Entity()
|
||||
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
||||
export default class GeoZone {
|
||||
@@ -87,6 +94,13 @@ export default class GeoZone {
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
city: string | null = null
|
||||
|
||||
@Property({ columnType: "text" })
|
||||
@Index({
|
||||
name: serviceZoneIdIndexName,
|
||||
expression: serviceZoneIdStatement,
|
||||
})
|
||||
service_zone_id: string
|
||||
|
||||
// TODO: Do we have an example or idea of what would be stored in this field? like lat/long for example?
|
||||
@Property({ columnType: "jsonb", nullable: true })
|
||||
postal_expression: Record<string, unknown> | null = null
|
||||
@@ -94,8 +108,10 @@ export default class GeoZone {
|
||||
@Property({ columnType: "jsonb", nullable: true })
|
||||
metadata: Record<string, unknown> | null = null
|
||||
|
||||
@ManyToMany(() => ServiceZone, (serviceZone) => serviceZone.geo_zones)
|
||||
service_zones = new Collection<ServiceZone>(this)
|
||||
@ManyToOne(() => ServiceZone, {
|
||||
persist: false,
|
||||
})
|
||||
service_zone: ServiceZone
|
||||
|
||||
@Property({
|
||||
onCreate: () => new Date(),
|
||||
@@ -122,10 +138,12 @@ export default class GeoZone {
|
||||
@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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,11 +6,12 @@ import {
|
||||
|
||||
import {
|
||||
BeforeCreate,
|
||||
Cascade,
|
||||
Collection,
|
||||
Entity,
|
||||
Filter,
|
||||
Index,
|
||||
ManyToMany,
|
||||
ManyToOne,
|
||||
OneToMany,
|
||||
OnInit,
|
||||
OptionalProps,
|
||||
@@ -32,6 +33,23 @@ const deletedAtIndexStatement = createPsqlIndexStatementHelper({
|
||||
where: "deleted_at IS NOT NULL",
|
||||
})
|
||||
|
||||
const nameIndexName = "IDX_service_zone_name_unique"
|
||||
const nameIndexStatement = createPsqlIndexStatementHelper({
|
||||
name: nameIndexName,
|
||||
tableName: "service_zone",
|
||||
columns: "name",
|
||||
unique: true,
|
||||
where: "deleted_at IS NULL",
|
||||
})
|
||||
|
||||
const fulfillmentSetIdIndexName = "IDX_service_zone_fulfillment_set_id"
|
||||
const fulfillmentSetIdIndexStatement = createPsqlIndexStatementHelper({
|
||||
name: fulfillmentSetIdIndexName,
|
||||
tableName: "service_zone",
|
||||
columns: "fulfillment_set_id",
|
||||
where: "deleted_at IS NULL",
|
||||
})
|
||||
|
||||
@Entity()
|
||||
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
||||
export default class ServiceZone {
|
||||
@@ -41,22 +59,28 @@ export default class ServiceZone {
|
||||
id: string
|
||||
|
||||
@Property({ columnType: "text" })
|
||||
@Index({
|
||||
name: nameIndexName,
|
||||
expression: nameIndexStatement,
|
||||
})
|
||||
name: string
|
||||
|
||||
@Property({ columnType: "jsonb", nullable: true })
|
||||
metadata: Record<string, unknown> | null = null
|
||||
|
||||
@ManyToMany(
|
||||
() => FulfillmentSet,
|
||||
(fulfillmentSet) => fulfillmentSet.service_zones
|
||||
)
|
||||
fulfillment_sets = new Collection<FulfillmentSet>(this)
|
||||
@Property({ columnType: "text" })
|
||||
@Index({
|
||||
name: fulfillmentSetIdIndexName,
|
||||
expression: fulfillmentSetIdIndexStatement,
|
||||
})
|
||||
fulfillment_set_id: string
|
||||
|
||||
@ManyToMany(() => GeoZone, "service_zones", {
|
||||
owner: true,
|
||||
pivotTable: "service_zone_geo_zones",
|
||||
joinColumn: "service_zone_id",
|
||||
inverseJoinColumn: "geo_zone_id",
|
||||
@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)
|
||||
|
||||
@@ -91,10 +115,12 @@ export default class ServiceZone {
|
||||
@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
|
||||
}
|
||||
}
|
||||
|
||||
59
packages/fulfillment/src/repositories/fulfillment-set.ts
Normal file
59
packages/fulfillment/src/repositories/fulfillment-set.ts
Normal file
@@ -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
|
||||
}
|
||||
}
|
||||
*/
|
||||
@@ -8,20 +8,32 @@ import {
|
||||
ModulesSdkTypes,
|
||||
UpdateFulfillmentSetDTO,
|
||||
} from "@medusajs/types"
|
||||
import { InjectTransactionManager, ModulesSdkUtils } from "@medusajs/utils"
|
||||
import {
|
||||
InjectManager,
|
||||
InjectTransactionManager,
|
||||
MedusaContext,
|
||||
MedusaError,
|
||||
ModulesSdkUtils,
|
||||
promiseAll,
|
||||
getSetDifference
|
||||
} from "@medusajs/utils"
|
||||
|
||||
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
|
||||
import { FulfillmentSet, ServiceZone, ShippingOption } from "@models"
|
||||
import { FulfillmentSet, GeoZone, ServiceZone, ShippingOption } from "@models"
|
||||
|
||||
const generateMethodForModels = [ServiceZone, ShippingOption]
|
||||
const generateMethodForModels = [ServiceZone, ShippingOption, GeoZone]
|
||||
|
||||
type InjectedDependencies = {
|
||||
baseRepository: DAL.RepositoryService
|
||||
fulfillmentService: ModulesSdkTypes.InternalModuleService<any>
|
||||
fulfillmentSetService: ModulesSdkTypes.InternalModuleService<any>
|
||||
serviceZoneService: ModulesSdkTypes.InternalModuleService<any>
|
||||
geoZoneService: ModulesSdkTypes.InternalModuleService<any>
|
||||
}
|
||||
|
||||
export default class FulfillmentModuleService<
|
||||
TEntity extends FulfillmentSet = FulfillmentSet
|
||||
TEntity extends FulfillmentSet = FulfillmentSet,
|
||||
TServiceZoneEntity extends ServiceZone = ServiceZone,
|
||||
TGeoZoneEntity extends GeoZone = GeoZone
|
||||
>
|
||||
extends ModulesSdkUtils.abstractModuleServiceFactory<
|
||||
InjectedDependencies,
|
||||
@@ -30,21 +42,31 @@ export default class FulfillmentModuleService<
|
||||
FulfillmentSet: { dto: FulfillmentTypes.FulfillmentSetDTO }
|
||||
ServiceZone: { dto: FulfillmentTypes.ServiceZoneDTO }
|
||||
ShippingOption: { dto: FulfillmentTypes.ShippingOptionDTO }
|
||||
GeoZone: { dto: FulfillmentTypes.GeoZoneDTO }
|
||||
}
|
||||
>(FulfillmentSet, generateMethodForModels, entityNameToLinkableKeysMap)
|
||||
implements IFulfillmentModuleService
|
||||
{
|
||||
protected baseRepository_: DAL.RepositoryService
|
||||
protected readonly fulfillmentService_: ModulesSdkTypes.InternalModuleService<TEntity>
|
||||
protected readonly fulfillmentSetService_: ModulesSdkTypes.InternalModuleService<TEntity>
|
||||
protected readonly serviceZoneService_: ModulesSdkTypes.InternalModuleService<TServiceZoneEntity>
|
||||
protected readonly geoZoneService_: ModulesSdkTypes.InternalModuleService<TGeoZoneEntity>
|
||||
|
||||
constructor(
|
||||
{ baseRepository, fulfillmentService }: InjectedDependencies,
|
||||
{
|
||||
baseRepository,
|
||||
fulfillmentSetService,
|
||||
serviceZoneService,
|
||||
geoZoneService,
|
||||
}: InjectedDependencies,
|
||||
protected readonly moduleDeclaration: InternalModuleDeclaration
|
||||
) {
|
||||
// @ts-ignore
|
||||
super(...arguments)
|
||||
this.baseRepository_ = baseRepository
|
||||
this.fulfillmentService_ = fulfillmentService
|
||||
this.fulfillmentSetService_ = fulfillmentSetService
|
||||
this.serviceZoneService_ = serviceZoneService
|
||||
this.geoZoneService_ = geoZoneService
|
||||
}
|
||||
|
||||
__joinerConfig(): ModuleJoinerConfig {
|
||||
@@ -60,16 +82,41 @@ export default class FulfillmentModuleService<
|
||||
sharedContext?: Context
|
||||
): Promise<FulfillmentTypes.FulfillmentSetDTO>
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
@InjectManager("baseRepository_")
|
||||
async create(
|
||||
data:
|
||||
| FulfillmentTypes.CreateFulfillmentSetDTO
|
||||
| FulfillmentTypes.CreateFulfillmentSetDTO[],
|
||||
sharedContext?: Context
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<
|
||||
FulfillmentTypes.FulfillmentSetDTO | FulfillmentTypes.FulfillmentSetDTO[]
|
||||
> {
|
||||
return []
|
||||
const createdFulfillmentSets = await this.create_(data, sharedContext)
|
||||
|
||||
return await this.baseRepository_.serialize<
|
||||
FulfillmentTypes.FulfillmentSetDTO | FulfillmentTypes.FulfillmentSetDTO[]
|
||||
>(createdFulfillmentSets, {
|
||||
populate: true,
|
||||
})
|
||||
}
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
protected async create_(
|
||||
data:
|
||||
| FulfillmentTypes.CreateFulfillmentSetDTO
|
||||
| FulfillmentTypes.CreateFulfillmentSetDTO[],
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<TEntity | TEntity[]> {
|
||||
const data_ = Array.isArray(data) ? data : [data]
|
||||
|
||||
const createdFulfillmentSets = await this.fulfillmentSetService_.create(
|
||||
data_,
|
||||
sharedContext
|
||||
)
|
||||
|
||||
return Array.isArray(data)
|
||||
? createdFulfillmentSets
|
||||
: createdFulfillmentSets[0]
|
||||
}
|
||||
|
||||
createServiceZones(
|
||||
@@ -81,16 +128,46 @@ export default class FulfillmentModuleService<
|
||||
sharedContext?: Context
|
||||
): Promise<FulfillmentTypes.ServiceZoneDTO>
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
@InjectManager("baseRepository_")
|
||||
async createServiceZones(
|
||||
data:
|
||||
| FulfillmentTypes.CreateServiceZoneDTO[]
|
||||
| FulfillmentTypes.CreateServiceZoneDTO,
|
||||
sharedContext?: Context
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<
|
||||
FulfillmentTypes.ServiceZoneDTO | FulfillmentTypes.ServiceZoneDTO[]
|
||||
> {
|
||||
return []
|
||||
const createdServiceZones = await this.createServiceZones_(
|
||||
data,
|
||||
sharedContext
|
||||
)
|
||||
|
||||
return await this.baseRepository_.serialize<
|
||||
FulfillmentTypes.ServiceZoneDTO | FulfillmentTypes.ServiceZoneDTO[]
|
||||
>(createdServiceZones, {
|
||||
populate: true,
|
||||
})
|
||||
}
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
protected async createServiceZones_(
|
||||
data:
|
||||
| FulfillmentTypes.CreateServiceZoneDTO[]
|
||||
| FulfillmentTypes.CreateServiceZoneDTO,
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<TServiceZoneEntity | TServiceZoneEntity[]> {
|
||||
let data_ = Array.isArray(data) ? data : [data]
|
||||
|
||||
if (!data_.length) {
|
||||
return []
|
||||
}
|
||||
|
||||
const createdServiceZones = await this.serviceZoneService_.create(
|
||||
data_,
|
||||
sharedContext
|
||||
)
|
||||
|
||||
return Array.isArray(data) ? createdServiceZones : createdServiceZones[0]
|
||||
}
|
||||
|
||||
createShippingOptions(
|
||||
@@ -107,13 +184,42 @@ export default class FulfillmentModuleService<
|
||||
data:
|
||||
| FulfillmentTypes.CreateShippingOptionDTO[]
|
||||
| FulfillmentTypes.CreateShippingOptionDTO,
|
||||
sharedContext?: Context
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<
|
||||
FulfillmentTypes.ShippingOptionDTO | FulfillmentTypes.ShippingOptionDTO[]
|
||||
> {
|
||||
return []
|
||||
}
|
||||
|
||||
createGeoZones(
|
||||
data: FulfillmentTypes.CreateGeoZoneDTO[],
|
||||
sharedContext?: Context
|
||||
): Promise<FulfillmentTypes.GeoZoneDTO[]>
|
||||
createGeoZones(
|
||||
data: FulfillmentTypes.CreateGeoZoneDTO,
|
||||
sharedContext?: Context
|
||||
): Promise<FulfillmentTypes.GeoZoneDTO>
|
||||
|
||||
@InjectManager("baseRepository_")
|
||||
async createGeoZones(
|
||||
data:
|
||||
| FulfillmentTypes.CreateGeoZoneDTO
|
||||
| FulfillmentTypes.CreateGeoZoneDTO[],
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<FulfillmentTypes.GeoZoneDTO | FulfillmentTypes.GeoZoneDTO[]> {
|
||||
const createdGeoZones = await this.geoZoneService_.create(
|
||||
data,
|
||||
sharedContext
|
||||
)
|
||||
|
||||
return await this.baseRepository_.serialize<FulfillmentTypes.GeoZoneDTO[]>(
|
||||
createdGeoZones,
|
||||
{
|
||||
populate: true,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
update(
|
||||
data: FulfillmentTypes.UpdateFulfillmentSetDTO[],
|
||||
sharedContext?: Context
|
||||
@@ -123,14 +229,170 @@ export default class FulfillmentModuleService<
|
||||
sharedContext?: Context
|
||||
): Promise<FulfillmentTypes.FulfillmentSetDTO>
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
@InjectManager("baseRepository_")
|
||||
async update(
|
||||
data: UpdateFulfillmentSetDTO[] | UpdateFulfillmentSetDTO,
|
||||
sharedContext?: Context
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<
|
||||
FulfillmentTypes.FulfillmentSetDTO[] | FulfillmentTypes.FulfillmentSetDTO
|
||||
> {
|
||||
return []
|
||||
const updatedFulfillmentSets = await this.update_(data, sharedContext)
|
||||
|
||||
return await this.baseRepository_.serialize<
|
||||
FulfillmentTypes.FulfillmentSetDTO | FulfillmentTypes.FulfillmentSetDTO[]
|
||||
>(updatedFulfillmentSets, {
|
||||
populate: true,
|
||||
})
|
||||
}
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
protected async update_(
|
||||
data: UpdateFulfillmentSetDTO[] | UpdateFulfillmentSetDTO,
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<TEntity[] | TEntity> {
|
||||
const data_ = Array.isArray(data) ? data : [data]
|
||||
|
||||
if (!data_.length) {
|
||||
return []
|
||||
}
|
||||
|
||||
const fulfillmentSetIds = data_.map((f) => f.id)
|
||||
if (!fulfillmentSetIds.length) {
|
||||
return []
|
||||
}
|
||||
|
||||
const fulfillmentSets = await this.fulfillmentSetService_.list(
|
||||
{
|
||||
id: fulfillmentSetIds,
|
||||
},
|
||||
{
|
||||
relations: ["service_zones", "service_zones.geo_zones"],
|
||||
},
|
||||
sharedContext
|
||||
)
|
||||
|
||||
const fulfillmentSetSet = new Set(fulfillmentSets.map((f) => f.id))
|
||||
const expectedFulfillmentSetSet = new Set(data_.map((f) => f.id))
|
||||
const missingFulfillmentSetIds = getSetDifference(
|
||||
expectedFulfillmentSetSet,
|
||||
fulfillmentSetSet
|
||||
)
|
||||
|
||||
if (missingFulfillmentSetIds.size) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.NOT_FOUND,
|
||||
`The following fulfillment sets does not exists: ${Array.from(
|
||||
missingFulfillmentSetIds
|
||||
).join(", ")}`
|
||||
)
|
||||
}
|
||||
|
||||
const fulfillmentSetMap = new Map<string, TEntity>(
|
||||
fulfillmentSets.map((f) => [f.id, f])
|
||||
)
|
||||
|
||||
// find service zones to delete
|
||||
const serviceZoneIdsToDelete: string[] = []
|
||||
const geoZoneIdsToDelete: string[] = []
|
||||
data_.forEach((fulfillmentSet) => {
|
||||
if (fulfillmentSet.service_zones) {
|
||||
/**
|
||||
* Detect and delete service zones that are not in the updated
|
||||
*/
|
||||
|
||||
const existingFulfillmentSet = fulfillmentSetMap.get(fulfillmentSet.id)!
|
||||
const existingServiceZones = existingFulfillmentSet.service_zones
|
||||
const updatedServiceZones = fulfillmentSet.service_zones
|
||||
const toDeleteServiceZoneIds = getSetDifference(
|
||||
new Set(existingServiceZones.map((s) => s.id)),
|
||||
new Set(
|
||||
updatedServiceZones
|
||||
.map((s) => "id" in s && s.id)
|
||||
.filter((id): id is string => !!id)
|
||||
)
|
||||
)
|
||||
if (toDeleteServiceZoneIds.size) {
|
||||
serviceZoneIdsToDelete.push(...Array.from(toDeleteServiceZoneIds))
|
||||
geoZoneIdsToDelete.push(
|
||||
...existingServiceZones
|
||||
.filter((s) => toDeleteServiceZoneIds.has(s.id))
|
||||
.flatMap((s) => s.geo_zones.map((g) => g.id))
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect and re assign service zones to the fulfillment set that are still present
|
||||
*/
|
||||
|
||||
const serviceZonesMap = new Map(
|
||||
existingFulfillmentSet.service_zones.map((serviceZone) => [
|
||||
serviceZone.id,
|
||||
serviceZone,
|
||||
])
|
||||
)
|
||||
const serviceZonesSet = new Set(
|
||||
existingServiceZones
|
||||
.map((s) => "id" in s && s.id)
|
||||
.filter((id): id is string => !!id)
|
||||
)
|
||||
const expectedServiceZoneSet = new Set(
|
||||
fulfillmentSet.service_zones
|
||||
.map((s) => "id" in s && s.id)
|
||||
.filter((id): id is string => !!id)
|
||||
)
|
||||
const missingServiceZoneIds = getSetDifference(
|
||||
expectedServiceZoneSet,
|
||||
serviceZonesSet
|
||||
)
|
||||
|
||||
if (missingServiceZoneIds.size) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.NOT_FOUND,
|
||||
`The following service zones does not exists: ${Array.from(
|
||||
missingServiceZoneIds
|
||||
).join(", ")}`
|
||||
)
|
||||
}
|
||||
|
||||
// re assign service zones to the fulfillment set
|
||||
if (fulfillmentSet.service_zones) {
|
||||
fulfillmentSet.service_zones = fulfillmentSet.service_zones.map(
|
||||
(serviceZone) => {
|
||||
if (!("id" in serviceZone)) {
|
||||
return serviceZone
|
||||
}
|
||||
return serviceZonesMap.get(serviceZone.id)!
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if (serviceZoneIdsToDelete.length) {
|
||||
await promiseAll([
|
||||
this.geoZoneService_.delete(
|
||||
{
|
||||
id: geoZoneIdsToDelete,
|
||||
},
|
||||
sharedContext
|
||||
),
|
||||
this.serviceZoneService_.delete(
|
||||
{
|
||||
id: serviceZoneIdsToDelete,
|
||||
},
|
||||
sharedContext
|
||||
),
|
||||
])
|
||||
}
|
||||
|
||||
const updatedFulfillmentSets = await this.fulfillmentSetService_.update(
|
||||
data_,
|
||||
sharedContext
|
||||
)
|
||||
|
||||
return Array.isArray(data)
|
||||
? updatedFulfillmentSets
|
||||
: updatedFulfillmentSets[0]
|
||||
}
|
||||
|
||||
updateServiceZones(
|
||||
@@ -142,16 +404,146 @@ export default class FulfillmentModuleService<
|
||||
sharedContext?: Context
|
||||
): Promise<FulfillmentTypes.ServiceZoneDTO>
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
@InjectManager("baseRepository_")
|
||||
async updateServiceZones(
|
||||
data:
|
||||
| FulfillmentTypes.UpdateServiceZoneDTO[]
|
||||
| FulfillmentTypes.UpdateServiceZoneDTO,
|
||||
sharedContext?: Context
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<
|
||||
FulfillmentTypes.ServiceZoneDTO[] | FulfillmentTypes.ServiceZoneDTO
|
||||
> {
|
||||
return []
|
||||
const updatedServiceZones = await this.updateServiceZones_(
|
||||
data,
|
||||
sharedContext
|
||||
)
|
||||
|
||||
return await this.baseRepository_.serialize<
|
||||
FulfillmentTypes.ServiceZoneDTO | FulfillmentTypes.ServiceZoneDTO[]
|
||||
>(updatedServiceZones, {
|
||||
populate: true,
|
||||
})
|
||||
}
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
protected async updateServiceZones_(
|
||||
data:
|
||||
| FulfillmentTypes.UpdateServiceZoneDTO[]
|
||||
| FulfillmentTypes.UpdateServiceZoneDTO,
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<TServiceZoneEntity | TServiceZoneEntity[]> {
|
||||
const data_ = Array.isArray(data) ? data : [data]
|
||||
|
||||
if (!data_.length) {
|
||||
return []
|
||||
}
|
||||
|
||||
const serviceZoneIds = data_.map((s) => s.id)
|
||||
if (!serviceZoneIds.length) {
|
||||
return []
|
||||
}
|
||||
|
||||
const serviceZones = await this.serviceZoneService_.list(
|
||||
{
|
||||
id: serviceZoneIds,
|
||||
},
|
||||
{
|
||||
relations: ["geo_zones"],
|
||||
},
|
||||
sharedContext
|
||||
)
|
||||
|
||||
const serviceZoneSet = new Set(serviceZones.map((s) => s.id))
|
||||
const expectedServiceZoneSet = new Set(data_.map((s) => s.id))
|
||||
const missingServiceZoneIds = getSetDifference(
|
||||
expectedServiceZoneSet,
|
||||
serviceZoneSet
|
||||
)
|
||||
|
||||
if (missingServiceZoneIds.size) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.NOT_FOUND,
|
||||
`The following service zones does not exists: ${Array.from(
|
||||
missingServiceZoneIds
|
||||
).join(", ")}`
|
||||
)
|
||||
}
|
||||
|
||||
const serviceZoneMap = new Map<string, TServiceZoneEntity>(
|
||||
serviceZones.map((s) => [s.id, s])
|
||||
)
|
||||
|
||||
const serviceZoneIdsToDelete: string[] = []
|
||||
const geoZoneIdsToDelete: string[] = []
|
||||
|
||||
data_.forEach((serviceZone) => {
|
||||
if (serviceZone.geo_zones) {
|
||||
const existingServiceZone = serviceZoneMap.get(serviceZone.id)!
|
||||
const existingGeoZones = existingServiceZone.geo_zones
|
||||
const updatedGeoZones = serviceZone.geo_zones
|
||||
const toDeleteGeoZoneIds = getSetDifference(
|
||||
new Set(existingGeoZones.map((g) => g.id)),
|
||||
new Set(
|
||||
updatedGeoZones
|
||||
.map((g) => "id" in g && g.id)
|
||||
.filter((id): id is string => !!id)
|
||||
)
|
||||
)
|
||||
if (toDeleteGeoZoneIds.size) {
|
||||
geoZoneIdsToDelete.push(...Array.from(toDeleteGeoZoneIds))
|
||||
}
|
||||
|
||||
const geoZonesMap = new Map(
|
||||
existingServiceZone.geo_zones.map((geoZone) => [geoZone.id, geoZone])
|
||||
)
|
||||
const geoZonesSet = new Set(
|
||||
existingGeoZones
|
||||
.map((g) => "id" in g && g.id)
|
||||
.filter((id): id is string => !!id)
|
||||
)
|
||||
const expectedGeoZoneSet = new Set(
|
||||
serviceZone.geo_zones
|
||||
.map((g) => "id" in g && g.id)
|
||||
.filter((id): id is string => !!id)
|
||||
)
|
||||
const missingGeoZoneIds = getSetDifference(
|
||||
expectedGeoZoneSet,
|
||||
geoZonesSet
|
||||
)
|
||||
|
||||
if (missingGeoZoneIds.size) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.NOT_FOUND,
|
||||
`The following geo zones does not exists: ${Array.from(
|
||||
missingGeoZoneIds
|
||||
).join(", ")}`
|
||||
)
|
||||
}
|
||||
|
||||
serviceZone.geo_zones = serviceZone.geo_zones.map((geoZone) => {
|
||||
if (!("id" in geoZone)) {
|
||||
return geoZone
|
||||
}
|
||||
return geoZonesMap.get(geoZone.id)!
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
if (geoZoneIdsToDelete.length) {
|
||||
await this.geoZoneService_.delete(
|
||||
{
|
||||
id: geoZoneIdsToDelete,
|
||||
},
|
||||
sharedContext
|
||||
)
|
||||
}
|
||||
|
||||
const updatedServiceZones = await this.serviceZoneService_.update(
|
||||
data_,
|
||||
sharedContext
|
||||
)
|
||||
|
||||
return Array.isArray(data) ? updatedServiceZones : updatedServiceZones[0]
|
||||
}
|
||||
|
||||
updateShippingOptions(
|
||||
@@ -168,10 +560,40 @@ export default class FulfillmentModuleService<
|
||||
data:
|
||||
| FulfillmentTypes.UpdateShippingOptionDTO[]
|
||||
| FulfillmentTypes.UpdateShippingOptionDTO,
|
||||
sharedContext?: Context
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<
|
||||
FulfillmentTypes.ShippingOptionDTO[] | FulfillmentTypes.ShippingOptionDTO
|
||||
> {
|
||||
return []
|
||||
}
|
||||
|
||||
updateGeoZones(
|
||||
data: FulfillmentTypes.UpdateGeoZoneDTO[],
|
||||
sharedContext?: Context
|
||||
): Promise<FulfillmentTypes.GeoZoneDTO[]>
|
||||
updateGeoZones(
|
||||
data: FulfillmentTypes.UpdateGeoZoneDTO,
|
||||
sharedContext?: Context
|
||||
): Promise<FulfillmentTypes.GeoZoneDTO>
|
||||
|
||||
@InjectManager("baseRepository_")
|
||||
async updateGeoZones(
|
||||
data:
|
||||
| FulfillmentTypes.UpdateGeoZoneDTO
|
||||
| FulfillmentTypes.UpdateGeoZoneDTO[],
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<FulfillmentTypes.GeoZoneDTO | FulfillmentTypes.GeoZoneDTO[]> {
|
||||
const updatedGeoZones = await this.geoZoneService_.update(
|
||||
data,
|
||||
sharedContext
|
||||
)
|
||||
|
||||
const serialized = await this.baseRepository_.serialize<
|
||||
FulfillmentTypes.GeoZoneDTO[]
|
||||
>(updatedGeoZones, {
|
||||
populate: true,
|
||||
})
|
||||
|
||||
return Array.isArray(data) ? serialized : serialized[0]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,12 @@ import { CreateServiceZoneDTO } from "./service-zone"
|
||||
export interface CreateFulfillmentSetDTO {
|
||||
name: string
|
||||
type: string
|
||||
service_zones: Omit<CreateServiceZoneDTO, "fulfillment_set_id">[]
|
||||
service_zones?: Omit<CreateServiceZoneDTO, 'fulfillment_set_id'>[]
|
||||
}
|
||||
|
||||
export interface UpdateFulfillmentSetDTO
|
||||
extends Partial<CreateFulfillmentSetDTO> {
|
||||
export interface UpdateFulfillmentSetDTO {
|
||||
id: string
|
||||
name?: string
|
||||
type?: string
|
||||
service_zones?: (Omit<CreateServiceZoneDTO, 'fulfillment_set_id'> | { id: string })[]
|
||||
}
|
||||
|
||||
@@ -9,24 +9,20 @@ interface CreateGeoZoneBaseDTO {
|
||||
|
||||
interface CreateCountryGeoZoneDTO extends CreateGeoZoneBaseDTO {
|
||||
type: "country"
|
||||
country_code: string
|
||||
}
|
||||
|
||||
interface CreateProvinceGeoZoneDTO extends CreateGeoZoneBaseDTO {
|
||||
type: "province"
|
||||
country_code: string
|
||||
province_code: string
|
||||
}
|
||||
|
||||
interface CreateCityGeoZoneDTO extends CreateGeoZoneBaseDTO {
|
||||
type: "city"
|
||||
country_code: string
|
||||
city: string
|
||||
}
|
||||
|
||||
interface CreateZipGeoZoneDTO extends CreateGeoZoneBaseDTO {
|
||||
type: "zip"
|
||||
country_code: string
|
||||
postal_expression: Record<string, any>
|
||||
}
|
||||
|
||||
@@ -42,24 +38,20 @@ interface UpdateGeoZoneBaseDTO extends Partial<CreateGeoZoneBaseDTO> {
|
||||
|
||||
interface UpdateCountryGeoZoneDTO extends UpdateGeoZoneBaseDTO {
|
||||
type: "country"
|
||||
country_code: string
|
||||
}
|
||||
|
||||
interface UpdateProvinceGeoZoneDTO extends UpdateGeoZoneBaseDTO {
|
||||
type: "province"
|
||||
country_code: string
|
||||
province_code: string
|
||||
}
|
||||
|
||||
interface UpdateCityGeoZoneDTO extends UpdateGeoZoneBaseDTO {
|
||||
type: "city"
|
||||
country_code: string
|
||||
city: string
|
||||
}
|
||||
|
||||
interface UpdateZipGeoZoneDTO extends UpdateGeoZoneBaseDTO {
|
||||
type: "zip"
|
||||
country_code: string
|
||||
postal_expression: Record<string, any>
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import { CreateGeoZoneDTO, UpdateGeoZoneDTO } from "./geo-zone"
|
||||
import { CreateGeoZoneDTO } from "./geo-zone"
|
||||
|
||||
export interface CreateServiceZoneDTO {
|
||||
fulfillment_set_id: string
|
||||
name: string
|
||||
geo_zones: (
|
||||
| Omit<CreateGeoZoneDTO, "service_zone_id">
|
||||
| Omit<UpdateGeoZoneDTO, "service_zone_id">
|
||||
)[]
|
||||
fulfillment_set_id: string
|
||||
geo_zones?: Omit<CreateGeoZoneDTO, "service_zone_id">[]
|
||||
}
|
||||
|
||||
export interface UpdateServiceZoneDTO extends Partial<CreateServiceZoneDTO> {
|
||||
export interface UpdateServiceZoneDTO {
|
||||
id: string
|
||||
name?: string
|
||||
geo_zones?: (Omit<CreateGeoZoneDTO, "service_zone_id"> | { id: string })[]
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { IModuleService } from "../modules-sdk"
|
||||
import {
|
||||
FilterableFulfillmentSetProps,
|
||||
FilterableGeoZoneProps,
|
||||
FilterableServiceZoneProps,
|
||||
FilterableShippingOptionProps,
|
||||
FulfillmentSetDTO,
|
||||
GeoZoneDTO,
|
||||
ServiceZoneDTO,
|
||||
ShippingOptionDTO,
|
||||
} from "./common"
|
||||
@@ -12,9 +14,11 @@ import { Context } from "../shared-context"
|
||||
import { RestoreReturn, SoftDeleteReturn } from "../dal"
|
||||
import {
|
||||
CreateFulfillmentSetDTO,
|
||||
CreateGeoZoneDTO,
|
||||
CreateServiceZoneDTO,
|
||||
CreateShippingOptionDTO,
|
||||
UpdateFulfillmentSetDTO,
|
||||
UpdateGeoZoneDTO,
|
||||
UpdateServiceZoneDTO,
|
||||
UpdateShippingOptionDTO,
|
||||
} from "./mutations"
|
||||
@@ -62,6 +66,20 @@ export interface IFulfillmentModuleService extends IModuleService {
|
||||
sharedContext?: Context
|
||||
): Promise<ShippingOptionDTO>
|
||||
|
||||
/**
|
||||
* Create a new geo zone
|
||||
* @param data
|
||||
* @param sharedContext
|
||||
*/
|
||||
createGeoZones(
|
||||
data: CreateGeoZoneDTO[],
|
||||
sharedContext?: Context
|
||||
): Promise<GeoZoneDTO[]>
|
||||
createGeoZones(
|
||||
data: CreateGeoZoneDTO,
|
||||
sharedContext?: Context
|
||||
): Promise<GeoZoneDTO>
|
||||
|
||||
/**
|
||||
* Update a fulfillment set
|
||||
* @param data
|
||||
@@ -104,6 +122,20 @@ export interface IFulfillmentModuleService extends IModuleService {
|
||||
sharedContext?: Context
|
||||
): Promise<ShippingOptionDTO>
|
||||
|
||||
/**
|
||||
* Update a geo zone
|
||||
* @param data
|
||||
* @param sharedContext
|
||||
*/
|
||||
updateGeoZones(
|
||||
data: UpdateGeoZoneDTO[],
|
||||
sharedContext?: Context
|
||||
): Promise<GeoZoneDTO[]>
|
||||
updateGeoZones(
|
||||
data: UpdateGeoZoneDTO,
|
||||
sharedContext?: Context
|
||||
): Promise<GeoZoneDTO>
|
||||
|
||||
/**
|
||||
* Delete a fulfillment set
|
||||
* @param ids
|
||||
@@ -128,6 +160,14 @@ export interface IFulfillmentModuleService extends IModuleService {
|
||||
deleteShippingOptions(ids: string[], sharedContext?: Context): Promise<void>
|
||||
deleteShippingOptions(id: string, sharedContext?: Context): Promise<void>
|
||||
|
||||
/**
|
||||
* Delete a geo zone
|
||||
* @param ids
|
||||
* @param sharedContext
|
||||
*/
|
||||
deleteGeoZones(ids: string[], sharedContext?: Context): Promise<void>
|
||||
deleteGeoZones(id: string, sharedContext?: Context): Promise<void>
|
||||
|
||||
/**
|
||||
* Retrieve a fulfillment set
|
||||
* @param id
|
||||
@@ -164,6 +204,18 @@ export interface IFulfillmentModuleService extends IModuleService {
|
||||
sharedContext?: Context
|
||||
): Promise<ShippingOptionDTO>
|
||||
|
||||
/**
|
||||
* Retrieve a geo zone
|
||||
* @param id
|
||||
* @param config
|
||||
* @param sharedContext
|
||||
*/
|
||||
retrieveGeoZone(
|
||||
id: string,
|
||||
config?: FindConfig<GeoZoneDTO>,
|
||||
sharedContext?: Context
|
||||
): Promise<GeoZoneDTO>
|
||||
|
||||
/**
|
||||
* List fulfillment sets
|
||||
* @param filters
|
||||
@@ -200,6 +252,18 @@ export interface IFulfillmentModuleService extends IModuleService {
|
||||
sharedContext?: Context
|
||||
): Promise<ShippingOptionDTO[]>
|
||||
|
||||
/**
|
||||
* List geo zones
|
||||
* @param filters
|
||||
* @param config
|
||||
* @param sharedContext
|
||||
*/
|
||||
listGeoZones(
|
||||
filters?: FilterableGeoZoneProps,
|
||||
config?: FindConfig<GeoZoneDTO>,
|
||||
sharedContext?: Context
|
||||
): Promise<GeoZoneDTO[]>
|
||||
|
||||
/**
|
||||
* List and count fulfillment sets
|
||||
* @param filters
|
||||
@@ -236,6 +300,18 @@ export interface IFulfillmentModuleService extends IModuleService {
|
||||
sharedContext?: Context
|
||||
): Promise<[ShippingOptionDTO[], number]>
|
||||
|
||||
/**
|
||||
* List and count geo zones
|
||||
* @param filters
|
||||
* @param config
|
||||
* @param sharedContext
|
||||
*/
|
||||
listAndCountGeoZones(
|
||||
filters?: FilterableGeoZoneProps,
|
||||
config?: FindConfig<GeoZoneDTO>,
|
||||
sharedContext?: Context
|
||||
): Promise<[GeoZoneDTO[], number]>
|
||||
|
||||
/**
|
||||
* Soft delete fulfillment sets
|
||||
* @param fulfillmentIds
|
||||
@@ -272,6 +348,18 @@ export interface IFulfillmentModuleService extends IModuleService {
|
||||
sharedContext?: Context
|
||||
): Promise<Record<string, string[]> | void>
|
||||
|
||||
/**
|
||||
* Soft delete geo zones
|
||||
* @param geoZoneIds
|
||||
* @param config
|
||||
* @param sharedContext
|
||||
*/
|
||||
softDeleteGeoZones<TReturnableLinkableKeys extends string = string>(
|
||||
geoZoneIds: string[],
|
||||
config?: SoftDeleteReturn<TReturnableLinkableKeys>,
|
||||
sharedContext?: Context
|
||||
): Promise<Record<string, string[]> | void>
|
||||
|
||||
restore<TReturnableLinkableKeys extends string = string>(
|
||||
fulfillmentIds: string[],
|
||||
config?: RestoreReturn<TReturnableLinkableKeys>,
|
||||
|
||||
19
packages/utils/src/common/get-set-difference.ts
Normal file
19
packages/utils/src/common/get-set-difference.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* Get the difference between two sets. The difference is the elements that are in the original set but not in the compare set.
|
||||
* @param orignalSet
|
||||
* @param compareSet
|
||||
*/
|
||||
export function getSetDifference<T>(
|
||||
orignalSet: Set<T>,
|
||||
compareSet: Set<T>
|
||||
): Set<T> {
|
||||
const difference = new Set<T>()
|
||||
|
||||
orignalSet.forEach((element) => {
|
||||
if (!compareSet.has(element)) {
|
||||
difference.add(element)
|
||||
}
|
||||
})
|
||||
|
||||
return difference
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
export * from "./alter-columns-helper"
|
||||
export * from "./array-difference"
|
||||
export * from "./get-set-difference"
|
||||
export * from "./build-query"
|
||||
export * from "./camel-to-snake-case"
|
||||
export * from "./container"
|
||||
@@ -46,4 +47,3 @@ export * from "./to-pascal-case"
|
||||
export * from "./transaction"
|
||||
export * from "./upper-case-first"
|
||||
export * from "./wrap-handler"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user