chore(order): aggregate statuses (#7497)
This commit is contained in:
committed by
GitHub
parent
8e66e10995
commit
bbca54efa7
@@ -155,6 +155,9 @@ medusaIntegrationTestRunner({
|
||||
version: 1,
|
||||
display_id: 1,
|
||||
payment_collections: [],
|
||||
payment_status: "not_paid",
|
||||
fulfillments: [],
|
||||
fulfillment_status: "not_fulfilled",
|
||||
summary: expect.objectContaining({
|
||||
// TODO: add all summary fields
|
||||
}),
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
import React, { useEffect, useState } from "react"
|
||||
import * as zod from "zod"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { useEffect, useState } from "react"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import * as zod from "zod"
|
||||
|
||||
import { useForm, useWatch } from "react-hook-form"
|
||||
import { AdminOrder } from "@medusajs/types"
|
||||
import { Alert, Button, Select, toast } from "@medusajs/ui"
|
||||
import { OrderDTO } from "@medusajs/types"
|
||||
import { useForm, useWatch } from "react-hook-form"
|
||||
|
||||
import { Form } from "../../../../../components/common/form"
|
||||
import {
|
||||
RouteFocusModal,
|
||||
useRouteModal,
|
||||
} from "../../../../../components/route-modal"
|
||||
import { CreateFulfillmentSchema } from "./constants"
|
||||
import { Form } from "../../../../../components/common/form"
|
||||
import { OrderCreateFulfillmentItem } from "./order-create-fulfillment-item"
|
||||
import { getFulfillableQuantity } from "../../../../../lib/order-item"
|
||||
import { useCreateFulfillment } from "../../../../../hooks/api/fulfillment"
|
||||
import { useStockLocations } from "../../../../../hooks/api/stock-locations"
|
||||
import { useFulfillmentProviders } from "../../../../../hooks/api/fulfillment-providers"
|
||||
import { useStockLocations } from "../../../../../hooks/api/stock-locations"
|
||||
import { cleanNonValues, pick } from "../../../../../lib/common"
|
||||
import { getFulfillableQuantity } from "../../../../../lib/order-item"
|
||||
import { CreateFulfillmentSchema } from "./constants"
|
||||
import { OrderCreateFulfillmentItem } from "./order-create-fulfillment-item"
|
||||
|
||||
type OrderCreateFulfillmentFormProps = {
|
||||
order: OrderDTO
|
||||
order: AdminOrder
|
||||
}
|
||||
|
||||
export function OrderCreateFulfillmentForm({
|
||||
@@ -43,10 +43,13 @@ export function OrderCreateFulfillmentForm({
|
||||
|
||||
const form = useForm<zod.infer<typeof CreateFulfillmentSchema>>({
|
||||
defaultValues: {
|
||||
quantity: fulfillableItems.reduce((acc, item) => {
|
||||
acc[item.id] = getFulfillableQuantity(item)
|
||||
return acc
|
||||
}, {} as Record<string, number>),
|
||||
quantity: fulfillableItems.reduce(
|
||||
(acc, item) => {
|
||||
acc[item.id] = getFulfillableQuantity(item)
|
||||
return acc
|
||||
},
|
||||
{} as Record<string, number>
|
||||
),
|
||||
// send_notification: !order.no_notification,
|
||||
},
|
||||
resolver: zodResolver(CreateFulfillmentSchema),
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { AdminOrder } from "@medusajs/types"
|
||||
import { Container, Heading } from "@medusajs/ui"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { OrderNoteForm } from "./order-note-form"
|
||||
import { OrderTimeline } from "./order-timeline"
|
||||
import { OrderDTO } from "@medusajs/types"
|
||||
|
||||
type OrderActivityProps = {
|
||||
order: OrderDTO
|
||||
order: AdminOrder
|
||||
}
|
||||
|
||||
export const OrderActivitySection = ({ order }: OrderActivityProps) => {
|
||||
|
||||
@@ -5,12 +5,12 @@ import { useRef } from "react"
|
||||
import { useForm } from "react-hook-form"
|
||||
import { z } from "zod"
|
||||
|
||||
import { AdminOrder } from "@medusajs/types"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { Form } from "../../../../../components/common/form"
|
||||
import { OrderDTO } from "@medusajs/types"
|
||||
|
||||
type OrderNoteFormProps = {
|
||||
order: OrderDTO
|
||||
order: AdminOrder
|
||||
}
|
||||
|
||||
const OrderNoteSchema = z.object({
|
||||
|
||||
@@ -6,14 +6,13 @@ import { PropsWithChildren, ReactNode, useMemo, useState } from "react"
|
||||
import { Link } from "react-router-dom"
|
||||
|
||||
import { XMarkMini } from "@medusajs/icons"
|
||||
import { AdminOrder } from "@medusajs/types"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { Skeleton } from "../../../../../components/common/skeleton"
|
||||
import { useDate } from "../../../../../hooks/use-date"
|
||||
import { getStylizedAmount } from "../../../../../lib/money-amount-helpers"
|
||||
import { OrderDTO } from "@medusajs/types"
|
||||
|
||||
type OrderTimelineProps = {
|
||||
order: OrderDTO
|
||||
order: AdminOrder
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Buildings, XCircle } from "@medusajs/icons"
|
||||
import {
|
||||
AdminOrder,
|
||||
FulfillmentDTO,
|
||||
OrderDTO,
|
||||
OrderLineItemDTO,
|
||||
ProductVariantDTO,
|
||||
} from "@medusajs/types"
|
||||
@@ -27,7 +27,7 @@ import { formatProvider } from "../../../../../lib/format-provider"
|
||||
import { getLocaleAmount } from "../../../../../lib/money-amount-helpers"
|
||||
|
||||
type OrderFulfillmentSectionProps = {
|
||||
order: OrderDTO & { fulfillments: FulfillmentDTO[] }
|
||||
order: AdminOrder
|
||||
}
|
||||
|
||||
export const OrderFulfillmentSection = ({
|
||||
@@ -103,11 +103,7 @@ const UnfulfilledItem = ({
|
||||
)
|
||||
}
|
||||
|
||||
const UnfulfilledItemBreakdown = ({
|
||||
order,
|
||||
}: {
|
||||
order: OrderDTO & { fulfillments: FulfillmentDTO[] }
|
||||
}) => {
|
||||
const UnfulfilledItemBreakdown = ({ order }: { order: AdminOrder }) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
// Create an array of order items that haven't been fulfilled or at least not fully fulfilled
|
||||
@@ -161,7 +157,7 @@ const Fulfillment = ({
|
||||
index,
|
||||
}: {
|
||||
fulfillment: FulfillmentDTO
|
||||
order: OrderDTO
|
||||
order: AdminOrder
|
||||
index: number
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { Buildings, PencilSquare, ArrowUturnLeft } from "@medusajs/icons"
|
||||
import { OrderDTO, OrderLineItemDTO, ReservationItemDTO } from "@medusajs/types"
|
||||
import {
|
||||
AdminOrder,
|
||||
OrderLineItemDTO,
|
||||
ReservationItemDTO,
|
||||
} from "@medusajs/types"
|
||||
import { Container, Copy, Heading, StatusBadge, Text } from "@medusajs/ui"
|
||||
import { useTranslation } from "react-i18next"
|
||||
|
||||
@@ -11,7 +14,7 @@ import {
|
||||
} from "../../../../../lib/money-amount-helpers"
|
||||
|
||||
type OrderSummarySectionProps = {
|
||||
order: OrderDTO
|
||||
order: AdminOrder
|
||||
}
|
||||
|
||||
export const OrderSummarySection = ({ order }: OrderSummarySectionProps) => {
|
||||
@@ -25,7 +28,7 @@ export const OrderSummarySection = ({ order }: OrderSummarySectionProps) => {
|
||||
)
|
||||
}
|
||||
|
||||
const Header = ({ order }: { order: OrderDTO }) => {
|
||||
const Header = ({ order }: { order: AdminOrder }) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
@@ -129,7 +132,7 @@ const Item = ({
|
||||
)
|
||||
}
|
||||
|
||||
const ItemBreakdown = ({ order }: { order: OrderDTO }) => {
|
||||
const ItemBreakdown = ({ order }: { order: AdminOrder }) => {
|
||||
// const { reservations, isError, error } = useAdminReservations({
|
||||
// line_item_id: order.items.map((i) => i.id),
|
||||
// })
|
||||
@@ -184,7 +187,7 @@ const Cost = ({
|
||||
</div>
|
||||
)
|
||||
|
||||
const CostBreakdown = ({ order }: { order: OrderDTO }) => {
|
||||
const CostBreakdown = ({ order }: { order: AdminOrder }) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
@@ -230,7 +233,7 @@ const CostBreakdown = ({ order }: { order: OrderDTO }) => {
|
||||
)
|
||||
}
|
||||
|
||||
const Total = ({ order }: { order: OrderDTO }) => {
|
||||
const Total = ({ order }: { order: AdminOrder }) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
import {
|
||||
getLastFulfillmentStatus,
|
||||
getLastPaymentStatus,
|
||||
} from "../aggregate-status"
|
||||
|
||||
describe("Aggregate Order Status", () => {
|
||||
it("should return aggregated payment collection status", () => {
|
||||
expect(
|
||||
getLastPaymentStatus({
|
||||
payment_collections: [],
|
||||
})
|
||||
).toEqual("not_paid")
|
||||
|
||||
expect(
|
||||
getLastPaymentStatus({
|
||||
payment_collections: [{ status: "not_paid" }],
|
||||
})
|
||||
).toEqual("not_paid")
|
||||
|
||||
expect(
|
||||
getLastPaymentStatus({
|
||||
payment_collections: [{ status: "not_paid" }, { status: "awaiting" }],
|
||||
})
|
||||
).toEqual("awaiting")
|
||||
|
||||
expect(
|
||||
getLastPaymentStatus({
|
||||
payment_collections: [
|
||||
{ status: "requires_action" },
|
||||
{ status: "refunded" },
|
||||
{ status: "refunded" },
|
||||
{ status: "captured" },
|
||||
{ status: "captured" },
|
||||
{ status: "canceled" },
|
||||
{ status: "authorized" },
|
||||
],
|
||||
})
|
||||
).toEqual("requires_action")
|
||||
|
||||
expect(
|
||||
getLastPaymentStatus({
|
||||
payment_collections: [
|
||||
{ status: "awaiting" },
|
||||
{ status: "awaiting" },
|
||||
{ status: "canceled" },
|
||||
{ status: "awaiting" },
|
||||
],
|
||||
})
|
||||
).toEqual("awaiting")
|
||||
|
||||
expect(
|
||||
getLastPaymentStatus({
|
||||
payment_collections: [
|
||||
{ status: "authorized" },
|
||||
{ status: "authorized" },
|
||||
{ status: "canceled" },
|
||||
],
|
||||
})
|
||||
).toEqual("authorized")
|
||||
|
||||
expect(
|
||||
getLastPaymentStatus({
|
||||
payment_collections: [
|
||||
{ status: "awaiting" },
|
||||
{ status: "authorized" },
|
||||
{ status: "canceled" },
|
||||
],
|
||||
})
|
||||
).toEqual("partially_authorized")
|
||||
|
||||
expect(
|
||||
getLastPaymentStatus({
|
||||
payment_collections: [
|
||||
{ status: "authorized", refunded_amount: 10, amount: 10 },
|
||||
{ status: "authorized", refunded_amount: 5, amount: 10 },
|
||||
{ status: "canceled" },
|
||||
],
|
||||
})
|
||||
).toEqual("partially_refunded")
|
||||
|
||||
expect(
|
||||
getLastPaymentStatus({
|
||||
payment_collections: [
|
||||
{ status: "authorized", captured_amount: 10, amount: 10 },
|
||||
{ status: "authorized", refunded_amount: 10, amount: 10 },
|
||||
{ status: "authorized", refunded_amount: 10, amount: 10 },
|
||||
{ status: "authorized" },
|
||||
{ status: "canceled" },
|
||||
],
|
||||
})
|
||||
).toEqual("partially_refunded")
|
||||
|
||||
expect(
|
||||
getLastPaymentStatus({
|
||||
payment_collections: [
|
||||
{ status: "authorized", captured_amount: 10, amount: 10 },
|
||||
{ status: "authorized", captured_amount: 12, amount: 12 },
|
||||
{ status: "canceled" },
|
||||
],
|
||||
})
|
||||
).toEqual("captured")
|
||||
|
||||
expect(
|
||||
getLastPaymentStatus({
|
||||
payment_collections: [
|
||||
{ status: "authorized", captured_amount: 10, amount: 10 },
|
||||
{ status: "authorized", captured_amount: 5, amount: 10 },
|
||||
],
|
||||
})
|
||||
).toEqual("partially_captured")
|
||||
|
||||
expect(
|
||||
getLastPaymentStatus({
|
||||
payment_collections: [
|
||||
{ status: "authorized", captured_amount: 10, amount: 10 },
|
||||
{ status: "authorized", captured_amount: 10, amount: 10 },
|
||||
{ status: "authorized" },
|
||||
],
|
||||
})
|
||||
).toEqual("partially_captured")
|
||||
|
||||
expect(
|
||||
getLastPaymentStatus({
|
||||
payment_collections: [
|
||||
{ status: "authorized", captured_amount: 10, amount: 10 },
|
||||
{ status: "authorized", captured_amount: 12, amount: 12 },
|
||||
],
|
||||
})
|
||||
).toEqual("captured")
|
||||
|
||||
expect(
|
||||
getLastPaymentStatus({
|
||||
payment_collections: [{ status: "canceled" }, { status: "canceled" }],
|
||||
})
|
||||
).toEqual("canceled")
|
||||
})
|
||||
|
||||
it("should return aggregated fulfillment status", () => {
|
||||
expect(
|
||||
getLastFulfillmentStatus({
|
||||
fulfillments: [],
|
||||
})
|
||||
).toEqual("not_fulfilled")
|
||||
|
||||
expect(
|
||||
getLastFulfillmentStatus({
|
||||
fulfillments: [{ created_at: new Date() }],
|
||||
})
|
||||
).toEqual("not_fulfilled")
|
||||
|
||||
expect(
|
||||
getLastFulfillmentStatus({
|
||||
fulfillments: [{ created_at: new Date() }, { packed_at: new Date() }],
|
||||
})
|
||||
).toEqual("partially_fulfilled")
|
||||
|
||||
expect(
|
||||
getLastFulfillmentStatus({
|
||||
fulfillments: [{ packed_at: new Date() }, { packed_at: new Date() }],
|
||||
})
|
||||
).toEqual("fulfilled")
|
||||
|
||||
expect(
|
||||
getLastFulfillmentStatus({
|
||||
fulfillments: [{ shipped_at: new Date() }, { packed_at: new Date() }],
|
||||
})
|
||||
).toEqual("partially_shipped")
|
||||
|
||||
expect(
|
||||
getLastFulfillmentStatus({
|
||||
fulfillments: [{ shipped_at: new Date() }, { shipped_at: new Date() }],
|
||||
})
|
||||
).toEqual("shipped")
|
||||
|
||||
expect(
|
||||
getLastFulfillmentStatus({
|
||||
fulfillments: [
|
||||
{ shipped_at: new Date() },
|
||||
{ delivered_at: new Date() },
|
||||
],
|
||||
})
|
||||
).toEqual("partially_delivered")
|
||||
|
||||
expect(
|
||||
getLastFulfillmentStatus({
|
||||
fulfillments: [
|
||||
{ delivered_at: new Date() },
|
||||
{ delivered_at: new Date() },
|
||||
],
|
||||
})
|
||||
).toEqual("delivered")
|
||||
|
||||
expect(
|
||||
getLastFulfillmentStatus({
|
||||
fulfillments: [
|
||||
{ delivered_at: new Date() },
|
||||
{ canceled_at: new Date() },
|
||||
],
|
||||
})
|
||||
).toEqual("delivered")
|
||||
|
||||
expect(
|
||||
getLastFulfillmentStatus({
|
||||
fulfillments: [{ shipped_at: new Date() }, { canceled_at: new Date() }],
|
||||
})
|
||||
).toEqual("shipped")
|
||||
|
||||
expect(
|
||||
getLastFulfillmentStatus({
|
||||
fulfillments: [
|
||||
{ packed_at: new Date() },
|
||||
{ shipped_at: new Date() },
|
||||
{ canceled_at: new Date() },
|
||||
],
|
||||
})
|
||||
).toEqual("partially_shipped")
|
||||
|
||||
expect(
|
||||
getLastFulfillmentStatus({
|
||||
fulfillments: [
|
||||
{ canceled_at: new Date() },
|
||||
{ canceled_at: new Date() },
|
||||
],
|
||||
})
|
||||
).toEqual("canceled")
|
||||
})
|
||||
})
|
||||
170
packages/core/core-flows/src/order/utils/aggregate-status.ts
Normal file
170
packages/core/core-flows/src/order/utils/aggregate-status.ts
Normal file
@@ -0,0 +1,170 @@
|
||||
import { OrderDetailDTO } from "@medusajs/types"
|
||||
import { MathBN } from "@medusajs/utils"
|
||||
|
||||
export const getLastPaymentStatus = (order: OrderDetailDTO) => {
|
||||
const PaymentStatus = {
|
||||
NOT_PAID: "not_paid",
|
||||
AWAITING: "awaiting",
|
||||
CAPTURED: "captured",
|
||||
PARTIALLY_CAPTURED: "partially_captured",
|
||||
PARTIALLY_REFUNDED: "partially_refunded",
|
||||
REFUNDED: "refunded",
|
||||
CANCELED: "canceled",
|
||||
REQUIRES_ACTION: "requires_action",
|
||||
AUTHORIZED: "authorized",
|
||||
PARTIALLY_AUTHORIZED: "partially_authorized",
|
||||
}
|
||||
|
||||
let paymentStatus = {}
|
||||
for (const status in PaymentStatus) {
|
||||
paymentStatus[PaymentStatus[status]] = 0
|
||||
}
|
||||
|
||||
for (const paymentCollection of order.payment_collections) {
|
||||
if (MathBN.gt(paymentCollection.captured_amount ?? 0, 0)) {
|
||||
paymentStatus[PaymentStatus.CAPTURED] += MathBN.eq(
|
||||
paymentCollection.captured_amount as number,
|
||||
paymentCollection.amount
|
||||
)
|
||||
? 1
|
||||
: 0.5
|
||||
}
|
||||
|
||||
if (MathBN.gt(paymentCollection.refunded_amount ?? 0, 0)) {
|
||||
paymentStatus[PaymentStatus.REFUNDED] += MathBN.eq(
|
||||
paymentCollection.refunded_amount as number,
|
||||
paymentCollection.amount
|
||||
)
|
||||
? 1
|
||||
: 0.5
|
||||
}
|
||||
|
||||
paymentStatus[paymentCollection.status] += 1
|
||||
}
|
||||
|
||||
const totalPayments = order.payment_collections.length
|
||||
const totalPaymentExceptCanceled =
|
||||
totalPayments - paymentStatus[PaymentStatus.CANCELED]
|
||||
|
||||
if (paymentStatus[PaymentStatus.REQUIRES_ACTION] > 0) {
|
||||
return PaymentStatus.REQUIRES_ACTION
|
||||
}
|
||||
|
||||
if (paymentStatus[PaymentStatus.REFUNDED] > 0) {
|
||||
if (paymentStatus[PaymentStatus.REFUNDED] === totalPaymentExceptCanceled) {
|
||||
return PaymentStatus.REFUNDED
|
||||
}
|
||||
|
||||
return PaymentStatus.PARTIALLY_REFUNDED
|
||||
}
|
||||
|
||||
if (paymentStatus[PaymentStatus.CAPTURED] > 0) {
|
||||
if (paymentStatus[PaymentStatus.CAPTURED] === totalPaymentExceptCanceled) {
|
||||
return PaymentStatus.CAPTURED
|
||||
}
|
||||
|
||||
return PaymentStatus.PARTIALLY_CAPTURED
|
||||
}
|
||||
|
||||
if (paymentStatus[PaymentStatus.AUTHORIZED] > 0) {
|
||||
if (
|
||||
paymentStatus[PaymentStatus.AUTHORIZED] === totalPaymentExceptCanceled
|
||||
) {
|
||||
return PaymentStatus.AUTHORIZED
|
||||
}
|
||||
|
||||
return PaymentStatus.PARTIALLY_AUTHORIZED
|
||||
}
|
||||
|
||||
if (
|
||||
paymentStatus[PaymentStatus.CANCELED] > 0 &&
|
||||
paymentStatus[PaymentStatus.CANCELED] === totalPayments
|
||||
) {
|
||||
return PaymentStatus.CANCELED
|
||||
}
|
||||
|
||||
if (paymentStatus[PaymentStatus.AWAITING] > 0) {
|
||||
return PaymentStatus.AWAITING
|
||||
}
|
||||
|
||||
return PaymentStatus.NOT_PAID
|
||||
}
|
||||
|
||||
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 = {}
|
||||
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,
|
||||
}
|
||||
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]
|
||||
|
||||
if (fulfillmentStatus[FulfillmentStatus.DELIVERED] > 0) {
|
||||
if (
|
||||
fulfillmentStatus[FulfillmentStatus.DELIVERED] ===
|
||||
totalFulfillmentsExceptCanceled
|
||||
) {
|
||||
return FulfillmentStatus.DELIVERED
|
||||
}
|
||||
|
||||
return FulfillmentStatus.PARTIALLY_DELIVERED
|
||||
}
|
||||
|
||||
if (fulfillmentStatus[FulfillmentStatus.SHIPPED] > 0) {
|
||||
if (
|
||||
fulfillmentStatus[FulfillmentStatus.SHIPPED] ===
|
||||
totalFulfillmentsExceptCanceled
|
||||
) {
|
||||
return FulfillmentStatus.SHIPPED
|
||||
}
|
||||
|
||||
return FulfillmentStatus.PARTIALLY_SHIPPED
|
||||
}
|
||||
|
||||
if (fulfillmentStatus[FulfillmentStatus.FULFILLED] > 0) {
|
||||
if (
|
||||
fulfillmentStatus[FulfillmentStatus.FULFILLED] ===
|
||||
totalFulfillmentsExceptCanceled
|
||||
) {
|
||||
return FulfillmentStatus.FULFILLED
|
||||
}
|
||||
|
||||
return FulfillmentStatus.PARTIALLY_FULFILLED
|
||||
}
|
||||
|
||||
if (
|
||||
fulfillmentStatus[FulfillmentStatus.CANCELED] > 0 &&
|
||||
fulfillmentStatus[FulfillmentStatus.CANCELED] === totalFulfillments
|
||||
) {
|
||||
return FulfillmentStatus.CANCELED
|
||||
}
|
||||
|
||||
return FulfillmentStatus.NOT_FULFILLED
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
import { OrderDTO, OrderDetailDTO } from "@medusajs/types"
|
||||
import { deduplicate } from "@medusajs/utils"
|
||||
import {
|
||||
WorkflowData,
|
||||
createWorkflow,
|
||||
transform,
|
||||
} from "@medusajs/workflows-sdk"
|
||||
import { useRemoteQueryStep } from "../../common"
|
||||
import {
|
||||
getLastFulfillmentStatus,
|
||||
getLastPaymentStatus,
|
||||
} from "../utils/aggregate-status"
|
||||
|
||||
export const getOrderDetailWorkflowId = "get-order-detail"
|
||||
export const getOrderDetailWorkflow = createWorkflow(
|
||||
getOrderDetailWorkflowId,
|
||||
(
|
||||
input: WorkflowData<{ fields: string[]; order_id: string }>
|
||||
): WorkflowData<OrderDetailDTO> => {
|
||||
const fields = transform(input, ({ fields }) => {
|
||||
return deduplicate([
|
||||
...fields,
|
||||
"id",
|
||||
"status",
|
||||
"version",
|
||||
"payment_collections.*",
|
||||
"fulfillments.*",
|
||||
])
|
||||
})
|
||||
|
||||
const order: OrderDTO = useRemoteQueryStep({
|
||||
entry_point: "orders",
|
||||
fields,
|
||||
variables: { id: input.order_id },
|
||||
list: false,
|
||||
throw_if_key_not_found: true,
|
||||
})
|
||||
|
||||
const aggregatedOrder = transform({ order }, ({ order }) => {
|
||||
const order_ = order as OrderDetailDTO
|
||||
|
||||
order_.payment_status = getLastPaymentStatus(
|
||||
order_
|
||||
) as OrderDetailDTO["payment_status"]
|
||||
order_.fulfillment_status = getLastFulfillmentStatus(
|
||||
order_
|
||||
) as OrderDetailDTO["fulfillment_status"]
|
||||
return order_
|
||||
})
|
||||
|
||||
return aggregatedOrder
|
||||
}
|
||||
)
|
||||
@@ -4,4 +4,5 @@ export * from "./create-fulfillment"
|
||||
export * from "./create-orders"
|
||||
export * from "./create-return"
|
||||
export * from "./create-shipment"
|
||||
export * from "./get-order-detail"
|
||||
export * from "./update-tax-lines"
|
||||
|
||||
@@ -221,6 +221,43 @@ export interface BaseOrderTransaction {
|
||||
updated_at: Date | string
|
||||
}
|
||||
|
||||
export interface BaseOrderFulfillment {
|
||||
id: string
|
||||
location_id: string
|
||||
packed_at: Date | null
|
||||
shipped_at: Date | null
|
||||
delivered_at: Date | null
|
||||
canceled_at: Date | null
|
||||
data: Record<string, unknown> | null
|
||||
provider_id: string
|
||||
shipping_option_id: string | null
|
||||
metadata: Record<string, unknown> | null
|
||||
created_at: Date
|
||||
updated_at: Date
|
||||
}
|
||||
|
||||
type PaymentStatus =
|
||||
| "not_paid"
|
||||
| "awaiting"
|
||||
| "authorized"
|
||||
| "partially_authorized"
|
||||
| "captured"
|
||||
| "partially_captured"
|
||||
| "partially_refunded"
|
||||
| "refunded"
|
||||
| "canceled"
|
||||
| "requires_action"
|
||||
|
||||
type FulfillmentStatus =
|
||||
| "not_fulfilled"
|
||||
| "partially_fulfilled"
|
||||
| "fulfilled"
|
||||
| "partially_shipped"
|
||||
| "shipped"
|
||||
| "partially_delivered"
|
||||
| "delivered"
|
||||
| "canceled"
|
||||
|
||||
export interface BaseOrder {
|
||||
id: string
|
||||
version: number
|
||||
@@ -234,7 +271,10 @@ export interface BaseOrder {
|
||||
billing_address?: BaseOrderAddress
|
||||
items: BaseOrderLineItem[] | null
|
||||
shipping_methods: BaseOrderShippingMethod[] | null
|
||||
payment_collection?: BasePaymentCollection
|
||||
payment_collections?: BasePaymentCollection[]
|
||||
payment_status: PaymentStatus
|
||||
fulfillments?: BaseOrderFulfillment[]
|
||||
fulfillment_status: FulfillmentStatus
|
||||
transactions?: BaseOrderTransaction[]
|
||||
summary: BaseOrderSummary
|
||||
metadata: Record<string, unknown> | null
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { BaseFilterable } from "../dal"
|
||||
import { OperatorMap } from "../dal/utils"
|
||||
import { FulfillmentDTO } from "../fulfillment"
|
||||
import { PaymentCollectionDTO } from "../payment"
|
||||
import { BigNumberRawValue, BigNumberValue } from "../totals"
|
||||
|
||||
export type ChangeActionType =
|
||||
@@ -1102,6 +1104,35 @@ export interface OrderDTO {
|
||||
raw_original_shipping_tax_total: BigNumberRawValue
|
||||
}
|
||||
|
||||
type PaymentStatus =
|
||||
| "not_paid"
|
||||
| "awaiting"
|
||||
| "authorized"
|
||||
| "partially_authorized"
|
||||
| "captured"
|
||||
| "partially_captured"
|
||||
| "partially_refunded"
|
||||
| "refunded"
|
||||
| "canceled"
|
||||
| "requires_action"
|
||||
|
||||
type FulfillmentStatus =
|
||||
| "not_fulfilled"
|
||||
| "partially_fulfilled"
|
||||
| "fulfilled"
|
||||
| "partially_shipped"
|
||||
| "shipped"
|
||||
| "partially_delivered"
|
||||
| "delivered"
|
||||
| "canceled"
|
||||
|
||||
export interface OrderDetailDTO extends OrderDTO {
|
||||
payment_collections: PaymentCollectionDTO[]
|
||||
payment_status: PaymentStatus
|
||||
fulfillments: FulfillmentDTO[]
|
||||
fulfillment_status: FulfillmentStatus
|
||||
}
|
||||
|
||||
export interface OrderChangeDTO {
|
||||
/**
|
||||
* The ID of the order change
|
||||
|
||||
@@ -100,6 +100,11 @@ export interface PaymentCollectionDTO {
|
||||
*/
|
||||
refunded_amount?: BigNumberValue
|
||||
|
||||
/**
|
||||
* The amount captured within the associated payments.
|
||||
*/
|
||||
captured_amount?: BigNumberValue
|
||||
|
||||
/**
|
||||
* When the payment collection was completed.
|
||||
*/
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { getOrderDetailWorkflow } from "@medusajs/core-flows"
|
||||
import {
|
||||
ContainerRegistrationKeys,
|
||||
remoteQueryObjectFromString,
|
||||
@@ -11,18 +12,15 @@ export const GET = async (
|
||||
req: AuthenticatedMedusaRequest,
|
||||
res: MedusaResponse
|
||||
) => {
|
||||
const remoteQuery = req.scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
|
||||
|
||||
const variables = { id: req.params.id }
|
||||
|
||||
const queryObject = remoteQueryObjectFromString({
|
||||
entryPoint: "order",
|
||||
variables,
|
||||
fields: req.remoteQueryConfig.fields,
|
||||
const worklow = getOrderDetailWorkflow(req.scope)
|
||||
const { result } = await worklow.run({
|
||||
input: {
|
||||
fields: req.remoteQueryConfig.fields,
|
||||
order_id: req.params.id,
|
||||
},
|
||||
})
|
||||
|
||||
const [order] = await remoteQuery(queryObject)
|
||||
res.status(200).json({ order })
|
||||
res.status(200).json({ order: result })
|
||||
}
|
||||
|
||||
export const POST = async (
|
||||
|
||||
Reference in New Issue
Block a user