Skip to content

Commit

Permalink
refactor #306 Change order number to Order relation on Refund (Zales0…
Browse files Browse the repository at this point in the history
…123)

This PR was merged into the 1.0-dev branch.

Discussion
----------

Partially fixes #193

Time has shown, such a low coupling was not the best approach from the technical and DX point of view. We still have time to change it, before the stable release, so let's do it :) If in the future we decide it's reasonable to lose this coupling (and we can justify it and implement it properly), it would be easier to be done without major BC breaks 🖖 🚀 

Commits
-------

19b78a2 Change order number to order on Refund
14df4ff Change Refund mapping to handle order relation
f290126 Fixes in tests and services
119dee3 UPGRADE informations and final fixes
  • Loading branch information
GSadee authored Jun 9, 2021
2 parents 0cf5bff + 119dee3 commit 7c0fb07
Show file tree
Hide file tree
Showing 20 changed files with 180 additions and 38 deletions.
10 changes: 10 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
### UPGRADE FROM 1.0.0-RC.10 TO 1.0.0-RC.11

1. `orderNumber` field on `Sylius\RefundPlugin\Entity\Refund` has been removed and replaced with relation to `Order` entity.
1. `Sylius\RefundPlugin\Entity\RefundInterface::getOrderNumber` function is left due to easier and smoother upgrades,
but is also deprecated and will be removed in the `v1.0.0` release. Use `Sylius\RefundPlugin\Entity\RefundInterface::getOrder` instead.
1. `Sylius\RefundPlugin\Creator\RefundCreator` takes `\Sylius\Component\Core\Repository\OrderRepositoryInterface`
as the 3rd argument.
1. `Sylius\RefundPlugin\Provider\OrderRefundedTotalProviderInterface::invoke` takes `OrderInterface $order` as an argument
instead of `string $orderNumber`

### UPGRADE FROM 1.0.0-RC.9 TO 1.0.0-RC.10

1. Support for Sylius 1.8 has been dropped, upgrade your application to [Sylius 1.9](https://github.com/Sylius/Sylius/blob/master/UPGRADE-1.9.md)
Expand Down
6 changes: 2 additions & 4 deletions spec/Checker/OrderFullyRefundedTotalCheckerSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,8 @@ public function it_returns_false_if_order_refunded_total_is_lower_than_order_tot
OrderRefundedTotalProviderInterface $orderRefundedTotalProvider
): void {
$order->getTotal()->willReturn(1000);
$order->getNumber()->willReturn('0000001');

$orderRefundedTotalProvider->__invoke('0000001')->willReturn(500);
$orderRefundedTotalProvider->__invoke($order)->willReturn(500);

$this->isOrderFullyRefunded($order)->shouldReturn(false);
}
Expand All @@ -53,9 +52,8 @@ public function it_returns_true_if_order_refunded_total_is_equal_to_order_total(
OrderRefundedTotalProviderInterface $orderRefundedTotalProvider
): void {
$order->getTotal()->willReturn(1000);
$order->getNumber()->willReturn('0000001');

$orderRefundedTotalProvider->__invoke('0000001')->willReturn(1000);
$orderRefundedTotalProvider->__invoke($order)->willReturn(1000);

$this->isOrderFullyRefunded($order)->shouldReturn(true);
}
Expand Down
27 changes: 25 additions & 2 deletions spec/Creator/RefundCreatorSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

