Followup to #2511266: Create a service for determining variation availability

PR: https://github.com/drupalcommerce/commerce/pull/593

We need to use the AvailabilityManager to check a product at these events:

  • On product load - disable add to cart if not available
  • On adding to cart - do not add to cart if not available
  • - This is now triggering but needs work.

  • On checkout - do not allow checkout if not available

This is blocking development of the stock module see #2709939: Stock availability checker service implements Commerce AvailabilityCheckerInterface

Commerce_stock() should handle checking for specific quantities of product - if you don't use that module then the availability check should always succeed unless another module causes the check to fail.

To do

the below are all the interactions between the store and availability checker. Some of those can possibly be moved to contrib .

On adding to cart

  • Do not add to cart if not available
  • Do not show the product added message if not available (need to be in commerce)
  • Show a Product was not added because it is unavailable message
  • Allow for the AvailabilityChecker to specify a message/action.

On product load

  • Disable add to cart button if not available (Ideally be in commerce)
  • Allow AvailabilityChecker to specify button state: text, enabled/disabled,action if enabled (specifying the text would do as a start)

On checkout

  • Do not allow entering checkout if not available - redirect to cart
  • AvailabilityChecker to specify the unavailable text
  • Check the AvailabilityChecker for all products before processing payment to make sure all is in stock before taking payment.

Comments

guy_schneerson created an issue. See original summary.

jonas139’s picture

Assigned: Unassigned » jonas139
agoradesign’s picture

What if you want to allow purchasing out-of-stock products, but only show info messages and/or calculate a different delivery time, etc?

For that requirement, we could do two things:

  1. Make disabling the button and the check during adding optional
  2. Implement a custom availability checker, that always returns TRUE

Both seem acceptable solutions to me, but we should think of, which one's the better way, before we implement this...

jonas139’s picture

True, I guess this needs some more thinking before implementing it.

jonas139’s picture

Assigned: jonas139 » Unassigned
guy_schneerson’s picture

Maybe we need a second service: availability actions or extending the existing to handle the actions.

jonas139’s picture

I guess the option to sell of out-of-stock products is a good case.
Maybe also add the option to either recalculate the availability of the product or just display a (custom) message and disable the add to cart button?

agoradesign’s picture

Or maybe we can just do it as simple as proposed in the issue description as well.

The philosophical question here is to clarify the term "available": is an out-of-stock product on a site, which wants to allow to sell out-of-stock product, "available" or not?

A slightly different thing is, if you want to output the availability information on the product on the page. Depending on how granular the information is, you want to display, asking the availabilty manager could be enough or not. If you want to just display "Available: yes/no", then you could ask the availabilty manager as well. But as soon as you want to display e.g. traffic lights, where yellow means "low on stock", or want to simply display "available" down to a specific amount, and for the rest something like "less than xx items on stock", etc, you would have to implement your own logic anyway.

So, if you e.g. want to sell out-of-stock products and display the "less than xx items on stock" information, you could use the "always in stock" availability checker anyway, because you have to implement the logic to display that message youself anyway

guy_schneerson’s picture

Also need to be able to repurpose the button for things like "Let me know wen back in stock" and "Reserve product".
If we can give the task to a plugable service we just need to implement the basic use case and live it to contrib.

jonas139’s picture

My idea was that we just display the yes/no message for the availability. The traffic lights (or something similar) would be a nice-to-have feature but is not really the original issue (I guess). Furthermore I would also add the option to let the user determine whether or not the add to cart button needs to be disabled or not.

At the other hand, I really like the idea for the custom availability checker and the 'product reservation/keep me posted' service. The question is, is this really necessary for default commerce behavior?

bojanz’s picture

Preordering and the related logic (notifications) is definitely contrib material.
Our concern here is to ensure that whatever logic we add can easily be swapped (service sounds good).

guy_schneerson’s picture

would be good to get going with a patch that simply disables the "add to cart" button and sets the text to "currently unavailable" to get things going and help test the stock and any other availability modules. We can then look at a full implementation.
the check should be:

