Inventory Kits

In this guide, you'll learn how inventory kits can be used in the Medusa application to support use cases like multi-part products, bundled products, and shared inventory across products.

What is an Inventory Kit?#

An inventory kit is a collection of inventory items that are linked to a single product variant. These inventory items can be used to represent different parts of a product, or to represent a bundle of products.

The Medusa application links inventory items from the Inventory Module to product variants in the Product Module. Each variant can have multiple inventory items, and these inventory items can be re-used or shared across variants.

Using inventory kits, you can implement use cases like:

  • Multi-part products: A product that consists of multiple parts, each with its own inventory item.
  • Bundled products: A product that is sold as a bundle, where each variant in the bundle product can re-use the inventory items of another product that should be sold as part of the bundle.

Multi-Part Products#

Consider your store sells bicycles that consist of a frame, wheels, and seats, and you want to manage the inventory of these parts separately.

To implement this in Medusa, you can:

  • Create inventory items for each of the different parts.
  • For each bicycle product, add a variant whose inventory kit consists of the inventory items of each of the parts.

Then, whenever a customer purchases a bicycle, the inventory of each part is updated accordingly. You can also use the required_quantity of the variant's inventory items to set how much quantity is consumed of the part's inventory when a bicycle is sold. For example, the bicycle's wheels require 2 wheels inventory items to be sold when a bicycle is sold.

Diagram showcasing how a variant is linked to multi-part inventory items

Create Multi-Part Product#

Using the Medusa Admin, you can create a multi-part product by creating its inventory items first, then assigning these inventory items to the product's variant(s).

Using workflows, you can implement this by first creating the inventory items:

