Mettre en place un contrôle de stock simple avec Drupal Commerce 2

stock of coffee box

Si nous ne disposons pas (encore) d'une solution contribuée (commerce_stock devrait être prochainement être disponible), Drupal Commerce 2 dispose d'ores et déjà d'une API pour mettre en place un contrôle des stocks, avec le service Availability Manager.

Il s'agit d'un service collector qui va collecter tous services déclarés sur le tag commerce.availability_checker. Son principe de fonctionnement est pour l'instant assez simple. Il suffit qu'un service qui implémente l'Interface AvailabilityCheckerInterface retourne FALSE pour que le produit ne soit plus considéré comme disponible.

Regardons comment mettre en place un contrôle de stock très simple, basé sur un champ (par exemple field_stock) qui aura été ajouté sur un produit.

Depuis notre module MY_MODULE, déclarons notre service au moyen du fichier MY_MODULE.services.yml.

services:

  my_module.availability_product_variation:
    class: Drupal\my_module\AvailabilityProductVariation
    arguments: ['@entity_type.manager']
    tags:
      - { name: commerce.availability_checker, priority: 100 }

Puis déclarons notre Class AvailabilityProductVariation.

<?php

namespace Drupal\my_module;

use Drupal\commerce\Context;
use Drupal\commerce\PurchasableEntityInterface;
use Drupal\commerce_product\Entity\ProductVariationInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\commerce\AvailabilityCheckerInterface;

/**
 * Provides an availability checker that removes variations that are no longer available.
 */
class AvailabilityProductVariation implements AvailabilityCheckerInterface {

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;


  /**
   * Constructs a new AvailabilityOrderProcessor object.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The availability manager.
   */
  public function __construct(EntityTypeManagerInterface $entity_type_manager) {
    $this->entityTypeManager = $entity_type_manager;
  }

  /**
   * {@inheritdoc}
   */
  public function applies(PurchasableEntityInterface $entity) {
    if ($entity->hasField('field_stock')) {
      $stock = $entity->field_stock->value;
      if (is_null($stock)) {
        return FALSE;
      }
      return TRUE;
    }
    return FALSE;
  }

  public function check(PurchasableEntityInterface $entity, $quantity, Context $context) {
    $stock = (integer) $entity->field_stock->value;
    $quantity = (integer) $quantity;
    if ($quantity > $stock) {
      return FALSE;
    }
  }
  
}

Ce service doit implémenter 2 méthodes :

  • applies() qui va déterminer si la vérification doit être réalisée ou non sur l'entité
  • check() qui va vérifier effectivement la disponibilité du produit.

Avec ce simple service, nous disposons alors d'un contrôle sur les produits ajoutés au Panier en fonction d'un champ Stock dédié.

Nous pouvons aussi maintenant faire appel au service AvailabilityManager directement au niveau du formulaire d'ajout au panier pour réagir en fonction de la disponibilité d'un produit sur le bouton d'ajout au panier. Par exemple, nous pouvons alors altérer ce formulaire avec ces quelques lignes qui auront pour effet de désactiver le bouton d'ajout au panier et d'ajouter un message d'avertissement dessous.

/** @var \Drupal\commerce\AvailabilityManagerInterface $availabiltyManager */
$availabiltyManager = \Drupal::service('commerce.availability_manager');

$entityTypeManager = \Drupal::entityTypeManager();
/** @var \Drupal\commerce_order\Entity\OrderInterface $order */
$order = $entityTypeManager->getStorage('commerce_order')->create(['type' => 'default']);
$store = $entityTypeManager->getStorage('commerce_store')->loadDefault();
$context = new \Drupal\commerce\Context($order->getCustomer(), $store);

if (!$availabiltyManager->check($purchased_entity, '1', $context)) {
  $form['actions']['submit']['#attributes']['disabled'] = TRUE;
  $form['actions']['submit']['#suffix'] = '<div class="description upper small out-stock">' . t('Out of stock') . '</div>';
}

Difficile également d'introduire une simple gestion de stock avec Drupal Commerce 2 sans mentionner un module de gestion de stock disponible sur GitHub qui semble prometteur et opérationnel dès maintenant. Mais la piste générique à privilégier sur le long terme reste assurément le module contribué commerce_stock dès que celui-ci sera finalisé.

La gestion de stock peut varier de façon infinie sur un projet e-commerce. Faut-il bloquer les commandes une fois le stock fini, continuer à enregistrer des commandes en attente, tout en prévenant le client ? Que faire sous une certaine limite atteinte ? Emettre une alerte en direction du gestionnaire ? Afficher un message aux visiteurs ? Si vos besoins métier en matière de gestion de stock restent standard, ils seront très certainement couvert par commerce stock. Et même si ce n'était pas le cas, l'API à disposition permettra d'adresser simplement les cas les plus atypiques avec l'aide d'un développeur Drupal 8

Enfin pour conclure, n'hésitez pas à suivre cette issue Finalize the availability manager service qui devrait introduire des modifications substantielles quant aux possibilités offertes nativement par cette API.

 

Commentaires

Ajouter un commentaire