|
| 1 | +--- |
| 2 | +description: Extend Discounts by adding your own rules and conditions |
| 3 | +editions: |
| 4 | + - lts-update |
| 5 | + - commerce |
| 6 | +month_change: true |
| 7 | +--- |
| 8 | + |
| 9 | +# Extend Discounts |
| 10 | + |
| 11 | +By extending [Discounts](discounts_guide.md), you can increase flexibility and control over how promotions are applied to suit your unique business rules. |
| 12 | +Together with the existing [events](event_reference.md) and the [Discounts PHP API](discounts_api.md), extending discounts gives you the ability to cover additional use cases related to selling products. |
| 13 | + |
| 14 | +## Create custom conditions |
| 15 | + |
| 16 | +With custom [conditions](discounts_api.md#conditions) you can create more advanced discounts that apply only in specific scenarios. |
| 17 | + |
| 18 | +The following example create discounts valid for your customers only on the anniversary of their account creation. |
| 19 | +Having a custom condition allows you to model this scenario using a single discount, hiding all the complexity within the condition. |
| 20 | + |
| 21 | +The logic for both the conditions and rules is specified using [Symfony's expression language](https://symfony.com/doc/current/components/expression_language.html). |
| 22 | + |
| 23 | +### Available expressions |
| 24 | + |
| 25 | +The following expressions are available for conditions and rules: |
| 26 | + |
| 27 | +| Type | Name | Value | Available for | |
| 28 | +| --- | --- | --- | --- | |
| 29 | +| Function | `get_current_region()` | [Region object](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Values-RegionInterface.html) of the current siteaccess.| Conditions, rules | |
| 30 | +| Function | `is_in_category()` | `true/false`, depending if a product belongs to given [product categories](pim_guide.md#product-categories).| Conditions, rules | |
| 31 | +| Function | `is_user_in_customer_group()` | `true/false`, depending if a user belongs to given [customer groups](customer_groups.md). | Conditions, rules | |
| 32 | +| Function | `calculate_purchase_amount()` | Purchase amount, calculated for all products in the cart before the discounts are applied.| Conditions, rules | |
| 33 | +| Function | <nobr>`is_product_in_product_codes()`</nobr> | `true/false`, depending if the product is part of the given list.| Conditions, rules | |
| 34 | +| Variable | `cart` | [Cart object](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Cart-Value-CartInterface.html) associated with current context.| Conditions, rules | |
| 35 | +| Variable | `currency` | [Currency object](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Values-CurrencyInterface.html) of the current siteaccess. | Conditions, rules | |
| 36 | +| Variable | `customer_group` | [Customer group object](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Values-CustomerGroupInterface.html) associated with given price context or the current user.| Conditions, rules | |
| 37 | +| Variable | `amount` | Original price of the product | Rules | |
| 38 | +| Variable | `product` | [Product object](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Values-ProductInterface.html)| Rules | |
| 39 | + |
| 40 | +### Custom expressions |
| 41 | + |
| 42 | +You can create your own variables and functions to make creating the conditions easier. |
| 43 | +To create the condition checking the registration date, the following example will use an additinal variable and a function: |
| 44 | + |
| 45 | +- `current_user`, a variable with the current [User object](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-User-User.html) |
| 46 | + |
| 47 | +To add it, create a class implementing the [`DiscountVariablesResolverInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountVariablesResolverInterface.html): |
| 48 | + |
| 49 | +``` php |
| 50 | +todo: verify |
| 51 | +``` |
| 52 | + |
| 53 | +And mark it as a service using the `ibexa.discounts.expression_language.variable_resolver` service tag: |
| 54 | + |
| 55 | +``` yaml |
| 56 | +todo: verify |
| 57 | +``` |
| 58 | +
|
| 59 | +- `is_anniversary()`, a function returning a boolean value indicating if the two dates passed as arguments fall on the same day. |
| 60 | + |
| 61 | +``` php |
| 62 | +todo: verify |
| 63 | +``` |
| 64 | + |
| 65 | +Mark it as a service using the `ibexa.discounts.expression_language.function` service tag and specify the function name in the service definition. |
| 66 | + |
| 67 | +``` yaml |
| 68 | +todo: verify |
| 69 | +``` |
| 70 | + |
| 71 | +Two new expressions are now available for use in custom conditions and rules. |
| 72 | + |
| 73 | +### Implement custom condition |
| 74 | + |
| 75 | +Now, create the condition by creating a class implementing the [`DiscountConditionInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-DiscountConditionInterface.html). |
| 76 | + |
| 77 | +``` php |
| 78 | +todo: verify |
| 79 | +``` |
| 80 | + |
| 81 | +The expression can evaluate to `true` or `false` depending on the custom expressions values. |
| 82 | +An additional variable, `today`, is defined to store the current date for comparison. |
| 83 | + |
| 84 | +For each condition class you must create a dedicated condition factory, a class implementing the `\Ibexa\Discounts\Repository\DiscountCondition\DiscountConditionFactoryInterface` inteface. |
| 85 | + |
| 86 | +This allows you to create conditions when working in the context of the Symfony service container. |
| 87 | + |
| 88 | +``` php |
| 89 | +todo |
| 90 | +``` |
| 91 | + |
| 92 | +Mark it as a service using the `ibexa.discounts.condition.factory` service tag and specify the condition's identifier. |
| 93 | + |
| 94 | +``` yaml |
| 95 | +todo |
| 96 | +``` |
| 97 | + |
| 98 | +## Create custom rules |
| 99 | + |
| 100 | +To implement a custom rule, create a class implementing the [`DiscountRuleInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-DiscountRuleInterface.html). |
| 101 | + |
| 102 | +The following example implements a [purchasing power parity discount](https://en.wikipedia.org/wiki/Purchasing_power_parity), adjusting product's price in the cart based on buyer's region. |
| 103 | + |
| 104 | +``` php |
| 105 | +todo |
| 106 | +``` |
| 107 | + |
| 108 | +As with conditions, create a dedicated rule factory. |
| 109 | + |
| 110 | +``` php |
| 111 | +todo |
| 112 | +``` |
| 113 | + |
| 114 | +Mark it as a service using the `ibexa.discounts.condition.factory` service tag and specify the rule's type. |
| 115 | + |
| 116 | +``` yaml |
| 117 | +todo |
| 118 | +``` |
| 119 | + |
| 120 | +### Custom discount formatting |
| 121 | + |
| 122 | +You can adjust how each discount type is displayed when using the [`ibexa_discounts_render_discount_badge` Twig function](discounts_twig_functions.md#ibexa_discounts_render_discount_badge) by implementing a custom formatter. |
| 123 | + |
| 124 | +To do it, create a class implementing the [`DiscountValueFormatterInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountValueFormatterInterface.html) and use the `ibexa.discounts.value.formatter` service tag: |
| 125 | + |
| 126 | +``` php |
| 127 | +todo |
| 128 | +``` |
| 129 | + |
| 130 | +``` yaml |
| 131 | +todo |
| 132 | +``` |
| 133 | + |
| 134 | +## Change discount priority |
| 135 | + |
| 136 | +You can change the [the defualt discount priority](discounts_guide.md#discounts-priority) by creating a class implementing the [`DiscountPrioritizationStrategyInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountPrioritizationStrategyInterface.html) and aliasing to it the default implementation. |
| 137 | + |
| 138 | +The example below decorates the default implementation to prioritize recently created discounts above all the others. |
| 139 | + |
| 140 | +``` php |
| 141 | +todo |
| 142 | +``` |
| 143 | + |
| 144 | +``` yaml |
| 145 | +todo |
| 146 | +``` |
| 147 | + |
| 148 | +## Form integration |
| 149 | + |
| 150 | +### Condition |
| 151 | + |
| 152 | +### Rules |
0 commit comments