mirror of
https://github.com/Sylius/Sylius.git
synced 2026-07-14 17:10:53 +00:00
Merge pull request #6741 from TheMadeleine/docs/cook/custom-promotion
[Documentation][Cookbook] How to add a custom promotion action?
This commit is contained in:
commit
bea9153911
3 changed files with 149 additions and 0 deletions
147
docs/cookbook/custom-promotion-action.rst
Normal file
147
docs/cookbook/custom-promotion-action.rst
Normal file
|
|
@ -0,0 +1,147 @@
|
||||||
|
How to add a custom promotion action?
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
Let's assume that you would like to have a promotion that gives **100% discount on the cheapest item in the cart**.
|
||||||
|
|
||||||
|
See what steps need to be taken to achieve that:
|
||||||
|
|
||||||
|
Create a new promotion action
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
You will need a new class ``CheapestProductDiscountPromotionActionCommand``.
|
||||||
|
|
||||||
|
It will give a discount equal to the unit price of the cheapest item. That's why it needs to have the Proportional Distributor and
|
||||||
|
the Adjustments Applicator. The ``execute`` method applies the discount and distributes it properly on the totals.
|
||||||
|
This class needs also a ``isConfigurationValid()`` method which was omitted in the snippet below.
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace AppBundle\Promotion\Action;
|
||||||
|
|
||||||
|
class CheapestProductDiscountPromotionActionCommand extends DiscountPromotionActionCommand
|
||||||
|
{
|
||||||
|
const TYPE = 'cheapest_item_discount';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ProportionalIntegerDistributorInterface
|
||||||
|
*/
|
||||||
|
private $proportionalDistributor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var UnitsPromotionAdjustmentsApplicatorInterface
|
||||||
|
*/
|
||||||
|
private $unitsPromotionAdjustmentsApplicator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ProportionalIntegerDistributorInterface $proportionalIntegerDistributor
|
||||||
|
* @param UnitsPromotionAdjustmentsApplicatorInterface $unitsPromotionAdjustmentsApplicator
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
ProportionalIntegerDistributorInterface $proportionalIntegerDistributor,
|
||||||
|
UnitsPromotionAdjustmentsApplicatorInterface $unitsPromotionAdjustmentsApplicator
|
||||||
|
) {
|
||||||
|
$this->proportionalDistributor = $proportionalIntegerDistributor;
|
||||||
|
$this->unitsPromotionAdjustmentsApplicator = $unitsPromotionAdjustmentsApplicator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function execute(PromotionSubjectInterface $subject, array $configuration, PromotionInterface $promotion)
|
||||||
|
{
|
||||||
|
if (!$subject instanceof OrderInterface) {
|
||||||
|
throw new UnexpectedTypeException($subject, OrderInterface::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
$items = $subject->getItems();
|
||||||
|
|
||||||
|
$cheapestItem = $items->first();
|
||||||
|
|
||||||
|
$itemsTotals = [];
|
||||||
|
|
||||||
|
foreach ($items as $item) {
|
||||||
|
$itemsTotals[] = $item->getTotal();
|
||||||
|
|
||||||
|
$cheapestItem = ($item->getVariant()->getPrice() < $cheapestItem->getVariant()->getPrice()) ? $item : $cheapestItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
$splitPromotion = $this->proportionalDistributor->distribute($itemsTotals, -1 * $cheapestItem->getVariant()->getPrice());
|
||||||
|
$this->unitsPromotionAdjustmentsApplicator->apply($subject, $promotion, $splitPromotion);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getConfigurationFormType()
|
||||||
|
{
|
||||||
|
return 'app_promotion_action_cheapest_product_discount_configuration';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Register the action as a service
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
In the ``AppBundle/Resources/config/services.yml`` configure:
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
# AppBundle/Resources/config/services.yml
|
||||||
|
app.promotion_action.cheapest_product_discount:
|
||||||
|
class: AppBundle\Promotion\Action\CheapestProductDiscountPromotionActionCommand
|
||||||
|
arguments: ['@sylius.proportional_integer_distributor', '@sylius.promotion.units_promotion_adjustments_applicator']
|
||||||
|
tags:
|
||||||
|
- { name: sylius.promotion_action, type: cheapest_product_discount, label: Cheapest product discount }
|
||||||
|
|
||||||
|
Prepare a configuration form type for the admin panel
|
||||||
|
-----------------------------------------------------
|
||||||
|
|
||||||
|
The new action needs a form type to be available in the admin panel, while creating a new promotion.
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace AppBundle\Form\Type\Action;
|
||||||
|
|
||||||
|
use Symfony\Component\Form\AbstractType;
|
||||||
|
|
||||||
|
class CheapestProductDiscountConfigurationType extends AbstractType
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return 'app_promotion_action_cheapest_product_discount_configuration';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Register the form type as a service
|
||||||
|
-----------------------------------
|
||||||
|
|
||||||
|
In the ``AppBundle/Resources/config/services.yml`` configure:
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
# AppBundle/Resources/config/services.yml
|
||||||
|
app.form.type.promotion_action.cheapest_product_discount_configuration:
|
||||||
|
class: AppBundle\Form\Type\Action\CheapestProductDiscountConfigurationType
|
||||||
|
tags:
|
||||||
|
- { name: form.type, alias: app_promotion_action_cheapest_product_discount_configuration }
|
||||||
|
|
||||||
|
Create a new promotion with your action
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
Go to the admin panel of your system. On the ``/admin/promotions/new`` url you can create a new promotion.
|
||||||
|
|
||||||
|
In its configuration you can choose your new "Cheapest product discount" action.
|
||||||
|
|
||||||
|
That's all. **Done!**
|
||||||
|
|
||||||
|
Learn more
|
||||||
|
----------
|
||||||
|
|
||||||
|
* :doc:`Customization Guide </customization/index>`
|
||||||
|
* :doc:`Promotions Concept Documentation </customization/index>`
|
||||||
|
|
@ -9,6 +9,7 @@ Cookbook
|
||||||
custom-model
|
custom-model
|
||||||
custom-email
|
custom-email
|
||||||
custom-promotion-rule
|
custom-promotion-rule
|
||||||
|
custom-promotion-action
|
||||||
paypal
|
paypal
|
||||||
stripe
|
stripe
|
||||||
api
|
api
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
* :doc:`/cookbook/custom-model`
|
* :doc:`/cookbook/custom-model`
|
||||||
* :doc:`/cookbook/custom-email`
|
* :doc:`/cookbook/custom-email`
|
||||||
* :doc:`/cookbook/custom-promotion-rule`
|
* :doc:`/cookbook/custom-promotion-rule`
|
||||||
|
* :doc:`/cookbook/custom-promotion-action`
|
||||||
* :doc:`/cookbook/paypal`
|
* :doc:`/cookbook/paypal`
|
||||||
* :doc:`/cookbook/stripe`
|
* :doc:`/cookbook/stripe`
|
||||||
* :doc:`/cookbook/api`
|
* :doc:`/cookbook/api`
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue