/**
  * 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);
     }
 }
 /**
  * MOBI-486: Add partial payment data to totals are requested with REST API.
  * MOBI-489: Add partial payment configuration to totals extension attributes.
  *
  * @param \Magento\Quote\Model\Cart\CartTotalRepository $subject
  * @param \Closure $proceed
  * @param $cartId
  * @return \Magento\Quote\Api\Data\TotalsInterface
  */
 public function aroundGet(\Magento\Quote\Model\Cart\CartTotalRepository $subject, \Closure $proceed, $cartId)
 {
     /** @var \Magento\Quote\Model\Cart\Totals $result */
     $result = $proceed($cartId);
     /* Get partial method configuration */
     $isPartialEnabled = $this->_hlpCfg->getWalletPartialEnabled();
     if ($isPartialEnabled) {
         //            $partialMaxPercent = $this->_hlpCfg->getWalletPartialPercent();
         //            /** @var \Magento\Quote\Api\Data\TotalExtensionInterface $exts */
         //            $exts = $this->_factTotalExt->create();
         //            /** @var \Praxigento\Wallet\Api\Data\Config\Payment\Method $extData */
         //            $extData = new \Praxigento\Wallet\Api\Data\Config\Payment\Method();
         //            $extData->setPartialMaxPercent($partialMaxPercent);
         //            $extData->setIsPartialEnabled($isPartialEnabled);
         //            $exts->setPraxigentoWalletPaymentConfig($extData);
         //            $result->setExtensionAttributes($exts);
         /* get partial data from repository */
         /** @var \Praxigento\Wallet\Data\Entity\Partial\Quote $found */
         $found = $this->_repoPartialQuote->getById($cartId);
         if ($found) {
             $basePartial = $found->getBasePartialAmount();
             $basePartial = $this->_hlpPriceCurrency->round($basePartial);
             /* add current partial total to segment */
             $segments = $result->getTotalSegments();
             /** @var \Magento\Quote\Api\Data\TotalSegmentInterface $seg */
             $seg = $this->_manObj->create(\Magento\Quote\Api\Data\TotalSegmentInterface::class);
             $seg->setCode(self::TOTAL_SEGMENT);
             $seg->setValue($basePartial);
             $segments[self::TOTAL_SEGMENT] = $seg;
             $result->setTotalSegments($segments);
         }
     }
     return $result;
 }
 public function execute(\Magento\Framework\Event\Observer $observer)
 {
     /** @var \Magento\Sales\Model\Order $order */
     $payment = $observer->getData(self::DATA_PAYMENT);
     assert($payment instanceof \Magento\Sales\Model\Order\Payment);
     $order = $payment->getOrder();
     $quoteId = $order->getQuoteId();
     $regQuote = $this->_repoPartialQuote->getById($quoteId);
     if ($regQuote) {
         $orderId = $order->getId();
         $customerId = $order->getCustomerId();
         $amount = $regQuote->getBasePartialAmount();
         $req = new \Praxigento\Wallet\Service\Operation\Request\PayForSaleOrder();
         $req->setOrderId($orderId);
         $req->setCustomerId($customerId);
         $req->setBaseAmountToPay($amount);
         $this->_callOperation->payForSaleOrder($req);
     }
 }
 /**
  * Decrease captured amount for partial payments.
  *
  * @param \Magento\Sales\Model\Order\Payment\Processor $subject
  * @param \Closure $proceed
  * @param \Magento\Sales\Api\Data\OrderPaymentInterface $payment
  * @param \Magento\Sales\Api\Data\InvoiceInterface|null $invoice
  * @return \Magento\Sales\Api\Data\OrderPaymentInterface
  */
 public function aroundCapture(\Magento\Sales\Model\Order\Payment\Processor $subject, \Closure $proceed, \Magento\Sales\Api\Data\OrderPaymentInterface $payment, \Magento\Sales\Api\Data\InvoiceInterface $invoice = null)
 {
     if ($invoice) {
         /* try to find related record in quote registry */
         $order = $payment->getOrder();
         $quoteId = $order->getQuoteId();
         $found = $this->_repoPartialQuote->getById($quoteId);
         if ($found) {
             /* decrease amount in invoice */
             $partialBase = $found->getBasePartialAmount();
             $partial = $found->getPartialAmount();
             $grandTotalBase = $invoice->getBaseGrandTotal();
             $grandTotal = $invoice->getGrandTotal();
             $grandTotalBase -= $partialBase;
             $grandTotal -= $partial;
             $invoice->setBaseGrandTotal($grandTotalBase);
             $invoice->setGrandTotal($grandTotal);
         }
     }
     $result = $proceed($payment, $invoice);
     return $result;
 }
 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;
 }
 /**
  * Delete partial payment registry data before quote deletion.
  *
  * @param $subject
  * @param \Magento\Quote\Api\Data\CartInterface $quote
  * @return array
  *
  * @SuppressWarnings(PHPMD.UnusedFormalParameter)
  */
 public function beforeDelete($subject, \Magento\Quote\Api\Data\CartInterface $quote)
 {
     $quoteId = $quote->getId();
     $this->_repoPartialQuote->deleteById($quoteId);
     return [$quote];
 }