Question

I'm in the process of adding support for a 3rd party gift card system. These cards will not exist in any way within the context of Magento, and an external web based API will validate/confirm balance/etc.

With that in mind, I simply need a way to alter the final cost of the order by adding one or more gift cards.

I feel like I'm close, but I'm getting very confused by how totals collection works in regards to \Magento\Quote\Model\Quote and \Magento\Quote\Model\Quote\Address\Total, specifically their ->getBaseGrandTotal()/->setBaseGrandTotal()/->getGrandTotal()/->setGrandTotal() methods.

$total->get[Base]GrandTotal() always seem to come back with a null or 0 value, even after calling $total->set[Base]GrandTotal(1234);

Here is my current collect() method, which seems to be not affecting the order total cost at all.

public function collect(
    \Magento\Quote\Model\Quote $quote,
    \Magento\Quote\Api\Data\ShippingAssignmentInterface $shippingAssignment,
    \Magento\Quote\Model\Quote\Address\Total $total
) {
    parent::collect($quote, $shippingAssignment, $total);

    $baseGrandTotal = $total->getGrandTotal(); //this is always zero!
    $totalGiftCardBalance = $this->_CardSessionHelper->GetTotalAvailableBalanceOfCurrentGiftCards();

    $giftCardContribution = min($baseGrandTotal, $totalGiftCardBalance);
    //this takes the total viable gift card amount and spreads it over multiple gift cards
    //depending on how much balance each one has 
    $this->_CardSessionHelper->AllocateToGiftCards($giftCardContribution);

    //$contribution is a negative value determined by the previous allocation
    $contribution = $this->_CardSessionHelper->GetSumOfCurrentGiftCardsContribution();
    $total->setGrandTotal($contribution);
    $total->setBaseGrandTotal($this->_PriceCurrency->convert($contribution));

    return $this;
}

I've had other variations of this method which $quote->set[Base]GrandTotal, and seemed to work for the most part, but trying to work out additional gift card contributions after the fact would result in negative quote total values, or other values that made little sense.

In addition to this, the collection seems to happen multiple times - I presume this is because of both billing and shipping addresses.

Is there a way to get it to work for a billing address only?

Was it helpful?

Solution

Collect Totals:

We should base on shipping address.

\Magento\Quote\Model\Quote::collectTotals (can be called at the first) loops through each quote address (quote address total):

 $total = $this->totalsCollector->collect($this);

The \Magento\Quote\Model\Quote\TotalsCollector::collect() and collectAddressTotals() will be called for the next step

\Magento\Quote\Model\Quote\TotalsCollector::collectAddressTotals()

 foreach ($this->collectorList->getCollectors($quote->getStoreId()) as $collector) {
            /** @var CollectorInterface $collector */
            $collector->collect($quote, $shippingAssignment, $total);
 }

In the foreach loop, we will get the collect total of each total Model, for example: \Magento\Quote\Model\Quote\Address\Total\Subtotal::collect(), Magento\Weee\Model\Total\Quote\Weee::collect(), Magento\SalesRule\Model\Quote\Discount::collect(). Our custom total will be called in this loop also.

Each total Model based on the shipping address.

So, we need to check: if having shipping address items, we will process the custom totals

For example, in the collect method, we need to check: vendor/magento/module-sales-rule/Model/Quote/Discount.php

    parent::collect($quote, $shippingAssignment, $total);

    $items = $shippingAssignment->getItems();
    if (!count($items)) {
        return $this;
    }

Or (your case can be used)

if ($shippingAssignment->getShipping()->getAddress()->getAddressType() != Address::TYPE_SHIPPING) {
            return $this;
}

Grand Totals:

As far as I know, the grand total is the "final" total after tax, discount,....

  • setBaseGrandTotal: the grand total bases on base currency.

  • setGrandTotal : bases on the current currency.

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top