[Catalog Promotions] Put catalog promotions into the processing state right after the delete request and keep this state until being removed

This commit is contained in:
Kevin Kaniaburka 2022-11-22 14:06:50 +01:00
parent d24c75f0e1
commit 958b8d73a9
No known key found for this signature in database
GPG key ID: 8DB4C54474F3FD72
19 changed files with 589 additions and 95 deletions

View file

@ -0,0 +1,38 @@
<?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\Bundle\CoreBundle\CatalogPromotion\Announcer;
use Sylius\Bundle\CoreBundle\CatalogPromotion\Command\DisableCatalogPromotion;
use Sylius\Bundle\CoreBundle\CatalogPromotion\Command\RemoveCatalogPromotion;
use Sylius\Bundle\CoreBundle\CatalogPromotion\Command\UpdateCatalogPromotionState;
use Sylius\Component\Core\Model\CatalogPromotionInterface;
use Symfony\Component\Messenger\MessageBusInterface;
final class CatalogPromotionRemovalAnnouncer implements CatalogPromotionRemovalAnnouncerInterface
{
public function __construct(private MessageBusInterface $commandBus)
{
}
public function dispatchCatalogPromotionRemoval(CatalogPromotionInterface $catalogPromotion): void
{
$this->commandBus->dispatch(new UpdateCatalogPromotionState($catalogPromotion->getCode()));
if ($catalogPromotion->isEnabled()) {
$this->commandBus->dispatch(new DisableCatalogPromotion($catalogPromotion->getCode()));
}
$this->commandBus->dispatch(new RemoveCatalogPromotion($catalogPromotion->getCode()));
}
}

View file

@ -0,0 +1,21 @@
<?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\Bundle\CoreBundle\CatalogPromotion\Announcer;
use Sylius\Component\Core\Model\CatalogPromotionInterface;
interface CatalogPromotionRemovalAnnouncerInterface
{
public function dispatchCatalogPromotionRemoval(CatalogPromotionInterface $catalogPromotion): void;
}

View file

@ -0,0 +1,21 @@
<?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\Bundle\CoreBundle\CatalogPromotion\Command;
final class DisableCatalogPromotion
{
public function __construct(public string $code)
{
}
}

View file

@ -0,0 +1,21 @@
<?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\Bundle\CoreBundle\CatalogPromotion\Command;
final class RemoveCatalogPromotion
{
public function __construct(public string $code)
{
}
}

View file

@ -13,9 +13,19 @@ declare(strict_types=1);
namespace Sylius\Bundle\CoreBundle\CatalogPromotion\Command;
/** @deprecated since 1.12 and will be removed in Sylius 2.0. Use {@see RemoveCatalogPromotion} instead. */
final class RemoveInactiveCatalogPromotion
{
public function __construct(public string $code)
{
trigger_deprecation(
'sylius/core-bundle',
'1.12',
sprintf(
'The "%s" class is deprecated since Sylius 1.12 and will be removed in 2.0. Use "%s" instead.',
self::class,
RemoveCatalogPromotion::class,
)
);
}
}

View file

@ -0,0 +1,41 @@
<?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\Bundle\CoreBundle\CatalogPromotion\CommandHandler;
use Sylius\Bundle\CoreBundle\CatalogPromotion\Command\DisableCatalogPromotion;
use Sylius\Bundle\CoreBundle\CatalogPromotion\Processor\AllProductVariantsCatalogPromotionsProcessorInterface;
use Sylius\Component\Core\Model\CatalogPromotionInterface;
use Sylius\Component\Promotion\Repository\CatalogPromotionRepositoryInterface;
final class DisableCatalogPromotionHandler
{
public function __construct(
private CatalogPromotionRepositoryInterface $catalogPromotionRepository,
private AllProductVariantsCatalogPromotionsProcessorInterface $allProductVariantsCatalogPromotionsProcessor,
) {
}
public function __invoke(DisableCatalogPromotion $command): void
{
/** @var CatalogPromotionInterface|null $catalogPromotion */
$catalogPromotion = $this->catalogPromotionRepository->findOneBy(['code' => $command->code]);
if (null === $catalogPromotion) {
return;
}
$catalogPromotion->disable();
$this->allProductVariantsCatalogPromotionsProcessor->process();
}
}

View file

