From 4175a6c2a1825c0cfb874335a93877ee981f1222 Mon Sep 17 00:00:00 2001 From: Lukas Mencl Date: Mon, 15 Jun 2015 18:44:08 +0200 Subject: [PATCH] coupon usage limit eligibilityChecker fix --- .../Doctrine/ORM/OrderRepository.php | 26 +++++++++++++++++++ .../Checker/PromotionEligibilityChecker.php | 24 +++++++++++++++-- .../Repository/OrderRepositoryInterface.php | 10 +++++++ 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/src/Sylius/Bundle/CoreBundle/Doctrine/ORM/OrderRepository.php b/src/Sylius/Bundle/CoreBundle/Doctrine/ORM/OrderRepository.php index 01f29dd4cd0..bda860645f1 100644 --- a/src/Sylius/Bundle/CoreBundle/Doctrine/ORM/OrderRepository.php +++ b/src/Sylius/Bundle/CoreBundle/Doctrine/ORM/OrderRepository.php @@ -206,6 +206,32 @@ public function countByUserAndCoupon(UserInterface $user, CouponInterface $coupo return $count; } + /** + * {@inheritdoc} + */ + public function countByCoupon(CouponInterface $coupon) + { + $this->_em->getFilters()->disable('softdeleteable'); + + $queryBuilder = $this->getQueryBuilder(); + $queryBuilder + ->select('count(o.id)') + ->innerJoin('o.promotionCoupons', 'coupons') + ->andWhere('o.completedAt IS NOT NULL') + ->andWhere($queryBuilder->expr()->in('coupons', ':coupons')) + ->setParameter('coupons', (array) $coupon) + ; + + $count = (int) $queryBuilder + ->getQuery() + ->getSingleScalarResult() + ; + + $this->_em->getFilters()->enable('softdeleteable'); + + return $count; + } + /** * Create checkouts paginator. * diff --git a/src/Sylius/Component/Core/Promotion/Checker/PromotionEligibilityChecker.php b/src/Sylius/Component/Core/Promotion/Checker/PromotionEligibilityChecker.php index 1c2f552f2c3..731cfebede6 100644 --- a/src/Sylius/Component/Core/Promotion/Checker/PromotionEligibilityChecker.php +++ b/src/Sylius/Component/Core/Promotion/Checker/PromotionEligibilityChecker.php @@ -75,6 +75,8 @@ protected function areCouponsEligibleForPromotion(PromotionSubjectInterface $sub if ($eligible) { $this->dispatcher->dispatch(SyliusPromotionEvents::COUPON_ELIGIBLE, new GenericEvent($promotion)); + } else { + $this->dispatcher->dispatch(SyliusPromotionEvents::COUPON_NOT_ELIGIBLE, new GenericEvent($promotion)); } return $eligible; @@ -86,6 +88,10 @@ private function isCouponEligibleToLimit(CouponInterface $coupon, PromotionInter return true; } + if (!$this->isCouponEligibleToCouponLimit($coupon)) { + return false; + } + if (!$coupon->getPerUserUsageLimit()) { return true; } @@ -97,12 +103,26 @@ private function isCouponEligibleToLimit(CouponInterface $coupon, PromotionInter return $this->isCouponEligible($coupon, $promotion, $user); } + private function isCouponEligibleToCouponLimit(CouponInterface $coupon) + { + if (!$coupon->getUsageLimit()) { + return true; + } + + $countPlacedOrders = $this->subjectRepository->countByCoupon($coupon); + + if ($countPlacedOrders < $coupon->getUsageLimit()) { + return true; + } + + return false; + } + private function isCouponEligible(CouponInterface $coupon, PromotionInterface $promotion, UserInterface $user) { $countPlacedOrders = $this->subjectRepository->countByUserAndCoupon($user, $coupon); - // <= because we need to include the cart orders as well - if ($countPlacedOrders <= $coupon->getPerUserUsageLimit()) { + if ($countPlacedOrders < $coupon->getPerUserUsageLimit()) { $this->dispatcher->dispatch(SyliusPromotionEvents::COUPON_ELIGIBLE, new GenericEvent($promotion)); return true; diff --git a/src/Sylius/Component/Core/Repository/OrderRepositoryInterface.php b/src/Sylius/Component/Core/Repository/OrderRepositoryInterface.php index ad0d2af47e4..2498a002f0a 100644 --- a/src/Sylius/Component/Core/Repository/OrderRepositoryInterface.php +++ b/src/Sylius/Component/Core/Repository/OrderRepositoryInterface.php @@ -39,6 +39,16 @@ public function findExpired(\DateTime $expiresAt, $state = OrderInterface::STATE */ public function countByUserAndCoupon(UserInterface $user, CouponInterface $coupon); + /** + * Gets the number of orders placed + * for a particular coupon. + * + * @param CouponInterface $coupon + * + * @return int + */ + public function countByCoupon(CouponInterface $coupon); + /** * Gets the number of orders placed by the user * with particular state.