use Doctrine\Persistence\ObjectManager;
use PhpSpec\ObjectBehavior;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Repository\OrderRepositoryInterface;
use Sylius\RefundPlugin\Creator\RefundCreatorInterface;
use Sylius\RefundPlugin\Entity\RefundInterface;
use Sylius\RefundPlugin\Exception\UnitAlreadyRefunded;
Expand All @@ -27,11 +29,13 @@ final class RefundCreatorSpec extends ObjectBehavior
public function let(
RefundFactoryInterface $refundFactory,
RemainingTotalProviderInterface $remainingTotalProvider,
OrderRepositoryInterface $orderRepository,
ObjectManager $refundEntityManager
): void {
$this->beConstructedWith(
$refundFactory,
$remainingTotalProvider,
$orderRepository,
$refundEntityManager
);
}
Expand All @@ -44,26 +48,45 @@ public function it_implements_refund_creator_interface(): void
public function it_creates_refund_with_given_data_and_save_it_in_database(
RefundFactoryInterface $refundFactory,
RemainingTotalProviderInterface $remainingTotalProvider,
OrderRepositoryInterface $orderRepository,
ObjectManager $refundEntityManager,
OrderInterface $order,
RefundInterface $refund
): void {
$refundType = RefundType::shipment();

$orderRepository->findOneByNumber('000222')->willReturn($order);
$remainingTotalProvider->getTotalLeftToRefund(1, $refundType)->willReturn(1000);

$refundFactory->createWithData('000222', 1, 1000, RefundType::shipment())->willReturn($refund);
$refundFactory->createWithData($order, 1, 1000, RefundType::shipment())->willReturn($refund);

$refundEntityManager->persist($refund)->shouldBeCalled();
$refundEntityManager->flush()->shouldBeCalled();

$this('000222', 1, 1000, $refundType);
}

public function it_throws_an_exception_if_order_with_given_number_does_not_exist(
OrderRepositoryInterface $orderRepository
): void {
$refundType = RefundType::shipment();

$orderRepository->findOneByNumber('000222')->willReturn(null);

$this
->shouldThrow(\InvalidArgumentException::class)
->during('__invoke', ['000222', 1, 1000, $refundType])
;
}

public function it_throws_exception_if_unit_has_already_been_refunded(
RemainingTotalProviderInterface $remainingTotalProvider
OrderRepositoryInterface $orderRepository,
RemainingTotalProviderInterface $remainingTotalProvider,
OrderInterface $order
): void {
$refundType = RefundType::shipment();

$orderRepository->findOneByNumber('000222')->willReturn($order);
$remainingTotalProvider->getTotalLeftToRefund(1, $refundType)->willReturn(0);

$this
Expand Down
12 changes: 8 additions & 4 deletions spec/Entity/RefundSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@
namespace spec\Sylius\RefundPlugin\Entity;

use PhpSpec\ObjectBehavior;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\RefundPlugin\Entity\RefundInterface;
use Sylius\RefundPlugin\Model\RefundType;

final class RefundSpec extends ObjectBehavior
{
public function let(): void
public function let(OrderInterface $order): void
{
$this->beConstructedWith('000666', 1000, 3, RefundType::orderItemUnit());
$this->beConstructedWith($order, 1000, 3, RefundType::orderItemUnit());
}

public function it_implements_refund_interface(): void
Expand All @@ -34,9 +35,12 @@ public function it_has_no_id_by_default(): void
$this->getId()->shouldReturn(null);
}

public function it_has_order_number(): void
public function it_has_order(OrderInterface $order): void
{
$this->getOrderNumber()->shouldReturn('000666');
$order->getNumber()->willReturn('000555');

$this->getOrder()->shouldReturn($order);
$this->getOrderNumber()->shouldReturn('000555');
}

public function it_has_amount(): void
Expand Down
7 changes: 4 additions & 3 deletions spec/Factory/RefundFactorySpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
namespace spec\Sylius\RefundPlugin\Factory;

use PhpSpec\ObjectBehavior;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\RefundPlugin\Entity\Refund;
use Sylius\RefundPlugin\Factory\RefundFactoryInterface;
use Sylius\RefundPlugin\Model\RefundType;
Expand All @@ -25,11 +26,11 @@ public function it_implements_refund_factory_interface(): void
$this->shouldImplement(RefundFactoryInterface::class);
}

