Problem/Motivation
We currently support multiple locations but those need to correlate to stores.
Proposed resolution
The changes have two main layers:
1. Architecture
The interfaces need to have the store provided as a parameter when getting stock location information.
This is relevant to StockServiceConfigInterface getAvailabilityLocations() and getTransactionLocation()
2. Implantation
Each store will have a primary location
Each store will have a list of locations available for fulfilment (this is for checking of stock not for creating transactions)
To support multiple stores you must add the following fields to your store (we may automate this later on):
- Available stock locations (field_available_stock_locations) – unlimited
- Stock allocation location (field_stock_allocation_location) - 1
Remaining tasks
PR #27 added support for multiple stores however we have a number of improvements we can make.
- Currently fields need to be added by hand. We can then look at UI for enabling support by store type and create the fields by code.
- More testing especially under real life use cases
- Use at using a resolver for determining the location.
Comments
Comment #2
guy_schneerson commentedA few notes:
also added related issues. read those for related discussions
Comment #3
guy_schneerson commentedEven better then providing the store I will use the commerce Context as that holds the store but also the customer and that can potentially be used by other implementations.
Comment #4
guy_schneerson commentedCreated pull request for the first part of the work: architectural changes only no implementation
https://github.com/BBGuy/commerce_stock/pull/27
Comment #5
steveoliver commentedI posted this in the child issue #2838050: Add further possibilities to filter stock locations available for stock allocation, but it is relevant here because the two issues are so intertwined, at least conceptually and architecturally.
Re-posting here:
OK, It's been a few months, and I haven't worked on it recently, but I'm posting my Work in Progress (WIP) PR -- https://github.com/BBGuy/commerce_stock/pull/35/files -- which addresses at least initially most, if not all, of the issues touched on in this issue.
I may have forgotten a few notes, but those are the big ones. It still needs more work to finish, but this is the direction I've headed and would love to discuss / get help on. I probably won't be able to work on this for at least another few months. If anyone would like to discuss, please find me on #commerce in drupal.slack.com or in the issue queue here.
Comment #6
guy_schneerson commentedHi @steveoliver I was also busy lately and will not have to much time in the next 9 weeks but I will find some time to go over this as I want us to find a direction to push towards.
Comment #7
heddnTagging. This is blocking #2613264: Drupal 8 port of Commerce Stock. And bumping priority because of that.
Comment #8
guy_schneerson commentedfinished reviewing other issues this is next on my list
Comment #9
guy_schneerson commentedRe https://github.com/BBGuy/commerce_stock/pull/35 I like the resolver aprouch but the commit does much more than add support for multiple stores and it removes key functionality that is currently used. I recommend we look at using a service resolver at as a separate exercise and go with https://github.com/BBGuy/commerce_stock/pull/27 for now.
If anyone has any other ideas please engage with me ASAP as we need to make a move on this.
Comment #10
rob c commentedIve reviewed both, figured 35 needs a reroll anyway and indeed too much in one PR. Do like it more then the other one but until the reason for the change is clear cant disagree. Lets create soms separate (followup) issues for the major things from the PR we really want / need.
Comment #11
guy_schneerson commentedThanks Rob
I have retested PR 27 and it needed one small change to bring it up to API changes in commerce 2.0.
Comment #12
guy_schneerson commentedWhat I am going for now is:
To support multiple stores the user will need to add the following two reference fields to relevant store bundles:
At a later stage we may automate the creation of the fields.
The logic will be if fields exists then it is used otherwise use the LocalStockServiceConfig default (currently all enabled locations and transactions created against the first one) so normal for single store shops it will work out of the box and anyone needing multiple store support will need to create the fields.
Comment #13
guy_schneerson commentedThe changes are now working and ready for testing but please note the following:
to support multiple stores you must add the following fields to your store (we may automate this later on):
* field_available_stock_locations, Entity reference to Stock Location, Unlimited
* field_stock_allocation_location, Entity reference to Stock Location, Limited: 1
Issues identified:
Comment #14
guy_schneerson commentedComment #15
guy_schneerson commentedI have added code to make sure the current store is supported by the PurchasableEntity. If not it will use the first store associated with the product. This solved both issues I have encountered so far although the store selection should ideally be removed from the product edit form as its value in the UI may not be the same as the persistent value and can cause data entry issues.
Comment #16
guy_schneerson commentedFollowing testing by Rob C I have changes the behavior in cases were the current store is not supported by the PurchasableEntity then the edit widget will not be displayed. The previous behavior is still availalbe as an option on the widget by setting "Context fallback" to TRUE.
Comment #18
guy_schneerson commentedGood news, we now have multi store support. See #12 or issue description for setup instructions
Comment #19
edurenye commentedThe commit 'fac45ca ' is throws an exception when the current store is not set because in '$store_to_use->id()' $store_to_use is null.
So this patch fixes the issue.
Comment #20
edurenye commentedForgot the patch.
Comment #21
guy_schneerson commentedThanks @edurenye
I can not get $store_to_use to be null on my setup but adding the check can only make the code more robust. Would have liked to be able to recreate but not a must.
The check needs adding to both getContext() and isValidContext() as the two share 90% of the code they should probably be combined to make sure they do not drift apart.
Comment #22
rob c commentedI had to think about this a bit more and i have some questions / comments:
What i think / what i've found:
I believe by now that with most code already (possibly) depending on the store entity it should be changed to always use a store. I propose to add a new property on the stock location that holds the store_id for that stock location, remove the available stock location fields on the store and add a 'store' select widget when creating / editing a stock location.
I got like 55 more lines of reasoning, including things like: access to stock locations depending on store, building UI's to transfer / list stock, transferring stock (and what to select), creating stock movement reports per store and more, but let's see about this first, might be enough to expose what i think could use some more work.
Comment #23
guy_schneerson commentedThanks Rob for your thoughts
1. Should a stock location always have a store id set ? No as locations can be not store related like a warehouse or a repair center and the stock transaction system allows for moving stock between those locations supporting back end supply chain functionality that's separated from the store(s).
2. Should 'commerce_stock_location's be able to work without 'commerce_store' ? (other entity types) - Yes same as (1)
3. Can an order exist without setting a store id? & Can an order be create by default without an existing store? (out of the box) Those are commerce core questions and I believe you are corect as list that's my assumption.
5. Can person at source X select target stock location at ...? (or should that occur at the target store) - If I understand you correctly then the answer is both Yes and No.
We have two possible workflows:
Beck end: We are currency providing an API and an admin interface where all is possible
front end / store(s): This is the out of the box logic I am going for
1) A single location for stock allocation should always be available.
2) One or more locations for checking stock availability should always be available.
The reason we are supporting more then one location for checking is that it is common for a store to want to make a product available as long as they have it somewhere. However this aprouch will likely need a richer back-end.
Comment #25
guy_schneerson commented@edurenye thanks for your patch I used it as the bases for the above commit.
Comment #26
rob c commentedI figured you would say something like this :)
Exactly why i asked. In my mind any stock location needs a store first. Not to sell products, but to have a location.
The commerce_store module might have been named commerce_location (cause that's how i look at it). A store of type 'warehouse' is very common in my setup, even stock location that's reserved at the manufacturer is a stock location + store of type manufacturer in my system.
And then permissions. The person moving stock might not even be able to view the stock location on the target side, while they can select the store. (and i wonder if they should be able to view the stock location on the target side anyway, but that's more from a process perspective, because moving stock now requires only an action on the source, while the target should be responsible for selecting the final stock location where the goods will be stored when receiving the stock. The source now selects where the product will be stored on the target, feels odd, not their responsibility).
No sour grapes, it's a choice and implementing as i propose might be done in a new independent module, just think we might debate this a bit, so it's clear for everybody how and why. For a simple webshop with only a single group of administrators the current implementation will work fine, but i wonder about more complex systems. I (for example) (with the current system) would need to limit the list of stock locations people can use in some way and everything is attached to a 'store', users, permissions for related entities, etc, except stock. So now i would need to implement something on top of stock and store to hook these 2 up. With the locations attached to a store this is totally different story.
When working with remote stock locations this might become a problem (i see why this choice is made), but stores are about to get a status field (with a bit of luck). And a different store type already offers a way to add per-type stock location settings (for remote stock api's etc).
See #2921000: Add a status field (enabled/disabled) to stores for the store status issue.
Comment #27
guy_schneerson commentedThanks Rob
I think its early days for stores and I currently see them in the more conventional way - A place that sells stuff.
I totally agree that permissions is an issue and as stores mature in that aria I am planning to follow.
My first goal is to make stock work for "mom and pop shop" and give all the base tools for more involved systems.
Any functionality that's blocking custom development will have high priority to go in and I will do my best to follow how the module is used and any common patterns will be candidate for changes/future versions.
I currently can not see why a location should be tagged with a store(s). I also do not believe in duplicate relationships so its Location->store or store->location we should use, unless the relationships are of a different nature.
A site can also resolve such issues in other ways like only allow creating of locations from a store and linking the two. I personally think that for many of my own use cases, a lot of the entity & relationship creation and management will be automated so for a mark place site it may be: A user registers for the service and a store and location are automatically created and linked together.
Comment #28
rob c commentedUnderstood and agreed.
Simpele use case of why:
Create 25 stores with each 5 stock locations with the exact same name. Think people might not be amused with the current UI. Plus more stock locations only makes this worse. No way to group them logically. And prolly sorted by id or name.
Again i understand why the choice is made, so lets continue.
Comment #29
guy_schneerson commentedHi Rob, I think your use case and most of the others I can think of are UI issues not data modeling / API. also in your case if a business has 25 stores and over a hundred locations he can afford the data entry or to pay someone like you or me to develop a kick ass interface :)
Comment #30
olafkarsten commentedA store in commerce is a billing location. https://drupalcommerce.org/blog/42419/commerce-2x-stories-stores
So a stock location is not a 1:1 relationship to store. Imagine two stores - a french one and a german one. Two warehouses - one for the french shop and one for the german shop and a repairshop that repairs items from both stores. As you cannot sell products / place orders without a store, each location belongs to at least one store, but can belong to multiple stores. I didn't see, how a stock location can't belong to a store. It's a many2many relationship.
So we should dig out pr35. I feel this will give us, most if not all of the extension points we need. It uses the plugin system and the resolver pattern. Commerce core is using this all over the place, so it's good for DX too. I will see if I can get steve back on this - at least to get us started again.
Comment #31
olafkarsten commentedI think we can close this one and handle the individual issues.