Vanilo 6.0 Released.See what's new
WARNING! You're browsing the documentation of the upcoming version of Vanilo. It may contain unreleased features and changes, or even features that will not be present in the next release as described here. The latest stable version is 6.x
On this page
Components Adjustments
5 min read

Adjustments

The Adjustments Module has been first released with Vanilo v3.1.

Overview

"Adjustments" is an abstract concept at first sight, but it solves a few important topics in ecommerce like:

  • Price discounts,
  • Shipping fees,
  • Tax handling,
  • "Paying" with credits, coupons, etc.

Adjustments can be applied to any eloquent model, but typically they're applied to the total price of an order/cart, or to an order/cart item or to an order’s shipment.

Adjustment

An Adjustment object tracks an adjustment to the price of an Adjustable (eg. order, order item, shipment).

Adjustment Types

Every adjustment is classified by type that can be promotion, shipping, tax or misc. The AdjustmentType is an enum object, therefore additional types can be added to it.

Amount, Charges, Credits

Every adjustment has an amount, that can be either positive or negative.

Adjustments that increase the total are called "charges", while those that decrease the total are called "credits".

Adjustments can also be 0, for example when there's free shipping above a certain cart value. In this case we still want to track the adjustment because when the value of the cart changes, the fee needs to be recalculated.

Included Adjustments

Adjustments can be considered included or additional. Included means that the adjustment is included in price of the adjustable (eg. order, order item).

An additional or "normal" adjustment is applied on top of the original item price. A shipping fee is a typical example of this type.

A simple example of an included adjustment is a VAT or sales tax. The amount of VAT is included in the prices, but with the help of adjustments we can track their value, and based on certain conditions it needs to be recalculated. As a result, VAT might either be deducted from the total, or it needs to be applied at a different rate.

Locking

Adjustments are recalculated upon certain events like modifying the contents of a cart. Adjustments can be locked to prevent them from being subsequently modified. Once an adjustment is locked, it will not be updated when the next recalculation is triggered.

Origin

Adjustments have an origin field that can hold a reference to an external source. It can be freely used, and can represent the id of a promotion entry in the database, or a coupon code, etc.

Adjustment Data

Adjustments can hold an array of arbitrary data that is designed to configure the concrete adjuster, primarily used at recalculation.

An example is in the built-in SimpleShippingFee adjuster that stores the amount and the freeThreshold as data. At every recalculation this data is being used to determine if the value of the $adjustable->itemsTotal() is higher the freeTreshold. If it's higher then the amount of the adjustment will be set to 0, if it's lower, then the adjustment amount will be the value of the configured amount.

$order = Order::create(['items_total' => 10.99]);

$shippingFee = new SimpleShippingFee($value = 6.99, $freeThreshold = 30);
$order->adjustments()->create($shippingFee);

$order->adjustments()->first()->getData();
// [ 'value' => 6.99, 'freeThreshold' => 30 ]

$order->adjustments()->total();
// 6.99

$order->items_total = 31;
$order->recalculateAdjustments();

$order->adjustments()->total();
// 0

Adjustables

Adjustable models are the subject of the adjustment. They can be virtually anything that has a price. In the Vanilo Framework the following entities are adjustable out of the box:

  • Carts and Cart Items
  • Orders and Order Items,
  • Shipments.

Adjustment Collections

Adjustables have an adjustments() method which returns an AdjustmentCollection instance. This interface simplifies the handling of adjustments of an adjustable.

Vanilo contains two implementations of the AdjustmentCollection interface, but most probably you'll only meet the RelationAdjustmentCollection variant, which works with eloquent models.

$order = Order::find(1);
$order->adjustments();
//= Vanilo\Adjustments\Support\RelationAdjustmentCollection

$order->adjustments()->create(new SimpleShippingFee(4.99));
$order->count();
//1
$order->adjustments()->total();
// 4.99

The total() method neglects the included adjustments from the total by default. To have the included adjustments incorporated in the total sum, pass true as parameter to the total() method:

$order->adjustments()->create(Adjustment::create(['amount' => 5, 'is_included' => true]));
$order->adjustments()->create(Adjustment::create(['amount' => 10, 'is_included' => false]));
$order->adjustments()->total();
// 10
$order->adjustments()->total(withIncluded: true);
// 15

Adjusters

Adjusters are classes the hold the logic for the adjustment calculation. Example adjuster classes are SimpleShippingFee, FixedAmountDiscount, PercentageDiscount, etc.

The base adjustments package contains several adjustments, and it is encouraged application developers to write their own adjusters that encapsulate the custom business logic, the concrete implementation requires.

Adjusters are designed to be configurable and the work with an Adjustable and an Adjustment.

The goal of adjusters is to calculate/recalculate adjustments based on a given adjustable instance. Adjusters don't store the state, they just take the input (config, adjustable), do the calculation and as a result they create or update an adjustment.

Adjuster Configuration

The configuration of the adjuster is when you specify the parameters of the adjuster. A good example is a shipping fee where you can configure the cost, and the minimum amount above which the shipping is free:

$shippingFee = new SimpleShippingFee($shippingCost = 6.99, $freeWhenOrderValueIsMoreThan = 30);

Using an Adjuster to Create an Adjustment

Once you have a configured adjuster instance, it can create an adjustment using an adjustable model, eg. a Cart:

$shippingFee = new SimpleShippingFee(6.99, 30);
$cart = Cart::model();

$adjustment = $shippingFee->createAdjustment($cart);

An even better approach is to let the adjustable do the heavy lifting of the creation and assignment. The code below will create and adjustment, calculate the values using the SimpleShippingFee adjuster and persist the adjustment in the database:

$cart->adjustments()->create(new SimpleShippingFee(5, 49));
Next in Components Taxes