shopware6 - 商店软件 6 : Tax Free with domestic delivery in DE (TaxDecorator & CartRuleLoader)

标签 shopware6

一些国内送货地址位于德国境内的客户仍然免税(例如北约或美国陆军)。 因为这被视为导出交货。

如何实现这一点?我找到的唯一解决方案是完全覆盖/替换 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/

相关文章:

Shopware6 应用程序使 services.cart 在 Custom Hook 中可用

symfony - ManyToOne 关联字段在商店软件 6 中不起作用

javascript - 在 Shopware 6 中覆盖现有的插件 JS

shopware - 当供应商太大时如何向商店添加插件?

twig - 如何获取媒体

plugins - 有没有办法为具有翻译的插件添加优先级?

Shopware:有条件地取消将产品添加到购物车

intl - 获取事件订阅者中当前的小数分隔符/将本地化字符串解析为 float

Shopware 6 自定义 npm 依赖项的路径无法在主题插件内解析

Shopware 6 - 自定义 CMS 元素 : How to get the data from two repositories into a custom CMS block?