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:
5
.changeset/olive-penguins-sin.md
Normal file
5
.changeset/olive-penguins-sin.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@medusajs/medusa": patch
|
||||
---
|
||||
|
||||
fix(medusa): use get instead of indexing into map
|
||||
@@ -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`,
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user