Drupal Commerce 2.x - Toutes les cartes pour un commerce métier.

Fabien Clément - @GozOo

Dir. Tech @lequipetech

Drupal & Commerce

A l'origine...

2007: Drupal 5 puis 6 et Ubercart.

2010: Drupal 7, Réécriture complète, création du module Commerce porté majoritairement par les Commerce Guys, société créée pour l’occasion.

Drupal 7 & commerce

Commerce premier à utiliser au maximum les nouvelles fonctionnalités de Drupal 7 (entités, bundles etc) et contribue à l’amélioration du core.

Aujourd'hui

Commerce 2.x, réécriture pour Drupal 8

Une trentaine des 60 modules contrib les plus utilisés ont eu leurs fonctionnalités intégrées à Commerce 2.x.

Drupal 8 & Commerce 2.x

Toujours une référence pour suivre les bonnes pratiques de développement.

Toujours contributeur au core Drupal 8.

Sous le capot de Commerce 2.x

Librairies PHP

Création de librairies PHP utilisables et utilisées par la communauté PHP

  • commerceguys/intl: Librairie d’internationalisation produite par les données CLDR. Gère les devises, leur format et bien plus.
  • commerceguys/addressing: Librairie de gestion des adresse, basée sur les données Google. Gère le stockage et la manipulation des adresses postales.

(Ab)use des entités

  • Store
  • Product
  • Product variation
  • Order
  • Order Item
  • Workflow
  • Checkout
  • Payment
  • Etc.

Mais aussi des plugins

  • Promotion
  • Coupon
  • CheckoutPane
  • PaymentGateway
  • States
  • TaxType
  • Etc.

Commerce Out of the Box

... NON

  • Configuration obligatoire pour démarrer son commerce simple (ex vendre des t-shirts)
  • Créer une boutique
  • Ajouter une devise
  • Définir ses types de produits
  • Gérer les affichages de produits, listing, ajout au panier
  • Parcours d’achat
  • Paiement
  • Pas de thème par défaut
  • etc.

Commerce métier

Qui dit métier, dit développement spécifique.

Terrain de prédilection de Commerce 2.x.

Quasiment tout peut être étendu, modifié, ajouter ses plugins, réagir à des événements, processors etc.

Cas pratiques

Affichages différents d'un même formulaire

Exemple: Un affichage de formulaire spécifique pour les entreprises, un autre affichage pour les particuliers.

Drupal 8 implémente les form view display.

Plusieurs affichages de formulaire d’une même entité suivant des conditions souhaités:

  • Affichage de widgets différents.
  • Affichage de plus ou moins de champs.

