custom/plugins/Promotions/src/Core/Checkout/Promotion/Cart/ExerpPromotionProcessor.php line 130

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Virgin\Promotions\Core\Checkout\Promotion\Cart;
  3. use Shopware\Core\Checkout\Cart\Cart;
  4. use Shopware\Core\Checkout\Cart\CartBehavior;
  5. use Shopware\Core\Checkout\Cart\CartProcessorInterface;
  6. use Shopware\Core\Checkout\Cart\Error\ErrorCollection;
  7. use Shopware\Core\Checkout\Cart\LineItem\CartDataCollection;
  8. use Shopware\Core\Checkout\Cart\LineItem\Group\LineItemGroupBuilder;
  9. use Shopware\Core\Checkout\Cart\LineItem\LineItem;
  10. use Shopware\Core\Checkout\Cart\LineItem\LineItemCollection;
  11. use Shopware\Core\Checkout\Cart\Price\PercentagePriceCalculator;
  12. use Shopware\Core\Checkout\Cart\Price\Struct\PercentagePriceDefinition;
  13. use Shopware\Core\Checkout\Cart\Rule\CartRuleScope;
  14. use Shopware\Core\Checkout\Promotion\PromotionEntity;
  15. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
  16. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  17. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  18. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  19. use Symfony\Component\HttpFoundation\Session\Session;
  20. use Virgin\ProductModelExtension\Custom\ProductType\ProductTypeEntity;
  21. use Virgin\Promotions\Custom\PromotionAttributes\PromotionAttributesEntity;
  22. class ExerpPromotionProcessor implements CartProcessorInterface
  23. {
  24. /**
  25. * @var EntityRepository
  26. */
  27. private $promotionAttributesRepository;
  28. /**
  29. * @var PercentagePriceCalculator
  30. */
  31. private $calculator;
  32. /**
  33. * @var LineItemGroupBuilder
  34. */
  35. private $groupBuilder;
  36. /**
  37. * @var EntityRepository
  38. */
  39. private $productRepository;
  40. /**
  41. * @var Session
  42. */
  43. private $session;
  44. public function __construct(
  45. EntityRepository $repository,
  46. PercentagePriceCalculator $calculator,
  47. LineItemGroupBuilder $groupBuilder,
  48. EntityRepository $productRepository,
  49. Session $session
  50. ) {
  51. $this->promotionAttributesRepository = $repository;
  52. $this->calculator = $calculator;
  53. $this->groupBuilder = $groupBuilder;
  54. $this->productRepository = $productRepository;
  55. $this->session = $session;
  56. }
  57. public function process(
  58. CartDataCollection $data,
  59. Cart $original,
  60. Cart $toCalculate,
  61. SalesChannelContext $context,
  62. CartBehavior $behavior
  63. ): void {
  64. /** @var array $exerpPromotions */
  65. $exerpPromotions = $data->get('exerpPromotions');
  66. $productLineItemCollection = new LineItemCollection();
  67. $promotion = null;
  68. foreach ($exerpPromotions as $exerpPromotion) {
  69. /** @var PromotionEntity $promotion */
  70. $promotion = $exerpPromotion['promotion'];
  71. $discountLineItem = new LineItem(
  72. $promotion->getId(),
  73. 'promotion',
  74. $exerpPromotion['code'],
  75. 1
  76. );
  77. if(!$promotion->getDiscounts()->getElements()){
  78. $discountLineItem->setLabel($promotion->getTranslation('name'));
  79. $discountLineItem->setGood(false);
  80. $discountLineItem->setStackable(true);
  81. $discountLineItem->setRemovable(true);
  82. $discountLineItem->setRequirement($promotion->getPreconditionRule());
  83. $discountLineItem->setPayloadValue('promotionId', $promotion->getId());
  84. $discountLineItem->setPayloadValue('code', $exerpPromotion['code']);
  85. $discountLineItem->setPayloadValue('exerpPromotion', true);
  86. $discountLineItem->setPayloadValue('badgeText', $exerpPromotion['attribute']->getBadgeText());
  87. $discountLineItem->setPayloadValue('exerpPromotionDescription', $exerpPromotion['attribute']->getDescription());
  88. $discountLineItem->setPayloadValue('exerpPromotionCode', $exerpPromotion['attribute']->getExerpCode());
  89. $discountLineItem->setPayloadValue('isSpecialPromoFlow', $exerpPromotion['attribute']->getIsSpecialPromoFlow());
  90. $discountLineItem->setPayloadValue('validUntil', $promotion->getValidUntil()?->getTimestamp());
  91. if (!empty($promoProrataDate = $exerpPromotion['attribute']->getPromoProrataDate())) {
  92. if($promoProrataDate->format('Y-m-d') < date("Y-m-d")) {
  93. $promoProrataDateFormatted = date("Y-m-d");
  94. } else {
  95. $promoProrataDateFormatted = $promoProrataDate->format('Y-m-d');
  96. }
  97. $discountLineItem->setPayloadValue('newPromotionDate', $promoProrataDateFormatted);
  98. if(!isset($_SESSION['prorata_date'])) {
  99. $_SESSION['prorata_date'] = $promoProrataDateFormatted;
  100. }
  101. }
  102. $discountLineItem->setPayloadValue('promoWithoutDiscount', true);
  103. /** @var PromotionAttributesEntity $promotionObject */
  104. $promotionObject = $exerpPromotion['attribute'];
  105. $definition = new PercentagePriceDefinition(
  106. -100,
  107. );
  108. $discountLineItem->setPriceDefinition($definition);
  109. // calculate price
  110. $discountLineItem->setPrice(
  111. $this->calculator->calculate(
  112. $definition->getPercentage(),
  113. $productLineItemCollection->getPrices(),
  114. $context
  115. )
  116. );
  117. $selectedStartDate = $this->session->get('prorata_date');
  118. if (!$this->isRequirementValid($discountLineItem, $toCalculate, $context, $selectedStartDate)) {
  119. continue;
  120. }
  121. // add discount to new cart
  122. $toCalculate->add($discountLineItem);
  123. $errors = $toCalculate->getErrors()->getElements();
  124. $errorToCalculate = [];
  125. foreach ($errors as $error){
  126. if($error->getCode()!=null && $error->getCode() != $exerpPromotion['code']){
  127. $errorToCalculate[] = $error;
  128. }
  129. }
  130. $toCalculate->setErrors(new ErrorCollection($errorToCalculate));
  131. }
  132. }
  133. $errorToCalculate = [];
  134. foreach ($toCalculate->getErrors() as $error){
  135. if(!$error instanceof \Shopware\Core\Checkout\Promotion\Cart\Error\PromotionNotFoundError){
  136. $errorToCalculate[] = $error;
  137. }
  138. }
  139. $toCalculate->setErrors(new ErrorCollection($errorToCalculate));
  140. }
  141. private function isRequirementValid(LineItem $lineItem, Cart $calculated, SalesChannelContext $context, $selectedStartDate=null): bool
  142. {
  143. if (!$lineItem->getRequirement()) {
  144. return true;
  145. }
  146. if ($selectedStartDate && $lineItem->getPayload()['validUntil'] && $selectedStartDate>$lineItem->getPayload()['validUntil']) {
  147. return false;
  148. }
  149. $scopeWithoutLineItem = new CartRuleScope($calculated, $context);
  150. $data = $scopeWithoutLineItem->getCart()->getData();
  151. $data->set(LineItemGroupBuilder::class, $this->groupBuilder);
  152. return $lineItem->getRequirement()->match($scopeWithoutLineItem);
  153. }
  154. }