Skip to content

Commit 6b04fbc

Browse files
authored
fix(core-flows): pass backorder flag when recreating reservations after fulfilment cancelation (medusajs#13076)
1 parent 059bfc1 commit 6b04fbc

File tree

3 files changed

+214
-0
lines changed

3 files changed

+214
-0
lines changed

.changeset/silver-spoons-switch.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@medusajs/core-flows": patch
3+
---
4+
5+
fix(core-flows): pass backorder flag when recreating reservations after fulfilment cancelation

integration-tests/http/__tests__/order/admin/order.spec.ts

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1691,6 +1691,212 @@ medusaIntegrationTestRunner({
16911691
)
16921692
})
16931693

1694+
it("should manage reservations when canceling a fulfillment (with allow_backorder item)", async () => {
1695+
const inventoryItemTablet = (
1696+
await api.post(
1697+
`/admin/inventory-items`,
1698+
{ sku: "tablet" },
1699+
adminHeaders
1700+
)
1701+
).data.inventory_item
1702+
1703+
await api.post(
1704+
`/admin/inventory-items/${inventoryItemTablet.id}/location-levels`,
1705+
{
1706+
location_id: stockLocation.id,
1707+
stocked_quantity: 1,
1708+
},
1709+
adminHeaders
1710+
)
1711+
1712+
const productTablet = (
1713+
await api.post(
1714+
"/admin/products",
1715+
{
1716+
title: `Tablet`,
1717+
shipping_profile_id: shippingProfile.id,
1718+
options: [{ title: "color", values: ["green"] }],
1719+
variants: [
1720+
{
1721+
title: "Green tablet",
1722+
sku: "green-tablet",
1723+
allow_backorder: true,
1724+
manage_inventory: true,
1725+
inventory_items: [
1726+
{
1727+
inventory_item_id: inventoryItemTablet.id,
1728+
required_quantity: 1,
1729+
},
1730+
],
1731+
prices: [
1732+
{
1733+
currency_code: "usd",
1734+
amount: 1000,
1735+
},
1736+
],
1737+
options: {
1738+
color: "green",
1739+
},
1740+
},
1741+
],
1742+
},
1743+
adminHeaders
1744+
)
1745+
).data.product
1746+
1747+
const cartTablet = (
1748+
await api.post(
1749+
`/store/carts`,
1750+
{
1751+
currency_code: "usd",
1752+
1753+
region_id: region.id,
1754+
shipping_address: {
1755+
address_1: "test address 1",
1756+
address_2: "test address 2",
1757+
city: "ny",
1758+
country_code: "us",
1759+
province: "ny",
1760+
postal_code: "94016",
1761+
},
1762+
billing_address: {
1763+
address_1: "test billing address 1",
1764+
address_2: "test billing address 2",
1765+
city: "ny",
1766+
country_code: "us",
1767+
province: "ny",
1768+
postal_code: "94016",
1769+
},
1770+
sales_channel_id: salesChannel.id,
1771+
items: [
1772+
{ quantity: 2, variant_id: productTablet.variants[0].id },
1773+
],
1774+
},
1775+
storeHeaders
1776+
)
1777+
).data.cart
1778+
1779+
await api.post(
1780+
`/store/carts/${cartTablet.id}/shipping-methods`,
1781+
{ option_id: shippingOption.id },
1782+
storeHeaders
1783+
)
1784+
1785+
const paymentCollectionTablet = (
1786+
await api.post(
1787+
`/store/payment-collections`,
1788+
{
1789+
cart_id: cartTablet.id,
1790+
},
1791+
storeHeaders
1792+
)
1793+
).data.payment_collection
1794+
1795+
await api.post(
1796+
`/store/payment-collections/${paymentCollectionTablet.id}/payment-sessions`,
1797+
{ provider_id: "pp_system_default" },
1798+
storeHeaders
1799+
)
1800+
1801+
const tabletOrder = (
1802+
await api.post(
1803+
`/store/carts/${cartTablet.id}/complete`,
1804+
{},
1805+
storeHeaders
1806+
)
1807+
).data.order
1808+
1809+
const lineItemId = tabletOrder.items[0].id
1810+
1811+
let reservations = (
1812+
await api.get(
1813+
`/admin/reservations?line_item_id[]=${lineItemId}`,
1814+
adminHeaders
1815+
)
1816+
).data.reservations
1817+
1818+
expect(reservations).toEqual(
1819+
expect.arrayContaining([
1820+
expect.objectContaining({
1821+
line_item_id: lineItemId,
1822+
inventory_item_id: inventoryItemTablet.id,
1823+
quantity: 2,
1824+
inventory_item: expect.objectContaining({
1825+
reserved_quantity: 2,
1826+
stocked_quantity: 1,
1827+
}),
1828+
}),
1829+
])
1830+
)
1831+
1832+
const fulOrder = (
1833+
await api.post(
1834+
`/admin/orders/${tabletOrder.id}/fulfillments?fields=*fulfillments,*fulfillments.items`,
1835+
{
1836+
items: [{ id: tabletOrder.items[0].id, quantity: 2 }],
1837+
},
1838+
adminHeaders
1839+
)
1840+
).data.order
1841+
1842+
reservations = (
1843+
await api.get(
1844+
`/admin/reservations?line_item_id[]=${lineItemId}`,
1845+
adminHeaders
1846+
)
1847+
).data.reservations
1848+
1849+
expect(reservations.length).toEqual(0)
1850+
1851+
const inventoryItem = (
1852+
await api.get(
1853+
`/admin/inventory-items/${inventoryItemTablet.id}`,
1854+
adminHeaders
1855+
)
1856+
).data.inventory_item
1857+
1858+
expect(inventoryItem).toEqual(
1859+
expect.objectContaining({
1860+
reserved_quantity: 0,
1861+
stocked_quantity: -1,
1862+
location_levels: [
1863+
expect.objectContaining({
1864+
available_quantity: -1,
1865+
reserved_quantity: 0,
1866+
stocked_quantity: -1,
1867+
}),
1868+
],
1869+
})
1870+
)
1871+
1872+
await api.post(
1873+
`/admin/orders/${tabletOrder.id}/fulfillments/${fulOrder.fulfillments[0].id}/cancel`,
1874+
{},
1875+
adminHeaders
1876+
)
1877+
1878+
reservations = (
1879+
await api.get(
1880+
`/admin/reservations?line_item_id[]=${lineItemId}`,
1881+
adminHeaders
1882+
)
1883+
).data.reservations
1884+
1885+
expect(reservations).toEqual(
1886+
expect.arrayContaining([
1887+
expect.objectContaining({
1888+
line_item_id: lineItemId,
1889+
inventory_item_id: inventoryItemTablet.id,
1890+
quantity: 2,
1891+
inventory_item: expect.objectContaining({
1892+
reserved_quantity: 2,
1893+
stocked_quantity: 1,
1894+
}),
1895+
}),
1896+
])
1897+
)
1898+
})
1899+
16941900
it("should correctly manage reservations when canceling a fulfillment (with inventory kit)", async () => {
16951901
let reservations = (await api.get(`/admin/reservations`, adminHeaders))
16961902
.data.reservations

packages/core/core-flows/src/order/workflows/cancel-order-fulfillment.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ function prepareInventoryUpdate({
205205
location_id: string
206206
quantity: BigNumberInput
207207
line_item_id: string
208+
allow_backorder: boolean
208209
}[] = []
209210
const toUpdate: {
210211
id: string
@@ -244,6 +245,7 @@ function prepareInventoryUpdate({
244245
location_id: fulfillment.location_id,
245246
quantity: fulfillmentItem.quantity, // <- this is the inventory quantity that is being fulfilled so it means it does include the required quantity
246247
line_item_id: fulfillmentItem.line_item_id as string,
248+
allow_backorder: !!orderItem?.variant?.allow_backorder,
247249
})
248250
} else {
249251
toUpdate.push({
@@ -313,6 +315,7 @@ export const cancelOrderFulfillmentWorkflow = createWorkflow(
313315
"status",
314316
"items.id",
315317
"items.quantity",
318+
"items.variant.allow_backorder",
316319
"items.variant.manage_inventory",
317320
"items.variant.inventory_items.inventory.id",
318321
"items.variant.inventory_items.required_quantity",

0 commit comments

Comments
 (0)