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:
@@ -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")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ export const getOrdersListWorkflow = createWorkflow(
|
||||
"id",
|
||||
"status",
|
||||
"version",
|
||||
"items.*",
|
||||
"payment_collections.status",
|
||||
"payment_collections.amount",
|
||||
"payment_collections.captured_amount",
|
||||
|
||||
Reference in New Issue
Block a user