custom/plugins/PremsBonusSystem/src/Core/Checkout/Bonus/BonusProcessor.php line 215

Open in your IDE?
  1. <?php
  2. declare(strict_types = 1);
  3. /**
  4. * PremSoft
  5. * Copyright © 2020 Premsoft - Sven Mittreiter
  6. *
  7. * @copyright Copyright (c) 2020, premsoft - Sven Mittreiter (http://www.premsoft.de)
  8. * @author Sven Mittreiter <info@premsoft.de>
  9. */
  10. namespace Prems\Plugin\PremsBonusSystem\Core\Checkout\Bonus;
  11. use Prems\Plugin\PremsBonusSystem\Core\Bonus\Calculation\CalculationService;
  12. use Prems\Plugin\PremsBonusSystem\Core\Bonus\ConfigData;
  13. use Prems\Plugin\PremsBonusSystem\Core\Bonus\ConfigService;
  14. use Shopware\Core\Checkout\Cart\Cart;
  15. use Shopware\Core\Checkout\Cart\LineItem\LineItem;
  16. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  17. use Symfony\Component\HttpFoundation\RequestStack;
  18. use Symfony\Component\HttpFoundation\Session\Session;
  19. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  20. /**
  21. * Store, get, delete and validate point redeem
  22. * Class BonusProcessor
  23. * @package Prems\Plugin\PremsBonusSystem\Core\Checkout\Bonus
  24. */
  25. class BonusProcessor
  26. {
  27. public const POINT_REDEEM_BASKET_DISCOUNT = 'basketDiscount';
  28. public const ROUTES_TO_BE_SKIPPED = [
  29. 'frontend.account.order.single.page'
  30. ];
  31. private ConfigService $configService;
  32. /**
  33. * @var SessionInterface
  34. */
  35. private $sessionService;
  36. /**
  37. * @var CalculationService
  38. */
  39. private $calculationService;
  40. /**
  41. * @var RequestStack
  42. */
  43. private $requestStack;
  44. public function __construct(
  45. ConfigService $configService,
  46. CalculationService $calculationService,
  47. RequestStack $requestStack)
  48. {
  49. $this->configService = $configService;
  50. $this->calculationService = $calculationService;
  51. $this->requestStack = $requestStack;
  52. // quick fix to prevent errors in a console
  53. $this->sessionService = new Session();
  54. if ($requestStack->getMainRequest() && $requestStack->getMainRequest()->hasSession()) {
  55. $this->sessionService = $requestStack->getMainRequest()->getSession();
  56. }
  57. }
  58. /**
  59. * Check if point redeem value is valid
  60. * @param $bonusPointsWantToRedeem
  61. * @param Cart $cart
  62. * @param $bonusSystemConversionFactor
  63. * @param $basketAmountRedeemRestriction
  64. * @param $basketAmountRedeemRestrictionValue
  65. * @param $hasPoints
  66. * @param SalesChannelContext $context
  67. * @return bool
  68. */
  69. public function isPointRedeemOk(
  70. $bonusPointsWantToRedeem,
  71. Cart $cart,
  72. $bonusSystemConversionFactor,
  73. $basketAmountRedeemRestriction,
  74. $basketAmountRedeemRestrictionValue,
  75. $hasPoints,
  76. SalesChannelContext $context
  77. ) {
  78. if ($bonusPointsWantToRedeem > $hasPoints) {
  79. return false;
  80. }
  81. $settings = $this->configService->getConfig($context);
  82. $settingVars = $settings->getVars();
  83. //$discount = $this->calculationService->calculateDiscountForBonusPoints($bonusPointsWantToRedeem, $bonusSystemConversionFactor, $context);
  84. $lineItems = $cart->getLineItems();
  85. if ($context->getCurrentCustomerGroup()->getDisplayGross()) {
  86. //if ($context->getCurrentCustomerGroup()->getDisplayGross() || !$settingVars['grossPricesForCalculation']) {
  87. $totalPrice = $cart->getShippingCosts()->getTotalPrice();
  88. } else {
  89. // Shipping costs total price is net when customer has no gross prices set. Calculate with gross price
  90. $totalPrice = $cart->getShippingCosts()->getTotalPrice() + $cart->getShippingCosts()->getCalculatedTaxes()->getAmount();
  91. }
  92. /** @var LineItem $lineItem */
  93. foreach ($lineItems as $lineItem) {
  94. // Don't reduce basket value with current bonus discount
  95. if ($lineItem->hasExtension('prems_bonus_system_discount')) {
  96. continue;
  97. }
  98. if ($context->getCurrentCustomerGroup()->getDisplayGross()) {
  99. //if ($context->getCurrentCustomerGroup()->getDisplayGross() || !$settingVars['grossPricesForCalculation']) {
  100. $totalPrice += $lineItem->getPrice()->getTotalPrice();
  101. } else {
  102. // Line item total price is net when customer has no gross prices set. Calculate with gross price
  103. $totalPrice += $lineItem->getPrice()->getTotalPrice() + $lineItem->getPrice()->getCalculatedTaxes()->getAmount();
  104. }
  105. }
  106. $totalPriceDefaultCurrency = $this->calculationService->getCurrencyCalculationService()->calculateToDefaultPrice($context->getCurrency(), $totalPrice);
  107. if ($basketAmountRedeemRestriction == ConfigData::BASKET_AMOUNT_REDEEM_RESTRICTION_MIN_ORDER_VALUE) {
  108. //$availableBasketAmountForRedeemPoints = floor($totalPriceDefaultCurrency - $basketAmountRedeemRestrictionValue);
  109. $availableBasketAmountForRedeemPoints = $totalPriceDefaultCurrency - $basketAmountRedeemRestrictionValue;
  110. }
  111. if ($basketAmountRedeemRestriction == ConfigData::BASKET_AMOUNT_REDEEM_RESTRICTION_MAX_VALUE) {
  112. if ($basketAmountRedeemRestrictionValue > $totalPriceDefaultCurrency) {
  113. //$availableBasketAmountForRedeemPoints = floor($totalPriceDefaultCurrency);
  114. $availableBasketAmountForRedeemPoints = $totalPriceDefaultCurrency;
  115. } else {
  116. //$availableBasketAmountForRedeemPoints = floor($basketAmountRedeemRestrictionValue);
  117. $availableBasketAmountForRedeemPoints = $basketAmountRedeemRestrictionValue;
  118. }
  119. }
  120. $availableBasketAmountForRedeemPoints = $this->calculationService->calculateAvailableBasketAmountWithConditions(
  121. $availableBasketAmountForRedeemPoints,
  122. $cart->getLineItems(),
  123. $context,
  124. false
  125. );
  126. foreach ($lineItems as $lineItem) {
  127. if (!$lineItem->hasExtension('premsBonusSystem')) {
  128. continue;
  129. }
  130. $lineItemPrice = $lineItem->getExtension('premsBonusSystem')->get('originalPrice')->getTotalPrice();
  131. $availableBasketAmountForRedeemPoints += $this->calculationService->getCurrencyCalculationService()->calculateToDefaultPrice($context->getCurrency(), $lineItemPrice);
  132. }
  133. // $calculatedMaxBonusPoints for availableBasketAmountForRedeemPoints (points are ceil, so that it is possible to create a 100% discount)
  134. $calculatedMaxBonusPoints = $this->calculationService->calculateBonusPointsForAmount($availableBasketAmountForRedeemPoints, $bonusSystemConversionFactor, $context);
  135. if ($bonusPointsWantToRedeem > $calculatedMaxBonusPoints) {
  136. return false;
  137. }
  138. return true;
  139. }
  140. /**
  141. * Remove points for a specific redeem type
  142. * @param string $redeemType
  143. */
  144. public function removePointRedeemByType(string $redeemType = self::POINT_REDEEM_BASKET_DISCOUNT)
  145. {
  146. if ($this->sessionService->has('prems_bonus_system_redeem_points')) {
  147. $bonusEntries = $this->sessionService->get('prems_bonus_system_redeem_points');
  148. unset($bonusEntries[$redeemType]);
  149. $this->sessionService->set('prems_bonus_system_redeem_points', $bonusEntries);
  150. }
  151. }
  152. /**
  153. * Store points for a redeem type
  154. * @param $bonusPoints
  155. * @param string $redeemType
  156. */
  157. public function storePointRedeem($bonusPoints, string $redeemType = self::POINT_REDEEM_BASKET_DISCOUNT, $amount = 0)
  158. {
  159. $bonusEntry = [$redeemType => [
  160. 'points' => $bonusPoints,
  161. 'amount' => $amount
  162. ]];
  163. $this->sessionService->set('prems_bonus_system_redeem_points', array_merge($this->sessionService->get('prems_bonus_system_redeem_points', []), $bonusEntry));
  164. }
  165. /**
  166. * Get points customer wants to redeem
  167. * @return int
  168. */
  169. public function getPointRedeem()
  170. {
  171. if ($this->sessionService->has('prems_bonus_system_redeem_points')) {
  172. $bonusEntries = $this->sessionService->get('prems_bonus_system_redeem_points');
  173. $points = 0;
  174. foreach ($bonusEntries as $bonusEntry) {
  175. $points += $bonusEntry['points'];
  176. }
  177. return (int)$points;
  178. }
  179. return 0;
  180. }
  181. public function getPointRedeemByType(string $redeemType = self::POINT_REDEEM_BASKET_DISCOUNT)
  182. {
  183. if (!$this->shouldSkipCurrentRoute() && $this->sessionService->has('prems_bonus_system_redeem_points')) {
  184. $bonusEntries = $this->sessionService->get('prems_bonus_system_redeem_points');
  185. $points = 0;
  186. $amount = 0;
  187. foreach ($bonusEntries as $key => $bonusEntry) {
  188. if ($key !== $redeemType) {
  189. continue;
  190. }
  191. $points += $bonusEntry['points'];
  192. $amount += $bonusEntry['amount'];
  193. }
  194. return ['points' => $points, 'amount' => $amount];
  195. }
  196. return ['points' => 0, 'amount' => 0];
  197. }
  198. public function removePointRedeem()
  199. {
  200. $this->sessionService->remove('prems_bonus_system_redeem_points');
  201. }
  202. public function removePointRedeemFromCart(Cart $cart)
  203. {
  204. /** @var LineItem $lineItem */
  205. foreach ($cart->getLineItems() as $lineItem) {
  206. if ($lineItem->hasExtension('prems_bonus_system_discount')) {
  207. $lineItem->setRemovable(true);
  208. $cart->remove($lineItem->getId());
  209. }
  210. }
  211. $this->removePointRedeemByType(self::POINT_REDEEM_BASKET_DISCOUNT);
  212. }
  213. /**
  214. * @return bool
  215. */
  216. public function shouldSkipCurrentRoute(): bool
  217. {
  218. if($this->requestStack->getMainRequest() === null) {
  219. return true;
  220. }
  221. $currentRoute = $this->requestStack->getCurrentRequest()->attributes->get('_route') ?: '';
  222. return in_array($currentRoute, self::ROUTES_TO_BE_SKIPPED, true);
  223. }
  224. }