fix(core-flows): Avoid throwing if no prices found for variant when adding to cart custom price item (#14528)

* Avoid throwing prices not found error when line item is custom unit price

* Add changeset

* Avoid throwing upo variant price validation for custom priced item variants
This commit is contained in:
Nicolas Gorga
2026-01-13 14:58:41 -03:00
committed by GitHub
parent d4173478f4
commit 28fae96cee
4 changed files with 116 additions and 8 deletions

View File

@@ -0,0 +1,5 @@
---
"@medusajs/core-flows": patch
---
fix(core-flows): Avoid throwing if no prices found for variant when adding to cart custom price item

View File

@@ -2474,6 +2474,103 @@ medusaIntegrationTestRunner({
])
})
it("should add item to cart with unit_price when variant has no price set", async () => {
const salesChannel = await scModuleService.createSalesChannels({
name: "Webshop",
})
const location = await stockLocationModule.createStockLocations({
name: "Warehouse",
})
let cart = await cartModuleService.createCarts({
currency_code: "usd",
sales_channel_id: salesChannel.id,
})
const [product] = await productModule.createProducts([
{
title: "Test product",
status: ProductStatus.PUBLISHED,
variants: [
{
title: "Test variant",
},
],
},
])
const inventoryItem = await inventoryModule.createInventoryItems({
sku: "inv-1234",
})
await inventoryModule.createInventoryLevels([
{
inventory_item_id: inventoryItem.id,
location_id: location.id,
stocked_quantity: 2,
reserved_quantity: 0,
},
])
await remoteLink.create([
{
[Modules.SALES_CHANNEL]: {
sales_channel_id: salesChannel.id,
},
[Modules.STOCK_LOCATION]: {
stock_location_id: location.id,
},
},
{
[Modules.PRODUCT]: {
variant_id: product.variants[0].id,
},
[Modules.INVENTORY]: {
inventory_item_id: inventoryItem.id,
},
},
])
cart = await cartModuleService.retrieveCart(cart.id, {
select: ["id", "region_id", "currency_code", "sales_channel_id"],
})
// Add item with unit_price specified even though variant has no price set
await addToCartWorkflow(appContainer).run({
input: {
items: [
{
variant_id: product.variants[0].id,
quantity: 1,
unit_price: 5000,
},
],
cart_id: cart.id,
},
})
cart = await cartModuleService.retrieveCart(cart.id, {
relations: ["items"],
})
expect(cart).toEqual(
expect.objectContaining({
id: cart.id,
currency_code: "usd",
items: expect.arrayContaining([
expect.objectContaining({
unit_price: 5000,
is_custom_price: true,
quantity: 1,
title: "Test product",
subtitle: "Test variant",
}),
]),
})
)
})
describe("setPricingContext hook", () => {
it("should use context provided by the hook", async () => {
const salesChannel = await scModuleService.createSalesChannels({

View File

@@ -91,13 +91,15 @@ async function fetchVariantPriceSets(
}
/**
* Validates that all variants have price sets and throws error for missing ones
* Validates that all variants without a custom price have price sets and throws error for missing ones
*/
function validateVariantPriceSets(
variantPriceSets: VariantPriceSetData[]
variantPriceSets: VariantPriceSetData[],
variantsWithCustomPrice: string[] = []
): void {
const variantsWithCustomPriceSet = new Set(variantsWithCustomPrice)
const notFound = variantPriceSets
.filter((v) => !v.price_set?.id)
.filter((v) => !v.price_set?.id && !variantsWithCustomPriceSet.has(v.id))
.map((v) => v.id)
if (notFound.length) {
@@ -287,7 +289,10 @@ export const getVariantPriceSetsStep = createStep(
const variantIds = bulkData.map((item) => item.variantId)
const variantPriceSets = await fetchVariantPriceSets(query, variantIds)
validateVariantPriceSets(variantPriceSets)
const variantsWithCustomPrice = bulkData
.filter((item) => !!item.context?.is_custom_price)
.map((item) => item.variantId)
validateVariantPriceSets(variantPriceSets, variantsWithCustomPrice)
// Map variant IDs to price set IDs
const variantToPriceSetId = new Map<string, string>()

View File

@@ -125,6 +125,7 @@ export const getVariantsAndItemsWithPrices = createWorkflow(
context: {
...baseContext,
quantity: item.quantity,
is_custom_price: !!item.unit_price,
},
}
})
@@ -180,7 +181,10 @@ export const getVariantsAndItemsWithPrices = createWorkflow(
calculatedPriceSet = calculatedPriceSets[item_.variant_id!]
}
if (!calculatedPriceSet && item_.variant_id) {
const isCustomPrice =
item_.is_custom_price ?? isDefined(item?.unit_price)
if (!calculatedPriceSet && item_.variant_id && !isCustomPrice) {
priceNotFound.push(item_.variant_id)
}
@@ -198,9 +202,6 @@ export const getVariantsAndItemsWithPrices = createWorkflow(
variant.calculated_price = calculatedPriceSet
}
const isCustomPrice =
item_.is_custom_price ?? isDefined(item?.unit_price)
const input: PrepareLineItemDataInput = {
item: item_,
variant: variant,