v2.12.0
medusajs/medusav2.12.0Dec 1, 2025by olivermrbl
AI Summary
This release introduces custom display IDs for orders, advanced promotion limits, and the ability to carry over promotions to exchanges. It also includes a breaking change in the Shipping Option Type relationship.
Key Highlights
- Custom order display ID with configurable generation hook
- Promotion limits at campaign, per-customer, and promotion levels
- Carry over promotions option for exchanges
- Admin user deletion capability
Breaking Changes
- Shipping Option Type relationship changed from one-to-one to many-to-one
New Features
- Custom display ID generation for orders
- Promotion usage limits per customer
- Carry over promotions toggle
- Metadata column on promotions
- Admin user deletion
Full Release Notes
<!--

# v2.12.0: New Promotion limit, custom display ID on orders, improved event management
This release introduces a new limit config on Promotions, the ability to customize display ID on Orders and more.
CMS_BREAK -->
## Highlights
This release introduces migrations, so remember to run migrations after installing the version:
```
npx medusa db:migrate
```
In addition to migrations with schema changes, this release also runs a data migration script added in [this PR](https://github.com/medusajs/medusa/pull/13306). The script populates a new `version` column on order line item adjustments, setting it to the latest version of the associated order.
### Custom order display ID
This release introduces a `custom_display_id` field on orders, along with a hook for automatically generating the value at order creation.
The key changes are:
- New `custom_display_id` column on orders
- Order Module now accepts a `generateCustomDisplayId` function in its module options
The generation can be used like so:
```ts
// medusa-config.ts
defineConfig({
// ...
modules: [{
resolve: "@medusajs/medusa/order",
options: {
generateCustomDisplayId: async function (order: OrderTypes.CreateOrderDTO, sharedContext: Context) {
// Return your custom display id
}
}
}]
})
```
We intentionally kept the existing display_id column unchanged. Migrating it from an auto-incrementing integer to text would be a significant breaking change.
To show the new `custom_display_id` in the Admin dashboard, you can use the View Configurations feature to customize columns on the order table:
```ts
// medusa-config.ts
defineConfig({
// ...
featureFlags: {
view_configurations: true
}
})
```
### Promotion limit
This release expands promotion configuration capabilities by introducing a limit enforced on promotions. Previously, limits could only be enforced at the campaign level. You can now configure limits at three levels:
- Campaign-level: limit the number of times a certain promotion in a campaign can be used
- Campaign-level per customer/email: limit the number of times a certain promotion in a campaign can be used by a specific customer or email
- Promotion-level: limit the number of times a certain promotion can be used
### Promotions on exchanges
This release adds the option to carry over promotions to exchanges on orders. When creating an exchange, you often want the original promotions applied to the outbound items to avoid recharging the customer. You can now opt into this by enabling "Carry over promotions" during the exchange flow.
### Admin user deletion
This release adds the ability for admin users to delete other users. This is a temporary solution ahead of a proper permissions system, which we plan to work on in the near future.
### Limiting event emission
This release improves event management, reducing unnecessary memory and processing overhead by only emitting events and adding to event queues whenever there are subscribers to the events.
### Shipping Option Type relation
> Breaking change
The relationship between Shipping Options and Shipping Option Types has changed from one-to-one to many-to-one. This change should be deemed more a fix, than an actual change of the feature, as this was always the intention. However, it is a breaking change, since the property name has changed.
### Features
* feat(dashboard): Improve error messages during file upload by @juanzgc in https://github.com/medusajs/medusa/pull/13991
* feat(medusa): allow users deletion by @NicolasGorga in https://github.com/medusajs/medusa/pull/13960
* feat(dashboard): include product material in product general section by @NicolasGorga in https://github.com/medusajs/medusa/pull/14021
* feat(promotion): Add metadata column to promotion by @juanzgc in https://github.com/medusajs/medusa/pull/13999
* feat(dashboard): show promo tooltip on the edit flows by @fPolic in https://github.com/medusajs/medusa/pull/14121
* feat: carry over promotions toggle on exchanges by @fPolic in https://github.com/medusajs/medusa/pull/14128
* feat: promotion usage limit by @fPolic in https://github.com/medusajs/medusa/pull/13760
### Bugs
* fix(dashboard): fix import for ptPT locale by @willbouch in https://github.com/medusajs/medusa/pull/13986
* fix(dashboard): Limit file uploads to 1MB by @juanzgc in https://github.com/medusajs/medusa/pull/13981
* fix(core-flows,types): change doc for upload file functions by @willbouch in https://github.com/medusajs/medusa/pull/13809
* fix(): Lock process payment to prevent ingesting payment processing t… by @adrien2p in https://github.com/medusajs/medusa/pull/13977
* fix(dashboard): update orders page filters to match interface expected by old DataTable component by @NicolasGorga in https://github.com/medusajs/medusa/pull/13994
* fix(product, types): add missing types for variant images and thumbnails by @shahednasser in https://github.com/medusajs/medusa/pull/14026
* fix(dashboard): use order version 1 for the initial node of activity timeline by @NicolasGorga in https://github.com/medusajs/medusa/pull/13997
* fix(medusa): preprocess `version` as number in AdminGetOrdersOrderParams validator by @NicolasGorga in https://github.com/medusajs/medusa/pull/13996
* fix(): Proper schema usage when running migrations by @adrien2p in https://github.com/medusajs/medusa/pull/14036
* fix(draft-order): Update copy phone number by @juanzgc in https://github.com/medusajs/medusa/pull/14044
* fix(): Identify step that should require a save on checkpoint by @adrien2p in https://github.com/medusajs/medusa/pull/14037
* fix(dashboard): reference global vite bin from scripts by @fPolic in https://github.com/medusajs/medusa/pull/14049
* fix(core-flows): avoid overriding customer and region from setPricingContext hook result by @NicolasGorga in https://github.com/medusajs/medusa/pull/14022
* fix(payment): Double idempotent capture called with auto capture beha… by @adrien2p in https://github.com/medusajs/medusa/pull/14073
* chore(): Update glob package by @adrien2p in https://github.com/medusajs/medusa/pull/14083
* fix(medusa): avoid throwing on error on set step failure endpoint by @NicolasGorga in https://github.com/medusajs/medusa/pull/14066
* fix(core-flows): prevent completing cart from webhook when order already exists by @NicolasGorga in https://github.com/medusajs/medusa/pull/14108
* fix(core-flows): Add discountable properties in queried fields to avoid overriding discountable properties when set by @NicolasGorga in https://github.com/medusajs/medusa/pull/14105
* fix(): Workflow engine redis worker instance in worker mode by @adrien2p in https://github.com/medusajs/medusa/pull/14099
* fix(product): add missing decorators to updateProductOptionValues method by @shahednasser in https://github.com/medusajs/medusa/pull/14060
* fix: Compute "virtual" adjustments for order previews by @olivermrbl in https://github.com/medusajs/medusa/pull/13306
* fix(core-flows): lock mark as delivered fulfillment/order flows by @NicolasGorga in https://github.com/medusajs/medusa/pull/14111
* fix(orchestration): fetch fields from link entities by @carlos-r-l-rodrigues in https://github.com/medusajs/medusa/pull/14097
* fix(js-sdk,types,medusa): add HTTP types for update order change API route by @shahednasser in https://github.com/medusajs/medusa/pull/14169
* fix(core-flows): create reservations on draft order conversion to regular order by @NicolasGorga in https://github.com/medusajs/medusa/pull/14010
* fix(fulfillment): make relationship between SO and SO type M:1 by @fPolic in https://github.com/medusajs/medusa/pull/14061
* fix(product): Update performance issue by @adrien2p in https://github.com/medusajs/medusa/pull/14150
### Documentation
* chore(docs): Updated UI Reference (automated) by @github-actions[bot] in https://github.com/medusajs/medusa/pull/13968
* docs: fix command bar position outside modal in category images guide by @shahednasser in https://github.com/medusajs/medusa/pull/13987
* docs: fix broken links in OAS by @shahednasser in https://github.com/medusajs/medusa/pull/14000
* docs-utils: fix type error in react-docs-generator by @shahednasser in https://github.com/medusajs/medusa/pull/14002
* docs: add missing middlewares in category images tutorial by @shahednasser in https://github.com/medusajs/medusa/pull/14001
* docs: added kapa logo + link to mcp server by @shahednasser in https://github.com/medusajs/medusa/pull/14005
* docs: add JSON-LD schemas to docs by @shahednasser in https://github.com/medusajs/medusa/pull/14007
* docs: generate OAS for 2.11.3 by @shahednasser in https://github.com/medusajs/medusa/pull/13973
* docs: mobile app guide with react native and expo by @shahednasser in https://github.com/medusajs/medusa/pull/13982
* fix some typos by @dhanushreddy291 in https://github.com/medusajs/medusa/pull/14017
* docs: add a copy button to AI assistant answers by @shahednasser in https://github.com/medusajs/medusa/pull/14052
* docs: fix required properties marked as optional in OAS with allOf schemas by @shahednasser in https://github.com/medusajs/medusa/pull/14062
* docs: add redis prerequisite for Caching Module by @shahednasser in https://github.com/medusajs/medusa/pull/14051
* docs: emails in cloud by @shahednasser in https://github.com/medusajs/medusa/pull/14040
* docs: fix filters in meilisearch and algolia guides by @shahednasser in https://github.com/medusajs/medusa/pull/14098
* docs: updates to billing details by @shahednasser in https://github.com/medusajs/medusa/pull/14096
* docs: fix callback validation for third-party authentication by @shahednasser in https://github.com/medusajs/medusa/pull/14109
* docs: customer tiers tutorial by @shahednasser in https://github.com/medusajs/medusa/pull/14122
* docs: add keywords to cloud, fixes to installation and Index Module docs by @shahednasser in https://github.com/medusajs/medusa/pull/14129
* docs: document locks for nested workflows by @shahednasser in https://github.com/medusajs/medusa/pull/14130
* docs: fix events payloads by @shahednasser in https://github.com/medusajs/medusa/pull/14131
* docs: add guide on clearing cache by @shahednasser in https://github.com/medusajs/medusa/pull/14133
* docs: handle product status change in MeiliSearch and Algolia guides by @shahednasser in https://github.com/medusajs/medusa/pull/14141
* docs: fixed keywords usage in some pages by @shahednasser in https://github.com/medusajs/medusa/pull/14140
* docs: mention managed inventory toggle in multi-part product user guide by @shahednasser in https://github.com/medusajs/medusa/pull/14142
* chore(): Update posthog by @adrien2p in https://github.com/medusajs/medusa/pull/14144
* docs: update recipes and tutorials to support locks and idempotency by @shahednasser in https://github.com/medusajs/medusa/pull/14151
* docs: clarify how links with cascade deletion are deleted by @shahednasser in https://github.com/medusajs/medusa/pull/14155
* Only two options to interact with Medusa application by @2azo in https://github.com/medusajs/medusa/pull/14162
* docs: fix highlights in digital products recipe by @shahednasser in https://github.com/medusajs/medusa/pull/14171
### Chores
* chore(docs): Update version in documentation (automated) by @github-actions[bot] in https://github.com/medusajs/medusa/pull/13966
* chore(docs): Generated DML JSON files (automated) by @github-actions[bot] in https://github.com/medusajs/medusa/pull/13967
* chore(docs): Generated References (automated) by @github-actions[bot] in https://github.com/medusajs/medusa/pull/13969
* chore(medusa): fix query http type parameter for get claim route by @shahednasser in https://github.com/medusajs/medusa/pull/13974
* chore: cleanup/improve bootstrap by @adrien2p in https://github.com/medusajs/medusa/pull/14023
* chore: Configure auth on JS-SDK in dashboard by @olivermrbl in https://github.com/medusajs/medusa/pull/14013
* chore(): Remove lodash.set entirely by @adrien2p in https://github.com/medusajs/medusa/pull/14041
* chore(): Upgrade vit to non vulnerable one by @adrien2p in https://github.com/medusajs/medusa/pull/14042
* chore(order): custom display id by @adrien2p in https://github.com/medusajs/medusa/pull/14024
* chore(event-bus-*): Do not emit if no subscribers: by @adrien2p in https://github.com/medusajs/medusa/pull/14084
* chore(): Improve product list when there is a single sales channel by @adrien2p in https://github.com/medusajs/medusa/pull/14082
* chore: fix payloads of events in TSDocs + description of emitEventStep by @shahednasser in https://github.com/medusajs/medusa/pull/14132
* chore(): Promotion auto managed joiner config by @adrien2p in https://github.com/medusajs/medusa/pull/14115
* chore: Update medusa exec worker mode by @adrien2p in https://github.com/medusajs/medusa/pull/14145
* chore: improve and add TSDocs for next release by @shahednasser in https://github.com/medusajs/medusa/pull/14170
* chore: improve completeCartWorkflow TSDocs by @shahednasser in https://github.com/medusajs/medusa/pull/14153
* chore: change 2.11.4 to 2.12.0 in TSDocs by @shahednasser in https://github.com/medusajs/medusa/pull/14174
### Other Changes
* feat(admin-vite-plugin,dashboard): support for react-router's splat and optional segments by @leobenzol in https://github.com/medusajs/medusa/pull/13547
* feat(dashboard): add pt-PT translation and register locale by @ZeB4la in https://github.com/medusajs/medusa/pull/13935
* feat(admin-*,dashboard): i18n labels for menu item extensions by @leobenzol in https://github.com/medusajs/medusa/pull/13843
* fix(core-flows): update SendNotificationsStepInput by @leobenzol in https://github.com/medusajs/medusa/pull/13979
* fix(core-flows): payment error handling by @SGFGOV in https://github.com/medusajs/medusa/pull/13876
* feat(admin): add custom admin route ranking feature by @bqst in https://github.com/medusajs/medusa/pull/13946
* Fix Node.js version text in installation page by @khai-pi in https://github.com/medusajs/medusa/pull/14015
* feat(payment-stripe): OXXO payment provider support with configurable expiration by @angelbanderasudg in https://github.com/medusajs/medusa/pull/13805
* fix(fulfillment) Variants changed from managed inventory to unmanaged are now fulfillable by @vethan in https://github.com/medusajs/medusa/pull/14056
* add from to notification model by @peterlgh7 in https://github.com/medusajs/medusa/pull/14102
* Add provider data to notifications by @peterlgh7 in https://github.com/medusajs/medusa/pull/14104
* chore(): Add new regression tests to the remote joiner by @adrien2p in https://github.com/medusajs/medusa/pull/14119
* Fix not in promotion rule empty value validation by @pepijn-vanvlaanderen in https://github.com/medusajs/medusa/pull/14172
* fix(dashboard): enable sorting by default based on apiColumn state - FIXES 14166 by @adevinwild in https://github.com/medusajs/medusa/pull/14167
* Add missing order metadata for create fulfillment by @pepijn-vanvlaanderen in https://github.com/medusajs/medusa/pull/14028
## New Contributors
* @ZeB4la made their first contribution in https://github.com/medusajs/medusa/pull/13935
* @khai-pi made their first contribution in https://github.com/medusajs/medusa/pull/14015
* @dhanushreddy291 made their first contribution in https://github.com/medusajs/medusa/pull/14017
* @angelbanderasudg made their first contribution in https://github.com/medusajs/medusa/pull/13805
* @2azo made their first contribution in https://github.com/medusajs/medusa/pull/14162
**Full Changelog**: https://github.com/medusajs/medusa/compare/v2.11.3...v2.12.0