Inventory update v.0.12-0.13


#1

Hello, I want to do some work with inventory and this is my current vision of how it should be. This is not all, just a part which I understand for today).

First of all we need to remember: inventory items could have status and orders could
have status and sometimes these statuses even have the same name, but they are different.

There was an idea to add more statuses to inventory item that it has now (now we have
new, reserved, backorder and in future we absolutely for sure need fulfilled), but I think we don’t need them, because I think inventory logic should be simple (dump) and clear. Statuses like packing etc we could put inside Orders statuses list.

We should move barcode field to inventory items.

We are talking here only about Inventory.

We could look at Inventory flow from two points. From admin point of view and from
customer point of view.

Admin Inventory flow

PDP

Admin could add variants to products (inventory/register fires at this moment). He could add inventoryQuantity to variants. By doing that, he fires inventory/adjust. BUT he can’t decrease inventoryQuantity or remove variant or product after the occurrence of certain conditions.

I like the following idea: If all product’s variants items have status “new”, then admin can remove this product or variant, but if at least one of variant items was reserved (status: “reserved”), after that it is impossible to remove such product with all its variants.

To achieve this we could add new field to product and variant. Lets call it status (just like inventory status field). It could contain several states. For example active - product are in use. This could be default status. Then removed – by that we could mark products/variants which was removed by admin, but they were contain reserved or fulfilled items.

Plus to that we need functionality to remove “dead” carts. Lets say of customer added something to cart and he not ordered this order in a 48 hours (may be other number), we should remove such carts and release items from them. System could update status from reserved back to new for such items. I suppose, our Jobs server could do this task well.

Next: How we could display the number of allowed to order number of items for each variant? We could use two ways, as I can see: denormalization and calculation on-the-fly. BUT in fact we can’t use calculation on the fly, because to have always fresh data about allowed quantity we will need have inventory publication which is not good, because the idea is to completely remove all inventory logic from the client (at least not for customers), because it’s really heavy.

Additionally we could add a job for cleaning removed products/variants with all inventory data after several years from last update.

We need separate interface to manage stock

It should be a table without reactivity and with simple numbers pagination. Rows are products/varaints with most important information, like title, inventoryQuantiry, availableQuantity buttons “add XX items”, “remove XX items”, “show variant items”.

  • “add XX items” this is obvious
  • “remove XX items” - we need an ability to remove X items from varaint, thus it is necessary to be able to spot removal. This could be necessary if the part of the party was defective and we need to took away some of specific inventory items. Remember that barcode should be within inventory items? That’s why it is also important to have an ability to remove concrete items from inventory.
  • “show variant items” should open something like modal window with a list of variant inventory items with status, barcode, also we should put here an info about current status of order of this item (it could be already packed, or sent, but not yet marked as fulfilled). Also we should have a button here - “remove item”.

This is not ordinary operation – to remove items from already payed order, for example, but it could happen, and in that case, we should send some mail to customer with description whats going on. Any ideas on that part of logic?

Client inventory flow

Client could:

  • add to cart. Inventory item status moves from new to reserved
  • remove items from cart. Item status should move back from reserved to new
  • Customer could make an order and nothing should change for an inventory item,
    because, remember, we have only four status state and after reserved we have fulfilled. Going forward – order status should change here.

Logic for the rental products

Some thoughts how this could work for rental products. We could have a circle from three states of statuses for item. newreserved (when customer put item to the cart) → fulfilled (when customer take an item for rent), and when items back, we mark it again → new.

Backorder

In case of items was backordered I see two ways: Admin could add an item through or new stack management table and in that case status backorder will be changed on reserved, or he could not give a damn on this stage and add item only when all order will be shipped. In that case system should automatically change item status from backorder to fulfilled.

That’s all for today. This was my current vision. Let’s discuss this :slight_smile:


#2

Hello, today I did small steps in adding availableQuantity field to variant schema and I have some ideas which should be discussed before their implementation.

