medusa
medusa copied to clipboard
Inconsistent inventory_quantity in ProductVariant with multiple locations
Bug report
Describe the bug
When utilizing the inventory
and stocklocation
modules, I've encountered an inconsistency with the inventory_quantity
attribute on the ProductVariant object. Specifically, my objective is to retrieve inventory quantities across different locations via the /store/product endpoint. However, the inventory_quantity fails to accurately reflect the stock levels set through the Admin Dashboard.
Despite correctly assigning inventory quantities for a variant across multiple locations, the inventory_quantity consistently returns 0 when queried through the /store/product/{id} route. This discrepancy does not align with the values observed directly in the raw product data, which accurately reflect the inventory levels as expected.
I want help to understand:
- Is this discrepancy indicative of a bug, or is there a configuration step I have overlooked?
- What approach is recommended for accurately accessing inventory quantities for each location through the product route?
System information
Medusa version (including plugins):
"@medusajs/admin": "7.1.5", "@medusajs/inventory": "^1.11.5", "@medusajs/medusa": "^1.20.1", "@medusajs/stock-location": "^1.11.4" Node.js version: 18.17.0 Database: 14.10 Operating system: Ventura 13.4
Steps to reproduce the behavior
- Install the inventory and stock location modules.
- Configure two distinct locations.
- Create a product with a single variant.
- Navigate to "Manage Inventory" and allocate inventory across both locations (100 items in the first location and 200 in the second).
- Save the configurations.
- Inspect the inventory_quantity attribute for discrepancies.
Expected behavior
Bug: The inventory_quantity should accurately aggregate the stock levels across all specified locations for a given variant.
Enhancement Suggestion: Ideally, the API response should also include a detailed breakdown of inventory quantities per location, enabling more granular inventory management.
Screenshots
Have you set up a sales channel associated with your inventory locations?
The inventory quantity on product variants will be calculated based on the locations associated with the customer's sales channel when using the multi-warehouse inventory modules. If you haven't associated any locations with your sales channel that would make your products show up as out of stock.
Hi @srindom
Yes, I have associated it with sales channels. In the route /admin/products
the total number of the products is right, but I do not understand the difference between the /store
and /admin
contexts. Additionally, I'm still not able to list the quantity by location.
I added some details on Discord: https://discord.com/channels/876835651130097704/1203083434692448266
Result of http://localhost:9000/admin/products/prod_01HNDBWXCHSF1C0BNSP2N6C6QE
{
"product": {
"id": "prod_01HNDBWXCHSF1C0BNSP2N6C6QE",
"created_at": "2024-01-30T14:20:47.025Z",
"updated_at": "2024-02-06T14:35:22.382Z",
"deleted_at": null,
"title": "My Product",
"subtitle": "",
"description": "Justa. test",
"handle": "my-test-product",
"is_giftcard": false,
"status": "published",
"thumbnail": null,
"weight": null,
"length": null,
"height": null,
"width": null,
"hs_code": null,
"origin_country": null,
"mid_code": null,
"material": "",
"collection_id": null,
"type_id": null,
"discountable": true,
"external_id": null,
"metadata": {},
"categories": [],
"collection": null,
"images": [],
"options": [
{
"id": "opt_01HNDBWXVT89F6TZ8HRKA3WSTJ",
"created_at": "2024-01-30T14:20:47.025Z",
"updated_at": "2024-01-30T19:42:17.314Z",
"deleted_at": null,
"title": "My Attribute",
"product_id": "prod_01HNDBWXCHSF1C0BNSP2N6C6QE",
"metadata": null
}
],
"profiles": [
{
"id": "sp_01HDSNE1WPD0ZXD0PS0BB46Y5K",
"created_at": "2023-10-27T22:52:45.186Z",
"updated_at": "2023-10-27T22:52:45.186Z",
"deleted_at": null,
"name": "Default Shipping Profile",
"type": "default",
"metadata": null
}
],
"profile": {
"id": "sp_01HDSNE1WPD0ZXD0PS0BB46Y5K",
"created_at": "2023-10-27T22:52:45.186Z",
"updated_at": "2023-10-27T22:52:45.186Z",
"deleted_at": null,
"name": "Default Shipping Profile",
"type": "default",
"metadata": null
},
"profile_id": "sp_01HDSNE1WPD0ZXD0PS0BB46Y5K",
"sales_channels": [
{
"id": "sc_01HDSNE1Y6YSAJJYTGZMMJ3N4Q",
"created_at": "2023-10-27T22:52:45.186Z",
"updated_at": "2023-10-27T22:52:45.186Z",
"deleted_at": null,
"name": "Default Sales Channel",
"description": "Created by Medusa",
"is_disabled": false,
"metadata": null
},
{
"id": "sc_01HNE7QHZQ2MMMH4T4FH5F0M55",
"created_at": "2024-01-30T22:27:12.059Z",
"updated_at": "2024-01-30T22:27:12.059Z",
"deleted_at": null,
"name": "Osasco",
"description": null,
"is_disabled": false,
"metadata": null
},
{
"id": "sc_01HNE7P2RT9VKMHW0PMWTJ9N7A",
"created_at": "2024-01-30T22:26:23.703Z",
"updated_at": "2024-01-30T22:26:41.624Z",
"deleted_at": null,
"name": "São Paulo Capital",
"description": null,
"is_disabled": false,
"metadata": null
}
],
"tags": [],
"type": null,
"variants": [
{
"id": "variant_01HNDBWYTE9HRW4TF881GD1TDY",
"created_at": "2024-01-30T14:20:47.025Z",
"updated_at": "2024-01-30T22:42:14.551Z",
"deleted_at": null,
"title": "My Variant I",
"product_id": "prod_01HNDBWXCHSF1C0BNSP2N6C6QE",
"sku": null,
"barcode": null,
"ean": null,
"upc": null,
"variant_rank": 0,
"inventory_quantity": 250,
"allow_backorder": false,
"manage_inventory": true,
"hs_code": null,
"origin_country": null,
"mid_code": null,
"material": null,
"weight": null,
"length": null,
"height": null,
"width": null,
"metadata": {},
"options": [
{
"id": "optval_01HNDBWYTEYZ5DQ6VHG5Q2WZWB",
"created_at": "2024-01-30T14:20:47.025Z",
"updated_at": "2024-01-30T14:20:47.025Z",
"deleted_at": null,
"value": "1",
"option_id": "opt_01HNDBWXVT89F6TZ8HRKA3WSTJ",
"variant_id": "variant_01HNDBWYTE9HRW4TF881GD1TDY",
"metadata": null
}
],
"prices": [
{
"id": "ma_01HNDBWZXGC2V7PPP7YZY1RMPA",
"created_at": "2024-01-30T14:20:47.025Z",
"updated_at": "2024-01-30T14:20:47.025Z",
"deleted_at": null,
"currency_code": "brl",
"amount": 200,
"min_quantity": null,
"max_quantity": null,
"price_list_id": null,
"region_id": null,
"price_list": null,
"variant_id": "variant_01HNDBWYTE9HRW4TF881GD1TDY"
}
],
"original_price": null,
"calculated_price": null,
"original_price_incl_tax": null,
"calculated_price_incl_tax": null,
"original_tax": null,
"calculated_tax": null,
"tax_rates": null,
"purchasable": true
}
]
}
}
I have the same issue , should we use custom endpoint ?
Hi @srindom
Yes, I have associated it with sales channels. In the route
/admin/products
the total number of the products is right, but I do not understand the difference between the/store
and/admin
contexts. Additionally, I'm still not able to list the quantity by location.I added some details on Discord: https://discord.com/channels/876835651130097704/1203083434692448266
Result of http://localhost:9000/admin/products/prod_01HNDBWXCHSF1C0BNSP2N6C6QE
{ "product": { "id": "prod_01HNDBWXCHSF1C0BNSP2N6C6QE", "created_at": "2024-01-30T14:20:47.025Z", "updated_at": "2024-02-06T14:35:22.382Z", "deleted_at": null, "title": "My Product", "subtitle": "", "description": "Justa. test", "handle": "my-test-product", "is_giftcard": false, "status": "published", "thumbnail": null, "weight": null, "length": null, "height": null, "width": null, "hs_code": null, "origin_country": null, "mid_code": null, "material": "", "collection_id": null, "type_id": null, "discountable": true, "external_id": null, "metadata": {}, "categories": [], "collection": null, "images": [], "options": [ { "id": "opt_01HNDBWXVT89F6TZ8HRKA3WSTJ", "created_at": "2024-01-30T14:20:47.025Z", "updated_at": "2024-01-30T19:42:17.314Z", "deleted_at": null, "title": "My Attribute", "product_id": "prod_01HNDBWXCHSF1C0BNSP2N6C6QE", "metadata": null } ], "profiles": [ { "id": "sp_01HDSNE1WPD0ZXD0PS0BB46Y5K", "created_at": "2023-10-27T22:52:45.186Z", "updated_at": "2023-10-27T22:52:45.186Z", "deleted_at": null, "name": "Default Shipping Profile", "type": "default", "metadata": null } ], "profile": { "id": "sp_01HDSNE1WPD0ZXD0PS0BB46Y5K", "created_at": "2023-10-27T22:52:45.186Z", "updated_at": "2023-10-27T22:52:45.186Z", "deleted_at": null, "name": "Default Shipping Profile", "type": "default", "metadata": null }, "profile_id": "sp_01HDSNE1WPD0ZXD0PS0BB46Y5K", "sales_channels": [ { "id": "sc_01HDSNE1Y6YSAJJYTGZMMJ3N4Q", "created_at": "2023-10-27T22:52:45.186Z", "updated_at": "2023-10-27T22:52:45.186Z", "deleted_at": null, "name": "Default Sales Channel", "description": "Created by Medusa", "is_disabled": false, "metadata": null }, { "id": "sc_01HNE7QHZQ2MMMH4T4FH5F0M55", "created_at": "2024-01-30T22:27:12.059Z", "updated_at": "2024-01-30T22:27:12.059Z", "deleted_at": null, "name": "Osasco", "description": null, "is_disabled": false, "metadata": null }, { "id": "sc_01HNE7P2RT9VKMHW0PMWTJ9N7A", "created_at": "2024-01-30T22:26:23.703Z", "updated_at": "2024-01-30T22:26:41.624Z", "deleted_at": null, "name": "São Paulo Capital", "description": null, "is_disabled": false, "metadata": null } ], "tags": [], "type": null, "variants": [ { "id": "variant_01HNDBWYTE9HRW4TF881GD1TDY", "created_at": "2024-01-30T14:20:47.025Z", "updated_at": "2024-01-30T22:42:14.551Z", "deleted_at": null, "title": "My Variant I", "product_id": "prod_01HNDBWXCHSF1C0BNSP2N6C6QE", "sku": null, "barcode": null, "ean": null, "upc": null, "variant_rank": 0, "inventory_quantity": 250, "allow_backorder": false, "manage_inventory": true, "hs_code": null, "origin_country": null, "mid_code": null, "material": null, "weight": null, "length": null, "height": null, "width": null, "metadata": {}, "options": [ { "id": "optval_01HNDBWYTEYZ5DQ6VHG5Q2WZWB", "created_at": "2024-01-30T14:20:47.025Z", "updated_at": "2024-01-30T14:20:47.025Z", "deleted_at": null, "value": "1", "option_id": "opt_01HNDBWXVT89F6TZ8HRKA3WSTJ", "variant_id": "variant_01HNDBWYTE9HRW4TF881GD1TDY", "metadata": null } ], "prices": [ { "id": "ma_01HNDBWZXGC2V7PPP7YZY1RMPA", "created_at": "2024-01-30T14:20:47.025Z", "updated_at": "2024-01-30T14:20:47.025Z", "deleted_at": null, "currency_code": "brl", "amount": 200, "min_quantity": null, "max_quantity": null, "price_list_id": null, "region_id": null, "price_list": null, "variant_id": "variant_01HNDBWYTE9HRW4TF881GD1TDY" } ], "original_price": null, "calculated_price": null, "original_price_incl_tax": null, "calculated_price_incl_tax": null, "original_tax": null, "calculated_tax": null, "tax_rates": null, "purchasable": true } ] } }
same for me
I believe the store is linked to the default sales channel in some way, I can confirm setting the default sales channel enables the store endpoint quantity.
I found it is very hard to understand how to get the stock locations inventory in the store front
Have you found a way to adjust the default_sales_channel? I ran into a validation error on the API, as the default_sales_channel_id is not part of the allowed body fields for the POST /store request.
@lucaslrolim - I am also facing the same issue with mulitple locations and multiple sales channel. The inventory quantity is returned as 0 when using publishable key to retrive the products. By any chance are you passing publishable key to pull the products?