Code
1import { 2  createInventoryItemsWorkflow, 3  useQueryGraphStep4} from "@medusajs/medusa/core-flows"5import { createWorkflow } from "@medusajs/framework/workflows-sdk"6
7export const createMultiPartProductsWorkflow = createWorkflow(8  "create-multi-part-products",9  () => {10    // Alternatively, you can create a stock location11    const { data: stockLocations } = useQueryGraphStep({12      entity: "stock_location",13      fields: ["*"],14      filters: {15        name: "European Warehouse"16      }17    })18
19    const inventoryItems = createInventoryItemsWorkflow.runAsStep({20      input: {21        items: [22          {23            sku: "FRAME",24            title: "Frame",25            location_levels: [26              {27                stocked_quantity: 100,28                location_id: stockLocations[0].id29              }30            ]31          },32          {33            sku: "WHEEL",34            title: "Wheel",35            location_levels: [36              {37                stocked_quantity: 100,38                location_id: stockLocations[0].id39              }40            ]41          },42          {43            sku: "SEAT",44            title: "Seat",45            location_levels: [46              {47                stocked_quantity: 100,48                location_id: stockLocations[0].id49              }50            ]51          }52        ]53      }54    })55
56    // TODO create the product57  }58)

You start by retrieving the stock location to create the inventory items in. Alternatively, you can create a stock location.

Then, you create the inventory items that the product variant consists of.

Next, create the product and pass the inventory item's IDs to the product's variant:

Code
1import { 2  // ...3  transform4} from "@medusajs/framework/workflows-sdk"5import { 6  // ...7  createProductsWorkflow8} from "@medusajs/medusa/core-flows"9
10export const createMultiPartProductsWorkflow = createWorkflow(11  "create-multi-part-products",12  () => {13    // ...14
15    const inventoryItemIds = transform({16      inventoryItems17    }, (data) => {18      return data.inventoryItems.map((inventoryItem) => {19        return {20          inventory_item_id: inventoryItem.id,21          // can also specify required_quantity22        }23      })24    })25
26    const products = createProductsWorkflow.runAsStep({27      input: {28        products: [29          {30            title: "Bicycle",31            variants: [32              {33                title: "Bicycle - Small",34                prices: [35                  {36                    amount: 100,37                    currency_code: "usd"38                  }39                ],40                options: {41                  "Default Option": "Default Variant"42                },43                inventory_items: inventoryItemIds44              }45            ],46            options: [47              {48                title: "Default Option",49                values: ["Default Variant"]50              }51            ]52          }53        ]54      }55    })56  }57)

You prepare the inventory item IDs to pass to the variant using transform from the Workflows SDK, then pass these IDs to the created product's variant.

You can now execute the workflow in API routes, scheduled jobs, or subscribers.


Bundled Products#

Consider you have three products: shirt, pants, and shoes. You sell those products separately, but you also want to offer them as a bundle.

Diagram showcasing products each having their own variants and inventory

You can do that by creating a product, where each variant re-uses the inventory items of each of the shirt, pants, and shoes products.

Then, when the bundled product's variant is purchased, the inventory quantity of the associated inventory items are updated.

Diagram showcasing a bundled product using the same inventory as the products part of the bundle

Create Bundled Product#

You can create a bundled product in the Medusa Admin by creating the products part of the bundle first, each having its own inventory items. Then, you create the bundled product whose variant(s) have inventory kits composed of inventory items from each of the products part of the bundle.

Using workflows, you can implement this by first creating the products part of the bundle:

Code
1import { 2  createWorkflow,3} from "@medusajs/framework/workflows-sdk"4import { 5  createProductsWorkflow,6} from "@medusajs/medusa/core-flows"7
8export const createBundledProducts = createWorkflow(9  "create-bundled-products",10  () => {11    const products = createProductsWorkflow.runAsStep({12      input: {13        products: [14          {15            title: "Shirt",16            variants: [17              {18                title: "Shirt",19                prices: [20                  {21                    amount: 10,22                    currency_code: "usd"23                  }24                ],25                options: {26                  "Default Option": "Default Variant"27                },28                manage_inventory: true29              }30            ],31            options: [32              {33                title: "Default Option",34                values: ["Default Variant"]35              }36            ]37          },38          {39            title: "Pants",40            variants: [41              {42                title: "Pants",43                prices: [44                  {45                    amount: 10,46                    currency_code: "usd"47                  }48                ],49                options: {50                  "Default Option": "Default Variant"51                },52                manage_inventory: true53              }54            ],55            options: [56              {57                title: "Default Option",58                values: ["Default Variant"]59              }60            ]61          },62          {63            title: "Shoes",64            variants: [65              {66                title: "Shoes",67                prices: [68                  {69                    amount: 10,70                    currency_code: "usd"71                  }72                ],73                options: {74                  "Default Option": "Default Variant"75                },76                manage_inventory: true77              }78            ],79            options: [80              {81                title: "Default Option",82                values: ["Default Variant"]83              }84            ]85          }86        ]87      }88    })89
90    // TODO re-retrieve with inventory91  }92)

You create three products and enable manage_inventory for their variants, which will create a default inventory item. You can also create the inventory item first for more control over the quantity as explained in the previous section.

Next, retrieve the products again but with variant information:

Code
1import { 2  // ...3  transform4} from "@medusajs/framework/workflows-sdk"5import { 6  useQueryGraphStep7} from "@medusajs/medusa/core-flows"8
9export const createBundledProducts = createWorkflow(10  "create-bundled-products",11  () => {12    // ...13    const productIds = transform({14      products15    }, (data) => data.products.map((product) => product.id))16
17    // @ts-ignore18    const { data: productsWithInventory } = useQueryGraphStep({19      entity: "product",20      fields: [21        "variants.*",22        "variants.inventory_items.*"23      ],24      filters: {25        id: productIds26      }27    })28
29    const inventoryItemIds = transform({30      productsWithInventory31    }, (data) => {32      return data.productsWithInventory.map((product) => {33        return {34          inventory_item_id: product.variants[0].inventory_items?.[0]?.inventory_item_id35        }36      })37    })38
39    // create bundled product40  }41)

Using Query, you retrieve the product again with the inventory items of each variant. Then, you prepare the inventory items to pass to the bundled product's variant.

Finally, create the bundled product:

Code
1export const createBundledProducts = createWorkflow(2  "create-bundled-products",3  () => {4    // ...5    const bundledProduct = createProductsWorkflow.runAsStep({6      input: {7        products: [8          {9            title: "Bundled Clothes",10            variants: [11              {12                title: "Bundle",13                prices: [14                  {15                    amount: 30,16                    currency_code: "usd"17                  }18                ],19                options: {20                  "Default Option": "Default Variant"21                },22                inventory_items: inventoryItemIds,23              }24            ],25            options: [26              {27                title: "Default Option",28                values: ["Default Variant"]29              }30            ]31          }32        ]33      }34    }).config({ name: "create-bundled-product" })35  }36)

The bundled product has the same inventory items as those of the products part of the bundle.

You can now execute the workflow in API routes, scheduled jobs, or subscribers.

Was this page helpful?
Edit this page