/**
  * Checks if given Coupon is valid. To determine its validity, this service
  * will evaluate all rules if there are any.
  *
  * @param CartInterface   $cart   Cart
  * @param CouponInterface $coupon Coupon
  *
  * @return boolean Coupon is valid
  */
 public function checkCouponValidity(CartInterface $cart, CouponInterface $coupon)
 {
     $rules = $coupon->getRules();
     return $rules->forAll(function ($_, AbstractRuleInterface $rule) use($cart, $coupon) {
         return $this->ruleManager->evaluateByRule($rule, ['cart' => $cart, 'coupon' => $coupon]);
     });
 }
 /**
  * Calculate coupon absolute value.
  *
  * @param CartInterface   $cart   Cart
  * @param CouponInterface $coupon Coupon
  *
  * @return MoneyInterface|false Absolute value for this coupon in this cart
  */
 public function getCouponAbsoluteValue(CartInterface $cart, CouponInterface $coupon)
 {
     $currency = $this->currencyWrapper->get();
     $couponPrice = Money::create(0, $currency);
     $value = $coupon->getValue();
     preg_match($this->regexp(), $value, $match);
     $m = (int) $match[1];
     $n = (int) $match[2];
     $expressionValue = isset($match[3]) ? $match[3] : '';
     $modifiers = isset($match[4]) ? $match[4] : '';
     $freePerGroup = $m - $n;
     $freePerGroup = max($freePerGroup, 0);
     foreach ($cart->getCartLines() as $cartLine) {
         $moneys = [];
         $purchasable = $cartLine->getPurchasable();
         $expressionEvaluator = $this->getExpressionLanguageInstance();
         $expressionResult = (empty($expressionValue) || $expressionEvaluator->evaluate($expressionValue, ['purchasable' => $purchasable])) && $this->evaluatePurchasableType($purchasable, $modifiers);
         if (true === $expressionResult) {
             $partialElements = $cartLine->getQuantity();
             for ($i = 0; $i < $partialElements; ++$i) {
                 $partialPurchasable = $cartLine->getPurchasable();
                 $moneys[] = $partialPurchasable->getReducedPrice()->getAmount() > 0 ? $partialPurchasable->getReducedPrice() : $partialPurchasable->getPrice();
             }
             $groups = $partialElements / $m;
             if ($groups > 0) {
                 $nbMoneys = $groups * $freePerGroup;
                 $moneysToDiscount = array_slice($moneys, 0, $nbMoneys);
                 foreach ($moneysToDiscount as $moneyToDiscount) {
                     $couponPrice = $couponPrice->add($this->currencyConverter->convertMoney($moneyToDiscount, $currency));
                 }
             }
         }
     }
     return $couponPrice;
 }
