Skip to content

Commit

Permalink
Feat/show order as allocated (#3497)
Browse files Browse the repository at this point in the history
**What**
- Add check to see if any items is unfulfilled when validating reservations for allocation indicator
- Add reservations refresh to onSuccess when creating a fulfillment to automatically update indicators on fulfillment



Fixes CORE-1248

Co-authored-by: Sebastian Rindom <[email protected]>
  • Loading branch information
pKorsholm and srindom authored Mar 16, 2023
1 parent e6e5291 commit 2e12f13
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 58 deletions.
5 changes: 5 additions & 0 deletions .changeset/large-bottles-perform.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@medusajs/admin-ui": patch
---

fix(admin-ui): fix(admin-ui): ensure that the allocation indicator is correctly displayed
Original file line number Diff line number Diff line change
Expand Up @@ -26,26 +26,19 @@ const EditAllocationDrawer = ({
close,
reservation,
item,
sales_channel_id,
totalReservedQuantity,
}: {
close: () => void
reservation?: ReservationItemDTO
item: LineItem
totalReservedQuantity: number
sales_channel_id?: string
}) => {
const form = useForm<EditAllocationLineItemForm>()

const { control, setValue, handleSubmit } = form

// if not sales channel is present fetch all locations
const stockLocationsFilter: { sales_channel_id?: string } = {}
if (sales_channel_id) {
stockLocationsFilter.sales_channel_id = sales_channel_id
}

const { stock_locations } = useAdminStockLocations(stockLocationsFilter)
const { stock_locations, isLoading: isLoadingStockLocations } =
useAdminStockLocations()

const { variant, isLoading } = useAdminVariantsInventory(
item.variant_id as string
Expand All @@ -59,14 +52,14 @@ const EditAllocationDrawer = ({
)

const locationOptions = useMemo(() => {
if (!stock_locations) {
if (!stock_locations || isLoadingStockLocations) {
return []
}
return stock_locations.map((sl) => ({
value: sl.id,
label: sl.name,
}))
}, [stock_locations])
}, [isLoadingStockLocations, stock_locations])

const notification = useNotification()
const handleDelete = () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,14 @@ type CreateFulfillmentModalProps = {
email?: string
orderToFulfill: Order | ClaimOrder | Swap
orderId: string
onComplete?: () => void
}

const CreateFulfillmentModal: React.FC<CreateFulfillmentModalProps> = ({
handleCancel,
orderToFulfill,
orderId,
onComplete,
}) => {
const { isFeatureEnabled } = useFeatureFlag()
const isLocationFulfillmentEnabled =
Expand Down Expand Up @@ -187,6 +189,7 @@ const CreateFulfillmentModal: React.FC<CreateFulfillmentModalProps> = ({
onSuccess: () => {
notification("Success", successText, "success")
handleCancel()
onComplete && onComplete()
},
onError: (err) => notification("Error", getErrorMessage(err), "error"),
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,15 @@ import { OrderEditContext } from "../../edit/context"
import OrderLine from "../order-line"
import StatusIndicator from "../../../../components/fundamentals/status-indicator"
import { sum } from "lodash"
import { useAdminReservations } from "medusa-react"
import { useFeatureFlag } from "../../../../providers/feature-flag-provider"
import useToggleState from "../../../../hooks/use-toggle-state"

type SummaryCardProps = {
order: Order
reservations: ReservationItemDTO[]
}

const SummaryCard: React.FC<SummaryCardProps> = ({
order,
}: {
order: Order
}) => {
const SummaryCard: React.FC<SummaryCardProps> = ({ order, reservations }) => {
const {
state: allocationModalIsOpen,
open: showAllocationModal,
Expand All @@ -34,23 +30,8 @@ const SummaryCard: React.FC<SummaryCardProps> = ({
const { isFeatureEnabled } = useFeatureFlag()
const inventoryEnabled = isFeatureEnabled("inventoryService")

const { reservations, isLoading, refetch } = useAdminReservations(
{
line_item_id: order.items.map((item) => item.id),
},
{
enabled: inventoryEnabled,
}
)

React.useEffect(() => {
if (inventoryEnabled) {
refetch()
}
}, [inventoryEnabled, refetch])

const reservationItemsMap = useMemo(() => {
if (!reservations?.length || !inventoryEnabled || isLoading) {
if (!reservations?.length || !inventoryEnabled) {
return {}
}

Expand All @@ -66,15 +47,17 @@ const SummaryCard: React.FC<SummaryCardProps> = ({
},
{}
)
}, [reservations, inventoryEnabled, isLoading])
}, [reservations, inventoryEnabled])

const allItemsReserved = useMemo(() => {
return order.items.every((item) => {
const reservations = reservationItemsMap[item.id]
if (!reservations) {
return false
}
return sum(reservations.map((r) => r.quantity)) === item.quantity

return (
item.quantity === item.fulfilled_quantity ||
(reservations &&
sum(reservations.map((r) => r.quantity)) === item.quantity)
)
})
}, [reservationItemsMap, order])

Expand Down
24 changes: 22 additions & 2 deletions packages/admin-ui/ui/src/domain/orders/details/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
useAdminCapturePayment,
useAdminOrder,
useAdminRegion,
useAdminReservations,
useAdminUpdateOrder,
} from "medusa-react"
import { useNavigate, useParams } from "react-router-dom"
Expand Down Expand Up @@ -55,8 +56,9 @@ import useClipboard from "../../../hooks/use-clipboard"
import { useHotkeys } from "react-hotkeys-hook"
import useImperativeDialog from "../../../hooks/use-imperative-dialog"
import useNotification from "../../../hooks/use-notification"
import { useState } from "react"
import { useEffect, useState } from "react"
import useToggleState from "../../../hooks/use-toggle-state"
import { useFeatureFlag } from "../../../providers/feature-flag-provider"

type OrderDetailFulfillment = {
title: string
Expand Down Expand Up @@ -145,6 +147,23 @@ const OrderDetails = () => {
const { region } = useAdminRegion(order?.region_id!, {
enabled: !!order?.region_id,
})
const { isFeatureEnabled } = useFeatureFlag()
const inventoryEnabled = isFeatureEnabled("inventoryService")

const { reservations, refetch: refetchReservations } = useAdminReservations(
{
line_item_id: order?.items.map((item) => item.id),
},
{
enabled: inventoryEnabled,
}
)

useEffect(() => {
if (inventoryEnabled) {
refetchReservations()
}
}, [inventoryEnabled, refetchReservations])

const navigate = useNavigate()
const notification = useNotification()
Expand Down Expand Up @@ -316,7 +335,7 @@ const OrderDetails = () => {
</div>
</BodyCard>

<SummaryCard order={order} />
<SummaryCard order={order} reservations={reservations || []} />

<BodyCard
className={"mb-4 h-auto min-h-0 w-full"}
Expand Down Expand Up @@ -513,6 +532,7 @@ const OrderDetails = () => {
orderToFulfill={order as any}
handleCancel={() => setShowFulfillment(false)}
orderId={order.id}
onComplete={refetchReservations}
/>
)}
{showRefund && (
Expand Down
45 changes: 27 additions & 18 deletions packages/admin-ui/ui/src/domain/orders/details/order-line/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,30 +94,39 @@ const ReservationIndicator = ({
const locationMap = new Map(stock_locations?.map((l) => [l.id, l.name]) || [])

const reservationsSum = sum(reservations?.map((r) => r.quantity) || [])
const awaitingAllocation = lineItem.quantity - reservationsSum

const allocatableSum = lineItem.quantity - (lineItem?.fulfilled_quantity || 0)

const awaitingAllocation = allocatableSum - reservationsSum

return (
<div className={awaitingAllocation ? "text-rose-50" : "text-grey-40"}>
<Tooltip
content={
<div className="inter-small-regular flex flex-col items-center px-1 pt-1 pb-2">
<div className="gap-y-base grid grid-cols-1 divide-y">
{!!awaitingAllocation && (
<span className="flex w-full items-center">
{awaitingAllocation} items await allocation
</span>
)}
{reservations?.map((reservation) => (
<EditAllocationButton
key={reservation.id}
locationName={locationMap.get(reservation.location_id)}
totalReservedQuantity={reservationsSum}
reservation={reservation}
lineItem={lineItem}
onClick={() => setReservation(reservation)}
/>
))}
</div>
{reservationsSum || awaitingAllocation ? (
<div className="gap-y-base grid grid-cols-1 divide-y">
{!!awaitingAllocation && (
<span className="flex w-full items-center">
{awaitingAllocation} items await allocation
</span>
)}
{reservations?.map((reservation) => (
<EditAllocationButton
key={reservation.id}
locationName={locationMap.get(reservation.location_id)}
totalReservedQuantity={reservationsSum}
reservation={reservation}
lineItem={lineItem}
onClick={() => setReservation(reservation)}
/>
))}
</div>
) : (
<span className="flex w-full items-center">
This item has been fulfilled.
</span>
)}
</div>
}
side="bottom"
Expand Down

0 comments on commit 2e12f13

Please sign in to comment.