/** * Check if a rule applies to a quote address * * @param Mage_SalesRule_Model_Rule $rule * @param Mage_Sales_Model_Quote_Address $address * * @return bool */ public function canApplyRule(Mage_SalesRule_Model_Rule $rule, Mage_Sales_Model_Quote_Address $address) { // If rule require a coupon, verify the coupon code and usage if ($rule->getCouponType() != Mage_SalesRule_Model_Rule::COUPON_TYPE_NO_COUPON) { // Grab the coupon code from the quote $couponCode = trim($address->getQuote()->getCouponCode()); // Rule requires a coupon and none was applied if (empty($couponCode)) { return false; } // Load the referenced coupon /** @var Mage_SalesRule_Model_Coupon $coupon */ $coupon = Mage::getModel('salesrule/coupon')->load($couponCode, 'code'); // Rule requires a coupon and the provided code is not valid if (!$coupon->getId() || $coupon->getRuleId() != $rule->getId()) { return false; } // Check coupon global usage limit if ($coupon->getUsageLimit() && $coupon->getTimesUsed() >= $coupon->getUsageLimit()) { return false; } // Check per customer usage limit - only for logged in customers if ($coupon->getUsagePerCustomer() && $address->getQuote()->getCustomerId()) { $useCount = $this->getCustomerCouponUseCount($address->getQuote()->getCustomerId(), $coupon); if ($useCount >= $coupon->getUsagePerCustomer()) { return false; } } } if ($rule->getUsesPerCustomer() && $address->getQuote()->getCustomerId()) { $useCount = $this->getCustomerRuleUseCount($address->getQuote()->getCustomerId(), $rule); if ($useCount >= $rule->getUsesPerCustomer()) { return false; } } // Since the rule passed all the pre-checks, if the rule conditions validate then the rule applies return $rule->validate($address); }
/** * Set coupon code to address if $rule contains validated coupon * * @param Mage_Sales_Model_Quote_Address $address * @param Mage_SalesRule_Model_Rule $rule * * @return Mage_SalesRule_Model_Validator */ protected function _maintainAddressCouponCode($address, $rule) { /* Rule is a part of rules collection, which includes only rules with 'No Coupon' type or with validated coupon. As a result, if rule uses coupon code(s) ('Specific' or 'Auto' Coupon Type), it always contains validated coupon */ if ($rule->getCouponType() != Mage_SalesRule_Model_Rule::COUPON_TYPE_NO_COUPON) { $address->setCouponCode($this->getCouponCode()); } return $this; }
/** * Check if rule can be applied for specific address/quote/customer * * @param Mage_SalesRule_Model_Rule $rule * @param Mage_Sales_Model_Quote_Address $address * @return bool */ protected function _canProcessRule($rule, $address) { if ($rule->hasIsValidForAddress($address) && !$address->isObjectNew()) { return $rule->getIsValidForAddress($address); } /** * check per coupon usage limit */ if ($rule->getCouponType() != Mage_SalesRule_Model_Rule::COUPON_TYPE_NO_COUPON) { $couponCode = $address->getQuote()->getCouponCode(); if ($couponCode) { $coupon = Mage::getModel('salesrule/coupon'); $coupon->load($couponCode, 'code'); if ($coupon->getId()) { // check entire usage limit if ($coupon->getUsageLimit() && $coupon->getTimesUsed() >= $coupon->getUsageLimit()) { $rule->setIsValidForAddress($address, false); return false; } // check per customer usage limit $customerId = $address->getQuote()->getCustomerId(); if ($customerId && $coupon->getUsagePerCustomer()) { $couponUsage = new Varien_Object(); Mage::getResourceModel('salesrule/coupon_usage')->loadByCustomerCoupon( $couponUsage, $customerId, $coupon->getId()); if ($couponUsage->getCouponId() && $couponUsage->getTimesUsed() >= $coupon->getUsagePerCustomer() ) { $rule->setIsValidForAddress($address, false); return false; } } } } } /** * check per rule usage limit */ $ruleId = $rule->getId(); if ($ruleId && $rule->getUsesPerCustomer()) { $customerId = $address->getQuote()->getCustomerId(); $ruleCustomer = Mage::getModel('salesrule/rule_customer'); $ruleCustomer->loadByCustomerRule($customerId, $ruleId); if ($ruleCustomer->getId()) { if ($ruleCustomer->getTimesUsed() >= $rule->getUsesPerCustomer()) { $rule->setIsValidForAddress($address, false); return false; } } } $rule->afterLoad(); /** * quote does not meet rule's conditions */ if (!$rule->validate($address)) { $rule->setIsValidForAddress($address, false); return false; } /** * passed all validations, remember to be valid */ $rule->setIsValidForAddress($address, true); return true; }
/** * Try to associate reminder rule with matched customers. * If customer was added earlier, update is_active column. * * @param Bronto_Reminder_Model_Rule $rule * @param null|Mage_SalesRule_Model_Rule $salesRule * @param int $websiteId * @param null $threshold * * @return $this * @throws Exception */ public function saveMatchedCustomers(Bronto_Reminder_Model_Rule $rule, $salesRule, $websiteId, $threshold = null) { $select = $rule->getConditions()->getConditionsSql($rule, $websiteId); $interval = Mage::helper('bronto_reminder')->getCronInterval(); if (!$rule->getConditionSql()) { return $this; } if ($threshold) { $select->where('c.emails_failed IS NULL OR c.emails_failed < ? ', $threshold); } // Only pull for reminders not already attached to an active record $select->where('c.is_active IS NULL OR c.is_active <> 1'); // Handle Send Limit $sendLimit = $rule->getSendLimit(); if ($sendLimit > 0) { $subSelect = $this->createSelect()->from(array($this->getTable('bronto_reminder/log')), array('num_send' => 'count(log_id)', 'unique_id'))->group(array('unique_id')); $select->joinLeft(array('l' => $subSelect), 'c.unique_id=l.unique_id', array())->where('l.num_send IS NULL OR l.num_send < ?', $sendLimit); } // Handle Send To Value switch ($rule->getSendTo()) { case 'user': $select->where('`root`.`customer_id` IS NOT NULL AND `root`.`customer_id` != 0'); break; case 'guest': $select->where('`root`.`customer_id` IS NULL OR `root`.`customer_id` = 0'); break; case 'both': default: // No need to filter break; } $i = 0; $ruleId = $rule->getId(); $adapter = $this->_getWriteAdapter(); $currentDate = $this->formatDate(time()); $dataToInsert = array(); Mage::helper('bronto_reminder')->writeDebug('ruleId: ' . $rule->getId() . ' website: ' . $websiteId, 'bronto_reminder_sql.log'); // Log the query with binds replaced $this->logFullQuery($select, array('rule_id' => $ruleId, 'interval' => $interval)); /* @var $stmt Varien_Db_Statement_Pdo_Mysql */ $stmt = $adapter->query($select, array('rule_id' => $ruleId, 'interval' => $interval)); Mage::helper('bronto_reminder')->writeDebug('saveMatchedCustomers():', 'bronto_reminder_sql.log'); try { $adapter->beginTransaction(); while ($row = $stmt->fetch()) { if (empty($row['coupon_id']) && $salesRule) { if ($salesRule->getCouponType() == Mage_SalesRule_Model_Rule::COUPON_TYPE_SPECIFIC && $salesRule->getUseAutoGeneration()) { $coupons = $salesRule->getCoupons(); if (!$coupons) { $coupons = array(); } foreach ($coupons as $couponTemp) { if ($couponTemp->getUsageLimit() > $couponTemp->getTimesUsed() && (is_null($couponTemp->getExpirationDate()) || $couponTemp->getExpirationDate() > date('Y-m-d H:i:s', mktime(0, 0, 0, date('m'), date('d'), date('Y'))))) { $coupon = $couponTemp; } } } else { $coupon = $salesRule->acquireCoupon(); } $couponId = $coupon !== null ? $coupon->getId() : null; } else { $couponId = $row['coupon_id']; } $dataToInsert[] = array('rule_id' => $ruleId, 'product_recommendation_id' => $rule->getProductRecommendationId(), 'coupon_id' => $couponId, 'unique_id' => $row['unique_id'], 'store_id' => $row['store_id'], 'customer_id' => $row['customer_id'], 'quote_id' => $row['quote_id'], 'wishlist_id' => $row['wishlist_id'], 'customer_email' => $row['customer_email'], 'associated_at' => $currentDate, 'is_active' => '1'); $i++; if ($i % 1000 == 0) { $this->_saveMatchedCustomerData($dataToInsert); $adapter->commit(); $adapter->beginTransaction(); $dataToInsert = array(); } } $this->_saveMatchedCustomerData($dataToInsert); $adapter->commit(); Mage::helper('bronto_reminder')->writeDebug(" Query Matched {$i} customers", 'bronto_reminder_sql.log'); } catch (Exception $e) { $adapter->rollBack(); throw $e; } return $this; }