public function it_allows_to_create_refund_with_given_data(): void
public function it_allows_to_create_refund_with_given_data(OrderInterface $order): void
{
$this
->createWithData('0001', 1, 1000, RefundType::orderItemUnit())
->shouldBeLike(new Refund('0001', 1000, 1, RefundType::orderItemUnit()))
->createWithData($order, 1, 1000, RefundType::orderItemUnit())
->shouldBeLike(new Refund($order->getWrappedObject(), 1000, 1, RefundType::orderItemUnit()))
;
}
}
8 changes: 5 additions & 3 deletions spec/Provider/OrderRefundedTotalProviderSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
namespace spec\Sylius\RefundPlugin\Provider;

use PhpSpec\ObjectBehavior;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Resource\Repository\RepositoryInterface;
use Sylius\RefundPlugin\Entity\RefundInterface;
use Sylius\RefundPlugin\Provider\OrderRefundedTotalProviderInterface;
Expand All @@ -33,13 +34,14 @@ public function it_implements_order_refunded_total_provider_interface(): void
public function it_returns_refunded_total_of_order_with_given_number(
RepositoryInterface $refundRepository,
RefundInterface $firstRefund,
RefundInterface $secondRefund
RefundInterface $secondRefund,
OrderInterface $order
): void {
$refundRepository->findBy(['orderNumber' => '000222'])->willReturn([$firstRefund, $secondRefund]);
$refundRepository->findBy(['order' => $order])->willReturn([$firstRefund, $secondRefund]);

$firstRefund->getAmount()->willReturn(1000);
$secondRefund->getAmount()->willReturn(500);

$this->__invoke('000222')->shouldReturn(1500);
$this->__invoke($order)->shouldReturn(1500);
}
}
7 changes: 1 addition & 6 deletions src/Checker/OrderFullyRefundedTotalChecker.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

use Sylius\Component\Core\Model\OrderInterface;
use Sylius\RefundPlugin\Provider\OrderRefundedTotalProviderInterface;
use Webmozart\Assert\Assert;