<?php
    $availabilityManager = \Drupal::service('commerce.availability_manager');
    $available = $availabilityManager->check($product_variation_id, 1);
?>

Not sure how to interact with the cart form so if anyone knows please help.

Also a second check on validating the submitted form would be good (replacing 1 with the requested quantity).

Once we figured out the mechanics of working with the cart form, it will be easier to develop more flexible business logic.

steveoliver’s picture

Issue summary: View changes

Updated issue summary based on comment #12 on add to cart form validate() checking, and adding idea about holding/decrementing available qty when added to cart.

kscheirer’s picture

Title: Add to Cart form to use AvailabilityManager » Use AvailabilityManager service
Priority: Normal » Major
Issue summary: View changes

Updated issue description. Any guidance on proper implementation?

kscheirer’s picture

Issue summary: View changes
guy_schneerson’s picture

The AvailabilityManager is now triggered by the add to cart form and if the product is out of stock the item is not added (I think it may be added and then removed).
However the form is not aware of the AvailabilityManager and both AvailabilityManager->check() & AvailabilityOrderProcessor->process() don't store the result of the check so even if the form had access to the AvailabilityManager the result of the check would not be available.
The result of all this is that the user gets the message "Product X added to your cart." although it wasn't.

guy_schneerson’s picture

Issue summary: View changes
guy_schneerson’s picture

Issue summary: View changes
guy_schneerson’s picture

I updated the description the Issue summary to include all the points of interaction between the store and the AvailabilityManager. Some of those may be handled by contrib.

guy_schneerson’s picture

One more observation: if we have products in our cart that are no longer available and we add a new product to the cart the availability check is run on the cart(order) and those products will be removed without prompting the user.

bojanz’s picture

Yes, that was the Commerce 1.x behavior too (unsure if Commerce 1.x showed a message along with that, should be checked)

guy_schneerson’s picture

Hi @bojanz Not sure I follow. Did Commerce 1.x have something like the availability manager?
The approach of stock was:
on the cart form only check the viewed/added product
on checkout: check the cart and if any items are out of stock send user to the cart page with a message explaining whats out of stock.

Not sure what is the perfect UI but at some point I am sure one of us will want a wait list type functionality and things disappearing from a cart may make this harder.

guy_schneerson’s picture

One more issue. using stock to illustrate.

Product X has quantity 2.

User adds product x to basket
-> AvailabilityManager calls check() with $quantity = 1
-> StockAvailabilityChecker return TRUE
Cart now has 1 of Product X

User adds one more product x to basket
-> AvailabilityManager calls check() with $quantity = 2
-> StockAvailabilityChecker return TRUE
Cart now has 2 of Product X

User adds one more product x to basket
-> AvailabilityManager calls check() with $quantity = 3
-> StockAvailabilityChecker return FALSE (as it only has 2)
-> AvailabilityOrderProcessor removes product X as it was told by the availabilityManager that it is not available.
Cart now has 0 of Product X

I think that we should consider returning the number of available units instead of TRUE/FALSE.

steveoliver’s picture

Status: Active » Needs review

For the points outlined above, I don't think a boolean response to check() will work. Instead of a check() method, what about a getAvailability method, which returns an AvailabilityResponse value object that contains $entity, $context, $minimum, and $maximum values.

By checking that the requested quantity is still within range of availability, AvailabilityOrderProcessor::process() can accurately know when to remove the item from the order, or to update the quantity to the max available.

This could use some more thought around how to deal with NULL / no opinion, but see POC here: https://github.com/drupalcommerce/commerce/pull/593

guy_schneerson’s picture

