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

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\EntityRepositoryInterface;
  17. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  18. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  19. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  20. use Symfony\Component\HttpFoundation\Session\Session;
  21. use Virgin\ProductModelExtension\Custom\ProductType\ProductTypeEntity;
  22. use Virgin\Promotions\Custom\PromotionAttributes\PromotionAttributesEntity;
  23. class ExerpPromotionProcessor implements CartProcessorInterface
  24. {
  25. /**
  26. * @var EntityRepository
  27. */
  28. private $promotionAttributesRepository;
  29. /**
  30. * @var PercentagePriceCalculator
  31. */
  32. private $calculator;
  33. /**
  34. * @var LineItemGroupBuilder
  35. */
  36. private $groupBuilder;
  37. /**
  38. * @var EntityRepositoryInterface
  39. */
  40. private $productRepository;
  41. /**
  42. * @var Session
  43. */
  44. private $session;
  45. public function __construct(
  46. EntityRepository $repository,
  47. PercentagePriceCalculator $calculator,
  48. LineItemGroupBuilder $groupBuilder,
  49. EntityRepositoryInterface $productRepository,
  50. Session $session
  51. ) {
  52. $this->promotionAttributesRepository = $repository;
  53. $this->calculator = $calculator;
  54. $this->groupBuilder = $groupBuilder;
  55. $this->productRepository = $productRepository;
  56. $this->session = $session;
  57. }
  58. public function process(
  59. CartDataCollection $data,
  60. Cart $original,
  61. Cart $toCalculate,
  62. SalesChannelContext $context,
  63. CartBehavior $behavior
  64. ): void {
  65. /** @var array $exerpPromotions */
  66. $exerpPromotions = $data->get('exerpPromotions');
  67. $productLineItemCollection = new LineItemCollection();
  68. $promotion = null;
  69. foreach ($exerpPromotions as $exerpPromotion) {
  70. /** @var PromotionEntity $promotion */
  71. $promotion = $exerpPromotion['promotion'];
  72. $discountLineItem = new LineItem(
  73. $promotion->getId(),
  74. 'promotion',
  75. $exerpPromotion['code'],
  76. 1
  77. );
  78. if(!$promotion->getDiscounts()->getElements()){
  79. $discountLineItem->setLabel($promotion->getName());
  80. $discountLineItem->setGood(false);
  81. $discountLineItem->setStackable(true);
  82. $discountLineItem->setRemovable(true);
  83. $discountLineItem->setRequirement($promotion->getPreconditionRule());
  84. $discountLineItem->setPayloadValue('promotionId', $promotion->getId());
  85. $discountLineItem->setPayloadValue('code', $exerpPromotion['code']);
  86. $discountLineItem->setPayloadValue('exerpPromotion', true);
  87. $discountLineItem->setPayloadValue('badgeText', $exerpPromotion['attribute']->getBadgeText());
  88. $discountLineItem->setPayloadValue('exerpPromotionDescription', $exerpPromotion['attribute']->getDescription());
  89. $discountLineItem->setPayloadValue('exerpPromotionCode', $exerpPromotion['attribute']->getExerpCode());
  90. $discountLineItem->setPayloadValue('isSpecialPromoFlow', $exerpPromotion['attribute']->getIsSpecialPromoFlow());
  91. $discountLineItem->setPayloadValue('validUntil', $promotion->getValidUntil() ? $promotion->getValidUntil()->getTimestamp():null);
  92. if (!empty($promoProrataDate = $exerpPromotion['attribute']->getPromoProrataDate())) {
  93. if($promoProrataDate->format('Y-m-d') < date("Y-m-d")) {
  94. $promoProrataDateFormatted = date("Y-m-d");
  95. } else {
  96. $promoProrataDateFormatted = $promoProrataDate->format('Y-m-d');
  97. }
  98. $discountLineItem->setPayloadValue('newPromotionDate', $promoProrataDateFormatted);
  99. if(!isset($_SESSION['prorata_date'])) {
  100. $_SESSION['prorata_date'] = $promoProrataDateFormatted;
  101. }
  102. }
  103. $discountLineItem->setPayloadValue('promoWithoutDiscount', true);
  104. /** @var PromotionAttributesEntity $promotionObject */
  105. $promotionObject = $exerpPromotion['attribute'];
  106. if ($promotionObject->getIsPromoValoreAggiunto()) {
  107. $discountLineItem->setPayloadValue('isPromoValoreAggiunto', true);
  108. $discountLineItem->setPayloadValue('cashbackType', $promotionObject->getCashbackType());
  109. $discountLineItem->setPayloadValue('cashbackValue', (float) $promotionObject->getCashbackValue());
  110. if($promotionObject->getCashbackType() != 'no_cashback') {
  111. $criteria = new Criteria();
  112. $criteria->addAssociation('productType');
  113. $criteria->addFilter(new EqualsFilter('product.productType.name', ProductTypeEntity::CASHBACK));
  114. $searchResult = $this->productRepository->search($criteria, $context->getContext())->first();
  115. $discountLineItem->setPayloadValue('cashbackCenterId', $searchResult->getCustomFields()['virgin_exerp_centerid']);
  116. $discountLineItem->setPayloadValue('cashbackProductId', $searchResult->getCustomFields()['virgin_exerp_productid']);
  117. }
  118. if($promotionObject->getProduct()) {
  119. $promoOmaggioProductType = $promotionObject->getProduct()->getExtensions()['productType']->getName();
  120. $discountLineItem->setPayloadValue('productOmaggioType', $promoOmaggioProductType);
  121. if(array_key_exists('virgin_exerp_centerid', $promotionObject->getProduct()->getCustomFields())) {
  122. $discountLineItem->setPayloadValue('productOmaggioCenterId', $promotionObject->getProduct()->getCustomFields()['virgin_exerp_centerid']);
  123. }
  124. if(array_key_exists('virgin_exerp_productid', $promotionObject->getProduct()->getCustomFields())) {
  125. $discountLineItem->setPayloadValue('productOmaggioProductId', $promotionObject->getProduct()->getCustomFields()['virgin_exerp_productid']);
  126. }
  127. if(array_key_exists('virgin_exerp_externalid', $promotionObject->getProduct()->getCustomFields())) {
  128. $discountLineItem->setPayloadValue('productOmaggioExternalId', $promotionObject->getProduct()->getCustomFields()['virgin_exerp_externalid']);
  129. }
  130. if(array_key_exists('virgin_exerp_type', $promotionObject->getProduct()->getCustomFields())) {
  131. $discountLineItem->setPayloadValue('productOmaggioExerpType', $promotionObject->getProduct()->getCustomFields()['virgin_exerp_type']);
  132. }
  133. $discountLineItem->setPayloadValue('productOmaggioQuantity', 1);
  134. }
  135. }
  136. $definition = new PercentagePriceDefinition(
  137. -100,
  138. );
  139. $discountLineItem->setPriceDefinition($definition);
  140. // calculate price
  141. $discountLineItem->setPrice(
  142. $this->calculator->calculate(
  143. $definition->getPercentage(),
  144. $productLineItemCollection->getPrices(),
  145. $context
  146. )
  147. );
  148. $selectedStartDate = $this->session->get('prorata_date');
  149. if (!$this->isRequirementValid($discountLineItem, $toCalculate, $context, $selectedStartDate)) {
  150. continue;
  151. }
  152. // add discount to new cart
  153. $toCalculate->add($discountLineItem);
  154. $errors = $toCalculate->getErrors()->getElements();
  155. $errorToCalculate = [];
  156. foreach ($errors as $error){
  157. if($error->getCode()!=null && $error->getCode() != $exerpPromotion['code']){
  158. array_push($errorToCalculate, $error);
  159. }
  160. }
  161. $toCalculate->setErrors(new ErrorCollection($errorToCalculate));
  162. }
  163. }
  164. $errorToCalculate = [];
  165. foreach ($toCalculate->getErrors() as $error){
  166. if(!$error instanceof \Shopware\Core\Checkout\Promotion\Cart\Error\PromotionNotFoundError){
  167. $errorToCalculate[] = $error;
  168. }
  169. }
  170. $toCalculate->setErrors(new ErrorCollection($errorToCalculate));
  171. }
  172. private function isRequirementValid(LineItem $lineItem, Cart $calculated, SalesChannelContext $context, $selectedStartDate=null): bool
  173. {
  174. if (!$lineItem->getRequirement()) {
  175. return true;
  176. }
  177. if ($selectedStartDate && $lineItem->getPayload()['validUntil'] && $selectedStartDate>$lineItem->getPayload()['validUntil']) {
  178. return false;
  179. }
  180. $scopeWithoutLineItem = new CartRuleScope($calculated, $context);
  181. $data = $scopeWithoutLineItem->getCart()->getData();
  182. $data->set(LineItemGroupBuilder::class, $this->groupBuilder);
  183. return $lineItem->getRequirement()->match($scopeWithoutLineItem);
  184. }
  185. }