Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ medusaIntegrationTestRunner({
let inventoryItem
let inventoryItemExtra
let location
let locationTwo
let productExtra
const shippingProviderId = "manual_test-provider"

Expand Down Expand Up @@ -553,10 +554,29 @@ medusaIntegrationTestRunner({
)
).data.stock_location

locationTwo = (
await api.post(
`/admin/stock-locations`,
{
name: "Test location two",
},
adminHeaders
)
).data.stock_location

await api.post(
`/admin/inventory-items/${inventoryItemLarge.id}/location-levels`,
{
location_id: location.id,
stocked_quantity: 0,
},
adminHeaders
)

await api.post(
`/admin/inventory-items/${inventoryItemLarge.id}/location-levels`,
{
location_id: locationTwo.id,
stocked_quantity: 10,
},
adminHeaders
Expand Down Expand Up @@ -766,6 +786,14 @@ medusaIntegrationTestRunner({
stock_location_id: location.id,
},
},
{
[Modules.SALES_CHANNEL]: {
sales_channel_id: salesChannel.id,
},
[Modules.STOCK_LOCATION]: {
stock_location_id: locationTwo.id,
},
},
])
})

Expand Down Expand Up @@ -860,6 +888,60 @@ medusaIntegrationTestRunner({
])
)
})

it("should manage inventory across locations in order edit", async () => {
let edit = (
await api.post(
`/admin/order-edits`,
{ order_id: order.id },
adminHeaders
)
).data.order_change

// Add item
await api.post(
`/admin/order-edits/${order.id}/items`,
{
items: [
{
variant_id: product.variants.find((v) => v.title === "L shirt")
.id,
quantity: 1,
},
],
},
adminHeaders
)

edit = (
await api.post(
`/admin/order-edits/${order.id}/request`,
{},
adminHeaders
)
).data.order_change

edit = (
await api.post(
`/admin/order-edits/${order.id}/confirm`,
{},
adminHeaders
)
).data.order_change

order = (await api.get(`/admin/orders/${order.id}`, adminHeaders)).data
.order

expect(order.items.length).toBe(3)
expect(order.items).toEqual(
expect.arrayContaining([
expect.objectContaining({
subtitle: "L shirt",
quantity: 2,
}),
])
)
})
})

