一些国内送货地址位于德国境内的客户仍然免税(例如北约或美国陆军)。 因为这被视为导出交货。
如何实现这一点?我找到的唯一解决方案是完全覆盖/替换 CartRuleLoader
到目前为止我所做的:我在客户中创建了一个自定义字段,商店编辑可以在其中将客户指定为免税(即使在德国境内)。
然后我覆盖了类TaxDetector
:
class TaxDetector extends \Shopware\Core\Checkout\Cart\Tax\TaxDetector
{
public function isNetDelivery(SalesChannelContext $context): bool
{
$customer = $context->getCustomer();
if ($customer && ($cf = $customer->getCustomFields()) && !empty($cf['mycustomfield']) && $cf['mycustomfield'] === 'nato') {
return true;
}
return parent::isNetDelivery($context);
}
public function getTaxState(SalesChannelContext $context): string
{
$customer = $context->getCustomer();
if ($customer && ($cf = $customer->getCustomFields()) && !empty($cf['mycustomfield']) && $cf['mycustomfield'] === 'nato') {
return CartPrice::TAX_STATE_FREE;
}
return parent::getTaxState($context);
}
}
问题在于,Shopware 6 在完成订单时会检查 CartRuleLoader
中税务状态的有效性。这里的测试是在我无法覆盖的私有(private)函数中完成的。
load -> validateTaxFree -> detectTaxType
关于如何解决这个更优雅和更进一步的问题,然后覆盖所有CartRuleLoader
,有什么建议吗?
最佳答案
这确实有点棘手。
当您查看方法 CartRuleLoader::detectTaxType
时,您可以找到以下几行:
$currency = $context->getCurrency();
$currencyTaxFreeAmount = $currency->getTaxFreeFrom();
$isReachedCurrencyTaxFreeAmount = $currencyTaxFreeAmount > 0 && $cartNetAmount >= $currencyTaxFreeAmount;
if ($isReachedCurrencyTaxFreeAmount) {
return CartPrice::TAX_STATE_FREE;
}
这可能有点棘手,但您可以通过将货币的免税金额设置为最低金额来“欺骗”Shopware 返回免税状态。
因此您可以装饰Shopware\Core\System\SalesChannel\Context\SalesChannelContextFactory
。
<service id="MyPlugin\Core\System\SalesChannel\Context\SalesChannelContextFactoryDecorator" decorates="Shopware\Core\System\SalesChannel\Context\SalesChannelContextFactory" decoration-priority="-999">
<argument type="service" id="MyPlugin\Core\System\SalesChannel\Context\SalesChannelContextFactoryDecorator.inner"/>
</service>
在装饰器中,您可以拥有自己的逻辑并设置免税金额:
<?php declare(strict_types=1);
namespace MyPlugin\Core\System\SalesChannel\Context;
use Shopware\Core\Checkout\Cart\Price\Struct\CartPrice;
use Shopware\Core\System\SalesChannel\Context\AbstractSalesChannelContextFactory;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
class SalesChannelContextFactoryDecorator extends AbstractSalesChannelContextFactory
{
private AbstractSalesChannelContextFactory $decorated;
public function __construct(
AbstractSalesChannelContextFactory $decorated,
) {
$this->decorated = $decorated;
}
public function getDecorated(): AbstractSalesChannelContextFactory
{
return $this->decorated;
}
public function create(string $token, string $salesChannelId, array $options = []): SalesChannelContext
{
$context = $this->getDecorated()->create($token, $salesChannelId, $options);
// ... your logic
if (...) {
$context->getCurrency()->setTaxFreeFrom(0.00001);
$context->setTaxState(CartPrice::TAX_STATE_FREE);
}
return $context;
}
}
编辑:看起来这还不够,因为有一个安全检查,它会检查之前的状态是否不是免税的,否则会重置它。
if ($previous !== CartPrice::TAX_STATE_FREE) {
$context->setTaxState($previous);
}
您可能还需要在装饰器中另外设置税收状态(更新了上面的示例)。免税金额将使其保持不变。
关于shopware6 - 商店软件 6 : Tax Free with domestic delivery in DE (TaxDecorator & CartRuleLoader),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73122989/