Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(dashboard): order fulfillment UI #7262

Merged
merged 25 commits into from
May 20, 2024
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
8207cf4
feat: initial impl. of Unfulfilled section and create flow
fPolic May 7, 2024
46c3d91
feat: create fulfillment
fPolic May 7, 2024
1feef74
feat: order <> fulfillment link, fulfillment section
fPolic May 7, 2024
b177083
feat: accept order_id when creating fulfillment
fPolic May 7, 2024
d3ff095
feat: finish create and cancel
fPolic May 7, 2024
a681a77
Merge branch 'develop' into feat/order-fulfillment-ui
fPolic May 7, 2024
9cd0306
Merge branch 'develop' into feat/order-fulfillment-ui
fPolic May 8, 2024
563688b
fix: integration test
fPolic May 8, 2024
c5a5c52
refactor: real Order<>Fulfillment link instead readonly, add link ste…
fPolic May 9, 2024
aab869a
fix: revert `order_id` definitions
fPolic May 9, 2024
dc8214b
chore: add changeset
fPolic May 9, 2024
4e0eec2
fix: build
fPolic May 9, 2024
0050678
Merge branch 'develop' into feat/order-fulfillment-ui
fPolic May 13, 2024
cd420c0
fix: address comments
fPolic May 14, 2024
a362341
Merge branch 'develop' into feat/order-fulfillment-ui
fPolic May 15, 2024
0ceb144
fix: fetch inventory and location levels for fulfilled variant
fPolic May 15, 2024
4179f14
fix: loading inventory details
fPolic May 15, 2024
6dbf987
add isList to order fulfillment link
olivermrbl May 19, 2024
0c2b1af
fix: resolve conflicts
olivermrbl May 19, 2024
6a5e4c5
Merge branch 'develop' into feat/order-fulfillment-ui
fPolic May 20, 2024
be2ab12
fix: duplicate declaration
fPolic May 20, 2024
a8ee64a
fix: type
fPolic May 20, 2024
6544d99
refactor: link orders step, fix client
fPolic May 20, 2024
c8561b1
fix: move translations to the new file
fPolic May 20, 2024
78924e0
fix: pass order id in test
fPolic May 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .changeset/long-islands-press.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"@medusajs/link-modules": patch
"@medusajs/core-flows": patch
"@medusajs/types": patch
"@medusajs/utils": patch
"@medusajs/medusa": patch
---

