Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
16 changes: 8 additions & 8 deletions spec/Creator/InvoiceCreatorSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ function it_creates_invoice_for_order(
): void {
$invoicePdf = new InvoicePdf('invoice.pdf', 'CONTENT');

$orderRepository->findOneByNumber('0000001')->willReturn($order);
$orderRepository->find(1)->willReturn($order);

$invoiceRepository->findOneByOrder($order)->willReturn(null);

Expand All @@ -73,7 +73,7 @@ function it_creates_invoice_for_order(

$invoiceRepository->add($invoice)->shouldBeCalled();

$this->__invoke('0000001', $invoiceDateTime);
$this->__invoke(1, $invoiceDateTime);
}

function it_creates_invoice_without_generating_pdf_file(
Expand All @@ -94,7 +94,7 @@ function it_creates_invoice_without_generating_pdf_file(
false
);

$orderRepository->findOneByNumber('0000001')->willReturn($order);
$orderRepository->find(1)->willReturn($order);

$invoiceRepository->findOneByOrder($order)->willReturn(null);

Expand All @@ -121,7 +121,7 @@ function it_removes_saved_invoice_file_if_database_update_fails(
): void {
$invoicePdf = new InvoicePdf('invoice.pdf', 'CONTENT');

$orderRepository->findOneByNumber('0000001')->willReturn($order);
$orderRepository->find(1)->willReturn($order);

$invoiceRepository->findOneByOrder($order)->willReturn(null);

Expand All @@ -134,7 +134,7 @@ function it_removes_saved_invoice_file_if_database_update_fails(
$invoiceRepository->add($invoice)->willThrow(ORMException::class);
$invoiceFileManager->remove($invoicePdf)->shouldBeCalled();

$this->__invoke('0000001', $invoiceDateTime);
$this->__invoke(1, $invoiceDateTime);
}

function it_throws_an_exception_when_invoice_was_already_created_for_given_order(
Expand All @@ -144,7 +144,7 @@ function it_throws_an_exception_when_invoice_was_already_created_for_given_order
OrderInterface $order,
InvoiceInterface $invoice
): void {
$orderRepository->findOneByNumber('0000001')->willReturn($order);
$orderRepository->find(1)->willReturn($order);
$invoiceRepository->findOneByOrder($order)->willReturn($invoice);

$invoiceDateTime = new \DateTimeImmutable('2019-02-25');
Expand All @@ -153,8 +153,8 @@ function it_throws_an_exception_when_invoice_was_already_created_for_given_order
$invoiceRepository->add(Argument::any())->shouldNotBeCalled();

$this
->shouldThrow(InvoiceAlreadyGenerated::withOrderNumber('0000001'))
->during('__invoke', ['0000001', $invoiceDateTime])
->shouldThrow(InvoiceAlreadyGenerated::withOrderId(1))
->during('__invoke', [1, $invoiceDateTime])
;
}
}
12 changes: 6 additions & 6 deletions spec/Creator/MassInvoicesCreatorSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,19 @@ function it_requests_invoices_creation_for_multiple_orders(
OrderInterface $secondOrder,
OrderInterface $thirdOrder
): void {
$firstOrder->getNumber()->willReturn('0000001');
$secondOrder->getNumber()->willReturn('0000002');
$thirdOrder->getNumber()->willReturn('0000003');
$firstOrder->getId()->willReturn(1);
$secondOrder->getId()->willReturn(2);
$thirdOrder->getId()->willReturn(3);

$firstInvoiceDateTime = new \DateTimeImmutable('2019-02-25');
$secondInvoiceDateTime = new \DateTimeImmutable('2019-02-25');
$thirdInvoiceDateTime = new \DateTimeImmutable('2019-02-25');

$dateTimeProvider->__invoke()->willReturn($firstInvoiceDateTime, $secondInvoiceDateTime, $thirdInvoiceDateTime);

$invoiceCreator->__invoke('0000001', $firstInvoiceDateTime)->shouldBeCalled();
$invoiceCreator->__invoke('0000002', $secondInvoiceDateTime)->shouldBeCalled();
$invoiceCreator->__invoke('0000003', $thirdInvoiceDateTime)->shouldBeCalled();
$invoiceCreator->__invoke(1, $firstInvoiceDateTime)->shouldBeCalled();
$invoiceCreator->__invoke(2, $secondInvoiceDateTime)->shouldBeCalled();
$invoiceCreator->__invoke(3, $thirdInvoiceDateTime)->shouldBeCalled();

$this->__invoke([$firstOrder->getWrappedObject(), $secondOrder->getWrappedObject(), $thirdOrder->getWrappedObject()]);
}
Expand Down
4 changes: 2 additions & 2 deletions spec/Event/OrderPlacedSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ function it_represents_an_immutable_fact_that_an_order_has_been_placed(): void
{
$date = new \DateTimeImmutable();

$this->beConstructedWith('000001', $date);
$this->beConstructedWith(1, $date);

$this->orderNumber()->shouldReturn('000001');
$this->orderId()->shouldReturn(1);
$this->date()->shouldBeLike($date);
}
}
4 changes: 2 additions & 2 deletions spec/EventListener/CreateInvoiceOnOrderPlacedListenerSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ function it_requests_invoice_creation(InvoiceCreatorInterface $invoiceCreator):
{
$issuedAt = new \DateTimeImmutable();

$invoiceCreator->__invoke('0000001', $issuedAt)->shouldBeCalled();
$invoiceCreator->__invoke(1, $issuedAt)->shouldBeCalled();

$this(new OrderPlaced('0000001', $issuedAt));
$this(new OrderPlaced(1, $issuedAt));
}
}
76 changes: 6 additions & 70 deletions spec/EventProducer/OrderPlacedProducerSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,14 @@ function it_dispatches_an_order_placed_event_for_persisted_order(
$dateTime = new \DateTime('2018-12-14');
$dateTimeProvider->__invoke()->willReturn($dateTime);

$order->getNumber()->willReturn('000666');
$order->getId()->willReturn(666);
$order->getCheckoutState()->willReturn(OrderCheckoutStates::STATE_COMPLETED);

$postPersistEvent = new LifecycleEventArgs($order->getWrappedObject(), $objectManager->getWrappedObject());
$orderPlacedEvent = new OrderPlaced('000666', $dateTime);
$orderPlacedEvent = new OrderPlaced(666, $dateTime);

$eventBus->dispatch($orderPlacedEvent)->shouldBeCalled()->willReturn(new Envelope($orderPlacedEvent));

$this->postPersist($postPersistEvent);
$this->__invoke($order);
}

