chore(core-flows): util to format inventory input (#8483)

This commit is contained in:
Carlos R. L. Rodrigues
2024-08-07 15:15:17 -03:00
committed by GitHub
parent d50161fa32
commit 0b6bcdd538
6 changed files with 127 additions and 118 deletions

View File

@@ -1,5 +1,8 @@
import { BigNumberInput } from "@medusajs/types"
import { MedusaError } from "@medusajs/utils"
import {
BigNumberInput,
ConfirmVariantInventoryWorkflowInputDTO,
} from "@medusajs/types"
import { MedusaError, deepFlatMap } from "@medusajs/utils"
interface ConfirmInventoryPreparationInput {
product_variant_inventory_items: {
@@ -29,7 +32,93 @@ interface ConfirmInventoryItem {
location_ids: string[]
}
export const prepareConfirmInventoryInput = ({
export const prepareConfirmInventoryInput = (data: {
input: ConfirmVariantInventoryWorkflowInputDTO
}) => {
const productVariantInventoryItems = new Map<string, any>()
const stockLocationIds = new Set<string>()
const allVariants = new Map<string, any>()
let hasSalesChannelStockLocation = false
let hasManagedInventory = false
const salesChannelId = data.input.sales_channel_id
for (const updateItem of data.input.itemsToUpdate ?? []) {
const item = data.input.items.find(
(item) => item.variant_id === updateItem.data.variant_id
)
if (item && updateItem.data.quantity) {
item.quantity = updateItem.data.quantity!
}
}
deepFlatMap(
data.input,
"variants.inventory_items.inventory.location_levels.stock_locations.sales_channels",
({ variants, inventory_items, stock_locations, sales_channels }) => {
if (!variants) {
return
}
if (
!hasSalesChannelStockLocation &&
sales_channels?.id === salesChannelId
) {
hasSalesChannelStockLocation = true
}
if (stock_locations) {
stockLocationIds.add(stock_locations.id)
}
if (inventory_items) {
const inventoryItemId = inventory_items.inventory_item_id
if (!productVariantInventoryItems.has(inventoryItemId)) {
productVariantInventoryItems.set(inventoryItemId, {
variant_id: inventory_items.variant_id,
inventory_item_id: inventoryItemId,
required_quantity: inventory_items.required_quantity,
})
}
}
if (!allVariants.has(variants.id)) {
if (!hasManagedInventory && variants.manage_inventory) {
hasManagedInventory = true
}
allVariants.set(variants.id, {
id: variants.id,
manage_inventory: variants.manage_inventory,
})
}
}
)
if (!hasManagedInventory) {
return { items: [] }
}
if (salesChannelId && !hasSalesChannelStockLocation) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`Sales channel ${salesChannelId} is not associated with any stock location.`
)
}
const items = formatInventoryInput({
product_variant_inventory_items: Array.from(
productVariantInventoryItems.values()
),
location_ids: Array.from(stockLocationIds),
items: data.input.items,
variants: Array.from(allVariants.values()),
})
return { items }
}
const formatInventoryInput = ({
product_variant_inventory_items,
location_ids,
items,

View File

@@ -17,12 +17,12 @@ import { authorizePaymentSessionStep } from "../../../payment/steps/authorize-pa
import { validateCartPaymentsStep } from "../steps"
import { reserveInventoryStep } from "../steps/reserve-inventory"
import { completeCartFields } from "../utils/fields"
import { prepareConfirmInventoryInput } from "../utils/prepare-confirm-inventory-input"
import {
prepareAdjustmentsData,
prepareLineItemData,
prepareTaxLinesData,
} from "../utils/prepare-line-item-data"
import { confirmVariantInventoryWorkflow } from "./confirm-variant-inventory"
export const completeCartWorkflowId = "complete-cart"
export const completeCartWorkflow = createWorkflow(
@@ -66,14 +66,16 @@ export const completeCartWorkflow = createWorkflow(
}
)
const formatedInventoryItems = confirmVariantInventoryWorkflow.runAsStep({
input: {
skipInventoryCheck: true,
sales_channel_id,
variants,
items,
const formatedInventoryItems = transform(
{
input: {
sales_channel_id,
variants,
items,
},
},
})
prepareConfirmInventoryInput
)
const [, finalCart] = parallelize(
reserveInventoryStep(formatedInventoryItems),

View File

@@ -1,11 +1,9 @@
import { ConfirmVariantInventoryWorkflowInputDTO } from "@medusajs/types"
import { MedusaError, deepFlatMap } from "@medusajs/utils"
import {
WorkflowData,
WorkflowResponse,
createWorkflow,
transform,
when,
} from "@medusajs/workflows-sdk"
import { confirmInventoryStep } from "../steps"
import { prepareConfirmInventoryInput } from "../utils/prepare-confirm-inventory-input"
@@ -27,95 +25,12 @@ export const confirmVariantInventoryWorkflow = createWorkflow(
(
input: WorkflowData<ConfirmVariantInventoryWorkflowInputDTO>
): WorkflowResponse<Output> => {
const confirmInventoryInput = transform({ input }, (data) => {
const productVariantInventoryItems = new Map<string, any>()
const stockLocationIds = new Set<string>()
const allVariants = new Map<string, any>()
let hasSalesChannelStockLocation = false
let hasManagedInventory = false
const confirmInventoryInput = transform(
{ input },
prepareConfirmInventoryInput
)
const salesChannelId = data.input.sales_channel_id
for (const updateItem of data.input.itemsToUpdate ?? []) {
const item = data.input.items.find(
(item) => item.variant_id === updateItem.data.variant_id
)
if (item && updateItem.data.quantity) {
item.quantity = updateItem.data.quantity!
}
}
deepFlatMap(
data.input,
"variants.inventory_items.inventory.location_levels.stock_locations.sales_channels",
({ variants, inventory_items, stock_locations, sales_channels }) => {
if (!variants) {
return
}
if (
!hasSalesChannelStockLocation &&
sales_channels?.id === salesChannelId
) {
hasSalesChannelStockLocation = true
}
if (stock_locations) {
stockLocationIds.add(stock_locations.id)
}
if (inventory_items) {
const inventoryItemId = inventory_items.inventory_item_id
if (!productVariantInventoryItems.has(inventoryItemId)) {
productVariantInventoryItems.set(inventoryItemId, {
variant_id: inventory_items.variant_id,
inventory_item_id: inventoryItemId,
required_quantity: inventory_items.required_quantity,
})
}
}
if (!allVariants.has(variants.id)) {
if (!hasManagedInventory && variants.manage_inventory) {
hasManagedInventory = true
}
allVariants.set(variants.id, {
id: variants.id,
manage_inventory: variants.manage_inventory,
})
}
}
)
if (!hasManagedInventory) {
return { items: [] }
}
if (salesChannelId && !hasSalesChannelStockLocation) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`Sales channel ${salesChannelId} is not associated with any stock location.`
)
}
const items = prepareConfirmInventoryInput({
product_variant_inventory_items: Array.from(
productVariantInventoryItems.values()
),
location_ids: Array.from(stockLocationIds),
items: data.input.items,
variants: Array.from(allVariants.values()),
})
return { items }
})
when({ input }, ({ input }) => {
return !input.skipInventoryCheck
}).then(() => {
confirmInventoryStep(confirmInventoryInput)
})
confirmInventoryStep(confirmInventoryInput)
return new WorkflowResponse(confirmInventoryInput)
}

View File

@@ -21,7 +21,7 @@ import {
} from "@medusajs/workflows-sdk"
import { createRemoteLinkStep, useRemoteQueryStep } from "../../../common"
import { reserveInventoryStep } from "../../../definition/cart/steps/reserve-inventory"
import { confirmVariantInventoryWorkflow } from "../../../definition/cart/workflows/confirm-variant-inventory"
import { prepareConfirmInventoryInput } from "../../../definition/cart/utils/prepare-confirm-inventory-input"
import { createReturnFulfillmentWorkflow } from "../../../fulfillment/workflows/create-return-fulfillment"
import { previewOrderChangeStep, updateReturnsStep } from "../../steps"
import { createOrderClaimItemsFromActionsStep } from "../../steps/claim/create-claim-items-from-actions"
@@ -310,14 +310,16 @@ export const confirmClaimRequestWorkflow = createWorkflow(
}
})
const formatedInventoryItems = confirmVariantInventoryWorkflow.runAsStep({
input: {
skipInventoryCheck: true,
sales_channel_id: (claim as any).order.sales_channel_id,
variants,
items,
const formatedInventoryItems = transform(
{
input: {
sales_channel_id: (claim as any).order.sales_channel_id,
variants,
items,
},
},
})
prepareConfirmInventoryInput
)
reserveInventoryStep(formatedInventoryItems)
})

View File

@@ -16,7 +16,7 @@ import {
} from "@medusajs/workflows-sdk"
import { createRemoteLinkStep, useRemoteQueryStep } from "../../../common"
import { reserveInventoryStep } from "../../../definition/cart/steps/reserve-inventory"
import { confirmVariantInventoryWorkflow } from "../../../definition/cart/workflows/confirm-variant-inventory"
import { prepareConfirmInventoryInput } from "../../../definition/cart/utils/prepare-confirm-inventory-input"
import { createReturnFulfillmentWorkflow } from "../../../fulfillment/workflows/create-return-fulfillment"
import { previewOrderChangeStep } from "../../steps"
import { confirmOrderChanges } from "../../steps/confirm-order-changes"
@@ -297,14 +297,16 @@ export const confirmExchangeRequestWorkflow = createWorkflow(
}
})
const formatedInventoryItems = confirmVariantInventoryWorkflow.runAsStep({
input: {
skipInventoryCheck: true,
sales_channel_id: (exchange as any).order.sales_channel_id,
variants,
items,
const formatedInventoryItems = transform(
{
input: {
sales_channel_id: (exchange as any).order.sales_channel_id,
variants,
items,
},
},
})
prepareConfirmInventoryInput
)
reserveInventoryStep(formatedInventoryItems)
})

View File

@@ -122,7 +122,6 @@ export interface CompleteCartWorkflowInputDTO {
}
export interface ConfirmVariantInventoryWorkflowInputDTO {
skipInventoryCheck?: boolean
sales_channel_id: string
variants: {
id: string