diff --git a/Model/Config/CurrencyRoundingConfig.php b/Model/Config/CurrencyRoundingConfig.php
index 21261df..4052200 100644
--- a/Model/Config/CurrencyRoundingConfig.php
+++ b/Model/Config/CurrencyRoundingConfig.php
@@ -7,8 +7,8 @@
namespace Opengento\CurrencyPrecision\Model\Config;
-use Magento\Store\Model\ScopeInterface;
use Magento\Framework\App\Config\ScopeConfigInterface;
+use Magento\Store\Model\ScopeInterface;
/**
* System configuration of currencies rounding.
diff --git a/Observer/AdjustCurrencyPrecision.php b/Observer/AdjustCurrencyPrecision.php
index 9ae4ffe..3731a6a 100644
--- a/Observer/AdjustCurrencyPrecision.php
+++ b/Observer/AdjustCurrencyPrecision.php
@@ -8,8 +8,8 @@
namespace Opengento\CurrencyPrecision\Observer;
use Magento\Framework\DataObject;
-use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\Event\Observer;
+use Magento\Framework\Event\ObserverInterface;
use Opengento\CurrencyPrecision\Model\CurrencyRounding;
/**
diff --git a/Plugin/CatalogRule/Model/Indexer/ProductPriceCalculatorRound.php b/Plugin/CatalogRule/Model/Indexer/ProductPriceCalculatorRound.php
new file mode 100644
index 0000000..4d559a2
--- /dev/null
+++ b/Plugin/CatalogRule/Model/Indexer/ProductPriceCalculatorRound.php
@@ -0,0 +1,61 @@
+storeManager = $storeManager;
+ $this->priceCurrency = $priceCurrency;
+ }
+
+ /**
+ * Extract currency object and pass to CurrencyRoundingForAdmin
+ *
+ * @param ProductPriceCalculator $calculator
+ * @param $ruleData
+ * @param null $productData
+ * @return array
+ * @throws \Magento\Framework\Exception\LocalizedException
+ * @see \Opengento\CurrencyPrecision\Plugin\Directory\Model\CurrencyRoundingForAdmin
+ */
+ public function beforeCalculate(
+ ProductPriceCalculator $calculator,
+ $ruleData,
+ $productData = null
+ ) {
+ $website = $this->storeManager->getWebsite($ruleData['website_id']);
+ $currency = $this->priceCurrency->getCurrency($website->getDefaultStore()->getId());
+ return [$ruleData, $productData];
+ }
+}
diff --git a/Plugin/Directory/Model/CurrencyRoundingForAdmin.php b/Plugin/Directory/Model/CurrencyRoundingForAdmin.php
new file mode 100644
index 0000000..9f5a5f1
--- /dev/null
+++ b/Plugin/Directory/Model/CurrencyRoundingForAdmin.php
@@ -0,0 +1,133 @@
+model = $model;
+ $this->storeManager = $storeManager;
+ }
+
+ /**
+ * Override original method to apply correct rounding logic.
+ *
+ * @param PriceCurrency $priceCurrency
+ * @param \Closure $proceed
+ * @param float $amount
+ * @param string $scope
+ * @param string $currency
+ * @param int $precision
+ * @return float
+ * @throws \Magento\Framework\Exception\NoSuchEntityException
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+ */
+ public function aroundConvertAndRound(
+ PriceCurrency $priceCurrency,
+ \Closure $proceed,
+ $amount,
+ $scope = null,
+ $currency = null,
+ $precision = PriceCurrency::DEFAULT_PRECISION
+ ) {
+ $targetCurrency = $priceCurrency->getCurrency($scope, $currency);
+ $convertedAmount = $this->storeManager->getStore($scope)->getBaseCurrency()->convert($amount, $targetCurrency);
+ if ($targetCurrency->getCode() === null) {
+ return $convertedAmount;
+ }
+
+ $roundedAmount = $this->round($targetCurrency->getCode(), (float)$convertedAmount);
+ return $roundedAmount;
+ }
+
+ /**
+ * Override original method to apply correct rounding logic.
+ *
+ * @param PriceCurrency $priceCurrency
+ * @param \Closure $proceed
+ * @param float $amount
+ * @return float
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+ */
+ public function aroundRound(
+ PriceCurrency $priceCurrency,
+ \Closure $proceed,
+ $amount
+ ) {
+ $currency = $this->currency;
+ $currencyCode = null;
+ if ($currency !== null) {
+ $currencyCode = $currency->getCode();
+ }
+
+ if ($currencyCode === null) {
+ return (float)$amount;
+ }
+
+ return $this->round($currencyCode, (float)$amount);
+ }
+
+ /**
+ * Set currency object when getCurrency called.
+ *
+ * @param \Magento\Directory\Model\PriceCurrency $subject
+ * @param $result
+ * @param bool|int|ScopeInterface|string|null $scope
+ * @param AbstractModel|string|null $currency
+ */
+ public function afterGetCurrency(
+ PriceCurrency $subject,
+ $result,
+ $scope = null,
+ $currency = null
+ ) {
+ $this->currency = $result;
+ return $result;
+ }
+
+
+
+ /**
+ * Round currency using rounding service.
+ */
+ private function round(string $currencyCode, float $amount): float
+ {
+ return $this->model->round($currencyCode, $amount);
+ }
+
+}
diff --git a/Plugin/PayPal/Api/RoundAmount.php b/Plugin/PayPal/Api/RoundAmount.php
new file mode 100644
index 0000000..41debca
--- /dev/null
+++ b/Plugin/PayPal/Api/RoundAmount.php
@@ -0,0 +1,39 @@
+model = $model;
+ }
+
+ /**
+ * @param Nvp $nvp
+ * @param \Closure $proceed
+ * @param $price
+ * @return string
+ */
+ public function aroundFormatPrice(
+ Nvp $nvp,
+ \Closure $proceed,
+ $price
+ ) {
+ $currencyCode = $nvp->getCurrencyCode();
+ $price = $this->model->round($currencyCode, $price);
+ return sprintf('%.2F', $price);
+ }
+}
diff --git a/Plugin/SalesRule/RoundDiscount.php b/Plugin/SalesRule/RoundDiscount.php
new file mode 100644
index 0000000..77a6f4e
--- /dev/null
+++ b/Plugin/SalesRule/RoundDiscount.php
@@ -0,0 +1,48 @@
+currencyRounding = $currencyRounding;
+ }
+
+ /**
+ * @param DiscountInterface $subject
+ * @param Data $result
+ * @param Rule $rule
+ * @param AbstractItem $item
+ * @param float $qty
+ * @return Data $result
+ */
+ public function afterCalculate(DiscountInterface $subject, $result, $rule, $item, $qty)
+ {
+ $quote = $item->getQuote();
+ $baseCurrency = $quote->getBaseCurrencyCode();
+ $quoteCurrency = $quote->getQuoteCurrencyCode();
+
+ $result->setAmount($this->currencyRounding->round($quoteCurrency, $result->getAmount()));
+ $result->setBaseAmount($this->currencyRounding->round($baseCurrency, $result->getBaseAmount()));
+ $result->setBaseOriginalAmount($this->currencyRounding->round($baseCurrency, $result->getBaseOriginalAmount()));
+ $result->setOriginalAmount($this->currencyRounding->round($quoteCurrency, $result->getOriginalAmount()));
+
+ return $result;
+ }
+}
diff --git a/Plugin/Tax/Pricing/ModifyAdjustment.php b/Plugin/Tax/Pricing/ModifyAdjustment.php
new file mode 100644
index 0000000..f370de4
--- /dev/null
+++ b/Plugin/Tax/Pricing/ModifyAdjustment.php
@@ -0,0 +1,132 @@
+taxHelper = $taxHelper;
+ $this->catalogHelper = $catalogHelper;
+ $this->priceCurrency = $priceCurrency;
+ $this->currencyRounding = $currencyRounding;
+ }
+
+ /**
+ * @param Adjustment $subject
+ * @param \Closure $proceed
+ * @param $amount
+ * @param SaleableInterface $saleableItem
+ * @param array $context
+ * @return float
+ */
+ public function aroundExtractAdjustment(
+ Adjustment $subject,
+ \Closure $proceed,
+ $amount,
+ SaleableInterface $saleableItem,
+ $context = []
+ ) {
+ if ($this->taxHelper->priceIncludesTax()) {
+ $adjustedAmount = $this->catalogHelper->getTaxPrice(
+ $saleableItem,
+ $amount,
+ false,
+ null,
+ null,
+ null,
+ null,
+ null,
+ $this->shouldRound()
+ );
+ $result = $amount - $adjustedAmount;
+ } else {
+ $result = 0.;
+ }
+ return $result;
+ }
+
+ /**
+ * @param Adjustment $subject
+ * @param \Closure $proceed
+ * @param $amount
+ * @param SaleableInterface $saleableItem
+ * @param array $context
+ * @return float
+ */
+ public function aroundApplyAdjustment(
+ Adjustment $subject,
+ \Closure $proceed,
+ $amount,
+ SaleableInterface $saleableItem,
+ $context = []
+ ) {
+ return $this->catalogHelper->getTaxPrice(
+ $saleableItem,
+ $amount,
+ true,
+ null,
+ null,
+ null,
+ null,
+ null,
+ $this->shouldRound()
+ );
+ }
+
+ /**
+ * Retrieve should rounding or not.
+ *
+ * @return bool
+ */
+ private function shouldRound()
+ {
+ $currency = $this->priceCurrency->getCurrency();
+ $precision = $this->currencyRounding->getPrecision($currency->getCode());
+ if ($precision === 0) {
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/Plugin/Tax/RoundQuoteItemPrice.php b/Plugin/Tax/RoundQuoteItemPrice.php
new file mode 100644
index 0000000..56f7924
--- /dev/null
+++ b/Plugin/Tax/RoundQuoteItemPrice.php
@@ -0,0 +1,64 @@
+currencyRounding = $currencyRounding;
+ }
+
+ /**
+ * @param CommonTaxCollector $subject
+ * @param CommonTaxCollector $result
+ * @param AbstractItem $quoteItem
+ * @param TaxDetailsItemInterface $itemTaxDetails
+ * @param TaxDetailsItemInterface $baseItemTaxDetails
+ * @param Store $store
+ */
+ public function afterUpdateItemTaxInfo(
+ CommonTaxCollector $subject,
+ CommonTaxCollector $result,
+ AbstractItem $quoteItem,
+ TaxDetailsItemInterface $itemTaxDetails,
+ TaxDetailsItemInterface $baseItemTaxDetails,
+ Store $store
+ ) {
+ $quote = $quoteItem->getQuote();
+ $baseCurrency = $quote->getBaseCurrencyCode();
+ if ($baseCurrency === null) {
+ $baseCurrency = $quote->getStore()->getBaseCurrencyCode();
+ }
+
+ $quoteItem->setBasePrice($this->round($quoteItem->getBasePrice(), $baseCurrency));
+ $quoteItem->setBasePriceInclTax($this->round($quoteItem->getBasePriceInclTax(), $baseCurrency));
+ $quoteItem->setBaseRowTotal($this->round($quoteItem->getBaseRowTotal(), $baseCurrency));
+ $quoteItem->setBaseRowTotalInclTax($this->round($quoteItem->getBaseRowTotalInclTax(), $baseCurrency));
+ $quoteItem->setBaseTaxAmount($this->round($quoteItem->getBaseTaxAmount(), $baseCurrency));
+ $quoteItem->setTaxPercent($baseItemTaxDetails->getTaxPercent());
+ //$quoteItem->setBaseDiscountTaxCompensationAmount($baseItemTaxDetails->getDiscountTaxCompensationAmount());
+
+ return $result;
+ }
+
+ private function round($amount, $currency)
+ {
+ return $this->currencyRounding->round($currency, $amount);
+ }
+}
diff --git a/Plugin/Tax/RoundSubtotal.php b/Plugin/Tax/RoundSubtotal.php
new file mode 100644
index 0000000..4eb564d
--- /dev/null
+++ b/Plugin/Tax/RoundSubtotal.php
@@ -0,0 +1,66 @@
+currencyRounding = $currencyRounding;
+ }
+
+ /**
+ * @param \Magento\Tax\Model\Sales\Total\Quote\Subtotal $subject
+ * @param $result
+ * @param Quote $quote
+ * @param ShippingAssignmentInterface $shippingAssignment
+ * @param Total $total
+ */
+ public function afterCollect(
+ \Magento\Tax\Model\Sales\Total\Quote\Subtotal $subject,
+ $result,
+ Quote $quote,
+ ShippingAssignmentInterface $shippingAssignment,
+ Total $total
+ ) {
+ $baseCurrency = $quote->getBaseCurrencyCode();
+ if ($baseCurrency === null) {
+ $baseCurrency = $quote->getStore()->getBaseCurrencyCode();
+ }
+
+ $total->setBaseTotalAmount('subtotal', $this->round($baseCurrency, $total->getTotalAmount('subtotal')));
+ $total->setBaseTotalAmount('tax', $this->round($baseCurrency, $total->getTotalAmount('tax')));
+ $total->setBaseTotalAmount('discount_tax_compensation', $this->round($baseCurrency, $total->getTotalAmount('discount_tax_compensation')));
+
+ $total->setBaseTaxAmount($this->round($baseCurrency, $total->getBaseTaxAmount()));
+ $total->setBaseSubtotalTotalInclTax(
+ $this->round($baseCurrency, $total->getBaseSubtotalTotalInclTax())
+ );
+ $total->setBaseSubtotalInclTax($this->round($baseCurrency, $total->getBaseSubtotalInclTax()));
+
+ $address = $shippingAssignment->getShipping()->getAddress();
+ $address->setBaseSubtotalTotalInclTax($total->getBaseSubtotalInclTax());
+ $address->setBaseSubtotal($total->getBaseSubtotal());
+ $address->setBaseTaxAmount($total->getBaseTaxAmount());
+ return $result;
+ }
+
+ private function round($code, $amount)
+ {
+ return $this->currencyRounding->round($code, (float)$amount);
+ }
+}
diff --git a/Plugin/Tax/RoundTaxAmount.php b/Plugin/Tax/RoundTaxAmount.php
new file mode 100644
index 0000000..a000b4d
--- /dev/null
+++ b/Plugin/Tax/RoundTaxAmount.php
@@ -0,0 +1,69 @@
+currencyRounding = $currencyRounding;
+ }
+
+ /**
+ * @param \Magento\Tax\Model\Sales\Total\Quote\Tax $subject
+ * @param $result
+ * @param Quote $quote
+ * @param ShippingAssignmentInterface $shippingAssignment
+ * @param Total $total
+ */
+ public function afterCollect(
+ \Magento\Tax\Model\Sales\Total\Quote\Tax $subject,
+ $result,
+ Quote $quote,
+ ShippingAssignmentInterface $shippingAssignment,
+ Total $total
+ ) {
+ $baseCurrency = $quote->getBaseCurrencyCode();
+ if ($baseCurrency === null) {
+ $baseCurrency = $quote->getStore()->getBaseCurrencyCode();
+ }
+
+ $total->setBaseTotalAmount('subtotal', $this->round($baseCurrency, $total->getBaseTotalAmount('subtotal')));
+ $total->setBaseTotalAmount('tax', $this->round($baseCurrency, $total->getBaseTotalAmount('tax')));
+ $total->setBaseTotalAmount('discount_tax_compensation', $this->round($baseCurrency, $total->getBaseTotalAmount('discount_tax_compensation')));
+
+ $total->setBaseTaxAmount($this->round($baseCurrency, $total->getBaseTaxAmount()));
+ $total->setBaseSubtotalTotalInclTax(
+ $this->round($baseCurrency, $total->getBaseSubtotalTotalInclTax())
+ );
+ $total->setBaseSubtotalInclTax($this->round($baseCurrency, $total->getBaseSubtotalInclTax()));
+
+ $address = $shippingAssignment->getShipping()->getAddress();
+ $address->setBaseSubtotalTotalInclTax($total->getBaseSubtotalTotalInclTax());
+ $address->setBaseSubtotal($total->getBaseSubtotal());
+ $address->setBaseTaxAmount($total->getBaseTaxAmount());
+
+ $total->getAppliedTaxes();
+
+ return $result;
+ }
+
+ private function round($code, $amount)
+ {
+ return $this->currencyRounding->round($code, (float)$amount);
+ }
+}
diff --git a/etc/adminhtml/di.xml b/etc/adminhtml/di.xml
new file mode 100644
index 0000000..2a35ccd
--- /dev/null
+++ b/etc/adminhtml/di.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/etc/di.xml b/etc/di.xml
index 306cc32..8c9380a 100644
--- a/etc/di.xml
+++ b/etc/di.xml
@@ -15,4 +15,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/etc/frontend/di.xml b/etc/frontend/di.xml
new file mode 100644
index 0000000..17d8b0b
--- /dev/null
+++ b/etc/frontend/di.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+