0

I need to set order increment quantities in my Commerce 2 website. The website has two stores: retail and wholesale. Customers who are shopping in my "retail consumers" store must have increments of 6 products in their cart in order to check out (6, 12, 18, 24, etc). Customers in my "wholesale consumers" store must have at least 4 products in their cart in order to check out (4, 8, 12, 16, etc).

My plan is to add a custom Condition that can be used for the two payment gateways that will be used in the stores (one for each store). That custom Condition would allow me to designate an increment value for the product quantity for each gateway. "Make this gateway available if the cart contains an increment of 6 products".

I recently created a similar plugin for product quantity minimums in the cart, and I think I can re-use most of that code with a few adjustments. I am just not sure how to factor in the incremental requirement. It would be acceptable to hard-code the increments of 6 if that is the best/easiest way to do it; I could then create two separate condition plugins, one for 6 and one for 4.

Below is the Condition plugin code I have so far:

<?php

namespace Drupal\order_total_quantity_increments\Plugin\Commerce\Condition;

use Drupal\commerce\Plugin\Commerce\Condition\ConditionBase;
use Drupal\commerce_price\Calculator;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;

/**
 * Provides the quantity increment condition for order items.
 *
 * @CommerceCondition(
 *   id = "order_total_quantity_increments",
 *   label = @Translation("Quantity Increment"),
 *   display_label = @Translation("Limit by quantity increments"),
 *   category = @Translation("Products"),
 *   entity_type = "commerce_order",
 *   weight = 10,
 * )
 */
class OrderTotalQuantityIncrements extends ConditionBase {
    
  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return [
      'increment' => NULL,
    ] + parent::defaultConfiguration();
  }

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
    $form = parent::buildConfigurationForm($form, $form_state);

    $increment = $this->configuration['increment'];
    
    if (isset($increment) && !isset($increment['number'])) {
      $increment = NULL;
    }

    $form['increment'] = [
      '#type' => 'number',
      '#title' => t('Increment'),
      '#default_value' => $this->configuration['increment'],
      '#min' => 1,
      '#required' => TRUE,
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
    parent::submitConfigurationForm($form, $form_state);

    $values = $form_state->getValue($form['#parents']);
    $this->configuration['increment'] = $values['increment'];
  }

  /**
   * {@inheritdoc}
   */
  public function evaluate(EntityInterface $entity) {
    $this->assertEntity($entity);
    /** @var \Drupal\commerce_order\Entity\OrderInterface $order */
    $order = $entity;
    $increment = '0';
    foreach ($order->getItems() as $order_item) {
      $increment = Calculator::add($increment, $order_item->getQuantity());
    }

  }

}

I believe I have to modify the last part of the code (below) or add something after it.

  public function evaluate(EntityInterface $entity) {
    $this->assertEntity($entity);
    /** @var \Drupal\commerce_order\Entity\OrderInterface $order */
    $order = $entity;
    $increment = '0';
    foreach ($order->getItems() as $order_item) {
      $increment = Calculator::add($increment, $order_item->getQuantity());
    }

  }

Can anyone please provide me with a direction to go in/guidance on how I should modify the code to meet my objective?

1 Answer 1

1

Per OP's comment, updated solution:

 public function evaluate(EntityInterface $entity) {
    $this->assertEntity($entity);
    /** @var \Drupal\commerce_order\Entity\OrderInterface $order */
    $order = $entity;
    $increment = $this->configuration['increment'];
    $total = 0;

    foreach ($order->getItems() as $order_item) {
      $total += $order_item->getQuantity();
    }
    if ($total % $increment !== 0) {  return FALSE;  }

    return TRUE;
  }
4
  • I think this is very close! When I add 6 or 12 or 18 of one product to the cart, it does work. However, if I add 5 of Product A and 1 of Product B to the cart (total of 6 products in the cart, it fails. If I add 6 of Product A and 6 of Product B to the same cart (12 products total), it succeeds, but the customer needs to be able to order a mixed cart of any products in any quantity, as long as the total quantity is an increment of 6 (divisible by 6). Any ideas on why that would be and how to resolve it? Thank you!
    – hockey2112
    Aug 27, 2020 at 2:41
  • The solution was to edit a couple of lines in the code you provided. Thanks again for your help! Can you edit your answer to include this code (assuming that you agree with it, of course): foreach ($order->getItems() as $order_item) { $total += $order_item->getQuantity(); } if ($total % $increment !== 0) { return FALSE; } return TRUE; }
    – hockey2112
    Aug 27, 2020 at 20:49
  • @hockey2112 Updated answer per your comment :) Sep 3, 2020 at 21:08
  • 1
    Thanks again, much appreciated!
    – hockey2112
    Sep 3, 2020 at 22:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.