Skip to content

Commit

Permalink
refactor #12718 [POC] Add change of tax by address (arti0090)
Browse files Browse the repository at this point in the history
This PR was merged into the 1.11-dev branch.

Discussion
----------

| Q               | A
| --------------- | -----
| Branch?         | master 
| Bug fix?        | no
| New feature?    | no
| BC breaks?      | not sure
| Related tickets | related to #10946
| License         | MIT

![Zrzut ekranu 2021-06-18 o 08 33 40](https://user-images.githubusercontent.com/35863747/122517317-242e4b80-d010-11eb-83ea-0173209f8935.png)
![Zrzut ekranu 2021-06-18 o 08 33 50](https://user-images.githubusercontent.com/35863747/122517321-24c6e200-d010-11eb-9846-1143be126ab8.png)


Commits
-------

ff8d727 [POC] Add change of tax by address
b05e446 Extract service
273c608 Minor fixes
ae32ed2 Rebase and fixes
d9b61b7 Add notes about new param
  • Loading branch information
GSadee committed Jun 23, 2021
2 parents 89f3cee + d9b61b7 commit 4d1d948
Show file tree
Hide file tree
Showing 10 changed files with 167 additions and 38 deletions.
14 changes: 14 additions & 0 deletions UPGRADE-1.11.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,17 @@
}
]
```

1. Constructor of `Core/OrderProcessing/OrderTaxesProcessor.php` has been changed where new service implementing
`TaxationAddressResolverInterface` will become mandatory from Sylius version 2.0:

```diff
public function __construct(
ZoneProviderInterface $defaultTaxZoneProvider,
ZoneMatcherInterface $zoneMatcher,
PrioritizedServiceRegistryInterface $strategyRegistry,
+ ?TaxationAddressResolverInterface $taxationAddressResolver = null
) {
...
}
```
40 changes: 6 additions & 34 deletions docs/cookbook/taxation/customize-tax-by-address.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,41 +9,13 @@ as from 1st July 2021 the new taxation rules will be applied.

You can learn more about new EU taxation rules `here <https://ec.europa.eu/taxation_customs/business/vat/modernising-vat-cross-border-ecommerce_en>`_.

To change the way how the taxes are calculated; by billing or by shipping address, you need to override the service called
``OrderTaxesProcessor.php`` from ``Sylius/Component/Core/OrderProcessing``.

First let's copy code from original Processor to our service
from ``%kernel.project_dir%/vendor/sylius/sylius/src/Sylius/Component/Core/OrderProcessing/OrderTaxesProcessor.php`` to ``src/OrderProcessing/OrderTaxesProcessor.php``

Then register our new service:
To change the way how the taxes are calculated: by billing or by shipping address, you need to add a parameter to your config:

.. code-block:: yaml
# app/config/services.yaml
App\OrderProcessing\OrderTaxesProcessor:
arguments:
- '@sylius.provider.channel_based_default_zone_provider'
- '@sylius.zone_matcher'
- '@sylius.registry.tax_calculation_strategy'
tags:
- { name: sylius.order_processor, priority: 10 }
Now we need to change the method ``getTaxZone`` to be using the shipping address:

.. code-block:: php
//...
private function getTaxZone(OrderInterface $order): ?ZoneInterface
{
$shippingAddress = $order->getShippingAddress();
$zone = null;
if (null !== $shippingAddress) {
$zone = $this->zoneMatcher->match($shippingAddress, Scope::TAX);
}
return $zone ?: $this->defaultTaxZoneProvider->getZone($order);
}
//...
# app/config/packages/_sylius.yaml
sylius_core:
# resources definitions
shipping_address_based_taxation: true
And with this change, the way how taxes are calculated will be based on shipping address.
And with this change, the way how taxes are calculated is now based on shipping address.
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public function getConfigTreeBuilder(): TreeBuilder
->children()
->scalarNode('driver')->defaultValue(SyliusResourceBundle::DRIVER_DOCTRINE_ORM)->end()
->booleanNode('prepend_doctrine_migrations')->defaultTrue()->end()
->booleanNode('shipping_address_based_taxation')->defaultFalse()->end()
->end()
;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ public function load(array $configs, ContainerBuilder $container): void

$loader->load('services.xml');

$container->setParameter('sylius_core.taxation.shipping_address_based_taxation', $config['shipping_address_based_taxation']);

