diff --git a/.changeset/tired-parents-like.md b/.changeset/tired-parents-like.md new file mode 100644 index 0000000000..11036e6e2a --- /dev/null +++ b/.changeset/tired-parents-like.md @@ -0,0 +1,6 @@ +--- +"@medusajs/fulfillment": minor +"@medusajs/types": minor +--- + +fix(fulfillment, types): make relationship between SO and SO type M:1 diff --git a/packages/core/types/src/fulfillment/mutations/shipping-option.ts b/packages/core/types/src/fulfillment/mutations/shipping-option.ts index ad878ca45c..3d694308f8 100644 --- a/packages/core/types/src/fulfillment/mutations/shipping-option.ts +++ b/packages/core/types/src/fulfillment/mutations/shipping-option.ts @@ -83,11 +83,23 @@ export interface UpdateShippingOptionDTO { */ provider_id?: string + /** + * The ID of the shipping option type. + */ + shipping_option_type_id?: string + + /** + * The ID of the type of shipping option. + * Column doesn't exist on the entity -> normalized to `shipping_option_type_id` + */ + type_id?: string + /** * The shipping option type associated with the shipping option. */ type?: - | CreateShippingOptionTypeDTO | string + | CreateShippingOptionTypeDTO + | string | { /** * The ID of the shipping option type. @@ -133,35 +145,35 @@ type CalculateShippingItems = { export type CalculatedRMAShippingContext = | { - /** - * The ID of the return. - */ - return_id: string - /** - * The details of the return's items. - */ - return_items: CalculateShippingItems[] - } + /** + * The ID of the return. + */ + return_id: string + /** + * The details of the return's items. + */ + return_items: CalculateShippingItems[] + } | { - /** - * The ID of the exchange. - */ - exchange_id: string - /** - * The details of the exchange's items. - */ - exchange_items: CalculateShippingItems[] - } + /** + * The ID of the exchange. + */ + exchange_id: string + /** + * The details of the exchange's items. + */ + exchange_items: CalculateShippingItems[] + } | { - /** - * The ID of the claim. - */ - claim_id: string - /** - * The details of the claim's items. - */ - claim_items: CalculateShippingItems[] - } + /** + * The ID of the claim. + */ + claim_id: string + /** + * The details of the claim's items. + */ + claim_items: CalculateShippingItems[] + } /** * The data needed for the associated fulfillment provider to calculate the price of a shipping option. diff --git a/packages/modules/fulfillment/src/migrations/.snapshot-medusa-fulfillment.json b/packages/modules/fulfillment/src/migrations/.snapshot-medusa-fulfillment.json index eb7e7fec8f..4b306733de 100644 --- a/packages/modules/fulfillment/src/migrations/.snapshot-medusa-fulfillment.json +++ b/packages/modules/fulfillment/src/migrations/.snapshot-medusa-fulfillment.json @@ -157,7 +157,7 @@ "constraint": false, "primary": false, "unique": false, - "expression": "CREATE INDEX IF NOT EXISTS \"IDX_fulfillment_address_deleted_at\" ON \"fulfillment_address\" (deleted_at) WHERE deleted_at IS NULL" + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_fulfillment_address_deleted_at\" ON \"fulfillment_address\" (\"deleted_at\") WHERE deleted_at IS NULL" }, { "keyName": "fulfillment_address_pkey", @@ -238,7 +238,7 @@ "constraint": false, "primary": false, "unique": false, - "expression": "CREATE INDEX IF NOT EXISTS \"IDX_fulfillment_provider_deleted_at\" ON \"fulfillment_provider\" (deleted_at) WHERE deleted_at IS NULL" + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_fulfillment_provider_deleted_at\" ON \"fulfillment_provider\" (\"deleted_at\") WHERE deleted_at IS NULL" }, { "keyName": "fulfillment_provider_pkey", @@ -336,7 +336,7 @@ "constraint": false, "primary": false, "unique": false, - "expression": "CREATE INDEX IF NOT EXISTS \"IDX_fulfillment_set_deleted_at\" ON \"fulfillment_set\" (deleted_at) WHERE deleted_at IS NULL" + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_fulfillment_set_deleted_at\" ON \"fulfillment_set\" (\"deleted_at\") WHERE deleted_at IS NULL" }, { "keyName": "IDX_fulfillment_set_name_unique", @@ -345,7 +345,7 @@ "constraint": false, "primary": false, "unique": false, - "expression": "CREATE UNIQUE INDEX IF NOT EXISTS \"IDX_fulfillment_set_name_unique\" ON \"fulfillment_set\" (name) WHERE deleted_at IS NULL" + "expression": "CREATE UNIQUE INDEX IF NOT EXISTS \"IDX_fulfillment_set_name_unique\" ON \"fulfillment_set\" (\"name\") WHERE deleted_at IS NULL" }, { "keyName": "fulfillment_set_pkey", @@ -443,7 +443,7 @@ "constraint": false, "primary": false, "unique": false, - "expression": "CREATE INDEX IF NOT EXISTS \"IDX_service_zone_fulfillment_set_id\" ON \"service_zone\" (fulfillment_set_id) WHERE deleted_at IS NULL" + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_service_zone_fulfillment_set_id\" ON \"service_zone\" (\"fulfillment_set_id\") WHERE deleted_at IS NULL" }, { "keyName": "IDX_service_zone_deleted_at", @@ -452,7 +452,7 @@ "constraint": false, "primary": false, "unique": false, - "expression": "CREATE INDEX IF NOT EXISTS \"IDX_service_zone_deleted_at\" ON \"service_zone\" (deleted_at) WHERE deleted_at IS NULL" + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_service_zone_deleted_at\" ON \"service_zone\" (\"deleted_at\") WHERE deleted_at IS NULL" }, { "keyName": "IDX_service_zone_name_unique", @@ -461,7 +461,7 @@ "constraint": false, "primary": false, "unique": false, - "expression": "CREATE UNIQUE INDEX IF NOT EXISTS \"IDX_service_zone_name_unique\" ON \"service_zone\" (name) WHERE deleted_at IS NULL" + "expression": "CREATE UNIQUE INDEX IF NOT EXISTS \"IDX_service_zone_name_unique\" ON \"service_zone\" (\"name\") WHERE deleted_at IS NULL" }, { "keyName": "service_zone_pkey", @@ -616,7 +616,7 @@ "constraint": false, "primary": false, "unique": false, - "expression": "CREATE INDEX IF NOT EXISTS \"IDX_geo_zone_service_zone_id\" ON \"geo_zone\" (service_zone_id) WHERE deleted_at IS NULL" + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_geo_zone_service_zone_id\" ON \"geo_zone\" (\"service_zone_id\") WHERE deleted_at IS NULL" }, { "keyName": "IDX_geo_zone_deleted_at", @@ -625,7 +625,7 @@ "constraint": false, "primary": false, "unique": false, - "expression": "CREATE INDEX IF NOT EXISTS \"IDX_geo_zone_deleted_at\" ON \"geo_zone\" (deleted_at) WHERE deleted_at IS NULL" + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_geo_zone_deleted_at\" ON \"geo_zone\" (\"deleted_at\") WHERE deleted_at IS NULL" }, { "keyName": "IDX_geo_zone_country_code", @@ -634,7 +634,7 @@ "constraint": false, "primary": false, "unique": false, - "expression": "CREATE INDEX IF NOT EXISTS \"IDX_geo_zone_country_code\" ON \"geo_zone\" (country_code) WHERE deleted_at IS NULL" + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_geo_zone_country_code\" ON \"geo_zone\" (\"country_code\") WHERE deleted_at IS NULL" }, { "keyName": "IDX_geo_zone_province_code", @@ -643,7 +643,7 @@ "constraint": false, "primary": false, "unique": false, - "expression": "CREATE INDEX IF NOT EXISTS \"IDX_geo_zone_province_code\" ON \"geo_zone\" (province_code) WHERE deleted_at IS NULL" + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_geo_zone_province_code\" ON \"geo_zone\" (\"province_code\") WHERE deleted_at IS NULL" }, { "keyName": "IDX_geo_zone_city", @@ -652,7 +652,7 @@ "constraint": false, "primary": false, "unique": false, - "expression": "CREATE INDEX IF NOT EXISTS \"IDX_geo_zone_city\" ON \"geo_zone\" (city) WHERE deleted_at IS NULL" + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_geo_zone_city\" ON \"geo_zone\" (\"city\") WHERE deleted_at IS NULL" }, { "keyName": "geo_zone_pkey", @@ -764,7 +764,7 @@ "constraint": false, "primary": false, "unique": false, - "expression": "CREATE INDEX IF NOT EXISTS \"IDX_shipping_option_type_deleted_at\" ON \"shipping_option_type\" (deleted_at) WHERE deleted_at IS NULL" + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_shipping_option_type_deleted_at\" ON \"shipping_option_type\" (\"deleted_at\") WHERE deleted_at IS NULL" }, { "keyName": "shipping_option_type_pkey", @@ -862,7 +862,7 @@ "constraint": false, "primary": false, "unique": false, - "expression": "CREATE INDEX IF NOT EXISTS \"IDX_shipping_profile_deleted_at\" ON \"shipping_profile\" (deleted_at) WHERE deleted_at IS NULL" + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_shipping_profile_deleted_at\" ON \"shipping_profile\" (\"deleted_at\") WHERE deleted_at IS NULL" }, { "keyName": "IDX_shipping_profile_name_unique", @@ -871,7 +871,7 @@ "constraint": false, "primary": false, "unique": false, - "expression": "CREATE UNIQUE INDEX IF NOT EXISTS \"IDX_shipping_profile_name_unique\" ON \"shipping_profile\" (name) WHERE deleted_at IS NULL" + "expression": "CREATE UNIQUE INDEX IF NOT EXISTS \"IDX_shipping_profile_name_unique\" ON \"shipping_profile\" (\"name\") WHERE deleted_at IS NULL" }, { "keyName": "shipping_profile_pkey", @@ -1019,7 +1019,7 @@ "constraint": false, "primary": false, "unique": false, - "expression": "CREATE INDEX IF NOT EXISTS \"IDX_shipping_option_service_zone_id\" ON \"shipping_option\" (service_zone_id) WHERE deleted_at IS NULL" + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_shipping_option_service_zone_id\" ON \"shipping_option\" (\"service_zone_id\") WHERE deleted_at IS NULL" }, { "keyName": "IDX_shipping_option_shipping_profile_id", @@ -1028,7 +1028,7 @@ "constraint": false, "primary": false, "unique": false, - "expression": "CREATE INDEX IF NOT EXISTS \"IDX_shipping_option_shipping_profile_id\" ON \"shipping_option\" (shipping_profile_id) WHERE deleted_at IS NULL" + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_shipping_option_shipping_profile_id\" ON \"shipping_option\" (\"shipping_profile_id\") WHERE deleted_at IS NULL" }, { "keyName": "IDX_shipping_option_provider_id", @@ -1037,7 +1037,16 @@ "constraint": false, "primary": false, "unique": false, - "expression": "CREATE INDEX IF NOT EXISTS \"IDX_shipping_option_provider_id\" ON \"shipping_option\" (provider_id) WHERE deleted_at IS NULL" + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_shipping_option_provider_id\" ON \"shipping_option\" (\"provider_id\") WHERE deleted_at IS NULL" + }, + { + "keyName": "IDX_shipping_option_shipping_option_type_id", + "columnNames": [], + "composite": false, + "constraint": false, + "primary": false, + "unique": false, + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_shipping_option_shipping_option_type_id\" ON \"shipping_option\" (\"shipping_option_type_id\") WHERE deleted_at IS NULL" }, { "keyName": "IDX_shipping_option_deleted_at", @@ -1046,7 +1055,7 @@ "constraint": false, "primary": false, "unique": false, - "expression": "CREATE INDEX IF NOT EXISTS \"IDX_shipping_option_deleted_at\" ON \"shipping_option\" (deleted_at) WHERE deleted_at IS NULL" + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_shipping_option_deleted_at\" ON \"shipping_option\" (\"deleted_at\") WHERE deleted_at IS NULL" }, { "keyName": "shipping_option_pkey", @@ -1215,7 +1224,7 @@ "constraint": false, "primary": false, "unique": false, - "expression": "CREATE INDEX IF NOT EXISTS \"IDX_shipping_option_rule_shipping_option_id\" ON \"shipping_option_rule\" (shipping_option_id) WHERE deleted_at IS NULL" + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_shipping_option_rule_shipping_option_id\" ON \"shipping_option_rule\" (\"shipping_option_id\") WHERE deleted_at IS NULL" }, { "keyName": "IDX_shipping_option_rule_deleted_at", @@ -1224,7 +1233,7 @@ "constraint": false, "primary": false, "unique": false, - "expression": "CREATE INDEX IF NOT EXISTS \"IDX_shipping_option_rule_deleted_at\" ON \"shipping_option_rule\" (deleted_at) WHERE deleted_at IS NULL" + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_shipping_option_rule_deleted_at\" ON \"shipping_option_rule\" (\"deleted_at\") WHERE deleted_at IS NULL" }, { "keyName": "shipping_option_rule_pkey", @@ -1431,7 +1440,7 @@ "constraint": false, "primary": false, "unique": false, - "expression": "CREATE INDEX IF NOT EXISTS \"IDX_fulfillment_shipping_option_id\" ON \"fulfillment\" (shipping_option_id) WHERE deleted_at IS NULL" + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_fulfillment_shipping_option_id\" ON \"fulfillment\" (\"shipping_option_id\") WHERE deleted_at IS NULL" }, { "keyName": "IDX_fulfillment_deleted_at", @@ -1440,7 +1449,7 @@ "constraint": false, "primary": false, "unique": false, - "expression": "CREATE INDEX IF NOT EXISTS \"IDX_fulfillment_deleted_at\" ON \"fulfillment\" (deleted_at) WHERE deleted_at IS NULL" + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_fulfillment_deleted_at\" ON \"fulfillment\" (\"deleted_at\") WHERE deleted_at IS NULL" }, { "keyName": "IDX_fulfillment_location_id", @@ -1449,7 +1458,7 @@ "constraint": false, "primary": false, "unique": false, - "expression": "CREATE INDEX IF NOT EXISTS \"IDX_fulfillment_location_id\" ON \"fulfillment\" (location_id) WHERE deleted_at IS NULL" + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_fulfillment_location_id\" ON \"fulfillment\" (\"location_id\") WHERE deleted_at IS NULL" }, { "keyName": "fulfillment_pkey", @@ -1596,7 +1605,7 @@ "constraint": false, "primary": false, "unique": false, - "expression": "CREATE INDEX IF NOT EXISTS \"IDX_fulfillment_label_fulfillment_id\" ON \"fulfillment_label\" (fulfillment_id) WHERE deleted_at IS NULL" + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_fulfillment_label_fulfillment_id\" ON \"fulfillment_label\" (\"fulfillment_id\") WHERE deleted_at IS NULL" }, { "keyName": "IDX_fulfillment_label_deleted_at", @@ -1605,7 +1614,7 @@ "constraint": false, "primary": false, "unique": false, - "expression": "CREATE INDEX IF NOT EXISTS \"IDX_fulfillment_label_deleted_at\" ON \"fulfillment_label\" (deleted_at) WHERE deleted_at IS NULL" + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_fulfillment_label_deleted_at\" ON \"fulfillment_label\" (\"deleted_at\") WHERE deleted_at IS NULL" }, { "keyName": "fulfillment_label_pkey", @@ -1762,7 +1771,7 @@ "constraint": false, "primary": false, "unique": false, - "expression": "CREATE INDEX IF NOT EXISTS \"IDX_fulfillment_item_fulfillment_id\" ON \"fulfillment_item\" (fulfillment_id) WHERE deleted_at IS NULL" + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_fulfillment_item_fulfillment_id\" ON \"fulfillment_item\" (\"fulfillment_id\") WHERE deleted_at IS NULL" }, { "keyName": "IDX_fulfillment_item_deleted_at", @@ -1771,7 +1780,7 @@ "constraint": false, "primary": false, "unique": false, - "expression": "CREATE INDEX IF NOT EXISTS \"IDX_fulfillment_item_deleted_at\" ON \"fulfillment_item\" (deleted_at) WHERE deleted_at IS NULL" + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_fulfillment_item_deleted_at\" ON \"fulfillment_item\" (\"deleted_at\") WHERE deleted_at IS NULL" }, { "keyName": "IDX_fulfillment_item_inventory_item_id", @@ -1780,7 +1789,7 @@ "constraint": false, "primary": false, "unique": false, - "expression": "CREATE INDEX IF NOT EXISTS \"IDX_fulfillment_item_inventory_item_id\" ON \"fulfillment_item\" (inventory_item_id) WHERE deleted_at IS NULL" + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_fulfillment_item_inventory_item_id\" ON \"fulfillment_item\" (\"inventory_item_id\") WHERE deleted_at IS NULL" }, { "keyName": "IDX_fulfillment_item_line_item_id", @@ -1789,7 +1798,7 @@ "constraint": false, "primary": false, "unique": false, - "expression": "CREATE INDEX IF NOT EXISTS \"IDX_fulfillment_item_line_item_id\" ON \"fulfillment_item\" (line_item_id) WHERE deleted_at IS NULL" + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_fulfillment_item_line_item_id\" ON \"fulfillment_item\" (\"line_item_id\") WHERE deleted_at IS NULL" }, { "keyName": "fulfillment_item_pkey", diff --git a/packages/modules/fulfillment/src/migrations/Migration20251114133146.ts b/packages/modules/fulfillment/src/migrations/Migration20251114133146.ts new file mode 100644 index 0000000000..0fa7fe5767 --- /dev/null +++ b/packages/modules/fulfillment/src/migrations/Migration20251114133146.ts @@ -0,0 +1,13 @@ +import { Migration } from '@mikro-orm/migrations'; + +export class Migration20251114133146 extends Migration { + + override async up(): Promise { + 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;`); + } + + override async down(): Promise { + this.addSql(`drop index if exists "IDX_shipping_option_shipping_option_type_id";`); + } + +} diff --git a/packages/modules/fulfillment/src/models/shipping-option-type.ts b/packages/modules/fulfillment/src/models/shipping-option-type.ts index 065a8b10ed..31c74b3bbb 100644 --- a/packages/modules/fulfillment/src/models/shipping-option-type.ts +++ b/packages/modules/fulfillment/src/models/shipping-option-type.ts @@ -7,7 +7,7 @@ export const ShippingOptionType = model.define("shipping_option_type", { label: model.text().searchable(), description: model.text().searchable().nullable(), code: model.text().searchable(), - shipping_option: model.hasOne(() => ShippingOption, { + shipping_options: model.hasMany(() => ShippingOption, { mappedBy: "type", }), }) diff --git a/packages/modules/fulfillment/src/models/shipping-option.ts b/packages/modules/fulfillment/src/models/shipping-option.ts index 9a1ee4ff3b..a43c6227f7 100644 --- a/packages/modules/fulfillment/src/models/shipping-option.ts +++ b/packages/modules/fulfillment/src/models/shipping-option.ts @@ -25,10 +25,10 @@ export const ShippingOption = model }) .nullable(), provider: model.belongsTo(() => FulfillmentProvider).nullable(), - type: model.hasOne(() => ShippingOptionType, { + type: model.belongsTo(() => ShippingOptionType, { foreignKey: true, foreignKeyName: "shipping_option_type_id", - mappedBy: undefined, + mappedBy: "shipping_options", }), rules: model.hasMany(() => ShippingOptionRule, { mappedBy: "shipping_option", diff --git a/packages/modules/fulfillment/src/services/fulfillment-module-service.ts b/packages/modules/fulfillment/src/services/fulfillment-module-service.ts index 2de8932ae0..124fceaa72 100644 --- a/packages/modules/fulfillment/src/services/fulfillment-module-service.ts +++ b/packages/modules/fulfillment/src/services/fulfillment-module-service.ts @@ -35,7 +35,6 @@ import { ModulesSdkUtils, promiseAll, } from "@medusajs/framework/utils" -import { isObject } from "@medusajs/utils" import { Fulfillment, FulfillmentProvider, @@ -1282,6 +1281,7 @@ export default class FulfillmentModuleService }, sharedContext ) + const existingShippingOptions = new Map( shippingOptions.map((s) => [s.id, s]) ) @@ -1295,15 +1295,15 @@ export default class FulfillmentModuleService const updatedRuleIds: string[] = [] const existingRuleIds: string[] = [] - const optionTypeDeletedIds: string[] = [] - dataArray.forEach((shippingOption) => { const existingShippingOption = existingShippingOptions.get( shippingOption.id )! // Guaranteed to exist since the validation above have been performed - if (isObject(shippingOption.type) && !("id" in shippingOption.type)) { - optionTypeDeletedIds.push(existingShippingOption.type.id) + // `type_id` doesn't exist on the entity/table, `type_id` argument is mapped to `shipping_option_type_id` + if (shippingOption.type_id) { + shippingOption.shipping_option_type_id = shippingOption.type_id + delete shippingOption.type_id } if (!shippingOption.rules) {