Highlights
Calculated shipping option price
This release introduces dynamically calculated shipping option prices, which comprise three key changes:
- Admin support for creating dynamically priced options
When creating a shipping option, choose the "calculated" price type. Upon sending the request to create the option, our fulfillment module verifies if the provider and method support calculated prices.
- New storefront endpoint to calculate shipping option prices
To display calculated prices on the storefront, use the endpoint below. Calculated shipping options do not include a price in the regular request to retrieve options for a cart. These are calculated separately–one request for each option.
POST /store/shipping-options/:id/calculate
{ cart_id: "cart_1234", data: { ... } }
Pass custom data in the data
property of the payload. The data
is passed down to the provider and can be used for the calculation, e.g. distance to destination.
Our Next.js starter has been updated to include this feature. Check it out here.
- Changes to the addShippingMethodToCartWorkflow
When adding a calculated shipping option to a cart, the price is computed dynamically similarly to the calculation endpoint.
Module DML migrations
More core modules have been migrated from MikroORM to DML. These migrations come with non-breaking schema changes, primarily around index renaming and adding default timestamp columns.
Removed orphan deletion
Additionally, we've removed the default orphanRemoval: true
configuration from one-to-one relationships. This is a less aggressive approach to cascade removal, meaning that disconnecting entities in such a relation will not delete the "child" of the association.
Required action
Run migrations to ensure your server functions as expected after upgrading:
npx medusa db:migrate
As part of migrating modules to use DML, we've uncovered a range of minor bugs (not affecting end-users) and improvements. You can read more about those in this PR.
Line items with custom prices
This release allows for custom prices on line items by decoupling variants and line items in the cart and order workflows.
Our core API doesn't support custom prices out of the box, however the underlying addToCartWorkflow
does.
Here's an example of how to use it in a custom API Route:
// POST /store/carts/:id/custom-line-items
import { addToCartWorkflow } from "@medusajs/medusa/core-flows"
async function thirdPartyCallToComputePrice(item: any) {
return {
...item,
unit_price: Math.floor(Math.random() * 900) + 100,
}
}
export const POST = async (req, res) => {
const { id } = req.params
const { items } = req.body
const query = req.scope.resolve("query")
const itemsWithDynamicPrice = await Promise.all(
items.map((item) => {
return thirdPartyCallToComputePrice(item)
})
)
const workflowInput = {
items: itemsWithDynamicPrice,
cart_id: id,
}
await addToCartWorkflow(req.scope).run({
input: workflowInput,
})
const updatedCart = await query.graph({
entity: "cart",
filters: { id },
fields: ["id", "items.*"],
})
res.status(200).json({ cart: updatedCart })
}
Nesting Admin UI Routes under existing domains
This release introduces support for nesting a UI Route under an existing domain in the sidebar instead of in the extensions section.
For example, you can locate Brands under Products:
import { defineRouteConfig } from "@medusajs/admin-sdk"
import { Container, Heading } from "@medusajs/ui"
const NestedProductsPage = () => {
return (
<Container className="divide-y p-0">
<div className="flex items-center justify-between px-6 py-4">
<Heading level="h1">Nested Products Page</Heading>
</div>
</Container>
)
}
export const config = defineRouteConfig({
label: "Nested Products",
nested: "/products",
})
export default NestedProductsPage
This improvement to our existing UI Routes tooling was a community contribution from @eugenepro2.
Features
- feat(core-flows,dashboard,js-sdk,medusa,types): support Fulfillment Options by @fPolic in #10622
- feat: Custom line items by @olivermrbl in #10408
- feat(order, types): Add Credit Line to order module by @riqwan in #10636
- feat(core-flows): pass fields variant details when creating fulfillment by @fPolic in #10665
Bugs
- fix(core-flows): export getItemTaxLinesStep by @shahednasser in #10640
- fix(medusa): Missing metadata field on order by @olivermrbl in #10651
- fix(dashboard): order details status by @fPolic in #10650
- fix(notification): Only use enabled providers for notis by @olivermrbl in #10659
- fix(core-flows): use useQueryGraphStep instead of useQueryStep by @shahednasser in #10643
- fix(core-flows): data passed to to fulfillment provider context by @fPolic in #10660
- fix(core-flows): refresh payment collections upon shipping changes by @riqwan in #10673
- fix(product): updating collections with products fix by @riqwan in #10668
- fix(core-flows): select stock locations for reservation from correct SC by @fPolic in #10661
Documentation
- docs: document float property (for v2.1.2) by @shahednasser in #10575
- docs-util: infer resolved resources in workflow + steps by @shahednasser in #10637
- docs: generate references manually for v2.1.2 by @shahednasser in #10639
- chore: fix redocly circular dependencies by @shahednasser in #10642
- docs: add tags package to generate tags by @shahednasser in #10666
- docs: support generating sidebar items with tags by @shahednasser in #10672
- docs: add tags manually to doc pages by @shahednasser in #10675
- docs: remove duplicate parsed tag items by @shahednasser in #10676
Chores
- chore(types): Keep intelisense while being more loosen by @adrien2p in #10657
- chore: improve tsdocs of fulfillment provider by @shahednasser in #10649
- chore(fulfillment, utils): Migrate module to DML by @adrien2p in #10617
Other Changes
- Add FilterableRefundReason filter by description and label by @vethan in #10606
- feat(dashboard): ability to locate new admin route under existing route by @eugenepro2 in #10587
New Contributors
- @vethan made their first contribution in #10606
- @eugenepro2 made their first contribution in #10587
Full Changelog: v2.1.2...v2.1.3