final class OrderFullyRefundedTotalChecker implements OrderFullyRefundedTotalCheckerInterface
{
Expand All @@ -29,10 +28,6 @@ public function __construct(OrderRefundedTotalProviderInterface $orderRefundedTo

public function isOrderFullyRefunded(OrderInterface $order): bool
{
/** @var string|null $orderNumber */
$orderNumber = $order->getNumber();
Assert::notNull($orderNumber);

return $order->getTotal() === $this->orderRefundedTotalProvider->__invoke($orderNumber);
return $order->getTotal() === $this->orderRefundedTotalProvider->__invoke($order);
}
}
14 changes: 13 additions & 1 deletion src/Creator/RefundCreator.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@
namespace Sylius\RefundPlugin\Creator;

use Doctrine\Persistence\ObjectManager;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Repository\OrderRepositoryInterface;
use Sylius\RefundPlugin\Exception\UnitAlreadyRefunded;
use Sylius\RefundPlugin\Factory\RefundFactoryInterface;
use Sylius\RefundPlugin\Model\RefundType;
use Sylius\RefundPlugin\Provider\RemainingTotalProviderInterface;
use Webmozart\Assert\Assert;

final class RefundCreator implements RefundCreatorInterface
{
Expand All @@ -27,28 +30,37 @@ final class RefundCreator implements RefundCreatorInterface
/** @var RemainingTotalProviderInterface */
private $remainingTotalProvider;

/** @var OrderRepositoryInterface */
private $orderRepository;

/** @var ObjectManager */
private $refundManager;

public function __construct(
RefundFactoryInterface $refundFactory,
RemainingTotalProviderInterface $remainingTotalProvider,
OrderRepositoryInterface $orderRepository,
ObjectManager $refundManager
) {
$this->refundFactory = $refundFactory;
$this->remainingTotalProvider = $remainingTotalProvider;
$this->orderRepository = $orderRepository;
$this->refundManager = $refundManager;
}

public function __invoke(string $orderNumber, int $unitId, int $amount, RefundType $refundType): void
{
/** @var OrderInterface|null $order */
$order = $this->orderRepository->findOneByNumber($orderNumber);
Assert::notNull($order);

$remainingTotal = $this->remainingTotalProvider->getTotalLeftToRefund($unitId, $refundType);

if ($remainingTotal === 0) {
throw UnitAlreadyRefunded::withIdAndOrderNumber($unitId, $orderNumber);
}

$refund = $this->refundFactory->createWithData($orderNumber, $unitId, $amount, $refundType);
$refund = $this->refundFactory->createWithData($order, $unitId, $amount, $refundType);

$this->refundManager->persist($refund);
$this->refundManager->flush();
Expand Down
16 changes: 11 additions & 5 deletions src/Entity/Refund.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,16 @@

namespace Sylius\RefundPlugin\Entity;

use Sylius\Component\Core\Model\OrderInterface;
use Sylius\RefundPlugin\Model\RefundType;

class Refund implements RefundInterface
{
/** @var int|null */
protected $id;

/** @var string */
protected $orderNumber;
/** @var OrderInterface */
protected $order;

/** @var int */
protected $amount;
Expand All @@ -32,9 +33,9 @@ class Refund implements RefundInterface
/** @var RefundType */
protected $type;

public function __construct(string $orderNumber, int $amount, int $refundedUnitId, RefundType $type)
public function __construct(OrderInterface $order, int $amount, int $refundedUnitId, RefundType $type)
{
$this->orderNumber = $orderNumber;
$this->order = $order;
$this->amount = $amount;
$this->refundedUnitId = $refundedUnitId;
$this->type = $type;
Expand All @@ -45,9 +46,14 @@ public function getId(): ?int
return $this->id;
}

public function getOrder(): OrderInterface
{
return $this->order;
}

public function getOrderNumber(): string
{
return $this->orderNumber;
return (string) $this->order->getNumber();
}

public function getAmount(): int
Expand Down
4 changes: 4 additions & 0 deletions src/Entity/RefundInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,15 @@

namespace Sylius\RefundPlugin\Entity;

use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Resource\Model\ResourceInterface;
use Sylius\RefundPlugin\Model\RefundType;

interface RefundInterface extends ResourceInterface
{
public function getOrder(): OrderInterface;

/** @deprecated this function is deprecated and will be removed in v1.0.0. Use RefundInterface::getOrder() instead */
public function getOrderNumber(): string;

public function getAmount(): int;
Expand Down
5 changes: 3 additions & 2 deletions src/Factory/RefundFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

namespace Sylius\RefundPlugin\Factory;

use Sylius\Component\Core\Model\OrderInterface;
use Sylius\RefundPlugin\Entity\Refund;
use Sylius\RefundPlugin\Entity\RefundInterface;
use Sylius\RefundPlugin\Model\RefundType;
Expand All @@ -24,8 +25,8 @@ public function createNew(): RefundInterface
throw new \InvalidArgumentException('This object is not default constructable.');
}

public function createWithData(string $orderNumber, int $unitId, int $amount, RefundType $type): RefundInterface
public function createWithData(OrderInterface $order, int $unitId, int $amount, RefundType $type): RefundInterface
{
return new Refund($orderNumber, $amount, $unitId, $type);
return new Refund($order, $amount, $unitId, $type);
}
}
3 changes: 2 additions & 1 deletion src/Factory/RefundFactoryInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@

namespace Sylius\RefundPlugin\Factory;

use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Resource\Factory\FactoryInterface;
use Sylius\RefundPlugin\Entity\RefundInterface;
use Sylius\RefundPlugin\Model\RefundType;

interface RefundFactoryInterface extends FactoryInterface
{
public function createWithData(string $orderNumber, int $unitId, int $amount, RefundType $type): RefundInterface;
public function createWithData(OrderInterface $order, int $unitId, int $amount, RefundType $type): RefundInterface;
}
Loading

0 comments on commit 7c0fb07

Please sign in to comment.