Fix(medusa): Missing location id on fulfillments (#3462)

**What**
- include location id when creating a fulfillment
- Allow location updates to reservations without passing along quantity

**Why**
- location_id on fulfillment was null after creation

Fixes CORE-1242, CORE-1243
This commit is contained in:
Philip Korsholm
2023-03-14 12:08:52 +01:00
committed by GitHub
parent 24604f1b71
commit 30a3203640
6 changed files with 169 additions and 6 deletions

View File

@@ -6,11 +6,15 @@ const { setPort, useApi } = require("../../../../helpers/use-api")
const adminSeeder = require("../../../helpers/admin-seeder")
const cartSeeder = require("../../../helpers/cart-seeder")
const { simpleProductFactory } = require("../../../../api/factories")
const {
simpleProductFactory,
simpleCustomerFactory,
} = require("../../../../api/factories")
const { simpleSalesChannelFactory } = require("../../../../api/factories")
const {
simpleOrderFactory,
simpleRegionFactory,
simpleCartFactory,
} = require("../../../factories")
jest.setTimeout(30000)
@@ -57,6 +61,10 @@ describe("/store/carts", () => {
let invItemId
let variantId
let prodVarInventoryService
let inventoryService
let stockLocationService
let salesChannelLocationService
let regionId
beforeEach(async () => {
const api = useApi()
@@ -64,13 +72,14 @@ describe("/store/carts", () => {
prodVarInventoryService = appContainer.resolve(
"productVariantInventoryService"
)
const inventoryService = appContainer.resolve("inventoryService")
const stockLocationService = appContainer.resolve("stockLocationService")
const salesChannelLocationService = appContainer.resolve(
inventoryService = appContainer.resolve("inventoryService")
stockLocationService = appContainer.resolve("stockLocationService")
salesChannelLocationService = appContainer.resolve(
"salesChannelLocationService"
)
const r = await simpleRegionFactory(dbConnection, {})
regionId = r.id
await simpleSalesChannelFactory(dbConnection, {
id: "test-channel",
is_default: true,
@@ -143,6 +152,149 @@ describe("/store/carts", () => {
describe("Fulfillments", () => {
const lineItemId = "line-item-id"
it("Adjusts reservations on successful fulfillment on updated reservation item", async () => {
const api = useApi()
const lineItemId1 = "line-item-id-1"
// create new location for the inventoryItem with a quantity
const loc = await stockLocationService.create({ name: "test-location" })
const customer = await simpleCustomerFactory(dbConnection, {})
const cart = await simpleCartFactory(dbConnection, {
email: "adrien@test.com",
region: regionId,
line_items: [
{
id: lineItemId1,
variant_id: variantId,
quantity: 1,
unit_price: 1000,
},
],
sales_channel_id: "test-channel",
shipping_address: {},
shipping_methods: [
{
shipping_option: {
region_id: regionId,
},
},
],
})
await appContainer
.resolve("cartService")
.update(cart.id, { customer_id: customer.id })
let inventoryItem = await api.get(
`/admin/inventory-items/${invItemId}`,
adminHeaders
)
expect(inventoryItem.data.inventory_item.location_levels[0]).toEqual(
expect.objectContaining({
stocked_quantity: 1,
reserved_quantity: 0,
available_quantity: 1,
})
)
await api.post(`/store/carts/${cart.id}/payment-sessions`)
const completeRes = await api.post(`/store/carts/${cart.id}/complete`)
const orderId = completeRes.data.data.id
await salesChannelLocationService.associateLocation(
"test-channel",
locationId
)
await inventoryService.createInventoryLevel({
inventory_item_id: invItemId,
location_id: loc.id,
stocked_quantity: 1,
})
inventoryItem = await api.get(
`/admin/inventory-items/${invItemId}`,
adminHeaders
)
expect(inventoryItem.data.inventory_item.location_levels).toEqual(
expect.arrayContaining([
expect.objectContaining({
stocked_quantity: 1,
reserved_quantity: 1,
available_quantity: 0,
}),
expect.objectContaining({
stocked_quantity: 1,
reserved_quantity: 0,
available_quantity: 1,
}),
])
)
// update reservation item
const reservationItems = await api.get(
`/admin/reservations?line_item_id[]=${lineItemId1}`,
adminHeaders
)
const reservationItem = reservationItems.data.reservations[0]
const res = await api.post(
`/admin/reservations/${reservationItem.id}`,
{ location_id: loc.id },
adminHeaders
)
const fulfillmentRes = await api.post(
`/admin/orders/${orderId}/fulfillment`,
{
items: [{ item_id: lineItemId1, quantity: 1 }],
location_id: locationId,
},
adminHeaders
)
expect(fulfillmentRes.status).toBe(200)
expect(
fulfillmentRes.data.order.fulfillments[0].location_id
).toBeTruthy()
inventoryItem = await api.get(
`/admin/inventory-items/${invItemId}`,
adminHeaders
)
const reservations = await api.get(
`/admin/reservations?inventory_item_id[]=${invItemId}`,
adminHeaders
)
expect(reservations.data.reservations.length).toBe(0)
expect(inventoryItem.data.inventory_item.location_levels).toEqual(
expect.arrayContaining([
expect.objectContaining({
location_id: locationId,
stocked_quantity: 0,
reserved_quantity: 0,
available_quantity: 0,
}),
expect.objectContaining({
location_id: loc.id,
stocked_quantity: 1,
reserved_quantity: 0,
available_quantity: 1,
}),
])
)
})
it("Adjusts reservations on successful fulfillment with reservation", async () => {
const api = useApi()

View File

@@ -23,6 +23,7 @@ export type CartFactoryData = {
line_items?: LineItemFactoryData[]
shipping_address?: AddressFactoryData
shipping_methods?: ShippingMethodFactoryData[]
sales_channel_id?: string
}
export const simpleCartFactory = async (
@@ -52,6 +53,7 @@ export const simpleCartFactory = async (
typeof data.email !== "undefined" ? data.email : faker.internet.email(),
region_id: regionId,
shipping_address_id: address.id,
sales_channel_id: data.sales_channel_id || null,
})
const cart = await manager.save(toSave)