Skip to content
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

Extract tax rate provider from line items converter #181

Merged
merged 2 commits into from
Jan 31, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 13 additions & 24 deletions spec/Converter/LineItemsConverterSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,20 @@

namespace spec\Sylius\RefundPlugin\Converter;

use Doctrine\Common\Collections\ArrayCollection;
use PhpSpec\ObjectBehavior;
use Sylius\Component\Core\Model\AdjustmentInterface;
use Sylius\Component\Core\Model\OrderItemInterface;
use Sylius\Component\Core\Model\OrderItemUnitInterface;
use Sylius\Component\Resource\Repository\RepositoryInterface;
use Sylius\RefundPlugin\Converter\LineItemsConverterInterface;
use Sylius\RefundPlugin\Entity\LineItem;
use Sylius\RefundPlugin\Model\OrderItemUnitRefund;
use Sylius\RefundPlugin\Provider\TaxRateProviderInterface;

final class LineItemsConverterSpec extends ObjectBehavior
{
function let(RepositoryInterface $orderItemUnitRepository): void
function let(RepositoryInterface $orderItemUnitRepository, TaxRateProviderInterface $taxRateProvider): void
{
$this->beConstructedWith($orderItemUnitRepository);
$this->beConstructedWith($orderItemUnitRepository, $taxRateProvider);
}

function it_implements_line_items_converter_interface(): void
Expand All @@ -28,9 +27,9 @@ function it_implements_line_items_converter_interface(): void

function it_converts_unit_refunds_to_line_items(
RepositoryInterface $orderItemUnitRepository,
TaxRateProviderInterface $taxRateProvider,
OrderItemUnitInterface $orderItemUnit,
OrderItemInterface $orderItem,
AdjustmentInterface $adjustment
OrderItemInterface $orderItem
): void {
$unitRefund = new OrderItemUnitRefund(1, 500);

Expand All @@ -39,13 +38,10 @@ function it_converts_unit_refunds_to_line_items(
$orderItemUnit->getOrderItem()->willReturn($orderItem);
$orderItemUnit->getTotal()->willReturn(1500);
$orderItemUnit->getTaxTotal()->willReturn(300);
$orderItemUnit
->getAdjustments(AdjustmentInterface::TAX_ADJUSTMENT)
->willReturn(new ArrayCollection([$adjustment->getWrappedObject()]))
;

$taxRateProvider->provide($orderItemUnit)->willReturn('25%');

$orderItem->getProductName()->willReturn('Portal gun');
$adjustment->getLabel()->willReturn('25%');

$this->convert([$unitRefund])->shouldBeLike([new LineItem(
'Portal gun',
Expand All @@ -61,12 +57,11 @@ function it_converts_unit_refunds_to_line_items(

function it_groups_the_same_line_items_during_converting(
RepositoryInterface $orderItemUnitRepository,
TaxRateProviderInterface $taxRateProvider,
OrderItemUnitInterface $firstOrderItemUnit,
OrderItemUnitInterface $secondOrderItemUnit,
OrderItemInterface $firstOrderItem,
OrderItemInterface $secondOrderItem,
AdjustmentInterface $firstAdjustment,
AdjustmentInterface $secondAdjustment
OrderItemInterface $secondOrderItem
): void {
$firstUnitRefund = new OrderItemUnitRefund(1, 500);
$secondUnitRefund = new OrderItemUnitRefund(2, 960);
Expand All @@ -77,26 +72,20 @@ function it_groups_the_same_line_items_during_converting(
$firstOrderItemUnit->getOrderItem()->willReturn($firstOrderItem);
$firstOrderItemUnit->getTotal()->willReturn(1500);
$firstOrderItemUnit->getTaxTotal()->willReturn(300);
$firstOrderItemUnit
->getAdjustments(AdjustmentInterface::TAX_ADJUSTMENT)
->willReturn(new ArrayCollection([$firstAdjustment->getWrappedObject()]))
;

$taxRateProvider->provide($firstOrderItemUnit)->willReturn('25%');

$firstOrderItem->getProductName()->willReturn('Portal gun');
$firstAdjustment->getLabel()->willReturn('25%');

$orderItemUnitRepository->find(2)->willReturn($secondOrderItemUnit);

$secondOrderItemUnit->getOrderItem()->willReturn($secondOrderItem);
$secondOrderItemUnit->getTotal()->willReturn(960);
$secondOrderItemUnit->getTaxTotal()->willReturn(160);
$secondOrderItemUnit
->getAdjustments(AdjustmentInterface::TAX_ADJUSTMENT)
->willReturn(new ArrayCollection([$secondAdjustment->getWrappedObject()]))
;

$taxRateProvider->provide($secondOrderItemUnit)->willReturn('20%');

$secondOrderItem->getProductName()->willReturn('Space gun');
$secondAdjustment->getLabel()->willReturn('20%');

$this->convert([$firstUnitRefund, $secondUnitRefund, $thirdUnitRefund])->shouldBeLike([
new LineItem(
Expand Down
57 changes: 57 additions & 0 deletions spec/Provider/LabelBasedTaxRateProviderSpec.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

declare(strict_types=1);

namespace spec\Sylius\RefundPlugin\Provider;

use Doctrine\Common\Collections\ArrayCollection;
use PhpSpec\ObjectBehavior;
use Sylius\Component\Core\Model\AdjustmentInterface;
use Sylius\Component\Core\Model\OrderItemUnitInterface;
use Sylius\RefundPlugin\Provider\TaxRateProviderInterface;

final class LabelBasedTaxRateProviderSpec extends ObjectBehavior
{
function it_implements_tax_rate_provider_interface(): void
{
$this->shouldImplement(TaxRateProviderInterface::class);
}

function it_provides_a_tax_rate_from_tax_adjustment_label(
OrderItemUnitInterface $orderItemUnit,
AdjustmentInterface $taxAdjustment
): void {
$orderItemUnit
->getAdjustments(AdjustmentInterface::TAX_ADJUSTMENT)
->willReturn(new ArrayCollection([$taxAdjustment->getWrappedObject()]))
;

$taxAdjustment->getLabel()->willReturn('VAT (20%)');

$this->provide($orderItemUnit)->shouldReturn('20%');
}

function it_provides_a_tax_adjustment_label_if_the_value_does_not_match_the_pattern(
OrderItemUnitInterface $orderItemUnit,
AdjustmentInterface $taxAdjustment
): void {
$orderItemUnit
->getAdjustments(AdjustmentInterface::TAX_ADJUSTMENT)
->willReturn(new ArrayCollection([$taxAdjustment->getWrappedObject()]))
;

$taxAdjustment->getLabel()->willReturn('20%');

$this->provide($orderItemUnit)->shouldReturn('20%');
}

function it_returns_null_if_there_is_no_tax_adjustment(OrderItemUnitInterface $orderItemUnit): void
{
$orderItemUnit
->getAdjustments(AdjustmentInterface::TAX_ADJUSTMENT)
->willReturn(new ArrayCollection([]))
;

$this->provide($orderItemUnit)->shouldReturn(null);
}
}
32 changes: 7 additions & 25 deletions src/Converter/LineItemsConverter.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,27 @@

namespace Sylius\RefundPlugin\Converter;

use Doctrine\Common\Collections\Collection;
use Sylius\Component\Core\Model\AdjustmentInterface;
use Sylius\Component\Core\Model\OrderItemInterface;
use Sylius\Component\Core\Model\OrderItemUnitInterface;
use Sylius\Component\Resource\Repository\RepositoryInterface;
use Sylius\RefundPlugin\Entity\LineItem;
use Sylius\RefundPlugin\Entity\LineItemInterface;
use Sylius\RefundPlugin\Model\UnitRefundInterface;
use Sylius\RefundPlugin\Provider\TaxRateProviderInterface;
use Webmozart\Assert\Assert;

final class LineItemsConverter implements LineItemsConverterInterface
{
/** @var RepositoryInterface */
private $orderItemUnitRepository;

public function __construct(RepositoryInterface $orderItemUnitRepository)
/** @var TaxRateProviderInterface */
private $taxRateProvider;

public function __construct(RepositoryInterface $orderItemUnitRepository, TaxRateProviderInterface $taxRateProvider)
{
$this->orderItemUnitRepository = $orderItemUnitRepository;
$this->taxRateProvider = $taxRateProvider;
}

public function convert(array $units): array
Expand Down Expand Up @@ -50,9 +53,6 @@ private function convertUnitRefundToLineItem(UnitRefundInterface $unitRefund): L
$taxAmount = (int) ($grossValue * $orderItemUnit->getTaxTotal() / $orderItemUnit->getTotal());
$netValue = $grossValue - $taxAmount;

/** @var Collection|AdjustmentInterface[] $taxAdjustments */
$taxAdjustments = $orderItemUnit->getAdjustments(AdjustmentInterface::TAX_ADJUSTMENT);

return new LineItem(
$orderItem->getProductName(),
1,
Expand All @@ -61,7 +61,7 @@ private function convertUnitRefundToLineItem(UnitRefundInterface $unitRefund): L
$netValue,
$grossValue,
$taxAmount,
$this->getTaxRate($taxAdjustments)
$this->taxRateProvider->provide($orderItemUnit)
);
}

Expand All @@ -85,22 +85,4 @@ private function addLineItem(LineItemInterface $newLineItem, array $lineItems):

return $lineItems;
}

/**
* @param Collection|AdjustmentInterface[] $taxAdjustments
*/
private function getTaxRate(Collection $taxAdjustments): ?string
{
if ($taxAdjustments->isEmpty()) {
return null;
}

$label = $taxAdjustments->first()->getLabel();

if (preg_match('/\((.*?)\)/', $label, $matches)) {
return end($matches); // returns percent tax rate from tax adjustment label
}

return $label;
}
}
30 changes: 30 additions & 0 deletions src/Provider/LabelBasedTaxRateProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

namespace Sylius\RefundPlugin\Provider;

use Doctrine\Common\Collections\Collection;
use Sylius\Component\Core\Model\AdjustmentInterface;
use Sylius\Component\Core\Model\OrderItemUnitInterface;

final class LabelBasedTaxRateProvider implements TaxRateProviderInterface
{
public function provide(OrderItemUnitInterface $orderItemUnit): ?string
{
/** @var Collection|AdjustmentInterface[] $taxAdjustments */
$taxAdjustments = $orderItemUnit->getAdjustments(AdjustmentInterface::TAX_ADJUSTMENT);

if ($taxAdjustments->isEmpty()) {
return null;
}

$label = $taxAdjustments->first()->getLabel();

if (preg_match('/\((.*?)\)/', $label, $matches)) {
return end($matches); // returns percent tax rate from tax adjustment label
}

return $label;
}
}
12 changes: 12 additions & 0 deletions src/Provider/TaxRateProviderInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace Sylius\RefundPlugin\Provider;

use Sylius\Component\Core\Model\OrderItemUnitInterface;

interface TaxRateProviderInterface
{
public function provide(OrderItemUnitInterface $orderItemUnit): ?string;
}
1 change: 1 addition & 0 deletions src/Resources/config/services/converter.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

<service id="Sylius\RefundPlugin\Converter\LineItemsConverterInterface" class="Sylius\RefundPlugin\Converter\LineItemsConverter">
<argument type="service" id="sylius.repository.order_item_unit" />
<argument type="service" id="Sylius\RefundPlugin\Provider\TaxRateProviderInterface" />
</service>

<service id="Sylius\RefundPlugin\Converter\ShipmentLineItemsConverterInterface" class="Sylius\RefundPlugin\Converter\ShipmentLineItemsConverter">
Expand Down
5 changes: 5 additions & 0 deletions src/Resources/config/services/provider.xml
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,10 @@
<argument type="service" id="sylius.repository.payment_method" />
<argument>%sylius_refund.supported_gateways%</argument>
</service>

<service
id="Sylius\RefundPlugin\Provider\TaxRateProviderInterface"
class="Sylius\RefundPlugin\Provider\LabelBasedTaxRateProvider"
/>
</services>
</container>