Edit in GitHubLog an issue
Thanks to Goivvy LLC for contributing this topic!

Price adjustments

Price adjustments adjust the product price as it is displayed on category or product pages.

In this example, we will add 1.79 to each product price.

To create a price adjustment, add the following code to the module's VENDOR/MODULE/etc/di.xml:

Copied to your clipboard
1<type name="Magento\Framework\Pricing\Adjustment\Collection">
2 <arguments>
3 <argument name="adjustments" xsi:type="array">
4 <item name="devadj" xsi:type="const">VENDOR\MODULE\Pricing\Adjustment::ADJUSTMENT_CODE</item>
5 </argument>
6 </arguments>
7</type>
8<type name="Magento\Framework\Pricing\Adjustment\Pool">
9 <arguments>
10 <argument name="adjustments" xsi:type="array">
11 <item name="devadj" xsi:type="array">
12 <item name="className" xsi:type="string">VENDOR\MODULE\Pricing\Adjustment</item>
13 <item name="sortOrder" xsi:type="string">10</item>
14 </item>
15 </argument>
16 </arguments>
17</type>

The VENDOR/MODULE/Pricing/Adjustment.php file should look like:

Copied to your clipboard
1namespace VENDOR\MODULE\Pricing;
2
3use Magento\Framework\Pricing\Adjustment\AdjustmentInterface;
4use Magento\Framework\Pricing\SaleableInterface;
5
6class Adjustment implements AdjustmentInterface
7{
8
9 const ADJUSTMENT_CODE = 'devadj';
10 const ADJUSTMENT_VALUE = 1.79;
11
12 /**
13 * Get adjustment code
14 *
15 * @return string
16 */
17 public function getAdjustmentCode()
18 {
19 return self::ADJUSTMENT_CODE;
20 }
21
22 /**
23 * Define if adjustment is included in base price
24 *
25 * @return bool
26 */
27 public function isIncludedInBasePrice()
28 {
29 return true;
30 }
31
32 /**
33 * Define if adjustment is included in display price
34 *
35 * @return bool
36 */
37 public function isIncludedInDisplayPrice()
38 {
39 return true;
40 }
41
42 /**
43 * Extract adjustment amount from the given amount value
44 *
45 * @param float $amount
46 * @param SaleableInterface $saleableItem
47 * @param null|array $context
48 * @return float
49 */
50 public function extractAdjustment($amount, SaleableInterface $saleableItem, $context = [])
51 {
52 return $amount - self::ADJUSTMENT_VALUE;
53 }
54
55 /**
56 * Apply adjustment amount and return result value
57 *
58 * @param float $amount
59 * @param SaleableInterface $saleableItem
60 * @param null|array $context
61 * @return float
62 */
63 public function applyAdjustment($amount, SaleableInterface $saleableItem, $context = [])
64 {
65 return $amount + self::ADJUSTMENT_VALUE;
66 }
67
68 /**
69 * Check if adjustment should be excluded from calculations along with the given adjustment
70 *
71 * @param string $adjustmentCode
72 * @return bool
73 */
74 public function isExcludedWith($adjustmentCode)
75 {
76 return $this->getAdjustmentCode() === $adjustmentCode;
77 }
78
79 /**
80 * Return sort order position
81 *
82 * @return int
83 */
84 public function getSortOrder()
85 {
86 return 21;
87 }
88}

The ADJUSTMENT_CODE constant is a unique code for the adjustment which it gets added to the Magento\Framework\Pricing\Adjustment\Collection collection.

The adjustment logic is defined in extractAdjustment and applyAdjustment functions.

Price adjustments affect storefront product prices.

Price adjustments will not affect quote item prices, so when a product is added to the cart, any price adjustments defined above are discarded.

Add price adjustments for quote items#

To adjustments prices for quote items, a custom quote total is added:

Add the following to VENDOR/MODULE/etc/sales.xml:

Copied to your clipboard
1<?xml version="1.0"?>
2<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Sales:etc/sales.xsd">
3 <section name="quote">
4 <group name="totals">
5 <item name="custom-surcharge" instance="VENDOR\MODULE\Model\Quote\Surcharge" sort_order="1000"/>
6 </group>
7 </section>
8</config>

