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:
co-authored by
Oliver Windall Juhl
parent
fe4b8feb7e
commit
0d1b63d773
@@ -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({
|
await inventoryService.createInventoryLevel({
|
||||||
inventory_item_id: invItem.id,
|
inventory_item_id: invItem.id,
|
||||||
location_id: locationId,
|
location_id: locationId,
|
||||||
stocked_quantity: 1,
|
stocked_quantity: 100,
|
||||||
})
|
})
|
||||||
|
|
||||||
const { id: orderId } = await simpleOrderFactory(dbConnection, {
|
const { id: orderId } = await simpleOrderFactory(dbConnection, {
|
||||||
@@ -143,9 +143,9 @@ describe("/store/carts", () => {
|
|||||||
|
|
||||||
expect(inventoryItem.data.inventory_item.location_levels[0]).toEqual(
|
expect(inventoryItem.data.inventory_item.location_levels[0]).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
stocked_quantity: 1,
|
stocked_quantity: 100,
|
||||||
reserved_quantity: 0,
|
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(inventoryItem.data.inventory_item.location_levels[0]).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
stocked_quantity: 1,
|
stocked_quantity: 100,
|
||||||
reserved_quantity: 0,
|
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(inventoryItem.data.inventory_item.location_levels).toEqual(
|
||||||
expect.arrayContaining([
|
expect.arrayContaining([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
stocked_quantity: 1,
|
stocked_quantity: 100,
|
||||||
reserved_quantity: 1,
|
reserved_quantity: 1,
|
||||||
available_quantity: 0,
|
available_quantity: 99,
|
||||||
}),
|
}),
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
stocked_quantity: 1,
|
stocked_quantity: 1,
|
||||||
@@ -281,9 +281,9 @@ describe("/store/carts", () => {
|
|||||||
expect.arrayContaining([
|
expect.arrayContaining([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
location_id: locationId,
|
location_id: locationId,
|
||||||
stocked_quantity: 0,
|
stocked_quantity: 99,
|
||||||
reserved_quantity: 0,
|
reserved_quantity: 0,
|
||||||
available_quantity: 0,
|
available_quantity: 99,
|
||||||
}),
|
}),
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
location_id: loc.id,
|
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 () => {
|
it("Adjusts reservation on successful fulfillment with reservation", async () => {
|
||||||
const api = useApi()
|
const api = useApi()
|
||||||
|
|
||||||
@@ -310,9 +434,9 @@ describe("/store/carts", () => {
|
|||||||
|
|
||||||
expect(inventoryItem.data.inventory_item.location_levels[0]).toEqual(
|
expect(inventoryItem.data.inventory_item.location_levels[0]).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
stocked_quantity: 1,
|
stocked_quantity: 100,
|
||||||
reserved_quantity: 1,
|
reserved_quantity: 1,
|
||||||
available_quantity: 0,
|
available_quantity: 99,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -343,9 +467,9 @@ describe("/store/carts", () => {
|
|||||||
expect(reservations.data.reservations.length).toBe(0)
|
expect(reservations.data.reservations.length).toBe(0)
|
||||||
expect(inventoryItem.data.inventory_item.location_levels[0]).toEqual(
|
expect(inventoryItem.data.inventory_item.location_levels[0]).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
stocked_quantity: 0,
|
stocked_quantity: 99,
|
||||||
reserved_quantity: 0,
|
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(inventoryItem.data.inventory_item.location_levels[0]).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
stocked_quantity: 0,
|
stocked_quantity: 99,
|
||||||
reserved_quantity: 0,
|
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(inventoryItem.data.inventory_item.location_levels[0]).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
stocked_quantity: 1,
|
stocked_quantity: 100,
|
||||||
reserved_quantity: 0,
|
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(inventoryItem.data.inventory_item.location_levels[0]).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
stocked_quantity: 0,
|
stocked_quantity: 99,
|
||||||
reserved_quantity: 0,
|
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 () => {
|
it("Fails to create fulfillment if there is not enough inventory at the fulfillment location", async () => {
|
||||||
const api = useApi()
|
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
|
const err = await api
|
||||||
.post(
|
.post(
|
||||||
`/admin/orders/${order.id}/fulfillment`,
|
`/admin/orders/${order.id}/fulfillment`,
|
||||||
|
|||||||
@@ -114,8 +114,8 @@ export default async (req, res) => {
|
|||||||
await orderServiceTx.retrieve(id, {
|
await orderServiceTx.retrieve(id, {
|
||||||
relations: ["fulfillments"],
|
relations: ["fulfillments"],
|
||||||
})
|
})
|
||||||
const existingFulfillmentMap = new Map(
|
const existingFulfillmentSet = new Set(
|
||||||
existingFulfillments.map((fulfillment) => [fulfillment.id, fulfillment])
|
existingFulfillments.map((fulfillment) => fulfillment.id)
|
||||||
)
|
)
|
||||||
|
|
||||||
await orderServiceTx.createFulfillment(id, validatedBody.items, {
|
await orderServiceTx.createFulfillment(id, validatedBody.items, {
|
||||||
@@ -137,7 +137,7 @@ export default async (req, res) => {
|
|||||||
pvInventoryService.withTransaction(transactionManager)
|
pvInventoryService.withTransaction(transactionManager)
|
||||||
|
|
||||||
await updateInventoryAndReservations(
|
await updateInventoryAndReservations(
|
||||||
fulfillments.filter((f) => !existingFulfillmentMap[f.id]),
|
fulfillments.filter((f) => !existingFulfillmentSet.has(f.id)),
|
||||||
{
|
{
|
||||||
inventoryService: pvInventoryServiceTx,
|
inventoryService: pvInventoryServiceTx,
|
||||||
locationId: validatedBody.location_id,
|
locationId: validatedBody.location_id,
|
||||||
|
|||||||
Reference in New Issue
Block a user