describe("Order Edit Shipping Methods", () => {
Expand Down
2 changes: 2 additions & 0 deletions packages/core/core-flows/src/cart/utils/fields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ export const completeCartFields = [
"items.variant.inventory_items.inventory.location_levels.reserved_quantity",
"items.variant.inventory_items.inventory.location_levels.raw_stocked_quantity",
"items.variant.inventory_items.inventory.location_levels.raw_reserved_quantity",
"items.variant.inventory_items.inventory.location_levels.location_id",
"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",
Expand Down Expand Up @@ -168,6 +169,7 @@ export const productVariantsFields = [
"inventory_items.inventory.requires_shipping",
"inventory_items.inventory.location_levels.stocked_quantity",
"inventory_items.inventory.location_levels.reserved_quantity",
"inventory_items.inventory.location_levels.location_id",
"inventory_items.inventory.location_levels.raw_stocked_quantity",
"inventory_items.inventory.location_levels.raw_reserved_quantity",
"inventory_items.inventory.location_levels.stock_locations.id",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,43 @@ import {
deepFlatMap,
} from "@medusajs/framework/utils"

export const requiredOrderFieldsForInventoryConfirmation = [
"id",
"version",
"canceled_at",
"sales_channel_id",
"items.*",
"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.stocked_quantity",
"items.variant.inventory_items.inventory.location_levels.reserved_quantity",
"items.variant.inventory_items.inventory.location_levels.raw_stocked_quantity",
"items.variant.inventory_items.inventory.location_levels.raw_reserved_quantity",
"items.variant.inventory_items.inventory.location_levels.location_id",
"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 requiredVariantFieldsForInventoryConfirmation = [
"manage_inventory",
"allow_backorder",
"inventory_items.inventory_item_id",
"inventory_items.required_quantity",
"inventory_items.inventory.location_levels.stocked_quantity",
"inventory_items.inventory.location_levels.reserved_quantity",
"inventory_items.inventory.location_levels.raw_stocked_quantity",
"inventory_items.inventory.location_levels.raw_reserved_quantity",
"inventory_items.inventory.location_levels.location_id",
"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",
]

interface ConfirmInventoryPreparationInput {
product_variant_inventory_items: {
variant_id: string
Expand Down
32 changes: 20 additions & 12 deletions packages/core/core-flows/src/cart/workflows/add-to-cart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ import {
AddToCartWorkflowInputDTO,
ConfirmVariantInventoryWorkflowInputDTO,
} from "@medusajs/framework/types"
import { CartWorkflowEvents, isDefined } from "@medusajs/framework/utils"
import {
CartWorkflowEvents,
deduplicate,
isDefined,
} from "@medusajs/framework/utils"
import {
createHook,
createWorkflow,
Expand All @@ -28,13 +32,14 @@ import {
cartFieldsForPricingContext,
productVariantsFields,
} from "../utils/fields"
import { requiredVariantFieldsForInventoryConfirmation } from "../utils/prepare-confirm-inventory-input"
import {
prepareLineItemData,
PrepareLineItemDataInput,
} from "../utils/prepare-line-item-data"
import { pricingContextResult } from "../utils/schemas"
import { confirmVariantInventoryWorkflow } from "./confirm-variant-inventory"
import { refreshCartItemsWorkflow } from "./refresh-cart-items"
import { pricingContextResult } from "../utils/schemas"

const cartFields = ["completed_at"].concat(cartFieldsForPricingContext)

Expand Down Expand Up @@ -71,23 +76,23 @@ export const addToCartWorkflowId = "add-to-cart"
*
* @property hooks.validate - This hook is executed before all operations. You can consume this hook to perform any custom validation. If validation fails, you can throw an error to stop the workflow execution.
* @property hooks.setPricingContext - This hook is executed after the cart is retrieved and before the line items are created. You can consume this hook to return any custom context useful for the prices retrieval of the variants to be added to the cart.
*
*
* For example, assuming you have the following custom pricing rule:
*
*
* ```json
* {
* "attribute": "location_id",
* "operator": "eq",
* "value": "sloc_123",
* }
* ```
*
*
* You can consume the `setPricingContext` hook to add the `location_id` context to the prices calculation:
*
*
* ```ts
* import { addToCartWorkflow } from "@medusajs/medusa/core-flows";
* import { StepResponse } from "@medusajs/workflows-sdk";
*
*
* addToCartWorkflow.hooks.setPricingContext((
* { cart, variantIds, items, additional_data }, { container }
* ) => {
Expand All @@ -96,13 +101,13 @@ export const addToCartWorkflowId = "add-to-cart"
* });
* });
* ```
*
*
* The variants' prices will now be retrieved using the context you return.
*
*
* :::note
*
*
* Learn more about prices calculation context in the [Prices Calculation](https://docs.medusajs.com/resources/commerce-modules/pricing/price-calculation) documentation.
*
*
* :::
*/
export const addToCartWorkflow = createWorkflow(
Expand Down Expand Up @@ -163,7 +168,10 @@ export const addToCartWorkflow = createWorkflow(
}).then(() => {
return useRemoteQueryStep({
entry_point: "variants",
fields: productVariantsFields,
fields: deduplicate([
...productVariantsFields,
...requiredVariantFieldsForInventoryConfirmation,
]),
variables: {
id: variantIds,
calculated_price: {
Expand Down
29 changes: 17 additions & 12 deletions packages/core/core-flows/src/cart/workflows/create-carts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
} from "@medusajs/framework/types"
import {
CartWorkflowEvents,
deduplicate,
isDefined,
MedusaError,
} from "@medusajs/framework/utils"
Expand All @@ -25,18 +26,19 @@ import {
findSalesChannelStep,
} from "../steps"
import { validateLineItemPricesStep } from "../steps/validate-line-item-prices"
import { validateSalesChannelStep } from "../steps/validate-sales-channel"
import { validateVariantPricesStep } from "../steps/validate-variant-prices"
import { productVariantsFields } from "../utils/fields"
import { requiredVariantFieldsForInventoryConfirmation } from "../utils/prepare-confirm-inventory-input"
import {
prepareLineItemData,
PrepareLineItemDataInput,
} from "../utils/prepare-line-item-data"
import { pricingContextResult } from "../utils/schemas"
import { confirmVariantInventoryWorkflow } from "./confirm-variant-inventory"
import { refreshPaymentCollectionForCartWorkflow } from "./refresh-payment-collection"
import { updateCartPromotionsWorkflow } from "./update-cart-promotions"
import { updateTaxLinesWorkflow } from "./update-tax-lines"
import { validateSalesChannelStep } from "../steps/validate-sales-channel"
import { pricingContextResult } from "../utils/schemas"

/**
* The data to create the cart, along with custom data that's passed to the workflow's hooks.
Expand Down Expand Up @@ -78,23 +80,23 @@ export const createCartWorkflowId = "create-cart"
* @property hooks.validate - This hook is executed before all operations. You can consume this hook to perform any custom validation. If validation fails, you can throw an error to stop the workflow execution.
* @property hooks.cartCreated - This hook is executed after a cart is created. You can consume this hook to perform custom actions on the created cart.
* @property hooks.setPricingContext - This hook is executed after the cart is retrieved and before the line items are created. You can consume this hook to return any custom context useful for the prices retrieval of the variants to be added to the cart.
*
*
* For example, assuming you have the following custom pricing rule:
*
*
* ```json
* {
* "attribute": "location_id",
* "operator": "eq",
* "value": "sloc_123",
* }
* ```
*
*
* You can consume the `setPricingContext` hook to add the `location_id` context to the prices calculation:
*
*
* ```ts
* import { createCartWorkflow } from "@medusajs/medusa/core-flows";
* import { StepResponse } from "@medusajs/workflows-sdk";
*
*
* createCartWorkflow.hooks.setPricingContext((
* { region, variantIds, salesChannel, customerData, additional_data }, { container }
* ) => {
Expand All @@ -103,13 +105,13 @@ export const createCartWorkflowId = "create-cart"
* });
* });
* ```
*
*
* The variants' prices will now be retrieved using the context you return.
*
*
* :::note
*
*
* Learn more about prices calculation context in the [Prices Calculation](https://docs.medusajs.com/resources/commerce-modules/pricing/price-calculation) documentation.
*
*
* :::
*/
export const createCartWorkflow = createWorkflow(
Expand Down Expand Up @@ -170,7 +172,10 @@ export const createCartWorkflow = createWorkflow(
}).then(() => {
return useRemoteQueryStep({
entry_point: "variants",
fields: productVariantsFields,
fields: deduplicate([
...productVariantsFields,
...requiredVariantFieldsForInventoryConfirmation,
]),
variables: {
id: variantIds,
calculated_price: {
Expand Down
Loading