0

I am using an extension that displays a message as the customer approaches a Free Shipping threshold (https://aheadworks.com/free-shipping-bar-extension-for-magento-2), eg, "30 euro left until Free Shipping" etc. However we also have a donation extension that allows customers to make donations in the checkout. The donation amount is being taken into account by the Free Shipping Bar extension and potentially telling the customer they are going to get free shipping when in fact they're not, as the donation is not counted towards free shipping. The actual shipping methods are working fine.

I think the solution is to change this line in the extension:

$total = $quote->getGrandTotal();  

to this

$total = $quote->getSubtotal(); 

(grand total includes any donations, whereas subtotal does not)

I did this directly in the extension code - \vendor\aheadworks\module-freeshippinglabel\Model\Label\Renderer\Quote\Calculator.php and it seemed to work. So now I am trying to redo it so that I don't overwrite the extension code. I think what I have to do is build a custom module with a preference? This is what I have so far:

app\code\Website\FreeShippingLabelNew\registration.php

<?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Website_FreeShippingLabelNew',
    __DIR__
);

app\code\Website\FreeShippingLabelNew\etc\di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
  <preference for="Aheadworks\Freeshippinglabel\Model\Label\Renderer\Quote\Calculator" type="Website\FreeShippingLabelNew\Model\Label\Renderer\Quote\Calculator" />
</config>

app\code\Website\FreeShippingLabelNew\etc\module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
  <module name="Website_FreeShippingLabelNew" setup_version="1.0.0" />    
</config>

app\code\Website\FreeShippingLabelNew\Model\Label\Renderer\Quote\Calculator.php

    <?php
namespace Website\FreeShippingLabelNew\Model\Label\Renderer\Quote;

/**use \Aheadworks\Freeshippinglabel\Model\Label\Condition\Loader as ConditionLoader;

 * Class Calculator
 *
 * @package Aheadworks\Freeshippinglabel\Model\Label\Renderer\Quote
 */
class Calculator extends \Aheadworks\Freeshippinglabel\Model\Label\Renderer\Quote\Calculator
{
    /**
     * @var ConditionLoader
     
    private $conditionLoader;*/

    /**
     * Calculate quote cost
     *
     * @param LabelInterface $label
     * @param Quote $quote
     * @return float
     */
    public function calculate($label, $quote)
    {   
  
    $total = 0;
        $conditions = $this->conditionLoader->loadCartCondition($label);
        $quote->collectTotals();
        if (!$label->getIsEnabledCartConditions()) {
            $total = $quote->getSubtotal();     
                $logger = \Magento\Framework\App\ObjectManager::getInstance()->get('\Psr\Log\LoggerInterface');
                $logger->debug('FreeShipping Model Override Test');  
                $logger->debug($total); 
            $total -= $quote->getShippingAmount();
        } else {
            foreach ($quote->getItems() as $item) {
                if (!$this->validator->isItemValid($item, $conditions)) {
                    $discount = $item->getDiscountAmount();
                    if ($item->getProduct()->getTypeId() == BundleType::TYPE_CODE) {
                        $discount = 0;
                        foreach ($item->getChildren() as $childItem) {
                            $discount += $childItem->getDiscountAmount();
                        }
                    }
                    $total += $item->getRowTotal() + $item->getTaxAmount() - $discount;
                }
            }
        }

        return $total;
    }
}

The original Calculator.php file is as follows:

<?php
namespace Aheadworks\Freeshippinglabel\Model\Label\Renderer\Quote;

use Magento\Quote\Model\Quote;
use Aheadworks\Freeshippinglabel\Api\Data\LabelInterface;
use Aheadworks\Freeshippinglabel\Model\Label\Condition\Loader as ConditionLoader;
use Magento\Bundle\Model\Product\Type as BundleType;

/**
 * Class Calculator
 *
 * @package Aheadworks\Freeshippinglabel\Model\Label\Renderer\Quote
 */
class Calculator
{
    /**
     * @var ConditionLoader
     */
    private $conditionLoader;

    /**
     * @var Validator
     */
    private $validator;

    /**
     * @param ConditionLoader $conditionLoader
     * @param Validator $validator
     */
    public function __construct(
        ConditionLoader $conditionLoader,
        Validator $validator
    ) {
        $this->conditionLoader = $conditionLoader;
        $this->validator = $validator;
    }

    /**
     * Calculate quote cost
     *
     * @param LabelInterface $label
     * @param Quote $quote
     * @return float
     */
    public function calculate($label, $quote)
    {
        $total = 0;
        $conditions = $this->conditionLoader->loadCartCondition($label);
        $quote->collectTotals();
        if (!$label->getIsEnabledCartConditions()) {
            $total = $quote->getGrandTotal();            
            $total -= $quote->getShippingAmount();
        } else {
            foreach ($quote->getItems() as $item) {
                if (!$this->validator->isItemValid($item, $conditions)) {
                    $discount = $item->getDiscountAmount();
                    if ($item->getProduct()->getTypeId() == BundleType::TYPE_CODE) {
                        $discount = 0;
                        foreach ($item->getChildren() as $childItem) {
                            $discount += $childItem->getDiscountAmount();
                        }
                    }
                    $total += $item->getRowTotal() + $item->getTaxAmount() - $discount;
                }
            }
        }

        return $total;
    }
}

Then I have run module:enable and then setup:upgrade and cache:clean.

On the cart page I get an error:

1 exception(s): Exception #0 (Exception): Notice: Undefined property: Website\FreeShippingLabelNew\Model\Label\Renderer\Quote\Calculator::$conditionLoader in /home/sitename/public_html/app/code/Website/FreeShippingLabelNew/Model/Label/Renderer/Quote/Calculator.php on line 28

If I uncomment the lines

use \Aheadworks\Freeshippinglabel\Model\Label\Condition\Loader as ConditionLoader; 

and this line

private $conditionLoader;

That error goes but there is a new one:

Error: Call to a member function loadCartCondition() on null in /home/website/public_html/app/code/Website/FreeShippingLabelNew/Model/Label/Renderer/Quote/Calculator.php:30

but I do get my logging message and my subtotal in debug.log so I think the module is put together correctly in terms of files etc.

If I put the whole content of the Calculator class from the original into my version I get this:

3 exception(s): Exception #0 (Magento\Framework\Exception\LocalizedException): Invalid block type: Aheadworks\Freeshippinglabel\Block\Label Exception #1 (ReflectionException): Impossible to process constructor argument Parameter #1 [ Website\FreeShippingLabelNew\Model\Label\Renderer\Quote\Validator $validator ] of Website\FreeShippingLabelNew\Model\Label\Renderer\Quote\Calculator class Exception #2 (ReflectionException): Class Website\FreeShippingLabelNew\Model\Label\Renderer\Quote\Validator does not exist

I'm just wondering how do I write this Calculator.php to get it to work. Every time I change Calculator.php I am rerunning setup:upgrade and cache:clean.

Edited after Sohel Rana's answer below: Current code is:

<?php
namespace OB\FreeShippingLabelOB\Model\Label\Renderer\Quote;
/*use \Aheadworks\Freeshippinglabel\Api\Data\LabelInterface;*/
use \Aheadworks\Freeshippinglabel\Model\Label\Condition\Loader as ConditionLoader;
/**
 * Class Calculator
 *
 * @package Aheadworks\Freeshippinglabel\Model\Label\Renderer\Quote
 */
class Calculator extends \Aheadworks\Freeshippinglabel\Model\Label\Renderer\Quote\Calculator
{
   
    /**
     * @var ConditionLoader
     */
    private $conditionLoader;

    /**
     * @var Validator
     */
    private $validator;

