feat: Confirm inventory in create cart workflow (#6635)
This commit is contained in:
@@ -18,6 +18,7 @@ import {
|
||||
ICartModuleService,
|
||||
ICustomerModuleService,
|
||||
IFulfillmentModuleService,
|
||||
IInventoryServiceNext,
|
||||
IPaymentModuleService,
|
||||
IPricingModuleService,
|
||||
IProductModuleService,
|
||||
@@ -45,6 +46,8 @@ medusaIntegrationTestRunner({
|
||||
let productModule: IProductModuleService
|
||||
let pricingModule: IPricingModuleService
|
||||
let paymentModule: IPaymentModuleService
|
||||
let inventoryModule: IInventoryServiceNext
|
||||
let stockLocationModule: IStockLocationServiceNext
|
||||
let fulfillmentModule: IFulfillmentModuleService
|
||||
let locationModule: IStockLocationServiceNext
|
||||
let remoteLink, remoteQuery
|
||||
@@ -64,6 +67,10 @@ medusaIntegrationTestRunner({
|
||||
productModule = appContainer.resolve(ModuleRegistrationName.PRODUCT)
|
||||
pricingModule = appContainer.resolve(ModuleRegistrationName.PRICING)
|
||||
paymentModule = appContainer.resolve(ModuleRegistrationName.PAYMENT)
|
||||
inventoryModule = appContainer.resolve(ModuleRegistrationName.INVENTORY)
|
||||
stockLocationModule = appContainer.resolve(
|
||||
ModuleRegistrationName.STOCK_LOCATION
|
||||
)
|
||||
fulfillmentModule = appContainer.resolve(
|
||||
ModuleRegistrationName.FULFILLMENT
|
||||
)
|
||||
@@ -97,6 +104,10 @@ medusaIntegrationTestRunner({
|
||||
name: "Webshop",
|
||||
})
|
||||
|
||||
const location = await stockLocationModule.create({
|
||||
name: "Warehouse",
|
||||
})
|
||||
|
||||
const [product] = await productModule.create([
|
||||
{
|
||||
title: "Test product",
|
||||
@@ -108,6 +119,19 @@ medusaIntegrationTestRunner({
|
||||
},
|
||||
])
|
||||
|
||||
const inventoryItem = await inventoryModule.create({
|
||||
sku: "inv-1234",
|
||||
})
|
||||
|
||||
await inventoryModule.createInventoryLevels([
|
||||
{
|
||||
inventory_item_id: inventoryItem.id,
|
||||
location_id: location.id,
|
||||
stocked_quantity: 2,
|
||||
reserved_quantity: 0,
|
||||
},
|
||||
])
|
||||
|
||||
const priceSet = await pricingModule.create({
|
||||
prices: [
|
||||
{
|
||||
@@ -119,13 +143,29 @@ medusaIntegrationTestRunner({
|
||||
|
||||
await remoteLink.create([
|
||||
{
|
||||
productService: {
|
||||
[Modules.PRODUCT]: {
|
||||
variant_id: product.variants[0].id,
|
||||
},
|
||||
pricingService: {
|
||||
[Modules.PRICING]: {
|
||||
price_set_id: priceSet.id,
|
||||
},
|
||||
},
|
||||
{
|
||||
[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,
|
||||
},
|
||||
},
|
||||
])
|
||||
|
||||
const { result } = await createCartWorkflow(appContainer).run({
|
||||
@@ -184,6 +224,99 @@ medusaIntegrationTestRunner({
|
||||
])
|
||||
})
|
||||
|
||||
it("should throw if variants are out of stock", async () => {
|
||||
const salesChannel = await scModuleService.create({
|
||||
name: "Webshop",
|
||||
})
|
||||
|
||||
const location = await stockLocationModule.create({
|
||||
name: "Warehouse",
|
||||
})
|
||||
|
||||
const [product] = await productModule.create([
|
||||
{
|
||||
title: "Test product",
|
||||
variants: [
|
||||
{
|
||||
title: "Test variant",
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
const inventoryItem = await inventoryModule.create({
|
||||
sku: "inv-1234",
|
||||
})
|
||||
|
||||
await inventoryModule.createInventoryLevels([
|
||||
{
|
||||
inventory_item_id: inventoryItem.id,
|
||||
location_id: location.id,
|
||||
stocked_quantity: 2,
|
||||
reserved_quantity: 2,
|
||||
},
|
||||
])
|
||||
|
||||
const priceSet = await pricingModule.create({
|
||||
prices: [
|
||||
{
|
||||
amount: 3000,
|
||||
currency_code: "usd",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
await remoteLink.create([
|
||||
{
|
||||
[Modules.PRODUCT]: {
|
||||
variant_id: product.variants[0].id,
|
||||
},
|
||||
[Modules.PRICING]: {
|
||||
price_set_id: priceSet.id,
|
||||
},
|
||||
},
|
||||
{
|
||||
[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,
|
||||
},
|
||||
},
|
||||
])
|
||||
|
||||
const { errors } = await createCartWorkflow(appContainer).run({
|
||||
input: {
|
||||
sales_channel_id: salesChannel.id,
|
||||
items: [
|
||||
{
|
||||
variant_id: product.variants[0].id,
|
||||
quantity: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
throwOnError: false,
|
||||
})
|
||||
|
||||
expect(errors).toEqual([
|
||||
{
|
||||
action: "confirm-inventory-step",
|
||||
handlerType: "invoke",
|
||||
error: new Error(
|
||||
"Some variant does not have the required inventory"
|
||||
),
|
||||
},
|
||||
])
|
||||
})
|
||||
|
||||
it("should throw if sales channel is disabled", async () => {
|
||||
const salesChannel = await scModuleService.create({
|
||||
name: "Webshop",
|
||||
@@ -283,8 +416,17 @@ medusaIntegrationTestRunner({
|
||||
|
||||
describe("AddToCartWorkflow", () => {
|
||||
it("should add item to cart", async () => {
|
||||
const salesChannel = await scModuleService.create({
|
||||
name: "Webshop",
|
||||
})
|
||||
|
||||
const location = await stockLocationModule.create({
|
||||
name: "Warehouse",
|
||||
})
|
||||
|
||||
let cart = await cartModuleService.create({
|
||||
currency_code: "usd",
|
||||
sales_channel_id: salesChannel.id,
|
||||
})
|
||||
|
||||
const [product] = await productModule.create([
|
||||
@@ -298,6 +440,19 @@ medusaIntegrationTestRunner({
|
||||
},
|
||||
])
|
||||
|
||||
const inventoryItem = await inventoryModule.create({
|
||||
sku: "inv-1234",
|
||||
})
|
||||
|
||||
await inventoryModule.createInventoryLevels([
|
||||
{
|
||||
inventory_item_id: inventoryItem.id,
|
||||
location_id: location.id,
|
||||
stocked_quantity: 2,
|
||||
reserved_quantity: 0,
|
||||
},
|
||||
])
|
||||
|
||||
const priceSet = await pricingModule.create({
|
||||
prices: [
|
||||
{
|
||||
@@ -309,13 +464,29 @@ medusaIntegrationTestRunner({
|
||||
|
||||
await remoteLink.create([
|
||||
{
|
||||
productService: {
|
||||
[Modules.PRODUCT]: {
|
||||
variant_id: product.variants[0].id,
|
||||
},
|
||||
pricingService: {
|
||||
[Modules.PRICING]: {
|
||||
price_set_id: priceSet.id,
|
||||
},
|
||||
},
|
||||
{
|
||||
[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.retrieve(cart.id, {
|
||||
@@ -354,8 +525,17 @@ medusaIntegrationTestRunner({
|
||||
})
|
||||
|
||||
it("should throw if no price sets for variant exist", async () => {
|
||||
const cart = await cartModuleService.create({
|
||||
const salesChannel = await scModuleService.create({
|
||||
name: "Webshop",
|
||||
})
|
||||
|
||||
const location = await stockLocationModule.create({
|
||||
name: "Warehouse",
|
||||
})
|
||||
|
||||
let cart = await cartModuleService.create({
|
||||
currency_code: "usd",
|
||||
sales_channel_id: salesChannel.id,
|
||||
})
|
||||
|
||||
const [product] = await productModule.create([
|
||||
@@ -369,6 +549,38 @@ medusaIntegrationTestRunner({
|
||||
},
|
||||
])
|
||||
|
||||
const inventoryItem = await inventoryModule.create({
|
||||
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,
|
||||
},
|
||||
},
|
||||
])
|
||||
|
||||
const { errors } = await addToCartWorkflow(appContainer).run({
|
||||
input: {
|
||||
items: [
|
||||
@@ -423,6 +635,14 @@ medusaIntegrationTestRunner({
|
||||
|
||||
describe("updateLineItemInCartWorkflow", () => {
|
||||
it("should update item in cart", async () => {
|
||||
const salesChannel = await scModuleService.create({
|
||||
name: "Webshop",
|
||||
})
|
||||
|
||||
const location = await stockLocationModule.create({
|
||||
name: "Warehouse",
|
||||
})
|
||||
|
||||
const [product] = await productModule.create([
|
||||
{
|
||||
title: "Test product",
|
||||
@@ -434,6 +654,19 @@ medusaIntegrationTestRunner({
|
||||
},
|
||||
])
|
||||
|
||||
const inventoryItem = await inventoryModule.create({
|
||||
sku: "inv-1234",
|
||||
})
|
||||
|
||||
await inventoryModule.createInventoryLevels([
|
||||
{
|
||||
inventory_item_id: inventoryItem.id,
|
||||
location_id: location.id,
|
||||
stocked_quantity: 2,
|
||||
reserved_quantity: 0,
|
||||
},
|
||||
])
|
||||
|
||||
const priceSet = await pricingModule.create({
|
||||
prices: [
|
||||
{
|
||||
@@ -445,17 +678,34 @@ medusaIntegrationTestRunner({
|
||||
|
||||
await remoteLink.create([
|
||||
{
|
||||
productService: {
|
||||
[Modules.PRODUCT]: {
|
||||
variant_id: product.variants[0].id,
|
||||
},
|
||||
pricingService: {
|
||||
[Modules.PRICING]: {
|
||||
price_set_id: priceSet.id,
|
||||
},
|
||||
},
|
||||
{
|
||||
[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,
|
||||
},
|
||||
},
|
||||
])
|
||||
|
||||
let cart = await cartModuleService.create({
|
||||
currency_code: "usd",
|
||||
sales_channel_id: salesChannel.id,
|
||||
items: [
|
||||
{
|
||||
variant_id: product.variants[0].id,
|
||||
@@ -473,7 +723,9 @@ medusaIntegrationTestRunner({
|
||||
|
||||
const item = cart.items?.[0]!
|
||||
|
||||
await updateLineItemInCartWorkflow(appContainer).run({
|
||||
const { errors } = await updateLineItemInCartWorkflow(
|
||||
appContainer
|
||||
).run({
|
||||
input: {
|
||||
cart,
|
||||
item,
|
||||
@@ -510,6 +762,14 @@ medusaIntegrationTestRunner({
|
||||
},
|
||||
})
|
||||
|
||||
const salesChannel = await scModuleService.create({
|
||||
name: "Webshop",
|
||||
})
|
||||
|
||||
const location = await stockLocationModule.create({
|
||||
name: "Warehouse",
|
||||
})
|
||||
|
||||
const [product] = await productModule.create([
|
||||
{
|
||||
title: "Test product",
|
||||
@@ -521,6 +781,55 @@ medusaIntegrationTestRunner({
|
||||
},
|
||||
])
|
||||
|
||||
const inventoryItem = await inventoryModule.create({
|
||||
sku: "inv-1234",
|
||||
})
|
||||
|
||||
await inventoryModule.createInventoryLevels([
|
||||
{
|
||||
inventory_item_id: inventoryItem.id,
|
||||
location_id: location.id,
|
||||
stocked_quantity: 2,
|
||||
reserved_quantity: 0,
|
||||
},
|
||||
])
|
||||
|
||||
const priceSet = await pricingModule.create({
|
||||
prices: [
|
||||
{
|
||||
amount: 3000,
|
||||
currency_code: "usd",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
await remoteLink.create([
|
||||
{
|
||||
[Modules.PRODUCT]: {
|
||||
variant_id: product.variants[0].id,
|
||||
},
|
||||
[Modules.PRICING]: {
|
||||
price_set_id: priceSet.id,
|
||||
},
|
||||
},
|
||||
{
|
||||
[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,
|
||||
},
|
||||
},
|
||||
])
|
||||
|
||||
let cart = await cartModuleService.create({
|
||||
currency_code: "usd",
|
||||
items: [
|
||||
@@ -533,26 +842,6 @@ medusaIntegrationTestRunner({
|
||||
],
|
||||
})
|
||||
|
||||
const priceSet = await pricingModule.create({
|
||||
prices: [
|
||||
{
|
||||
amount: 5000,
|
||||
currency_code: "usd",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
await remoteLink.create([
|
||||
{
|
||||
productService: {
|
||||
variant_id: product.variants[0].id,
|
||||
},
|
||||
pricingService: {
|
||||
price_set_id: priceSet.id,
|
||||
},
|
||||
},
|
||||
])
|
||||
|
||||
cart = await cartModuleService.retrieve(cart.id, {
|
||||
select: ["id", "region_id", "currency_code"],
|
||||
relations: ["items", "items.variant_id", "items.metadata"],
|
||||
|
||||
@@ -80,9 +80,11 @@ medusaIntegrationTestRunner({
|
||||
title: "Test product",
|
||||
variants: [
|
||||
{
|
||||
manage_inventory: false,
|
||||
title: "Test variant",
|
||||
},
|
||||
{
|
||||
manage_inventory: false,
|
||||
title: "Test variant 2",
|
||||
},
|
||||
],
|
||||
@@ -178,10 +180,16 @@ medusaIntegrationTestRunner({
|
||||
const [product] = await productModule.create([
|
||||
{
|
||||
title: "Test product default tax",
|
||||
variants: [{ title: "Test variant default tax" }],
|
||||
variants: [
|
||||
{ title: "Test variant default tax", manage_inventory: false },
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
const salesChannel = await scModule.create({
|
||||
name: "Webshop",
|
||||
})
|
||||
|
||||
const [priceSet] = await pricingModule.create([
|
||||
{ prices: [{ amount: 3000, currency_code: "usd" }] },
|
||||
])
|
||||
@@ -204,6 +212,7 @@ medusaIntegrationTestRunner({
|
||||
province: "NY",
|
||||
postal_code: "94016",
|
||||
},
|
||||
sales_channel_id: salesChannel.id,
|
||||
items: [
|
||||
{
|
||||
quantity: 1,
|
||||
@@ -789,25 +798,32 @@ medusaIntegrationTestRunner({
|
||||
email: "tony@stark-industries.com",
|
||||
})
|
||||
|
||||
const salesChannel = await scModule.create({
|
||||
name: "Webshop",
|
||||
})
|
||||
|
||||
const [productWithSpecialTax] = await productModule.create([
|
||||
{
|
||||
// This product ID is setup in the tax structure fixture (setupTaxStructure)
|
||||
id: "product_id_1",
|
||||
title: "Test product",
|
||||
variants: [{ title: "Test variant" }],
|
||||
variants: [{ title: "Test variant", manage_inventory: false }],
|
||||
} as any,
|
||||
])
|
||||
|
||||
const [productWithDefaultTax] = await productModule.create([
|
||||
{
|
||||
title: "Test product default tax",
|
||||
variants: [{ title: "Test variant default tax" }],
|
||||
variants: [
|
||||
{ title: "Test variant default tax", manage_inventory: false },
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
const cart = await cartModule.create({
|
||||
currency_code: "usd",
|
||||
customer_id: customer.id,
|
||||
sales_channel_id: salesChannel.id,
|
||||
region_id: region.id,
|
||||
shipping_address: {
|
||||
customer_id: customer.id,
|
||||
|
||||
Reference in New Issue
Block a user