/**
  * Process original realtions then save partial payment totals.
  *
  * @param \Magento\Quote\Model\Quote\Relation $subject
  * @param \Closure $proceed
  * @param \Magento\Framework\Model\AbstractModel $object
  *
  * @SuppressWarnings(PHPMD.UnusedFormalParameter)
  */
 public function aroundProcessRelation(\Magento\Quote\Model\Quote\Relation $subject, \Closure $proceed, \Magento\Framework\Model\AbstractModel $object)
 {
     $proceed($object);
     assert($object instanceof \Magento\Quote\Model\Quote);
     $quoteId = $object->getId();
     /** @var \Magento\Quote\Model\Quote\Address $addrShipping */
     $addrShipping = $object->getShippingAddress();
     $total = $addrShipping->getData(\Praxigento\Wallet\Model\Quote\Address\Total\Partial::CODE_TOTAL);
     $baseTotal = $addrShipping->getData(\Praxigento\Wallet\Model\Quote\Address\Total\Partial::CODE_BASE_TOTAL);
     /* check if current total exist */
     /** @var \Praxigento\Wallet\Data\Entity\Partial\Quote $exist */
     $exist = $this->_repoPartialQuote->getById($quoteId);
     if ($exist) {
         /* there is record in registry */
         $baseTotalExist = $exist->getBasePartialAmount();
         if ($baseTotalExist == $baseTotal) {
             /* amount is equal to stored, do nothing */
         } elseif (abs($baseTotal) < 1.0E-5) {
             /* amount is zero, remove data from registry */
             $this->_repoPartialQuote->deleteById($quoteId);
         } else {
             /* update saved value */
             $exist->setPartialAmount($total);
             $exist->setBasePartialAmount($baseTotal);
             $this->_repoPartialQuote->updateById($quoteId, $exist);
         }
     } elseif (abs($baseTotal) > 1.0E-5) {
         /* create new record in registry */
         $data = new \Praxigento\Wallet\Data\Entity\Partial\Quote();
         $data->setQuoteRef($quoteId);
         $exist->setPartialAmount($total);
         $data->setBasePartialAmount($baseTotal);
         $this->_repoPartialQuote->create($data);
     }
 }
 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);
     /* get fresh grands from calculating totals */
     $grandBase = $total->getData(\Magento\Quote\Api\Data\TotalsInterface::KEY_BASE_GRAND_TOTAL);
     $grand = $total->getData(\Magento\Quote\Api\Data\TotalsInterface::KEY_GRAND_TOTAL);
     if ($grandBase == 0) {
         /* this is billing address, compose result */
         $total->setBaseTotalAmount(self::CODE, 0);
         $total->setTotalAmount(self::CODE, 0);
     } else {
         $isPartialEnabled = $this->hlpConfig->getWalletPartialEnabled();
         if ($isPartialEnabled) {
             $quoteId = $quote->getId();
             /** @var \Praxigento\Wallet\Data\Entity\Partial\Quote $partialDataSaved */
             $partialDataSaved = $this->repoPartialQuote->getById($quoteId);
             /**
              * Check quote for partial payment switcher.
              * See \Praxigento\Wallet\Observer\SalesQuotePaymentImportDataBefore
              */
             $usePartial = $quote->getData(self::ATTR_QUOTE_SWITCH_PARTIAL_PAYMENT);
             if (!is_null($usePartial)) {
                 /* there is switcher in the quote,  */
                 if ($usePartial) {
                     /* switcher is on - we need to recalculate amounts */
                     /* get max. percent to pay partially */
                     $percent = $this->hlpConfig->getWalletPartialPercent();
                     /* calculate values */
                     $partial = $this->hlpPriceCurrency->round($grand * $percent);
                     $partialBase = $this->hlpPriceCurrency->round($grandBase * $percent);
                     /* re-save partial if they are different */
                     if ($partialDataSaved) {
                         /* get saved partial totals */
                         $partialSavedBase = $partialDataSaved->getBasePartialAmount();
                         $partialSaved = $partialDataSaved->getPartialAmount();
                         if ($partialSavedBase != $partialBase || $partialSaved != $partial) {
                             /* re-save quote partial in registry */
                             $partialDataSaved->setBasePartialAmount($partialBase);
                             $partialDataSaved->setPartialAmount($partial);
                             $this->repoPartialQuote->updateById($quoteId, $partialDataSaved);
                         }
                     } else {
                         /* create new record in the registry */
                         $partialDataSaved = new \Praxigento\Wallet\Data\Entity\Partial\Quote();
                         $partialDataSaved->setQuoteRef($quoteId);
                         $partialDataSaved->setBasePartialAmount($partialBase);
                         $partialDataSaved->setPartialAmount($partial);
                         $this->repoPartialQuote->create($partialDataSaved);
                     }
                     /* reset totals in quote and compose result */
                     $quote->setData(self::CODE_BASE_TOTAL, $partialBase);
                     $quote->setData(self::CODE_TOTAL, $partial);
                     $total->setBaseTotalAmount(self::CODE, $partialBase);
                     $total->setTotalAmount(self::CODE, $partial);
                 } else {
                     /* switcher is off - clean up saved quote if exist */
                     if ($partialDataSaved) {
                         $this->repoPartialQuote->deleteById($quoteId);
                     }
                     /* reset totals in quote and compose result */
                     $quote->setData(self::CODE_BASE_TOTAL, 0);
                     $quote->setData(self::CODE_TOTAL, 0);
                     $total->setBaseTotalAmount(self::CODE, 0);
                     $total->setTotalAmount(self::CODE, 0);
                 }
             } else {
                 /* use quote saved totals if exist */
                 if ($partialDataSaved) {
                     /* there are saved data for the quote */
                     /* get max. percent to pay partially */
                     $percent = $this->hlpConfig->getWalletPartialPercent();
                     /* calculate values */
                     $partialBase = $this->hlpPriceCurrency->round($grandBase * $percent);
                     $partial = $this->hlpPriceCurrency->round($grand * $percent);
                     /* get saved partial totals */
                     $partialSavedBase = $partialDataSaved->getBasePartialAmount();
                     $partialSaved = $partialDataSaved->getPartialAmount();
                     if ($partialSavedBase != $partialBase || $partialSaved != $partial) {
                         /* re-save quote partial in registry */
                         $partialDataSaved->setBasePartialAmount($partialBase);
                         $partialDataSaved->setPartialAmount($partial);
                         $this->repoPartialQuote->updateById($quoteId, $partialDataSaved);
                     }
                     /* reset totals in quote and compose result */
                     $quote->setData(self::CODE_BASE_TOTAL, $partialBase);
                     $quote->setData(self::CODE_TOTAL, $partial);
                     $total->setBaseTotalAmount(self::CODE, $partialBase);
                     $total->setTotalAmount(self::CODE, $partial);
                 } else {
                     /* partial payment does not used */
                     /* reset totals in quote and compose result */
                     $quote->setData(self::CODE_BASE_TOTAL, 0);
                     $quote->setData(self::CODE_TOTAL, 0);
                     $total->setBaseTotalAmount(self::CODE, 0);
                     $total->setTotalAmount(self::CODE, 0);
                 }
             }
         }
     }
     return $this;
 }