Skip to content

Instantly share code, notes, and snippets.

@IvanChepurnyi
Last active June 26, 2020 22:22
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save IvanChepurnyi/70fcea1793db4b22c7fe to your computer and use it in GitHub Desktop.
Save IvanChepurnyi/70fcea1793db4b22c7fe to your computer and use it in GitHub Desktop.
Architectural Proposal for Magento 2 Inventory and Prices Mechanism

Problem

There are too tight relations of stock and prices to store views and websites in Magento that results in high complexity of implementation of b2b and drop shipping solutions in Magento.

The issue was very visible with the price index structure for Magento 1, and now Magento 2 stock index follows the same idea of having an index entry per website.

This strict relation to a website makes unnecessary data duplications in case if you have global stock. Although it makes over complicated multi-warehouse delivery, as you will be required to create a separate website for each warehouse, that duplicates other product data in the flat index structure and price index.

Solution

Create a separate scope entity for Price and Inventory, for using them as scope fields for respective data structures.

Inventory Scope

Inventory scope should be a separate entity, which can be managed by the admin user. In the core system, it consists only of identifier and system name, which is used by the admin user. Also, it makes sense to specify that this scope is indexable and is editable.

  • If a scope is indexable, then an index is going to be generated for it.
  • If a scope is editable, then admin user can edit stock levels per product for this scope.

Why should we have these flags? The idea behind it, to have a possibility to create aggregated scope, that has index information from multiple warehouses and will be used for product lists to show availability in general.

Inventory Record

Inventory record is an entity with a unique foreign key pair to product and scope entities. This entity is the same thing as current stock_item in Magento 1.

Scope Resolver Interface

Should be a main contract for matching inventory scope to a product item or product list (i.e. index matched scope) Might contain such methods (up to core devs how to name it):

  • findIndexScope($storeScope, $customerScope) - finds scope for attaching index on product lists
  • findProductScope($product, $storeScope, $customerScope) - find product scope for single product
  • findCartScope($quoteItem, $quote) - find inventory scope for a particular quote option, as different items can be delivered from different warehouses, etc.

For default scope resolver implementation should be just a simple retrieval of configuration values on appropriate store view, and a more complex solution can be left for extension developers and enterprise edition.

So by introducing scope resolvers, we remove these huge duplications of data in the index and make the system more flexible to various implementations of inventory management.

Scope Indexer Resolver Interface and Scope Indexer Interface

We need to have a possibility to create a custom inventory scope indexer, as data for different scopes can have different business logic inside. For instance, a merchant has two delivery options:

  • Home delivery
  • Pick up at store

Home delivery is a separate warehouse for home delivery, but pick up at store is an availability at particular brick and mortar location. In this case product can be delivered from both locations, and if it is not available for home delivery it still can be order on the webshop as pick up at local store option. To make such a level of customization, it will be possible to achieve it by using just different inventory scopes and simple indexer for it.

  • Global Availability Scope (isEditable = false, isIndexable = true)
  • Home Delivery Scope (isEditable = true, isIndexable = true)
  • Pick Up at Store (isEditable = false, isIndexable = true)
  • Store 1 Inventory Scope (isEditable = true, isIndexable = false)
  • Store 2 Inventory Scope (isEditable = true, isIndexable = false)

In this case indexers for:

  • Global inventory aggregates Home Delivery Scope and Pick Up at Store Scope
  • Pick Up at Store aggregates Store 1 and Store 2 Inventory

So on the frontend customer can see the availability information for the product in general, not only for a particular scope.

With this level of indexation system will be more simple and more customizable by extension developers and by solution providers.

Price Scopes

For price scope, I advise very similar approach as in inventory. Only with a difference, that there is the only global level of price scope resolver, no list or item level resolvers.

For instance, you have such a pricing scheme for your business:

  • Retail Prices (Western Europe)
  • Retail Prices (Eastern Europe)
  • Retail Prices (U.S.)
  • Distributor Prices (Global)

In current Magento implementation, it is impossible to have such a separation of the data without duplicating data across different websites, and if we have for instance different languages for store views, it gets even worse.

But with detached price scope, the issue is quite easy to solve:

We create just four price scopes, and only four different values are manageable per product.

And on the frontend we also reduce price index size and make possible to use customer groups in Magento for more precise customer targeting, as price is bound to price scope and not to a customer group. Although you'll be able to set default price scope for a particular store view and override it on a particular customer group.

The more precise architecture of it can be discussed in detail with the core team if you like this kind of approach.

@ladle3000
Copy link

I like it.

@antonkril
Copy link

In general as we discussed, Store/Group/Website separation is too limited. But we planned to have generic notion of scope for configuration only. In business code it's usually easier to understand implementation when it operates with more specific domain-related entities.

In your example all editable scopes can be represented as warehouses (their stock levels can always be edited).

@tegansnyder
Copy link

I'm sold on multi-country/website/customer group indexing optimizations for price and inventory to prevent duplication. This is a good spec to work towards.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment