/** * Calculate tax for each product * * @param Mage_Sales_Model_Quote_Item_Abstract $item * @param type $rate * @return Magestore_Magestore_Model_Total_Quote_Tax */ protected function _calcUnitTaxAmount(Mage_Sales_Model_Quote_Item_Abstract $item, $rate) { $discount = $item->getDiscountAmount(); $baseDiscount = $item->getBaseDiscountAmount(); if ($item->getIsPriceInclTax()) { $item->setMagestoreDiscountTax($this->_calculator->calcTaxAmount($item->getMagestoreDiscount(), $rate, false, false)); $item->setMagestoreBaseDiscountTax($this->_calculator->calcTaxAmount($item->getMagestoreBaseDiscount(), $rate, false, false)); } $item->setDiscountAmount($discount + $item->getMagestoreDiscount() + $item->getMagestoreDiscountTax()); $item->setBaseDiscountAmount($baseDiscount + $item->getMagestoreDiscount() + $item->getMagestoreBaseDiscountTax()); parent::_calcUnitTaxAmount($item, $rate); $afterDiscount = (bool) Mage::getStoreConfig(Mage_Tax_Model_Config::CONFIG_XML_PATH_APPLY_AFTER_DISCOUNT, $this->_store); if ($item->getIsPriceInclTax() && $afterDiscount) { foreach ($this->_hiddenTaxes as $key => $taxInfoItem) { if (isset($taxInfoItem['item']) && $item->getId() == $taxInfoItem['item']->getId() && $taxInfoItem['value'] >= $item->getMagestoreDiscountTax() && $item->getMagestoreDiscountTax() > 0) { $this->_hiddenTaxes[$key]['value'] = $taxInfoItem['value'] - $item->getMagestoreDiscountTax(); $this->_hiddenTaxes[$key]['base_value'] = $taxInfoItem['base_value'] - $item->getMagestoreBaseDiscountTax(); break; } } //fix 1.4 if ($item->getHiddenTaxAmount()) { $item->setHiddenTaxAmount($item->getHiddenTaxAmount() - $item->getMagestoreDiscountTax()); $item->setBaseHiddenTaxAmount($item->getBaseHiddenTaxAmount() - $item->getMagestoreBaseDiscountTax()); } } $item->setDiscountAmount($discount); $item->setBaseDiscountAmount($baseDiscount); return $this; }
/** * Calculate tax for each product * * @param Mage_Sales_Model_Quote_Item_Abstract $item * @param type $rate * @return Magestore_Customerreward_Model_Total_Quote_Tax */ protected function _calcUnitTaxAmount(Mage_Sales_Model_Quote_Item_Abstract $item, $rate) { $discount = $item->getDiscountAmount(); $baseDiscount = $item->getBaseDiscountAmount(); $item->setDiscountAmount($discount + $item->getAffiliateplusAmount() + $item->getCustomerrewardAmount()); $item->setBaseDiscountAmount($baseDiscount + $item->getBaseAffiliateplusAmount() + $item->getBaseCustomerrewardAmount()); parent::_calcUnitTaxAmount($item, $rate); $item->setDiscountAmount($discount); $item->setBaseDiscountAmount($baseDiscount); return $this; }
/** * Calculate tax for each product * * @param Mage_Sales_Model_Quote_Item_Abstract $item * @param type $rate * @return Magestore_Customerreward_Model_Total_Quote_Tax */ protected function _calcUnitTaxAmount(Mage_Sales_Model_Quote_Item_Abstract $item, $rate, &$taxGroups = null, $taxId = null, $recalculateRowTotalInclTax = false) { $discount = $item->getDiscountAmount(); $baseDiscount = $item->getBaseDiscountAmount(); /* hainh add this for calculating discount base on incl or excl tax price 22-04-2014 */ if (!$this->_discountIncludeTax()) { $item->setDiscountAmount($discount + $item->getAffiliateplusAmount() + $item->getCustomerrewardAmount()); $item->setBaseDiscountAmount($baseDiscount + $item->getBaseAffiliateplusAmount() + $item->getBaseCustomerrewardAmount()); } parent::_calcUnitTaxAmount($item, $rate, $taxGroups, $taxId, $recalculateRowTotalInclTax); $item->setDiscountAmount($discount); $item->setBaseDiscountAmount($baseDiscount); return $this; }
public function process(Mage_Sales_Model_Quote_Item_Abstract $item) { $item->setDiscountAmount(0); $item->setBaseDiscountAmount(0); $item->setDiscountPercent(0); $quote = $item->getQuote(); $address = $this->_getAddress($item); $qty = $item->getTotalQty(); $itemPrice = $this->_getItemPrice($item); $baseItemPrice = $this->_getItemBasePrice($item); $itemOriginalPrice = $this->_getItemOriginalPrice($item); $baseItemOriginalPrice = $this->_getItemBaseOriginalPrice($item); if ($itemPrice < 0) { return $this; } if ($this->_totaldiscountpay > 0) { if ($this->_rulesItemTotalspay['giftcardpay']['items_count'] <= 1) { $quoteAmount = $quote->getStore()->convertPrice($this->_totaldiscountpay); $baseDiscountAmount = min($baseItemPrice * $qty, $this->_totaldiscountpay); } else { $discountRate = $baseItemPrice * $qty / $this->_rulesItemTotalspay['giftcardpay']['base_items_price']; $maximumItemDiscount = $this->_totaldiscountpay * $discountRate; $quoteAmount = $quote->getStore()->convertPrice($maximumItemDiscount); $baseDiscountAmount = min($baseItemPrice * $qty, $maximumItemDiscount); $this->_rulesItemTotalspay['giftcardpay']['items_count']--; } $discountAmount = min($itemPrice * $qty, $quoteAmount); $discountAmount = $quote->getStore()->roundPrice($discountAmount); $baseDiscountAmount = $quote->getStore()->roundPrice($baseDiscountAmount); //get discount for original price $originalDiscountAmount = min($itemOriginalPrice * $qty, $quoteAmount); $baseOriginalDiscountAmount = $quote->getStore()->roundPrice($baseItemOriginalPrice); $this->_totaldiscountpay -= $baseDiscountAmount; } $itemDiscountAmount = $item->getDiscountAmount(); $itemBaseDiscountAmount = $item->getBaseDiscountAmount(); $discountAmount = min($itemDiscountAmount + $discountAmount, $itemPrice * $qty); $baseDiscountAmount = min($itemBaseDiscountAmount + $baseDiscountAmount, $baseItemPrice * $qty); $item->getGiftCardEarn($discountAmount); $item->getGiftCardBaseEarn($discountAmount); $baseTaxableAmount = $item->getBaseTaxableAmount(); $taxableAmount = $item->getTaxableAmount(); $item->setBaseTaxableAmount(max(0, $baseTaxableAmount - $discountAmount)); $item->setTaxableAmount(max(0, $taxableAmount - $discountAmount)); return $this; }
/** * Quote item discount calculation process * * @param Mage_Sales_Model_Quote_Item_Abstract $item * @return Mage_SalesRule_Model_Validator */ public function process(Mage_Sales_Model_Quote_Item_Abstract $item) { $item->setDiscountAmount(0); $item->setBaseDiscountAmount(0); $item->setDiscountPercent(0); $quote = $item->getQuote(); $address = $this->_getAddress($item); $itemPrice = $this->_getItemPrice($item); $baseItemPrice = $this->_getItemBasePrice($item); $itemOriginalPrice = $this->_getItemOriginalPrice($item); $baseItemOriginalPrice = $this->_getItemBaseOriginalPrice($item); if ($itemPrice < 0) { return $this; } $appliedRuleIds = array(); $this->_stopFurtherRules = false; foreach ($this->_getRules() as $rule) { /* @var $rule Mage_SalesRule_Model_Rule */ if (!$this->_canProcessRule($rule, $address)) { continue; } if (!$rule->getActions()->validate($item)) { continue; } $qty = $this->_getItemQty($item, $rule); $rulePercent = min(100, $rule->getDiscountAmount()); $discountAmount = 0; $baseDiscountAmount = 0; //discount for original price $originalDiscountAmount = 0; $baseOriginalDiscountAmount = 0; switch ($rule->getSimpleAction()) { case Mage_SalesRule_Model_Rule::TO_PERCENT_ACTION: $rulePercent = max(0, 100 - $rule->getDiscountAmount()); //no break; //no break; case Mage_SalesRule_Model_Rule::BY_PERCENT_ACTION: $step = $rule->getDiscountStep(); if ($step) { $qty = floor($qty / $step) * $step; } $_rulePct = $rulePercent / 100; $discountAmount = ($qty * $itemPrice - $item->getDiscountAmount()) * $_rulePct; $baseDiscountAmount = ($qty * $baseItemPrice - $item->getBaseDiscountAmount()) * $_rulePct; //get discount for original price $originalDiscountAmount = ($qty * $itemOriginalPrice - $item->getDiscountAmount()) * $_rulePct; $baseOriginalDiscountAmount = ($qty * $baseItemOriginalPrice - $item->getDiscountAmount()) * $_rulePct; if (!$rule->getDiscountQty() || $rule->getDiscountQty() > $qty) { $discountPercent = min(100, $item->getDiscountPercent() + $rulePercent); $item->setDiscountPercent($discountPercent); } break; case Mage_SalesRule_Model_Rule::TO_FIXED_ACTION: $quoteAmount = $quote->getStore()->convertPrice($rule->getDiscountAmount()); $discountAmount = $qty * ($itemPrice - $quoteAmount); $baseDiscountAmount = $qty * ($baseItemPrice - $rule->getDiscountAmount()); //get discount for original price $originalDiscountAmount = $qty * ($itemOriginalPrice - $quoteAmount); $baseOriginalDiscountAmount = $qty * ($baseItemOriginalPrice - $rule->getDiscountAmount()); break; case Mage_SalesRule_Model_Rule::BY_FIXED_ACTION: $step = $rule->getDiscountStep(); if ($step) { $qty = floor($qty / $step) * $step; } $quoteAmount = $quote->getStore()->convertPrice($rule->getDiscountAmount()); $discountAmount = $qty * $quoteAmount; $baseDiscountAmount = $qty * $rule->getDiscountAmount(); break; case Mage_SalesRule_Model_Rule::CART_FIXED_ACTION: if (empty($this->_rulesItemTotals[$rule->getId()])) { Mage::throwException(Mage::helper('salesrule')->__('Item totals are not set for rule.')); } /** * prevent applying whole cart discount for every shipping order, but only for first order */ if ($quote->getIsMultiShipping()) { $usedForAddressId = $this->getCartFixedRuleUsedForAddress($rule->getId()); if ($usedForAddressId && $usedForAddressId != $address->getId()) { break; } else { $this->setCartFixedRuleUsedForAddress($rule->getId(), $address->getId()); } } $cartRules = $address->getCartFixedRules(); if (!isset($cartRules[$rule->getId()])) { $cartRules[$rule->getId()] = $rule->getDiscountAmount(); } if ($cartRules[$rule->getId()] > 0) { if ($this->_rulesItemTotals[$rule->getId()]['items_count'] <= 1) { $quoteAmount = $quote->getStore()->convertPrice($cartRules[$rule->getId()]); $baseDiscountAmount = min($baseItemPrice * $qty, $cartRules[$rule->getId()]); } else { $discountRate = $baseItemPrice * $qty / $this->_rulesItemTotals[$rule->getId()]['base_items_price']; $maximumItemDiscount = $rule->getDiscountAmount() * $discountRate; $quoteAmount = $quote->getStore()->convertPrice($maximumItemDiscount); $baseDiscountAmount = min($baseItemPrice * $qty, $maximumItemDiscount); $this->_rulesItemTotals[$rule->getId()]['items_count']--; } $discountAmount = min($itemPrice * $qty, $quoteAmount); $discountAmount = $quote->getStore()->roundPrice($discountAmount); $baseDiscountAmount = $quote->getStore()->roundPrice($baseDiscountAmount); //get discount for original price $originalDiscountAmount = min($itemOriginalPrice * $qty, $quoteAmount); $baseOriginalDiscountAmount = $quote->getStore()->roundPrice($baseItemOriginalPrice); $cartRules[$rule->getId()] -= $baseDiscountAmount; } $address->setCartFixedRules($cartRules); break; case Mage_SalesRule_Model_Rule::BUY_X_GET_Y_ACTION: $x = $rule->getDiscountStep(); $y = $rule->getDiscountAmount(); if (!$x || $y > $x) { break; } $buyAndDiscountQty = $x + $y; $fullRuleQtyPeriod = floor($qty / $buyAndDiscountQty); $freeQty = $qty - $fullRuleQtyPeriod * $buyAndDiscountQty; $discountQty = $fullRuleQtyPeriod * $y; if ($freeQty > $x) { $discountQty += $freeQty - $x; } $discountAmount = $discountQty * $itemPrice; $baseDiscountAmount = $discountQty * $baseItemPrice; //get discount for original price $originalDiscountAmount = $discountQty * $itemOriginalPrice; $baseOriginalDiscountAmount = $discountQty * $baseItemOriginalPrice; break; } $result = new Varien_Object(array('discount_amount' => $discountAmount, 'base_discount_amount' => $baseDiscountAmount)); Mage::dispatchEvent('salesrule_validator_process', array('rule' => $rule, 'item' => $item, 'address' => $address, 'quote' => $quote, 'qty' => $qty, 'result' => $result)); $discountAmount = $result->getDiscountAmount(); $baseDiscountAmount = $result->getBaseDiscountAmount(); $percentKey = $item->getDiscountPercent(); /** * Process "delta" rounding */ if ($percentKey) { $delta = isset($this->_roundingDeltas[$percentKey]) ? $this->_roundingDeltas[$percentKey] : 0; $baseDelta = isset($this->_baseRoundingDeltas[$percentKey]) ? $this->_baseRoundingDeltas[$percentKey] : 0; $discountAmount += $delta; $baseDiscountAmount += $baseDelta; $this->_roundingDeltas[$percentKey] = $discountAmount - $quote->getStore()->roundPrice($discountAmount); $this->_baseRoundingDeltas[$percentKey] = $baseDiscountAmount - $quote->getStore()->roundPrice($baseDiscountAmount); $discountAmount = $quote->getStore()->roundPrice($discountAmount); $baseDiscountAmount = $quote->getStore()->roundPrice($baseDiscountAmount); } else { $discountAmount = $quote->getStore()->roundPrice($discountAmount); $baseDiscountAmount = $quote->getStore()->roundPrice($baseDiscountAmount); } /** * We can't use row total here because row total not include tax * Discount can be applied on price included tax */ $itemDiscountAmount = $item->getDiscountAmount(); $itemBaseDiscountAmount = $item->getBaseDiscountAmount(); $discountAmount = min($itemDiscountAmount + $discountAmount, $itemPrice * $qty); $baseDiscountAmount = min($itemBaseDiscountAmount + $baseDiscountAmount, $baseItemPrice * $qty); $item->setDiscountAmount($discountAmount); $item->setBaseDiscountAmount($baseDiscountAmount); $item->setOriginalDiscountAmount($originalDiscountAmount); $item->setBaseOriginalDiscountAmount($baseOriginalDiscountAmount); $appliedRuleIds[$rule->getRuleId()] = $rule->getRuleId(); $this->_maintainAddressCouponCode($address, $rule); $this->_addDiscountDescription($address, $rule); if ($rule->getStopRulesProcessing()) { $this->_stopFurtherRules = true; break; } } $item->setAppliedRuleIds(join(',', $appliedRuleIds)); $address->setAppliedRuleIds($this->mergeIds($address->getAppliedRuleIds(), $appliedRuleIds)); $quote->setAppliedRuleIds($this->mergeIds($quote->getAppliedRuleIds(), $appliedRuleIds)); return $this; }
protected function resetItem(Mage_Sales_Model_Quote_Item_Abstract $item) { $item->setDiscountAmount(0.0); $item->setBaseDiscountAmount(0.0); $item->setRowTotalWithDiscount($item->getRowTotal()); $item->setBaseRowTotalWithDiscount($item->getBaseRowTotal()); $item->setDiscountPercent(0); $item->setAppliedRuleIds(''); $item->setFreeShipping(false); }
public function apply(Mage_Sales_Model_Quote_Item_Abstract $item) { # Do not apply any discount if Ext is Disabled if (Mage::helper('referafriend')->getExtDisabled()) { return $this; } $this->_quote = $quote = $item->getQuote(); if ($item instanceof Mage_Sales_Model_Quote_Address_Item) { $address = $item->getAddress(); } elseif ($quote->isVirtual()) { $address = $quote->getBillingAddress(); } else { $address = $quote->getShippingAddress(); } # allow additional discount logic start $hasAdditional = $item->getQuote()->getCouponCode() ? true : false; $helper = Mage::helper('referafriend/referrer'); $baseSubtotal = $address->getBaseSubtotal(); $clearUse = array(); if (!$this->_discount) { Mage::helper('referafriend')->setCustomerDiscount(0); $customer = $quote->getCustomer(); $referrerId = $customer->getId(); $discounts = Mage::getResourceModel('referafriend/discount_collection')->loadByReferrer($referrerId); if (count($discounts)) { foreach ($discounts as $discount) { $rule = Mage::getSingleton('referafriend/rule')->load($discount->getRuleId()); if ($rule->getDiscountUsage() == 0 || $rule->getDiscountUsage() > $discount->getDiscountUsed()) { # allow additional discount logic if ($hasAdditional && $rule->getAllowAdditionalDiscount() || !$hasAdditional) { $this->_discount[$discount->getId()] = $discount; } else { $clearUse[] = $discount->getId(); } } } } } if (!count($this->_discount)) { # Reset used discount $customer = Mage::getSingleton('customer/session'); if ($customer->isLoggedIn()) { $customer->setDiscountUsed(array()); } return $this; } $this->_getCouponCode(); // $this->_couponCode = $this->_getCouponCode(); $customer = Mage::getSingleton('customer/session'); if ($customer->isLoggedIn()) { $discountUsed = (array) $customer->getDiscountUsed(); } $rafDiscount = Mage::helper('referafriend')->getCustomerDiscount(false) ? Mage::helper('referafriend')->getCustomerDiscount(false) : 0; $notUsed = array(); foreach ($this->_discount as $discountId => $discount) { $discountAmount = 0; $baseDiscountAmount = 0; $rule = Mage::getModel('referafriend/rule')->load($discount->getRuleId()); switch ($discount->getType()) { case self::TYPE_PERCENT: $discountPercent = min(100, $discount->getAmount()); $discountAmount = ($item->getRowTotal() - $item->getDiscountAmount()) * $discountPercent / 100; $baseDiscountAmount = ($item->getBaseRowTotal() - $item->getBaseDiscountAmount()) * $discountPercent / 100; $checkDiscountAmount = $baseSubtotal * $discountPercent / 100; if (!($rule->getDiscountGreater() && $checkDiscountAmount < $rule->getDiscountGreater()) && !($rule->getTotalGreater() && $baseSubtotal < $rule->getTotalGreater())) { if (isset($discountUsed)) { if (!isset($discountUsed[$discountId])) { $discountUsed[$discountId] = false; } } $rafDiscount += $baseDiscountAmount; $discountAmount = min($discountAmount + $item->getDiscountAmount(), $item->getRowTotal()); $baseDiscountAmount = min($baseDiscountAmount + $item->getBaseDiscountAmount(), $item->getBaseRowTotal()); //$discountPercent = min(100, $item->getDiscountPercent()+$percentDiscount); $item->setDiscountPercent(min(100, $item->getDiscountPercent() + $discountPercent)); $discountAmount = $quote->getStore()->roundPrice($discountAmount); $baseDiscountAmount = $quote->getStore()->roundPrice($baseDiscountAmount); $item->setDiscountAmount($discountAmount); $item->setBaseDiscountAmount($baseDiscountAmount); } else { $notUsed[] = $discountId; if (isset($discountUsed[$discountId])) { unset($discountUsed[$discountId]); } } break; case self::TYPE_FLATRATE: $discountAmount = min($item->getRowTotal() - $item->getDiscountAmount(), $quote->getStore()->convertPrice($discount->getAmount())); $baseDiscountAmount = min($item->getBaseRowTotal() - $item->getBaseDiscountAmount(), $discount->getAmount()); $checkDiscountAmount = $discount->getAmount(); if (!($rule->getDiscountGreater() && $checkDiscountAmount < $rule->getDiscountGreater()) && !($rule->getTotalGreater() && $baseSubtotal < $rule->getTotalGreater())) { if (isset($discountUsed)) { if (!isset($discountUsed[$discountId])) { $discountUsed[$discountId] = false; } } $rafDiscount += $baseDiscountAmount; $this->_discount[$discountId]->setAmount($discount->getAmount() - $baseDiscountAmount); /*$discountAmount = $quote->getStore()->roundPrice($discountAmount); $baseDiscountAmount = $quote->getStore()->roundPrice($baseDiscountAmount);*/ $discountAmount = min($discountAmount + $item->getDiscountAmount(), $item->getRowTotal()); $baseDiscountAmount = min($baseDiscountAmount + $item->getBaseDiscountAmount(), $item->getBaseRowTotal()); $item->setDiscountAmount($discountAmount); $item->setBaseDiscountAmount($baseDiscountAmount); } else { $notUsed[] = $discountId; if (isset($discountUsed[$discountId])) { unset($discountUsed[$discountId]); } } break; } } $trueDiscounts = Mage::helper('referafriend')->getTrueDiscount(); if (isset($trueDiscounts[$item->getId()]['discounts'][1])) { $item->setDiscountAmount($trueDiscounts[$item->getId()]['discounts'][1]); } Mage::helper('referafriend')->setTrueDiscount($item->getId(), $item->getDiscountAmount()); if (!$this->_couponCode) { $this->_couponCode = $this->_getPostCouponCode($notUsed); } $couponCode = explode(', ', $address->getCouponCode()); $couponCode[] = $helper->getCouponCodeDescription($this->_couponCode); $couponCode = array_unique(array_filter($couponCode)); $address->setCouponCode(implode(', ', $couponCode)); # injectin to Discount Description Array directly if (Mage::helper('referafriend')->checkVersion('1.4.0.0')) { $arr = array(); $arr[1] = implode(', ', $couponCode); $address->setDiscountDescriptionArray($arr); } # put discount amount in session store for future history Mage::helper('referafriend')->setCustomerDiscount($rafDiscount); if (count($clearUse) && $discountUsed && is_array($discountUsed) && count($discountUsed)) { foreach ($clearUse as $discountId) { if (isset($discountUsed[$discountId])) { unset($discountUsed[$discountId]); } } } if (isset($discountUsed)) { $customer->setDiscountUsed($discountUsed); } return $this; }
public function process(Mage_Sales_Model_Quote_Item_Abstract $item) { $item->setFreeShipping(false); $item->setDiscountAmount(0); $item->setBaseDiscountAmount(0); $item->setDiscountPercent(0); $quote = $item->getQuote(); $address = $item->getAddress(); if (!$address) { $address = $item->getQuote()->getShippingAddress(); } $customerId = $quote->getCustomerId(); $ruleCustomer = Mage::getModel('salesrule/rule_customer'); $appliedRuleIds = array(); foreach ($this->_rules as $rule) { /** * already tried to validate and failed */ if ($rule->getIsValid() === false) { continue; } if ($rule->getIsValid() !== true) { /** * too many times used in general */ if ($rule->getUsesPerCoupon() && $rule->getTimesUsed() >= $rule->getUsesPerCoupon()) { $rule->setIsValid(false); continue; } /** * too many times used for this customer */ if ($ruleId = $rule->getId()) { $ruleCustomer->loadByCustomerRule($customerId, $ruleId); if ($ruleCustomer->getId()) { if ($ruleCustomer->getTimesUsed() >= $rule->getUsesPerCustomer()) { continue; } } } $rule->afterLoad(); /** * quote does not meet rule's conditions */ if (!$rule->validate($address)) { $rule->setIsValid(false); continue; } /** * passed all validations, remember to be valid */ $rule->setIsValid(true); } /** * although the rule is valid, this item is not marked for action */ if (!$rule->getActions()->validate($item)) { continue; } $qty = $rule->getDiscountQty() ? min($item->getQty(), $rule->getDiscountQty()) : $item->getQty(); $rulePercent = $rule->getDiscountAmount(); switch ($rule->getSimpleAction()) { case 'to_percent': $rulePercent = max(0, 100 - $rule->getDiscountAmount()); //no break; //no break; case 'by_percent': $discountAmount = $qty * $item->getCalculationPrice() * $rulePercent / 100; $baseDiscountAmount = $qty * $item->getBaseCalculationPrice() * $rulePercent / 100; if (!$rule->getDiscountQty()) { $discountPercent = min(100, $item->getDiscountPercent() + $rulePercent); $item->setDiscountPercent($discountPercent); } break; case 'to_fixed': $quoteAmount = $quote->getStore()->convertPrice($rule->getDiscountAmount()); $discountAmount = $qty * ($item->getCalculationPrice() - $quoteAmount); $baseDiscountAmount = $qty * ($item->getBaseCalculationPrice() - $rule->getDiscountAmount()); break; case 'by_fixed': $quoteAmount = $quote->getStore()->convertPrice($rule->getDiscountAmount()); $discountAmount = $qty * $quoteAmount; $baseDiscountAmount = $qty * $rule->getDiscountAmount(); break; } $discountAmount = $quote->getStore()->roundPrice($discountAmount); $baseDiscountAmount = $quote->getStore()->roundPrice($baseDiscountAmount); $discountAmount = min($discountAmount, $item->getRowTotal()); $baseDiscountAmount = min($baseDiscountAmount, $item->getBaseRowTotal()); $item->setDiscountAmount($discountAmount); $item->setBaseDiscountAmount($baseDiscountAmount); switch ($rule->getSimpleFreeShipping()) { case Mage_SalesRule_Model_Rule::FREE_SHIPPING_ITEM: $item->setFreeShipping($rule->getDiscountQty() ? $rule->getDiscountQty() : true); break; case Mage_SalesRule_Model_Rule::FREE_SHIPPING_ADDRESS: $address->setFreeShipping(true); break; } $appliedRuleIds[$rule->getRuleId()] = $rule->getRuleId(); if ($rule->getStopRulesProcessing()) { break; } if ($rule->getCouponCode() && $rule->getCouponCode() == $this->getCouponCode()) { $address->setCouponCode($this->getCouponCode()); } } $item->setAppliedRuleIds(join(',', $appliedRuleIds)); $address->setAppliedRuleIds($this->mergeIds($address->getAppliedRuleIds(), $appliedRuleIds)); $quote->setAppliedRuleIds($this->mergeIds($quote->getAppliedRuleIds(), $appliedRuleIds)); return $this; }
/** * Quote item discount calculation process * * @param Mage_Sales_Model_Quote_Item_Abstract $item * @return Mage_SalesRule_Model_Validator */ public function process(Mage_Sales_Model_Quote_Item_Abstract $item) { $item->setDiscountAmount(0); $item->setBaseDiscountAmount(0); $item->setDiscountPercent(0); $quote = $item->getQuote(); $address = $this->_getAddress($item); //Clearing applied rule ids for quote and address if ($this->_isFirstTimeProcessRun !== true) { $this->_isFirstTimeProcessRun = true; $quote->setAppliedRuleIds(''); $address->setAppliedRuleIds(''); } $itemPrice = $item->getDiscountCalculationPrice(); if ($itemPrice !== null) { $baseItemPrice = $item->getBaseDiscountCalculationPrice(); } else { $itemPrice = $item->getCalculationPrice(); $baseItemPrice = $item->getBaseCalculationPrice(); } $appliedRuleIds = array(); foreach ($this->_getRules() as $rule) { /* @var $rule Mage_SalesRule_Model_Rule */ if (!$this->_canProcessRule($rule, $address)) { continue; } if (!$rule->getActions()->validate($item)) { continue; } $qty = $item->getTotalQty(); $qty = $rule->getDiscountQty() ? min($qty, $rule->getDiscountQty()) : $qty; $rulePercent = min(100, $rule->getDiscountAmount()); $discountAmount = 0; $baseDiscountAmount = 0; switch ($rule->getSimpleAction()) { case 'to_percent': $rulePercent = max(0, 100 - $rule->getDiscountAmount()); //no break; //no break; case 'by_percent': $step = $rule->getDiscountStep(); if ($step) { $qty = floor($qty / $step) * $step; } $discountAmount = ($qty * $itemPrice - $item->getDiscountAmount()) * $rulePercent / 100; $baseDiscountAmount = ($qty * $baseItemPrice - $item->getBaseDiscountAmount()) * $rulePercent / 100; if (!$rule->getDiscountQty() || $rule->getDiscountQty() > $qty) { $discountPercent = min(100, $item->getDiscountPercent() + $rulePercent); $item->setDiscountPercent($discountPercent); } break; case 'to_fixed': $quoteAmount = $quote->getStore()->convertPrice($rule->getDiscountAmount()); $discountAmount = $qty * ($itemPrice - $quoteAmount); $baseDiscountAmount = $qty * ($baseItemPrice - $rule->getDiscountAmount()); break; case 'by_fixed': $step = $rule->getDiscountStep(); if ($step) { $qty = floor($qty / $step) * $step; } $quoteAmount = $quote->getStore()->convertPrice($rule->getDiscountAmount()); $discountAmount = $qty * $quoteAmount; $baseDiscountAmount = $qty * $rule->getDiscountAmount(); break; case 'cart_fixed': $cartRules = $address->getCartFixedRules(); if (!isset($cartRules[$rule->getId()])) { $cartRules[$rule->getId()] = $rule->getDiscountAmount(); } if ($cartRules[$rule->getId()] > 0) { $quoteAmount = $quote->getStore()->convertPrice($cartRules[$rule->getId()]); /** * We can't use row total here because row total not include tax */ $discountAmount = min($itemPrice * $qty - $item->getDiscountAmount(), $quoteAmount); $baseDiscountAmount = min($baseItemPrice * $qty - $item->getBaseDiscountAmount(), $cartRules[$rule->getId()]); $cartRules[$rule->getId()] -= $baseDiscountAmount; } $address->setCartFixedRules($cartRules); break; case 'buy_x_get_y': $x = $rule->getDiscountStep(); $y = $rule->getDiscountAmount(); if (!$x || $y >= $x) { break; } $buy = 0; $free = 0; while ($buy + $free < $qty) { $buy += $x; if ($buy + $free >= $qty) { break; } $free += min($y, $qty - $buy - $free); if ($buy + $free >= $qty) { break; } } $discountAmount = $free * $itemPrice; $baseDiscountAmount = $free * $baseItemPrice; break; } $result = new Varien_Object(array('discount_amount' => $discountAmount, 'base_discount_amount' => $baseDiscountAmount)); Mage::dispatchEvent('salesrule_validator_process', array('rule' => $rule, 'item' => $item, 'address' => $address, 'quote' => $quote, 'qty' => $qty, 'result' => $result)); $discountAmount = $result->getDiscountAmount(); $baseDiscountAmount = $result->getBaseDiscountAmount(); $percentKey = $item->getDiscountPercent(); /** * Process "delta" rounding */ if ($percentKey) { $delta = isset($this->_roundingDeltas[$percentKey]) ? $this->_roundingDeltas[$percentKey] : 0; $baseDelta = isset($this->_baseRoundingDeltas[$percentKey]) ? $this->_baseRoundingDeltas[$percentKey] : 0; $discountAmount += $delta; $baseDiscountAmount += $baseDelta; $this->_roundingDeltas[$percentKey] = $discountAmount - $quote->getStore()->roundPrice($discountAmount); $this->_baseRoundingDeltas[$percentKey] = $baseDiscountAmount - $quote->getStore()->roundPrice($baseDiscountAmount); $discountAmount = $quote->getStore()->roundPrice($discountAmount); $baseDiscountAmount = $quote->getStore()->roundPrice($baseDiscountAmount); } else { $discountAmount = $quote->getStore()->roundPrice($discountAmount); $baseDiscountAmount = $quote->getStore()->roundPrice($baseDiscountAmount); } /** * We can't use row total here because row total not include tax * Discount can be applied on price included tax */ $discountAmount = min($item->getDiscountAmount() + $discountAmount, $itemPrice * $qty); $baseDiscountAmount = min($item->getBaseDiscountAmount() + $baseDiscountAmount, $baseItemPrice * $qty); $item->setDiscountAmount($discountAmount); $item->setBaseDiscountAmount($baseDiscountAmount); $appliedRuleIds[$rule->getRuleId()] = $rule->getRuleId(); $this->_maintainAddressCouponCode($address, $rule); $this->_addDiscountDescription($address, $rule); if ($rule->getStopRulesProcessing()) { break; } } $item->setAppliedRuleIds(join(',', $appliedRuleIds)); $address->setAppliedRuleIds($this->mergeIds($address->getAppliedRuleIds(), $appliedRuleIds)); $quote->setAppliedRuleIds($this->mergeIds($quote->getAppliedRuleIds(), $appliedRuleIds)); return $this; }
/** * Quote item discount calculation process * * @param Mage_Sales_Model_Quote_Item_Abstract $item * @return Mage_SalesRule_Model_Validator */ public function process(Mage_Sales_Model_Quote_Item_Abstract $item) { $item->setDiscountAmount(0); $item->setBaseDiscountAmount(0); $item->setDiscountPercent(0); $quote = $item->getQuote(); $address = $this->_getAddress($item); $itemPrice = $this->_getItemPrice($item); $baseItemPrice = $this->_getItemBasePrice($item); $itemOriginalPrice = $this->_getItemOriginalPrice($item); $baseItemOriginalPrice = $this->_getItemBaseOriginalPrice($item); if ($itemPrice < 0) { return $this; } $appliedRuleIds = array(); foreach ($this->_getRules() as $rule) { /* @var $rule Mage_SalesRule_Model_Rule */ if (!$this->_canProcessRule($rule, $address)) { continue; } if (!$rule->getActions()->validate($item)) { continue; } $qty = $this->_getItemQty($item, $rule); $rulePercent = min(100, $rule->getDiscountAmount()); $discountAmount = 0; $baseDiscountAmount = 0; //discount for original price $originalDiscountAmount = 0; $baseOriginalDiscountAmount = 0; switch ($rule->getSimpleAction()) { case Mage_SalesRule_Model_Rule::TO_PERCENT_ACTION: $rulePercent = max(0, 100 - $rule->getDiscountAmount()); //no break; //no break; case Mage_SalesRule_Model_Rule::BY_PERCENT_ACTION: $step = $rule->getDiscountStep(); if ($step) { $qty = floor($qty / $step) * $step; } $_rulePct = $rulePercent / 100; $discountAmount = ($qty * $itemPrice - $item->getDiscountAmount()) * $_rulePct; $baseDiscountAmount = ($qty * $baseItemPrice - $item->getBaseDiscountAmount()) * $_rulePct; //get discount for original price $originalDiscountAmount = ($qty * $itemOriginalPrice - $item->getDiscountAmount()) * $_rulePct; $baseOriginalDiscountAmount = ($qty * $baseItemOriginalPrice - $item->getDiscountAmount()) * $_rulePct; if (!$rule->getDiscountQty() || $rule->getDiscountQty() > $qty) { $discountPercent = min(100, $item->getDiscountPercent() + $rulePercent); $item->setDiscountPercent($discountPercent); } break; case Mage_SalesRule_Model_Rule::TO_FIXED_ACTION: $quoteAmount = $quote->getStore()->convertPrice($rule->getDiscountAmount()); $discountAmount = $qty * ($itemPrice - $quoteAmount); $baseDiscountAmount = $qty * ($baseItemPrice - $rule->getDiscountAmount()); //get discount for original price $originalDiscountAmount = $qty * ($itemOriginalPrice - $quoteAmount); $baseOriginalDiscountAmount = $qty * ($baseItemOriginalPrice - $rule->getDiscountAmount()); break; case Mage_SalesRule_Model_Rule::BY_FIXED_ACTION: $step = $rule->getDiscountStep(); if ($step) { $qty = floor($qty / $step) * $step; } $quoteAmount = $quote->getStore()->convertPrice($rule->getDiscountAmount()); $discountAmount = $qty * $quoteAmount; $baseDiscountAmount = $qty * $rule->getDiscountAmount(); break; case Mage_SalesRule_Model_Rule::CART_FIXED_ACTION: if (empty($this->_rulesItemTotals[$rule->getId()])) { Mage::throwException(Mage::helper('salesrule')->__('Item totals are not set for rule.')); } /** * prevent applying whole cart discount for every shipping order, but only for first order */ if ($quote->getIsMultiShipping()) { $usedForAddressId = $this->getCartFixedRuleUsedForAddress($rule->getId()); if ($usedForAddressId && $usedForAddressId != $address->getId()) { break; } else { $this->setCartFixedRuleUsedForAddress($rule->getId(), $address->getId()); } } $cartRules = $address->getCartFixedRules(); if (!isset($cartRules[$rule->getId()])) { $cartRules[$rule->getId()] = $rule->getDiscountAmount(); } if ($cartRules[$rule->getId()] > 0) { if ($this->_rulesItemTotals[$rule->getId()]['items_count'] <= 1) { $quoteAmount = $quote->getStore()->convertPrice($cartRules[$rule->getId()]); $baseDiscountAmount = min($baseItemPrice * $qty, $cartRules[$rule->getId()]); } else { $discountRate = $baseItemPrice * $qty / $this->_rulesItemTotals[$rule->getId()]['base_items_price']; $maximumItemDiscount = $rule->getDiscountAmount() * $discountRate; $quoteAmount = $quote->getStore()->convertPrice($maximumItemDiscount); $baseDiscountAmount = min($baseItemPrice * $qty, $maximumItemDiscount); $this->_rulesItemTotals[$rule->getId()]['items_count']--; } $discountAmount = min($itemPrice * $qty, $quoteAmount); $discountAmount = $quote->getStore()->roundPrice($discountAmount); $baseDiscountAmount = $quote->getStore()->roundPrice($baseDiscountAmount); //get discount for original price $originalDiscountAmount = min($itemOriginalPrice * $qty, $quoteAmount); $baseOriginalDiscountAmount = $quote->getStore()->roundPrice($originalDiscountAmount); $baseOriginalDiscountAmount = $quote->getStore()->roundPrice($baseItemOriginalPrice); $cartRules[$rule->getId()] -= $baseDiscountAmount; } $address->setCartFixedRules($cartRules); break; case Mage_SalesRule_Model_Rule::BUY_X_GET_Y_ACTION: $x = $rule->getDiscountStep(); $y = $rule->getDiscountAmount(); if (!$x || $y > $x) { break; } $buyAndDiscountQty = $x + $y; $fullRuleQtyPeriod = floor($qty / $buyAndDiscountQty); $freeQty = $qty - $fullRuleQtyPeriod * $buyAndDiscountQty; $discountQty = $fullRuleQtyPeriod * $y; if ($freeQty > $x) { $discountQty += $freeQty - $x; } $discountAmount = $discountQty * $itemPrice; $baseDiscountAmount = $discountQty * $baseItemPrice; //get discount for original price $originalDiscountAmount = $discountQty * $itemOriginalPrice; $baseOriginalDiscountAmount = $discountQty * $baseItemOriginalPrice; break; case Mage_SalesRule_Model_Rule::GET_BLANKET_FREE: // use $promoImage if you want to have additional image to Promo item, for example: a gift icon. //$promoImage = '<br/><img src="'.Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_SKIN).'\frontend\default\default\images\YOUR_IMAGE.jpg" alt="Promo" title="Promo"/>'; $product = Mage::getModel('catalog/product')->loadByAttribute('sku', "[YOUR_SKU_HERE]"); //simple product only $productId = $product->getId(); $productSku = $product->getSku(); Mage::getModel('cataloginventory/stock_item')->assignProduct($product); $quoteItem = Mage::getModel('sales/quote_item')->setProduct($product); $quoteItem->setQuote($quote)->setQty(1)->setCustomPrice(0.0)->setTaxAmount(0.0)->setTaxPercent(0.0)->setOriginalCustomPrice(0.0)->setWeeeTaxApplied('a:0:{}')->setStoreId($storeId); if ($rule->getIsApplied()) { return; } else { if ($quote->hasProductId($productId)) { foreach ($quote->getAllItems() as $item) { if ($item->getSku() == $productSku) { $quote->removeItem($item->getId()); } } } else { } if (count($quote->getAllItems()) > 0) { $quote->addItem($quoteItem); $quoteItem->setApplyingRule($rule); $rule->setIsApplied(true); } } break; } $result = new Varien_Object(array('discount_amount' => $discountAmount, 'base_discount_amount' => $baseDiscountAmount)); Mage::dispatchEvent('salesrule_validator_process', array('rule' => $rule, 'item' => $item, 'address' => $address, 'quote' => $quote, 'qty' => $qty, 'result' => $result)); $discountAmount = $result->getDiscountAmount(); $baseDiscountAmount = $result->getBaseDiscountAmount(); $percentKey = $item->getDiscountPercent(); /** * Process "delta" rounding */ if ($percentKey) { $delta = isset($this->_roundingDeltas[$percentKey]) ? $this->_roundingDeltas[$percentKey] : 0; $baseDelta = isset($this->_baseRoundingDeltas[$percentKey]) ? $this->_baseRoundingDeltas[$percentKey] : 0; $discountAmount += $delta; $baseDiscountAmount += $baseDelta; $this->_roundingDeltas[$percentKey] = $discountAmount - $quote->getStore()->roundPrice($discountAmount); $this->_baseRoundingDeltas[$percentKey] = $baseDiscountAmount - $quote->getStore()->roundPrice($baseDiscountAmount); $discountAmount = $quote->getStore()->roundPrice($discountAmount); $baseDiscountAmount = $quote->getStore()->roundPrice($baseDiscountAmount); } else { $discountAmount = $quote->getStore()->roundPrice($discountAmount); $baseDiscountAmount = $quote->getStore()->roundPrice($baseDiscountAmount); } /** * We can't use row total here because row total not include tax * Discount can be applied on price included tax */ $itemDiscountAmount = $item->getDiscountAmount(); $itemBaseDiscountAmount = $item->getBaseDiscountAmount(); $discountAmount = min($itemDiscountAmount + $discountAmount, $itemPrice * $qty); $baseDiscountAmount = min($itemBaseDiscountAmount + $baseDiscountAmount, $baseItemPrice * $qty); $item->setDiscountAmount($discountAmount); $item->setBaseDiscountAmount($baseDiscountAmount); $item->setOriginalDiscountAmount($originalDiscountAmount); $item->setBaseOriginalDiscountAmount($baseOriginalDiscountAmount); $appliedRuleIds[$rule->getRuleId()] = $rule->getRuleId(); $this->_maintainAddressCouponCode($address, $rule); $this->_addDiscountDescription($address, $rule); if ($rule->getStopRulesProcessing()) { break; } } $item->setAppliedRuleIds(join(',', $appliedRuleIds)); $address->setAppliedRuleIds($this->mergeIds($address->getAppliedRuleIds(), $appliedRuleIds)); $quote->setAppliedRuleIds($this->mergeIds($quote->getAppliedRuleIds(), $appliedRuleIds)); return $this; }
/** * Fire a legacy event to process this rule for this item * * @param Mage_SalesRule_Model_Rule $rule * @param Mage_Sales_Model_Quote_Item_Abstract $item * @param Mage_Sales_Model_Quote_Address $address * * @return bool */ protected function fireLegacyEvent(Mage_SalesRule_Model_Rule $rule, Mage_Sales_Model_Quote_Item_Abstract $item, Mage_Sales_Model_Quote_Address $address) { // Prepare values for the event $quote = $address->getQuote(); $qty = $rule->getDiscountQty() ? min($item->getTotalQty(), $rule->getDiscountQty()) : $item->getTotalQty(); // Prepare result object $result = new Varien_Object(['discount_amount' => 0.0, 'base_discount_amount' => 0.0, 'applied' => false]); // Fire legacy event Mage::dispatchEvent('salesrule_validator_process', ['quote' => $quote, 'address' => $address, 'rule' => $rule, 'item' => $item, 'qty' => $qty, 'result' => $result]); // Save discount amounts $item->setDiscountAmount($item->getDiscountAmount() + $result->getData('discount_amount')); $item->setBaseDiscountAmount($item->getBaseDiscountAmount() + $result->getData('base_discount_amount')); // brain-dead check to see if a rule was applied return $result->getData('applied') || $result->getData('discount_amount') != 0.0; }
/** * Quote item discount calculation process * * @param Mage_Sales_Model_Quote_Item_Abstract $item * * @return Mage_SalesRule_Model_Validator */ public function process(Mage_Sales_Model_Quote_Item_Abstract $item) { $item->setDiscountAmount(0); $item->setBaseDiscountAmount(0); $item->setDiscountPercent(0); $quote = $item->getQuote(); $address = $this->_getAddress($item); $itemPrice = $this->_getItemPrice($item); $baseItemPrice = $this->_getItemBasePrice($item); $itemOriginalPrice = $this->_getItemOriginalPrice($item); $baseItemOriginalPrice = $this->_getItemBaseOriginalPrice($item); if ($itemPrice < 0) { return $this; } $appliedRuleIds = array(); foreach ($this->_getRules() as $rule) { /* @var $rule Mage_SalesRule_Model_Rule */ if (!$this->_canProcessRule($rule, $address)) { continue; } if (!$rule->getActions()->validate($item)) { continue; } $qty = $this->_getItemQty($item, $rule); $discountAmount = 0; $baseDiscountAmount = 0; //discount for original price $originalDiscountAmount = 0; $baseOriginalDiscountAmount = 0; if ($rule->getSimpleAction() != Mage_SalesRule_Model_Rule::BUY_X_GET_Y_ACTION) { return parent::process($item); } switch ($rule->getSimpleAction()) { case Mage_SalesRule_Model_Rule::BUY_X_GET_Y_ACTION: $x = $rule->getDiscountStep(); $y = $rule->getDiscountAmount(); if (!$x || $y > $x) { break; } $buyAndDiscountQty = $x + $y; $fullRuleQtyPeriod = floor($qty / $buyAndDiscountQty); $freeQty = $qty - $fullRuleQtyPeriod * $buyAndDiscountQty; $discountQty = $fullRuleQtyPeriod * $y; if ($freeQty > $x) { $discountQty += $freeQty - $x; } /** * This is the only needed part to get/apply the discount, if you have any issues or different * Different version of @see Mage_SalesRule_Model_Validator you can take this code and update this file * With your version of @see Mage_SalesRule_Model_Validator */ if ($address->getByXGetY()) { $arrItems = Mage::helper('web_rules')->getItemsToDiscount($rule, $address, $item); if (isset($arrItems[$item->getId()])) { $discountQty = $arrItems[$item->getId()]; } else { $discountQty = 0; } } /** The modifications end here */ $discountAmount = $discountQty * $itemPrice; $baseDiscountAmount = $discountQty * $baseItemPrice; //get discount for original price $originalDiscountAmount = $discountQty * $itemOriginalPrice; $baseOriginalDiscountAmount = $discountQty * $baseItemOriginalPrice; break; } $result = new Varien_Object(array('discount_amount' => $discountAmount, 'base_discount_amount' => $baseDiscountAmount)); Mage::dispatchEvent('salesrule_validator_process', array('rule' => $rule, 'item' => $item, 'address' => $address, 'quote' => $quote, 'qty' => $qty, 'result' => $result)); $discountAmount = $result->getDiscountAmount(); $baseDiscountAmount = $result->getBaseDiscountAmount(); $percentKey = $item->getDiscountPercent(); /** * Process "delta" rounding */ if ($percentKey) { $delta = isset($this->_roundingDeltas[$percentKey]) ? $this->_roundingDeltas[$percentKey] : 0; $baseDelta = isset($this->_baseRoundingDeltas[$percentKey]) ? $this->_baseRoundingDeltas[$percentKey] : 0; $discountAmount += $delta; $baseDiscountAmount += $baseDelta; $this->_roundingDeltas[$percentKey] = $discountAmount - $quote->getStore()->roundPrice($discountAmount); $this->_baseRoundingDeltas[$percentKey] = $baseDiscountAmount - $quote->getStore()->roundPrice($baseDiscountAmount); $discountAmount = $quote->getStore()->roundPrice($discountAmount); $baseDiscountAmount = $quote->getStore()->roundPrice($baseDiscountAmount); } else { $discountAmount = $quote->getStore()->roundPrice($discountAmount); $baseDiscountAmount = $quote->getStore()->roundPrice($baseDiscountAmount); } /** * We can't use row total here because row total not include tax * Discount can be applied on price included tax */ $itemDiscountAmount = $item->getDiscountAmount(); $itemBaseDiscountAmount = $item->getBaseDiscountAmount(); $discountAmount = min($itemDiscountAmount + $discountAmount, $itemPrice * $qty); $baseDiscountAmount = min($itemBaseDiscountAmount + $baseDiscountAmount, $baseItemPrice * $qty); $item->setDiscountAmount($discountAmount); $item->setBaseDiscountAmount($baseDiscountAmount); $item->setOriginalDiscountAmount($originalDiscountAmount); $item->setBaseOriginalDiscountAmount($baseOriginalDiscountAmount); $appliedRuleIds[$rule->getRuleId()] = $rule->getRuleId(); $this->_maintainAddressCouponCode($address, $rule); $this->_addDiscountDescription($address, $rule); if ($rule->getStopRulesProcessing()) { break; } } $item->setAppliedRuleIds(join(',', $appliedRuleIds)); $address->setAppliedRuleIds($this->mergeIds($address->getAppliedRuleIds(), $appliedRuleIds)); $quote->setAppliedRuleIds($this->mergeIds($quote->getAppliedRuleIds(), $appliedRuleIds)); return $this; }
/** * Quote item discount calculation process * * @param Mage_Sales_Model_Quote_Item_Abstract $item * @return Mage_SalesRule_Model_Validator */ public function originalProcessAfter142(Mage_Sales_Model_Quote_Item_Abstract $item) { $item->setDiscountAmount(0); $item->setBaseDiscountAmount(0); $item->setDiscountPercent(0); $quote = $item->getQuote(); $address = $this->_getAddress($item); //Clearing applied rule ids for quote and address if ($this->_isFirstTimeProcessRun !== true) { $this->_isFirstTimeProcessRun = true; $quote->setAppliedRuleIds(''); $address->setAppliedRuleIds(''); } $itemPrice = $this->_getItemPrice($item); $baseItemPrice = $this->_getItemBasePrice($item); if ($itemPrice <= 0) { return $this; } $appliedRuleIds = array(); foreach ($this->_getRules() as $rule) { /* @var $rule Mage_SalesRule_Model_Rule */ if (!$this->_canProcessRule($rule, $address)) { continue; } if (!$rule->getActions()->validate($item)) { continue; } // WDCA CODE BEGIN $rewards_rule = $this->getRule($rule->getId()); // WDCA CODE END $qty = $this->_getItemQty($item, $rule); $rulePercent = min(100, $rule->getDiscountAmount()); $discountAmount = 0; $baseDiscountAmount = 0; switch ($rule->getSimpleAction()) { case Mage_SalesRule_Model_Rule::TO_PERCENT_ACTION: $rulePercent = max(0, 100 - $rule->getDiscountAmount()); //no break; //no break; case Mage_SalesRule_Model_Rule::BY_PERCENT_ACTION: $step = $rule->getDiscountStep(); if ($step) { $qty = floor($qty / $step) * $step; } $discountAmount = ($qty * $itemPrice - $item->getDiscountAmount()) * $rulePercent / 100; $baseDiscountAmount = ($qty * $baseItemPrice - $item->getBaseDiscountAmount()) * $rulePercent / 100; if (!$rule->getDiscountQty() || $rule->getDiscountQty() > $qty) { $discountPercent = min(100, $item->getDiscountPercent() + $rulePercent); $item->setDiscountPercent($discountPercent); } break; case Mage_SalesRule_Model_Rule::TO_FIXED_ACTION: $quoteAmount = $quote->getStore()->convertPrice($rule->getDiscountAmount()); $discountAmount = $qty * ($itemPrice - $quoteAmount); $baseDiscountAmount = $qty * ($baseItemPrice - $rule->getDiscountAmount()); break; case Mage_SalesRule_Model_Rule::BY_FIXED_ACTION: $step = $rule->getDiscountStep(); if ($step) { $qty = floor($qty / $step) * $step; } $quoteAmount = $quote->getStore()->convertPrice($rule->getDiscountAmount()); $discountAmount = $qty * $quoteAmount; $baseDiscountAmount = $qty * $rule->getDiscountAmount(); break; case Mage_SalesRule_Model_Rule::CART_FIXED_ACTION: if (empty($this->_rulesItemTotals[$rule->getId()])) { Mage::throwException(Mage::helper('salesrule')->__('Item totals are not set for rule.')); } $cartRules = $address->getCartFixedRules(); if (!isset($cartRules[$rule->getId()])) { $cartRules[$rule->getId()] = $rule->getDiscountAmount(); } if ($cartRules[$rule->getId()] > 0) { if (1 >= $this->_rulesItemTotals[$rule->getId()]['items_count']) { $quoteAmount = $quote->getStore()->convertPrice($cartRules[$rule->getId()]); $discountAmount = min($itemPrice * $qty, $quoteAmount); $baseDiscountAmount = min($baseItemPrice * $qty, $cartRules[$rule->getId()]); } else { $discountRate = $baseItemPrice * $qty / $this->_rulesItemTotals[$rule->getId()]['base_items_price']; $maximumItemDiscount = $rule->getDiscountAmount() * $discountRate; $quoteAmount = $quote->getStore()->convertPrice($maximumItemDiscount); $discountAmount = min($itemPrice * $qty, $quoteAmount); $baseDiscountAmount = min($baseItemPrice * $qty, $maximumItemDiscount); $this->_rulesItemTotals[$rule->getId()]['items_count']--; } $cartRules[$rule->getId()] -= $baseDiscountAmount; } $address->setCartFixedRules($cartRules); break; case Mage_SalesRule_Model_Rule::BUY_X_GET_Y_ACTION: $x = $rule->getDiscountStep(); $y = $rule->getDiscountAmount(); if (!$x || $y >= $x) { break; } $buyAndDiscountQty = $x + $y; $fullRuleQtyPeriod = floor($qty / $buyAndDiscountQty); $freeQty = $qty - $fullRuleQtyPeriod * $buyAndDiscountQty; $discountQty = $fullRuleQtyPeriod * $y; if ($freeQty > $x) { $discountQty += $freeQty - $x; } $discountAmount = $discountQty * $itemPrice; $baseDiscountAmount = $discountQty * $baseItemPrice; break; } $result = new Varien_Object(array('discount_amount' => $discountAmount, 'base_discount_amount' => $baseDiscountAmount)); Mage::dispatchEvent('salesrule_validator_process', array('rule' => $rule, 'item' => $item, 'address' => $address, 'quote' => $quote, 'qty' => $qty, 'result' => $result)); $discountAmount = $result->getDiscountAmount(); $baseDiscountAmount = $result->getBaseDiscountAmount(); $percentKey = $item->getDiscountPercent(); /** * Process "delta" rounding */ if ($percentKey) { $delta = isset($this->_roundingDeltas[$percentKey]) ? $this->_roundingDeltas[$percentKey] : 0; $baseDelta = isset($this->_baseRoundingDeltas[$percentKey]) ? $this->_baseRoundingDeltas[$percentKey] : 0; $discountAmount += $delta; $baseDiscountAmount += $baseDelta; $this->_roundingDeltas[$percentKey] = $discountAmount - $quote->getStore()->roundPrice($discountAmount); $this->_baseRoundingDeltas[$percentKey] = $baseDiscountAmount - $quote->getStore()->roundPrice($baseDiscountAmount); $discountAmount = $quote->getStore()->roundPrice($discountAmount); $baseDiscountAmount = $quote->getStore()->roundPrice($baseDiscountAmount); } else { $discountAmount = $quote->getStore()->roundPrice($discountAmount); $baseDiscountAmount = $quote->getStore()->roundPrice($baseDiscountAmount); } /** * We can't use row total here because row total not include tax * Discount can be applied on price included tax */ $discountAmount = min($item->getDiscountAmount() + $discountAmount, $itemPrice * $qty); $baseDiscountAmount = min($item->getBaseDiscountAmount() + $baseDiscountAmount, $baseItemPrice * $qty); $item->setDiscountAmount($discountAmount); $item->setBaseDiscountAmount($baseDiscountAmount); //@nelkaake -a 16/11/10: //@nelkaake 2/6/2010 2:34:20 PM : WDCA CODE BEGIN (just added the if statement) if (!$rewards_rule->isPointsRule()) { switch ($rule->getSimpleFreeShipping()) { case Mage_SalesRule_Model_Rule::FREE_SHIPPING_ITEM: $item->setFreeShipping($rule->getDiscountQty() ? $rule->getDiscountQty() : true); break; case Mage_SalesRule_Model_Rule::FREE_SHIPPING_ADDRESS: $address->setFreeShipping(true); break; } } //@nelkaake 2/6/2010 2:34:38 PM : WDCA CODE END $appliedRuleIds[$rule->getRuleId()] = $rule->getRuleId(); $this->_maintainAddressCouponCode($address, $rule); $this->_addDiscountDescription($address, $rule); //@nelkaake 2/6/2010 2:34:20 PM : WDCA CODE BEGIN (just added the if statement) if ($rule->getStopRulesProcessing()) { //@nelkaake Don't break the loop if this is a rewards rule: if ($rewards_rule->isRedemptionRule()) { } else { break; } } } $item->setAppliedRuleIds(join(',', $appliedRuleIds)); $address->setAppliedRuleIds($this->mergeIds($address->getAppliedRuleIds(), $appliedRuleIds)); $quote->setAppliedRuleIds($this->mergeIds($quote->getAppliedRuleIds(), $appliedRuleIds)); return $this; }
public function process(Mage_Sales_Model_Quote_Item_Abstract $item) { $item->setFreeShipping(false); $item->setDiscountAmount(0); $item->setBaseDiscountAmount(0); $item->setDiscountPercent(0); $quote = $item->getQuote(); if ($item instanceof Mage_Sales_Model_Quote_Address_Item) { $address = $item->getAddress(); } elseif ($quote->isVirtual()) { $address = $quote->getBillingAddress(); } else { $address = $quote->getShippingAddress(); } $customerId = $quote->getCustomerId(); $ruleCustomer = Mage::getModel('salesrule/rule_customer'); $appliedRuleIds = array(); foreach ($this->_rules as $rule) { /* @var $rule Mage_SalesRule_Model_Rule */ /** * already tried to validate and failed */ if ($rule->getIsValid() === false) { continue; } if ($rule->getIsValid() !== true) { /** * too many times used in general */ if ($rule->getUsesPerCoupon() && $rule->getTimesUsed() >= $rule->getUsesPerCoupon()) { $rule->setIsValid(false); continue; } /** * too many times used for this customer */ $ruleId = $rule->getId(); if ($ruleId && $rule->getUsesPerCustomer()) { $ruleCustomer->loadByCustomerRule($customerId, $ruleId); if ($ruleCustomer->getId()) { if ($ruleCustomer->getTimesUsed() >= $rule->getUsesPerCustomer()) { continue; } } } $rule->afterLoad(); /** * quote does not meet rule's conditions */ if (!$rule->validate($address)) { $rule->setIsValid(false); continue; } /** * passed all validations, remember to be valid */ $rule->setIsValid(true); } /** * although the rule is valid, this item is not marked for action */ if (!$rule->getActions()->validate($item)) { continue; } $qty = $item->getQty(); if ($item->getParentItem()) { $qty *= $item->getParentItem()->getQty(); } $qty = $rule->getDiscountQty() ? min($qty, $rule->getDiscountQty()) : $qty; $rulePercent = min(100, $rule->getDiscountAmount()); $discountAmount = 0; $baseDiscountAmount = 0; switch ($rule->getSimpleAction()) { case 'to_percent': $rulePercent = max(0, 100 - $rule->getDiscountAmount()); //no break; //no break; case 'by_percent': if ($step = $rule->getDiscountStep()) { $qty = floor($qty / $step) * $step; } $discountAmount = ($qty * $item->getCalculationPrice() - $item->getDiscountAmount()) * $rulePercent / 100; $baseDiscountAmount = ($qty * $item->getBaseCalculationPrice() - $item->getBaseDiscountAmount()) * $rulePercent / 100; if (!$rule->getDiscountQty() || $rule->getDiscountQty() > $qty) { $discountPercent = min(100, $item->getDiscountPercent() + $rulePercent); $item->setDiscountPercent($discountPercent); } break; case 'to_fixed': $quoteAmount = $quote->getStore()->convertPrice($rule->getDiscountAmount()); $discountAmount = $qty * ($item->getCalculationPrice() - $quoteAmount); $baseDiscountAmount = $qty * ($item->getBaseCalculationPrice() - $rule->getDiscountAmount()); break; case 'by_fixed': if ($step = $rule->getDiscountStep()) { $qty = floor($qty / $step) * $step; } $quoteAmount = $quote->getStore()->convertPrice($rule->getDiscountAmount()); $discountAmount = $qty * $quoteAmount; $baseDiscountAmount = $qty * $rule->getDiscountAmount(); break; case 'cart_fixed': $cartRules = $address->getCartFixedRules(); if (!isset($cartRules[$rule->getId()])) { $cartRules[$rule->getId()] = $rule->getDiscountAmount(); } if ($cartRules[$rule->getId()] > 0) { $quoteAmount = $quote->getStore()->convertPrice($cartRules[$rule->getId()]); $discountAmount = min($item->getRowTotal(), $quoteAmount); $baseDiscountAmount = min($item->getBaseRowTotal(), $cartRules[$rule->getId()]); $cartRules[$rule->getId()] -= $baseDiscountAmount; } $address->setCartFixedRules($cartRules); break; case 'buy_x_get_y': $x = $rule->getDiscountStep(); $y = $rule->getDiscountAmount(); if (!$x || $y >= $x) { break; } $buy = 0; $free = 0; while ($buy + $free < $qty) { $buy += $x; if ($buy + $free >= $qty) { break; } $free += min($y, $qty - $buy - $free); if ($buy + $free >= $qty) { break; } } $discountAmount = $free * $item->getCalculationPrice(); $baseDiscountAmount = $free * $item->getBaseCalculationPrice(); break; } $result = new Varien_Object(array('discount_amount' => $discountAmount, 'base_discount_amount' => $baseDiscountAmount)); Mage::dispatchEvent('salesrule_validator_process', array('rule' => $rule, 'item' => $item, 'address' => $address, 'quote' => $quote, 'qty' => $qty, 'result' => $result)); $discountAmount = $result->getDiscountAmount(); $baseDiscountAmount = $result->getBaseDiscountAmount(); $discountAmount = $quote->getStore()->roundPrice($discountAmount); $baseDiscountAmount = $quote->getStore()->roundPrice($baseDiscountAmount); $discountAmount = min($item->getDiscountAmount() + $discountAmount, $item->getRowTotal()); $baseDiscountAmount = min($item->getBaseDiscountAmount() + $baseDiscountAmount, $item->getBaseRowTotal()); $item->setDiscountAmount($discountAmount); $item->setBaseDiscountAmount($baseDiscountAmount); switch ($rule->getSimpleFreeShipping()) { case Mage_SalesRule_Model_Rule::FREE_SHIPPING_ITEM: $item->setFreeShipping($rule->getDiscountQty() ? $rule->getDiscountQty() : true); break; case Mage_SalesRule_Model_Rule::FREE_SHIPPING_ADDRESS: $address->setFreeShipping(true); break; } $appliedRuleIds[$rule->getRuleId()] = $rule->getRuleId(); if ($rule->getCouponCode() && strtolower($rule->getCouponCode()) == strtolower($this->getCouponCode())) { $address->setCouponCode($this->getCouponCode()); } if ($rule->getStopRulesProcessing()) { break; } } $item->setAppliedRuleIds(join(',', $appliedRuleIds)); $address->setAppliedRuleIds($this->mergeIds($address->getAppliedRuleIds(), $appliedRuleIds)); $quote->setAppliedRuleIds($this->mergeIds($quote->getAppliedRuleIds(), $appliedRuleIds)); return $this; }