/** * Update auto generated Specific Coupon if it's rule changed * * @param Mage_SalesRule_Model_Rule $rule * @return Mage_SalesRule_Model_Resource_Coupon */ public function updateSpecificCoupons(Mage_SalesRule_Model_Rule $rule) { if (!$rule || !$rule->getId() || !$rule->hasDataChanges()) { return $this; } $updateArray = array(); if ($rule->dataHasChangedFor('uses_per_coupon')) { $updateArray['usage_limit'] = $rule->getUsesPerCoupon(); } if ($rule->dataHasChangedFor('uses_per_customer')) { $updateArray['usage_per_customer'] = $rule->getUsesPerCustomer(); } $ruleNewDate = new Zend_Date($rule->getToDate()); $ruleOldDate = new Zend_Date($rule->getOrigData('to_date')); if ($ruleNewDate->compare($ruleOldDate)) { $updateArray['expiration_date'] = $rule->getToDate(); } if (!empty($updateArray)) { $this->_getWriteAdapter()->update($this->getTable('salesrule/coupon'), $updateArray, array('rule_id = ?' => $rule->getId(), 'generated_by_dotmailer is null')); } //update coupons added by dotmailer. not to change expiration date $dotmailerUpdateArray = $updateArray; unset($dotmailerUpdateArray['expiration_date']); if (!empty($dotmailerUpdateArray)) { $this->_getWriteAdapter()->update($this->getTable('salesrule/coupon'), $dotmailerUpdateArray, array('rule_id = ?' => $rule->getId(), 'generated_by_dotmailer is 1')); } 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 (strlen($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; }
/** * Validate the rule usage for given address * @param Mage_SalesRule_Model_Rule * @param Mage_Sales_Model_Quote_Address * @return bool */ protected function isValidRuleUsageForAddress(Mage_SalesRule_Model_Rule $rule, Mage_Sales_Model_Quote_Address $address) { $ruleId = $rule->getId(); $customerId = $address->getQuote()->getCustomerId(); $ruleCustomer = $this->getRuleCustomerModel(); $ruleCustomer->loadByCustomerRule($customerId, $ruleId); if ($ruleCustomer->getId() && $ruleCustomer->getTimesUsed() >= $rule->getUsesPerCustomer()) { return false; } return true; }
/** * Update auto generated Specific Coupon if it's rule changed * * @param Mage_SalesRule_Model_Rule $rule * @return Mage_SalesRule_Model_Resource_Coupon */ public function updateSpecificCoupons(Mage_SalesRule_Model_Rule $rule) { if (!$rule || !$rule->getId() || !$rule->hasDataChanges()) { return $this; } $updateArray = array(); if ($rule->dataHasChangedFor('uses_per_coupon')) { $updateArray['usage_limit'] = $rule->getUsesPerCoupon(); } if ($rule->dataHasChangedFor('uses_per_customer')) { $updateArray['usage_per_customer'] = $rule->getUsesPerCustomer(); } $ruleNewDate = new Zend_Date($rule->getToDate()); $ruleOldDate = new Zend_Date($rule->getOrigData('to_date')); if ($ruleNewDate->compare($ruleOldDate)) { $updateArray['expiration_date'] = $rule->getToDate(); } if (!empty($updateArray)) { $this->_getWriteAdapter()->update($this->getTable('salesrule_coupon'), $updateArray, array('rule_id = ?' => $rule->getId())); } return $this; }
/** * 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); }
/** * Validates conditions in the "Rule Information" tab of sales rule admin. * * @param Mage_SalesRule_Model_Rule $rule * @param Mage_SalesRule_Model_Coupon $coupon * @return string */ protected function _validateGeneral($rule, $coupon) { if (!$rule->getIsActive()) { Mage::throwException($this->_formatMessage('Your coupon is inactive.')); } // check websites $websiteIds = $rule->getWebsiteIds(); if (!in_array($this->_getQuote()->getStore()->getWebsiteId(), $websiteIds)) { $websiteNames = Mage::getResourceModel('core/website_collection')->addFieldToFilter('website_id', array('in' => $websiteIds))->getColumnValues('name'); Mage::throwException($this->_formatMessage('Your coupon is not valid for this store.', implode(', ', $websiteNames), 'Allowed Websites: %s.')); } // check customer groups $groupIds = $rule->getCustomerGroupIds(); if (!in_array($this->_getQuote()->getCustomerGroupId(), $groupIds)) { $customerGroupNames = Mage::getResourceModel('customer/group_collection')->addFieldToFilter('customer_group_id', array('in' => $groupIds))->getColumnValues('customer_group_code'); Mage::throwException($this->_formatMessage('Your coupon is not valid for your Customer Group.', implode(', ', $customerGroupNames), 'Allowed Customer Groups: %s.')); } // check dates $now = new Zend_Date(Mage::getModel('core/date')->timestamp(time()), Zend_Date::TIMESTAMP); // check from date if ($rule->getFromDate()) { $fromDate = new Zend_Date($rule->getFromDate(), Varien_Date::DATE_INTERNAL_FORMAT); if ($now->isEarlier($fromDate, Zend_Date::DATE_MEDIUM)) { Mage::throwException($this->_formatMessage('Your coupon is not valid yet. It will be active on %s.', Mage::helper('core')->formatDate($fromDate, Mage_Core_Model_Locale::FORMAT_TYPE_LONG), '')); } } // check to date if ($rule->getToDate()) { $toDate = new Zend_Date($rule->getToDate(), Varien_Date::DATE_INTERNAL_FORMAT); if ($now->isLater($toDate, Zend_Date::DATE_MEDIUM)) { Mage::throwException($this->_formatMessage('Your coupon is no longer valid. It expired on %s.', Mage::helper('core')->formatDate($toDate, Mage_Core_Model_Locale::FORMAT_TYPE_LONG), '')); } } // magemail coupon-level auto-expiration date $isCouponAlreadyUsed = $coupon->getUsageLimit() && $coupon->getTimesUsed() >= $coupon->getUsageLimit(); if ($coupon->getdata('magemail_expired_at') && $isCouponAlreadyUsed) { $expirationDate = Mage::getSingleton('core/date')->date('M d, Y', $coupon->getdata('magemail_expired_at')); Mage::throwException($this->_formatMessage('Your coupon is no longer valid. It expired on %s.', $expirationDate)); } // check global usage limit if ($coupon->getUsageLimit() && $coupon->getTimesUsed() >= $coupon->getUsageLimit()) { Mage::throwException($this->_formatMessage('Your coupon was already used.', $coupon->getUsageLimit(), sprintf('It may only be used %d time(s).', $coupon->getUsageLimit()))); } // check per customer usage limit $customerId = $this->_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()) { Mage::throwException($this->_formatMessage('You have already used your coupon.', $coupon->getUsageLimit(), sprintf('It may only be used %d time(s).', $coupon->getUsagePerCustomer()))); } } // check per rule usage limit $ruleId = $rule->getId(); if ($ruleId && $rule->getUsesPerCustomer()) { $ruleCustomer = Mage::getModel('salesrule/rule_customer'); $ruleCustomer->loadByCustomerRule($customerId, $ruleId); if ($ruleCustomer->getId()) { if ($ruleCustomer->getTimesUsed() >= $rule->getUsesPerCustomer()) { Mage::throwException($this->_formatMessage('You have already used your coupon.', $coupon->getUsageLimit(), sprintf('It may only be used %d time(s).', $coupon->getUsagePerCustomer()))); } } } }
/** * 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->hasIsValid()) { /** * too many times used in general */ if ($rule->getUsesPerCoupon() && $rule->getTimesUsed() >= $rule->getUsesPerCoupon()) { $rule->setIsValid(false); return false; } /** * too many times used for this customer */ $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->setIsValid(false); return false; } } } $rule->afterLoad(); /** * quote does not meet rule's conditions */ if (!$rule->validate($address)) { $rule->setIsValid(false); return false; } /** * passed all validations, remember to be valid */ $rule->setIsValid(true); } return $rule->getIsValid(); }