diff --git a/.changeset/twelve-queens-hug.md b/.changeset/twelve-queens-hug.md
new file mode 100644
index 0000000000..8b607f2fda
--- /dev/null
+++ b/.changeset/twelve-queens-hug.md
@@ -0,0 +1,6 @@
+---
+"@medusajs/admin-ui": patch
+"@medusajs/medusa": patch
+---
+
+fix(medusa, admin-ui): refine create-fulfillment flow
diff --git a/packages/admin-ui/ui/src/components/organisms/product-variants-section/edit-variant-inventory-modal.tsx b/packages/admin-ui/ui/src/components/organisms/product-variants-section/edit-variant-inventory-modal.tsx
index bbdd4250f0..20b6f7c2a9 100644
--- a/packages/admin-ui/ui/src/components/organisms/product-variants-section/edit-variant-inventory-modal.tsx
+++ b/packages/admin-ui/ui/src/components/organisms/product-variants-section/edit-variant-inventory-modal.tsx
@@ -76,7 +76,7 @@ const EditVariantInventoryModal = ({ onClose, product, variant }: Props) => {
deleteLocations.map(async (location: InventoryLevelDTO) => {
await client.admin.inventoryItems.deleteLocationLevel(
inventoryItemId!,
- location.id
+ location.location_id
)
})
)
diff --git a/packages/admin-ui/ui/src/domain/orders/details/allocations/allocate-items-modal.tsx b/packages/admin-ui/ui/src/domain/orders/details/allocations/allocate-items-modal.tsx
index 8e38397ced..77006e603e 100644
--- a/packages/admin-ui/ui/src/domain/orders/details/allocations/allocate-items-modal.tsx
+++ b/packages/admin-ui/ui/src/domain/orders/details/allocations/allocate-items-modal.tsx
@@ -287,8 +287,8 @@ export const AllocationLineItem: React.FC<{
}
)}
>
-
{availableQuantity || "N/A"} available
- ({inStockQuantity || "N/A"} in stock)
+ {availableQuantity || 0} available
+ ({inStockQuantity || 0} in stock)
= ({
value?: string
label?: string
}>({})
+
const [metadata, setMetadata] = useState([
{ key: "", value: "" },
])
diff --git a/packages/admin-ui/ui/src/domain/orders/details/create-fulfillment/item-table.tsx b/packages/admin-ui/ui/src/domain/orders/details/create-fulfillment/item-table.tsx
index b18e7fc987..8ca0eebb08 100644
--- a/packages/admin-ui/ui/src/domain/orders/details/create-fulfillment/item-table.tsx
+++ b/packages/admin-ui/ui/src/domain/orders/details/create-fulfillment/item-table.tsx
@@ -4,6 +4,7 @@ import FeatureToggle from "../../../../components/fundamentals/feature-toggle"
import ImagePlaceholder from "../../../../components/fundamentals/image-placeholder"
import InputField from "../../../../components/molecules/input"
import { LineItem } from "@medusajs/medusa"
+import clsx from "clsx"
import { useAdminVariantsInventory } from "medusa-react"
import { useFeatureFlag } from "../../../../providers/feature-flag-provider"
@@ -24,16 +25,20 @@ const CreateFulfillmentItemsTable = ({
locationId: string
setErrors: (errors: React.SetStateAction<{}>) => void
}) => {
- const handleQuantityUpdate = (value: number, id: string) => {
- let newQuantities = { ...quantities }
+ const handleQuantityUpdate = React.useCallback(
+ (value: number, id: string) => {
+ let newQuantities = { ...quantities }
- newQuantities = {
- ...newQuantities,
- [id]: value,
- }
+ newQuantities = {
+ ...newQuantities,
+ [id]: value,
+ }
+
+ setQuantities(newQuantities)
+ },
+ [quantities, setQuantities]
+ )
- setQuantities(newQuantities)
- }
return (
{items.map((item, idx) => {
@@ -118,12 +123,31 @@ const FulfillmentLine = ({
})
}, [validQuantity, setErrors, item.id])
+ React.useEffect(() => {
+ if (!availableQuantity) {
+ handleQuantityUpdate(0, item.id)
+ } else {
+ handleQuantityUpdate(
+ Math.min(getFulfillableQuantity(item), availableQuantity),
+ item.id
+ )
+ }
+ // Note: we can't add handleQuantityUpdate to the dependency array as it will cause an infinite loop
+ }, [availableQuantity, item, item.id])
+
if (getFulfillableQuantity(item) <= 0) {
return null
}
return (
-
+
{item.thumbnail ? (
@@ -148,8 +172,8 @@ const FulfillmentLine = ({
-
{availableQuantity || "N/A"} available
-
({inStockQuantity || "N/A"} in stock)
+
{availableQuantity || 0} available
+
({inStockQuantity || 0} in stock)
}
value={quantities[item.id]}
- max={getFulfillableQuantity(item)}
+ max={Math.min(availableQuantity || 0, getFulfillableQuantity(item))}
onChange={(e) =>
handleQuantityUpdate(e.target.valueAsNumber, item.id)
}
diff --git a/packages/medusa/src/api/routes/admin/orders/create-fulfillment.ts b/packages/medusa/src/api/routes/admin/orders/create-fulfillment.ts
index 27d2063244..8351e7b926 100644
--- a/packages/medusa/src/api/routes/admin/orders/create-fulfillment.ts
+++ b/packages/medusa/src/api/routes/admin/orders/create-fulfillment.ts
@@ -168,7 +168,11 @@ export const updateInventoryAndReservations = async (
items.map(({ item, quantity }) => ({ ...item, quantity } as LineItem)),
locationId
)
+ })
+ )
+ await Promise.all(
+ fulfillments.map(async ({ items }) => {
await Promise.all(
items.map(async ({ item, quantity }) => {
if (!item.variant_id) {
diff --git a/packages/medusa/src/services/product-variant-inventory.ts b/packages/medusa/src/services/product-variant-inventory.ts
index 06f565e51f..b18f736b95 100644
--- a/packages/medusa/src/services/product-variant-inventory.ts
+++ b/packages/medusa/src/services/product-variant-inventory.ts
@@ -514,12 +514,19 @@ class ProductVariantInventoryService extends TransactionBaseService {
for (const item of itemsToValidate) {
const pvInventoryItems = await this.listByVariant(item.variant_id!)
- const [inventoryLevels] =
+ const [inventoryLevels, inventoryLevelCount] =
await this.inventoryService_.listInventoryLevels({
inventory_item_id: pvInventoryItems.map((i) => i.inventory_item_id),
location_id: locationId,
})
+ if (!inventoryLevelCount) {
+ throw new MedusaError(
+ MedusaError.Types.NOT_ALLOWED,
+ `Inventory item for ${item.title} not found at location`
+ )
+ }
+
const pviMap: Map = new Map(
pvInventoryItems.map((pvi) => [pvi.inventory_item_id, pvi])
)