-
Notifications
You must be signed in to change notification settings - Fork 71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add dynamic shipping tax calculation #176
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
<?php | ||
/** | ||
* Copyright © 2020 FireGento e.V. | ||
* See LICENSE.md bundled with this module for license details. | ||
*/ | ||
|
||
namespace FireGento\MageSetup\Model\System\Config\Source\Tax; | ||
|
||
use Magento\Framework\Data\OptionSourceInterface; | ||
|
||
/** | ||
* Source model for Dynamic taxes. | ||
*/ | ||
class Dynamic implements OptionSourceInterface | ||
{ | ||
public const DYNAMIC_TYPE_SHIPPING_TAX_DEFAULT = 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe |
||
public const DYNAMIC_TYPE_HIGHEST_PRODUCT_TAX = 1; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe |
||
|
||
/** | ||
* @var array | ||
*/ | ||
private $options; | ||
|
||
/** | ||
* Method for returning options array | ||
* | ||
* @return array|array[] | ||
*/ | ||
public function toOptionArray(): array | ||
{ | ||
if (null === $this->options) { | ||
$options = [ | ||
[ | ||
'value' => self::DYNAMIC_TYPE_SHIPPING_TAX_DEFAULT, | ||
'label' => __('No dynamic shipping tax calculation') | ||
], | ||
[ | ||
'value' => self::DYNAMIC_TYPE_HIGHEST_PRODUCT_TAX, | ||
'label' => __('Use the highest product tax') | ||
] | ||
]; | ||
|
||
$this->options = $options; | ||
} | ||
|
||
return $this->options; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,192 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace FireGento\MageSetup\Plugin\Tax\Config; | ||
|
||
use FireGento\MageSetup\Model\Config as FireGentoConfig; | ||
use FireGento\MageSetup\Model\System\Config\Source\Tax\Dynamic as FireGentoSource; | ||
use Magento\Checkout\Model\Cart; | ||
use Magento\Customer\Model\ResourceModel\GroupRepository; | ||
use Magento\Customer\Model\Session; | ||
use Magento\Framework\App\Config\ScopeConfigInterface; | ||
use Magento\Quote\Model\Quote\Item; | ||
use Magento\Store\Model\ScopeInterface; | ||
use Magento\Store\Model\Store; | ||
use Magento\Tax\Model\Calculation\Proxy; | ||
use Magento\Tax\Model\Config; | ||
|
||
/** | ||
* Class ShippingTaxPlugin | ||
* | ||
* FireGento\MageSetup\Plugin\Tax\Config | ||
*/ | ||
class ShippingTaxPlugin | ||
{ | ||
|
||
/** | ||
* @var ScopeConfigInterface | ||
*/ | ||
private $scopeConfig; | ||
|
||
/** | ||
* @var Cart | ||
*/ | ||
private $cart; | ||
|
||
/** | ||
* @var Session | ||
*/ | ||
private $customerSession; | ||
|
||
/** | ||
* @var GroupRepository | ||
*/ | ||
private $groupRepository; | ||
|
||
/** | ||
* @var Proxy | ||
*/ | ||
private $taxCalculation; | ||
|
||
/** | ||
* @var FireGentoConfig | ||
*/ | ||
private $config; | ||
|
||
/** | ||
* Constructor class | ||
* | ||
* @param ScopeConfigInterface $scopeConfig | ||
* @param Cart $cart | ||
* @param Session $customerSession | ||
* @param GroupRepository $groupRepository | ||
* @param FireGentoConfig $config | ||
*/ | ||
public function __construct( | ||
ScopeConfigInterface $scopeConfig, | ||
Cart $cart, | ||
Session $customerSession, | ||
GroupRepository $groupRepository, | ||
FireGentoConfig $config | ||
) { | ||
$this->scopeConfig = $scopeConfig; | ||
$this->cart = $cart; | ||
$this->customerSession = $customerSession; | ||
$this->groupRepository = $groupRepository; | ||
$this->config = $config; | ||
} | ||
|
||
/** | ||
* After plugin for \Magento\Tax\Model\Config::getShippingTaxClass | ||
* | ||
* @param Config $config | ||
* @param int $shippingTaxClass | ||
* @param null $store | ||
* | ||
* @return bool|int|mixed | ||
*/ | ||
public function afterGetShippingTaxClass(Config $config, int $shippingTaxClass, $store = null) | ||
{ | ||
$dynamicType = (int)$this->scopeConfig->getValue( | ||
$this->config->getDynamicShippingConfigPath(), | ||
ScopeInterface::SCOPE_STORE, | ||
$store | ||
); | ||
|
||
$quoteItems = $this->cart->getItems(); | ||
|
||
// If the default behaviour was configured or there are no products in cart, use default tax class id | ||
if ($dynamicType === FireGentoSource::DYNAMIC_TYPE_SHIPPING_TAX_DEFAULT || count($quoteItems) === 0) { | ||
return $shippingTaxClass; | ||
} | ||
|
||
$taxClassId = false; | ||
|
||
// Retrieve the highest product tax class | ||
if ($dynamicType === FireGentoSource::DYNAMIC_TYPE_HIGHEST_PRODUCT_TAX) { | ||
$taxClassId = $this->getHighestProductTaxClassId($quoteItems, $store); | ||
} | ||
|
||
// If no tax class id was found, use default one | ||
if (!$taxClassId) { | ||
$taxClassId = $shippingTaxClass; | ||
} | ||
|
||
return $taxClassId; | ||
} | ||
|
||
/** | ||
* Method for getting highest product tax class id | ||
* | ||
* @param array $quoteItems | ||
* @param null|string|bool|int|Store $store | ||
* | ||
* @return bool|mixed|null | ||
*/ | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please remove this line. |
||
private function getHighestProductTaxClassId($quoteItems, $store) | ||
{ | ||
$taxClassIds = []; | ||
$highestTaxRate = null; | ||
|
||
foreach ($quoteItems as $quoteItem) { | ||
|
||
/** @var $quoteItem Item */ | ||
if ($quoteItem->getParentItem()) { | ||
continue; | ||
} | ||
|
||
// Retrieve the tax percent | ||
$taxPercent = $quoteItem->getTaxPercent(); | ||
if (!$taxPercent) { | ||
$taxPercent = $this->getTaxPercent($quoteItem->getTaxClassId(), $store); | ||
} | ||
|
||
// Add the tax class | ||
if (($taxPercent) && !in_array($taxPercent, $taxClassIds)) { | ||
$taxClassIds[$taxPercent] = $quoteItem->getTaxClassId(); | ||
} | ||
} | ||
|
||
/** | ||
* Fetch the highest tax rate | ||
*/ | ||
ksort($taxClassIds); | ||
if (count($taxClassIds) > 0) { | ||
$highestTaxRate = array_pop($taxClassIds); | ||
} | ||
if (!$highestTaxRate || $highestTaxRate === null) { | ||
return false; | ||
} | ||
|
||
return $highestTaxRate; | ||
} | ||
|
||
/** | ||
* Method for getting tax prcentage | ||
* | ||
* @param int $productTaxClassId | ||
* @param null|string|bool|int|Store $store | ||
* | ||
* @return int | ||
* @throws \Magento\Framework\Exception\LocalizedException | ||
* @throws \Magento\Framework\Exception\NoSuchEntityException | ||
*/ | ||
private function getTaxPercent(int $productTaxClassId, $store): int | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The returnType of the rate is float, not int |
||
{ | ||
$groupId = $this->customerSession->getCustomerGroupId(); | ||
$group = $this->groupRepository->getById($groupId); | ||
$customerTaxClassId = $group->getTaxClassId(); | ||
|
||
$request = $this->taxCalculation->getRateRequest(null, null, $customerTaxClassId, $store); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not actually set in the constructor. |
||
$request->setData('product_class_id', $productTaxClassId); | ||
|
||
$taxPercent = $this->taxCalculation->getRate($request); | ||
if (!$taxPercent) { | ||
$taxPercent = 0; | ||
} | ||
|
||
return $taxPercent; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,10 +2,16 @@ | |
"name": "firegento/magesetup2", | ||
"description": "MageSetup provides the necessary configuration (system config, tax, agreements, etc. for a national market.", | ||
"require": { | ||
"php": "~7.2.0||~7.3.0", | ||
"magento/module-store": "*", | ||
"magento/module-backend": "*", | ||
"magento/framework": "*" | ||
"php": "~7.2.0|~7.3.0", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please fix the formatting. |
||
"magento/framework": "*", | ||
"magento/module-backend": "*", | ||
"magento/module-catalog": "*", | ||
"magento/module-checkout": "*", | ||
"magento/module-configurable-product": "*", | ||
"magento/module-customer": "*", | ||
"magento/module-quote": "*", | ||
"magento/module-store": "*", | ||
"magento/module-tax": "*" | ||
}, | ||
"type": "magento2-module", | ||
"license": "GPL-3.0", | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -55,3 +55,5 @@ SWIFT,SWIFT | |
"CMS Page for Shipping Info","CMS-Seite für Versandkosten" | ||
"Show ""incl. Shipping Cost"" instead of ""excl. Shipping Cost""","Zeige ""inkl. Versandkosten"" anstatt ""exkl. Versandkosten""" | ||
"Display Delivery Time on Product Listing","Lieferzeit auf Produktübersichtsseiten anzeigen" | ||
"No dynamic shipping tax calculation","Keine dynamische Versandsteuerberechnung" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please re-generate the English language file and then edit the German file. Hint:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems that you re-generated the English file. Great! Now IMHO, we need to update the German file accordingly (add the strings to the position similar to the EN file, not at the end of the file). |
||
"Use the highest product tax","Verwenden Sie die höchste Produktsteuer" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not think this adds much value. I think we should add a new method in
\FireGento\MageSetup\Model\System\Config
, which returns the actual configuration value of that option.