В своем пользовательском модуле добавьте следующее config.xml
:
<models>
<salesrule>
<rewrite>
<quote_discount>Namespace_Module_Rewrite_SalesRule_Model_Quote_Discount</quote_discount>
</rewrite>
</salesrule>
</models>
<frontend>
<routers>
<checkout>
<args>
<modules>
<Namespace_Module before="Mage_Checkout">Namespace_Module_Checkout</Namespace_Module>
</modules>
</args>
</checkout>
</routers>
</frontend>
Первый - это переписать Mage_SalesRule_Model_Quote_Discount
вNamespace_Module_Rewrite_SalesRule_Model_Quote_Discount
Второй - перегруженный контроллер Mage_Checkout_CartController
Затем добавьте следующий файл app/code/community/Namespace/Module/controllers/Checkout/CartController.php
и вставьте следующий код:
<?php
require_once 'Mage/Checkout/controllers/CartController.php';
class Namespace_Module_Checkout_CartController extends Mage_Checkout_CartController
{
/**
* Initialize coupon
*/
public function couponPostAction()
{
/**
* No reason continue with empty shopping cart
*/
if (!$this->_getCart()->getQuote()->getItemsCount()) {
$this->_goBack();
return;
}
$couponCode = (string) $this->getRequest()->getParam('coupon_code');
if ($this->getRequest()->getParam('remove') == 1) {
$couponCode = '';
}
$oldCouponCode = $this->_getQuote()->getCouponCode();
if (!strlen($couponCode) && !strlen($oldCouponCode)) {
$this->_goBack();
return;
}
try {
$codeLength = strlen($couponCode);
$isCodeLengthValid = $codeLength && $codeLength <= Mage_Checkout_Helper_Cart::COUPON_CODE_MAX_LENGTH;
// Combine multiple coupons
$couponFlag = true;
if ($isCodeLengthValid) {
$del = ',';
if ($oldCouponCode) {
if ($oldCouponCode == $couponCode) {
$couponCode = $oldCouponCode;
} else {
$couponCode = $oldCouponCode . $del . $couponCode;
}
}
} else {
$couponCode = '';
}
$this->_getQuote()->getShippingAddress()->setCollectShippingRates(true);
$this->_getQuote()->setCouponCode($couponCode)
->collectTotals()
->save();
if ($codeLength) {
if ($isCodeLengthValid && $couponFlag) {
$this->_getSession()->addSuccess(
$this->__('Coupon code "%s" was applied.', Mage::helper('core')->escapeHtml($couponCode))
);
} else {
$this->_getSession()->addError(
$this->__('Coupon code "%s" is not valid.', Mage::helper('core')->escapeHtml($couponCode))
);
}
} else {
$this->_getSession()->addSuccess($this->__('Coupon code was canceled.'));
}
} catch (Mage_Core_Exception $e) {
$this->_getSession()->addError($e->getMessage());
} catch (Exception $e) {
$this->_getSession()->addError($this->__('Cannot apply the coupon code.'));
Mage::logException($e);
}
$this->_goBack();
}
}
Вы заметите, что я добавил раздел для объединения кодов купонов, разделенных символом ",". Это, очевидно, может быть более точным, и вы можете добавить дополнительную проверку и т. Д., Но этот код должен работать сразу.
И, наконец, нам нужно добавить кусок, который делает всю магию. Добавить файлapp/code/community/Namespace/Module/Rewrite/SalesRule/Model/Quote/Discount.php
и добавьте контент:
<?php
class Namespace_Module_Rewrite_SalesRule_Model_Quote_Discount extends Mage_SalesRule_Model_Quote_Discount
{
/**
* Collect address discount amount
*
* @param Mage_Sales_Model_Quote_Address $address
* @return Mage_SalesRule_Model_Quote_Discount
*/
public function collect(Mage_Sales_Model_Quote_Address $address)
{
Mage_Sales_Model_Quote_Address_Total_Abstract::collect($address);
$quote = $address->getQuote();
$store = Mage::app()->getStore($quote->getStoreId());
$this->_calculator->reset($address);
$items = $this->_getAddressItems($address);
if (!count($items)) {
return $this;
}
$couponCode = $quote->getCouponCode();
$couponArray = explode(',',$couponCode);
foreach ($couponArray as $couponCode) {
$this->_calculator->init($store->getWebsiteId(), $quote->getCustomerGroupId(), $couponCode);
$this->_calculator->initTotals($items, $address);
$eventArgs = array(
'website_id' => $store->getWebsiteId(),
'customer_group_id' => $quote->getCustomerGroupId(),
'coupon_code' => $couponCode,
);
$address->setDiscountDescription(array());
$items = $this->_calculator->sortItemsByPriority($items);
foreach ($items as $item) {
if ($item->getNoDiscount()) {
$item->setDiscountAmount(0);
$item->setBaseDiscountAmount(0);
}
else {
/**
* Child item discount we calculate for parent
*/
if ($item->getParentItemId()) {
continue;
}
$eventArgs['item'] = $item;
Mage::dispatchEvent('sales_quote_address_discount_item', $eventArgs);
if ($item->getHasChildren() && $item->isChildrenCalculated()) {
foreach ($item->getChildren() as $child) {
$this->_calculator->process($child);
$eventArgs['item'] = $child;
Mage::dispatchEvent('sales_quote_address_discount_item', $eventArgs);
$this->_aggregateItemDiscount($child);
}
} else {
$this->_calculator->process($item);
$this->_aggregateItemDiscount($item);
}
}
}
/**
* process weee amount
*/
if (Mage::helper('weee')->isEnabled() && Mage::helper('weee')->isDiscounted($store)) {
$this->_calculator->processWeeeAmount($address, $items);
}
/**
* Process shipping amount discount
*/
$address->setShippingDiscountAmount(0);
$address->setBaseShippingDiscountAmount(0);
if ($address->getShippingAmount()) {
$this->_calculator->processShippingAmount($address);
$this->_addAmount(-$address->getShippingDiscountAmount());
$this->_addBaseAmount(-$address->getBaseShippingDiscountAmount());
}
$this->_calculator->prepareDescription($address);
}
return $this;
}
}
По сути, это нарушает повышение купона, циклически просматривает каждый код купона, вычисляет и обновляет итоговые цены.
Чтобы проверить, я установил 2 правила корзины покупок:
- тест 1 - скидка 10% на цену товара - остановка дальнейших правил обработки: нет
- тест 2 - скидка 10% на цену товара - остановка дальнейших правил обработки: нет
Нет купона:
Добавлен купонный тест 1:
Добавлен купонный тест 2
Я проверил со скидкой фиксированной суммы, и это работает как ожидалось.
И, как я уже сказал, вам может понадобиться добавить дополнительную проверку, возможно, для дубликатов, но это то, где вы должны начать. Для внешнего интерфейса вы можете добавить некоторую логику, разделить коды по своему усмотрению или оставить как есть.