src/Core/Checkout/Promotion/Subscriber/PromotionIndividualCodeRedeemer.php line 45

  1. <?php
  2. declare(strict_types=1);
  3. namespace Shopware\Core\Checkout\Promotion\Subscriber;
  4. use Shopware\Core\Checkout\Cart\Event\CheckoutOrderPlacedEvent;
  5. use Shopware\Core\Checkout\Order\Aggregate\OrderCustomer\OrderCustomerEntity;
  6. use Shopware\Core\Checkout\Promotion\Aggregate\PromotionIndividualCode\PromotionIndividualCodeCollection;
  7. use Shopware\Core\Checkout\Promotion\Aggregate\PromotionIndividualCode\PromotionIndividualCodeEntity;
  8. use Shopware\Core\Checkout\Promotion\Cart\PromotionProcessor;
  9. use Shopware\Core\Checkout\Promotion\Exception\CodeAlreadyRedeemedException;
  10. use Shopware\Core\Checkout\Promotion\Exception\PromotionCodeNotFoundException;
  11. use Shopware\Core\Framework\Context;
  12. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
  13. use Shopware\Core\Framework\DataAbstractionLayer\Exception\InconsistentCriteriaIdsException;
  14. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  15. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  16. use Shopware\Core\Framework\Log\Package;
  17. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  18. /**
  19.  * @internal
  20.  */
  21. #[Package('checkout')]
  22. class PromotionIndividualCodeRedeemer implements EventSubscriberInterface
  23. {
  24.     /**
  25.      * @internal
  26.      */
  27.     public function __construct(private readonly EntityRepository $codesRepository)
  28.     {
  29.     }
  30.     public static function getSubscribedEvents(): array
  31.     {
  32.         return [
  33.             CheckoutOrderPlacedEvent::class => 'onOrderPlaced',
  34.         ];
  35.     }
  36.     /**
  37.      * @throws CodeAlreadyRedeemedException
  38.      * @throws InconsistentCriteriaIdsException
  39.      */
  40.     public function onOrderPlaced(CheckoutOrderPlacedEvent $event): void
  41.     {
  42.         foreach ($event->getOrder()->getLineItems() ?? [] as $item) {
  43.             // only update promotions in here
  44.             if ($item->getType() !== PromotionProcessor::LINE_ITEM_TYPE) {
  45.                 continue;
  46.             }
  47.             /** @var string $code */
  48.             $code $item->getPayload()['code'] ?? '';
  49.             try {
  50.                 // first try if its an individual
  51.                 // if not, then it might be a global promotion
  52.                 $individualCode $this->getIndividualCode($code$event->getContext());
  53.             } catch (PromotionCodeNotFoundException) {
  54.                 $individualCode null;
  55.             }
  56.             // if we did not use an individual code we might have
  57.             // just used a global one or anything else, so just quit in this case.
  58.             if (!($individualCode instanceof PromotionIndividualCodeEntity)) {
  59.                 return;
  60.             }
  61.             /** @var OrderCustomerEntity $customer */
  62.             $customer $event->getOrder()->getOrderCustomer();
  63.             // set the code to be redeemed
  64.             // and assign all required meta data
  65.             // for later needs
  66.             $individualCode->setRedeemed(
  67.                 $item->getOrderId(),
  68.                 $customer->getCustomerId() ?? '',
  69.                 $customer->getFirstName() . ' ' $customer->getLastName()
  70.             );
  71.             // save in database
  72.             $this->codesRepository->update(
  73.                 [
  74.                     [
  75.                         'id' => $individualCode->getId(),
  76.                         'payload' => $individualCode->getPayload(),
  77.                     ],
  78.                 ],
  79.                 $event->getContext()
  80.             );
  81.         }
  82.     }
  83.     /**
  84.      * Gets all individual code entities for the provided code value.
  85.      *
  86.      * @throws PromotionCodeNotFoundException
  87.      * @throws InconsistentCriteriaIdsException
  88.      */
  89.     private function getIndividualCode(string $codeContext $context): PromotionIndividualCodeEntity
  90.     {
  91.         $criteria = new Criteria();
  92.         $criteria->addFilter(
  93.             new EqualsFilter('code'$code)
  94.         );
  95.         /** @var PromotionIndividualCodeCollection $result */
  96.         $result $this->codesRepository->search($criteria$context)->getEntities();
  97.         if (\count($result->getElements()) <= 0) {
  98.             throw new PromotionCodeNotFoundException($code);
  99.         }
  100.         // return first element
  101.         return $result->first();
  102.     }
  103. }