Example #3
0
 /**
  * Checks if given Coupon is valid. To determine its validity, this service
  * will evaluate all rules if there are any.
  *
  * @param CartInterface   $cart   Cart
  * @param CouponInterface $coupon Coupon
  *
  * @return boolean Coupon is valid
  */
 public function checkCouponValidity(CartInterface $cart, CouponInterface $coupon)
 {
     $rule = $coupon->getRule();
     if (null === $rule) {
         return true;
     }
     try {
         return $this->ruleManager->evaluate($rule, ['cart' => $cart, 'coupon' => $coupon]);
     } catch (\Exception $e) {
         // Maybe log something in case of exception?
     }
     return false;
 }
 /**
  * Check if cart meets minimum price requirements for a coupon.
  *
  * @param CartInterface   $cart   Cart
  * @param CouponInterface $coupon Coupon
  *
  * @throws CouponBelowMinimumPurchaseException Minimum value not reached
  */
 public function validateCartCouponMinimumPrice(CartInterface $cart, CouponInterface $coupon)
 {
     $couponMinimumPrice = $coupon->getMinimumPurchase();
     if ($couponMinimumPrice->getAmount() === 0) {
         return;
     }
     $productMoney = $cart->getProductAmount();
     if ($couponMinimumPrice->getCurrency() != $productMoney->getCurrency()) {
         $couponMinimumPrice = $this->currencyConverter->convertMoney($couponMinimumPrice, $productMoney->getCurrency());
     }
     if ($productMoney->isLessThan($couponMinimumPrice)) {
         throw new CouponBelowMinimumPurchaseException();
     }
 }
 /**
  * Checks if given Coupon is valid. To determine its validity, this service
  * will evaluate all rules if there are any.
  *
  * @param CartInterface   $cart   Cart
  * @param CouponInterface $coupon Coupon
  *
  * @throws CouponRulesNotValidateException Rules not valid
  */
 public function validateCartCouponRules(CartInterface $cart, CouponInterface $coupon)
 {
     $rule = $coupon->getRule();
     if (null === $rule) {
         return;
     }
     try {
         $isValid = $this->ruleManager->evaluate($rule, ['cart' => $cart, 'coupon' => $coupon]);
         if (!$isValid) {
             throw new CouponRulesNotValidateException();
         }
         return;
     } catch (Exception $e) {
         // Maybe log something in case of exception?
     }
     throw new CouponRulesNotValidateException();
 }
 /**
  * Check if this coupon can be applied when other coupons had previously
  * been applied.
  *
  * @param CartInterface   $cart   Cart
  * @param CouponInterface $coupon Coupon
  *
  * @throws CouponNotStackableException Coupon is not stackable
  */
 public function validateStackableCoupon(CartInterface $cart, CouponInterface $coupon)
 {
     $cartCoupons = $this->cartCouponRepository->findBy(['cart' => $cart]);
     /**
      * If there are no previously applied coupons we can skip the check.
      */
     if (0 == count($cartCoupons)) {
         return;
     }
     $appliedCouponsCanBeStacked = array_reduce($cartCoupons, function ($previousCouponsAreStackable, CartCouponInterface $cartCoupon) {
         return $previousCouponsAreStackable && $cartCoupon->getCoupon()->getStackable();
     }, true);
     /**
      * Checked coupon can be stackable and everything that was
      * previously applied is also stackable.
      */
     if ($coupon->getStackable() && $appliedCouponsCanBeStacked) {
         return;
     }
     throw new CouponNotStackableException();
 }
 /**
  * Given a cart and a coupon, returns the real value of the coupon.
  * If the type of the coupon is not valid, then an empty Money instance will
  * be returned, with value 0.
  *
  * @param CartInterface   $cart   Abstract Cart object
  * @param CouponInterface $coupon Coupon
  *
  * @return MoneyInterface Coupon price
  */
 public function getCouponAbsolutePrice(CartInterface $cart, CouponInterface $coupon)
 {
     $currency = $this->currencyWrapper->get();
     $couponPrice = Money::create(0, $currency);
     switch ($coupon->getType()) {
         case ElcodiCouponTypes::TYPE_PERCENT:
             $couponPercent = $coupon->getDiscount();
             $couponPrice = $cart->getProductAmount()->multiply($couponPercent / 100);
             break;
         case ElcodiCouponTypes::TYPE_AMOUNT:
             $amount = $coupon->getPrice();
             $couponPrice = $this->currencyConverter->convertMoney($amount, $currency);
             break;
     }
     return $couponPrice;
 }
Example #8
0
 /**
  * Check if a coupon can be currently used.
  *
  * @param CouponInterface $coupon
  *
  * @return bool
  */
 private function canBeUsed(CouponInterface $coupon)
 {
     $count = $coupon->getCount();
     if ($count === 0) {
         return true;
     }
     if ($coupon->getUsed() < $count) {
         return true;
     }
     return false;
 }
 /**
  * Check if a coupon has manual enforcement
  *
  * @param CouponInterface $coupon Coupon
  *
  * @return bool
  */
 protected function isManual(CouponInterface $coupon)
 {
     return $coupon->getEnforcement() === ElcodiCouponTypes::ENFORCEMENT_MANUAL;
 }
 /**
  * Calculate coupon absolute value.
  *
  * @param CartInterface   $cart   Cart
  * @param CouponInterface $coupon Coupon
  *
  * @return MoneyInterface|false Absolute value for this coupon in this cart.
  */
 public function getCouponAbsoluteValue(CartInterface $cart, CouponInterface $coupon)
 {
     $couponPercent = $coupon->getDiscount();
     return $cart->getPurchasableAmount()->multiply($couponPercent / 100);
 }