@steveoliver that will resolve most of the issues.
The only remaining issue will be:

  1. Ability to control the message (if we can't then we can always add a second message in contrib custom code)
  2. Control the text, state and action of the add to cart button, if the product is out of stock. (may possibly need to be done outside core commerce).
steveoliver’s picture

Title: Use AvailabilityManager service » Finalize the availability manager service
steveoliver’s picture

Remaining tasks:

- Finish building the availability response classes
- Work out the line between commerce core and commerce contrib for configurable actions/messaging based on ^

Work is happening at https://github.com/drupalcommerce/commerce/pull/593 -- I'll resume today or tomorrow.

ransomweaver’s picture

I'd like to contribute to shaping the discussion of how backorder is going to work with commerce_stock, as its a critical need for the app I'm building at the moment.

Use cases are always good, so I will describe the needed functionality for us, and how I have gone about it so far.

For our app--
* variation has stock
* variation may or may not be sold with 0 stock (backorder/custom order) depending on some setting for the variation.
* variations that may not be purchased, due to 0 stock and backorder not allowed:
- have add-to-cart button disabled
- display "availability: out of stock"
- are filtered out from a view of available products
* a variation that can be backordered needs to display a custom "Availability" string, supplied by the product owner on a per-variation basis. E.g. "ships in 3-4 weeks"

How I have built this so far:
- local stock service
- commerce_stock field_stock on variation, uses stock api to add stock to variations via UI or custom csv processor
- allow_no_stock_sale (backorder) bool field on variation
- no_stock_sale_message textfield on variation
- custom StockFormatter to display e.g. " 7 remaining" or "out of stock" or "ships in 3 weeks" depending on the custom fields above

Of course, the above does not actually do anything about disabling the cart button, views filtering or getting a back-orderable product into the cart.

What I would like to know/understand is how can I integrate the above with the developing Stock availability service, or how to change my approach to integrate with that service.

steveoliver’s picture

@ransomweaver -- I think the approach you've taken so far makes sense--you'll need a custom formatter for the stock field if you choose to show it, and some form alteration on the add to cart form 'submit' button.

I've made progress on the availability response PR here: https://github.com/drupalcommerce/commerce/pull/593/files

AvailabilityManager::check returns a (new) AvailabilityResponseInterface (one of AvailabilityResponseNeutral, AvailabilityResponseAvailable, or AvailabilityResponseUnavailable). Each response has these six methods: isNeutral(), isAvailable(), and isUnavailable, and getMin(), getMax(), and getReason. With these methods any response from the Availability Manager service can be used to make informed decisions in about what to do or show in case of needing to remove or change the quantity of any item under consideration.

The implications of the responses, i.e. to disable the add to cart form, show other actions, etc. should come from each module(s) use cases and configuration. PR 593 makes the add to cart form able to be altered by e.g. commerce_stock or your custom implementation.

This issue should be concerned only with the API of the availability manager service -- please review the PR and let me know your thoughts.

For reference, here's what the commerce_stock local storage module might do to disable the add to cart form when an item is unavailable for a qty of 1:

diff --git a/modules/local_storage/commerce_stock_local.module b/modules/local_storage/commerce_stock_local.module
index af686c2..060b880 100644
--- a/modules/local_storage/commerce_stock_local.module
+++ b/modules/local_storage/commerce_stock_local.module
@@ -1,5 +1,30 @@
 <?php
 
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\commerce\Context;
+
+function commerce_stock_local_form_alter(&$form, FormStateInterface $form_state, $form_id) {
+  if (!empty($form['base_form_id']) && $form['base_form_id']['#value'] == 'commerce_order_item_add_to_cart_form') {
+    /** @var \Drupal\commerce_cart\Form\AddToCartForm $form_object */
+    $form_object = $form_state->getBuildInfo()['callback_object'];
+
+    /** @var \Drupal\commerce_order\Entity\OrderItemInterface $order_item */
+    $order_item = $form_object->getEntity();
+    $purchasable_entity = $order_item->getPurchasedEntity();
+    $store = $form_object->selectStore($purchasable_entity);
+    $context = new Context($form_object->getCurrentUser(), $store);
+    /** @var \Drupal\commerce\AvailabilityResponse\AvailabilityResponseInterface $availability */
+    $availability = $form_object->getAvailabilityManager()->check($purchasable_entity, 1, $context);
+
+    if ($availability->isUnavailable()) {
+      $form['actions']['submit']['#value'] = t('Unavailable');
+      $form['actions']['submit']['#attributes'] = [
+        'disabled' => 'disabled',
+      ];
+    }
+  }
+}
+
 /**
  * Implements hook_cron().
  */
diff --git a/src/StockAvailabilityChecker.php b/src/StockAvailabilityChecker.php
index fb6c354..d3eb088 100755
--- a/src/StockAvailabilityChecker.php
+++ b/src/StockAvailabilityChecker.php
@@ -3,6 +3,7 @@
 namespace Drupal\commerce_stock;
 
 use Drupal\commerce\AvailabilityCheckerInterface;
+use Drupal\commerce\AvailabilityResponse\AvailabilityResponse;
 use Drupal\commerce\PurchasableEntityInterface;
 use Drupal\commerce\Context;
 
@@ -46,27 +47,25 @@ class StockAvailabilityChecker implements AvailabilityCheckerInterface {
    * {@inheritdoc}
    */
   public function check(PurchasableEntityInterface $entity, $quantity, Context $context) {
-    if (empty($quantity)) {
-      $quantity = 1;
-    }
     $stock_service = $this->stockServiceManager->getService($entity);
     $stock_checker = $stock_service->getStockChecker();
     $stock_config = $stock_service->getConfiguration();
-
     $entity_id = $entity->id();
-
-    // Get locations.
     $locations = $stock_config->getLocationList($entity_id);
 
-    // Check if always in stock.
-    if (!$stock_checker->getIsAlwaysInStock($entity_id)) {
-      // Check if quantity is available.
-      $stock_level = $stock_checker->getTotalStockLevel($entity_id, $locations);
-
-      return ($stock_level >= $quantity);
+    if ($stock_checker->getIsAlwaysInStock($entity_id)) {
+      return AvailabilityResponse::available();
     }
 
-    return TRUE;
+    $stock_level = $stock_checker->getTotalStockLevel($entity_id, $locations);
+    // @todo Minimum qty instead of 0?
+
+    if ($stock_level > $quantity) {
+      return AvailabilityResponse::available(0, $stock_level);
+    }
+    else {
+      return AvailabilityResponse::unavailable(0, $stock_level, 'maximum exceeded');
+    }
   }
 
 }

steveoliver’s picture

This is now passing Travis CI builds and is ready for a real review. See https://github.com/drupalcommerce/commerce/pull/593.

Copied from the latest PR review comment:

The main change is in classed responses, and returning min and max values for available and unavailable responses. Min and Max are the widest range of all indicated availability.

An explicit "unavailable" return from any checker will automatically return unavailable for the entire check.

No opinion (Neutral) responses are still ignored / passed on from AvailabilityManager::check() as available.

Added the availability manager service to add to cart form, originally thinking we'd use it within the core add to cart form, but instead not doing anything, but providing it and the currentUser(), selectStore() methods, plus the base form id as conveniences for hook_form_alter implementations.

guy_schneerson’s picture

I really like the idea of the range although I think the min/max should be reversed see my note.
One more potential complication is that some modules may have an opinion only on the min or max but I suppose in such case they can just return an obscene large number for max and something like 0.0001 for min (as we need to support decimal quotients).
I can imaging cases where we have multiple stock fulfillment services that will have the other requirements but I think we should address those by:
a) in the stock module
b) custom/contrib modules inheriting from stock and providing the additional min/max calculation.

