inventory icon indicating copy to clipboard operation
inventory copied to clipboard

Magento 2 MSI not updating the salable Quantity Properly and thus customer can order more product than actual available stock.

Open JithinEdathadan opened this issue 4 years ago • 16 comments

Hi Am facing a Tricky issue on Magneto 2.3.3 Opensource edition .

** Preconditions **

1 Magneto 2.3.3 . 2 Multi Store enabled . 3 Multi inventory enabled. 4 Fresh Magneto installed without any custom plugins .

** Summary **

When an inventory is shared among two or more stores the purchase of a product from the store should update the salable quantity of product among other stores which the inventory is shared . The issue is as follows (Explained with an example for ease of understanding ) :

I have Two stores on an magneto admin say Store X and Store Y , one for county X and other for country Y .

I have also 2 Separate Inventory (representing my 2 physical warehouse ) Say Inventory-X and Inventory-Y.

The Store X has access to two inventories Inventory-X and Inventory-Y . Where as . The Store Y has access only access to Inventory-Y .

Now I have a product Test Which is available on both stores . and on Inventory-X it is of quantity 10 and on Inventory-Y it is of quantity 5 .

That is on Store X salable quantity of product Test is 15 and on Store Y salable quantity of product Test is 5 . It is initially correctly set by Magneto Without any issues.

Now comes our real issue :

Now suppose a customer orders 15 product from Store X Then Magneto updates the salable quantity of Store X with 0 , but not updating the salable quantity of Store Y as 0 , which is logical , and thus this allows another customer to place order 5 product Test from Store Y ,Which has already been sold out through Store X .

Steps to reproduce

1 Create Two Stores on am admin Store-1 , Store-1 . 2 Create two different inventories inventory-1 ,inventory-2. 3 Assign stock as follows :- store-1 with inventory-1 and inventory-2 . store-2 with inventory-1 only . 4 Create a product P1 and assign inventory-1 quantity =10 and inventory-2 quantity =5 enble this product for both store-1 and store-2.

5 order 15 products from store-1 . 6 you will also be able to order another 5 product from store-2 , which is not expected.

Expected result

After First Customer done the purchase salable quantity of Store-1 and Sore-2 should have been set as zero , thus not allowing any more purchases on both sores .

Actual result

Salable Quantity of Store-1 only got updated , Salable quantity of Store-2 remains the same thus allowing 5 more product P1 to be purchased from store-2 .

JithinEdathadan avatar Nov 21 '19 17:11 JithinEdathadan

Hi @JithinEdathadan. Thank you for your report. To help us process this issue please make sure that you provided the following information:

  • [ ] Summary of the issue
  • [ ] Information on your environment
  • [ ] Steps to reproduce
  • [ ] Expected and actual results

Please make sure that the issue is reproducible on the vanilla Magento instance following Steps to reproduce. To deploy vanilla Magento instance on our environment, please, add a comment to the issue:

@magento give me 2.3-develop instance - upcoming 2.3.x release

For more details, please, review the Magento Contributor Assistant documentation.

@JithinEdathadan do you confirm that you were able to reproduce the issue on vanilla Magento instance following steps to reproduce?

  • [ ] yes
  • [ ] no

m2-assistant[bot] avatar Nov 21 '19 17:11 m2-assistant[bot]

@magento give me 2.3-develop instance - upcoming 2.3.x release

JithinEdathadan avatar Nov 22 '19 06:11 JithinEdathadan

Hi @JithinEdathadan. Thank you for your request. I'm working on Magento 2.3-develop instance for you

magento-engcom-team avatar Nov 22 '19 06:11 magento-engcom-team

Hi @JithinEdathadan, here is your Magento instance. Admin access: https://i-25691-2-3-develop.instances.magento-community.engineering/admin Login: admin Password: 123123q Instance will be terminated in up to 3 hours.

magento-engcom-team avatar Nov 22 '19 06:11 magento-engcom-team