Example #11
0
 /**
  * Given a cart and a coupon, returns the real value of the coupon
  *
  * @param CartInterface   $cart   Abstract Cart object
  * @param CouponInterface $coupon Coupon
  *
  * @return MoneyInterface Coupon price
  */
 protected function getPriceCoupon(CartInterface $cart, CouponInterface $coupon)
 {
     $currency = $this->currencyWrapper->getCurrency();
     switch ($coupon->getType()) {
         case ElcodiCouponTypes::TYPE_AMOUNT:
             $amount = $coupon->getPrice();
             return $this->currencyConverter->convertMoney($amount, $currency);
         case ElcodiCouponTypes::TYPE_PERCENT:
             $couponPercent = $coupon->getDiscount();
             return $cart->getProductAmount()->multiply($couponPercent / 100);
     }
 }
 /**
  * Calculate coupon absolute value.
  *
  * @param CartInterface   $cart   Cart
  * @param CouponInterface $coupon Coupon
  *
  * @return MoneyInterface|false Absolute value for this coupon in this cart
  */
 public function getCouponAbsoluteValue(CartInterface $cart, CouponInterface $coupon)
 {
     $currency = $this->currencyWrapper->get();
     $amount = $coupon->getPrice();
     return $this->currencyConverter->convertMoney($amount, $currency);
 }
Example #13
0
 /**
  * Creates a new coupon instance, given an existing Coupon as reference
  *
  * You can specify a DateTime new coupon will be valid from.
  * If not specified, current DateTime will be used
  *
  * If given coupon is valid forever, new coupon will also be
  * Otherwise, this method will add to validFrom, the same interval than given Coupon
  *
  * Also can be specified how new Coupon name must be defined.
  * If none, automatic generator will add to existing name, 10 random digits.
  *
  * Given Coupon name: FOO
  * New Coupon name: FOO_a67b6786a6
  *
  * Coupons are only generated, and are not persisted in Manager not Flushed
  *
  * @param CouponInterface $coupon   Reference coupon
  * @param DateTime        $dateFrom Date From. If null, takes actual dateTime
  *
  * @return CouponInterface Coupon generated
  */
 public function duplicateCoupon(CouponInterface $coupon, DateTime $dateFrom = null)
 {
     /**
      * Creates a valid date interval given the referent Coupon
      */
     if (!$dateFrom instanceof DateTime) {
         $dateFrom = new DateTime();
     }
     $dateTo = null;
     if ($coupon->getValidTo() instanceof DateTime) {
         $interval = $coupon->getValidFrom()->diff($coupon->getValidTo());
         $dateTo = clone $dateFrom;
         $dateTo->add($interval);
     }
     /**
      * @var CouponInterface $couponGenerated
      */
     $couponGenerated = $this->couponFactory->create();
     $couponGenerated->setCode($this->couponCodeGenerator->generate())->setName($coupon->getName())->setType($coupon->getType())->setPrice($coupon->getPrice())->setDiscount($coupon->getDiscount())->setCount($coupon->getCount())->setPriority($coupon->getPriority())->setMinimumPurchase($coupon->getMinimumPurchase())->setValidFrom($dateFrom)->setValidTo($dateTo)->setEnabled(true);
     return $couponGenerated;
 }
 /**
  * Can be applied.
  *
  * @param CartInterface   $cart   Cart
  * @param CouponInterface $coupon Coupon
  *
  * @return bool Can be applied
  */
 public function canBeApplied(CartInterface $cart, CouponInterface $coupon)
 {
     return $coupon->getType() === self::id() && 1 === preg_match($this->regexp(), $coupon->getValue());
 }