feat(medusa): complete cart create reservation (#7250)
This commit is contained in:
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
"@medusajs/core-flows": patch
|
||||||
|
"@medusajs/types": patch
|
||||||
|
"@medusajs/utils": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Create stock reservation on complete cart flow
|
||||||
@@ -709,10 +709,9 @@ medusaIntegrationTestRunner({
|
|||||||
|
|
||||||
expect(errors).toEqual([
|
expect(errors).toEqual([
|
||||||
{
|
{
|
||||||
action: "confirm-item-inventory-as-step",
|
action: "validate-variant-prices",
|
||||||
handlerType: "invoke",
|
handlerType: "invoke",
|
||||||
error: expect.objectContaining({
|
error: expect.objectContaining({
|
||||||
// TODO: FIX runAsStep nested errors
|
|
||||||
message: expect.stringContaining(
|
message: expect.stringContaining(
|
||||||
`Variants with IDs ${product.variants[0].id} do not have a price`
|
`Variants with IDs ${product.variants[0].id} do not have a price`
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1480,6 +1480,8 @@ medusaIntegrationTestRunner({
|
|||||||
let shippingProfile
|
let shippingProfile
|
||||||
let fulfillmentSet
|
let fulfillmentSet
|
||||||
let shippingOption
|
let shippingOption
|
||||||
|
let stockLocation
|
||||||
|
let inventoryItem
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await setupTaxStructure(taxModule)
|
await setupTaxStructure(taxModule)
|
||||||
@@ -1510,7 +1512,6 @@ medusaIntegrationTestRunner({
|
|||||||
variants: [
|
variants: [
|
||||||
{
|
{
|
||||||
title: "Test variant",
|
title: "Test variant",
|
||||||
inventory_quantity: 10,
|
|
||||||
prices: [
|
prices: [
|
||||||
{
|
{
|
||||||
currency_code: "usd",
|
currency_code: "usd",
|
||||||
@@ -1528,7 +1529,7 @@ medusaIntegrationTestRunner({
|
|||||||
)
|
)
|
||||||
).data.product
|
).data.product
|
||||||
|
|
||||||
const stockLocation = (
|
stockLocation = (
|
||||||
await api.post(
|
await api.post(
|
||||||
`/admin/stock-locations`,
|
`/admin/stock-locations`,
|
||||||
{ name: "test location" },
|
{ name: "test location" },
|
||||||
@@ -1536,6 +1537,25 @@ medusaIntegrationTestRunner({
|
|||||||
)
|
)
|
||||||
).data.stock_location
|
).data.stock_location
|
||||||
|
|
||||||
|
inventoryItem = (
|
||||||
|
await api.post(
|
||||||
|
`/admin/inventory-items`,
|
||||||
|
{
|
||||||
|
sku: "12345",
|
||||||
|
},
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
).data.inventory_item
|
||||||
|
|
||||||
|
await api.post(
|
||||||
|
`/admin/inventory-items/${inventoryItem.id}/location-levels`,
|
||||||
|
{
|
||||||
|
location_id: stockLocation.id,
|
||||||
|
stocked_quantity: 10,
|
||||||
|
},
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
|
||||||
await api.post(
|
await api.post(
|
||||||
`/admin/stock-locations/${stockLocation.id}/sales-channels`,
|
`/admin/stock-locations/${stockLocation.id}/sales-channels`,
|
||||||
{ add: [salesChannel.id] },
|
{ add: [salesChannel.id] },
|
||||||
@@ -1563,6 +1583,14 @@ medusaIntegrationTestRunner({
|
|||||||
[Modules.STOCK_LOCATION]: { stock_location_id: stockLocation.id },
|
[Modules.STOCK_LOCATION]: { stock_location_id: stockLocation.id },
|
||||||
[Modules.FULFILLMENT]: { fulfillment_set_id: fulfillmentSet.id },
|
[Modules.FULFILLMENT]: { fulfillment_set_id: fulfillmentSet.id },
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
[Modules.PRODUCT]: {
|
||||||
|
variant_id: product.variants[0].id,
|
||||||
|
},
|
||||||
|
[Modules.INVENTORY]: {
|
||||||
|
inventory_item_id: inventoryItem.id,
|
||||||
|
},
|
||||||
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
shippingOption = (
|
shippingOption = (
|
||||||
@@ -1590,7 +1618,7 @@ medusaIntegrationTestRunner({
|
|||||||
).data.shipping_option
|
).data.shipping_option
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should create an order", async () => {
|
it("should create an order and create item reservations", async () => {
|
||||||
const cartResponse = await api.post(`/store/carts`, {
|
const cartResponse = await api.post(`/store/carts`, {
|
||||||
currency_code: "usd",
|
currency_code: "usd",
|
||||||
email: "tony@stark-industries.com",
|
email: "tony@stark-industries.com",
|
||||||
@@ -1602,8 +1630,7 @@ medusaIntegrationTestRunner({
|
|||||||
province: "ny",
|
province: "ny",
|
||||||
postal_code: "94016",
|
postal_code: "94016",
|
||||||
},
|
},
|
||||||
// TODO: inventory isn't being managed on a product level
|
sales_channel_id: salesChannel.id,
|
||||||
// sales_channel_id: salesChannel.id,
|
|
||||||
items: [{ quantity: 1, variant_id: product.variants[0].id }],
|
items: [{ quantity: 1, variant_id: product.variants[0].id }],
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -1661,6 +1688,19 @@ medusaIntegrationTestRunner({
|
|||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const reservation = await api.get(`/admin/reservations`, adminHeaders)
|
||||||
|
const reservationItem = reservation.data.reservations[0]
|
||||||
|
|
||||||
|
expect(reservationItem).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
id: expect.stringContaining("resitem_"),
|
||||||
|
location_id: stockLocation.id,
|
||||||
|
inventory_item_id: inventoryItem.id,
|
||||||
|
quantity: cartResponse.data.cart.items[0].quantity,
|
||||||
|
line_item_id: cartResponse.data.cart.items[0].id,
|
||||||
|
})
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||||
import { IInventoryService } from "@medusajs/types"
|
import { IInventoryServiceNext } from "@medusajs/types"
|
||||||
import { promiseAll } from "@medusajs/utils"
|
import { promiseAll } from "@medusajs/utils"
|
||||||
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
||||||
import { MedusaError } from "medusa-core-utils"
|
import { MedusaError } from "medusa-core-utils"
|
||||||
@@ -18,7 +18,7 @@ export const confirmInventoryStepId = "confirm-inventory-step"
|
|||||||
export const confirmInventoryStep = createStep(
|
export const confirmInventoryStep = createStep(
|
||||||
confirmInventoryStepId,
|
confirmInventoryStepId,
|
||||||
async (data: StepInput, { container }) => {
|
async (data: StepInput, { container }) => {
|
||||||
const inventoryService = container.resolve<IInventoryService>(
|
const inventoryService = container.resolve<IInventoryServiceNext>(
|
||||||
ModuleRegistrationName.INVENTORY
|
ModuleRegistrationName.INVENTORY
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -22,4 +22,4 @@ export * from "./set-tax-lines-for-items"
|
|||||||
export * from "./update-cart-promotions"
|
export * from "./update-cart-promotions"
|
||||||
export * from "./update-carts"
|
export * from "./update-carts"
|
||||||
export * from "./validate-cart-shipping-options"
|
export * from "./validate-cart-shipping-options"
|
||||||
export * from "./validate-variants-existence"
|
export * from "./validate-variant-prices"
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||||
|
import { IInventoryServiceNext } from "@medusajs/types"
|
||||||
|
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
||||||
|
|
||||||
|
interface StepInput {
|
||||||
|
items: {
|
||||||
|
id?: string
|
||||||
|
inventory_item_id: string
|
||||||
|
required_quantity: number
|
||||||
|
allow_backorder: boolean
|
||||||
|
quantity: number
|
||||||
|
location_ids: string[]
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const reserveInventoryStepId = "reserve-inventory-step"
|
||||||
|
export const reserveInventoryStep = createStep(
|
||||||
|
reserveInventoryStepId,
|
||||||
|
async (data: StepInput, { container }) => {
|
||||||
|
const inventoryService = container.resolve<IInventoryServiceNext>(
|
||||||
|
ModuleRegistrationName.INVENTORY
|
||||||
|
)
|
||||||
|
|
||||||
|
const items = data.items.map((item) => ({
|
||||||
|
line_item_id: item.id,
|
||||||
|
inventory_item_id: item.inventory_item_id,
|
||||||
|
quantity: item.required_quantity * item.quantity,
|
||||||
|
allow_backorder: item.allow_backorder,
|
||||||
|
location_id: item.location_ids[0],
|
||||||
|
}))
|
||||||
|
|
||||||
|
const reservations = await inventoryService.createReservationItems(items)
|
||||||
|
|
||||||
|
return new StepResponse(void 0, {
|
||||||
|
reservations: reservations.map((r) => r.id),
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async (data, { container }) => {
|
||||||
|
if (!data) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const inventoryService = container.resolve<IInventoryServiceNext>(
|
||||||
|
ModuleRegistrationName.INVENTORY
|
||||||
|
)
|
||||||
|
|
||||||
|
await inventoryService.deleteReservationItems(data.reservations)
|
||||||
|
|
||||||
|
return new StepResponse()
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { BigNumberInput } from "@medusajs/types"
|
||||||
|
import { MedusaError, isDefined } from "@medusajs/utils"
|
||||||
|
import { createStep } from "@medusajs/workflows-sdk"
|
||||||
|
|
||||||
|
interface StepInput {
|
||||||
|
variants: {
|
||||||
|
id: string
|
||||||
|
calculated_price?: BigNumberInput
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const validateVariantPricesStepId = "validate-variant-prices"
|
||||||
|
export const validateVariantPricesStep = createStep(
|
||||||
|
validateVariantPricesStepId,
|
||||||
|
async (data: StepInput, { container }) => {
|
||||||
|
const priceNotFound: string[] = []
|
||||||
|
|
||||||
|
for (const variant of data.variants) {
|
||||||
|
if (!isDefined(variant.calculated_price)) {
|
||||||
|
priceNotFound.push(variant.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priceNotFound.length > 0) {
|
||||||
|
throw new MedusaError(
|
||||||
|
MedusaError.Types.INVALID_DATA,
|
||||||
|
`Variants with IDs ${priceNotFound.join(", ")} do not have a price`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
|
||||||
import { IProductModuleService } from "@medusajs/types"
|
|
||||||
import { MedusaError } from "@medusajs/utils"
|
|
||||||
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
|
||||||
|
|
||||||
interface StepInput {
|
|
||||||
variantIds: string[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export const validateVariantsExistStepId = "validate-variants-exist"
|
|
||||||
export const validateVariantsExistStep = createStep(
|
|
||||||
validateVariantsExistStepId,
|
|
||||||
async (data: StepInput, { container }) => {
|
|
||||||
const productModuleService = container.resolve<IProductModuleService>(
|
|
||||||
ModuleRegistrationName.PRODUCT
|
|
||||||
)
|
|
||||||
|
|
||||||
const variants = await productModuleService.listVariants(
|
|
||||||
{ id: data.variantIds },
|
|
||||||
{ select: ["id"] }
|
|
||||||
)
|
|
||||||
|
|
||||||
const variantIdToData = new Set(variants.map((v) => v.id))
|
|
||||||
|
|
||||||
const notFoundVariants = new Set(
|
|
||||||
[...data.variantIds].filter((x) => !variantIdToData.has(x))
|
|
||||||
)
|
|
||||||
|
|
||||||
if (notFoundVariants.size) {
|
|
||||||
throw new MedusaError(
|
|
||||||
MedusaError.Types.INVALID_DATA,
|
|
||||||
`Variants with IDs ${[...notFoundVariants].join(", ")} do not exist`
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return new StepResponse(Array.from(variants.map((v) => v.id)))
|
|
||||||
}
|
|
||||||
)
|
|
||||||
@@ -8,6 +8,7 @@ interface ConfirmInventoryPreparationInput {
|
|||||||
required_quantity: number
|
required_quantity: number
|
||||||
}[]
|
}[]
|
||||||
items: {
|
items: {
|
||||||
|
id?: string
|
||||||
variant_id?: string
|
variant_id?: string
|
||||||
quantity: BigNumberInput
|
quantity: BigNumberInput
|
||||||
}[]
|
}[]
|
||||||
@@ -20,6 +21,7 @@ interface ConfirmInventoryPreparationInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface ConfirmInventoryItem {
|
interface ConfirmInventoryItem {
|
||||||
|
id?: string
|
||||||
inventory_item_id: string
|
inventory_item_id: string
|
||||||
required_quantity: number
|
required_quantity: number
|
||||||
allow_backorder: boolean
|
allow_backorder: boolean
|
||||||
@@ -63,6 +65,7 @@ export const prepareConfirmInventoryInput = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
itemsToConfirm.push({
|
itemsToConfirm.push({
|
||||||
|
id: item.id,
|
||||||
inventory_item_id: variantInventoryItem.inventory_item_id,
|
inventory_item_id: variantInventoryItem.inventory_item_id,
|
||||||
required_quantity: variantInventoryItem.required_quantity,
|
required_quantity: variantInventoryItem.required_quantity,
|
||||||
allow_backorder: !!variant.allow_backorder,
|
allow_backorder: !!variant.allow_backorder,
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { useRemoteQueryStep } from "../../../common/steps/use-remote-query"
|
|||||||
import { addToCartStep, refreshCartShippingMethodsStep } from "../steps"
|
import { addToCartStep, refreshCartShippingMethodsStep } from "../steps"
|
||||||
import { refreshCartPromotionsStep } from "../steps/refresh-cart-promotions"
|
import { refreshCartPromotionsStep } from "../steps/refresh-cart-promotions"
|
||||||
import { updateTaxLinesStep } from "../steps/update-tax-lines"
|
import { updateTaxLinesStep } from "../steps/update-tax-lines"
|
||||||
|
import { validateVariantPricesStep } from "../steps/validate-variant-prices"
|
||||||
import {
|
import {
|
||||||
cartFieldsForRefreshSteps,
|
cartFieldsForRefreshSteps,
|
||||||
productVariantsFields,
|
productVariantsFields,
|
||||||
@@ -51,6 +52,8 @@ export const addToCartWorkflow = createWorkflow(
|
|||||||
throw_if_key_not_found: true,
|
throw_if_key_not_found: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
validateVariantPricesStep({ variants })
|
||||||
|
|
||||||
confirmVariantInventoryWorkflow.runAsStep({
|
confirmVariantInventoryWorkflow.runAsStep({
|
||||||
input: {
|
input: {
|
||||||
sales_channel_id: input.cart.sales_channel_id as string,
|
sales_channel_id: input.cart.sales_channel_id as string,
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
} from "@medusajs/workflows-sdk"
|
} from "@medusajs/workflows-sdk"
|
||||||
import { useRemoteQueryStep } from "../../../common"
|
import { useRemoteQueryStep } from "../../../common"
|
||||||
import { createOrderFromCartStep } from "../steps"
|
import { createOrderFromCartStep } from "../steps"
|
||||||
|
import { reserveInventoryStep } from "../steps/reserve-inventory"
|
||||||
import { updateTaxLinesStep } from "../steps/update-tax-lines"
|
import { updateTaxLinesStep } from "../steps/update-tax-lines"
|
||||||
import { completeCartFields } from "../utils/fields"
|
import { completeCartFields } from "../utils/fields"
|
||||||
import { confirmVariantInventoryWorkflow } from "./confirm-variant-inventory"
|
import { confirmVariantInventoryWorkflow } from "./confirm-variant-inventory"
|
||||||
@@ -40,6 +41,7 @@ export const completeCartWorkflow = createWorkflow(
|
|||||||
data.cart.items.forEach((item) => {
|
data.cart.items.forEach((item) => {
|
||||||
allItems.push({
|
allItems.push({
|
||||||
id: item.id,
|
id: item.id,
|
||||||
|
variant_id: item.variant_id,
|
||||||
quantity: item.quantity,
|
quantity: item.quantity,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -54,9 +56,8 @@ export const completeCartWorkflow = createWorkflow(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
confirmVariantInventoryWorkflow.runAsStep({
|
const formatedInventoryItems = confirmVariantInventoryWorkflow.runAsStep({
|
||||||
input: {
|
input: {
|
||||||
ignore_price_check: true,
|
|
||||||
sales_channel_id,
|
sales_channel_id,
|
||||||
variants,
|
variants,
|
||||||
items,
|
items,
|
||||||
@@ -65,6 +66,8 @@ export const completeCartWorkflow = createWorkflow(
|
|||||||
|
|
||||||
updateTaxLinesStep({ cart_or_cart_id: cart, force_tax_calculation: true })
|
updateTaxLinesStep({ cart_or_cart_id: cart, force_tax_calculation: true })
|
||||||
|
|
||||||
|
reserveInventoryStep(formatedInventoryItems)
|
||||||
|
|
||||||
const finalCart = useRemoteQueryStep({
|
const finalCart = useRemoteQueryStep({
|
||||||
entry_point: "cart",
|
entry_point: "cart",
|
||||||
fields: completeCartFields,
|
fields: completeCartFields,
|
||||||
|
|||||||
+32
-21
@@ -1,5 +1,5 @@
|
|||||||
import { ConfirmVariantInventoryWorkflowInputDTO } from "@medusajs/types"
|
import { ConfirmVariantInventoryWorkflowInputDTO } from "@medusajs/types"
|
||||||
import { MedusaError, deepFlatMap, isDefined } from "@medusajs/utils"
|
import { MedusaError, deepFlatMap } from "@medusajs/utils"
|
||||||
import {
|
import {
|
||||||
WorkflowData,
|
WorkflowData,
|
||||||
createWorkflow,
|
createWorkflow,
|
||||||
@@ -8,13 +8,25 @@ import {
|
|||||||
import { confirmInventoryStep } from "../steps"
|
import { confirmInventoryStep } from "../steps"
|
||||||
import { prepareConfirmInventoryInput } from "../utils/prepare-confirm-inventory-input"
|
import { prepareConfirmInventoryInput } from "../utils/prepare-confirm-inventory-input"
|
||||||
|
|
||||||
|
interface Output {
|
||||||
|
items: {
|
||||||
|
id?: string
|
||||||
|
inventory_item_id: string
|
||||||
|
required_quantity: number
|
||||||
|
allow_backorder: boolean
|
||||||
|
quantity: number
|
||||||
|
location_ids: string[]
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
export const confirmVariantInventoryWorkflowId = "confirm-item-inventory"
|
export const confirmVariantInventoryWorkflowId = "confirm-item-inventory"
|
||||||
export const confirmVariantInventoryWorkflow = createWorkflow(
|
export const confirmVariantInventoryWorkflow = createWorkflow(
|
||||||
confirmVariantInventoryWorkflowId,
|
confirmVariantInventoryWorkflowId,
|
||||||
(input: WorkflowData<ConfirmVariantInventoryWorkflowInputDTO>) => {
|
(
|
||||||
|
input: WorkflowData<ConfirmVariantInventoryWorkflowInputDTO>
|
||||||
|
): WorkflowData<Output> => {
|
||||||
const confirmInventoryInput = transform({ input }, (data) => {
|
const confirmInventoryInput = transform({ input }, (data) => {
|
||||||
const productVariantInventoryItems = new Map<string, any>()
|
const productVariantInventoryItems = new Map<string, any>()
|
||||||
const priceNotFound: string[] = []
|
|
||||||
const stockLocationIds = new Set<string>()
|
const stockLocationIds = new Set<string>()
|
||||||
const allVariants = new Map<string, any>()
|
const allVariants = new Map<string, any>()
|
||||||
let hasSalesChannelStockLocation = false
|
let hasSalesChannelStockLocation = false
|
||||||
@@ -26,6 +38,10 @@ export const confirmVariantInventoryWorkflow = createWorkflow(
|
|||||||
data.input,
|
data.input,
|
||||||
"variants.inventory_items.inventory.location_levels.stock_locations.sales_channels",
|
"variants.inventory_items.inventory.location_levels.stock_locations.sales_channels",
|
||||||
({ variants, inventory_items, stock_locations, sales_channels }) => {
|
({ variants, inventory_items, stock_locations, sales_channels }) => {
|
||||||
|
if (!variants) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!hasSalesChannelStockLocation &&
|
!hasSalesChannelStockLocation &&
|
||||||
sales_channels?.id === salesChannelId
|
sales_channels?.id === salesChannelId
|
||||||
@@ -33,19 +49,19 @@ export const confirmVariantInventoryWorkflow = createWorkflow(
|
|||||||
hasSalesChannelStockLocation = true
|
hasSalesChannelStockLocation = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isDefined(variants.calculated_price)) {
|
if (stock_locations) {
|
||||||
priceNotFound.push(variants.id)
|
stockLocationIds.add(stock_locations.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
stockLocationIds.add(stock_locations.id)
|
if (inventory_items) {
|
||||||
|
const inventoryItemId = inventory_items.inventory_item_id
|
||||||
const inventoryItemId = inventory_items.inventory_item_id
|
if (!productVariantInventoryItems.has(inventoryItemId)) {
|
||||||
if (!productVariantInventoryItems.has(inventoryItemId)) {
|
productVariantInventoryItems.set(inventoryItemId, {
|
||||||
productVariantInventoryItems.set(inventoryItemId, {
|
variant_id: inventory_items.variant_id,
|
||||||
variant_id: inventory_items.variant_id,
|
inventory_item_id: inventoryItemId,
|
||||||
inventory_item_id: inventoryItemId,
|
required_quantity: inventory_items.required_quantity,
|
||||||
required_quantity: inventory_items.required_quantity,
|
})
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!allVariants.has(variants.id)) {
|
if (!allVariants.has(variants.id)) {
|
||||||
@@ -72,13 +88,6 @@ export const confirmVariantInventoryWorkflow = createWorkflow(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priceNotFound.length && !data.input.ignore_price_check) {
|
|
||||||
throw new MedusaError(
|
|
||||||
MedusaError.Types.INVALID_DATA,
|
|
||||||
`Variants with IDs ${priceNotFound.join(", ")} do not have a price`
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const items = prepareConfirmInventoryInput({
|
const items = prepareConfirmInventoryInput({
|
||||||
product_variant_inventory_items: Array.from(
|
product_variant_inventory_items: Array.from(
|
||||||
productVariantInventoryItems.values()
|
productVariantInventoryItems.values()
|
||||||
@@ -92,5 +101,7 @@ export const confirmVariantInventoryWorkflow = createWorkflow(
|
|||||||
})
|
})
|
||||||
|
|
||||||
confirmInventoryStep(confirmInventoryInput)
|
confirmInventoryStep(confirmInventoryInput)
|
||||||
|
|
||||||
|
return confirmInventoryInput
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import {
|
|||||||
} from "../steps"
|
} from "../steps"
|
||||||
import { refreshCartPromotionsStep } from "../steps/refresh-cart-promotions"
|
import { refreshCartPromotionsStep } from "../steps/refresh-cart-promotions"
|
||||||
import { updateTaxLinesStep } from "../steps/update-tax-lines"
|
import { updateTaxLinesStep } from "../steps/update-tax-lines"
|
||||||
|
import { validateVariantPricesStep } from "../steps/validate-variant-prices"
|
||||||
import { productVariantsFields } from "../utils/fields"
|
import { productVariantsFields } from "../utils/fields"
|
||||||
import { prepareLineItemData } from "../utils/prepare-line-item-data"
|
import { prepareLineItemData } from "../utils/prepare-line-item-data"
|
||||||
import { confirmVariantInventoryWorkflow } from "./confirm-variant-inventory"
|
import { confirmVariantInventoryWorkflow } from "./confirm-variant-inventory"
|
||||||
@@ -68,6 +69,8 @@ export const createCartWorkflow = createWorkflow(
|
|||||||
throw_if_key_not_found: true,
|
throw_if_key_not_found: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
validateVariantPricesStep({ variants })
|
||||||
|
|
||||||
confirmVariantInventoryWorkflow.runAsStep({
|
confirmVariantInventoryWorkflow.runAsStep({
|
||||||
input: {
|
input: {
|
||||||
sales_channel_id: salesChannel.id,
|
sales_channel_id: salesChannel.id,
|
||||||
|
|||||||
+1
-1
@@ -78,7 +78,7 @@ export const listShippingOptionsForCartWorkflow = createWorkflow(
|
|||||||
({ shipping_options }) => {
|
({ shipping_options }) => {
|
||||||
const { calculated_price, ...options } = shipping_options ?? {}
|
const { calculated_price, ...options } = shipping_options ?? {}
|
||||||
|
|
||||||
if (!calculated_price) {
|
if (options?.id && !calculated_price) {
|
||||||
optionsMissingPrices.push(options.id)
|
optionsMissingPrices.push(options.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { useRemoteQueryStep } from "../../../common/steps/use-remote-query"
|
|||||||
import { updateLineItemsStep } from "../../line-item/steps"
|
import { updateLineItemsStep } from "../../line-item/steps"
|
||||||
import { refreshCartShippingMethodsStep } from "../steps"
|
import { refreshCartShippingMethodsStep } from "../steps"
|
||||||
import { refreshCartPromotionsStep } from "../steps/refresh-cart-promotions"
|
import { refreshCartPromotionsStep } from "../steps/refresh-cart-promotions"
|
||||||
|
import { validateVariantPricesStep } from "../steps/validate-variant-prices"
|
||||||
import {
|
import {
|
||||||
cartFieldsForRefreshSteps,
|
cartFieldsForRefreshSteps,
|
||||||
productVariantsFields,
|
productVariantsFields,
|
||||||
@@ -47,6 +48,8 @@ export const updateLineItemInCartWorkflow = createWorkflow(
|
|||||||
throw_if_key_not_found: true,
|
throw_if_key_not_found: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
validateVariantPricesStep({ variants })
|
||||||
|
|
||||||
const items = transform({ input }, (data) => {
|
const items = transform({ input }, (data) => {
|
||||||
return [data.input.item]
|
return [data.input.item]
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import { findOrCreateCustomerStep } from "../../definition/cart/steps/find-or-cr
|
|||||||
import { findSalesChannelStep } from "../../definition/cart/steps/find-sales-channel"
|
import { findSalesChannelStep } from "../../definition/cart/steps/find-sales-channel"
|
||||||
import { getVariantPriceSetsStep } from "../../definition/cart/steps/get-variant-price-sets"
|
import { getVariantPriceSetsStep } from "../../definition/cart/steps/get-variant-price-sets"
|
||||||
import { getVariantsStep } from "../../definition/cart/steps/get-variants"
|
import { getVariantsStep } from "../../definition/cart/steps/get-variants"
|
||||||
import { validateVariantsExistStep } from "../../definition/cart/steps/validate-variants-existence"
|
|
||||||
import { prepareConfirmInventoryInput } from "../../definition/cart/utils/prepare-confirm-inventory-input"
|
import { prepareConfirmInventoryInput } from "../../definition/cart/utils/prepare-confirm-inventory-input"
|
||||||
import { prepareLineItemData } from "../../definition/cart/utils/prepare-line-item-data"
|
import { prepareLineItemData } from "../../definition/cart/utils/prepare-line-item-data"
|
||||||
import { createOrdersStep, updateOrderTaxLinesStep } from "../steps"
|
import { createOrdersStep, updateOrderTaxLinesStep } from "../steps"
|
||||||
@@ -39,8 +38,8 @@ export const createOrdersWorkflow = createWorkflow(
|
|||||||
findOrCreateCustomerStep({
|
findOrCreateCustomerStep({
|
||||||
customerId: input.customer_id,
|
customerId: input.customer_id,
|
||||||
email: input.email,
|
email: input.email,
|
||||||
}),
|
})
|
||||||
validateVariantsExistStep({ variantIds })
|
// validateVariantsExistStep({ variantIds })
|
||||||
)
|
)
|
||||||
|
|
||||||
const variants = getVariantsStep({
|
const variants = getVariantsStep({
|
||||||
|
|||||||
@@ -124,8 +124,6 @@ export interface CompleteCartWorkflowInputDTO {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ConfirmVariantInventoryWorkflowInputDTO {
|
export interface ConfirmVariantInventoryWorkflowInputDTO {
|
||||||
ignore_price_check?: boolean
|
|
||||||
|
|
||||||
sales_channel_id: string
|
sales_channel_id: string
|
||||||
variants: {
|
variants: {
|
||||||
id: string
|
id: string
|
||||||
|
|||||||
@@ -83,6 +83,11 @@ export function deepFlatMap(
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (Array.isArray(element[currentKey])) {
|
if (Array.isArray(element[currentKey])) {
|
||||||
|
if (element[currentKey].length === 0) {
|
||||||
|
callback({ ...context })
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
element[currentKey].forEach((item) => {
|
element[currentKey].forEach((item) => {
|
||||||
stack.push({
|
stack.push({
|
||||||
element: item,
|
element: item,
|
||||||
|
|||||||
Reference in New Issue
Block a user