diff --git a/packages/admin-next/dashboard/src/hooks/api/fulfillment.tsx b/packages/admin-next/dashboard/src/hooks/api/fulfillment.tsx index d3e7821ad8..f5dd586c1f 100644 --- a/packages/admin-next/dashboard/src/hooks/api/fulfillment.tsx +++ b/packages/admin-next/dashboard/src/hooks/api/fulfillment.tsx @@ -43,10 +43,10 @@ export const useCancelFulfillment = ( }) } -export const useCreateShipment = ( +export const useCreateFulfillmentShipment = ( fulfillmentId: string, options?: UseMutationOptions< - { order: HttpTypes.AdminOrder }, + { fulfillment: HttpTypes.AdminFulfillment }, Error, HttpTypes.AdminCreateFulfillmentShipment > diff --git a/packages/admin-next/dashboard/src/hooks/api/orders.tsx b/packages/admin-next/dashboard/src/hooks/api/orders.tsx index a8a1e54fbc..e6fa7bc863 100644 --- a/packages/admin-next/dashboard/src/hooks/api/orders.tsx +++ b/packages/admin-next/dashboard/src/hooks/api/orders.tsx @@ -9,6 +9,7 @@ import { import { queryClient } from "../../lib/query-client" import { queryKeysFactory } from "../../lib/query-key-factory" import { sdk } from "../../lib/client" +import { AdminCreateOrderShipment, HttpTypes } from "@medusajs/types" const ORDERS_QUERY_KEY = "orders" as const export const ordersQueryKeys = queryKeysFactory(ORDERS_QUERY_KEY) @@ -81,6 +82,28 @@ export const useCancelOrderFulfillment = ( }) } +export const useCreateOrderShipment = ( + orderId: string, + fulfillmentId: string, + options?: UseMutationOptions< + { order: HttpTypes.AdminOrder }, + Error, + HttpTypes.AdminCreateOrderShipment + > +) => { + return useMutation({ + mutationFn: (payload: HttpTypes.AdminCreateOrderShipment) => + sdk.admin.order.createShipment(orderId, fulfillmentId, payload), + onSuccess: (data: any, variables: any, context: any) => { + queryClient.invalidateQueries({ + queryKey: ordersQueryKeys.details(), + }) + options?.onSuccess?.(data, variables, context) + }, + ...options, + }) +} + export const useCancelOrder = ( orderId: string, options?: UseMutationOptions diff --git a/packages/admin-next/dashboard/src/routes/orders/order-create-shipment/components/order-create-shipment-form/constants.ts b/packages/admin-next/dashboard/src/routes/orders/order-create-shipment/components/order-create-shipment-form/constants.ts index 45df05e20c..107d2b0f3e 100644 --- a/packages/admin-next/dashboard/src/routes/orders/order-create-shipment/components/order-create-shipment-form/constants.ts +++ b/packages/admin-next/dashboard/src/routes/orders/order-create-shipment/components/order-create-shipment-form/constants.ts @@ -1,15 +1,13 @@ import { z } from "zod" export const CreateShipmentSchema = z.object({ - labels: z - .array( - z.object({ - tracking_number: z.string(), - // TODO: this 2 are not optional in the API - tracking_url: z.string().optional(), - label_url: z.string().optional(), - }) - ) - .min(1), + labels: z.array( + z.object({ + tracking_number: z.string(), + // TODO: this 2 are not optional in the API + tracking_url: z.string().optional(), + label_url: z.string().optional(), + }) + ), send_notification: z.boolean().optional(), }) diff --git a/packages/admin-next/dashboard/src/routes/orders/order-create-shipment/components/order-create-shipment-form/order-create-shipment-form.tsx b/packages/admin-next/dashboard/src/routes/orders/order-create-shipment/components/order-create-shipment-form/order-create-shipment-form.tsx index 55fc5500a1..0e8e26b83a 100644 --- a/packages/admin-next/dashboard/src/routes/orders/order-create-shipment/components/order-create-shipment-form/order-create-shipment-form.tsx +++ b/packages/admin-next/dashboard/src/routes/orders/order-create-shipment/components/order-create-shipment-form/order-create-shipment-form.tsx @@ -11,8 +11,8 @@ import { RouteFocusModal, useRouteModal, } from "../../../../../components/modals" -import { useCreateShipment } from "../../../../../hooks/api/fulfillment.tsx" import { CreateShipmentSchema } from "./constants" +import { useCreateOrderShipment } from "../../../../../hooks/api" type OrderCreateFulfillmentFormProps = { order: AdminOrder @@ -27,12 +27,11 @@ export function OrderCreateShipmentForm({ const { handleSuccess } = useRouteModal() const { mutateAsync: createShipment, isPending: isMutating } = - useCreateShipment(fulfillment.id) + useCreateOrderShipment(order.id, fulfillment.id) const form = useForm>({ defaultValues: { - labels: [{ tracking_number: "" }], - send_notification: !order.no_notification, // TODO: not supported in the API + send_notification: !order.no_notification, }, resolver: zodResolver(CreateShipmentSchema), }) @@ -45,6 +44,10 @@ export function OrderCreateShipmentForm({ const handleSubmit = form.handleSubmit(async (data) => { await createShipment( { + items: fulfillment.items.map((i) => ({ + id: i.line_item_id, + quantity: i.quantity, + })), labels: data.labels .filter((l) => !!l.tracking_number) .map((l) => ({ @@ -52,7 +55,7 @@ export function OrderCreateShipmentForm({ tracking_url: "#", label_url: "#", })), - // no_notification: !data.send_notification, + no_notification: !data.send_notification, }, { onSuccess: () => { diff --git a/packages/admin-next/dashboard/src/routes/orders/order-create-shipment/order-create-shipment.tsx b/packages/admin-next/dashboard/src/routes/orders/order-create-shipment/order-create-shipment.tsx index bf48fe68f7..16efba729a 100644 --- a/packages/admin-next/dashboard/src/routes/orders/order-create-shipment/order-create-shipment.tsx +++ b/packages/admin-next/dashboard/src/routes/orders/order-create-shipment/order-create-shipment.tsx @@ -8,7 +8,7 @@ export function OrderCreateShipment() { const { id, f_id } = useParams() const { order, isLoading, isError, error } = useOrder(id!, { - fields: "*fulfillments", + fields: "*fulfillments,*fulfillments.items", }) if (isError) { diff --git a/packages/core/js-sdk/src/admin/order.ts b/packages/core/js-sdk/src/admin/order.ts index 6a3ff70ce3..55a253c384 100644 --- a/packages/core/js-sdk/src/admin/order.ts +++ b/packages/core/js-sdk/src/admin/order.ts @@ -1,4 +1,5 @@ import { + AdminCreateOrderShipment, FindParams, HttpTypes, PaginatedResponse, @@ -77,4 +78,22 @@ export class Order { } ) } + + async createShipment( + id: string, + fulfillmentId: string, + body: HttpTypes.AdminCreateOrderShipment, + query?: SelectParams, + headers?: ClientHeaders + ) { + return await this.client.fetch<{ order: HttpTypes.AdminOrder }>( + `/admin/orders/${id}/fulfillments/${fulfillmentId}/shipments`, + { + method: "POST", + headers, + body, + query, + } + ) + } } diff --git a/packages/core/types/src/http/order/admin.ts b/packages/core/types/src/http/order/admin.ts index 6fe2aa89df..a7fd6ccfbe 100644 --- a/packages/core/types/src/http/order/admin.ts +++ b/packages/core/types/src/http/order/admin.ts @@ -19,6 +19,17 @@ export interface AdminCreateOrderFulfillment { metadata?: Record } +export interface AdminCreateOrderShipment { + items: { id: string; quantity: number }[] + labels?: { + tracking_number: string + tracking_url: string + label_url: string + }[] + no_notification?: boolean + metadata?: Record +} + export interface AdminCancelOrderFulfillment { no_notification?: boolean } diff --git a/packages/medusa/src/api/admin/orders/[id]/fulfillments/[fulfillment_id]/shipment/route.ts b/packages/medusa/src/api/admin/orders/[id]/fulfillments/[fulfillment_id]/shipments/route.ts similarity index 100% rename from packages/medusa/src/api/admin/orders/[id]/fulfillments/[fulfillment_id]/shipment/route.ts rename to packages/medusa/src/api/admin/orders/[id]/fulfillments/[fulfillment_id]/shipments/route.ts diff --git a/packages/medusa/src/api/admin/orders/middlewares.ts b/packages/medusa/src/api/admin/orders/middlewares.ts index daebd688e0..c5c357478f 100644 --- a/packages/medusa/src/api/admin/orders/middlewares.ts +++ b/packages/medusa/src/api/admin/orders/middlewares.ts @@ -9,6 +9,7 @@ import { AdminGetOrdersParams, AdminOrderCancelFulfillment, AdminOrderCreateFulfillment, + AdminOrderCreateShipment, } from "./validators" export const adminOrderRoutesMiddlewares: MiddlewareRoute[] = [ @@ -88,4 +89,15 @@ export const adminOrderRoutesMiddlewares: MiddlewareRoute[] = [ ), ], }, + { + method: ["POST"], + matcher: "/admin/orders/:id/fulfillments/:fulfillment_id/shipments", + middlewares: [ + validateAndTransformBody(AdminOrderCreateShipment), + validateAndTransformQuery( + AdminGetOrdersOrderParams, + QueryConfig.retrieveTransformQueryConfig + ), + ], + }, ] diff --git a/packages/medusa/src/api/admin/returns/middlewares.ts b/packages/medusa/src/api/admin/returns/middlewares.ts index a02a74a28a..77f269af9c 100644 --- a/packages/medusa/src/api/admin/returns/middlewares.ts +++ b/packages/medusa/src/api/admin/returns/middlewares.ts @@ -8,7 +8,7 @@ import { AdminPostReturnsReqSchema, } from "./validators" -export const adminOrderRoutesMiddlewares: MiddlewareRoute[] = [ +export const adminReturnRoutesMiddlewares: MiddlewareRoute[] = [ { method: ["GET"], matcher: "/admin/returns", diff --git a/packages/medusa/src/api/middlewares.ts b/packages/medusa/src/api/middlewares.ts index c4aef9349c..9c9aa2312f 100644 --- a/packages/medusa/src/api/middlewares.ts +++ b/packages/medusa/src/api/middlewares.ts @@ -47,6 +47,7 @@ import { storeProductRoutesMiddlewares } from "./store/products/middlewares" import { storeRegionRoutesMiddlewares } from "./store/regions/middlewares" import { storeReturnReasonRoutesMiddlewares } from "./store/return-reasons/middlewares" import { storeShippingOptionRoutesMiddlewares } from "./store/shipping-options/middlewares" +import { adminReturnRoutesMiddlewares } from "./admin/returns/middlewares" export const config: MiddlewaresConfig = { routes: [ @@ -67,6 +68,7 @@ export const config: MiddlewaresConfig = { ...adminWorkflowsExecutionsMiddlewares, ...storeRegionRoutesMiddlewares, ...adminRegionRoutesMiddlewares, + ...adminReturnRoutesMiddlewares, ...adminUserRoutesMiddlewares, ...adminInviteRoutesMiddlewares, ...adminTaxRateRoutesMiddlewares,