Plusieurs checkout (parcours d'achat)

  • Checkout téléchargement de fichier e-book.
  • Checkout achat de livre.

Pour chacun, des étapes et des processus d’achats différents.

Plusieurs checkout

Pour cela:

  • Checkout: entité
  • Mais aussi:
    • Plugins pour gérer les volets (pane).
    • Flux de paiement (checkoutFlow).
    • Resolver pour surcharger les règles du flux de paiement.

Plusieurs stores (boutiques)

Exemple: Besoin de faire un store par pays.

Store: entité

  • Un store a une devise par défaut.
  • Les produits sont assignés à un ou plusieur stores.
  • Le store est disponible pour contextualiser checkout, prix etc.

Configuration des paiements intégrée

Payment: plugin

  • Uniformisation de la configuration des paiements:
    • Crédentials par environnement développement, validation, production.
    • Méthodes et routes pour les retours du service de paiement.

Configuration des paiements intégrée

  • Paiement Onsite (intégré au site).
  • Paiement Offsite (Redirection vers le service de paiement).
  • Méthodes de paiement intégrées au core et surchargeables via plugin.

Price Resolver

Ex: Réservation d’une chambre, possibilité de calculer le prix dynamiquement à partir du prix de base et en fonction de la période, du nombre de personnes etc.

Lors de l’affichage ou de l’utilisation d’un prix calculé, possibilité d’ajouter ses propres règles de calcul.


services:
 booking.room_price_resolver:
   class: Drupal\booking\Resolver\RoomPriceResolver
   tags:
     - { name: commerce_price.price_resolver, priority: 0 }
                        

Adjustments & OrderProcessor

Il est possible d’ajouter des modifications à un total de commande ou de ligne de commande.

Les promotions (anciennement discount) sont un exemple d’ajustement proposé par défaut. Ils permettent d’ajouter des plugins configurables par l’utilisateur.

Les taxes sont un autre exemple d'ajustement fourni par le core.

Adjustments & OrderProcessor

Le module de promotion ajoute un service au transformateur de commande qui lui permet ensuite de sélectionner et appliquer les promotions et ajustements souhaités.


services:
 commerce_promotion.promotion_order_processor:
   class: Drupal\commerce_promotion\PromotionOrderProcessor
   arguments: ['@entity_type.manager']
   tags:
     - { name: commerce_order.order_processor, priority: 50 }
                        

Adjustments & OrderProcessor

Exemple pour appliquer une réduction de n%.


$order->addAdjustment(new Adjustment([
 'type' => 'promotion',
 'label' => t('Discount'),
 'amount' => $adjustment_amount->multiply('-1'),
 'percentage' => $this->getPercentage(),
 'source_id' => $promotion->id(),
]));
                        

Promotions

Promotions (ex discount) et coupons font désormais parties de commerce et sont des plugins facilement extensibles.


/**
 * Provides the product condition for order items.
 *
 * @CommerceCondition(
 *   id = "order_item_product",
 *   label = @Translation("Product"),
 *   display_label = @Translation("Limit by product"),
 *   category = @Translation("Product"),
 *   entity_type = "commerce_order_item",
 * )
 */
class OrderItemProduct extends ConditionBase implements ContainerFactoryPluginInterface {}
                        

Promotions



/**
 * Provides the percentage off offer for orders.
 *
 * @CommercePromotionOffer(
 *   id = "order_external_off",
 *   label = @Translation("Fixed amount off the order total depending of external service"),
 *   entity_type = "commerce_order",
 * )
 */
class OrderExternalOff extends FixedAmountOffBase {
 /**
  * {@inheritdoc}
  */
 public function apply(EntityInterface $entity, PromotionInterface $promotion) {
   $this->assertEntity($entity);
   /** @var \Drupal\commerce_order\Entity\OrderInterface $order */
   $order = $entity;
   $total_price = $order->getTotalPrice();
   $adjustment_amount = $this->getAmount();
   $external_service = \Drupal::service('order.promotion.external.service');
 
   $order->addAdjustment(new Adjustment([
     'type' => 'promotion',
     // @todo Change to label from UI when added in #2770731.
     'label' => t('Discount'),
     'amount' => $external_service->getPromotionAmount($entity),
     'source_id' => $promotion->id(),
   ]));
  }
}
                        

Migration

Plus besoin de module spécifique pour gérer les migrations de commerce 2.x.


id: import_products
label: 'Import products to Commerce'
source:
  ...
process:
  type:
    plugin: default_value
    default_value: default
  title: title_from_import
  ...
destination:
  plugin: 'entity:commerce_product'
                        

Migration - sauf...

Si vous souhaitez migrer un commerce depuis D7 ou Ubercart. Le module commerce_migrate peut vous aider.

Synchronisation services externes

  • Entités et plugins peuvent être créés/modifiés via migration.
  • Des événements (symfony EventSubscribers) permettent de réagir et d’appeler les services au bon moment.
  • Le module REST intégré au core permet une mise en place rapide.

En avance sur le core

  • Gestion des événements plutôt que les hook (adieu les hook!).
  • Des tests unitaires et fonctionnels PHPUnit (+ javascript avec mink).
  • Utilisation de composer depuis ses débuts.

Et bien sur

Une équipe disponible et réactive.

Une adoption constante avec 2k utilisations depuis sa release en septembre.

Pour aller plus loin

La roadmap de commerce 2.x est disponible sur https://www.drupal.org/node/2913801

Des questions ?

Cette présentation est disponible en ligne sur https://gozoo.github.io/prez-drupal-commerce-2-dclannion