feat: Confirm inventory in create cart workflow (#6635)

This commit is contained in:
Oli Juhl
2024-03-13 18:24:08 +01:00
committed by GitHub
parent b78f863d80
commit 02e784ce78
11 changed files with 652 additions and 102 deletions

View File

@@ -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"],

View File

@@ -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,