Comment ajouter un attribut de produit personnalisé en tant que filtre pour les tarifs d'expédition
Publié: 2020-04-07Souvent, dans Magento 2, le nombre d'attributs de produit standard pouvant être utilisés pour définir des conditions est limité. Une personnalisation supplémentaire serait nécessaire pour répondre aux besoins de l'entreprise.
À partir de cet article, vous apprendrez comment y parvenir et ajouter des attributs de produit personnalisés en tant que filtre pour les tarifs d'expédition.
Remarques:
- Voir l'exemple de code complet sur GitHub.
- La première partie de l'exemple, qui ajoute l'attribut 'Volume Weight' comme filtre aux tarifs d'expédition, est disponible ici.
- Le module original Magento 2 Shipping Suite Ultimate est requis.
Allons directement à discuter de ce qui doit être fait exactement pour atteindre l'objectif.
Table des matières
- Guide étape par étape sur l'ajout d'un attribut de produit personnalisé
- Étape 1. Créer un nouveau module en ajoutant les fichiers de base
- Étape 2. Créer une structure de module
- Étape 3. Interface utilisateur
- Formulaire
- Grille
Guide étape par étape sur l'ajout d'un attribut de produit personnalisé
Étape 1. Créer un nouveau module en ajoutant les fichiers de base
Commencez par nommer le module :
> app/code/MageWorx/ShippingRateByProductAttribute/registration.php <?php /** * Copyright MageWorx. All rights reserved. * See LICENSE.txt for license details. */ \Magento\Framework\Component\ComponentRegistrar::register( \Magento\Framework\Component\ComponentRegistrar::MODULE, 'MageWorx_ShippingRateByProductAttribute', __DIR__ );
Ensuite, détectez et déclarez ses exigences. Vous devrez également donner un nom à notre module pour le compositeur, définir la version et ajouter une courte description :
> app/code/MageWorx/ShippingRateByProductAttribute/composer.json { "name": "mageworx/module-shipping-rate-by-product-attribute", "description": "Shipping Rules Extension: Adds product attribute to the Rates", "require": { "magento/module-shipping": ">=100.1.0 < 101", "magento/module-ui": ">=100.1.0 < 102", "mageworx/module-shippingrules": ">=2.7.1" }, "type": "magento2-module", "version": "1.0.0", "license": [ "OSL-3.0", "AFL-3.0" ], "autoload": { "files": [ "registration.php" ], "psr-4": { "MageWorx\\ShippingRateByProductAttribute\\": "" } } }
De plus, nous pouvons définir le nom initial et la version dans la configuration de Magento 2, déclarer la séquence :
> app/code/MageWorx/ShippingRateByProductAttribute/etc/module.xml <?xml version="1.0"?> <!-- /** * Copyright MageWorx. All rights reserved. * See LICENSE.txt for license details. */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> <module name="MageWorx_ShippingRateByProductAttribute" setup_version="1.0.0"> <sequence> <module name="MageWorx_ShippingRules" /> </sequence> </module> </config>
Étape 2. Créer une structure de module
Supposons que nous ayons un attribut de produit nommé 'shippingnew', qui a été créé du côté administrateur. Il s'agit d'un type d'entrée déroulant et comporte quelques options nommées "A, B, C, D", etc. Ces options décrivent comment nous expédions nos articles par zones. Chaque valeur a son propre prix, et les produits avec le prix le plus élevé modifieront le coût de la méthode d'expédition lors du paiement.
Tout d'abord, nous devons créer un tableau séparé pour nos conditions étendues de tarifs d'expédition. Plus tard, nous les ajouterons en utilisant les attributs d'extension réguliers du modèle (le modèle 'Shipping Rate' étend `\Magento\Framework\Model\AbstractExtensibleModel` ).
> app/code/MageWorx/ShippingRateByProductAttribute/Setup/InstallSchema.php <?php /** * Copyright MageWorx. All rights reserved. * See LICENSE.txt for license details. */ namespace MageWorx\ShippingRateByProductAttribute\Setup; use Magento\Framework\DB\Ddl\Table; use Magento\Framework\Setup\InstallSchemaInterface; use Magento\Framework\Setup\ModuleContextInterface; use Magento\Framework\Setup\SchemaSetupInterface; /** * Class InstallSchema */ class InstallSchema implements InstallSchemaInterface { /** * Installs DB schema for a module * * @param SchemaSetupInterface $setup * @param ModuleContextInterface $context * @return void * @throws \Zend_Db_Exception */ public function install(SchemaSetupInterface $setup, ModuleContextInterface $context) { $installer = $setup; $installer->startSetup(); $ratesTable = $installer->getTable(\MageWorx\ShippingRules\Model\Carrier::RATE_TABLE_NAME); /** * Create table 'mageworx_shippingrules_rates_shippingnew' */ $table = $installer->getConnection()->newTable( $installer->getTable('mageworx_shippingrules_rates_shippingnew') )->addColumn( 'rate_id', Table::TYPE_INTEGER, null, ['unsigned' => true, 'nullable' => false], 'Rate Id' )->addColumn( 'shippingnew', Table::TYPE_TEXT, '120', ['nullable' => false], 'shippingnew attribute value' )->addForeignKey( $installer->getFkName('mageworx_shippingrules_rates_shippingnew', 'rate_id', $ratesTable, 'rate_id'), 'rate_id', $ratesTable, 'rate_id', Table::ACTION_CASCADE )->addIndex( $installer->getIdxName( 'mageworx_shippingrules_rates_product_attributes', ['rate_id', 'shippingnew'], \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE ), ['rate_id', 'shippingnew'], ['type' => \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE] )->setComment( 'Product Attributes For Shipping Suite Rates' ); $installer->getConnection()->createTable($table); } }
Nous avons nommé notre table comme suit : `'mageworx_shippingrules_rates_shippingnew'`. Il n'a que 2 colonnes. L'un d'eux est utilisé comme clé étrangère. Il s'agit de la colonne `rate_id`, qui sera liée à la table régulière `mageworx_shippingrules_rates` du module MageWorx Shipping Suite Ultimate pour Magento 2. Une autre colonne contiendra les valeurs de l'attribut `shippingnew`.
Avant de faire en sorte qu'un observateur charge/enregistre/supprime nos données personnalisées dans la table, nous devons créer au moins deux modèles : le modèle standard et le modèle de ressource.
> app/code/MageWorx/ShippingRateByProductAttribute/Model/ShippingNew.php <?php /** * Copyright MageWorx. All rights reserved. * See LICENSE.txt for license details. */ namespace MageWorx\ShippingRateByProductAttribute\Model; use Magento\Framework\Model\AbstractModel; /** * Class ShippingNew */ class ShippingNew extends AbstractModel { /** * Prefix of model events names * * @var string */ protected $_eventPrefix = 'mageworx_shippingnew'; /** * Parameter name in event * * In observe method you can use $observer->getEvent()->getObject() in this case * * @var string */ protected $_eventObject = 'shippingnew'; /** * Set resource model and Id field name * * @return void */ protected function _construct() { parent::_construct(); $this->_init('MageWorx\ShippingRateByProductAttribute\Model\ResourceModel\ShippingNew'); $this->setIdFieldName('rate_id'); } }
Remarques:
- ` _eventPrefix ` sera utilisé pour détecter nos événements de modèle.
- `_eventObject` sera utilisé pour stocker des données dans l'objet événement. En utilisant ce nom, nous pouvons obtenir notre modèle à partir de l'objet événement.
- `$this->_init( 'MageWorx\ShippingRateByProductAttribute\Model\ResourceModel\ ShippingNew' );` relie notre modèle au modèle de ressource correspondant.
- `$this->setIdFieldName( 'rate_id' );` décrit quel champ de la table doit être utilisé comme clé (généralement nous l'appelons id)
> app/code/MageWorx/ShippingRateByProductAttribute/Model/ResourceModel/ShippingNew.php <?php /** * Copyright MageWorx. All rights reserved. * See LICENSE.txt for license details. */ namespace MageWorx\ShippingRateByProductAttribute\Model\ResourceModel; use Magento\Framework\Model\ResourceModel\Db\AbstractDb; /** * Class ShippingNew */ class ShippingNew extends AbstractDb { /** * Resource initialization * * @return void */ protected function _construct() { $this->_init('mageworx_shippingrules_rates_shippingnew', 'rate_id'); } /** * @param $rateId * @param int $shippingNew * @return int * @throws \Magento\Framework\Exception\LocalizedException */ public function insertUpdateRecord($rateId, int $shippingNew) { $rowsAffected = $this->getConnection()->insertOnDuplicate( $this->getMainTable(), [ 'rate_id' => $rateId, 'shippingnew' => $shippingNew ] ); return $rowsAffected; } /** * @param $rateId * @return int * @throws \Magento\Framework\Exception\LocalizedException */ public function deleteRecord($rateId) { $rowsAffected = $this->getConnection()->delete( $this->getMainTable(), [ 'rate_id = ?' => $rateId ] ); return $rowsAffected; } }
Remarques:
- $this->_init( 'mageworx_shippingrules_rates_shippingnew' , 'rate_id' ); définir le nom de la table principale et le nom du champ id.
- La fonction publique insertUpdateRecord($rateId, int $shippingNew) est la méthode qui pourrait nous aider à mettre à jour la valeur de l'attribut dans notre table personnalisée.
- La fonction publique deleteRecord($rateId) est conçue pour supprimer la colonne.
Plus tard, nous utiliserons ces méthodes dans nos observateurs.
Ajoutons maintenant nos nouvelles données en tant qu'attribut d'extension au modèle Shipping Rate :
> app/code/MageWorx/ShippingRateByProductAttribute/etc/extension_attributes.xml <?xml version="1.0"?> <!-- /** * Copyright MageWorx. All rights reserved. * See LICENSE.txt for license details. */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd"> <!-- Rate Extension --> <extension_attributes for="MageWorx\ShippingRules\Api\Data\RateInterface"> <attribute code="shippingnew" type="int"> <join reference_table="mageworx_shippingrules_rates_shippingnew" reference_field="rate_id" join_on_field="rate_id"> <field>shippingnew</field> </join> </attribute> </extension_attributes> </config>
Nous devons également nous occuper des opérations régulières de notre condition personnalisée :
> app/code/MageWorx/ShippingRateByProductAttribute/etc/events.xml <?xml version="1.0"?> <!-- /** * Copyright MageWorx. All rights reserved. * See LICENSE.txt for license details. */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd"> <!-- Add Extension Attributes to the Rates Collection --> <!-- Save custom attribute value during rate saving --> <event name="mageworx_shippingrules_rate_save_after"> <observer name="mageworx_save_shippingnew_attribute" instance="MageWorx\ShippingRateByProductAttribute\Observer\SaveShippingNewRateAttribute" /> </event> <!-- Add custom attribute value to the rates collection --> <event name="rates_collection_render_filters_before"> <observer name="mageworx_add_shippingnew_attribute" instance="MageWorx\ShippingRateByProductAttribute\Observer\AddShippingNewToRatesCollection" /> </event> <!-- Take care of filtering the rates grid --> <event name="mageworx_suitable_rates_collection_load_before"> <observer name="mageworx_filter_rates_by_shippingnew_attribute" instance="MageWorx\ShippingRateByProductAttribute\Observer\FilterRatesCollectionByShippingNewAttribute" /> </event> <!-- 3 event observers for the Export/Import rates with custom attribute in conditions --> <event name="mageworx_rates_export_collection_join_linked_tables_after"> <observer name="mageworx_join_shipping_new_table_to_export_rates_collection" instance="MageWorx\ShippingRateByProductAttribute\Observer\JoinShippingNewTableToExportRatesCollection" /> </event> <event name="mageworx_filter_rates_data_before_insert"> <observer name="mageworx_remove_shipping_new_before_insert" instance="MageWorx\ShippingRateByProductAttribute\Observer\RemoveShippingNewBeforeInsert" /> </event> <event name="mageworx_shippingrules_import_insert_rates"> <observer name="mageworx_shippingrules_import_insert_update_shipping_new" instance="MageWorx\ShippingRateByProductAttribute\Observer\InsertUpdateShippingNewDuringImport" /> </event> </config>
Le premier événement concerne l'enregistrement/la mise à jour/la suppression de la valeur de l'attribut personnalisé dans la condition des tarifs.
Les deux événements suivants permettent d'ajouter cette valeur d'attribut à la collection.
Les trois derniers événements concernent la fonctionnalité d'importation/exportation.
Analysons-les un par un plus en détail :
> app/code/MageWorx/ShippingRateByProductAttribute/Observer/SaveShippingNewRateAttribute.php <?php /** * Copyright MageWorx. All rights reserved. * See LICENSE.txt for license details. */ namespace MageWorx\ShippingRateByProductAttribute\Observer; use Magento\Framework\Event\Observer; use Magento\Framework\Event\ObserverInterface; use Magento\Framework\Exception\LocalizedException; use MageWorx\ShippingRules\Api\Data\RateInterface; /** * Class SaveShippingNewRateAttribute * * Saves custom attribute (`shippingnew`) values after model was saved */ class SaveShippingNewRateAttribute implements ObserverInterface { /** * @var \MageWorx\ShippingRateByProductAttribute\Model\ResourceModel\ShippingNew */ private $resource; /** * @var \Magento\Framework\Message\ManagerInterface */ private $messagesManager; /** * SaveVolumeWeightRateAttribute constructor. * * @param \MageWorx\ShippingRateByProductAttribute\Model\ResourceModel\ShippingNew $resource * @param \Magento\Framework\Message\ManagerInterface $messagesManager */ public function __construct( \MageWorx\ShippingRateByProductAttribute\Model\ResourceModel\ShippingNew $resource, \Magento\Framework\Message\ManagerInterface $messagesManager ) { $this->resource = $resource; $this->messagesManager = $messagesManager; } /** * @param Observer $observer * @return void */ public function execute(Observer $observer) { /** @var RateInterface $model */ $model = $observer->getEvent()->getData('rate'); if (!$model instanceof RateInterface) { return; } $shippingNewValue = $model->getData('shippingnew') !== '' ? $model->getData('shippingnew') : null; if ($shippingNewValue === null) { try { $this->resource->deleteRecord($model->getRateId()); } catch (LocalizedException $deleteException) { $this->messagesManager->addErrorMessage( __('Unable to delete the Shipping Category for the Rate %1', $model->getRateId()) ); } } else { try { $this->resource->insertUpdateRecord($model->getRateId(), $shippingNewValue); } catch (LocalizedException $saveException) { $this->messagesManager->addErrorMessage( __('Unable to save the Shipping Category for the Rate %1', $model->getRateId()) ); } } return; } }
C'est aussi simple que ça. Lorsque nous enregistrons un tarif, nous devons également prendre soin d'enregistrer la valeur de l'attribut personnalisé. Si sa valeur est égale à "null", supprimez simplement un enregistrement.
> app/code/MageWorx/ShippingRateByProductAttribute/Observer/AddShippingNewToRatesCollection.php <?php /** * Copyright MageWorx. All rights reserved. * See LICENSE.txt for license details. */ namespace MageWorx\ShippingRateByProductAttribute\Observer; use Magento\Framework\Event\Observer; use Magento\Framework\Event\ObserverInterface; /** * Class AddShippingNewToRatesCollection * * Adds custom attribute to the rates collection. * It will be used later during quote validation. */ class AddShippingNewToRatesCollection implements ObserverInterface { /** * Join custom table to the rates collection to obtain the `shippingnew` attribute anywhere in the code. * * @param Observer $observer * @return void */ public function execute(Observer $observer) { /** @var \MageWorx\ShippingRules\Model\ResourceModel\Rate\Collection $collection */ $collection = $observer->getEvent()->getData('collection'); if (!$collection instanceof \MageWorx\ShippingRules\Model\ResourceModel\Rate\Collection) { return; } if ($collection->isLoaded()) { return; } $joinTable = $collection->getTable('mageworx_shippingrules_rates_shippingnew'); $collection->getSelect() ->joinLeft( $joinTable, '`main_table`.`rate_id` = `' . $joinTable . '`.`rate_id`', ['shippingnew'] ); } }
Pour rendre la validation disponible, lorsqu'un client passe à la caisse ou à l'estimation des tarifs d'expédition, joignons notre tableau avec l'attribut personnalisé au tableau des tarifs réguliers.
> app/code/MageWorx/ShippingRateByProductAttribute/Observer/FilterRatesCollectionByShippingNewAttribute.php <?php /** * Copyright MageWorx. All rights reserved. * See LICENSE.txt for license details. */ namespace MageWorx\ShippingRateByProductAttribute\Observer; use Magento\Framework\Event\Observer; use Magento\Framework\Event\ObserverInterface; /** * Class FilterRatesCollectionByShippingNewAttribute * * Filter rates collection before we load it by custom attribute: shippingnew. * * For more details * * @see \MageWorx\ShippingRules\Model\Carrier\Artificial::getSuitableRatesAccordingRequest() * */ class FilterRatesCollectionByShippingNewAttribute implements ObserverInterface { /** * @param Observer $observer * @return void */ public function execute(Observer $observer) { /** @var \MageWorx\ShippingRules\Model\ResourceModel\Rate\Collection $collection */ $collection = $observer->getEvent()->getData('rates_collection'); if (!$collection instanceof \MageWorx\ShippingRules\Model\ResourceModel\Rate\Collection) { return; } /** @var \Magento\Quote\Model\Quote\Address\RateRequest $request */ $request = $observer->getEvent()->getData('request'); if (!$request instanceof \Magento\Quote\Model\Quote\Address\RateRequest) { return; } /** @var \Magento\Quote\Model\Quote\Item[] $items */ $items = $request->getAllItems() ?? []; $shippingCategories = []; foreach ($items as $item) { $value = $item->getProduct()->getData('shippingnew'); if ($value !== null) { $shippingCategories[] = $value; } } $shippingCategories = array_unique($shippingCategories); $joinTable = $collection->getTable('mageworx_shippingrules_rates_shippingnew'); $collection->getSelect() ->joinLeft( ['sn' => $joinTable], '`main_table`.`rate_id` = `sn`.`rate_id`', ['shippingnew'] ); $collection->getSelect()->where( "`sn`.`shippingnew` IN (?)", $shippingCategories ); } }
C'est l'observateur le plus compliqué de notre pile. Il est conçu pour collecter toutes les valeurs d'attribut ("$shippingCategories") du panier d'un client et ajoute la valeur d'attribut en tant que filtre à la collecte des tarifs réguliers (notre table est déjà jointe). Pour faire simple, je l'ai nommé "Filtre". Lorsque le travail est terminé, un client verra les tarifs d'expédition réels pour les articles du panier en cours.
Trois autres observateurs d'événements sont conçus pour ajouter et recevoir des données personnalisées lors de l'exportation et de l'importation des tarifs d'expédition. Nous ignorons son code dans le billet de blog, mais il sera disponible dans le référentiel avec le code source.
Étape 3. Interface utilisateur
Il est temps d'ajouter notre attribut à la grille et à la forme des tarifs d'expédition.
Formulaire
> app/code/MageWorx/ShippingRateByProductAttribute/view/adminhtml/ui_component/mageworx_shippingrules_rate_form.xml <?xml version="1.0" encoding="UTF-8"?> <!-- /** * Copyright MageWorx. All rights reserved. * See LICENSE.txt for license details. */ --> <form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd"> <fieldset name="conditions"> <field name="shippingnew"> <argument name="data" xsi:type="array"> <item name="options" xsi:type="object">MageWorx\ShippingRateByProductAttribute\Model\Config\Source\ShippingCategory</item> <item name="config" xsi:type="array"> <item name="label" xsi:type="string" translate="true">Shipping Category</item> <item name="dataType" xsi:type="string">int</item> <item name="formElement" xsi:type="string">select</item> <item name="dataScope" xsi:type="string">shippingnew</item> <item name="source" xsi:type="string">mageworx_shippingrules_rate_form.custom_attributes</item> </item> </argument> </field> </fieldset> </form>
Grille
> app/code/MageWorx/ShippingRateByProductAttribute/view/adminhtml/ui_component/mageworx_shippingrules_rates_regular_listing.xml <?xml version="1.0"?> <!-- Copyright MageWorx. All rights reserved. See LICENSE.txt for license details. --> <listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Ui/etc/ui_configuration.xsd"> <columns name="mageworx_shippingrules_rates_columns"> <column name="shippingnew"> <argument name="data" xsi:type="array"> <item name="options" xsi:type="object">MageWorx\ShippingRateByProductAttribute\Model\Config\Source\ShippingCategory</item> <item name="config" xsi:type="array"> <item name="filter" xsi:type="string">select</item> <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/select</item> <item name="dataType" xsi:type="string">select</item> <item name="label" xsi:type="string" translate="true">Shipping Category</item> <item name="visible" xsi:type="boolean">true</item> <item name="sortOrder" xsi:type="number">40</item> <item name="editor" xsi:type="string">select</item> </item> </argument> </column> </columns> </listing>
Comme vous pouvez le voir, nous utilisons le modèle source personnalisé dans ces fichiers. Créons-le. Il chargera un attribut correspondant (`shippingnew`) et nous donnera toutes les valeurs disponibles.
> app/code/MageWorx/ShippingRateByProductAttribute/Model/Config/Source/ShippingCategory.php <?php /** * Copyright MageWorx. All rights reserved. * See LICENSE.txt for license details. */ namespace MageWorx\ShippingRateByProductAttribute\Model\Config\Source; use Magento\Framework\Exception\LocalizedException; /** * Class ShippingCategory * * Obtain options for specified product attribute */ class ShippingCategory extends \Magento\Eav\Model\Entity\Attribute\Source\AbstractSource { /** * @var \Magento\Catalog\Api\ProductAttributeRepositoryInterface */ protected $productAttributeRepository; /** * @var \Psr\Log\LoggerInterface */ protected $logger; /** * ShippingCategory constructor. * * @param \Magento\Catalog\Api\ProductAttributeRepositoryInterface $productAttributeRepository * @param \Psr\Log\LoggerInterface $logger */ public function __construct( \Magento\Catalog\Api\ProductAttributeRepositoryInterface $productAttributeRepository, \Psr\Log\LoggerInterface $logger ) { $this->productAttributeRepository = $productAttributeRepository; $this->logger = $logger; } /** * @inheritDoc */ public function getAllOptions() { if (empty($this->_options)) { try { /** @var \Magento\Catalog\Api\Data\ProductAttributeInterface $attribute */ $attribute = $this->productAttributeRepository->get('shippingnew'); $this->_options = $attribute->usesSource() ? $attribute->getSource()->getAllOptions() : []; } catch (LocalizedException $localizedException) { $this->logger->critical($localizedException->getLogMessage()); } } return $this->_options; } }
Le morceau de code est assez simple. Nous utilisons le référentiel d'attributs pour charger notre attribut, puis en obtenons toutes les options (valeurs). Gardez à l'esprit que l'attribut avec le code `shippingnew` doit être créé dans le panneau d'administration et doit avoir un type d'entrée déroulant avec des options prédéfinies (valeurs). Vous pouvez le faire depuis le menu 'Magasins > Attributs > Produit'. N'oubliez pas d'ajouter cet attribut à l'ensemble d'attributs que vous utilisez pour les produits.
Quand tout est fait, il suffit d'activer le module et de lancer le `setup:upgrade`. Le cache sera vidé automatiquement.
Allez dans la grille des tarifs ('Magasins > Tarifs d'expédition') et vous verrez la nouvelle colonne :
Cette condition sera disponible dans le formulaire des tarifs :
Si nous définissons le paramètre "Calcul du prix des tarifs multiples" sur "Utiliser le tarif avec le prix maximum" dans la méthode d'expédition correspondante, le tarif avec le prix le plus élevé sera utilisé lors du calcul du prix d'expédition.
Voici un petit exemple de son fonctionnement sous forme de captures d'écran :
- Configurez vos produits
- Paramétrer les tarifs
- Paramétrer l'algorithme de calcul du prix (dans le formulaire mode de livraison)
- Vérifiez le prix d'expédition pour la méthode correspondante avec les produits sélectionnés dans le panier (sur le frontend).
Ce n'est pas tout ce dont le module Shipping Suite est capable. N'hésitez pas à jouer avec les réglages pour obtenir le résultat souhaité.
Je serai heureux de répondre à toutes vos questions ! Ainsi, n'hésitez pas à laisser vos commentaires dans le champ dédié ci-dessous.