    /**
     * @param ConditionLoader $conditionLoader
     * @param Validator $validator
     */
    public function __construct(
        ConditionLoader $conditionLoader,
        Validator $validator
    ) {
        $this->conditionLoader = $conditionLoader;
        $this->validator = $validator;
        parent::__construct($conditionLoader, $validator);
    }

    /**
     * Calculate quote cost
     *
     * @param LabelInterface $label
     * @param Quote $quote
     * @return float
     */
    public function calculate($label, $quote)
    {   
  
    $total = 0;
        $conditions = $this->conditionLoader->loadCartCondition($label);
        $quote->collectTotals();
        if (!$label->getIsEnabledCartConditions()) {
            $total = $quote->getSubtotal();     
                $logger = \Magento\Framework\App\ObjectManager::getInstance()->get('\Psr\Log\LoggerInterface');
                $logger->debug('FreeShipping Model Override Test');  
                $logger->debug($total); 
            $total -= $quote->getShippingAmount();
        } else {
            foreach ($quote->getItems() as $item) {
                if (!$this->validator->isItemValid($item, $conditions)) {
                    $discount = $item->getDiscountAmount();
                    if ($item->getProduct()->getTypeId() == BundleType::TYPE_CODE) {
                        $discount = 0;
                        foreach ($item->getChildren() as $childItem) {
                            $discount += $childItem->getDiscountAmount();
                        }
                    }
                    $total += $item->getRowTotal() + $item->getTaxAmount() - $discount;
                }
            }
        }

        return $total;
    }
}

Still same errors: 3 exception(s): Exception #0 (Magento\Framework\Exception\LocalizedException): Invalid block type: Aheadworks\Freeshippinglabel\Block\Label Exception #1 (ReflectionException): Impossible to process constructor argument Parameter #1 [ Website\FreeShippingLabelNew\Model\Label\Renderer\Quote\Validator $validator ] of Website\FreeShippingLabelNew\Model\Label\Renderer\Quote\Calculator class Exception #2 (ReflectionException): Class Website\FreeShippingLabelNew\Model\Label\Renderer\Quote\Validator does not exist

1 Answer 1

0

This is a property scope issue. Add the following code in your custom class:

/**
 * @var ConditionLoader
 */
private $conditionLoader;

/**
 * @var Validator
 */
private $validator;

/**
 * @param ConditionLoader $conditionLoader
 * @param Validator $validator
 */
public function __construct(
    ConditionLoader $conditionLoader,
    Validator $validator
) {
    $this->conditionLoader = $conditionLoader;
    $this->validator = $validator;
    parent::__construct($conditionLoader, $validator)
}
4
  • Thank you, just tried that - it's still giving same errors, code in OP 3 exception(s): Exception #0 (Magento\Framework\Exception\LocalizedException): Invalid block type: Aheadworks\Freeshippinglabel\Block\Label Exception #1 (ReflectionException): Impossible to process constructor argument Parameter #1 [ <required> Website\FreeShippingLabelNew\Model\Label\Renderer\Quote\Validator $validator ] of Website\FreeShippingLabelNew\Model\Label\Renderer\Quote\Calculator class Exception #2 (ReflectionException): Class Website\FreeShippingLabelNew\Model\Label\Renderer\Quote\Validator does not exist Oct 18, 2021 at 13:30
  • Add "use \Aheadworks\Freeshippinglabel\Model\Label\Condition\Loader as ConditionLoader;' and Validator
    – Sohel Rana
    Oct 18, 2021 at 13:57
  • Might be Aheadworks\Freeshippinglabel\Model\Label\Renderer\Quote\Validator, but not sure. Use the exact class
    – Sohel Rana
    Oct 18, 2021 at 13:59
  • Thank you so so much, it seems to have worked - I have use \Aheadworks\Freeshippinglabel\Api\Data\LabelInterface; use \Aheadworks\Freeshippinglabel\Model\Label\Condition\Loader as ConditionLoader; use \Aheadworks\Freeshippinglabel\Model\Label\Renderer\Quote\Validator as Validator; Oct 18, 2021 at 14:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.