Then in VENDOR/MODULE/Model/Quote/Surcharge.php:

Copied to your clipboard
1namespace VENDOR\MODULE\Model\Quote;
2
3use Magento\Quote\Api\Data\ShippingAssignmentInterface;
4use Magento\Quote\Model\Quote\Address\Total;
5use Magento\Quote\Model\Quote;
6
7class Surcharge extends \Magento\Quote\Model\Quote\Address\Total\AbstractTotal
8{
9
10 const COLLECTOR_TYPE_CODE = 'custom-surcharge';
11
12 /**
13 * Custom constructor.
14 */
15 public function __construct()
16 {
17 $this->setCode(self::COLLECTOR_TYPE_CODE);
18 }
19
20 /**
21 * Collect address discount amount
22 *
23 * @param Quote $quote
24 * @param ShippingAssignmentInterface $shippingAssignment
25 * @param Total $total
26 * @return $this
27 */
28 public function collect(
29 Quote $quote,
30 ShippingAssignmentInterface $shippingAssignment,
31 Total $total
32 ) {
33 parent::collect($quote, $shippingAssignment, $total);
34
35 $items = $shippingAssignment->getItems();
36 if (!count($items)) {
37 return $this;
38 }
39
40 $amount = 0;
41 foreach($quote->getItemsCollection() as $_quoteItem){
42 $amount += $_quoteItem->getQty() * \VENDOR\MODULE\Pricing\Adjustment::ADJUSTMENT_VALUE;
43 }
44
45 $total->setTotalAmount(self::COLLECTOR_TYPE_CODE, $amount);
46 $total->setBaseTotalAmount(self::COLLECTOR_TYPE_CODE, $amount);
47 $total->setCustomAmount($amount);
48 $total->setBaseCustomAmount($amount);
49 $total->setGrandTotal($total->getGrandTotal() + $amount);
50 $total->setBaseGrandTotal($total->getBaseGrandTotal() + $amount);
51 return $this;
52 }
53
54 /**
55 * @param Total $total
56 */
57 protected function clearValues(Total $total)
58 {
59 $total->setTotalAmount('subtotal', 0);
60 $total->setBaseTotalAmount('subtotal', 0);
61 $total->setTotalAmount(self::COLLECTOR_TYPE_CODE, 0);
62 $total->setBaseTotalAmount(self::COLLECTOR_TYPE_CODE, 0);
63 $total->setSubtotalInclTax(0);
64 $total->setBaseSubtotalInclTax(0);
65 }
66
67 /**
68 * @param Quote $quote
69 * @param Total $total
70 * @return array
71 */
72 public function fetch(
73 Quote $quote,
74 Total $total
75 ) {
76
77 $amount = 0;
78
79 foreach ($quote->getItemsCollection() as $_quoteItem) {
80 $amount += $_quoteItem->getQty() * \VENDOR\MODULE\Pricing\Adjustment::ADJUSTMENT_VALUE;
81 }
82
83 return [
84 'code' => $this->getCode(),
85 'title' => __('Custom Total'),
86 'value' => $amount
87 ];
88 }
89
90 /**
91 * @return \Magento\Framework\Phrase
92 */
93 public function getLabel()
94 {
95 return __('Custom Surchange');
96 }
97}

The COLLECTOR_TYPE_CODE constant is a unique name of the custom total. It can be accessed with Magento\Quote\Model\Quote\Address\Total::getTotalAmount, and set with Magento\Quote\Model\Quote\Address\Total::setTotalAmount.

Display price-adjusted totals on the cart page#

To display the price-adjusted total on the cart page, we need to create a few files.

First, add the new total:

VENDOR/MODULE/view/frontend/layout/checkout_cart_index.xml:

Copied to your clipboard
1<?xml version="1.0"?>
2<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
3 <body>
4 <referenceBlock name="checkout.cart.totals">
5 <arguments>
6 <argument name="jsLayout" xsi:type="array">
7 <item name="components" xsi:type="array">
8 <item name="block-totals" xsi:type="array">
9 <item name="children" xsi:type="array">
10 <item name="custom-surcharge" xsi:type="array">
11 <item name="component" xsi:type="string">VENDOR_MODULE/js/view/cart/totals/surcharge</item>
12 <item name="config" xsi:type="array">
13 <item name="title" xsi:type="string" translate="true">Custom Surcharge</item>
14 </item>
15 </item>
16 </item>
17 </item>
18 </item>
19 </argument>
20 </arguments>
21 </referenceBlock>
22 </body>
23</page>

Then, define a new component: VENDOR_MODULE/js/view/cart/totals/surcharge:

VENDOR/MODULE/view/frontend/web/js/view/cart/totals/surcharge.js:

Copied to your clipboard
1define([
2 'Magento_Checkout/js/view/summary/abstract-total',
3 'Magento_Checkout/js/model/quote'
4], function (Component, quote) {
5 'use strict';
6
7 return Component.extend({
8 defaults: {
9 template: 'VENDOR_MODULE/summary/surcharge'
10 },
11 totals: quote.getTotals(),
12
13 /**
14 * @return {*|Boolean}
15 */
16 isDisplayed: function () {
17 return this.isFullMode() && this.getPureValue() != 0;
18 },
19
20 /**
21 * Get surcharge title
22 *
23 * @returns {null|String}
24 */
25 getTitle: function () {
26 if (!this.totals()) {
27 return null;
28 }
29
30 return 'Custom Surcharge';
31 },
32
33 /**
34 * @return {Number}
35 */
36 getPureValue: function () {
37 var price = 0;
38 for (var i=0; i < window.checkoutConfig.quoteItemData.length; i++) {
39 price += window.checkoutConfig.quoteItemData[i].qty * 1.79;
40 }
41
42 return price;
43 },
44
45 /**
46 * @return {*|String}
47 */
48 getValue: function () {
49 return this.getFormattedPrice(this.getPureValue());
50 }
51 });
52});

Then create the template VENDOR_MODULE/summary/surcharge:

Copied to your clipboard
1<!-- ko if: isDisplayed() -->
2<tr class="totals surcharge">
3 <th class="mark" scope="row">
4 <span class="title" data-bind="text: getTitle()"></span>
5 </th>
6 <td class="amount">
7 <span class="price" data-bind="text: getValue(), attr: {'data-th': name}"></span>
8 </td>
9</tr>
10<!-- /ko -->

Display price-adjusted total on the checkout page#

To display the price-adjusted total on the checkout page, add it to the totals component.

VENDOR/MODULE/view/frontend/layout/checkout_index_index.xml:

Copied to your clipboard
1<?xml version="1.0"?>
2<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
3 <body>
4 <referenceBlock name="checkout.root">
5 <arguments>
6 <argument name="jsLayout" xsi:type="array">
7 <item name="components" xsi:type="array">
8 <item name="checkout" xsi:type="array">
9 <item name="children" xsi:type="array">
10 <item name="sidebar" xsi:type="array">
11 <item name="children" xsi:type="array">
12 <item name="summary" xsi:type="array">
13 <item name="children" xsi:type="array">
14 <item name="totals" xsi:type="array">
15 <item name="children" xsi:type="array">
16 <item name="discount" xsi:type="array">
17 <item name="component" xsi:type="string">VENDOR_MODULE/js/view/cart/totals/surcharge</item>
18 <item name="config" xsi:type="array">
19 <item name="title" xsi:type="string" translate="true">Custom Surcharge</item>
20 </item>
21 </item>
22 </item>
23 </item>
24 </item>
25 </item>
26 </item>
27 </item>
28 </item>
29 </item>
30 </item>
31 </argument>
32 </arguments>
33 </referenceBlock>
34 </body>
35</page>

The VENDOR_MODULE/js/view/cart/totals/surcharge component was defined earlier in the article.

If all has gone smoothly, when run, you should see the adjusted price reflected in the shopping cart.

Was this helpful?
  • Privacy
  • Terms of Use
  • Do not sell my personal information
  • AdChoices
Copyright © 2022 Adobe. All rights reserved.