@ -0,0 +1,51 @@
<?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\Bundle\CoreBundle\CatalogPromotion\CommandHandler;
use Doctrine\ORM\EntityManager;
use Sylius\Bundle\CoreBundle\CatalogPromotion\Command\RemoveCatalogPromotion;
use Sylius\Component\Core\Model\CatalogPromotionInterface;
use Sylius\Component\Promotion\Exception\InvalidCatalogPromotionStateException;
use Sylius\Component\Promotion\Model\CatalogPromotionStates;
use Sylius\Component\Promotion\Repository\CatalogPromotionRepositoryInterface;
final class RemoveCatalogPromotionHandler
{
public function __construct(
private CatalogPromotionRepositoryInterface $catalogPromotionRepository,
private EntityManager $entityManager,
) {
}
public function __invoke(RemoveCatalogPromotion $command): void
{
/** @var CatalogPromotionInterface|null $catalogPromotion */
$catalogPromotion = $this->catalogPromotionRepository->findOneBy(['code' => $command->code]);
if (null === $catalogPromotion) {
return;
}
if ($catalogPromotion->getState() !== CatalogPromotionStates::STATE_PROCESSING) {
throw new InvalidCatalogPromotionStateException(
sprintf(
'Catalog promotion with code "%s" cannot be removed as it is not in a processing state.',
$catalogPromotion->getCode(),
),
);
}
$this->entityManager->remove($catalogPromotion);
}
}

View file

