Skip to content

Commit

Permalink
chore: complete cart part 2 (medusajs#7227)
Browse files Browse the repository at this point in the history
  • Loading branch information
carlos-r-l-rodrigues authored May 5, 2024
1 parent c32a31e commit aba194d
Show file tree
Hide file tree
Showing 24 changed files with 344 additions and 321 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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"
),
}),
},
])
Expand Down Expand Up @@ -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`
),
}),
},
])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ interface StepInput {
items: {
inventory_item_id: string
required_quantity: number
allow_backorder: boolean
quantity: number
location_ids: string[]
}[]
Expand All @@ -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(
Expand Down
53 changes: 53 additions & 0 deletions packages/core/core-flows/src/definition/cart/utils/fields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.*",
Expand All @@ -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",
]
Original file line number Diff line number Diff line change
Expand Up @@ -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[]
}
Expand All @@ -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[] = []
Expand All @@ -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,
})
Expand Down
110 changes: 13 additions & 97 deletions packages/core/core-flows/src/definition/cart/workflows/add-to-cart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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: {
Expand All @@ -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)!
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -19,16 +24,45 @@ 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,
variables: { id: input.id },
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({
Expand Down
Loading

0 comments on commit aba194d

Please sign in to comment.