Problem/Motivation

Define the high level functionality and link it with the technologies and API's needed.
The functionality covers these main areas:

  1. Stock availability checking
  2. Stock Levels tracking
  3. Backend & configuration
  4. User Interface enforcement.
  5. Reporting - maybe at a later stage

Proposed resolution

1. User Interface enforcement - Control the user interface to enforce stock control
Objectives:

a) Don't allow the purchasing of products that are out of stock (this is for enforcement not the actual checking)
Proposed:

  • Disable the add to cart if needed
  • Check before adding to cart
  • Check before entering checkout
  • Check before payment

b) Allow for configuration of button and messages.
Proposed:

  • Text & class for disabled button.
  • Text for out of stock messages for the 3 other checks

c) Support for alternative workflows - Instead of just disabling the add to cart button provide alternative actions to the user.
This can be:"Let me know when back in stock", "purchase for later delivery", any other examples ?
Proposed:

  • TBA - we are looking at supporting those actions not developing them as part of the stock module.

2. Stock availability checking - Provide a generic way to check stock based on the commerce 2.x interface: AvailabilityCheckerInterface.php
The following are a few uses cases

  • Stock levels - if greater then 0 available
  • Check external system to find out if available
  • Mark specific products as always in stock
  • Have a Y/N available flag.

It is not the responsibility of stock to provide all of these but to support them.
The plan is to support the following.

  • Stock levels - if greater then 0 available
  • Mark specific products as always in stock

3. Stock Levels tracking - This is going to be a much more powerful and complete system for stock tracking.
Supporting the following:

  • Stock movements transactions
  • Support for multiple locations/warehouses
  • High performance & high accuracy for supporting high traffic and large orders.
  • Support external stock systems
  • Stock cost - for FIFO and LIFO reporting (may be schema support only)

We will provide a schema supporting the above requirements and an API for creating the transactions.

Stock movements transactions:
The system will provide the following transaction workflows (high level functionality) in the order of priority and should ideally be extensible if needed
Transaction type: receive stock
+ Create a transaction when stock is received or added
Sell Stock:
+ Create a transaction when stock is sold
Move Stock from one location to another
+ Create a positive stock transaction on the receiving location
+ Create a negative stock transaction origin location
Stock returns
+ at least initially this can be same as receive stock
Damaged stock / stock checking / other ..
+ TBA

Support for multiple locations/warehouses:
This may be only implemented as a schema and possibly low level functions for the first version.
We have two pieces of information regarding the location (not sure on best generic terminology)

  • Location - typically the warehouse but can be factory / van ..
  • Location zone- Typically - aisle, bay, shelf, bin

The location will be a controlled list.
Location zone is typically stored as four sections this can be four fields or a single field in the format of "aisle.bay. shelf.bin". a single string is more flexible but harder to index and search but as far as I know this is used for locating stock and not for reporting and stock level checking so I think a single field will do.

The Database schema
We will have three main schema tables + one for locations.
The proposed tables are:

  • inventory_location - list of locations - as this has no performance requirements can be an entity
  • inventory_transaction - a single record will be inserted each time a product is sold - this will guarantee high performance without the risk of deadlocks.
  • inventory_location_level - this is a performance table. A cron job will regularly total the values of transactions and keep a product - level record for fast checking of stock for the location. It will also store the last transaction id that was used for the calculation so the next time it gets updated it can pick of where it left.
  • inventory_product_level - T.B.A - if we allocated one or more locations that can be used for fulfilling a product we can use this to table to hold a single total.

Note that for version 1 we may only support a single location but should have the low level API defined.
Also the inventory_product_level table can be used for the following:
Simple stock management (hopefully will not be needed)
Caching for external Stock systems.

Both the database schema and the low level functions will be handled by the commerce_stock_ls (local storage module)

4. Backend & configuration - As 2.x supports product hierarchy this may not be as straight forward as commerce 1.x that was managed by bundle.
Proposed:

  • Provide an interface for specifying what products should be stock controlled.
  • Provide an interface for adding stock movements and possibly stock levels.

5. Reporting - Provide a way to visualize stock levels and movement
For a later stage or a separate module

Related

Original issue talking about transactional inventory system
A couple of sandboxes:
Commerce Stock Record
Commerce transactional stock feature

