fix(medusa): Use get for creating fulfillments (#3498)

* use get

* changeset

* use set

* add tests

---------

Co-authored-by: Oliver Windall Juhl <59018053+olivermrbl@users.noreply.github.com>
This commit is contained in:
Philip Korsholm
2023-03-16 19:03:36 +01:00
committed by GitHub
parent fe4b8feb7e
commit 0d1b63d773
3 changed files with 176 additions and 22 deletions

View File

@@ -0,0 +1,5 @@
---
"@medusajs/medusa": patch
---
fix(medusa): use get instead of indexing into map

View File

@@ -112,7 +112,7 @@ describe("/store/carts", () => {
await inventoryService.createInventoryLevel({
inventory_item_id: invItem.id,
location_id: locationId,
stocked_quantity: 1,
stocked_quantity: 100,
})
const { id: orderId } = await simpleOrderFactory(dbConnection, {
@@ -143,9 +143,9 @@ describe("/store/carts", () => {
expect(inventoryItem.data.inventory_item.location_levels[0]).toEqual(
expect.objectContaining({
stocked_quantity: 1,
stocked_quantity: 100,
reserved_quantity: 0,
available_quantity: 1,
available_quantity: 100,
})
)
})
@@ -196,9 +196,9 @@ describe("/store/carts", () => {
expect(inventoryItem.data.inventory_item.location_levels[0]).toEqual(
expect.objectContaining({
stocked_quantity: 1,
stocked_quantity: 100,
reserved_quantity: 0,
available_quantity: 1,
available_quantity: 100,
})
)
@@ -226,9 +226,9 @@ describe("/store/carts", () => {
expect(inventoryItem.data.inventory_item.location_levels).toEqual(
expect.arrayContaining([
expect.objectContaining({
stocked_quantity: 1,
stocked_quantity: 100,
reserved_quantity: 1,
available_quantity: 0,
available_quantity: 99,
}),
expect.objectContaining({
stocked_quantity: 1,
@@ -281,9 +281,9 @@ describe("/store/carts", () => {
expect.arrayContaining([
expect.objectContaining({
location_id: locationId,
stocked_quantity: 0,
stocked_quantity: 99,
reserved_quantity: 0,
available_quantity: 0,
available_quantity: 99,
}),
expect.objectContaining({
location_id: loc.id,
@@ -295,6 +295,130 @@ describe("/store/carts", () => {
)
})
it("Adjusts reservations on several subsequent fulfillments (being cancelled in-between), with a total quantity greater that the line item quantity", async () => {
const api = useApi()
const lineItemId1 = "line-item-id-1"
const customer = await simpleCustomerFactory(dbConnection, {})
const cart = await simpleCartFactory(dbConnection, {
email: "adrien@test.com",
region: regionId,
line_items: [
{
id: lineItemId1,
variant_id: variantId,
quantity: 3,
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: 100,
reserved_quantity: 0,
available_quantity: 100,
})
)
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
let fulfillmentRes = await api.post(
`/admin/orders/${orderId}/fulfillment`,
{
items: [{ item_id: lineItemId1, quantity: 2 }],
location_id: locationId,
},
adminHeaders
)
expect(fulfillmentRes.status).toBe(200)
expect(
fulfillmentRes.data.order.fulfillments[0].location_id
).toBeTruthy()
expect(fulfillmentRes.data.order.fulfillment_status).toEqual(
"partially_fulfilled"
)
await api.post(
`/admin/orders/${orderId}/fulfillments/${fulfillmentRes.data.order.fulfillments[0].id}/cancel`,
{},
adminHeaders
)
fulfillmentRes = await api.post(
`/admin/orders/${orderId}/fulfillment`,
{
items: [{ item_id: lineItemId1, quantity: 2 }],
location_id: locationId,
},
adminHeaders
)
expect(fulfillmentRes.status).toBe(200)
expect(
fulfillmentRes.data.order.fulfillments[1].location_id
).toBeTruthy()
expect(fulfillmentRes.data.order.fulfillment_status).toEqual(
"partially_fulfilled"
)
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: 98,
reserved_quantity: 0,
available_quantity: 98,
}),
])
)
const orderRes = await api.get(`/admin/orders/${orderId}`, adminHeaders)
expect(orderRes.data.order.items).toEqual([
expect.objectContaining({
id: lineItemId1,
fulfilled_quantity: 2,
quantity: 3,
}),
])
})
it("Adjusts reservation on successful fulfillment with reservation", async () => {
const api = useApi()
@@ -310,9 +434,9 @@ describe("/store/carts", () => {
expect(inventoryItem.data.inventory_item.location_levels[0]).toEqual(
expect.objectContaining({
stocked_quantity: 1,
stocked_quantity: 100,
reserved_quantity: 1,
available_quantity: 0,
available_quantity: 99,
})
)
@@ -343,9 +467,9 @@ describe("/store/carts", () => {
expect(reservations.data.reservations.length).toBe(0)
expect(inventoryItem.data.inventory_item.location_levels[0]).toEqual(
expect.objectContaining({
stocked_quantity: 0,
stocked_quantity: 99,
reserved_quantity: 0,
available_quantity: 0,
available_quantity: 99,
})
)
})
@@ -646,9 +770,9 @@ describe("/store/carts", () => {
expect(inventoryItem.data.inventory_item.location_levels[0]).toEqual(
expect.objectContaining({
stocked_quantity: 0,
stocked_quantity: 99,
reserved_quantity: 0,
available_quantity: 0,
available_quantity: 99,
})
)
@@ -669,9 +793,9 @@ describe("/store/carts", () => {
)
expect(inventoryItem.data.inventory_item.location_levels[0]).toEqual(
expect.objectContaining({
stocked_quantity: 1,
stocked_quantity: 100,
reserved_quantity: 0,
available_quantity: 1,
available_quantity: 100,
})
)
})
@@ -699,9 +823,9 @@ describe("/store/carts", () => {
expect(inventoryItem.data.inventory_item.location_levels[0]).toEqual(
expect.objectContaining({
stocked_quantity: 0,
stocked_quantity: 99,
reserved_quantity: 0,
available_quantity: 0,
available_quantity: 99,
})
)
})
@@ -709,6 +833,31 @@ describe("/store/carts", () => {
it("Fails to create fulfillment if there is not enough inventory at the fulfillment location", async () => {
const api = useApi()
const updateRes = await api.post(
`/admin/inventory-items/${invItemId}/location-levels/${locationId}`,
{
stocked_quantity: 1,
},
adminHeaders
)
expect(updateRes.status).toBe(200)
const locationLevels = await api.get(
`/admin/variants/${variantId}/inventory`,
adminHeaders
)
expect(
locationLevels.data.variant.inventory[0].location_levels[0]
).toEqual(
expect.objectContaining({
stocked_quantity: 1,
reserved_quantity: 0,
available_quantity: 1,
})
)
const err = await api
.post(
`/admin/orders/${order.id}/fulfillment`,

View File

@@ -114,8 +114,8 @@ export default async (req, res) => {
await orderServiceTx.retrieve(id, {
relations: ["fulfillments"],
})
const existingFulfillmentMap = new Map(
existingFulfillments.map((fulfillment) => [fulfillment.id, fulfillment])
const existingFulfillmentSet = new Set(
existingFulfillments.map((fulfillment) => fulfillment.id)
)
await orderServiceTx.createFulfillment(id, validatedBody.items, {
@@ -137,7 +137,7 @@ export default async (req, res) => {
pvInventoryService.withTransaction(transactionManager)
await updateInventoryAndReservations(
fulfillments.filter((f) => !existingFulfillmentMap[f.id]),
fulfillments.filter((f) => !existingFulfillmentSet.has(f.id)),
{
inventoryService: pvInventoryServiceTx,
locationId: validatedBody.location_id,