steveoliver’s picture

I agree on the min/max() swap Guy recommends. While working on this, as you can see by my thinking about min/max before being convinced by Guy, I have been thinking of Availability in the context of stock only ... but of course availability responses can come from other considerations, such as business rules for min/max per order, etc.

guy_schneerson’s picture

Hi @ransomweaver I think we need to limit the scope of the availability manager. so looks like we are using an and for available/not available. So if one of the checkers says its not available then its not and an intersection of min/max (Steve is making this change).
The way i think you should address your needs is by inheriting from the commerce stock, that way you can create a "Local stock with back order" service. That will allow you to control the order of checks using your own business logic with full access to the inherited functionality.
would be nice to see your code if you manage to make it general. Maybe can be added to the stock module as a sub module or a another contrib.
At some point I think we will add an option to reserve stock on an "add to cart" this will need a cron job for returning the stock after a given time.
We should move most of this discussion to the stock issue Q.

ransomweaver’s picture

Ok @guy, I was going to work on my checker today, but I will cease that until you guys are finished, and approach it as building my own local stock service.

guy_schneerson’s picture

@ransomweaver cool, I think that once the availability manager service is finalize (this issue) the part you need to override should not change and you can start your work. Let us know how you get on.

ransomweaver’s picture

I have made a sandbox module called commerce_stock_backorderable here: https://www.drupal.org/sandbox/ransomweaver/2848270

