Introduction
This article teaches X-Cart developers how they can create discounts via custom module. For the sake of example, we will show how to create a straight-forward 10% discount to order subtotal.
Video tutorial
Video showing the process of creating the module for X-Cart 5.1.x:
Implementation
We start with creating an empty module. We create the module with developer ID XCExample and module ID DiscountDemo.
You can create a discount in X-Cart by extending the \XLite\Logic\Order\Modifier\Discount
class. The \XLite\Logic\Order\Modifier
type of class defines different types of order surcharges, e.g. shipping, taxes, discounts, etc. We use one that is typical discount: \XLite\Logic\Order\Modifier\Discount
.
We create classes/XLite/Module/XCExample/DiscountDemo/Logic/Order/Modifier/Discount.php
file with the following content:
<?php
namespace XLite\Module\XCExample\DiscountDemo\Logic\Order\Modifier;
class Discount extends \XLite\Logic\Order\Modifier\Discount
{
const MODIFIER_CODE = 'DISCOUNT';
protected $type = \XLite\Model\Base\Surcharge::TYPE_DISCOUNT;
protected $code = self::MODIFIER_CODE;
public function calculate()
{
$surcharge = null;
$discount = $this->getOrder()->getSubtotal() * 0.1;
$surcharge = $this->addOrderSurcharge($this->code, $discount * -1);
$this->distributeDiscount($discount);
return $surcharge;
}
}
Let us have a closer look at this class' code.
The code below defines that this order modifier is a discount and the surcharge value should be aggregated into single Discount line in order totals:
const MODIFIER_CODE = 'DISCOUNT';
protected $type = \XLite\Model\Base\Surcharge::TYPE_DISCOUNT;
protected $code = self::MODIFIER_CODE;calculate()
method is the most important part of this class. It defines the routine of calculating discount and applying it to the order object. This method will be called in thecalculate()
method of the\XLite\Model\Order
object in thisforeach()
:foreach ($this->getModifiers() as $modifier) {
if ($modifier->canApply()) {
$modifier->calculate();
}
}Note: our mod does not use it, but you can define
canApply()
method in your class in order to define whether this modifier must be applied or not.Let us get back to our implementation of
calculate()
method. First we calculate the discount value:$discount = $this->getOrder()->getSubtotal() * 0.1;
and then we apply this discount to the order as a negative value:
$surcharge = $this->addOrderSurcharge($this->code, $discount * -1);
We get the
$surcharge
object as a result, which will be returned as a result ofcalculate()
method.Final step is we distribute the discount value across all order items in the cart:
$this->distributeDiscount($discount);
That is it with discount class.
Now we need to register this order modifier in X-Cart and for that purpose we create the classes/XLite/Module/XCExample/DiscountDemo/install.yaml
file with the following content:
XLite\Model\Order\Modifier:
- { class: '\XLite\Module\XCExample\DiscountDemo\Logic\Order\Modifier\Discount', weight: 100 }
This way we tell X-Cart that our class described above must be registered as order modifier with weight 100. The higher the weight, the later this order modifier will be run in foreach()
of bullet-point 3.
Note: if you want to check all currently registered order modifiers, you can pull this info from the xc_order_modifiers MySQL table.
Once our install.yaml file is ready, we need to push it to the database. After that re-deploy the store and check the results: add any product to a cart and go to cart page. You will see a discount applied there:
Module pack
You can download this module's pack from here: XCExample-DiscountDemo-v5_3_0.tar
Attachments:
- custom-discount-applied.png (image/png)