Comments

guy_schneerson created an issue. See original summary.

guy_schneerson’s picture

Issue summary: View changes
guy_schneerson’s picture

Issue summary: View changes
guy_schneerson’s picture

Issue summary: View changes
iaugur’s picture

Issue summary: View changes
guy_schneerson’s picture

guy_schneerson’s picture

Issue summary: View changes
millionleaves’s picture

In terms of multiple locations, I'm interested in how Commerce should calculate the availability of stock in different scenarios.

It looks like your proposed approach would involve having a stock level for each location and then calculating a total stock level at the product level which would be used as the stock count during checkout.

However, say I have a store that operates in the US and Canada, and fulfils orders from warehouses in Chicago (for the US) and Vancouver (for Canada).

Should stock in a Chicago warehouse be counted as "available" for an order placed for delivery in Canada? I'm not talking about the logistics of deciding how to fulfill the order, purely the question of whether the product should be considered "in stock" for a Canadian customer if it's available in the Chicago warehouse but not in the Vancouver warehouse.

Another scenario might be where I'm offering same day delivery in NYC, but can only achieve this if the stock is available in the NYC warehouse - the stock level for NYC might be used to determine whether the shipping rules return "Same day" as a shipping option.

I'm thinking this could be solved by having "location groups", where each location can be added to one or more location groups, and the total for each location group is calculated in the same way as your proposed product level stock level. The availability of a given product for a given customer would depend on the stock level of that product in the location group(s) available to that customer.

guy_schneerson’s picture

Hi millionleaves and thanks for your feedback
I am not sure at all about the inventory_product_level and that's why it was marked as T.B.A.
What I was thinking of is developing a low level API that supports checking by location (inventory_location_level) this will allow checking stock for "Loc1 + Loc2" I am not sure about the implantation of the high level checking logic at this point. I am probably pinning my hopes on Rules integration.
However I do like the idea of "location groups" and if implemented can replace the inventory_product_level as this will be a all location group.
However "location groups" may have the same problam as the inventory_product_level in that it may be hard to keep up to date so may end up as metadata: letting us know what locations need checking for stock instead of holding actual level.

millionleaves’s picture

Issue summary: View changes

HI Guy - appreciate your feedback. Glad I'm on the right track!

Regarding the inventory_product_level, I agree that this is an unreliable measure if it's not being updated in realtime, and realtime updates will be costly in terms of load and resources.

However, I wonder if we need to know the inventory_product_level when checking if a product is in stock? The most frequent reason for a stock check will occur when loading a product page - do we show the Add to Cart button or an Out of Stock message? At that point, surely we just need to know if the product is in stock, not the level of the stock?

In other words, for these real-time "do we have enough stock to proceed?" checks, we probably just need to know that at least one of the locations in the location_group meets the stock level threshold to continue. This threshold would change during the checkout cycle. It might be 1 unit for the product page load but, if someone adds 5 units to their cart, we'd need to check that we have 5 available.