function it_dispatches_an_order_placed_event_for_updated_order(
Expand All @@ -72,14 +71,13 @@ function it_dispatches_an_order_placed_event_for_updated_order(

$entityManager->getUnitOfWork()->willReturn($unitOfWork);

$order->getNumber()->willReturn('000666');
$order->getId()->willReturn(666);

$postUpdateEvent = new LifecycleEventArgs($order->getWrappedObject(), $entityManager->getWrappedObject());
$orderPlacedEvent = new OrderPlaced('000666', $dateTime);
$orderPlacedEvent = new OrderPlaced(666, $dateTime);

$eventBus->dispatch($orderPlacedEvent)->shouldBeCalled()->willReturn(new Envelope($orderPlacedEvent));

$this->postUpdate($postUpdateEvent);
$this->__invoke($order);
}

function it_does_nothing_after_persisting_if_event_entity_is_not_order(
Expand All @@ -89,8 +87,6 @@ function it_does_nothing_after_persisting_if_event_entity_is_not_order(
$event->getEntity()->willReturn('notAnOrder');

$eventBus->dispatch(Argument::any())->shouldNotBeCalled();

$this->postPersist($event);
}

function it_does_nothing_after_update_if_event_entity_is_not_order(
Expand All @@ -100,65 +96,5 @@ function it_does_nothing_after_update_if_event_entity_is_not_order(
$event->getEntity()->willReturn('notAnOrder');

$eventBus->dispatch(Argument::any())->shouldNotBeCalled();

$this->postUpdate($event);
}

function it_does_nothing_after_persisting_if_order_is_not_completed(
MessageBusInterface $eventBus,
LifecycleEventArgs $event,
OrderInterface $order
): void {
$event->getEntity()->willReturn($order);

$order->getCheckoutState()->willReturn(OrderCheckoutStates::STATE_CART);

$eventBus->dispatch(Argument::any())->shouldNotBeCalled();

$this->postPersist($event);
}

function it_does_nothing_after_update_if_order_checkout_state_has_not_changed(
MessageBusInterface $eventBus,
LifecycleEventArgs $event,
EntityManagerInterface $entityManager,
OrderInterface $order
): void {
$event->getEntity()->willReturn($order);

$event->getEntityManager()->willReturn($entityManager);

/** @var UnitOfWork|MockInterface $unitOfWork */
$unitOfWork = Mockery::mock(UnitOfWork::class);
$unitOfWork->shouldReceive('getEntityChangeSet')->withArgs([$order->getWrappedObject()])->andReturn([]);

$entityManager->getUnitOfWork()->willReturn($unitOfWork);

$eventBus->dispatch(Argument::any())->shouldNotBeCalled();

$this->postUpdate($event);
}

function it_does_nothing_after_update_if_order_checkout_state_has_not_changed_to_completed(
MessageBusInterface $eventBus,
LifecycleEventArgs $event,
EntityManagerInterface $entityManager,
OrderInterface $order
): void {
$event->getEntity()->willReturn($order);

$event->getEntityManager()->willReturn($entityManager);

/** @var UnitOfWork|MockInterface $unitOfWork */
$unitOfWork = Mockery::mock(UnitOfWork::class);
$unitOfWork->shouldReceive('getEntityChangeSet')->withArgs([$order->getWrappedObject()])->andReturn([
'checkoutState' => [OrderCheckoutStates::STATE_CART, OrderCheckoutStates::STATE_ADDRESSED],
]);

$entityManager->getUnitOfWork()->willReturn($unitOfWork);

$eventBus->dispatch(Argument::any())->shouldNotBeCalled();

$this->postUpdate($event);
}
}
6 changes: 3 additions & 3 deletions src/Creator/InvoiceCreator.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,16 @@ public function __construct(
) {
}

public function __invoke(string $orderNumber, \DateTimeInterface $dateTime): void
public function __invoke(int $orderId, \DateTimeInterface $dateTime): void
{
/** @var OrderInterface $order */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This phpdoc is missing the possibility of null

$order = $this->orderRepository->findOneByNumber($orderNumber);
$order = $this->orderRepository->find($orderId);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
$order = $this->orderRepository->find($orderId);
/** @var OrderInterface|null $order */
$order = $this->orderRepository->findOneBy(['number' => $orderNumber]);
Assert::notNull($order, sprintf('Order with number "%s" does not exist.', $orderNumber));

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried this before but it didn't work, I'll try again.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Behat test is maybe missing something, in my current projet I have to prepare my order doing this :

$stateMachine = $this->stateMachineFactory->get($order, OrderTransitions::GRAPH);

$stateMachine->apply(OrderTransitions::TRANSITION_CREATE);

save it to the database and complete the order (OrderCheckoutTransitions::TRANSITION_COMPLETE).


/** @var InvoiceInterface|null $invoice */
$invoice = $this->invoiceRepository->findOneByOrder($order);

if (null !== $invoice) {
throw InvoiceAlreadyGenerated::withOrderNumber($orderNumber);
throw InvoiceAlreadyGenerated::withOrderId($orderId);
}

$invoice = $this->invoiceGenerator->generateForOrder($order, $dateTime);
Expand Down
2 changes: 1 addition & 1 deletion src/Creator/InvoiceCreatorInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@

interface InvoiceCreatorInterface
{
public function __invoke(string $orderNumber, \DateTimeInterface $dateTime): void;
public function __invoke(int $orderId, \DateTimeInterface $dateTime): void;
}
2 changes: 1 addition & 1 deletion src/Creator/MassInvoicesCreator.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public function __invoke(array $orders): void
/** @var OrderInterface $order */
foreach ($orders as $order) {
try {
$this->invoiceCreator->__invoke($order->getNumber(), $this->dateTimeProvider->__invoke());
$this->invoiceCreator->__invoke($order->getId(), $this->dateTimeProvider->__invoke());
} catch (InvoiceAlreadyGenerated $exception) {
continue;
}
Expand Down
10 changes: 5 additions & 5 deletions src/Event/OrderPlaced.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,19 @@

final class OrderPlaced
{
private string $orderNumber;
private int $orderId;

private \DateTimeInterface $date;

public function __construct(string $orderNumber, \DateTimeInterface $date)
public function __construct(int $orderId, \DateTimeInterface $date)
{
$this->orderNumber = $orderNumber;
$this->orderId = $orderId;
$this->date = clone $date;
}

public function orderNumber(): string
public function orderId(): int
{
return $this->orderNumber;
return $this->orderId;
}

public function date(): \DateTimeInterface
Expand Down
2 changes: 1 addition & 1 deletion src/EventListener/CreateInvoiceOnOrderPlacedListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public function __construct(InvoiceCreatorInterface $invoiceCreator)
public function __invoke(OrderPlaced $event): void
{
try {
$this->invoiceCreator->__invoke($event->orderNumber(), $event->date());
$this->invoiceCreator->__invoke($event->orderId(), $event->date());
} catch (InvoiceAlreadyGenerated $exception) {
return;
}
Expand Down
43 changes: 2 additions & 41 deletions src/EventProducer/OrderPlacedProducer.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@

namespace Sylius\InvoicingPlugin\EventProducer;

use Doctrine\ORM\Event\LifecycleEventArgs;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\OrderCheckoutStates;
use Sylius\InvoicingPlugin\DateTimeProvider;
use Sylius\InvoicingPlugin\Event\OrderPlaced;
use Symfony\Component\Messenger\MessageBusInterface;
Expand All @@ -32,47 +30,10 @@ public function __construct(MessageBusInterface $eventBus, DateTimeProvider $dat
$this->dateTimeProvider = $dateTimeProvider;
}

public function postPersist(LifecycleEventArgs $event): void
{
$order = $event->getEntity();

if (
!$order instanceof OrderInterface ||
$order->getCheckoutState() !== OrderCheckoutStates::STATE_COMPLETED
) {
return;
}

$this->dispatchOrderPlacedEvent($order);
}

public function postUpdate(LifecycleEventArgs $event): void
{
$order = $event->getEntity();

if (!$order instanceof OrderInterface) {
return;
}

$entityManager = $event->getEntityManager();

$unitOfWork = $entityManager->getUnitOfWork();
$changeSet = $unitOfWork->getEntityChangeSet($order);

if (
!isset($changeSet['checkoutState']) ||
$changeSet['checkoutState'][1] !== OrderCheckoutStates::STATE_COMPLETED
) {
return;
}

$this->dispatchOrderPlacedEvent($order);
}

private function dispatchOrderPlacedEvent(OrderInterface $order): void
public function __invoke(OrderInterface $order): void
{
$this->eventBus->dispatch(
new OrderPlaced($order->getNumber(), $this->dateTimeProvider->__invoke())
new OrderPlaced($order->getId(), $this->dateTimeProvider->__invoke())
);
}
}
4 changes: 2 additions & 2 deletions src/Exception/InvoiceAlreadyGenerated.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@

final class InvoiceAlreadyGenerated extends \DomainException
{
public static function withOrderNumber(string $orderNumber): self
public static function withOrderId(int $orderId): self
{
return new self(sprintf('An invoice for order with number %s was already generated', $orderNumber));
return new self(sprintf('An invoice for order with id %s was already generated', $orderId));
}
}
7 changes: 7 additions & 0 deletions src/Resources/config/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ winzou_state_machine:
on: ['complete']
do: ['@sylius_invoicing_plugin.event_producer.order_payment_paid', '__invoke']
args: ['object']
sylius_order:
callbacks:
after:
sylius_invoicing_plugin_order_placed_producer:
on: ['create']
do: ['@sylius_invoicing_plugin.event_producer.order_placed', '__invoke']
args: ['object']
Copy link
Contributor

@Prometee Prometee Jun 30, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reading what the OrderPlacedProducer is doing :

  • onPostPersist : when order.checkout_state === 'completed' then dispatch creation of sylius_invoicing_plugin_invoice new item
  • onPostUpdate : when the new value of order.checkout_state === 'completed' then dispatch creation of sylius_invoicing_plugin_invoice new item

Don't you think the new callback should be set on the state machine named : sylius_order_checkout on ['complete'] ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll try this, and check if order_number is available at this time.
All behat tests passed for me... not for you ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The order number is assigned here : https://github.com/Sylius/Sylius/blob/master/src/Sylius/Bundle/CoreBundle/Resources/config/app/state_machine/sylius_order.yml#L26
If your callback don't have a priority it should be executed after the order number assigner.


sylius_grid:
templates:
Expand Down
2 changes: 0 additions & 2 deletions src/Resources/config/services/events.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@
<service id="sylius_invoicing_plugin.event_producer.order_placed" class="Sylius\InvoicingPlugin\EventProducer\OrderPlacedProducer">
<argument type="service" id="sylius.event_bus" />
<argument type="service" id="sylius_invoicing_plugin.date_time_provider" />
<tag name="doctrine.event_listener" event="postPersist" />
<tag name="doctrine.event_listener" event="postUpdate" />
</service>

<service id="sylius_invoicing_plugin.listener.order_payment_paid" class="Sylius\InvoicingPlugin\EventListener\OrderPaymentPaidListener">
Expand Down