I find it works as needed with not other alterations to commerce_stock that i can see.

londova’s picture

@ransomweaver
Could you please provide the link to download the module and test it?
Thanks

ransomweaver’s picture

@londova, how do you mean? Its a sandbox project, is there some other way to link to a sandbox project?

heddn’s picture

Tagging. This is blocking #2613264: Drupal 8 port of Commerce Stock. Leaving at major, since this a blocker.

mglaman’s picture

Issue summary: View changes

Put PR link in summary, took a minute to find it.

mglaman’s picture

I did a cursory review. I think it looks good so far. Just a constants fail on PHP < 7. Some of the visibility changes on methods I'm unsure of. I think users altering the form _that much_ should extend it and implement their class. This is what I have done on three client sites, now.

joachim’s picture

Status: Needs review » Needs work

That PR is changing AvailabilityCheckerInterface, which now we're at 2.0 would be breaking API.

steveoliver’s picture

Status: Needs work » Active

To help move this issue forward, I'll summarize the changes related to the availability manager, availability checkers, and availability responses.

  1. The signatures of AvailabilityManager::check and AvailabilityCheckerInterface::check have not changed, they are still check(Entity, Quantity, Context).
  2. But responses from availability checks are no longer TRUE|FALSE|NULL, but are now Available, Unavailable, Neutral (AvailabilityResponseInterface) value objects
  3. Responses have min, max and reason properties.
  4. The AvailabilityManager will immediately return an Unavailable response (which may include its own reason) received from any checker.
  5. In the case of any checkers returning Available responses, the highest minimum and lowest maximum of all checks will be returned.
  6. If there is some availability from the checkers, but the checked quantity is not available within the range of all checks, an Unavailable response is returned with the minimum and maximum quantity available and a reason string--either "minimum not met" or "maximum exceeded".
  7. Neutral and Available responses do not have reasons.

If this logic works for the use cases of those following this issue, I say we add a few more assertions for our expected reason messages. If there are any questions or concerns, please comment. So close!

joachim’s picture

> But responses from availability checks are no longer TRUE|FALSE|NULL, but are now Available, Unavailable, Neutral (AvailabilityResponseInterface) value objects

Now that we are at a stable release, that breaks API, because it breaks any code that implements AvailabilityCheckerInterface::check.

ransomweaver’s picture

I think in practice, contrib code will not consume AvailabilityResponses, it will generate them. e.g. my commerce_stock_backorderable sandbox module requires this commerce PR as a patch, and it overrides StockAvailabilityChecker to take into account that the product may be backorderable, allowing the customer to buy more than the existing stock, and it tells commerce with an AvailabilityResponse.

So the situation Joachim should be concerned about is commerce receiving a TRUE|FALSE|NULL when it expects an AvailabilityResponse. Can't we make this commerce code backwards compatible and handle boolean as well as AvailabilityResponse?

epetvir’s picture

