chore(order): custom display id (#14024)

* chore(order): Accept a custom display generator option

* chore(order): Accept a custom display generator option

* wip

* wip

* finalize

* Create tricky-olives-battle.md

* fields

* changeset

* update integration tests

* update migrations

* fix changeset
This commit is contained in:
Adrien de Peretti authored and GitHub committed 2025-11-18 10:17:46 +01:00
1 parent 0a0c2f41d8
commit 6746fecd72
29 files changed
+479 -260

No files matched your search

+9
View File
@@ -0,0 +1,9 @@
---
"@medusajs/medusa": patch
"@medusajs/order": patch
"@medusajs/dashboard": patch
"@medusajs/core-flows": patch
"@medusajs/types": patch
---
Chore/order custom display
@@ -281,6 +281,7 @@ medusaIntegrationTestRunner({
status: "pending", status: "pending",
version: 1, version: 1,
display_id: 2, display_id: 2,
custom_display_id: null,
payment_collections: [], payment_collections: [],
payment_status: "not_paid", payment_status: "not_paid",
region_id: "test_region_id", region_id: "test_region_id",
@@ -5,6 +5,7 @@ const DEFAULT_PROPERTIES = [
"canceled_at", "canceled_at",
"email", "email",
"display_id", "display_id",
"custom_display_id",
"currency_code", "currency_code",
"metadata", "metadata",
// --- TOTALS --- // --- TOTALS ---
@@ -4,6 +4,7 @@ export const DEFAULT_PROPERTIES = [
"created_at", "created_at",
"email", "email",
"display_id", "display_id",
"custom_display_id",
"payment_status", "payment_status",
"fulfillment_status", "fulfillment_status",
"total", "total",
@@ -400,6 +400,7 @@ export const createOrderFulfillmentWorkflow = createWorkflow(
fields: [ fields: [
"id", "id",
"display_id", "display_id",
"custom_display_id",
"status", "status",
"customer_id", "customer_id",
"customer.*", "customer.*",
@@ -740,6 +740,10 @@ export interface BaseOrder {
* The order's display ID. * The order's display ID.
*/ */
display_id?: number display_id?: number
/**
* The order's custom display ID.
*/
custom_display_id?: string
/** /**
* The order's status. * The order's status.
*/ */
+5
View File
@@ -1036,6 +1036,11 @@ export interface OrderDTO {
*/ */
display_id: number display_id: number
/**
* The order's custom display ID.
*/
custom_display_id?: string
/** /**
* The active order change, if any. * The active order change, if any.
* *
@@ -1,6 +1,7 @@
export const defaultAdminListOrderFields = [ export const defaultAdminListOrderFields = [
"id", "id",
"display_id", "display_id",
"custom_display_id",
"status", "status",
"version", "version",
"email", "email",
@@ -16,6 +17,7 @@ export const defaultAdminListOrderFields = [
export const defaultAdminOrderFields = [ export const defaultAdminOrderFields = [
"id", "id",
"display_id", "display_id",
"custom_display_id",
"status", "status",
"version", "version",
"email", "email",
@@ -1,6 +1,7 @@
export const defaultAdminOrderFields = [ export const defaultAdminOrderFields = [
"id", "id",
"display_id", "display_id",
"custom_display_id",
"status", "status",
"version", "version",
"summary", "summary",
@@ -22,14 +22,19 @@ export const getColumnCategory = (
semanticType?: string semanticType?: string
): HttpTypes.AdminColumn["category"] => { ): HttpTypes.AdminColumn["category"] => {
// Check semantic type first // Check semantic type first
if (semanticType === "timestamp") return "timestamp" if (semanticType === "timestamp") {
if (semanticType === "status") return "status" return "timestamp"
}
if (semanticType === "status") {
return "status"
}
// Check field name patterns // Check field name patterns
if ( if (
fieldName.includes("_id") || fieldName.includes("_id") ||
fieldName === "id" || fieldName === "id" ||
fieldName.includes("display_id") || fieldName.includes("display_id") ||
fieldName.includes("custom_display_id") ||
fieldName === "code" fieldName === "code"
) { ) {
return "identifier" return "identifier"
@@ -191,7 +196,7 @@ export const getTypeInfoFromGraphQLType = (
semantic_type: "object", semantic_type: "object",
context: "metadata", context: "metadata",
} }
} else if (fieldName === "display_id") { } else if (fieldName === "display_id" || fieldName === "custom_display_id") {
return { return {
data_type: "string", data_type: "string",
semantic_type: "identifier", semantic_type: "identifier",
@@ -264,6 +269,7 @@ const ADDITIONAL_ENTITY_TYPES: Partial<Record<Entities, string[]>> = {
export const DEFAULT_COLUMN_ORDERS: Record<Entities, Record<string, number>> = { export const DEFAULT_COLUMN_ORDERS: Record<Entities, Record<string, number>> = {
orders: { orders: {
display_id: 100, display_id: 100,
custom_display_id: 101,
created_at: 200, created_at: 200,
customer_display: 300, customer_display: 300,
"sales_channel.name": 400, "sales_channel.name": 400,
@@ -370,6 +376,10 @@ export const generateEntityColumns = (
directFields.unshift("display_id") directFields.unshift("display_id")
} }
if (entity === "orders" && !directFields.includes("custom_display_id")) {
directFields.unshift("custom_display_id")
}
const additionalTypes = ADDITIONAL_ENTITY_TYPES[entity as Entities] ?? [] const additionalTypes = ADDITIONAL_ENTITY_TYPES[entity as Entities] ?? []
additionalTypes.forEach((typeName) => { additionalTypes.forEach((typeName) => {
@@ -380,11 +390,7 @@ export const generateEntityColumns = (
return return
} }
const additionalFields = graphqlSchemaToFields( const additionalFields = graphqlSchemaToFields(schemaTypeMap, typeName, [])
schemaTypeMap,
typeName,
[]
)
additionalFields.forEach((fieldName) => { additionalFields.forEach((fieldName) => {
if (directFields.includes(fieldName)) { if (directFields.includes(fieldName)) {
@@ -460,7 +466,8 @@ export const generateEntityColumns = (
const directColumns = directFields.map((fieldName) => { const directColumns = directFields.map((fieldName) => {
const displayName = formatFieldName(fieldName) const displayName = formatFieldName(fieldName)
const fieldDef = entityFields[fieldName] || additionalFieldDefinitions.get(fieldName) const fieldDef =
entityFields[fieldName] || additionalFieldDefinitions.get(fieldName)
const typeInfo = fieldDef const typeInfo = fieldDef
? getTypeInfoFromGraphQLType(fieldDef.type, fieldName) ? getTypeInfoFromGraphQLType(fieldDef.type, fieldName)
: getTypeInfoFromGraphQLType(null, fieldName) : getTypeInfoFromGraphQLType(null, fieldName)
@@ -5,6 +5,7 @@ export const defaultStoreOrderFields = [
"status", "status",
"summary", "summary",
"display_id", "display_id",
"custom_display_id",
"total", "total",
"currency_code", "currency_code",
"metadata", "metadata",
@@ -18,6 +19,7 @@ export const defaultStoreRetrieveOrderFields = [
"summary", "summary",
"currency_code", "currency_code",
"display_id", "display_id",
"custom_display_id",
"region_id", "region_id",
"email", "email",
"total", "total",
@@ -1,15 +1,17 @@
import { Migration } from '@mikro-orm/migrations'; import { Migration } from "@medusajs/framework/mikro-orm/migrations"
export class Migration20251015123842 extends Migration { export class Migration20251015123842 extends Migration {
override async up(): Promise<void> { override async up(): Promise<void> {
this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_api_key_revoked_at" ON "api_key" (revoked_at) WHERE deleted_at IS NULL;`); this.addSql(
this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_api_key_redacted" ON "api_key" (redacted) WHERE deleted_at IS NULL;`); `CREATE INDEX IF NOT EXISTS "IDX_api_key_revoked_at" ON "api_key" (revoked_at) WHERE deleted_at IS NULL;`
)
this.addSql(
`CREATE INDEX IF NOT EXISTS "IDX_api_key_redacted" ON "api_key" (redacted) WHERE deleted_at IS NULL;`
)
} }
override async down(): Promise<void> { override async down(): Promise<void> {
this.addSql(`drop index if exists "IDX_api_key_revoked_at";`); this.addSql(`drop index if exists "IDX_api_key_revoked_at";`)
this.addSql(`drop index if exists "IDX_api_key_redacted";`); this.addSql(`drop index if exists "IDX_api_key_redacted";`)
} }
} }
@@ -1,33 +1,43 @@
import { Migration } from '@mikro-orm/migrations'; import { Migration } from "@medusajs/framework/mikro-orm/migrations"
export class Migration20251017153909 extends Migration { export class Migration20251017153909 extends Migration {
override async up(): Promise<void> { override async up(): Promise<void> {
this.addSql(`drop index if exists "IDX_line_item_cart_id";`); this.addSql(`drop index if exists "IDX_line_item_cart_id";`)
this.addSql(`drop index if exists "IDX_adjustment_item_id";`); this.addSql(`drop index if exists "IDX_adjustment_item_id";`)
this.addSql(`drop index if exists "IDX_tax_line_item_id";`); this.addSql(`drop index if exists "IDX_tax_line_item_id";`)
this.addSql(`drop index if exists "IDX_shipping_method_cart_id";`); this.addSql(`drop index if exists "IDX_shipping_method_cart_id";`)
this.addSql(`drop index if exists "IDX_adjustment_shipping_method_id";`); this.addSql(`drop index if exists "IDX_adjustment_shipping_method_id";`)
this.addSql(`drop index if exists "IDX_tax_line_shipping_method_id";`); this.addSql(`drop index if exists "IDX_tax_line_shipping_method_id";`)
} }
override async down(): Promise<void> { override async down(): Promise<void> {
this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_line_item_cart_id" ON "cart_line_item" (cart_id) WHERE deleted_at IS NULL;`); this.addSql(
`CREATE INDEX IF NOT EXISTS "IDX_line_item_cart_id" ON "cart_line_item" (cart_id) WHERE deleted_at IS NULL;`
)
this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_adjustment_item_id" ON "cart_line_item_adjustment" (item_id) WHERE deleted_at IS NULL;`); this.addSql(
`CREATE INDEX IF NOT EXISTS "IDX_adjustment_item_id" ON "cart_line_item_adjustment" (item_id) WHERE deleted_at IS NULL;`
)
this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_tax_line_item_id" ON "cart_line_item_tax_line" (item_id) WHERE deleted_at IS NULL;`); this.addSql(
`CREATE INDEX IF NOT EXISTS "IDX_tax_line_item_id" ON "cart_line_item_tax_line" (item_id) WHERE deleted_at IS NULL;`
)
this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_shipping_method_cart_id" ON "cart_shipping_method" (cart_id) WHERE deleted_at IS NULL;`); this.addSql(
`CREATE INDEX IF NOT EXISTS "IDX_shipping_method_cart_id" ON "cart_shipping_method" (cart_id) WHERE deleted_at IS NULL;`
)
this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_adjustment_shipping_method_id" ON "cart_shipping_method_adjustment" (shipping_method_id) WHERE deleted_at IS NULL;`); this.addSql(
`CREATE INDEX IF NOT EXISTS "IDX_adjustment_shipping_method_id" ON "cart_shipping_method_adjustment" (shipping_method_id) WHERE deleted_at IS NULL;`
)
this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_tax_line_shipping_method_id" ON "cart_shipping_method_tax_line" (shipping_method_id) WHERE deleted_at IS NULL;`); this.addSql(
`CREATE INDEX IF NOT EXISTS "IDX_tax_line_shipping_method_id" ON "cart_shipping_method_tax_line" (shipping_method_id) WHERE deleted_at IS NULL;`
)
} }
} }
@@ -1,17 +1,13 @@
import { Migration } from '@mikro-orm/migrations'; import { Migration } from "@medusajs/framework/mikro-orm/migrations"
export class Migration20251010130829 extends Migration { export class Migration20251010130829 extends Migration {
override async up(): Promise<void> { override async up(): Promise<void> {
this.addSql( this.addSql('DROP INDEX IF EXISTS "IDX_customer_group_name";')
'DROP INDEX IF EXISTS "IDX_customer_group_name";'
);
} }
override async down(): Promise<void> { override async down(): Promise<void> {
this.addSql( this.addSql(
'CREATE UNIQUE INDEX IF NOT EXISTS "IDX_customer_group_name" ON "customer_group" ("name") WHERE "deleted_at" IS NULL;' 'CREATE UNIQUE INDEX IF NOT EXISTS "IDX_customer_group_name" ON "customer_group" ("name") WHERE "deleted_at" IS NULL;'
); )
} }
} }
@@ -1,17 +1,13 @@
import { Migration } from '@mikro-orm/migrations'; import { Migration } from "@medusajs/framework/mikro-orm/migrations"
export class Migration20251010131115 extends Migration { export class Migration20251010131115 extends Migration {
override async up(): Promise<void> { override async up(): Promise<void> {
this.addSql( this.addSql('DROP INDEX IF EXISTS "IDX_inventory_level_item_location";')
'DROP INDEX IF EXISTS "IDX_inventory_level_item_location";'
);
} }
override async down(): Promise<void> { override async down(): Promise<void> {
this.addSql( this.addSql(
'CREATE UNIQUE INDEX IF NOT EXISTS "IDX_inventory_level_item_location" ON "inventory_level" (inventory_item_id, location_id) WHERE deleted_at IS NULL;' 'CREATE UNIQUE INDEX IF NOT EXISTS "IDX_inventory_level_item_location" ON "inventory_level" (inventory_item_id, location_id) WHERE deleted_at IS NULL;'
); )
} }
} }
@@ -1,15 +1,21 @@
import { Migration } from '@mikro-orm/migrations'; import { Migration } from "@medusajs/framework/mikro-orm/migrations"
export class Migration20251028172715 extends Migration { export class Migration20251028172715 extends Migration {
override async up(): Promise<void> { override async up(): Promise<void> {
this.addSql(`alter table if exists "notification" alter column "template" type text using ("template"::text);`); this.addSql(
this.addSql(`alter table if exists "notification" alter column "template" drop not null;`); `alter table if exists "notification" alter column "template" type text using ("template"::text);`
)
this.addSql(
`alter table if exists "notification" alter column "template" drop not null;`
)
} }
override async down(): Promise<void> { override async down(): Promise<void> {
this.addSql(`alter table if exists "notification" alter column "template" type text using ("template"::text);`); this.addSql(
this.addSql(`alter table if exists "notification" alter column "template" set not null;`); `alter table if exists "notification" alter column "template" type text using ("template"::text);`
)
this.addSql(
`alter table if exists "notification" alter column "template" set not null;`
)
} }
} }
@@ -6,6 +6,11 @@ jest.setTimeout(100000)
moduleIntegrationTestRunner<IOrderModuleService>({ moduleIntegrationTestRunner<IOrderModuleService>({
moduleName: Modules.ORDER, moduleName: Modules.ORDER,
moduleOptions: {
generateCustomDisplayId: async (order: CreateOrderDTO): Promise<string> => {
return order.currency_code + "_1234567890"
},
},
testSuite: ({ service, MikroOrmWrapper }) => { testSuite: ({ service, MikroOrmWrapper }) => {
describe("Order Module Service", () => { describe("Order Module Service", () => {
const input = { const input = {
@@ -124,6 +129,7 @@ moduleIntegrationTestRunner<IOrderModuleService>({
id: expect.stringContaining("order_"), id: expect.stringContaining("order_"),
version: 1, version: 1,
display_id: 1, display_id: 1,
custom_display_id: "usd_1234567890",
summary: expect.objectContaining({ summary: expect.objectContaining({
// TODO: add all summary fields // TODO: add all summary fields
}), }),
@@ -413,6 +419,7 @@ moduleIntegrationTestRunner<IOrderModuleService>({
"id", "id",
"display_id", "display_id",
"version", "version",
"custom_display_id",
"items.id", "items.id",
"summary", "summary",
"items.quantity", "items.quantity",
File diff suppressed because it is too large. Load diff
@@ -1,4 +1,4 @@
import { Migration } from "@mikro-orm/migrations" import { Migration } from "@medusajs/framework/mikro-orm/migrations"
export class Migration20251016182939 extends Migration { export class Migration20251016182939 extends Migration {
override async up(): Promise<void> { override async up(): Promise<void> {
@@ -1,25 +1,31 @@
import { Migration } from '@mikro-orm/migrations'; import { Migration } from "@medusajs/framework/mikro-orm/migrations"
export class Migration20251017155709 extends Migration { export class Migration20251017155709 extends Migration {
override async up(): Promise<void> { override async up(): Promise<void> {
this.addSql(`drop index if exists "IDX_order_item_version";`); this.addSql(`drop index if exists "IDX_order_item_version";`)
this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_order_item_order_id_version" ON "order_item" (order_id, version) WHERE deleted_at IS NULL;`); this.addSql(
`CREATE INDEX IF NOT EXISTS "IDX_order_item_order_id_version" ON "order_item" (order_id, version) WHERE deleted_at IS NULL;`
)
this.addSql(`drop index if exists "IDX_order_shipping_version";`); this.addSql(`drop index if exists "IDX_order_shipping_version";`)
this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_order_shipping_order_id_version" ON "order_shipping" (order_id, version) WHERE deleted_at IS NULL;`); this.addSql(
`CREATE INDEX IF NOT EXISTS "IDX_order_shipping_order_id_version" ON "order_shipping" (order_id, version) WHERE deleted_at IS NULL;`
)
} }
override async down(): Promise<void> { override async down(): Promise<void> {
this.addSql(`drop index if exists "IDX_order_item_order_id_version";`); this.addSql(`drop index if exists "IDX_order_item_order_id_version";`)
this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_order_item_version" ON "order_item" (order_id, version) WHERE deleted_at IS NULL;`); this.addSql(
`CREATE INDEX IF NOT EXISTS "IDX_order_item_version" ON "order_item" (order_id, version) WHERE deleted_at IS NULL;`
)
this.addSql(`drop index if exists "IDX_order_shipping_order_id_version";`); this.addSql(`drop index if exists "IDX_order_shipping_order_id_version";`)
this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_order_shipping_version" ON "order_shipping" (order_id, version) WHERE deleted_at IS NULL;`); this.addSql(
`CREATE INDEX IF NOT EXISTS "IDX_order_shipping_version" ON "order_shipping" (order_id, version) WHERE deleted_at IS NULL;`
)
} }
} }
@@ -0,0 +1,131 @@
import { Migration } from "@medusajs/framework/mikro-orm/migrations"
export class Migration20251114100559 extends Migration {
override async up(): Promise<void> {
this.addSql(
`alter table if exists "order" add column if not exists "custom_display_id" text null;`
)
this.addSql(
`CREATE UNIQUE INDEX IF NOT EXISTS "IDX_order_custom_display_id" ON "order" ("custom_display_id") WHERE deleted_at IS NULL;`
)
this.addSql(
`alter table if exists "order_item" alter column "raw_fulfilled_quantity" type jsonb using ("raw_fulfilled_quantity"::jsonb);`
)
this.addSql(
`alter table if exists "order_item" alter column "raw_fulfilled_quantity" set default '{"value":"0","precision":20}';`
)
this.addSql(
`alter table if exists "order_item" alter column "raw_delivered_quantity" type jsonb using ("raw_delivered_quantity"::jsonb);`
)
this.addSql(
`alter table if exists "order_item" alter column "raw_delivered_quantity" set default '{"value":"0","precision":20}';`
)
this.addSql(
`alter table if exists "order_item" alter column "raw_shipped_quantity" type jsonb using ("raw_shipped_quantity"::jsonb);`
)
this.addSql(
`alter table if exists "order_item" alter column "raw_shipped_quantity" set default '{"value":"0","precision":20}';`
)
this.addSql(
`alter table if exists "order_item" alter column "raw_return_requested_quantity" type jsonb using ("raw_return_requested_quantity"::jsonb);`
)
this.addSql(
`alter table if exists "order_item" alter column "raw_return_requested_quantity" set default '{"value":"0","precision":20}';`
)
this.addSql(
`alter table if exists "order_item" alter column "raw_return_received_quantity" type jsonb using ("raw_return_received_quantity"::jsonb);`
)
this.addSql(
`alter table if exists "order_item" alter column "raw_return_received_quantity" set default '{"value":"0","precision":20}';`
)
this.addSql(
`alter table if exists "order_item" alter column "raw_return_dismissed_quantity" type jsonb using ("raw_return_dismissed_quantity"::jsonb);`
)
this.addSql(
`alter table if exists "order_item" alter column "raw_return_dismissed_quantity" set default '{"value":"0","precision":20}';`
)
this.addSql(
`alter table if exists "order_item" alter column "raw_written_off_quantity" type jsonb using ("raw_written_off_quantity"::jsonb);`
)
this.addSql(
`alter table if exists "order_item" alter column "raw_written_off_quantity" set default '{"value":"0","precision":20}';`
)
this.addSql(
`alter table if exists "return_item" alter column "raw_received_quantity" type jsonb using ("raw_received_quantity"::jsonb);`
)
this.addSql(
`alter table if exists "return_item" alter column "raw_received_quantity" set default '{"value":"0","precision":20}';`
)
this.addSql(
`alter table if exists "return_item" alter column "raw_damaged_quantity" type jsonb using ("raw_damaged_quantity"::jsonb);`
)
this.addSql(
`alter table if exists "return_item" alter column "raw_damaged_quantity" set default '{"value":"0","precision":20}';`
)
}
override async down(): Promise<void> {
this.addSql(`drop index if exists "IDX_order_custom_display_id";`)
this.addSql(
`alter table if exists "order" drop column if exists "custom_display_id";`
)
this.addSql(
`alter table if exists "order_item" alter column "raw_fulfilled_quantity" drop default;`
)
this.addSql(
`alter table if exists "order_item" alter column "raw_fulfilled_quantity" type jsonb using ("raw_fulfilled_quantity"::jsonb);`
)
this.addSql(
`alter table if exists "order_item" alter column "raw_delivered_quantity" drop default;`
)
this.addSql(
`alter table if exists "order_item" alter column "raw_delivered_quantity" type jsonb using ("raw_delivered_quantity"::jsonb);`
)
this.addSql(
`alter table if exists "order_item" alter column "raw_shipped_quantity" drop default;`
)
this.addSql(
`alter table if exists "order_item" alter column "raw_shipped_quantity" type jsonb using ("raw_shipped_quantity"::jsonb);`
)
this.addSql(
`alter table if exists "order_item" alter column "raw_return_requested_quantity" drop default;`
)
this.addSql(
`alter table if exists "order_item" alter column "raw_return_requested_quantity" type jsonb using ("raw_return_requested_quantity"::jsonb);`
)
this.addSql(
`alter table if exists "order_item" alter column "raw_return_received_quantity" drop default;`
)
this.addSql(
`alter table if exists "order_item" alter column "raw_return_received_quantity" type jsonb using ("raw_return_received_quantity"::jsonb);`
)
this.addSql(
`alter table if exists "order_item" alter column "raw_return_dismissed_quantity" drop default;`
)
this.addSql(
`alter table if exists "order_item" alter column "raw_return_dismissed_quantity" type jsonb using ("raw_return_dismissed_quantity"::jsonb);`
)
this.addSql(
`alter table if exists "order_item" alter column "raw_written_off_quantity" drop default;`
)
this.addSql(
`alter table if exists "order_item" alter column "raw_written_off_quantity" type jsonb using ("raw_written_off_quantity"::jsonb);`
)
this.addSql(
`alter table if exists "return_item" alter column "raw_received_quantity" drop default;`
)
this.addSql(
`alter table if exists "return_item" alter column "raw_received_quantity" type jsonb using ("raw_received_quantity"::jsonb);`
)
this.addSql(
`alter table if exists "return_item" alter column "raw_damaged_quantity" drop default;`
)
this.addSql(
`alter table if exists "return_item" alter column "raw_damaged_quantity" type jsonb using ("raw_damaged_quantity"::jsonb);`
)
}
}
@@ -11,6 +11,7 @@ const _Order = model
.define("Order", { .define("Order", {
id: model.id({ prefix: "order" }).primaryKey(), id: model.id({ prefix: "order" }).primaryKey(),
display_id: model.autoincrement().searchable(), display_id: model.autoincrement().searchable(),
custom_display_id: model.text().nullable(),
region_id: model.text().nullable(), region_id: model.text().nullable(),
customer_id: model.text().nullable(), customer_id: model.text().nullable(),
version: model.number().default(1), version: model.number().default(1),
@@ -71,6 +72,12 @@ const _Order = model
unique: false, unique: false,
where: "deleted_at IS NULL", where: "deleted_at IS NULL",
}, },
{
name: "IDX_order_custom_display_id",
on: ["custom_display_id"],
unique: true,
where: "deleted_at IS NULL",
},
{ {
name: "IDX_order_region_id", name: "IDX_order_region_id",
on: ["region_id"], on: ["region_id"],
@@ -249,6 +249,8 @@ type Order {
status: OrderStatus! status: OrderStatus!
region_id: String region_id: String
customer_id: String customer_id: String
display_id: String
custom_display_id: String
sales_channel_id: String sales_channel_id: String
email: String email: String
currency_code: String! currency_code: String!
@@ -7,7 +7,6 @@ import {
FilterableOrderReturnReasonProps, FilterableOrderReturnReasonProps,
FindConfig, FindConfig,
InferEntityType, InferEntityType,
InternalModuleDeclaration,
IOrderModuleService, IOrderModuleService,
ModuleJoinerConfig, ModuleJoinerConfig,
ModulesSdkTypes, ModulesSdkTypes,
@@ -218,6 +217,14 @@ export default class OrderModuleService
}>(generateMethodForModels) }>(generateMethodForModels)
implements IOrderModuleService implements IOrderModuleService
{ {
protected generateCustomDisplayId_: (
this: OrderModuleService,
order: OrderTypes.CreateOrderDTO,
sharedContext: Context
) => Promise<string | undefined> = async () => {
return undefined
}
protected baseRepository_: DAL.RepositoryService protected baseRepository_: DAL.RepositoryService
protected orderService_: OrderService protected orderService_: OrderService
protected orderAddressService_: ModulesSdkTypes.IMedusaInternalService< protected orderAddressService_: ModulesSdkTypes.IMedusaInternalService<
@@ -311,7 +318,12 @@ export default class OrderModuleService
orderExchangeService, orderExchangeService,
orderCreditLineService, orderCreditLineService,
}: InjectedDependencies, }: InjectedDependencies,
protected readonly moduleDeclaration: InternalModuleDeclaration options?: {
generateCustomDisplayId?: (
order: OrderTypes.CreateOrderDTO,
sharedContext: Context
) => Promise<string | undefined>
}
) { ) {
// @ts-ignore // @ts-ignore
super(...arguments) super(...arguments)
@@ -338,6 +350,9 @@ export default class OrderModuleService
this.orderClaimService_ = orderClaimService this.orderClaimService_ = orderClaimService
this.orderExchangeService_ = orderExchangeService this.orderExchangeService_ = orderExchangeService
this.orderCreditLineService_ = orderCreditLineService this.orderCreditLineService_ = orderCreditLineService
this.generateCustomDisplayId_ =
options?.generateCustomDisplayId ?? this.generateCustomDisplayId_
} }
__joinerConfig(): ModuleJoinerConfig { __joinerConfig(): ModuleJoinerConfig {
@@ -740,14 +755,15 @@ export default class OrderModuleService
const creditLinesToCreate: CreateOrderCreditLineDTO[] = [] const creditLinesToCreate: CreateOrderCreditLineDTO[] = []
const createdOrders: InferEntityType<typeof Order>[] = [] const createdOrders: InferEntityType<typeof Order>[] = []
for (const { for (const data_ of data) {
items, const {
shipping_methods, items,
credit_lines, shipping_methods,
shipping_address, credit_lines,
billing_address, shipping_address,
...order billing_address,
} of data) { ...order
} = data_
const ord = order as any const ord = order as any
const shippingMethods = shipping_methods?.map((sm: any) => { const shippingMethods = shipping_methods?.map((sm: any) => {
@@ -777,6 +793,11 @@ export default class OrderModuleService
totals: calculated.summary, totals: calculated.summary,
} }
ord.custom_display_id = await this.generateCustomDisplayId_.bind(this)(
data_,
sharedContext
)
const created = await this.orderService_.create(ord, sharedContext) const created = await this.orderService_.create(ord, sharedContext)
creditLinesToCreate.push( creditLinesToCreate.push(
@@ -1,13 +1,13 @@
import { Migration } from '@mikro-orm/migrations'; import { Migration } from "@medusajs/framework/mikro-orm/migrations"
export class Migration20250911092221 extends Migration { export class Migration20250911092221 extends Migration {
override async up(): Promise<void> { override async up(): Promise<void> {
this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_product_status" ON "product" (status) WHERE deleted_at IS NULL;`); this.addSql(
`CREATE INDEX IF NOT EXISTS "IDX_product_status" ON "product" (status) WHERE deleted_at IS NULL;`
)
} }
override async down(): Promise<void> { override async down(): Promise<void> {
this.addSql(`drop index if exists "IDX_product_status";`); this.addSql(`drop index if exists "IDX_product_status";`)
} }
} }
@@ -1,18 +1,15 @@
import { Migration } from '@mikro-orm/migrations'; import { Migration } from "@medusajs/framework/mikro-orm/migrations"
export class Migration20251011090511 extends Migration { export class Migration20251011090511 extends Migration {
// UP: Fixes the bug by dropping the bad index from product_collection. // UP: Fixes the bug by dropping the bad index from product_collection.
override async up(): Promise<void> { override async up(): Promise<void> {
this.addSql( this.addSql('DROP INDEX IF EXISTS "IDX_product_category_deleted_at";')
'DROP INDEX IF EXISTS "IDX_product_category_deleted_at";'
);
} }
// DOWN: Reverts the fix by re-creating the original bug. // DOWN: Reverts the fix by re-creating the original bug.
override async down(): Promise<void> { override async down(): Promise<void> {
this.addSql( this.addSql(
'CREATE INDEX IF NOT EXISTS "IDX_product_category_deleted_at" ON "product_collection" ("deleted_at");' 'CREATE INDEX IF NOT EXISTS "IDX_product_category_deleted_at" ON "product_collection" ("deleted_at");'
); )
} }
} }
@@ -1,19 +1,25 @@
import { Migration } from '@mikro-orm/migrations'; import { Migration } from "@medusajs/framework/mikro-orm/migrations"
export class Migration20250917143818 extends Migration { export class Migration20250917143818 extends Migration {
override async up(): Promise<void> { override async up(): Promise<void> {
this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_promotion_is_automatic" ON "promotion" (is_automatic) WHERE deleted_at IS NULL;`); this.addSql(
`CREATE INDEX IF NOT EXISTS "IDX_promotion_is_automatic" ON "promotion" (is_automatic) WHERE deleted_at IS NULL;`
)
this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_promotion_rule_value_rule_id_value" ON "promotion_rule_value" (promotion_rule_id, value) WHERE deleted_at IS NULL;`); this.addSql(
this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_promotion_rule_value_value" ON "promotion_rule_value" (value) WHERE deleted_at IS NULL;`); `CREATE INDEX IF NOT EXISTS "IDX_promotion_rule_value_rule_id_value" ON "promotion_rule_value" (promotion_rule_id, value) WHERE deleted_at IS NULL;`
)
this.addSql(
`CREATE INDEX IF NOT EXISTS "IDX_promotion_rule_value_value" ON "promotion_rule_value" (value) WHERE deleted_at IS NULL;`
)
} }
override async down(): Promise<void> { override async down(): Promise<void> {
this.addSql(`drop index if exists "IDX_promotion_is_automatic";`); this.addSql(`drop index if exists "IDX_promotion_is_automatic";`)
this.addSql(`drop index if exists "IDX_promotion_rule_value_rule_id_value";`); this.addSql(
this.addSql(`drop index if exists "IDX_promotion_rule_value_value";`); `drop index if exists "IDX_promotion_rule_value_rule_id_value";`
)
this.addSql(`drop index if exists "IDX_promotion_rule_value_value";`)
} }
} }
@@ -1,13 +1,15 @@
import { Migration } from '@mikro-orm/migrations'; import { Migration } from "@medusajs/framework/mikro-orm/migrations"
export class Migration20250919122137 extends Migration { export class Migration20250919122137 extends Migration {
override async up(): Promise<void> { override async up(): Promise<void> {
this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_promotion_rule_attribute_operator_id" ON "promotion_rule" (operator, attribute, id) WHERE deleted_at IS NULL;`); this.addSql(
`CREATE INDEX IF NOT EXISTS "IDX_promotion_rule_attribute_operator_id" ON "promotion_rule" (operator, attribute, id) WHERE deleted_at IS NULL;`
)
} }
override async down(): Promise<void> { override async down(): Promise<void> {
this.addSql(`drop index if exists "IDX_promotion_rule_attribute_operator_id";`); this.addSql(
`drop index if exists "IDX_promotion_rule_attribute_operator_id";`
)
} }
} }
@@ -1,15 +1,21 @@
import { Migration } from '@mikro-orm/migrations'; import { Migration } from "@medusajs/framework/mikro-orm/migrations"
export class Migration20251006000000 extends Migration { export class Migration20251006000000 extends Migration {
override async up(): Promise<void> { override async up(): Promise<void> {
this.addSql(`ALTER TABLE "promotion_application_method" DROP CONSTRAINT IF EXISTS "promotion_application_method_allocation_check";`); this.addSql(
this.addSql(`ALTER TABLE "promotion_application_method" ADD CONSTRAINT "promotion_application_method_allocation_check" CHECK ("allocation" IN ('each', 'across', 'once'));`); `ALTER TABLE "promotion_application_method" DROP CONSTRAINT IF EXISTS "promotion_application_method_allocation_check";`
)
this.addSql(
`ALTER TABLE "promotion_application_method" ADD CONSTRAINT "promotion_application_method_allocation_check" CHECK ("allocation" IN ('each', 'across', 'once'));`
)
} }
override async down(): Promise<void> { override async down(): Promise<void> {
this.addSql(`ALTER TABLE "promotion_application_method" DROP CONSTRAINT IF EXISTS "promotion_application_method_allocation_check";`); this.addSql(
this.addSql(`ALTER TABLE "promotion_application_method" ADD CONSTRAINT "promotion_application_method_allocation_check" CHECK ("allocation" IN ('each', 'across'));`); `ALTER TABLE "promotion_application_method" DROP CONSTRAINT IF EXISTS "promotion_application_method_allocation_check";`
)
this.addSql(
`ALTER TABLE "promotion_application_method" ADD CONSTRAINT "promotion_application_method_allocation_check" CHECK ("allocation" IN ('each', 'across'));`
)
} }
} }