Hi @magento-engcom-team there is no : Inventory -> Sources and Inventory -> Sources Stocks options available on this instance , so i cannot replicate this issue over this .

image

JithinEdathadan avatar Nov 22 '19 06:11 JithinEdathadan

Hi @engcom-Echo. Thank you for working on this issue. In order to make sure that issue has enough information and ready for development, please read and check the following instruction: :point_down:

  • [ ] 1. Verify that issue has all the required information. (Preconditions, Steps to reproduce, Expected result, Actual result).

    DetailsIf the issue has a valid description, the label Issue: Format is valid will be added to the issue automatically. Please, edit issue description if needed, until label Issue: Format is valid appears.

  • [ ] 2. Verify that issue has a meaningful description and provides enough information to reproduce the issue. If the report is valid, add Issue: Clear Description label to the issue by yourself.

  • [ ] 3. Add Component: XXXXX label(s) to the ticket, indicating the components it may be related to.

  • [ ] 4. Verify that the issue is reproducible on 2.3-develop branch

    Details- Add the comment @magento give me 2.3-develop instance to deploy test instance on Magento infrastructure.
    - If the issue is reproducible on 2.3-develop branch, please, add the label Reproduced on 2.3.x.
    - If the issue is not reproducible, add your comment that issue is not reproducible and close the issue and stop verification process here!

  • [ ] 5. Add label Issue: Confirmed once verification is complete.

  • [ ] 6. Make sure that automatic system confirms that report has been added to the backlog.

m2-assistant[bot] avatar Nov 22 '19 08:11 m2-assistant[bot]

Hi All,

i can confirm this issue because we were testing how reservations works with MSI and everything described by @JithinEdathadan is correct.

The main issue seems to be that reservation are stored by stock_id, while they should be registered by source, so any time a reservation is made on a source (the one from which the stock will be subtracted when the order is shipped) the quantity sold is removed on the salable quantity for each stock that source is connected with.

I think this is a big issue, since right now reservations works correctly only when each stock has its own sources and no sources are shared among stocks.

Bump

MarcoPierozziTriboo avatar Nov 27 '19 16:11 MarcoPierozziTriboo

hey guys @JithinEdathadan @MarcoPierozziTriboo

you are both right, Magento currently does not recommend to assign the same source to multiples Stocks as this may lead to overselling. The main reason for this as @MarcoPierozziTriboo correctly mentioned is the fact that placing an order Magento creates reservation per Stock (not per source). The reason why we've implemented the business logic this way - because our main intention is to make the order placement process as lightweight as possible, and not being dependent on the number of active sources a merchant has configured (we already saw Magento + MSI installations with 400+ active sources).

Having the reservations on the level of stock - we keep order placement and whole storefront operations in general not aware of the sources behind. Thus, the time and complexity of placing the order is constant - O(1), otherwise if we wanted to make source-level reservations - we had to run the Source-Selection algorithm at the time of order placement to determine on which sources we should reserve products and in which quantity. In this case, the time for execution of this algorithm is dependent on the number of active sources assigned to current stock which may be used to fulfill the order. The notation for this complexity could be represented as O(n!). Just imagine if you have 100 sources that may be used for fulfillment, and shopper ordered SKU in Qty=1 - that's 100 different variations. But if the shopper ordered SKU-1 in Qty=10, SKU-2 in Qty=5 and SKU-3 in Qty=20 - the number of permutations is huge! Thus such an approach would not be applicable for big merchants, as it will drastically affect checkout performance.

