Open erickirt opened 2 hours ago
Below are two versions of the getLastFulfillmentStatus
function tailored to address the reported confusion around the fulfilled
status when packed_at
timestamps are present. Each version includes a concise explanation of the changes made.
Changes:
PACKED
to distinctly represent when items are packed but not yet shipped.packed_at
without immediately setting the fulfillment status to FULFILLED
.export const getLastFulfillmentStatus = (order: OrderDetailDTO) => {
const FulfillmentStatus = {
NOT_FULFILLED: "not_fulfilled",
PARTIALLY_FULFILLED: "partially_fulfilled",
PACKED: "packed", // New status added
FULFILLED: "fulfilled",
PARTIALLY_SHIPPED: "partially_shipped",
SHIPPED: "shipped",
DELIVERED: "delivered",
PARTIALLY_DELIVERED: "partially_delivered",
CANCELED: "canceled",
}
let fulfillmentStatus: { [key: string]: number } = {}
for (const status in FulfillmentStatus) {
fulfillmentStatus[FulfillmentStatus[status]] = 0
}
const statusMap = {
canceled_at: FulfillmentStatus.CANCELED,
delivered_at: FulfillmentStatus.DELIVERED,
shipped_at: FulfillmentStatus.SHIPPED,
packed_at: FulfillmentStatus.PACKED, // Updated mapping
}
for (const fulfillmentCollection of order.fulfillments) {
for (const key in statusMap) {
if (fulfillmentCollection[key]) {
fulfillmentStatus[statusMap[key]] += 1
break
}
}
}
const totalFulfillments = order.fulfillments.length
const totalFulfillmentsExceptCanceled =
totalFulfillments - fulfillmentStatus[FulfillmentStatus.CANCELED]
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 &&
!hasUnfulfilledItems
) {
return FulfillmentStatus.DELIVERED
}
return FulfillmentStatus.PARTIALLY_DELIVERED
}
if (fulfillmentStatus[FulfillmentStatus.SHIPPED] > 0) {
if (
fulfillmentStatus[FulfillmentStatus.SHIPPED] ===
totalFulfillmentsExceptCanceled &&
!hasUnfulfilledItems
) {
return FulfillmentStatus.SHIPPED
}
return FulfillmentStatus.PARTIALLY_SHIPPED
}
if (fulfillmentStatus[FulfillmentStatus.PACKED] > 0) { // New condition
if (
fulfillmentStatus[FulfillmentStatus.PACKED] ===
totalFulfillmentsExceptCanceled &&
!hasUnfulfilledItems
) {
return FulfillmentStatus.PACKED
}
return FulfillmentStatus.PARTIALLY_FULFILLED
}
if (fulfillmentStatus[FulfillmentStatus.FULFILLED] > 0) {
if (
fulfillmentStatus[FulfillmentStatus.FULFILLED] ===
totalFulfillmentsExceptCanceled &&
!hasUnfulfilledItems
) {
return FulfillmentStatus.FULFILLED
}
return FulfillmentStatus.PARTIALLY_FULFILLED
}
if (
fulfillmentStatus[FulfillmentStatus.CANCELED] > 0 &&
fulfillmentStatus[FulfillmentStatus.CANCELED] === totalFulfillments
) {
return FulfillmentStatus.CANCELED
}
return FulfillmentStatus.NOT_FULFILLED
}
Explanation:
PACKED
Status: Differentiates between items that are packed (PACKED
) and those that are fully fulfilled (FULFILLED
), reducing confusion.Changes:
packed_at
as a stage before fulfilled
, ensuring that the fulfillment status does not directly switch to FULFILLED
upon packing.export const getLastFulfillmentStatus = (order: OrderDetailDTO) => {
const FulfillmentStatus = {
NOT_FULFILLED: "not_fulfilled",
PARTIALLY_FULFILLED: "partially_fulfilled",
FULFILLED: "fulfilled",
PARTIALLY_SHIPPED: "partially_shipped",
SHIPPED: "shipped",
DELIVERED: "delivered",
PARTIALLY_DELIVERED: "partially_delivered",
CANCELED: "canceled",
}
let fulfillmentStatus: { [key: string]: number } = {}
for (const status in FulfillmentStatus) {
fulfillmentStatus[FulfillmentStatus[status]] = 0
}
const statusMap = {
canceled_at: FulfillmentStatus.CANCELED,
delivered_at: FulfillmentStatus.DELIVERED,
shipped_at: FulfillmentStatus.SHIPPED,
packed_at: FulfillmentStatus.PARTIALLY_FULFILLED, // Changed mapping
}
for (const fulfillmentCollection of order.fulfillments) {
for (const key in statusMap) {
if (fulfillmentCollection[key]) {
fulfillmentStatus[statusMap[key]] += 1
break
}
}
}
const totalFulfillments = order.fulfillments.length
const totalFulfillmentsExceptCanceled =
totalFulfillments - fulfillmentStatus[FulfillmentStatus.CANCELED]
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 &&
!hasUnfulfilledItems
) {
return FulfillmentStatus.DELIVERED
}
return FulfillmentStatus.PARTIALLY_DELIVERED
}
if (fulfillmentStatus[FulfillmentStatus.SHIPPED] > 0) {
if (
fulfillmentStatus[FulfillmentStatus.SHIPPED] ===
totalFulfillmentsExceptCanceled &&
!hasUnfulfilledItems
) {
return FulfillmentStatus.SHIPPED
}
return FulfillmentStatus.PARTIALLY_SHIPPED
}
if (fulfillmentStatus[FulfillmentStatus.FULFILLED] > 0) {
if (
fulfillmentStatus[FulfillmentStatus.FULFILLED] ===
totalFulfillmentsExceptCanceled &&
!hasUnfulfilledItems
) {
return FulfillmentStatus.FULFILLED
}
return FulfillmentStatus.PARTIALLY_FULFILLED
}
if (fulfillmentStatus[FulfillmentStatus.PARTIALLY_FULFILLED] > 0) { // New condition
return FulfillmentStatus.PARTIALLY_FULFILLED
}
if (
fulfillmentStatus[FulfillmentStatus.CANCELED] > 0 &&
fulfillmentStatus[FulfillmentStatus.CANCELED] === totalFulfillments
) {
return FulfillmentStatus.CANCELED
}
return FulfillmentStatus.NOT_FULFILLED
}
Explanation:
packed_at
to PARTIALLY_FULFILLED
: Instead of directly setting the status to FULFILLED
, packed items now contribute to a PARTIALLY_FULFILLED
status, ensuring that the order is only marked as fully fulfilled when all fulfillment criteria are met.Version 1:
PACKED
Status to clearly differentiate between packed and fulfilled states.packed_at
to the new PACKED
status.Version 2:
packed_at
to PARTIALLY_FULFILLED
instead of FULFILLED
.
I encountered a potential issue where the order’s fulfillment_status is set to "fulfilled" when all items in the fulfillment have a packed_at timestamp. This can cause confusion, as "fulfilled" typically implies the order has been shipped, not just packed. The current behavior of equating packed_at with the "fulfilled" status could be misleading, as it does not distinguish between an order being fully packed and actually shipped. Could you clarify if this is the intended behavior, or if a distinction between packed and shipped statuses is needed?
Link to file