I've been trying to disable the add-to-cart button when a variation is out of stock, following the reference in #29.

This works fine for products with only one variation. However, when the add-to-cart form of a product with multiple variations is Ajax refreshed, $form_state->getBuildInfo()['callback_object'] always references the default variation.

I've worked around this by using $form_state->get('selected_variation') when it's available (ajax refresh) and reverting to build_info when the product page is loaded. This seems to work, but I don't know how good an approach it is.

ransomweaver’s picture

@epetivir this is the subject of this issue https://www.drupal.org/node/2847529 and commerce_stock PR #37

guy_schneerson’s picture

@ransomweaver will try and look into #37 in the next few days.

guy_schneerson’s picture

@ransomweaver yes #37 looks good also created a https://github.com/BBGuy/commerce_stock/pull/38 for the other changes needed for the new AvailabilityResponse.
Both can go in once the availability manager service PR is committed to commerce.

cocoshogo’s picture

Hello All,
My Observations and comments may be to late to be considered but I have a thought I would like to get some feedback. Can the availability use the Drupal State system? So that site owners could define custom Availability states, and actions to take once Stock goes into handout of that state. For example I could define that the product is still purchasable after -20 items have been sold. After that the availability goes into a Out of Stock state and is no longer purchasable. The query for the cart would be to see if the product is purchasable or something like that. Now, Im not a developer and may be ignorant about my question. But I think this would allow for better per site and per product handling of how they want to sell or back sell items.

steveoliver’s picture

@cocoshogo: Yes, with the API change proposed in this issue, you would implement an availability checker service that inspects your stock and inventory business logic, and respond with AvailabilityResponse::available()/unavailable()/neutral() each time availability was checked.

Aside from the breaking API change(s) pointed out by Joachim in #44 (which of course needs discussion/planning), I wonder if the AvailabilityResponseInterface and these three specific types of responses (Available, Unavailable, Neutral), with their min and max values, and reason message, is flexible enough to respresent all possible availability responses.

For example, do we want the API to qualify 'availability' requests with what it is requesting a check for--e.g. 'order', 'backorder'?

Or, do we want to return not a reason String but a Reason type of value object, where we can respond to different reasons for a response, such that the next checker(s) can be informed with the results' passed to them in the resolver chain?

I think any comments on that topic might help spark the discussion and review needed to get this in.

joachim’s picture

> For example, do we want the API to qualify 'availability' requests with what it is requesting a check for--e.g. 'order', 'backorder'?

Regarding that, I filed #2937041: AvailabilityManager needs to be aware of the order, if there is one, and there is also #2862546: Context for Availability Manager,

bojanz’s picture

Status: Active » Needs review

It's time to finally wrap this up. Sorry for the long wait.

I've pinged guy_schneerson to go over some of the details on Slack, but here are some questions and notes in the meantime:

0) Note the current AvailabilityManagerInterface docblock:

 * Example checks:
 * - Whether the entity is in stock.
 * - Whether the entity's "available on" date is before the current date.

We want to make sure that the "available on" use case isn't made too awkward by hardcoding only stock expectations. Probably by documenting that the returned "known quantity" can be NULL.

1) Why does the new API have min/max quantities, instead of a single quantity, indicating how many items are available? What do we gain with that approach?
2) If the response now tells us the available quantity, is there a point in passing $quantity to the method at all? The idea was that were asking for a specific $quantity, but that's obviously not flexible enough.

3) Why is there a getReason() when it's not used, and documented as "Intended for developers, hence not translatable."?
We have the need for the following messages:
a) The general message that can be shown on the product (In stock / Discontinued / Out of stock / 10 remaining / Ships in 10 weeks)
b) the add to cart submit button label when the button is disabled (is this needed if we have the general message somewhere above?)
c) A message shown when the product is removed due to unavailability ("@entity has been removed from your cart because it is no longer available")
d) A message shown when the product quantity is reduced due to unavailability ("@entity has been removed from your cart because it is no longer available")
I thought we'd want to let the AvailabilityResult dictate at least some of them (a, or a/b for example)?