feat: add Order<>Fulfillment link
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export function generateCreateFulfillmentData(
},
],
order: data.order ?? {},
order_id: data.order_id,
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ medusaIntegrationTestRunner({
const data = generateCreateFulfillmentData({
provider_id: providerId,
shipping_option_id: shippingOption.id,
order_id: "order_123",
})

const response = await api
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -528,8 +528,20 @@
"unfulfilledItems": "Unfulfilled Items",
"statusLabel": "Fulfillment status",
"statusTitle": "Fulfillment Status",
"awaitingFullfillmentBadge": "Awaiting fulfillment",
"fulfillItems": "Fulfill items",
"awaitingFulfillmentBadge": "Awaiting fulfillment",
"number": "Fulfillment #{{number}}",
"itemsToFulfill": "Items to fulfill",
"create": "Create Fulfillment",
"available": "Available",
"inStock": "In stock",
"itemsToFulfillDesc": "Choose items and quantities to fulfill",
"locationDescription": "Choose which location you want to fulfill items from.",
"error": {
"wrongQuantity": "Only one item is available for fulfillment",
"wrongQuantity_other": "Quantity should be a number between 1 and {{number}}",
"noItems": "No items to fulfill."
},
"status": {
"notFulfilled": "Not fulfilled",
"partiallyFulfilled": "Partially fulfilled",
Expand All @@ -542,6 +554,7 @@
"requiresAction": "Requires action"
},
"toast": {
"created": "Fulfillment created successfully",
"canceled": "Fulfillment successfully canceled",
"fulfillmentShipped": "Cannot cancel an already shipped fulfillment"
},
Expand Down
43 changes: 43 additions & 0 deletions packages/admin-next/dashboard/src/hooks/api/fulfillment.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { useMutation, UseMutationOptions } from "@tanstack/react-query"

import { queryKeysFactory } from "../../lib/query-key-factory"

import { client } from "../../lib/client"
import { queryClient } from "../../lib/medusa"
import { ordersQueryKeys } from "./orders"

const FULFILLMENTS_QUERY_KEY = "fulfillments" as const
export const fulfillmentsQueryKeys = queryKeysFactory(FULFILLMENTS_QUERY_KEY)

export const useCreateFulfillment = (
options?: UseMutationOptions<any, Error, any>
) => {
return useMutation({
mutationFn: (payload: any) => client.fulfillments.create(payload),
onSuccess: (data: any, variables: any, context: any) => {
queryClient.invalidateQueries({ queryKey: fulfillmentsQueryKeys.lists() })
queryClient.invalidateQueries({
queryKey: ordersQueryKeys.details(),
})
options?.onSuccess?.(data, variables, context)
},
...options,
})
}

export const useCancelFulfillment = (
id: string,
options?: UseMutationOptions<any, Error, any>
) => {
return useMutation({
mutationFn: () => client.fulfillments.cancel(id),
onSuccess: (data: any, variables: any, context: any) => {
queryClient.invalidateQueries({ queryKey: fulfillmentsQueryKeys.lists() })
queryClient.invalidateQueries({
queryKey: ordersQueryKeys.details(),
})
options?.onSuccess?.(data, variables, context)
},
...options,
})
}
2 changes: 2 additions & 0 deletions packages/admin-next/dashboard/src/lib/client/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { productTypes } from "./product-types"
import { products } from "./products"
import { promotions } from "./promotions"
import { regions } from "./regions"
import { fulfillments } from "./fulfillments"
import { fulfillmentProviders } from "./fulfillment-providers"
import { reservations } from "./reservations"
import { salesChannels } from "./sales-channels"
Expand Down Expand Up @@ -50,6 +51,7 @@ export const client = {
invites: invites,
inventoryItems: inventoryItems,
reservations: reservations,
fulfillments: fulfillments,
fulfillmentProviders: fulfillmentProviders,
products: products,
productTypes: productTypes,
Expand Down
17 changes: 17 additions & 0 deletions packages/admin-next/dashboard/src/lib/client/fulfillments.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { CreateFulfillmentDTO } from "@medusajs/types"

import { FulfillmentRes } from "../../types/api-responses"
import { postRequest } from "./common"

async function createFulfillment(payload: CreateFulfillmentDTO) {
return postRequest<FulfillmentRes>(`/admin/fulfillments`, payload)
}

async function cancelFulfillment(id: string) {
return postRequest<FulfillmentRes>(`/admin/fulfillments/${id}/cancel`)
}

export const fulfillments = {
create: createFulfillment,
cancel: cancelFulfillment,
}
16 changes: 16 additions & 0 deletions packages/admin-next/dashboard/src/lib/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,19 @@ export function pick(obj: Record<string, any>, keys: string[]) {

return ret
}

/**
* Remove properties that are `null` or `undefined` from the object.
* @param obj
*/
export function cleanNonValues(obj: Record<string, any>) {
const ret: Record<string, any> = {}

for (const key in obj) {
if (obj[key] !== null && typeof obj[key] !== "undefined") {
ret[key] = obj[key]
}
}

return ret
}
5 changes: 5 additions & 0 deletions packages/admin-next/dashboard/src/lib/order-item.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { OrderLineItemDTO } from "@medusajs/types"

export const getFulfillableQuantity = (item: OrderLineItemDTO) => {
return item.quantity - item.detail.fulfilled_quantity
}
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,13 @@ export const RouteMap: RouteObject[] = [
{
path: ":id",
lazy: () => import("../../v2-routes/orders/order-detail"),
children: [
{
path: "fulfillment",
lazy: () =>
import("../../v2-routes/orders/order-create-fulfillment"),
},
],
},
],
},
Expand Down
6 changes: 6 additions & 0 deletions packages/admin-next/dashboard/src/types/api-responses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
CampaignDTO,
CurrencyDTO,
CustomerGroupDTO,
FulfillmentDTO,
FulfillmentProviderDTO,
InventoryNext,
InviteDTO,
Expand Down Expand Up @@ -73,6 +74,11 @@ export type RegionRes = { region: RegionDTO }
export type RegionListRes = { regions: RegionDTO[] } & ListRes
export type RegionDeleteRes = DeleteRes

// Fulfillments
export type FulfillmentRes = { fulfillment: FulfillmentDTO }
export type FulfillmentListRes = { fulfillments: FulfillmentDTO[] } & ListRes
export type FulfillmentDeleteRes = DeleteRes

// Reservations
export type ReservationRes = { reservation: InventoryNext.ReservationItemDTO }
export type ReservationListRes = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { z } from "zod"

export const CreateFulfillmentSchema = z.object({
quantity: z.record(z.string(), z.number()),

location_id: z.string(),
send_notification: z.boolean().optional(),
})
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./order-create-fulfillment-form"
Loading
Loading