fix(core-flows): account for unfulfilled items while generating order status (#8698)

what:

- account for unfulfilled items while generating order status

RESOLVES CC-314
This commit is contained in:
Riqwan Thamir
2024-08-21 16:33:43 +02:00
committed by GitHub
parent 0da9445d80
commit de7848f68d
3 changed files with 103 additions and 10 deletions

View File

@@ -877,7 +877,7 @@ medusaIntegrationTestRunner({
items: [
{
variant_id: productExtra.variants[0].id,
quantity: 2,
quantity: 3,
},
],
},
@@ -917,7 +917,7 @@ medusaIntegrationTestRunner({
await api.get(`/admin/orders/${order.id}`, adminHeaders)
).data.order
const fulfillableItem = fulfillOrder.items.find(
const fulfillableItem = fulfillOrder.items.filter(
(item) => item.detail.fulfilled_quantity === 0
)
@@ -925,10 +925,85 @@ medusaIntegrationTestRunner({
`/admin/orders/${order.id}/fulfillments`,
{
location_id: location.id,
items: [{ id: fulfillableItem.id, quantity: 1 }],
items: [{ id: fulfillableItem[0].id, quantity: 1 }],
},
adminHeaders
)
let orderResult = (
await api.get(`/admin/orders/${order.id}`, adminHeaders)
).data.order
expect(orderResult.fulfillment_status).toEqual("partially_fulfilled")
await api.post(
`/admin/orders/${order.id}/fulfillments`,
{
location_id: location.id,
items: [{ id: fulfillableItem[0].id, quantity: 2 }],
},
adminHeaders
)
orderResult = (
await api.get(
`/admin/orders/${order.id}?fields=*fulfillments,*fulfillments.items`,
adminHeaders
)
).data.order
expect(orderResult.fulfillment_status).toEqual("fulfilled")
await api.post(
`admin/orders/${order.id}/fulfillments/${orderResult.fulfillments[0].id}/shipments`,
{
items: orderResult.fulfillments[0]?.items?.map((i) => ({
id: i.line_item_id,
quantity: i.quantity,
})),
},
adminHeaders
)
orderResult = (
await api.get(
`/admin/orders/${order.id}?fields=*fulfillments,*fulfillments.items`,
adminHeaders
)
).data.order
expect(orderResult.fulfillment_status).toEqual("partially_shipped")
await api.post(
`admin/orders/${order.id}/fulfillments/${orderResult.fulfillments[1].id}/shipments`,
{
items: orderResult.fulfillments[1]?.items?.map((i) => ({
id: i.line_item_id,
quantity: i.quantity,
})),
},
adminHeaders
)
await api.post(
`admin/orders/${order.id}/fulfillments/${orderResult.fulfillments[2].id}/shipments`,
{
items: orderResult.fulfillments[2]?.items?.map((i) => ({
id: i.line_item_id,
quantity: i.quantity,
})),
},
adminHeaders
)
orderResult = (
await api.get(
`/admin/orders/${order.id}?fields=*fulfillments`,
adminHeaders
)
).data.order
expect(orderResult.fulfillment_status).toEqual("shipped")
})
})
})

View File

@@ -1,5 +1,5 @@
import { OrderDetailDTO } from "@medusajs/types"
import { MathBN } from "@medusajs/utils"
import { isDefined, MathBN } from "@medusajs/utils"
export const getLastPaymentStatus = (order: OrderDetailDTO) => {
const PaymentStatus = {
@@ -103,17 +103,22 @@ export const getLastFulfillmentStatus = (order: OrderDetailDTO) => {
}
let fulfillmentStatus = {}
for (const status in FulfillmentStatus) {
fulfillmentStatus[FulfillmentStatus[status]] = 0
}
const statusMap = {
packed_at: FulfillmentStatus.FULFILLED,
shipped_at: FulfillmentStatus.SHIPPED,
delivered_at: FulfillmentStatus.DELIVERED,
canceled_at: FulfillmentStatus.CANCELED,
delivered_at: FulfillmentStatus.DELIVERED,
shipped_at: FulfillmentStatus.SHIPPED,
packed_at: FulfillmentStatus.FULFILLED,
}
for (const fulfillmentCollection of order.fulfillments) {
// Note: The order of the statusMap keys is important as we break
// the loop when we have found a match. The match should be prioritized
// based on order of precedence of statuses
for (const key in statusMap) {
if (fulfillmentCollection[key]) {
fulfillmentStatus[statusMap[key]] += 1
@@ -126,10 +131,20 @@ export const getLastFulfillmentStatus = (order: OrderDetailDTO) => {
const totalFulfillmentsExceptCanceled =
totalFulfillments - fulfillmentStatus[FulfillmentStatus.CANCELED]
// Whenever there are any unfulfilled items in the order, it should be
// considered partially_[STATUS] where status is picked up from the hierarchy
// of statuses
const hasUnfulfilledItems = (order.items || [])?.filter(
(i) =>
isDefined(i?.detail?.raw_fulfilled_quantity) &&
MathBN.lt(i.detail.raw_fulfilled_quantity, i.raw_quantity)
).length > 0
if (fulfillmentStatus[FulfillmentStatus.DELIVERED] > 0) {
if (
fulfillmentStatus[FulfillmentStatus.DELIVERED] ===
totalFulfillmentsExceptCanceled
totalFulfillmentsExceptCanceled &&
!hasUnfulfilledItems
) {
return FulfillmentStatus.DELIVERED
}
@@ -140,7 +155,8 @@ export const getLastFulfillmentStatus = (order: OrderDetailDTO) => {
if (fulfillmentStatus[FulfillmentStatus.SHIPPED] > 0) {
if (
fulfillmentStatus[FulfillmentStatus.SHIPPED] ===
totalFulfillmentsExceptCanceled
totalFulfillmentsExceptCanceled &&
!hasUnfulfilledItems
) {
return FulfillmentStatus.SHIPPED
}
@@ -151,7 +167,8 @@ export const getLastFulfillmentStatus = (order: OrderDetailDTO) => {
if (fulfillmentStatus[FulfillmentStatus.FULFILLED] > 0) {
if (
fulfillmentStatus[FulfillmentStatus.FULFILLED] ===
totalFulfillmentsExceptCanceled
totalFulfillmentsExceptCanceled &&
!hasUnfulfilledItems
) {
return FulfillmentStatus.FULFILLED
}

View File

@@ -37,6 +37,7 @@ export const getOrdersListWorkflow = createWorkflow(
"id",
"status",
"version",
"items.*",
"payment_collections.status",
"payment_collections.amount",
"payment_collections.captured_amount",