medusajs / medusa

The world's most flexible commerce platform.
https://medusajs.com
MIT License
25.58k stars 2.55k forks source link

Inconsistent inventory_quantity in ProductVariant with multiple locations #6277

Open lucaslrolim opened 9 months ago

lucaslrolim commented 9 months ago

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:

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

  1. Install the inventory and stock location modules.
  2. Configure two distinct locations.
  3. Create a product with a single variant.
  4. Navigate to "Manage Inventory" and allocate inventory across both locations (100 items in the first location and 200 in the second).
  5. Save the configurations.
  6. 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

image

image

image

srindom commented 8 months ago

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.

lucaslrolim commented 8 months ago

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
}
]
}
}
alsherif-khalaf commented 8 months ago

I have the same issue , should we use custom endpoint ?

alsherif-khalaf commented 8 months ago

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

Bernix01 commented 8 months ago

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.

alsherif-khalaf commented 8 months ago

I found it is very hard to understand how to get the stock locations inventory in the store front

lexvz14 commented 8 months ago

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.

sumanchy88 commented 4 months ago

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