diff --git a/spec/Converter/LineItem/OrderItemUnitLineItemsConverterSpec.php b/spec/Converter/LineItem/OrderItemUnitLineItemsConverterSpec.php index b05ea3e0..763b2069 100644 --- a/spec/Converter/LineItem/OrderItemUnitLineItemsConverterSpec.php +++ b/spec/Converter/LineItem/OrderItemUnitLineItemsConverterSpec.php @@ -19,15 +19,20 @@ use Sylius\Component\Resource\Repository\RepositoryInterface; use Sylius\RefundPlugin\Converter\LineItem\LineItemsConverterInterface; use Sylius\RefundPlugin\Entity\LineItem; +use Sylius\RefundPlugin\Entity\LineItemInterface; +use Sylius\RefundPlugin\Factory\LineItemFactoryInterface; use Sylius\RefundPlugin\Model\OrderItemUnitRefund; use Sylius\RefundPlugin\Model\ShipmentRefund; use Sylius\RefundPlugin\Provider\TaxRateProviderInterface; final class OrderItemUnitLineItemsConverterSpec extends ObjectBehavior { - function let(RepositoryInterface $orderItemUnitRepository, TaxRateProviderInterface $taxRateProvider): void - { - $this->beConstructedWith($orderItemUnitRepository, $taxRateProvider); + function let( + RepositoryInterface $orderItemUnitRepository, + TaxRateProviderInterface $taxRateProvider, + LineItemFactoryInterface $lineItemFactory, + ): void { + $this->beConstructedWith($orderItemUnitRepository, $taxRateProvider, $lineItemFactory); } function it_implements_line_items_converter_interface(): void @@ -38,8 +43,10 @@ function it_implements_line_items_converter_interface(): void function it_converts_unit_refunds_to_line_items( RepositoryInterface $orderItemUnitRepository, TaxRateProviderInterface $taxRateProvider, + LineItemFactoryInterface $lineItemFactory, OrderItemUnitInterface $orderItemUnit, OrderItemInterface $orderItem, + LineItemInterface $lineItem, ): void { $unitRefund = new OrderItemUnitRefund(1, 500); @@ -53,6 +60,40 @@ function it_converts_unit_refunds_to_line_items( $orderItem->getProductName()->willReturn('Portal gun'); + $lineItemFactory->createWithData( + 'Portal gun', + 1, + 400, + 500, + 400, + 500, + 100, + '25%', + )->willReturn($lineItem); + + $this->convert([$unitRefund])->shouldBeLike([$lineItem]); + } + + function it_converts_unit_refunds_to_line_items_without_using_factory( + RepositoryInterface $orderItemUnitRepository, + TaxRateProviderInterface $taxRateProvider, + OrderItemUnitInterface $orderItemUnit, + OrderItemInterface $orderItem, + ): void { + $this->beConstructedWith($orderItemUnitRepository, $taxRateProvider, null); + + $unitRefund = new OrderItemUnitRefund(1, 500); + + $orderItemUnitRepository->find(1)->willReturn($orderItemUnit); + + $orderItemUnit->getOrderItem()->willReturn($orderItem); + $orderItemUnit->getTotal()->willReturn(1500); + $orderItemUnit->getTaxTotal()->willReturn(300); + + $taxRateProvider->provide($orderItemUnit)->willReturn('25%'); + + $orderItem->getProductName()->willReturn('Portal gun'); + $this->convert([$unitRefund])->shouldBeLike([new LineItem( 'Portal gun', 1, @@ -65,18 +106,82 @@ function it_converts_unit_refunds_to_line_items( )]); } - function it_throws_an_error_if_one_of_units_is_not_order_item_unit_refund(): void - { - $unitRefund = new OrderItemUnitRefund(1, 500); - $shipmentRefund = new ShipmentRefund(3, 1500); + function it_groups_the_same_line_items_during_converting( + RepositoryInterface $orderItemUnitRepository, + TaxRateProviderInterface $taxRateProvider, + LineItemFactoryInterface $lineItemFactory, + OrderItemUnitInterface $firstOrderItemUnit, + OrderItemUnitInterface $secondOrderItemUnit, + OrderItemInterface $firstOrderItem, + OrderItemInterface $secondOrderItem, + LineItemInterface $firstLineItem, + LineItemInterface $secondLineItem, + LineItemInterface $thirdLineItem, + ): void { + $firstUnitRefund = new OrderItemUnitRefund(1, 500); + $secondUnitRefund = new OrderItemUnitRefund(2, 960); + $thirdUnitRefund = new OrderItemUnitRefund(2, 960); + + $orderItemUnitRepository->find(1)->willReturn($firstOrderItemUnit); + + $firstOrderItemUnit->getOrderItem()->willReturn($firstOrderItem); + $firstOrderItemUnit->getTotal()->willReturn(1500); + $firstOrderItemUnit->getTaxTotal()->willReturn(300); + + $taxRateProvider->provide($firstOrderItemUnit)->willReturn('25%'); + + $firstOrderItem->getProductName()->willReturn('Portal gun'); + + $orderItemUnitRepository->find(2)->willReturn($secondOrderItemUnit); + + $secondOrderItemUnit->getOrderItem()->willReturn($secondOrderItem); + $secondOrderItemUnit->getTotal()->willReturn(960); + $secondOrderItemUnit->getTaxTotal()->willReturn(160); + + $taxRateProvider->provide($secondOrderItemUnit)->willReturn('20%'); + + $secondOrderItem->getProductName()->willReturn('Space gun'); + + $lineItemFactory->createWithData( + 'Portal gun', + 1, + 400, + 500, + 400, + 500, + 100, + '25%', + )->willReturn($firstLineItem); + + $lineItemFactory->createWithData( + 'Space gun', + 1, + 800, + 960, + 800, + 960, + 160, + '20%', + )->willReturn($secondLineItem, $thirdLineItem); + + $firstLineItem + ->compare($secondLineItem) + ->willReturn(false); + $firstLineItem + ->compare($thirdLineItem) + ->willReturn(false); + + $secondLineItem + ->compare($thirdLineItem) + ->willReturn(true); + $secondLineItem->merge($thirdLineItem)->shouldBeCalled(); $this - ->shouldThrow(\InvalidArgumentException::class) - ->during('convert', [[$unitRefund, $shipmentRefund]]) - ; + ->convert([$firstUnitRefund, $secondUnitRefund, $thirdUnitRefund]) + ->shouldBeLike([$firstLineItem, $secondLineItem]); } - function it_groups_the_same_line_items_during_converting( + function it_groups_the_same_line_items_during_converting_without_using_factory( RepositoryInterface $orderItemUnitRepository, TaxRateProviderInterface $taxRateProvider, OrderItemUnitInterface $firstOrderItemUnit, @@ -84,6 +189,8 @@ function it_groups_the_same_line_items_during_converting( OrderItemInterface $firstOrderItem, OrderItemInterface $secondOrderItem, ): void { + $this->beConstructedWith($orderItemUnitRepository, $taxRateProvider, null); + $firstUnitRefund = new OrderItemUnitRefund(1, 500); $secondUnitRefund = new OrderItemUnitRefund(2, 960); $thirdUnitRefund = new OrderItemUnitRefund(2, 960); @@ -132,7 +239,17 @@ function it_groups_the_same_line_items_during_converting( ]); } - function it_throws_an_exception_if_there_is_no_shipping_adjustment_with_given_id( + function it_throws_an_error_if_one_of_units_is_not_order_item_unit_refund(): void + { + $unitRefund = new OrderItemUnitRefund(1, 500); + $shipmentRefund = new ShipmentRefund(3, 1500); + + $this + ->shouldThrow(\InvalidArgumentException::class) + ->during('convert', [[$unitRefund, $shipmentRefund]]); + } + + function it_throws_an_exception_if_there_is_no_order_item_unit_with_given_id( RepositoryInterface $orderItemUnitRepository, ): void { $unitRefund = new OrderItemUnitRefund(1, 500); @@ -141,11 +258,10 @@ function it_throws_an_exception_if_there_is_no_shipping_adjustment_with_given_id $this ->shouldThrow(\InvalidArgumentException::class) - ->during('convert', [[$unitRefund]]) - ; + ->during('convert', [[$unitRefund]]); } - function it_throws_an_exception_if_refund_amount_is_higher_than_shipping_amount( + function it_throws_an_exception_if_refund_amount_is_higher_than_order_item_unit_total( RepositoryInterface $orderItemUnitRepository, OrderItemUnitInterface $orderItemUnit, ): void { @@ -156,7 +272,6 @@ function it_throws_an_exception_if_refund_amount_is_higher_than_shipping_amount( $this ->shouldThrow(\InvalidArgumentException::class) - ->during('convert', [[$unitRefund]]) - ; + ->during('convert', [[$unitRefund]]); } } diff --git a/spec/Converter/LineItem/ShipmentLineItemsConverterSpec.php b/spec/Converter/LineItem/ShipmentLineItemsConverterSpec.php index 846d2811..9376a5a8 100644 --- a/spec/Converter/LineItem/ShipmentLineItemsConverterSpec.php +++ b/spec/Converter/LineItem/ShipmentLineItemsConverterSpec.php @@ -20,16 +20,21 @@ use Sylius\Component\Resource\Repository\RepositoryInterface; use Sylius\RefundPlugin\Converter\LineItem\LineItemsConverterInterface; use Sylius\RefundPlugin\Entity\LineItem; +use Sylius\RefundPlugin\Entity\LineItemInterface; use Sylius\RefundPlugin\Exception\MoreThanOneTaxAdjustment; +use Sylius\RefundPlugin\Factory\LineItemFactoryInterface; use Sylius\RefundPlugin\Model\OrderItemUnitRefund; use Sylius\RefundPlugin\Model\ShipmentRefund; use Sylius\RefundPlugin\Provider\TaxRateProviderInterface; final class ShipmentLineItemsConverterSpec extends ObjectBehavior { - function let(RepositoryInterface $adjustmentRepository, TaxRateProviderInterface $taxRateProvider): void - { - $this->beConstructedWith($adjustmentRepository, $taxRateProvider); + function let( + RepositoryInterface $adjustmentRepository, + TaxRateProviderInterface $taxRateProvider, + LineItemFactoryInterface $lineItemFactory, + ): void { + $this->beConstructedWith($adjustmentRepository, $taxRateProvider, $lineItemFactory); } function it_implements_line_items_converter_interface(): void @@ -38,12 +43,55 @@ function it_implements_line_items_converter_interface(): void } function it_converts_shipment_unit_refunds_to_line_items( + RepositoryInterface $adjustmentRepository, + TaxRateProviderInterface $taxRateProvider, + LineItemFactoryInterface $lineItemFactory, + AdjustmentInterface $shippingAdjustment, + AdjustmentInterface $taxAdjustment, + ShipmentInterface $shipment, + LineItemInterface $lineItem, + ): void { + $shipmentRefund = new ShipmentRefund(1, 575); + + $adjustmentRepository + ->findOneBy(['id' => 1, 'type' => AdjustmentInterface::SHIPPING_ADJUSTMENT]) + ->willReturn($shippingAdjustment) + ; + $shippingAdjustment->getLabel()->willReturn('Galaxy post'); + $shippingAdjustment->getShipment()->willReturn($shipment); + + $shipment->getAdjustmentsTotal()->willReturn(1150); + $shipment + ->getAdjustments(AdjustmentInterface::TAX_ADJUSTMENT) + ->willReturn(new ArrayCollection([$taxAdjustment->getWrappedObject()])) + ; + + $taxAdjustment->getAmount()->willReturn(150); + $taxRateProvider->provide($shipment)->willReturn('15%'); + + $lineItemFactory->createWithData( + 'Galaxy post', + 1, + 500, + 575, + 500, + 575, + 75, + '15%', + )->willReturn($lineItem); + + $this->convert([$shipmentRefund])->shouldBeLike([$lineItem]); + } + + function it_converts_shipment_unit_refunds_to_line_items_without_using_factory( RepositoryInterface $adjustmentRepository, TaxRateProviderInterface $taxRateProvider, AdjustmentInterface $shippingAdjustment, AdjustmentInterface $taxAdjustment, ShipmentInterface $shipment, ): void { + $this->beConstructedWith($adjustmentRepository, $taxRateProvider, null); + $shipmentRefund = new ShipmentRefund(1, 575); $adjustmentRepository diff --git a/src/Converter/LineItem/OrderItemUnitLineItemsConverter.php b/src/Converter/LineItem/OrderItemUnitLineItemsConverter.php index af958875..44813754 100644 --- a/src/Converter/LineItem/OrderItemUnitLineItemsConverter.php +++ b/src/Converter/LineItem/OrderItemUnitLineItemsConverter.php @@ -18,6 +18,7 @@ use Sylius\Component\Resource\Repository\RepositoryInterface; use Sylius\RefundPlugin\Entity\LineItem; use Sylius\RefundPlugin\Entity\LineItemInterface; +use Sylius\RefundPlugin\Factory\LineItemFactoryInterface; use Sylius\RefundPlugin\Model\OrderItemUnitRefund; use Sylius\RefundPlugin\Provider\TaxRateProviderInterface; use Webmozart\Assert\Assert; @@ -27,7 +28,16 @@ final class OrderItemUnitLineItemsConverter implements LineItemsConverterUnitRef public function __construct( private RepositoryInterface $orderItemUnitRepository, private TaxRateProviderInterface $taxRateProvider, + private ?LineItemFactoryInterface $lineItemFactory, ) { + if (null === $this->lineItemFactory) { + trigger_deprecation( + 'sylius/refund-plugin', + '1.5', + 'Not passing a line item factory to "%s" is deprecated and will be removed in 2.0.', + self::class, + ); + } } public function convert(array $units): array @@ -67,15 +77,28 @@ private function convertUnitRefundToLineItem(OrderItemUnitRefund $unitRefund): L $productName = $orderItem->getProductName(); Assert::notNull($productName); - return new LineItem( - $productName, - 1, - $netValue, - $grossValue, - $netValue, - $grossValue, - $taxAmount, - $this->taxRateProvider->provide($orderItemUnit), + if (null === $this->lineItemFactory) { + return new LineItem( + $productName, + 1, + $netValue, + $grossValue, + $netValue, + $grossValue, + $taxAmount, + $this->taxRateProvider->provide($orderItemUnit), + ); + } + + return $this->lineItemFactory->createWithData( + name: $productName, + quantity: 1, + unitNetPrice: $netValue, + unitGrossPrice: $grossValue, + netValue: $netValue, + grossValue: $grossValue, + taxAmount: $taxAmount, + taxRate: $this->taxRateProvider->provide($orderItemUnit), ); } diff --git a/src/Converter/LineItem/ShipmentLineItemsConverter.php b/src/Converter/LineItem/ShipmentLineItemsConverter.php index 5bed81e2..40246580 100644 --- a/src/Converter/LineItem/ShipmentLineItemsConverter.php +++ b/src/Converter/LineItem/ShipmentLineItemsConverter.php @@ -20,6 +20,7 @@ use Sylius\RefundPlugin\Entity\LineItem; use Sylius\RefundPlugin\Entity\LineItemInterface; use Sylius\RefundPlugin\Exception\MoreThanOneTaxAdjustment; +use Sylius\RefundPlugin\Factory\LineItemFactoryInterface; use Sylius\RefundPlugin\Model\ShipmentRefund; use Sylius\RefundPlugin\Provider\TaxRateProviderInterface; use Webmozart\Assert\Assert; @@ -29,7 +30,16 @@ final class ShipmentLineItemsConverter implements LineItemsConverterUnitRefundAw public function __construct( private RepositoryInterface $adjustmentRepository, private TaxRateProviderInterface $taxRateProvider, + private ?LineItemFactoryInterface $lineItemFactory, ) { + if (null === $this->lineItemFactory) { + trigger_deprecation( + 'sylius/refund-plugin', + '1.5', + 'Not passing a line item factory to "%s" is deprecated and will be removed in 2.0.', + self::class, + ); + } } public function convert(array $units): array @@ -77,15 +87,28 @@ private function convertShipmentRefundToLineItem(ShipmentRefund $shipmentRefund) $label = $shippingAdjustment->getLabel(); Assert::notNull($label); - return new LineItem( - $label, - 1, - $netValue, - $grossValue, - $netValue, - $grossValue, - $taxAmount, - $this->taxRateProvider->provide($shipment), + if (null === $this->lineItemFactory) { + return new LineItem( + $label, + 1, + $netValue, + $grossValue, + $netValue, + $grossValue, + $taxAmount, + $this->taxRateProvider->provide($shipment), + ); + } + + return $this->lineItemFactory->createWithData( + name: $label, + quantity: 1, + unitNetPrice: $netValue, + unitGrossPrice: $grossValue, + netValue: $netValue, + grossValue: $grossValue, + taxAmount: $taxAmount, + taxRate: $this->taxRateProvider->provide($shipment), ); } diff --git a/src/Resources/config/services/converters.xml b/src/Resources/config/services/converters.xml index aaa0d1af..665e149c 100644 --- a/src/Resources/config/services/converters.xml +++ b/src/Resources/config/services/converters.xml @@ -32,6 +32,7 @@ + @@ -41,6 +42,7 @@ +