$env = $container->getParameter('kernel.environment');
if ('test' === $env || 'test_cached' === $env) {
$loader->load('test_services.xml');
Expand Down
4 changes: 4 additions & 0 deletions src/Sylius/Bundle/CoreBundle/Resources/config/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@
</service>
<service id="Sylius\Component\Shipping\Resolver\DefaultShippingMethodResolverInterface" alias="sylius.shipping_method_resolver.default" />

<service id="sylius.taxation_address_resolver" class="Sylius\Component\Core\Resolver\TaxationAddressResolver">
<argument>%sylius_core.taxation.shipping_address_based_taxation%</argument>
</service>

<service id="sylius.context.customer" class="Sylius\Bundle\CoreBundle\Context\CustomerContext">
<argument type="service" id="security.token_storage" />
<argument type="service" id="security.authorization_checker" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
<argument type="service" id="sylius.provider.channel_based_default_zone_provider" />
<argument type="service" id="sylius.zone_matcher" />
<argument type="service" id="sylius.registry.tax_calculation_strategy" />
<argument type="service" id="sylius.taxation_address_resolver" />
<tag name="sylius.order_processor" priority="10"/>
</service>

Expand Down
23 changes: 19 additions & 4 deletions src/Sylius/Component/Core/OrderProcessing/OrderTaxesProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@

use Sylius\Component\Addressing\Matcher\ZoneMatcherInterface;
use Sylius\Component\Addressing\Model\ZoneInterface;
use Sylius\Component\Core\Model\AddressInterface;
use Sylius\Component\Core\Model\AdjustmentInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Model\Scope;
use Sylius\Component\Core\Model\ShipmentInterface;
use Sylius\Component\Core\Provider\ZoneProviderInterface;
use Sylius\Component\Core\Resolver\TaxationAddressResolverInterface;
use Sylius\Component\Core\Taxation\Exception\UnsupportedTaxCalculationStrategyException;
use Sylius\Component\Core\Taxation\Strategy\TaxCalculationStrategyInterface;
use Sylius\Component\Order\Model\OrderInterface as BaseOrderInterface;
Expand All @@ -38,14 +40,22 @@ final class OrderTaxesProcessor implements OrderProcessorInterface
/** @var PrioritizedServiceRegistryInterface */
private $strategyRegistry;

/** @var TaxationAddressResolverInterface|null */
private $taxationAddressResolver;

public function __construct(
ZoneProviderInterface $defaultTaxZoneProvider,
ZoneMatcherInterface $zoneMatcher,
PrioritizedServiceRegistryInterface $strategyRegistry
PrioritizedServiceRegistryInterface $strategyRegistry,
?TaxationAddressResolverInterface $taxationAddressResolver = null
) {
$this->defaultTaxZoneProvider = $defaultTaxZoneProvider;
$this->zoneMatcher = $zoneMatcher;
$this->strategyRegistry = $strategyRegistry;
$this->taxationAddressResolver = $taxationAddressResolver;
if ($this->taxationAddressResolver === null) {
@trigger_error(sprintf('Not passing a $taxationAddressResolver to %s constructor is deprecated since Sylius 1.11 and will be removed in Sylius 2.0.', self::class), \E_USER_DEPRECATED);
}
}

public function process(BaseOrderInterface $order): void
Expand Down Expand Up @@ -78,11 +88,16 @@ public function process(BaseOrderInterface $order): void

private function getTaxZone(OrderInterface $order): ?ZoneInterface
{
$billingAddress = $order->getBillingAddress();
$taxationAddress = $order->getBillingAddress();

if ($this->taxationAddressResolver) {
$taxationAddress = $this->taxationAddressResolver->getTaxationAddressFromOrder($order);
}

$zone = null;

if (null !== $billingAddress) {
$zone = $this->zoneMatcher->match($billingAddress, Scope::TAX);
if (null !== $taxationAddress) {
$zone = $this->zoneMatcher->match($taxationAddress, Scope::TAX);
}

return $zone ?: $this->defaultTaxZoneProvider->getZone($order);
Expand Down
37 changes: 37 additions & 0 deletions src/Sylius/Component/Core/Resolver/TaxationAddressResolver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Sylius\Component\Core\Resolver;

use Sylius\Component\Core\Model\AddressInterface;
use Sylius\Component\Core\Model\OrderInterface;

final class TaxationAddressResolver Implements TaxationAddressResolverInterface
{
/** @var bool */
private $shippingAddressBasedTaxation;

public function __construct(bool $shippingAddressBasedTaxation)
{
$this->shippingAddressBasedTaxation = $shippingAddressBasedTaxation;
}

public function getTaxationAddressFromOrder(OrderInterface $order): ?AddressInterface
{
if ($this->shippingAddressBasedTaxation) {
return $order->getShippingAddress();
}

return $order->getBillingAddress();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Sylius\Component\Core\Resolver;

use Sylius\Component\Core\Model\AddressInterface;
use Sylius\Component\Core\Model\OrderInterface;

interface TaxationAddressResolverInterface
{
public function getTaxationAddressFromOrder(OrderInterface $order): ?AddressInterface;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace spec\Sylius\Component\Core\Resolver;

use PhpSpec\ObjectBehavior;
use Sylius\Component\Core\Model\AddressInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Resolver\TaxationAddressResolverInterface;

final class TaxationAddressResolverSpec extends ObjectBehavior
{
public function let(): void
{
$this->beConstructedWith(false);
}

public function it_implements_taxation_address_resolver_interface(): void
{
$this->shouldImplement(TaxationAddressResolverInterface::class);
}

public function it_returns_billing_address_from_order_if_it_has_default_parameter(
OrderInterface $order,
AddressInterface $billingAddress,
AddressInterface $shippingAddress
): void {
$order->setBillingAddress($billingAddress);
$order->setShippingAddress($shippingAddress);

$order->getBillingAddress()->willReturn($billingAddress);

$this->getTaxationAddressFromOrder($order)->shouldReturn($billingAddress);
$this->getTaxationAddressFromOrder($order)->shouldNotReturn($shippingAddress);
}

public function it_returns_shipping_address_from_order_if_parameter_is_true(
OrderInterface $order,
AddressInterface $billingAddress,
AddressInterface $shippingAddress
): void {
$this->beConstructedWith(true);
$order->setBillingAddress($billingAddress);
$order->setShippingAddress($shippingAddress);

$order->getShippingAddress()->willReturn($shippingAddress);

$this->getTaxationAddressFromOrder($order)->shouldReturn($shippingAddress);
$this->getTaxationAddressFromOrder($order)->shouldNotReturn($billingAddress);
}
}

0 comments on commit 4d1d948

Please sign in to comment.