feat(medusa): Remove reservations for all line items when an order edit is accepted (#3544)
**What** - Remove all allocations to line items once an order edit is confirmed **Why** - Since all line items of an order are discarded once an order edit is confirmed it will orphan the reservations causing inconsistencies with the stock
This commit is contained in:
@@ -960,5 +960,107 @@ describe("/store/carts", () => {
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("POST /admin/order-edits", () => {
|
||||
let order
|
||||
|
||||
beforeEach(async () => {
|
||||
const api = useApi()
|
||||
|
||||
const cart = await simpleCartFactory(dbConnection, {
|
||||
id: "test-cart",
|
||||
sales_channel_id: "test-channel",
|
||||
})
|
||||
|
||||
const cartId = cart.id
|
||||
|
||||
await api.post(
|
||||
`/store/carts/${cartId}/line-items`,
|
||||
{
|
||||
variant_id: variantId,
|
||||
quantity: 3,
|
||||
},
|
||||
{ withCredentials: true }
|
||||
)
|
||||
|
||||
await api.post(
|
||||
`/store/carts/${cartId}`,
|
||||
{
|
||||
email: "test@test.com",
|
||||
},
|
||||
{ withCredentials: true }
|
||||
)
|
||||
|
||||
await api.post(`/store/carts/${cartId}/payment-sessions`)
|
||||
await api.post(`/store/carts/${cartId}/payment-session`, {
|
||||
provider_id: "test-pay",
|
||||
})
|
||||
const completeRes = await api.post(`/store/carts/${cartId}/complete`)
|
||||
|
||||
expect(completeRes.status).toEqual(200)
|
||||
expect(completeRes.data.type).toEqual("order")
|
||||
|
||||
order = completeRes.data.data
|
||||
})
|
||||
|
||||
it("deletes reservations when an order edit is confirmed", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const lineItemIds = order.items.map((item) => item.id)
|
||||
|
||||
const inventoryService = appContainer.resolve("inventoryService")
|
||||
|
||||
const [, count] = await inventoryService.listReservationItems({
|
||||
line_item_id: lineItemIds,
|
||||
})
|
||||
|
||||
expect(count).toEqual(1)
|
||||
|
||||
let response = await api.post(
|
||||
`/admin/order-edits/`,
|
||||
{
|
||||
order_id: order.id,
|
||||
internal_note: "This is an internal note",
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
const orderEditId = response.data.order_edit.id
|
||||
|
||||
const itemToUpdate = response.data.order_edit.items.find(
|
||||
(item) => item.original_item_id === order.items[0].id
|
||||
)
|
||||
|
||||
response = await api.post(
|
||||
`/admin/order-edits/${orderEditId}/items/${itemToUpdate.id}`,
|
||||
{ quantity: 2 },
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
response = await api.post(
|
||||
`/admin/order-edits/${orderEditId}/confirm`,
|
||||
{},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.order_edit).toEqual(
|
||||
expect.objectContaining({
|
||||
id: orderEditId,
|
||||
created_by: "admin_user",
|
||||
confirmed_by: "admin_user",
|
||||
confirmed_at: expect.any(String),
|
||||
status: "confirmed",
|
||||
})
|
||||
)
|
||||
|
||||
const [, countAfterConfirm] =
|
||||
await inventoryService.listReservationItems({
|
||||
line_item_id: lineItemIds,
|
||||
})
|
||||
|
||||
expect(countAfterConfirm).toEqual(0)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
import { Connection } from "typeorm"
|
||||
import faker from "faker"
|
||||
import { Cart } from "@medusajs/medusa"
|
||||
|
||||
import { RegionFactoryData, simpleRegionFactory } from "./simple-region-factory"
|
||||
import {
|
||||
LineItemFactoryData,
|
||||
simpleLineItemFactory,
|
||||
} from "./simple-line-item-factory"
|
||||
import {
|
||||
AddressFactoryData,
|
||||
simpleAddressFactory,
|
||||
} from "./simple-address-factory"
|
||||
import { Connection, DataSource } from "typeorm"
|
||||
import {
|
||||
LineItemFactoryData,
|
||||
simpleLineItemFactory,
|
||||
} from "./simple-line-item-factory"
|
||||
import { RegionFactoryData, simpleRegionFactory } from "./simple-region-factory"
|
||||
import {
|
||||
ShippingMethodFactoryData,
|
||||
simpleShippingMethodFactory,
|
||||
} from "./simple-shipping-method-factory"
|
||||
|
||||
import { Cart } from "@medusajs/medusa"
|
||||
import faker from "faker"
|
||||
|
||||
export type CartFactoryData = {
|
||||
id?: string
|
||||
region?: RegionFactoryData | string
|
||||
@@ -27,7 +27,7 @@ export type CartFactoryData = {
|
||||
}
|
||||
|
||||
export const simpleCartFactory = async (
|
||||
connection: Connection,
|
||||
dataSource: DataSource,
|
||||
data: CartFactoryData = {},
|
||||
seed: number
|
||||
): Promise<Cart> => {
|
||||
@@ -35,16 +35,16 @@ export const simpleCartFactory = async (
|
||||
faker.seed(seed)
|
||||
}
|
||||
|
||||
const manager = connection.manager
|
||||
const manager = dataSource.manager
|
||||
|
||||
let regionId: string
|
||||
if (typeof data.region === "string") {
|
||||
regionId = data.region
|
||||
} else {
|
||||
const region = await simpleRegionFactory(connection, data.region)
|
||||
const region = await simpleRegionFactory(dataSource, data.region)
|
||||
regionId = region.id
|
||||
}
|
||||
const address = await simpleAddressFactory(connection, data.shipping_address)
|
||||
const address = await simpleAddressFactory(dataSource, data.shipping_address)
|
||||
|
||||
const id = data.id || `simple-cart-${Math.random() * 1000}`
|
||||
const toSave = manager.create(Cart, {
|
||||
@@ -60,12 +60,12 @@ export const simpleCartFactory = async (
|
||||
|
||||
const shippingMethods = data.shipping_methods || []
|
||||
for (const sm of shippingMethods) {
|
||||
await simpleShippingMethodFactory(connection, { ...sm, cart_id: id })
|
||||
await simpleShippingMethodFactory(dataSource, { ...sm, cart_id: id })
|
||||
}
|
||||
|
||||
const items = data.line_items
|
||||
for (const item of items) {
|
||||
await simpleLineItemFactory(connection, { ...item, cart_id: id })
|
||||
for (const item of items || []) {
|
||||
await simpleLineItemFactory(dataSource, { ...item, cart_id: id })
|
||||
}
|
||||
|
||||
return cart
|
||||
|
||||
Reference in New Issue
Block a user