@ -20,14 +20,25 @@ use Sylius\Component\Promotion\Exception\InvalidCatalogPromotionStateException;
use Sylius\Component\Promotion\Model\CatalogPromotionStates;
use Sylius\Component\Promotion\Repository\CatalogPromotionRepositoryInterface;
/** @deprecated since 1.12 and will be removed in Sylius 2.0. Use {@see RemoveCatalogPromotionHandler} instead. */
final class RemoveInactiveCatalogPromotionHandler
{
public function __construct(
private CatalogPromotionRepositoryInterface $catalogPromotionRepository,
private EntityManager $entityManager,
) {
trigger_deprecation(
'sylius/core-bundle',
'1.12',
sprintf(
'The "%s" class is deprecated since Sylius 1.12 and will be removed in 2.0. Use "%s" instead.',
self::class,
RemoveCatalogPromotionHandler::class,
)
);
}
/** @psalm-suppress DeprecatedClass */
public function __invoke(RemoveInactiveCatalogPromotion $command): void
{
/** @var CatalogPromotionInterface|null $catalogPromotion */

View file

@ -13,9 +13,9 @@ declare(strict_types=1);
namespace Sylius\Bundle\CoreBundle\CatalogPromotion\Processor;
use Sylius\Bundle\CoreBundle\CatalogPromotion\Command\RemoveInactiveCatalogPromotion;
use Sylius\Bundle\CoreBundle\CatalogPromotion\Announcer\CatalogPromotionRemovalAnnouncer;
use Sylius\Bundle\CoreBundle\CatalogPromotion\Announcer\CatalogPromotionRemovalAnnouncerInterface;
use Sylius\Component\Core\Model\CatalogPromotionInterface;
use Sylius\Component\Promotion\Event\CatalogPromotionEnded;
use Sylius\Component\Promotion\Exception\CatalogPromotionNotFoundException;
use Sylius\Component\Promotion\Exception\InvalidCatalogPromotionStateException;
use Sylius\Component\Promotion\Model\CatalogPromotionStates;
@ -26,9 +26,19 @@ final class CatalogPromotionRemovalProcessor implements CatalogPromotionRemovalP
{
public function __construct(
private CatalogPromotionRepositoryInterface $catalogPromotionRepository,
private MessageBusInterface $commandBus,
private MessageBusInterface $eventBus,
/** @var CatalogPromotionRemovalAnnouncerInterface $catalogPromotionRemovalAnnouncer */
private CatalogPromotionRemovalAnnouncerInterface|MessageBusInterface $catalogPromotionRemovalAnnouncer,
private ?MessageBusInterface $eventBus = null,
) {
if ($catalogPromotionRemovalAnnouncer instanceof MessageBusInterface) {
trigger_deprecation('sylius/core-bundle', '1.12', sprintf('Passing an instance of %s as second constructor argument for %s is deprecated as of Sylius 1.12 and will be removed in 2.0. Pass an instance of %s instead.', MessageBusInterface::class, self::class, CatalogPromotionRemovalAnnouncerInterface::class));
$this->catalogPromotionRemovalAnnouncer = new CatalogPromotionRemovalAnnouncer($catalogPromotionRemovalAnnouncer);
}
if (null !== $eventBus) {
trigger_deprecation('sylius/core-bundle', '1.12', sprintf('Passing third constructor argument for %s is deprecated as of Sylius 1.12 and will be removed in 2.0.', self::class));
}
}
public function removeCatalogPromotion(string $catalogPromotionCode): void
@ -36,20 +46,6 @@ final class CatalogPromotionRemovalProcessor implements CatalogPromotionRemovalP
/** @var CatalogPromotionInterface|null $catalogPromotion */
$catalogPromotion = $this->getCatalogPromotion($catalogPromotionCode);
if ($catalogPromotion->getState() === CatalogPromotionStates::STATE_INACTIVE) {
$this->announceInactiveCatalogPromotionRemoval($catalogPromotionCode);
return;
}
if ($catalogPromotion->getState() === CatalogPromotionStates::STATE_ACTIVE) {
$this->disableCatalogPromotion($catalogPromotion);
$this->announceCatalogPromotionEnd($catalogPromotionCode);
$this->announceInactiveCatalogPromotionRemoval($catalogPromotionCode);
return;
}
if ($catalogPromotion->getState() === CatalogPromotionStates::STATE_PROCESSING) {
throw new InvalidCatalogPromotionStateException(
sprintf(
@ -59,22 +55,11 @@ final class CatalogPromotionRemovalProcessor implements CatalogPromotionRemovalP
);
}
throw new \DomainException('Invalid catalog promotion state.');
}
if (!in_array($catalogPromotion->getState(), [CatalogPromotionStates::STATE_ACTIVE, CatalogPromotionStates::STATE_INACTIVE], true)) {
throw new \DomainException('Invalid catalog promotion state.');
}
private function announceCatalogPromotionEnd(string $catalogPromotionCode): void
{
$this->eventBus->dispatch(new CatalogPromotionEnded($catalogPromotionCode));
}
private function announceInactiveCatalogPromotionRemoval(string $catalogPromotionCode): void
{
$this->commandBus->dispatch(new RemoveInactiveCatalogPromotion($catalogPromotionCode));
}
private function disableCatalogPromotion(CatalogPromotionInterface $catalogPromotion): void
{
$catalogPromotion->setEnabled(false);
$this->catalogPromotionRemovalAnnouncer->dispatchCatalogPromotionRemoval($catalogPromotion);
}
private function getCatalogPromotion(string $catalogPromotionCode): CatalogPromotionInterface

View file

@ -19,8 +19,9 @@ framework:
queue_name: 'catalog_promotion_removal_failed'
reset_on_message: true
routing:
'Sylius\Bundle\CoreBundle\CatalogPromotion\Command\UpdateCatalogPromotionState': main
'Sylius\Bundle\CoreBundle\CatalogPromotion\Command\ApplyCatalogPromotionsOnVariants': main
'Sylius\Bundle\CoreBundle\CatalogPromotion\Command\DisableCatalogPromotion': main
'Sylius\Bundle\CoreBundle\CatalogPromotion\Command\RemoveCatalogPromotion': catalog_promotion_removal
'Sylius\Bundle\CoreBundle\CatalogPromotion\Command\RemoveInactiveCatalogPromotion': catalog_promotion_removal
'Sylius\Component\Promotion\Event\CatalogPromotionCreated': main
'Sylius\Component\Promotion\Event\CatalogPromotionEnded': main

View file

@ -32,6 +32,7 @@
<service id="Sylius\Bundle\CoreBundle\CatalogPromotion\DiscountApplicationCriteria\MinimumPriceCriteria">
<tag name="sylius.catalog_promotion.applicator_criteria" />
</service>
<service
id="Sylius\Bundle\CoreBundle\CatalogPromotion\Announcer\CatalogPromotionAnnouncerInterface"
class="Sylius\Bundle\CoreBundle\CatalogPromotion\Announcer\CatalogPromotionAnnouncer"
@ -41,6 +42,13 @@
<argument type="service" id="Sylius\Calendar\Provider\DateTimeProviderInterface" />
</service>
<service
id="Sylius\Bundle\CoreBundle\CatalogPromotion\Announcer\CatalogPromotionRemovalAnnouncerInterface"
class="Sylius\Bundle\CoreBundle\CatalogPromotion\Announcer\CatalogPromotionRemovalAnnouncer"
>
<argument type="service" id="sylius.command_bus" />
</service>
<service
id="Sylius\Bundle\CoreBundle\CatalogPromotion\CommandDispatcher\ApplyCatalogPromotionsOnVariantsCommandDispatcherInterface"
class="Sylius\Bundle\CoreBundle\CatalogPromotion\CommandDispatcher\BatchedApplyCatalogPromotionsOnVariantsCommandDispatcher"

View file

@ -23,6 +23,18 @@
<tag name="messenger.message_handler" bus="sylius.command_bus" />
</service>
<service id="Sylius\Bundle\CoreBundle\CatalogPromotion\CommandHandler\DisableCatalogPromotionHandler">
<argument type="service" id="sylius.repository.catalog_promotion" />
<argument type="service" id="Sylius\Bundle\CoreBundle\CatalogPromotion\Processor\AllProductVariantsCatalogPromotionsProcessorInterface"/>
<tag name="messenger.message_handler" bus="sylius.command_bus" />
</service>
<service id="Sylius\Bundle\CoreBundle\CatalogPromotion\CommandHandler\RemoveCatalogPromotionHandler">
<argument type="service" id="sylius.repository.catalog_promotion" />
<argument type="service" id="sylius.manager.catalog_promotion"/>
<tag name="messenger.message_handler" bus="sylius.command_bus" />
</service>
<service id="Sylius\Bundle\CoreBundle\CatalogPromotion\CommandHandler\RemoveInactiveCatalogPromotionHandler">
<argument type="service" id="sylius.repository.catalog_promotion" />
<argument type="service" id="sylius.manager.catalog_promotion"/>

View file

@ -55,8 +55,7 @@
class="Sylius\Bundle\CoreBundle\CatalogPromotion\Processor\CatalogPromotionRemovalProcessor"
>
<argument type="service" id="sylius.repository.catalog_promotion" />
<argument type="service" id="sylius.command_bus" />
<argument type="service" id="sylius.event_bus" />
<argument type="service" id="Sylius\Bundle\CoreBundle\CatalogPromotion\Announcer\CatalogPromotionRemovalAnnouncerInterface" />
</service>
</services>
</container>

View file

@ -0,0 +1,81 @@
<?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\Bundle\CoreBundle\CatalogPromotion\Announcer;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Sylius\Bundle\CoreBundle\Calculator\DelayStampCalculatorInterface;
use Sylius\Bundle\CoreBundle\CatalogPromotion\Announcer\CatalogPromotionAnnouncerInterface;
use Sylius\Bundle\CoreBundle\CatalogPromotion\Announcer\CatalogPromotionRemovalAnnouncerInterface;
use Sylius\Bundle\CoreBundle\CatalogPromotion\Command\DisableCatalogPromotion;
use Sylius\Bundle\CoreBundle\CatalogPromotion\Command\RemoveCatalogPromotion;
use Sylius\Bundle\CoreBundle\CatalogPromotion\Command\UpdateCatalogPromotionState;
use Sylius\Bundle\CoreBundle\CatalogPromotion\Processor\AllProductVariantsCatalogPromotionsProcessorInterface;
use Sylius\Calendar\Provider\DateTimeProviderInterface;
use Sylius\Component\Core\Model\CatalogPromotionInterface;
use Sylius\Component\Promotion\Event\CatalogPromotionCreated;
use Sylius\Component\Promotion\Event\CatalogPromotionEnded;
use Sylius\Component\Promotion\Event\CatalogPromotionUpdated;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\Messenger\Stamp\DelayStamp;
final class CatalogPromotionRemovalAnnouncerSpec extends ObjectBehavior
{
function let(MessageBusInterface $commandBus): void
{
$this->beConstructedWith($commandBus);
}
function it_implements_catalog_promotion_removal_announcer_interface(): void
{
$this->shouldImplement(CatalogPromotionRemovalAnnouncerInterface::class);
}
function it_dispatches_remove_catalog_promotion_command_on_enabled_catalog_promotion(
MessageBusInterface $commandBus,
CatalogPromotionInterface $catalogPromotion,
): void {
$catalogPromotion->getCode()->willReturn('CATALOG_PROMOTION_CODE');
$catalogPromotion->isEnabled()->willReturn(true);
$updateCatalogPromotionStateCommand = new UpdateCatalogPromotionState('CATALOG_PROMOTION_CODE');
$disableCatalogPromotionCommand = new DisableCatalogPromotion('CATALOG_PROMOTION_CODE');
$removeCatalogPromotionCommand = new RemoveCatalogPromotion('CATALOG_PROMOTION_CODE');
$commandBus->dispatch($updateCatalogPromotionStateCommand)->willReturn(new Envelope($updateCatalogPromotionStateCommand))->shouldBeCalled();
$commandBus->dispatch($disableCatalogPromotionCommand)->willReturn(new Envelope($disableCatalogPromotionCommand))->shouldBeCalled();
$commandBus->dispatch($removeCatalogPromotionCommand)->willReturn(new Envelope($removeCatalogPromotionCommand))->shouldBeCalled();
$this->dispatchCatalogPromotionRemoval($catalogPromotion);
}
function it_dispatches_remove_catalog_promotion_command_on_disabled_catalog_promotion(
MessageBusInterface $commandBus,
CatalogPromotionInterface $catalogPromotion,
): void {
$catalogPromotion->getCode()->willReturn('CATALOG_PROMOTION_CODE');
$catalogPromotion->isEnabled()->willReturn(false);
$updateCatalogPromotionStateCommand = new UpdateCatalogPromotionState('CATALOG_PROMOTION_CODE');
$disableCatalogPromotionCommand = new DisableCatalogPromotion('CATALOG_PROMOTION_CODE');
$removeCatalogPromotionCommand = new RemoveCatalogPromotion('CATALOG_PROMOTION_CODE');
$commandBus->dispatch($updateCatalogPromotionStateCommand)->willReturn(new Envelope($updateCatalogPromotionStateCommand))->shouldBeCalled();
$commandBus->dispatch($disableCatalogPromotionCommand)->shouldNotBeCalled();
$commandBus->dispatch($removeCatalogPromotionCommand)->willReturn(new Envelope($removeCatalogPromotionCommand))->shouldBeCalled();
$this->dispatchCatalogPromotionRemoval($catalogPromotion);
}
}

View file

@ -0,0 +1,62 @@
<?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\Bundle\CoreBundle\CatalogPromotion\CommandHandler;
use Doctrine\ORM\EntityManager;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Sylius\Bundle\CoreBundle\CatalogPromotion\Command\DisableCatalogPromotion;
use Sylius\Bundle\CoreBundle\CatalogPromotion\Command\RemoveCatalogPromotion;
use Sylius\Bundle\CoreBundle\CatalogPromotion\Command\RemoveInactiveCatalogPromotion;
use Sylius\Bundle\CoreBundle\CatalogPromotion\Processor\AllProductVariantsCatalogPromotionsProcessorInterface;
use Sylius\Component\Core\Model\CatalogPromotionInterface;
use Sylius\Component\Promotion\Exception\InvalidCatalogPromotionStateException;
use Sylius\Component\Promotion\Model\CatalogPromotionStates;
use Sylius\Component\Promotion\Repository\CatalogPromotionRepositoryInterface;
final class DisableCatalogPromotionHandlerSpec extends ObjectBehavior
{
public function let(
CatalogPromotionRepositoryInterface $catalogPromotionRepository,
AllProductVariantsCatalogPromotionsProcessorInterface $allProductVariantsCatalogPromotionsProcessor,
): void {
$this->beConstructedWith($catalogPromotionRepository, $allProductVariantsCatalogPromotionsProcessor);
}
public function it_disables_catalog_promotion(
CatalogPromotionRepositoryInterface $catalogPromotionRepository,
AllProductVariantsCatalogPromotionsProcessorInterface $allProductVariantsCatalogPromotionsProcessor,
CatalogPromotionInterface $catalogPromotion,
): void {
$catalogPromotionRepository->findOneBy(['code' => 'CATALOG_PROMOTION_CODE'])->willReturn($catalogPromotion);
$catalogPromotion->disable()->shouldBeCalled();
$allProductVariantsCatalogPromotionsProcessor->process()->shouldBeCalled();
$this(new DisableCatalogPromotion('CATALOG_PROMOTION_CODE'));
}
public function it_returns_if_there_is_no_catalog_promotion_with_given_code(
CatalogPromotionRepositoryInterface $catalogPromotionRepository,
AllProductVariantsCatalogPromotionsProcessorInterface $allProductVariantsCatalogPromotionsProcessor,
CatalogPromotionInterface $catalogPromotion,
): void {
$catalogPromotionRepository->findOneBy(['code' => 'CATALOG_PROMOTION_CODE'])->willReturn(null);
$catalogPromotion->disable()->shouldNotBeCalled();
$allProductVariantsCatalogPromotionsProcessor->process()->shouldNotBeCalled();
$this(new DisableCatalogPromotion('CATALOG_PROMOTION_CODE'));
}
}

View file

@ -0,0 +1,77 @@
<?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\Bundle\CoreBundle\CatalogPromotion\CommandHandler;
use Doctrine\ORM\EntityManager;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Sylius\Bundle\CoreBundle\CatalogPromotion\Command\RemoveCatalogPromotion;
use Sylius\Bundle\CoreBundle\CatalogPromotion\Command\RemoveInactiveCatalogPromotion;
use Sylius\Component\Core\Model\CatalogPromotionInterface;
use Sylius\Component\Promotion\Exception\InvalidCatalogPromotionStateException;
use Sylius\Component\Promotion\Model\CatalogPromotionStates;
use Sylius\Component\Promotion\Repository\CatalogPromotionRepositoryInterface;
final class RemoveCatalogPromotionHandlerSpec extends ObjectBehavior
{
public function let(
CatalogPromotionRepositoryInterface $catalogPromotionRepository,
EntityManager $entityManager,
): void {
$this->beConstructedWith($catalogPromotionRepository, $entityManager);
}
public function it_removes_catalog_promotion_being_processed(
CatalogPromotionRepositoryInterface $catalogPromotionRepository,
EntityManager $entityManager,
CatalogPromotionInterface $catalogPromotion,
): void {
$catalogPromotionRepository->findOneBy(['code' => 'CATALOG_PROMOTION_CODE'])->willReturn($catalogPromotion);
$catalogPromotion->getState()->willReturn(CatalogPromotionStates::STATE_PROCESSING);
$this(new RemoveCatalogPromotion('CATALOG_PROMOTION_CODE'));
$entityManager->remove($catalogPromotion)->shouldBeCalled();
}
public function it_throws_an_exception_if_catalog_promotion_is_not_in_a_processing_state(
CatalogPromotionRepositoryInterface $catalogPromotionRepository,
EntityManager $entityManager,
CatalogPromotionInterface $catalogPromotion,
): void {
$catalogPromotionRepository->findOneBy(['code' => 'CATALOG_PROMOTION_CODE'])->willReturn($catalogPromotion);
$catalogPromotion->getState()->willReturn(CatalogPromotionStates::STATE_ACTIVE);
$catalogPromotion->getCode()->willReturn('CATALOG_PROMOTION_CODE');
$entityManager->remove(Argument::any())->shouldNotBeCalled();
$this
->shouldThrow(InvalidCatalogPromotionStateException::class)
->during('__invoke', [new RemoveCatalogPromotion('CATALOG_PROMOTION_CODE')])
;
}
public function it_returns_if_there_is_no_catalog_promotion_with_given_code(
CatalogPromotionRepositoryInterface $catalogPromotionRepository,
EntityManager $entityManager,
): void {
$catalogPromotionRepository->findOneBy(['code' => 'CATALOG_PROMOTION_CODE'])->willReturn(null);
$entityManager->remove(Argument::any())->shouldNotBeCalled();
$this(new RemoveCatalogPromotion('CATALOG_PROMOTION_CODE'));
}
}

View file

@ -15,12 +15,16 @@ namespace spec\Sylius\Bundle\CoreBundle\CatalogPromotion\Processor;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Sylius\Bundle\CoreBundle\CatalogPromotion\Announcer\CatalogPromotionRemovalAnnouncerInterface;
use Sylius\Bundle\CoreBundle\CatalogPromotion\Command\RemoveInactiveCatalogPromotion;
use Sylius\Bundle\CoreBundle\CatalogPromotion\Processor\CatalogPromotionRemovalProcessor;
use Sylius\Bundle\CoreBundle\CatalogPromotion\Processor\CatalogPromotionRemovalProcessorInterface;
use Sylius\Component\Core\Model\CatalogPromotionInterface;
use Sylius\Component\Promotion\Event\CatalogPromotionEnded;
use Sylius\Component\Promotion\Event\CatalogPromotionUpdated;
use Sylius\Component\Promotion\Exception\CatalogPromotionNotFoundException;
use Sylius\Component\Promotion\Exception\InvalidCatalogPromotionStateException;
use Sylius\Component\Promotion\Model\CatalogPromotionStates;
use Sylius\Component\Promotion\Repository\CatalogPromotionRepositoryInterface;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\MessageBusInterface;
@ -29,71 +33,51 @@ final class CatalogPromotionRemovalProcessorSpec extends ObjectBehavior
{
public function let(
CatalogPromotionRepositoryInterface $catalogPromotionRepository,
MessageBusInterface $commandBus,
MessageBusInterface $eventBus,
CatalogPromotionRemovalAnnouncerInterface $catalogPromotionRemovalAnnouncer,
): void {
$this->beConstructedWith($catalogPromotionRepository, $commandBus, $eventBus);
$this->beConstructedWith($catalogPromotionRepository, $catalogPromotionRemovalAnnouncer);
}
public function it_removes_an_active_catalog_promotion_by_disabling_it_and_dispatching_catalog_promotion_ended_event_and_remove_inactive_catalog_promotion_command(
public function it_implements_catalog_promotion_removal_processor_interface(): void
{
$this->shouldImplement(CatalogPromotionRemovalProcessorInterface::class);
}
public function it_removes_an_active_catalog_promotion(
CatalogPromotionRepositoryInterface $catalogPromotionRepository,
MessageBusInterface $commandBus,
MessageBusInterface $eventBus,
CatalogPromotionRemovalAnnouncerInterface $catalogPromotionRemovalAnnouncer,
CatalogPromotionInterface $catalogPromotion,
): void {
$catalogPromotionRepository->findOneBy(['code' => 'CATALOG_PROMOTION_CODE'])->willReturn($catalogPromotion);
$catalogPromotion->getState()->willReturn(CatalogPromotionStates::STATE_ACTIVE);
$catalogPromotion->getState()->willReturn('active');
$catalogPromotion->setEnabled(false)->shouldBeCalled();
$event = new CatalogPromotionEnded('CATALOG_PROMOTION_CODE');
$command = new RemoveInactiveCatalogPromotion('CATALOG_PROMOTION_CODE');
$eventBus->dispatch($event)->willReturn(new Envelope($event));
$commandBus->dispatch($command)->willReturn(new Envelope($command));
$catalogPromotionRemovalAnnouncer->dispatchCatalogPromotionRemoval($catalogPromotion)->shouldBeCalled();
$this->removeCatalogPromotion('CATALOG_PROMOTION_CODE');
}
public function it_removes_an_inactive_catalog_promotion_by_dispatching_remove_inactive_catalog_promotion_command_without_recalculating_the_catalog(
public function it_removes_an_inactive_catalog_promotion(
CatalogPromotionRepositoryInterface $catalogPromotionRepository,
MessageBusInterface $commandBus,
MessageBusInterface $eventBus,
CatalogPromotionRemovalAnnouncerInterface $catalogPromotionRemovalAnnouncer,
CatalogPromotionInterface $catalogPromotion,
): void {
$catalogPromotionRepository->findOneBy(['code' => 'CATALOG_PROMOTION_CODE'])->willReturn($catalogPromotion);
$catalogPromotion->getState()->willReturn(CatalogPromotionStates::STATE_INACTIVE);
$catalogPromotion->getState()->willReturn('inactive');
$catalogPromotion->setEnabled(Argument::any())->shouldNotBeCalled();
$event = new CatalogPromotionEnded('CATALOG_PROMOTION_CODE');
$command = new RemoveInactiveCatalogPromotion('CATALOG_PROMOTION_CODE');
$eventBus->dispatch($event)->shouldNotBeCalled();
$commandBus->dispatch($command)->willReturn(new Envelope($command));
$catalogPromotionRemovalAnnouncer->dispatchCatalogPromotionRemoval($catalogPromotion)->shouldBeCalled();
$this->removeCatalogPromotion('CATALOG_PROMOTION_CODE');
}
public function it_does_not_dispatch_any_events_and_commands_if_catalog_promotion_from_command_does_not_exist(
public function it_does_not_dispatch_catalog_promotion_removal_if_catalog_promotion_from_command_does_not_exist(
CatalogPromotionRepositoryInterface $catalogPromotionRepository,
MessageBusInterface $commandBus,
MessageBusInterface $eventBus,
CatalogPromotionRemovalAnnouncerInterface $catalogPromotionRemovalAnnouncer,
CatalogPromotionInterface $catalogPromotion,
): void {
$catalogPromotionRepository->findOneBy(['code' => 'CATALOG_PROMOTION_CODE'])->willReturn(null);
$catalogPromotion->getState()->shouldNotBeCalled();
$catalogPromotion->setEnabled(Argument::any())->shouldNotBeCalled();
$event = new CatalogPromotionUpdated('CATALOG_PROMOTION_CODE');
$command = new RemoveInactiveCatalogPromotion('CATALOG_PROMOTION_CODE');
$eventBus->dispatch($event)->shouldNotBeCalled();
$commandBus->dispatch($command)->shouldNotBeCalled();
$catalogPromotionRemovalAnnouncer->dispatchCatalogPromotionRemoval(Argument::any())->shouldNotBeCalled();
$this
->shouldThrow(CatalogPromotionNotFoundException::class)
@ -103,21 +87,13 @@ final class CatalogPromotionRemovalProcessorSpec extends ObjectBehavior
public function it_throws_an_exception_if_catalog_promotion_is_being_processed(
CatalogPromotionRepositoryInterface $catalogPromotionRepository,
MessageBusInterface $commandBus,
MessageBusInterface $eventBus,
CatalogPromotionRemovalAnnouncerInterface $catalogPromotionRemovalAnnouncer,
CatalogPromotionInterface $catalogPromotion,
): void {
$catalogPromotionRepository->findOneBy(['code' => 'CATALOG_PROMOTION_CODE'])->willReturn($catalogPromotion);
$catalogPromotion->getState()->willReturn(CatalogPromotionStates::STATE_PROCESSING);
$catalogPromotion->getState()->willReturn('processing');
$catalogPromotion->setEnabled(Argument::any())->shouldNotBeCalled();
$event = new CatalogPromotionEnded('CATALOG_PROMOTION_CODE');
$command = new RemoveInactiveCatalogPromotion('CATALOG_PROMOTION_CODE');
$eventBus->dispatch($event)->shouldNotBeCalled();
$commandBus->dispatch($command)->shouldNotBeCalled();
$catalogPromotionRemovalAnnouncer->dispatchCatalogPromotionRemoval(Argument::any())->shouldNotBeCalled();
$this
->shouldThrow(InvalidCatalogPromotionStateException::class)
@ -127,25 +103,36 @@ final class CatalogPromotionRemovalProcessorSpec extends ObjectBehavior
public function it_throws_an_exception_if_catalog_promotion_state_is_out_of_invalid_one(
CatalogPromotionRepositoryInterface $catalogPromotionRepository,
MessageBusInterface $commandBus,
MessageBusInterface $eventBus,
CatalogPromotionRemovalAnnouncerInterface $catalogPromotionRemovalAnnouncer,
CatalogPromotionInterface $catalogPromotion,
): void {
$catalogPromotionRepository->findOneBy(['code' => 'CATALOG_PROMOTION_CODE'])->willReturn($catalogPromotion);
$catalogPromotion->getState()->willReturn('invalid_state');
$catalogPromotion->setEnabled(Argument::any())->shouldNotBeCalled();
$event = new CatalogPromotionEnded('CATALOG_PROMOTION_CODE');
$command = new RemoveInactiveCatalogPromotion('CATALOG_PROMOTION_CODE');
$eventBus->dispatch($event)->shouldNotBeCalled();
$commandBus->dispatch($command)->shouldNotBeCalled();
$catalogPromotionRemovalAnnouncer->dispatchCatalogPromotionRemoval(Argument::any())->shouldNotBeCalled();
$this
->shouldThrow(\DomainException::class)
->during('removeCatalogPromotion', ['CATALOG_PROMOTION_CODE'])
;
}
public function it_deprecates_passing_message_busses(
CatalogPromotionRepositoryInterface $catalogPromotionRepository,
MessageBusInterface $eventBus,
MessageBusInterface $commandBus,
): void
{
$this->beConstructedWith($catalogPromotionRepository, $eventBus, $commandBus);
$this
->shouldTrigger(\E_USER_DEPRECATED, sprintf('Passing an instance of %s as second constructor argument for %s is deprecated as of Sylius 1.12 and will be removed in 2.0. Pass an instance of %s instead.', MessageBusInterface::class, CatalogPromotionRemovalProcessor::class, CatalogPromotionRemovalAnnouncerInterface::class))
->duringInstantiation()
;
$this
->shouldTrigger(\E_USER_DEPRECATED, sprintf('Passing third constructor argument for %s is deprecated as of Sylius 1.12 and will be removed in 2.0.', CatalogPromotionRemovalProcessor::class))
->duringInstantiation()
;
}
}

View file

@ -4,3 +4,8 @@ Sylius\Component\Core\Model\CatalogPromotion:
name: Sale1
enabled: true
state: inactive
sale_2:
code: sale2
name: Sale2
enabled: true
state: active

View file

@ -0,0 +1,63 @@
<?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\Tests\Functional;
use Fidry\AliceDataFixtures\LoaderInterface;
use Fidry\AliceDataFixtures\Persistence\PurgeMode;
use Sylius\Bundle\CoreBundle\CatalogPromotion\Announcer\CatalogPromotionRemovalAnnouncerInterface;
use Sylius\Component\Core\Model\CatalogPromotion;
use Sylius\Component\Core\Model\CatalogPromotionInterface;
final class CatalogPromotionRemovalAnnouncerTest extends AbstractWebTestCase
{
/** @test */
public function it_puts_catalog_promotion_into_processing_state(): void
{
$this->createClient();
$catalogPromotion = $this->getCatalogPromotion();
/** @var CatalogPromotionRemovalAnnouncerInterface $catalogPromotionRemovalAnnouncer */
$catalogPromotionRemovalAnnouncer = self::$kernel->getContainer()->get('Sylius\Bundle\CoreBundle\CatalogPromotion\Announcer\CatalogPromotionRemovalAnnouncerInterface');
$catalogPromotionRemovalAnnouncer->dispatchCatalogPromotionRemoval($catalogPromotion);
$this->assertSame('processing', $catalogPromotion->getState());
}
/** @test */
public function it_removes_active_catalog_promotion_when_processing_has_been_finished(): void
{
$this->createClient();
$catalogPromotion = $this->getCatalogPromotion();
/** @var CatalogPromotionRemovalAnnouncerInterface $catalogPromotionRemovalAnnouncer */
$catalogPromotionRemovalAnnouncer = self::$kernel->getContainer()->get('Sylius\Bundle\CoreBundle\CatalogPromotion\Announcer\CatalogPromotionRemovalAnnouncerInterface');
$catalogPromotionRemovalAnnouncer->dispatchCatalogPromotionRemoval($catalogPromotion);
$this->assertNull(self::$kernel->getContainer()->get('sylius.repository.catalog_promotion')->findOneBy(['code' => $catalogPromotion->getCode()]));
}
private function getCatalogPromotion(): CatalogPromotionInterface
{
/** @var LoaderInterface $fixtureLoader */
$fixtureLoader = self::$kernel->getContainer()->get('fidry_alice_data_fixtures.loader.doctrine');
$fixtures = $fixtureLoader->load([__DIR__ . '/../DataFixtures/ORM/resources/catalog_promotions.yml'], [], [], PurgeMode::createDeleteMode());
/** @var CatalogPromotion $catalogPromotion */
$catalogPromotion = $fixtures['sale_2'];
return $catalogPromotion;
}
}