The idea is to remove hooks from Products collection. First of all, I dislike the whole pattern of hooks because it makes things unpredictable, and when app will be bigger it’s easy to be confusing by them. Hooks are cool for a small apps, I suppose. So, why I want to remove hooks from Products?

We need to run denormalization for variant availableQuantity on each Inventory collection insert/update/remove (read as “on each action with product item”). At the end the flow of this process looks like:
Products.update() ->
product.after.update hooks ->
Inventory.operation ->
Inventory.after.op hooks ->
denormalization function which updates product availableQuantity field ->
and again product.after.update hooks ->
Inventory.operation.

I suppose we could avoid last two operation by building a tons of new checks in Products.hooks, but, frankly, for me, it’s easier to remove hooks :wink: from Products

What do you think on it?


#3

Hopefully my response makes sense, and covers the major issues we’re discussing here.

This is the intended use of the workflow schema, ie: workflow.status. I’d like to see all things with a status/state functionality to continue to use the workflow as a pattern. I’d really like to see us invest more in a workflow/state manager built around the package.registry + shop.layout + collection.workflow pattern, as I see all these workflows/services being configurable workflows.

Agree about the workflow, this could also be done with transforms or schema level checks.

I do see where hooks could becoming limiting as the application grows, but I like to think of the hooks, as a convenient way to identify connector points, where a more advanced implementation could readily provide replacement functionality, perhaps more in the form of a workflow manager / microservice that enforces rules and executes corresponding methods from the workflow. I’d like to see the hooks more normalized and manageable towards that goal though.

The methods like “inventory/adjust” I think are the ones that need to be removed, and the only reason the fulfillment isn’t finished isn’t because of architecturally it not working- it’s only because we’re not finished.

To be sure that we understand and agree on the term denormalization. You are meaning flattening and storing redundant data for read performance, ie: the practice of transforming data and storing the transformed results, such as a min and max number being transformed and stored as a range string. I’m still trying to see what the value of this really is in a Meteor application, (not doubting that it is a valid approach, here’s a good doc) - I’m just concerned we now need to worry about the provenance of this denormalized data, and I’d like to see this used sparingly.

We could remove the recently introduced denormalizations and replace with collection transformations, as demonstrated with cart pricing transforms. Client collection data does not need to reflect the server values, and collection transformations or publications, can be readily adapted for different use cases, from a smaller data set. I think we could make the argument that you’ll get better performance on reads, but if the data is transformed in a publication, or even another collection, do you really get better performance to the client? I feel, that with the use of client only collections, we can accomplish the same performance goals of denormalization without adding the concerns over the transactional history of these denormalized values.

In any case, denormalization only really make sense when the data is read more than it is changing, and I’m not sure that’s true with inventory, but maybe…

The client inventory collection in fact does not need to be heavy, we can reduce inventory and map just the current product subscription’s inventory back as transformations on the products themselves. (replacing the current structure, but without any changes to the schema would be trivial).


#4

Just my .02 regarding hooks and denormalizing.

TL;DR Hooks good. Denormalizing: Bad

re: Hooks
I have worked on several large scale apps that use this model quite well, and it is a very valid method of decoupling parts of your apps when you need to scale up (for example, you could have a dedicated pool of servers just handling certain types of events). It’s essentially the Reactor pattern (GoF) I would personally like to see more of this rather than less. Not to say there aren’t ways we could make this more manageable.

re: Denormalizing.

It’s bad. Sometimes you have to do it for performance reasons. Usually because you didn’t design a part of your application well enough in the first place. I am against it except when pressed against the wall by real-world use cases. It’s like a virus in your system that you can never get out, and nothing can ruin your life like not knowing exactly what you have in inventory. In all areas of the app, I would say the very last place we would want to denormalize would be inventory.

On top of that you already have "trust issues’ with using a non-relational db like Mongo, I’d hate to pile on to that with denormalization.

Lastly, I created this ticket today about handling inventory. Is this a step in the right direction to start getting inventory fully implemented? https://github.com/reactioncommerce/reaction/issues/964