So, if we want to postpone heavy computations till order processing time (when the performance is not that critical because we already got an order and charged a shopper), we have two choices:

  • overselling (that's what happens now if the single source assigned to multiple stocks )
  • underselling (that might happen if we would create several reservations for different stocks)

Usually underselling is worse than overselling, that's why our out of the box implementation implemented the way see it now. But there are 3rd party extensions which already provide Source Level reservations mechanism which might be run at the order placement time. You can contact @paales for more details. But just take into account that running Source Selection algorithm (SSA) on checkout time might be a good idea if you know in advance that you have just a few sources and SSA would not take a long time for execution. In the opposite case - a merchant may end up with a high rate of abandoned checkouts.

maghamed avatar Dec 05 '19 00:12 maghamed

@paales can you please share the details of the module that was mentioned on the above comment.

JithinJay avatar Dec 18 '19 13:12 JithinJay

We've developed the following module: https://www.reachdigital.nl/en/magento-module-development/magento-2-order-source-reservation-module

The module is commercial and we charge a certain percentage of the initial development costs (so it's more expensive than a standard module). If you're interested, you can contact met at [email protected]

paales avatar Dec 19 '19 10:12 paales

Hi @maghamed, I totally understand you guys try to create a solution that "fits" for all merchants but I will tell you a true story of what happen in real life with a luxuary merchant who almost all the time have the last pieces in stock. As you know in real life we need new customers to have our business growing, so we invest hard on e-marketing, it costs a lot to us to bring new customers to our website and try to create a new story with them. Now imagine we have last pieces and MSI stock is not accurate because you guys decided to oversell?

Our new customer (paid source) we are starting to share a new story was hard to convince because our products are not cheap, as the possibility to place his order, he's happy! A couple of minutes after we see that this order is not exportable to our warehouse because no source has been assigned. Stock was wrong on MSI due to the oversell feature... As we are a luxuary brand we try to have the best customer service ever and we call this customer, we are very sorry for him, we try to sell another product to not lose the sale... This costs a lot for us internally as we are taking time of humans to do so.

Conclusion: he has a very bad experience and will never come back. If we are lucky he won't complain on social network... if we aren't, he will spread the word that our brand is not fair etc, he will also speak with people around. That's very bad for our brand.

This kind of merchants I'm speaking about have not a big volume in term of number of orders but total average order is high. It's where Adobe Commerce earns money.

That's real life, don't forget about this.

jonathanribas avatar Jan 16 '20 07:01 jonathanribas

this is a serious issue @magento-devops

Adel-Magebinary avatar Jun 18 '20 01:06 Adel-Magebinary

I just found this thread and it's indeed a very serious issue. The whole point of having a MSI is because you want to have accurate stock level information on the store per warehouse availability. Both overselling and underselling is bad for the shop and the customer experience. This is a really severe issue for MSI setup that needs attention. Isn't there a way to do the check more efficiently on checkout?

The way you explained there should at least be a configuration option to run the SSA on checkout or on order fulfillment time. At least then it would be more versatile.

I imagine a merchant with 500 daily orders would constantly oversell as it is now

ioweb-gr avatar Nov 09 '20 22:11 ioweb-gr

Totally support this, that's serious. +1 If you assign multiple sources to a store, even if allowed countries (for store and source) are configured properly, it's not taking that constraint into account and allows overselling. We constantly have issues because of that.

We're thinking of splitting up that store so that we can apply a 1:1 relation to source and store. What a pity.

ni-bschmitt avatar Dec 20 '21 14:12 ni-bschmitt

FYI. We've opensourced some stuff a long time ago: https://github.com/ho-nl/magento2-ReachDigital_InventoryOrderSourceReservations

I haven't got an active customer for this functionality, but it should work.

paales avatar Dec 21 '21 12:12 paales

For anyone who has run into this issue, there is a simple workaround.

Looks like Magento decided to keep legacy stock logic alongside MSI. Then it created lots of other bugs and this.

The easiest way to make sure the MSI logic is working perfectly is to create a new source to bypass the hardcoded id 1 of (Default source and default stock) in order to bypass the legacy stock logic.

You can simply create a new stock(id !=1) assigned to a new source (id !=1). Then assign all products to the new source. Then you will find MSI is working as it should.

It has done it for us for the last 12 months without stock related issues.

Adel-Magebinary avatar Jan 25 '22 03:01 Adel-Magebinary