Skip to content

Commit

Permalink
feat(fulfillment): Shipping options, rules CRUD + rules based context…
Browse files Browse the repository at this point in the history
… filtering (medusajs#6455)

**What**
- Update shipping options with its rules and type
- create/update rules independently
- context based validation fundation
- 🔴 list shipping options with context rules fitlering will come in a separate pr to keep this one smaller

FIXES CORE-1743
FIXES CORE-1764
  • Loading branch information
adrien2p authored Feb 23, 2024
1 parent 78b6d46 commit 788c4a1
Show file tree
Hide file tree
Showing 19 changed files with 1,767 additions and 55 deletions.

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions packages/fulfillment/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ module.exports = {
"^@services": "<rootDir>/src/services",
"^@repositories": "<rootDir>/src/repositories",
"^@types": "<rootDir>/src/types",
"^@utils": "<rootDir>/src/utils",
},
transform: {
"^.+\\.[jt]s?$": [
Expand Down
2 changes: 1 addition & 1 deletion packages/fulfillment/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"test": "jest --runInBand --bail --forceExit -- src/**/__tests__/**/*.ts",
"test:integration": "jest --runInBand --forceExit -- integration-tests/**/__tests__/**/*.spec.ts",
"migration:generate": " MIKRO_ORM_CLI=./mikro-orm.config.dev.ts mikro-orm migration:generate",
"migration:initial": " MIKRO_ORM_CLI=./mikro-orm.config.dev.ts mikro-orm migration:create --initial",
"migration:initial": " MIKRO_ORM_CLI=./mikro-orm.config.dev.ts mikro-orm migration:create --initial -n InitialSetupMigration",
"migration:create": " MIKRO_ORM_CLI=./mikro-orm.config.dev.ts mikro-orm migration:create",
"migration:up": " MIKRO_ORM_CLI=./mikro-orm.config.dev.ts mikro-orm migration:up",
"orm:cache:clear": " MIKRO_ORM_CLI=./mikro-orm.config.dev.ts mikro-orm cache:clear"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,20 @@
}
],
"checks": [],
"foreignKeys": {}
"foreignKeys": {
"service_zone_fulfillment_set_id_foreign": {
"constraintName": "service_zone_fulfillment_set_id_foreign",
"columnNames": [
"fulfillment_set_id"
],
"localTableName": "public.service_zone",
"referencedColumnNames": [
"id"
],
"referencedTableName": "public.fulfillment_set",
"updateRule": "cascade"
}
}
},
{
"columns": {
Expand Down Expand Up @@ -673,7 +686,20 @@
}
],
"checks": [],
"foreignKeys": {}
"foreignKeys": {
"geo_zone_service_zone_id_foreign": {
"constraintName": "geo_zone_service_zone_id_foreign",
"columnNames": [
"service_zone_id"
],
"localTableName": "public.geo_zone",
"referencedColumnNames": [
"id"
],
"referencedTableName": "public.service_zone",
"updateRule": "cascade"
}
}
},
{
"columns": {
Expand Down Expand Up @@ -713,15 +739,6 @@
"nullable": false,
"mappedType": "text"
},
"shipping_option_id": {
"name": "shipping_option_id",
"type": "text",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": false,
"mappedType": "text"
},
"created_at": {
"name": "created_at",
"type": "timestamptz",
Expand Down Expand Up @@ -758,16 +775,6 @@
"name": "shipping_option_type",
"schema": "public",
"indexes": [
{
"keyName": "IDX_shipping_option_type_shipping_option_id",
"columnNames": [
"shipping_option_id"
],
"composite": false,
"primary": false,
"unique": false,
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_shipping_option_type_shipping_option_id\" ON \"shipping_option_type\" (shipping_option_id) WHERE deleted_at IS NULL"
},
{
"keyName": "IDX_shipping_option_type_deleted_at",
"columnNames": [
Expand Down Expand Up @@ -1093,6 +1100,18 @@
],
"checks": [],
"foreignKeys": {
"shipping_option_service_zone_id_foreign": {
"constraintName": "shipping_option_service_zone_id_foreign",
"columnNames": [
"service_zone_id"
],
"localTableName": "public.shipping_option",
"referencedColumnNames": [
"id"
],
"referencedTableName": "public.service_zone",
"updateRule": "cascade"
},
"shipping_option_shipping_profile_id_foreign": {
"constraintName": "shipping_option_shipping_profile_id_foreign",
"columnNames": [
Expand Down Expand Up @@ -1161,7 +1180,17 @@
"autoincrement": false,
"primary": false,
"nullable": false,
"mappedType": "text"
"enumItems": [
"in",
"eq",
"ne",
"gt",
"gte",
"lt",
"lte",
"nin"
],
"mappedType": "enum"
},
"value": {
"name": "value",
Expand Down Expand Up @@ -1248,7 +1277,20 @@
}
],
"checks": [],
"foreignKeys": {}
"foreignKeys": {
"shipping_option_rule_shipping_option_id_foreign": {
"constraintName": "shipping_option_rule_shipping_option_id_foreign",
"columnNames": [
"shipping_option_id"
],
"localTableName": "public.shipping_option_rule",
"referencedColumnNames": [
"id"
],
"referencedTableName": "public.shipping_option",
"updateRule": "cascade"
}
}
},
{
"columns": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Migration } from '@mikro-orm/migrations';

export class Migration20240219115644 extends Migration {
export class Migration20240221164918_InitialSetupMigration 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"));');
Expand All @@ -26,8 +26,7 @@ export class Migration20240219115644 extends Migration {
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 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"));');
Expand All @@ -42,7 +41,7 @@ export class Migration20240219115644 extends Migration {
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 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;');

Expand All @@ -62,10 +61,17 @@ export class Migration20240219115644 extends Migration {
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 on delete set null;');
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 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;');

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;');
Expand Down
6 changes: 5 additions & 1 deletion packages/fulfillment/src/models/geo-zone.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,11 @@ export default class GeoZone {
@Property({ columnType: "text", nullable: true })
city: string | null = null

@Property({ columnType: "text" })
@ManyToOne(() => ServiceZone, {
type: "text",
mapToPk: true,
fieldName: "service_zone_id",
})
@ServiceZoneIdIndex.MikroORMIndex()
service_zone_id: string

Expand Down
6 changes: 5 additions & 1 deletion packages/fulfillment/src/models/service-zone.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,11 @@ export default class ServiceZone {
@Property({ columnType: "jsonb", nullable: true })
metadata: Record<string, unknown> | null = null

@Property({ columnType: "text" })
@ManyToOne(() => FulfillmentSet, {
type: "text",
mapToPk: true,
fieldName: "fulfillment_set_id",
})
@FulfillmentSetIdIndex.MikroORMIndex()
fulfillment_set_id: string

Expand Down
21 changes: 16 additions & 5 deletions packages/fulfillment/src/models/shipping-option-rule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { DAL } from "@medusajs/types"
import {
BeforeCreate,
Entity,
Enum,
Filter,
ManyToOne,
OnInit,
Expand All @@ -16,6 +17,7 @@ import {
Property,
} from "@mikro-orm/core"
import ShippingOption from "./shipping-option"
import { RuleOperator } from "@utils"

type ShippingOptionRuleOptionalProps = DAL.SoftDeletableEntityDateColumns

Expand All @@ -42,17 +44,26 @@ export default class ShippingOptionRule {
@Property({ columnType: "text" })
attribute: string

@Property({ columnType: "text" })
operator: string
@Enum({
items: () => Object.values(RuleOperator),
columnType: "text",
})
operator: Lowercase<keyof typeof RuleOperator>

@Property({ columnType: "jsonb", nullable: true })
value: { value: string | string[] } | null = null
value: string | string[] | null = null

@Property({ columnType: "text" })
@ManyToOne(() => ShippingOption, {
type: "text",
mapToPk: true,
fieldName: "shipping_option_id",
})
@ShippingOptionIdIndex.MikroORMIndex()
shipping_option_id: string

@ManyToOne(() => ShippingOption, { persist: false })
@ManyToOne(() => ShippingOption, {
persist: false,
})
shipping_option: ShippingOption

@Property({
Expand Down
8 changes: 1 addition & 7 deletions packages/fulfillment/src/models/shipping-option-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,8 @@ export default class ShippingOptionType {
@Property({ columnType: "text" })
code: string

@Property({ columnType: "text" })
@ShippingOptionIdIndex.MikroORMIndex()
shipping_option_id: string

@OneToOne(() => ShippingOption, (so) => so.type, {
persist: false,
type: "text",
})
shipping_option: ShippingOption

Expand All @@ -79,12 +75,10 @@ export default class ShippingOptionType {
@BeforeCreate()
onCreate() {
this.id = generateEntityId(this.id, "sotype")
this.shipping_option_id ??= this.shipping_option?.id
}

@OnInit()
onInit() {
this.id = generateEntityId(this.id, "sotype")
this.shipping_option_id ??= this.shipping_option?.id
}
}
3 changes: 2 additions & 1 deletion packages/fulfillment/src/models/shipping-option.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export default class ShippingOption {
})
price_type: ShippingOptionPriceType

@ManyToOne(() => ShippingProfile, {
@ManyToOne(() => ServiceZone, {
type: "text",
fieldName: "service_zone_id",
mapToPk: true,
Expand Down Expand Up @@ -129,6 +129,7 @@ export default class ShippingOption {
@OneToOne(() => ShippingOptionType, (so) => so.shipping_option, {
owner: true,
cascade: [Cascade.PERSIST, Cascade.REMOVE, "soft-remove"] as any,
orphanRemoval: true,
fieldName: "shipping_option_type_id",
})
type: ShippingOptionType
Expand Down
Loading

0 comments on commit 788c4a1

Please sign in to comment.