chore: complete cart part 2 (#7227)

This commit is contained in:
Carlos R. L. Rodrigues
2024-05-05 10:35:09 -03:00
committed by GitHub
parent c32a31e139
commit aba194de9a
24 changed files with 344 additions and 321 deletions

View File

@@ -415,10 +415,12 @@ medusaIntegrationTestRunner({
expect(errors).toEqual([
{
action: "confirm-inventory-step",
action: "confirm-item-inventory-as-step",
handlerType: "invoke",
error: expect.objectContaining({
message: "Some variant does not have the required inventory",
message: expect.stringContaining(
"Some variant does not have the required inventory"
),
}),
},
])
@@ -707,10 +709,13 @@ medusaIntegrationTestRunner({
expect(errors).toEqual([
{
action: "confirm-inventory-step",
action: "confirm-item-inventory-as-step",
handlerType: "invoke",
error: expect.objectContaining({
message: `Variants with IDs ${product.variants[0].id} do not have a price`,
// TODO: FIX runAsStep nested errors
message: expect.stringContaining(
`Variants with IDs ${product.variants[0].id} do not have a price`
),
}),
},
])

View File

@@ -83,7 +83,7 @@ medusaIntegrationTestRunner({
})
describe("POST /store/carts", () => {
it.skip("should create a cart", async () => {
it("should create a cart", async () => {
const region = await regionModule.create({
name: "US",
currency_code: "usd",

View File

@@ -8,6 +8,7 @@ interface StepInput {
items: {
inventory_item_id: string
required_quantity: number
allow_backorder: boolean
quantity: number
location_ids: string[]
}[]
@@ -23,6 +24,10 @@ export const confirmInventoryStep = createStep(
// TODO: Should be bulk
const promises = data.items.map(async (item) => {
if (item.allow_backorder) {
return true
}
const itemQuantity = item.required_quantity * item.quantity
return await inventoryService.confirmInventory(

View File

@@ -37,6 +37,26 @@ export const completeCartFields = [
"original_shipping_tax_total",
"original_shipping_tax_subtotal",
"original_shipping_total",
"raw_total",
"raw_subtotal",
"raw_tax_total",
"raw_discount_total",
"raw_discount_tax_total",
"raw_original_total",
"raw_original_tax_total",
"raw_item_total",
"raw_item_subtotal",
"raw_item_tax_total",
"raw_sales_channel_id",
"raw_original_item_total",
"raw_original_item_subtotal",
"raw_original_item_tax_total",
"raw_shipping_total",
"raw_shipping_subtotal",
"raw_shipping_tax_total",
"raw_original_shipping_tax_total",
"raw_original_shipping_tax_subtotal",
"raw_original_shipping_total",
"items.*",
"items.tax_lines.*",
"items.adjustments.*",
@@ -49,4 +69,37 @@ export const completeCartFields = [
"region.*",
"payment_collection.*",
"payment_collection.payment_sessions.*",
"items.variant.id",
"items.variant.manage_inventory",
"items.variant.allow_backorder",
"items.variant.inventory_items.inventory_item_id",
"items.variant.inventory_items.required_quantity",
"items.variant.inventory_items.inventory.location_levels.stock_locations.id",
"items.variant.inventory_items.inventory.location_levels.stock_locations.name",
"items.variant.inventory_items.inventory.location_levels.stock_locations.sales_channels.id",
"items.variant.inventory_items.inventory.location_levels.stock_locations.sales_channels.name",
]
export const productVariantsFields = [
"id",
"title",
"sku",
"manage_inventory",
"allow_backorder",
"barcode",
"product.id",
"product.title",
"product.description",
"product.subtitle",
"product.thumbnail",
"product.type",
"product.collection",
"product.handle",
"calculated_price.calculated_amount",
"inventory_items.inventory_item_id",
"inventory_items.required_quantity",
"inventory_items.inventory.location_levels.stock_locations.id",
"inventory_items.inventory.location_levels.stock_locations.name",
"inventory_items.inventory.location_levels.stock_locations.sales_channels.id",
"inventory_items.inventory.location_levels.stock_locations.sales_channels.name",
]

View File

@@ -7,14 +7,22 @@ interface ConfirmInventoryPreparationInput {
inventory_item_id: string
required_quantity: number
}[]
items: { variant_id?: string; quantity: BigNumberInput }[]
variants: { id: string; manage_inventory?: boolean }[]
items: {
variant_id?: string
quantity: BigNumberInput
}[]
variants: {
id: string
manage_inventory?: boolean
allow_backorder?: boolean
}[]
location_ids: string[]
}
interface ConfirmInventoryItem {
inventory_item_id: string
required_quantity: number
allow_backorder: boolean
quantity: number
location_ids: string[]
}
@@ -31,7 +39,7 @@ export const prepareConfirmInventoryInput = ({
const variantsMap = new Map<
string,
{ id: string; manage_inventory?: boolean }
ConfirmInventoryPreparationInput["variants"][0]
>(variants.map((v) => [v.id, v]))
const itemsToConfirm: ConfirmInventoryItem[] = []
@@ -57,6 +65,7 @@ export const prepareConfirmInventoryInput = ({
itemsToConfirm.push({
inventory_item_id: variantInventoryItem.inventory_item_id,
required_quantity: variantInventoryItem.required_quantity,
allow_backorder: !!variant.allow_backorder,
quantity: item.quantity as number, // TODO: update type to BigNumberInput
location_ids: location_ids,
})

View File

@@ -7,18 +7,16 @@ import {
createWorkflow,
transform,
} from "@medusajs/workflows-sdk"
import { MedusaError } from "medusa-core-utils"
import { useRemoteQueryStep } from "../../../common/steps/use-remote-query"
import {
addToCartStep,
confirmInventoryStep,
refreshCartShippingMethodsStep,
} from "../steps"
import { addToCartStep, refreshCartShippingMethodsStep } from "../steps"
import { refreshCartPromotionsStep } from "../steps/refresh-cart-promotions"
import { updateTaxLinesStep } from "../steps/update-tax-lines"
import { cartFieldsForRefreshSteps } from "../utils/fields"
import { prepareConfirmInventoryInput } from "../utils/prepare-confirm-inventory-input"
import {
cartFieldsForRefreshSteps,
productVariantsFields,
} from "../utils/fields"
import { prepareLineItemData } from "../utils/prepare-line-item-data"
import { confirmVariantInventoryWorkflow } from "./confirm-variant-inventory"
import { refreshPaymentCollectionForCartStep } from "./refresh-payment-collection"
// TODO: The AddToCartWorkflow are missing the following steps:
@@ -43,32 +41,7 @@ export const addToCartWorkflow = createWorkflow(
const variants = useRemoteQueryStep({
entry_point: "variants",
fields: [
"id",
"title",
"sku",
"barcode",
"manage_inventory",
"product.id",
"product.title",
"product.description",
"product.subtitle",
"product.thumbnail",
"product.type",
"product.collection",
"product.handle",
"calculated_price.calculated_amount",
"inventory_items.inventory_item_id",
"inventory_items.required_quantity",
"inventory_items.inventory.location_levels.stock_locations.id",
"inventory_items.inventory.location_levels.stock_locations.name",
"inventory_items.inventory.location_levels.stock_locations.sales_channels.id",
"inventory_items.inventory.location_levels.stock_locations.sales_channels.name",
],
fields: productVariantsFields,
variables: {
id: variantIds,
calculated_price: {
@@ -78,71 +51,14 @@ export const addToCartWorkflow = createWorkflow(
throw_if_key_not_found: true,
})
const confirmInventoryInput = transform({ input, variants }, (data) => {
const managedVariants = data.variants.filter((v) => v.manage_inventory)
if (!managedVariants.length) {
return { items: [] }
}
const productVariantInventoryItems: any[] = []
const stockLocations = data.variants
.map((v) => v.inventory_items)
.flat()
.map((ii) => {
productVariantInventoryItems.push({
variant_id: ii.variant_id,
inventory_item_id: ii.inventory_item_id,
required_quantity: ii.required_quantity,
})
return ii.inventory.location_levels
})
.flat()
.map((ll) => ll.stock_locations)
.flat()
const salesChannelId = data.input.cart.sales_channel_id
if (salesChannelId) {
const salesChannels = stockLocations
.map((sl) => sl.sales_channels)
.flat()
.filter((sc) => sc.id === salesChannelId)
if (!salesChannels.length) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`Sales channel ${salesChannelId} is not associated with any stock locations.`
)
}
}
const priceNotFound: string[] = data.variants
.filter((v) => !v.calculated_price)
.map((v) => v.id)
if (priceNotFound.length) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`Variants with IDs ${priceNotFound.join(", ")} do not have a price`
)
}
const items = prepareConfirmInventoryInput({
product_variant_inventory_items: productVariantInventoryItems,
location_ids: stockLocations.map((l) => l.id),
items: data.input.items!,
variants: data.variants.map((v) => ({
id: v.id,
manage_inventory: v.manage_inventory,
})),
})
return { items }
confirmVariantInventoryWorkflow.runAsStep({
input: {
sales_channel_id: input.cart.sales_channel_id as string,
variants,
items: input.items,
},
})
confirmInventoryStep(confirmInventoryInput)
const lineItems = transform({ input, variants }, (data) => {
const items = (data.input.items ?? []).map((item) => {
const variant = data.variants.find((v) => v.id === item.variant_id)!

View File

@@ -1,9 +1,14 @@
import { CompleteCartWorkflowInputDTO, OrderDTO } from "@medusajs/types"
import { WorkflowData, createWorkflow } from "@medusajs/workflows-sdk"
import { OrderDTO } from "@medusajs/types"
import {
WorkflowData,
createWorkflow,
transform,
} from "@medusajs/workflows-sdk"
import { useRemoteQueryStep } from "../../../common"
import { createOrderFromCartStep } from "../steps"
import { updateTaxLinesStep } from "../steps/update-tax-lines"
import { completeCartFields } from "../utils/fields"
import { confirmVariantInventoryWorkflow } from "./confirm-variant-inventory"
/*
- [] Create Tax Lines
@@ -19,9 +24,7 @@ import { completeCartFields } from "../utils/fields"
export const completeCartWorkflowId = "complete-cart"
export const completeCartWorkflow = createWorkflow(
completeCartWorkflowId,
(
input: WorkflowData<CompleteCartWorkflowInputDTO>
): WorkflowData<OrderDTO> => {
(input: WorkflowData<any>): WorkflowData<OrderDTO> => {
const cart = useRemoteQueryStep({
entry_point: "cart",
fields: completeCartFields,
@@ -29,6 +32,37 @@ export const completeCartWorkflow = createWorkflow(
list: false,
})
const { variants, items, sales_channel_id } = transform(
{ cart },
(data) => {
const allItems: any[] = []
const allVariants: any[] = []
data.cart.items.forEach((item) => {
allItems.push({
id: item.id,
quantity: item.quantity,
})
allVariants.push(item.variant)
})
return {
variants: allVariants,
items: allItems,
sales_channel_id: data.cart.sales_channel_id,
}
}
)
confirmVariantInventoryWorkflow.runAsStep({
input: {
ignore_price_check: true,
sales_channel_id,
variants,
items,
},
})
updateTaxLinesStep({ cart_or_cart_id: cart, force_tax_calculation: true })
const finalCart = useRemoteQueryStep({

View File

@@ -0,0 +1,96 @@
import { ConfirmVariantInventoryWorkflowInputDTO } from "@medusajs/types"
import { MedusaError, deepFlatMap, isDefined } from "@medusajs/utils"
import {
WorkflowData,
createWorkflow,
transform,
} from "@medusajs/workflows-sdk"
import { confirmInventoryStep } from "../steps"
import { prepareConfirmInventoryInput } from "../utils/prepare-confirm-inventory-input"
export const confirmVariantInventoryWorkflowId = "confirm-item-inventory"
export const confirmVariantInventoryWorkflow = createWorkflow(
confirmVariantInventoryWorkflowId,
(input: WorkflowData<ConfirmVariantInventoryWorkflowInputDTO>) => {
const confirmInventoryInput = transform({ input }, (data) => {
const productVariantInventoryItems = new Map<string, any>()
const priceNotFound: string[] = []
const stockLocationIds = new Set<string>()
const allVariants = new Map<string, any>()
let hasSalesChannelStockLocation = false
let hasManagedInventory = false
const salesChannelId = data.input.sales_channel_id
deepFlatMap(
data.input,
"variants.inventory_items.inventory.location_levels.stock_locations.sales_channels",
({ variants, inventory_items, stock_locations, sales_channels }) => {
if (
!hasSalesChannelStockLocation &&
sales_channels?.id === salesChannelId
) {
hasSalesChannelStockLocation = true
}
if (!isDefined(variants.calculated_price)) {
priceNotFound.push(variants.id)
}
stockLocationIds.add(stock_locations.id)
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 locations.`
)
}
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({
product_variant_inventory_items: Array.from(
productVariantInventoryItems.values()
),
location_ids: Array.from(stockLocationIds),
items: data.input.items,
variants: Array.from(allVariants.values()),
})
return { items }
})
confirmInventoryStep(confirmInventoryInput)
}
)

View File

@@ -5,10 +5,8 @@ import {
parallelize,
transform,
} from "@medusajs/workflows-sdk"
import { MedusaError } from "medusa-core-utils"
import { useRemoteQueryStep } from "../../../common/steps/use-remote-query"
import {
confirmInventoryStep,
createCartsStep,
findOneOrAnyRegionStep,
findOrCreateCustomerStep,
@@ -17,8 +15,9 @@ import {
} from "../steps"
import { refreshCartPromotionsStep } from "../steps/refresh-cart-promotions"
import { updateTaxLinesStep } from "../steps/update-tax-lines"
import { prepareConfirmInventoryInput } from "../utils/prepare-confirm-inventory-input"
import { productVariantsFields } from "../utils/fields"
import { prepareLineItemData } from "../utils/prepare-line-item-data"
import { confirmVariantInventoryWorkflow } from "./confirm-variant-inventory"
import { refreshPaymentCollectionForCartStep } from "./refresh-payment-collection"
// TODO: The createCartWorkflow are missing the following steps:
@@ -59,32 +58,7 @@ export const createCartWorkflow = createWorkflow(
const variants = useRemoteQueryStep({
entry_point: "variants",
fields: [
"id",
"title",
"sku",
"manage_inventory",
"barcode",
"product.id",
"product.title",
"product.description",
"product.subtitle",
"product.thumbnail",
"product.type",
"product.collection",
"product.handle",
"calculated_price.calculated_amount",
"inventory_items.inventory_item_id",
"inventory_items.required_quantity",
"inventory_items.inventory.location_levels.stock_locations.id",
"inventory_items.inventory.location_levels.stock_locations.name",
"inventory_items.inventory.location_levels.stock_locations.sales_channels.id",
"inventory_items.inventory.location_levels.stock_locations.sales_channels.name",
],
fields: productVariantsFields,
variables: {
id: variantIds,
calculated_price: {
@@ -94,73 +68,13 @@ export const createCartWorkflow = createWorkflow(
throw_if_key_not_found: true,
})
const confirmInventoryInput = transform(
{ input, salesChannel, variants },
(data) => {
const managedVariants = data.variants.filter((v) => v.manage_inventory)
if (!managedVariants.length) {
return { items: [] }
}
const productVariantInventoryItems: any[] = []
const stockLocations = managedVariants
.map((v) => v.inventory_items)
.flat()
.map((ii) => {
productVariantInventoryItems.push({
variant_id: ii.variant_id,
inventory_item_id: ii.inventory_item_id,
required_quantity: ii.required_quantity,
})
return ii.inventory.location_levels
})
.flat()
.map((ll) => ll.stock_locations)
.flat()
const salesChannelId = data.salesChannel?.id
if (salesChannelId) {
const salesChannels = stockLocations
.map((sl) => sl.sales_channels)
.flat()
.filter((sc) => sc.id === salesChannelId)
if (!salesChannels.length) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`Sales channel ${salesChannelId} is not associated with any stock locations.`
)
}
}
const priceNotFound: string[] = data.variants
.filter((v) => !v.calculated_price)
.map((v) => v.id)
if (priceNotFound.length) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`Variants with IDs ${priceNotFound.join(", ")} do not have a price`
)
}
const items = prepareConfirmInventoryInput({
product_variant_inventory_items: productVariantInventoryItems,
location_ids: stockLocations.map((l) => l.id),
items: data.input.items!,
variants: data.variants.map((v) => ({
id: v.id,
manage_inventory: v.manage_inventory,
})),
})
return { items }
}
)
confirmInventoryStep(confirmInventoryInput)
confirmVariantInventoryWorkflow.runAsStep({
input: {
sales_channel_id: salesChannel.id,
variants,
items: input.items!,
},
})
const priceSets = getVariantPriceSetsStep({
variantIds,

View File

@@ -1,13 +1,9 @@
import {
CartDTO,
CreatePaymentCollectionForCartWorkflowInputDTO,
} from "@medusajs/types"
import { CreatePaymentCollectionForCartWorkflowInputDTO } from "@medusajs/types"
import {
WorkflowData,
createWorkflow,
transform,
} from "@medusajs/workflows-sdk"
import { retrieveCartStep } from "../steps"
import { createPaymentCollectionsStep } from "../steps/create-payment-collection"
import { linkCartAndPaymentCollectionsStep } from "../steps/link-cart-payment-collection"
@@ -17,7 +13,7 @@ export const createPaymentCollectionForCartWorkflow = createWorkflow(
createPaymentCollectionForCartWorkflowId,
(
input: WorkflowData<CreatePaymentCollectionForCartWorkflowInputDTO>
): WorkflowData<CartDTO> => {
): WorkflowData<void> => {
const created = createPaymentCollectionsStep([input])
const link = transform({ cartId: input.cart_id, created }, (data) => ({
@@ -30,9 +26,5 @@ export const createPaymentCollectionForCartWorkflow = createWorkflow(
}))
linkCartAndPaymentCollectionsStep(link)
const cart = retrieveCartStep({ id: input.cart_id })
return cart
}
)

View File

@@ -4,13 +4,15 @@ import {
createWorkflow,
transform,
} from "@medusajs/workflows-sdk"
import { MedusaError } from "medusa-core-utils"
import { useRemoteQueryStep } from "../../../common/steps/use-remote-query"
import { updateLineItemsStep } from "../../line-item/steps"
import { confirmInventoryStep, refreshCartShippingMethodsStep } from "../steps"
import { refreshCartShippingMethodsStep } from "../steps"
import { refreshCartPromotionsStep } from "../steps/refresh-cart-promotions"
import { cartFieldsForRefreshSteps } from "../utils/fields"
import { prepareConfirmInventoryInput } from "../utils/prepare-confirm-inventory-input"
import {
cartFieldsForRefreshSteps,
productVariantsFields,
} from "../utils/fields"
import { confirmVariantInventoryWorkflow } from "./confirm-variant-inventory"
import { refreshPaymentCollectionForCartStep } from "./refresh-payment-collection"
// TODO: The UpdateLineItemsWorkflow are missing the following steps:
@@ -35,32 +37,7 @@ export const updateLineItemInCartWorkflow = createWorkflow(
const variants = useRemoteQueryStep({
entry_point: "variants",
fields: [
"id",
"title",
"sku",
"barcode",
"manage_inventory",
"product.id",
"product.title",
"product.description",
"product.subtitle",
"product.thumbnail",
"product.type",
"product.collection",
"product.handle",
"calculated_price.calculated_amount",
"inventory_items.inventory_item_id",
"inventory_items.required_quantity",
"inventory_items.inventory.location_levels.stock_locations.id",
"inventory_items.inventory.location_levels.stock_locations.name",
"inventory_items.inventory.location_levels.stock_locations.sales_channels.id",
"inventory_items.inventory.location_levels.stock_locations.sales_channels.name",
],
fields: productVariantsFields,
variables: {
id: variantIds,
calculated_price: {
@@ -70,70 +47,17 @@ export const updateLineItemInCartWorkflow = createWorkflow(
throw_if_key_not_found: true,
})
const confirmInventoryInput = transform({ input, variants }, (data) => {
const managedVariants = data.variants.filter((v) => v.manage_inventory)
if (!managedVariants.length) {
return { items: [] }
}
const productVariantInventoryItems: any[] = []
const stockLocations = data.variants
.map((v) => v.inventory_items)
.flat()
.map((ii) => {
productVariantInventoryItems.push({
variant_id: ii.variant_id,
inventory_item_id: ii.inventory_item_id,
required_quantity: ii.required_quantity,
})
return ii.inventory.location_levels
})
.flat()
.map((ll) => ll.stock_locations)
.flat()
const salesChannelId = data.input.cart.sales_channel_id
if (salesChannelId) {
const salesChannels = stockLocations
.map((sl) => sl.sales_channels)
.flat()
.filter((sc) => sc.id === salesChannelId)
if (!salesChannels.length) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`Sales channel ${salesChannelId} is not associated with any stock locations.`
)
}
}
const priceNotFound: string[] = data.variants
.filter((v) => !v.calculated_price)
.map((v) => v.id)
if (priceNotFound.length) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`Variants with IDs ${priceNotFound.join(", ")} do not have a price`
)
}
const items = prepareConfirmInventoryInput({
product_variant_inventory_items: productVariantInventoryItems,
location_ids: stockLocations.map((l) => l.id),
items: [data.input.item!],
variants: data.variants.map((v) => ({
id: v.id,
manage_inventory: v.manage_inventory,
})),
})
return { items }
const items = transform({ input }, (data) => {
return [data.input.item]
})
confirmInventoryStep(confirmInventoryInput)
confirmVariantInventoryWorkflow.runAsStep({
input: {
sales_channel_id: input.cart.sales_channel_id as string,
variants,
items,
},
})
const lineItemUpdate = transform({ input, variants }, (data) => {
const variant = data.variants[0]

View File

@@ -122,3 +122,32 @@ export interface PricedShippingOptionDTO extends ShippingOptionDTO {
export interface CompleteCartWorkflowInputDTO {
id: string
}
export interface ConfirmVariantInventoryWorkflowInputDTO {
ignore_price_check?: boolean
sales_channel_id: string
variants: {
id: string
manage_inventory: boolean
inventory_items: {
inventory_item_id: string
variant_id: string
required_quantity: BigNumberInput
inventory: {
location_levels: {
stock_locations: {
id: string
sales_channels: {
id: string
}[]
}[]
}
}[]
}[]
}[]
items: {
variant_id?: string
quantity: BigNumberInput
}[]
}

View File

@@ -4,8 +4,10 @@ import {
WorkflowManager,
} from "@medusajs/orchestration"
import { LoadedModule, MedusaContainer } from "@medusajs/types"
import { isString, OrchestrationUtils } from "@medusajs/utils"
import { OrchestrationUtils, isString } from "@medusajs/utils"
import { exportWorkflow } from "../../helper"
import { createStep } from "./create-step"
import { StepResponse } from "./helpers"
import { proxify } from "./helpers/proxy"
import {
CreateWorkflowComposerContext,
@@ -14,8 +16,6 @@ import {
WorkflowData,
WorkflowDataProperties,
} from "./type"
import { createStep } from "./create-step"
import { StepResponse } from "./helpers"
global[OrchestrationUtils.SymbolMedusaWorkflowComposerContext] = null

View File

@@ -7,7 +7,7 @@ export const POST = async (
req: MedusaRequest<StoreCompleteCartType>,
res: MedusaResponse
) => {
const { idempotency_key: idempotencyKey } = req.validatedBody
const cart_id = req.params.id
// If the idempotencyKey is present:
// - is workflow is running?
@@ -17,6 +17,9 @@ export const POST = async (
const { errors, result } = await completeCartWorkflow(req.scope).run({
input: { id: req.params.id },
context: {
transactionId: cart_id,
},
throwOnError: false,
})

View File

@@ -14,7 +14,6 @@ export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
select: [
"id",
"sales_channel_id",
"subtotal",
"currency_code",
"shipping_address.city",
"shipping_address.country_code",

View File

@@ -1,11 +1,6 @@
export * from "./cart-customer"
export * from "./cart-payment-collection"
export * from "./cart-promotion"
export * from "./cart-region"
export * from "./cart-sales-channel"
export * from "./inventory-level-stock-location"
export * from "./location-fulfillment-set"
export * from "./order-customer"
export * from "./fulfillment-set-location"
export * from "./order-promotion"
export * from "./order-region"
export * from "./order-sales-channel"
@@ -14,8 +9,7 @@ export * from "./product-shipping-profile"
export * from "./product-variant-inventory-item"
export * from "./product-variant-price-set"
export * from "./publishable-api-key-sales-channel"
export * from "./readonly"
export * from "./region-payment-provider"
export * from "./sales-channel-location"
export * from "./shipping-option-price-set"
export * from "./store-default-currency"

View File

@@ -0,0 +1,43 @@
import { Modules } from "@medusajs/modules-sdk"
import { ModuleJoinerConfig } from "@medusajs/types"
export const CartProduct: ModuleJoinerConfig = {
isLink: true,
isReadOnlyLink: true,
extends: [
{
serviceName: Modules.CART,
relationship: {
serviceName: Modules.PRODUCT,
primaryKey: "id",
foreignKey: "items.product_id",
alias: "product",
},
},
{
serviceName: Modules.CART,
relationship: {
serviceName: Modules.PRODUCT,
primaryKey: "id",
foreignKey: "items.variant_id",
alias: "variant",
args: {
methodSuffix: "Variants",
},
},
},
{
serviceName: Modules.PRODUCT,
relationship: {
serviceName: Modules.CART,
primaryKey: "variant_id",
foreignKey: "id",
alias: "cart_items",
isList: true,
args: {
methodSuffix: "LineItems",
},
},
},
],
}

View File

@@ -0,0 +1,7 @@
export * from "./cart-customer"
export * from "./cart-product"
export * from "./cart-region"
export * from "./cart-sales-channel"
export * from "./inventory-level-stock-location"
export * from "./order-customer"
export * from "./store-default-currency"