So the stock check done during a product page load or add_to_cart action could involve cycling through the locations in the location_group until one is found with enough stock (or generating a running total if the first location doesn't meet the threshold), and stopping as soon as that happens, to avoid further load on the server.

We could streamline this further by making sure that locations that are more likely to have stock are checked first (e.g. a central hub before a regional spoke). To this end, we could provide a weighting value for each member of a location_group that determines the order in which we cycle through them. Another option would be to check locations that are marked as fulfilment locations (i.e. it may be that not all locations in the location_group are used to fulfil online orders).

guy_schneerson’s picture

Hi millionleaves I agree about not needing to necessarily check all locations added the following as a result to you post https://www.drupal.org/node/2627208
However checking of stock should be very officiant and not wearied at this point at optimizing the checking. however the business logic of fulfillment is another story and your ideas about the location group would be helpful. If you got time you can start a new issue for location groups so it's not forgotten.

skyredwang’s picture

Commerce 2.x has Store Entity. I am interested in learning how Stock would integrate with Store Entity. So, most use cases can be solved by different configurations instead of Commerce Stock Module providing out of box solutions.

guy_schneerson’s picture

Hi @skyredwang
The planed version of stock will support multiple locations although currently only working on the low level functionality so can only answer in concept that the following should all be possible

  1. All stores share stock from a single location/warehouses
  2. Allocate a Location/warehouses per store
  3. Allocate multiple Location/warehouses per store (some can be shared)

How the Interface and the business logic implantation will work will be determined at a later point but both the database architecture and the low level API should support the above. if you can think of other use cases do let me know.

zeezhao’s picture

Hi. Since D8 commerce has stores, will it be possible with the current architecture to enable tracking of a universal SKU across multiple stores? i.e. each store uses same SKU, so that total stock is sum of stock across stores.

Please see here for my initial post under commerce. https://www.drupal.org/node/2650294

guy_schneerson’s picture

Hi @zeezhao The plan is to support stores and other stock locations like warehouse however the exact implementation is not yet defined. I do suspect that it will be possible to check all available stock across all locations per SKU.

skyredwang’s picture

Including me, I think more people are getting interested in following your direction. If you could, list out small issues or tasks, so that people can get started to help.

guy_schneerson’s picture

Hi @skyredwang that's great as I sure can do with help, unfortunately I am away from Thursday until the end of the month so may not have time for creating issues but if I get a chance will post the next task as we are currently in really early stages.
Also if you or anyone else are interested in helping send me an email via my contact form with email and wen I am back I will try and organize a few mini sprints to get some significant progress done.

tasmaniaman’s picture

Hi Guy,

I'm really interested in the Stock movements transactions feature for the D8 version of commerce stock.

I'd love to be a tester for the development of the D8 version. :-)

Looking forward to helping out.

Peter.

skyredwang’s picture

Following @guy_schneerson's architecture, we are doing the development on Github https://github.com/INsReady/drupal-commerce-stock. Hopefully, this initial work can give us more details to discuss.

For example, I have a specific question: we are now setting Stock level tracking on Product Variant. As the time of writing, the current Commerce Stock has its own UI to select Stores. On the other hand, DC2 has this Visibility Setting, which allows admin to choose store. I am thinking if Commerce Stock should use that setting instead of creating its own. However, by using the DC2 visibility setting, admin won't be able to choose store for individual variant.

Let me know your thoughts?

bojanz’s picture

I clarified with skyred that we should not be using stores as stock locations, those should be separate entities.

Spree has a sensible architecture worth copying: https://guides.spreecommerce.com/developer/inventory.html

guy_schneerson’s picture

@skyredwang what is the github repo for? I can not see any issues or a wiki to go with it.

skyredwang’s picture

@guy_schneerson , the github repo is just for us to do the development work, and your reviewing. If you a suggestion on how we should contribute at the early stage, please let me know.

guy_schneerson’s picture

skyred, bojanz Stock locations should definitely not be stores as those can be warehouse shops or even transport vehicles, however I don't see why we can not look into optionally link them to a store or other entity types at a later stage.
The Schema for the DC is similar to Spree:
DC Location is Spree Location
Inventory Transaction looks to me like the Spree Stock Movements
Stock Items on Spree sounds similar to the DC inventory location level - this is to be a derived value on DC not sure how Spree are managing it.

bojanz’s picture

Sure, stock locations can belong to stores. That makes sense, just like for orders.

skyredwang’s picture

StatusFileSize
new67.84 KB
new75.53 KB
new58.33 KB
new117.69 KB

@guy_schneerson, we have done a lot of development on Github, https://github.com/INsReady/drupal-commerce-stock with one objective to follow your original design as much as possible. We are aware that there are many codes not following the best practice or coding standard, but we have a production site to launch, therefore, the other goal was to make it work first, then improve it later.

Below are some screenshots

guy_schneerson’s picture

Thanks @skyredwang I have just committed most of the low level API needed although still needs work. I will look at your git repo later today.

guy_schneerson’s picture

Hi @skyredwang I had a quick look and I can not see any implementation of the schema and the low level API I proposed. The idea is to have an high performance insert only transaction table with a "location level" that will regularly total the transactions. this will need sum() queries both at the point of checking stock and the updating of "location level" table. I suspect you started working on the high level functionality while I am starting at he bottom.
Do correct me if I am missing out something, otherwise we may meet in the middle at some point.

agoradesign’s picture

I've read your blog post (https://www.blue-bag.com/blog/stock-drupal-8-commerce-technical-overview...) and also tried to get a quick overview of the current implementation in the repository... First of all, the plan is great, absolutely makes sense! As you've written, there are different needs and use cases and it's therefore important to have a flexible approach, to be pluggable and exensible in order to cover all needs. And also to provide good default services like described

I only had a quick look at the repo, but here are a few thoughts:

  • A look into the src directory is already quite confusing, as every class and interface is in the same directory (and I guess, it'll grow in future) - I'd vote for the one or other subpackage here in order to have a better overview. I'd either move your service implementations (local stock, always in stock) or structure by functionality (check, update, ...)
  • Consider declaring the implementations of your three interfaces (StockCheckInterface, StockUpdateInterface & StockConfigurationInterface) also as services and inject them into the stock service instead.
    That would have several advantages: you provide even more flexibility by offering the possibility to even swap one single of these stock service parts, without having to swap the stock service itself.
    If more complex implementations also need other services (which is very likely), you can use dependency injection as well for them.
    These reasons further mean better testability and less problems in unit tests (think of you need some mock implementaions of other services instead,...). And last but not least you'd follow the typical Drupal/Symfony approach
  • The "always in stock" service actually only makes sense, as soon as you have implemented the possibilty to use different services within a project - otherwise you'd not need to install commerce_stock at all
  • Consider moving your two default implementaions into own sub modules to avoid to have unneeded services registered
  • Is the local stock service actually implemented? The blog post seemed so, but I couldn't find it in the repo!?
  • To be a little bit nitpicky: if you want to stick to common coding style guidelines, the sooner you go for it, the better it is. (Because later on, when more people participate and propose patches, their patches will break likely, just because you've done the changes at that time). Eg just on scanning through your classes, I saw multiple line breaks very often,...

I think, these are all my thoughts by now - I was interrupted a little bit during writing, so I may have missed something :D

guy_schneerson’s picture

Thanks @agoradesign super useful stuff.

Totally Agree on the src folder. It was getting crowded. I will look at other projects to get an idea of how to best organize.
--
Re local stock & always in stock: The local stock is in a sub module "Commerce Stock Storage" same idea as "simple stock" on D7. the idea of always in stock is to have a default service that doesn't do anything until you enable and set the local stock or another service. It can also be used to disable the module functionality with out uninstalling. I thought its an elegant solution but if proves to be expensive can easily be replaced with code that goes: "no service or user chose the disable option" -> return product is available.
And yes the local stock service is working and is in the sub module. You can get it working by using the dev interface to create transactions and than calling the commerce availability manager:

<?php
    $availabilityManager = \Drupal::service('commerce.availability_manager');
    $availabe = $availabilityManager->check($product_variation, $prod_qty);
?>

I find it so cool: calling a commerce service that triggers the Stock Manager that calls the configured Stock service :)
--

Consider declaring the implementations of your three interfaces: Agree especially useful for StockConfigurationInterface as this will determine the location to use and that's likely to have different use cases: by product type. by store. by store + product taxonomy ... same goes to the configuration class of the StockManager. It did cross my mind but I was worried I was going service mad as they are so cool.
--
nitpicky: Thanks for that and will do.
--
I am close to finishing the next stage implantation of a business layer StockTransactionsInterface that's a high level functions implemented by the StockManager for creating typed transactions "sold stock" "new stock"... this will use the existing low level function provided by the services. that will hopefully be the last bit before starting on the UI.

Really appreciate your eyes over this. It's harder and less fun writing loads of open source code wen no one is sharing your journey.
Will create issues for all your points (feel free to beat me to it if you got the time).

agoradesign’s picture

I've totally overseen the submodule! :-)

In this context, the idea of the always in stock service is clear and makes absolutley sense to me! Don't panic, I don't think, that this is expensive. D8 and Symfony2 relies on heavy services usage in its architecture. That's ok

You're right. That kind of integration is really cool

I'm looking forward to the next steps :)

You're right - this is, what makes open source in general and especially Drupal! I'd really like to help you with some issues, but as you know for sure, the only problem mostly is having enough time... At our current (and first) two Drupal 8 Commerce projects, we won't need stock management at all. And I'm currently busy getting every feature in, I need. Most likely I will have to write a payment gateway integration, as soon as bojanz has committed the initial Payment API. But maybe (and hopefully) I will have a bit more time next month or so. That's definitely a feature, that i'm interesting in and willing to spend some spare time on it also, as soon as I have some again :D

guy_schneerson’s picture

@agoradesign - created the following three tasks:
#2726581: better organisation of classes and interfaces
#2726583: Consider declaring the implementations of some interfaces
#2726587: Coding standards
covering the points you made.

Thanks again for your help.

dwkitchen’s picture

Finally getting round to replying on here after I said I would at DrupalCon.

Getting the ecosystem around the core commerce modules has always been something I have been interested in and drew this diagram to illustrate it. The top right half is showing those systems required for a physical goods store, and the top left those for a digital; the bottom being common extensions.

http://dwkitchen.github.io/commerce-2.x-slides/#/4/3

There is a combination of modules that provide functionality around physical goods, stock, shipping, fulfilment; and not on the diagram, management.

I see the balance for the Commerce Stock module keeping its functionality limited without extending too far in the providing Stock management functions which might be done using a ERP system or a further Commerce Stock Management module.

The primary function I want from the stock module is controlling the sale of items based on rules. My experience with ERP systems is that this needs to happen in the Drupal application without relying on the ERPs API, which might be the sFTP transfer of a CSV file overnight.

The most common rules are going to be around holding stock; when someone adds a product to their cart it is allocated and the available stock level reduced, if the cart is abandoned it is returned to available stock. I have even done this where the customer gets a countdown timer until the stock allocation will be lost.

Those further rules might be around where the stock can be sourced from. In the multi-vendor marketplace environment (Amazon Marketplace example) where stores are selling the same product only the stock for the store the customer has selected can be used.

It looks like idea of the stock availability manager being the solution for further modules to provide more complex methods of checking availability. The Commerce Stock module having the simplest included as an example.

The stock transaction interface also is a good way of making this extensible with Commerce Stock having:
Stock Allocated
Stock Sold

But these can be extended by further modules; Commerce Stock ERP having Stock Received, Commerce RMA having Stock Returned.

guy_schneerson’s picture

Hi @dwkitchen great to hear from you.
I am attempting to address 3 issues with the new D8 module:

  1. The base commerce module doesn't provide direct stock control but the interfaces and service architecture for those to plug in. this will allow for ERP interrogations
  2. Provide a full stock management for those not using external ERP
  3. Improve the functionality of the existing stock module by adding locations & transactions while improving performance. So even if you don't need the extra stuff it should work better then the 7 version.

I think the first is relevant for you. the stock module provides the StockManager this allows for creating StockServices with specific implementation while the StockManager provides higher level functionality.

I am totally in agreement with you about the implementation of the business logic for both creating transactions (sold/reserved ..) and what locations to check. I am hoping to address those using plugable configuration classes (what locations are relevant for the user the product ..) and possibly rules for stock transactions.
I am not attempting to provide complex functionality out of the box. Its likely to be single location and simple sold/new stock transactions only so will not behave much different out of the box to the current module.

I recently implanted a new interface StockTransactionsInterface that allows high level functionality (receiveStock, sellStock, moveStock & returnStock) while only needing the installed service to provide a single createTransaction method. This plus configurable transaction types will hopefully allow for creating workflow functionality without needing to know the stock implementation. So you can start building a site or create contrib modules before a specific ERP is selected.
note: configurable transaction types not yet implanted.

In my experience larger clients all use dedicated ERP systems but most smaller organization don't but do need more powerful stock management and are struggling with things like multi channel selling, so I am hoping the module can cater for both.

As the availability manager is in core if none of the above is of any use, users can just plug a replacement. Although I think the commerce core availability manager may need more work - multiple states and actions but I haven't got that far yet.

olafkarsten’s picture

Hi, not sure, that is the right issue (there are soo many ... )

The current stock module is in different places tightly coupled to one of multiple possible product architectures as it requires a product variation / variation_id here and there. (For those that havn't read that: https://drupalcommerce.org/blog/42500/commerce-2x-stories-products). Consider declaring the essential interfaces more generic and using PurchasedEntityInterface all of the place instead.

guy_schneerson’s picture

Hi olafkarsten you are absolutely correct. Start a new issue for this if you get a chance.

olafkarsten’s picture

I learned a little bit what others do and found out, that they often have one thing in common. At least one object that holds the stock related data per product variant. Assume someone wants a "minimum stock level" setting per product/location and a "optimum stock level" , e.g. to issue warnings when the stock level falls below and backorder whatever it needs to reach the optimum level. I think I have seen this in nearly all inventory system I've come across.

Wonder how we would accomplish this with our current architecture.

guy_schneerson’s picture

Hi @olafkarsten Yes it is a requirement that comes up. With D7 the approach was to use rules with an entity update event.
I would not expect this to be in the first version of the module and we should evaluate at a later date.
The two possible options I see are:

  1. Rules integration - we will need to add an event as transactions do not trigger a entity update.
  2. Inheritance - This will allow us to easily add functionality to additional sub modules or other contrib modules

Inheritance could have also been used for the "always in stock" feature. If for some reason this feature had a big overhead (it doesn't) or it had other un-resolvable issues like not allowing the user to uninstall (sounds like we can sort that one) then we could easily create a new module inherited from the local_storage and added the functionality to it. more or less same amount of code.

The two biggest requests I had for D7 that needed to be addressed in the out of the box functionality are:

  1. Always in stock - digital / made on demand
  2. Decimal stock - how long would you like the piece of string to be?

The next one that didn't make it in is:

  • Wait list for out of stock products - I think this + minimum stock level should be the target after we have a stable version.
tasmaniaman’s picture

@guy_schneerson love seeing all the work that being done on this module on Github! :-)

Had a thought about transactions and taxes, in Australia (not sure about other countries) when a transaction journal is created the value stored is always excluding tax.

So if you sold 1 x Widget for $22 in Australia the transaction journal would store $20 because of our 10% GST tax.

When looking at a STOCK ON HAND report you would always see the value of stock on hand less taxes.

I know the Tax implementation is being reworked at the moment before RC1 but it might be something to keep in mind.

guy_schneerson’s picture

Hi @tasmaniaman
@steveoliver & @olafkarsten have been really helping to progress the D8 version and it is really taking shape.
It is interesting what you are saying about prices. Let me explain the aprouch and would love your feedback:
I have allowed for a unit_cost field on the transaction table however no sell_unit_price column as we are linking to the order. Do you think we need one? We can get price data from the order as the transaction has a relation to it, however it may not be straight forward as stamping this at the point of creating a transaction.
We are also talking about having an archive transactions function, this may initially be a delete only but I can see records ending on a warehoused database at some point and that may be useful to have the data available.
I do not think we will do any work with cost/price for the beta version of stock however I would like the database schema to be fixed so any changes to support future functionality should be made soon.
As far as ex vat prices this can easily be a configuration option or an event that helps calculate the stored value.
If you are up for it create a new issue for this as understanding this now, can really make a difference in the log term.

tasmaniaman’s picture

@guy_schneerson - I'll put something together and create an issue - I have access to an accountant who has strong views on the financial side of things.. :-)

olafkarsten’s picture

I do not think we will do any work with cost/price for the beta version of stock however I would like the database schema to be fixed so any changes to support future functionality should be made soon.

That is exactly what I'm trying to solve with my idea to separate transactions and metadata entities and make the metadata configurable by the user. We need an approach that is easily to extend, but do not interfere with our stock level calculation. We never ever will get a transaction database schema which tackles all valid use cases.

guy_schneerson’s picture

Hi @olafkarsten
I am happy for us to look into having a more "general" way of extending transactions. However it was always my intention to provide ERP level functionality and those tend to have excepted standards/practices.
so far those included:
* transactions
* multiple locations with storage location info
I am aware that financial information is a part of this but I have only gone with what I know and had no time to finish the research so only included the
* cost field
Most of this data is vary lightweight and it is not an endless pool of permutations. The business rules mostly are to do with how the data is used for example cost can be used in two accounting systems FIFO and LIFO I suspect that any permutations in other price/cost related needs will not affect the schema but how it is used for example storing prices with vat or without can be determined at the point of creating a transaction based on business rules / configuration.
I am extremely keen to have as full understanding of the financial side of stock and looking forward to any information @tasmaniaman or anyone else can provide.

olafkarsten’s picture

I'm totally agree that we need to learn as much as we can. I only think, we can't expect to have a future proof solution that will not need any changes. I'm fine with unit costs too, we will need the currency code to the amount, but I think I have seen that in one of steves PR's. I'm have serious doubts, that serialized metadata is the right solution. But I think we have an separat issue for that.

olafkarsten’s picture

Issue summary: View changes

Updated some bits of the issue summary, but needs some more cleanup.

- Removed the remaining tasks: This issue is not about getting things done, its about how we design the code.

jcandan’s picture

I am working on a project with both commerce and non-commerce inventory needs, and the need for both serialized and non-serialized inventory tracking. I'll lay out a couple scenarios i'm familiar with and/or working on, and will offer a suggestion that I hope we're not too late in development to consider.

First, what is serialized inventory?

A serialized inventory item has a serial number (unique identifier). Although each copy of the Product is the same, it's quantity is the calculated total of serial numbers of that item in stock, each a qty of 1. The need for this comes when one needs to track the history of a specific inventory item.

Example:

Product type: Phone
Product: Pixel 6
Qty: 2 (calculated on number of serial numbers)
Serial numbers:
 - X6123: { sold: false }
 - X6124: { sold: true }
 - X6125: { sold: false }

Scenario 1: RC Car raceway

We sell services like race admission and yearly memberships. We sell merchandise (t-shirts, RC cars, parts) online and onsite and need to ensure availability. We sell food and beverage for which we want to inventory supplies (burger buns, patties). But we also want to inventory parts for our own RC Car repairs, and track serialized LiPo batteries' usage, charge cycles, and proper disposal (see which make/model batteries last longest).

Scenario 2: Satellite Dish Installer

We do fulfillment for DIRECTV, sending our techs out to complete residential installs.

We take in both unserialized and serialized equipment from DIRECTV. We have to track serialized equipment and ensure they are installed in a timely manner, or they must be returned to DIRECTV. We can be charged as much as $500 for each satellite TV box if it remains in our warehouse past a certain time threshold (60 days if I remember correctly). We must track transfer, installation, or return of said serial numbered boxes.

Proposed Solution

These scenarios highlight an important aspect of inventory--it's not always commerce related. I propose an Inventory control module that exists outside of the Drupal Commerce ecosystem, but that the commerce_stock module can take advantage of. It would need to be flexible, which can be tough to engineer. But if done, would open a MASSIVE development market where other ERP systems fall short, Drupal can again reign supreme in yet another vertical.

olafkarsten’s picture

Comes to mind another use case - a print of something beautiful signed by the artist itself, limited number 0-100 - user can choose the number.

Okay, not sure i'm awake, but I don't see any bigger issues here. The availability calculation would be the same. It's not relevant which serial number you have in stock, when you want to know, if you have X of the serialized stuff available.

The crucial part is the stock transaction. One could swap out the stock service and use one, that is able to handle the serialized stuff. Thats where @steveoliver's unfinished work shines. If we would use chainresolvers for part of the stock services, and make the services plugins, one could put a focused service with a limited scope in place. Thats exactly the sexiness of the idea. Build a stack of stock services, that fit your needs.

I am optimistic that we will end up with a module that makes it easy to extend it with such functionality.

@guy_schneerson *knockknock* - It would be even easier if we had transactions as an entity. Put together your own type. Add a serialized field and your are done. Happy XMAS! But thats only an side issue in this case :D

olafkarsten’s picture

@guy_schneerson
Lets decide finally for this release if want to make stock services plugins and use chainresolvers to resolve stockservice on runtime.

See: https://www.drupal.org/project/commerce_stock/issues/2858391#comment-123...

I'm all in for this. I think this will allow much more flexibility in extending the stock module. If we don't do this now, we have to wait for another major release and this may take years. This approach will be a such a architectural change, that you probably don't launch it a minor release.

We have some work done in PR35 referenced in the issue above ^_^. If you want to go this route. Lets open an issue and get this done.
The PR is somewhat WTF ... I know. But the stock service / chain resolver part would give us a good base to start.

olafkarsten’s picture

Status: Active » Closed (outdated)

i think we are done with meta discussions for now