4) Right now we follow the Commerce 1.x logic of running the checkers on each order refresh. I think that we need to remove that, and make the runs explicit: add to cart form submit -> entering checkout -> confirming checkout (just before payment). That would help with performance too.
Related: #2757369: commerce.availability_manager needs to pass what "phase" we're checking in.

5) Do we want availability checkers to run in the admin UI, when adding a product to an order? Or does admin know best? Or should they get an informative message only?

6) Same question for the REST API, where I'm guessing the answer depends on #5. Do we validate on POST /carts/{id}/items but not on /orders/{id}/items?

6) Right now availability is a base module API, so it can't be aware of orders. We'll need to introduce an order-aware API such as #2948117: Add an API for validating whether an order is allowed to enter/complete checkout, same way we have price resolvers and order processors. I thought about whether that would make the product-level API irrelevant, but it still feels like it would have value.

It is true that we'll most likely break BC by fixing this. I'll figure out the best way to minimize that once we agree on the ideal API.

mglaman’s picture

1) Why does the new API have min/max quantities, instead of a single quantity, indicating how many items are available? What do we gain with that approach?

I've seen this where there is a maximum order amount. But I don't know if it is something we should support. I'd rather it be a simple "this how much is available" and make sure business logic on minimum and maximum buys can be respected by hooking into the system.

6) Same question for the REST API, where I'm guessing the answer depends on #5. Do we validate on POST /carts/{id}/items but not on /orders/{id}/items?

I'd imagine yes in both cases. Because `/orders/{id}/items` could be a decoupled admin theme.

tormi’s picture

Issue summary: View changes

Minor issue summary correction.

olafkarsten’s picture

my2cents to #53,

1) Why does the new API have min/max quantities, instead of a single quantity, indicating how many items are available? What do we gain with that approach?

This is overly complex. A single quantity should be sufficient.

2) If the response now tells us the available quantity, is there a point in passing $quantity to the method at all?

I guess it clearifies the responsibility, if we don't pass it along. -> "How many of the purchasable entity is available in this context?". But I think it will make in even harder in terms of BC?

to 3) I would only ask for 3a. That should be sufficient as default. I guess getReason() was meant to do so? I would rename it to something like "getDisplayMessage()" or so. I'm a fan of small API's. On the other hand, its propbably cheap and we provide a base class anyway. So we could give meaningful defaults.

to 5) We want the checkers to run. [I never met an admin that know best ;)]

I thought about whether that would make the product-level API irrelevant, but it still feels like it would have value.

I think so, too. It would be a really bad UX, if you let the user adding stuff to the cart and at checkout throw a bunch of messages and quantity adjustments at him.

guy_schneerson’s picture

The stock module will (at list for now) use it's own code and not the availability manager service. We need to provide a working module soon. We can look at this at a later stage.

Wisamx’s picture

I am really in need for sock management right now.
I made a simple one https://github.com/wisamx/commerce_simple_stock
(getting some code from inventory and another commerce stock project)
maybe it benefits someone else.

guy_schneerson’s picture

We now have a version with UI enforcement (add to cart form / cart page / checkout) of stock in testing and will go to alpha soon. Can be found at https://github.com/BBGuy/commerce_stock/pull/55
feedback appreciated

edurenye’s picture

Status: Needs review » Needs work

https://github.com/drupalcommerce/commerce/pull/593
The PR does not apply anymore, it must be rebased.

guy_schneerson’s picture

@edurenye I think the availability manager has been abandoned (at least for now)

steveoliver’s picture

Happy to see this issue revived ;)

mglaman’s picture

Component: Product » Other
Category: Task » Plan
Status: Needs work » Active
mglaman’s picture

We definitely need to triage this issue.

#3138952: Make the AvailabilityManager order aware landed which improves the availability manager. It also adds messaging support. The availability result message should cover a lot of the remaining items.