Змініть ставку податку на предмети котирування та перерахунок


31

У мене є категорія товарів, на які (юридично) потрібно змінити ставку податку, коли ви замовляєте більше певної кількості. Я розширив різні моделі оподаткування, щоб це працювало, коли ви додаєте новий товар у кошик, але у мене виникають проблеми, коли користувач оновлює кількість у кошику або додає додаткові продукти, які доводять кількість вже в кошику понад поріг кількість.

Проблема 1:

Перш за все, я не на 100%, яку подію (ів) слід спостерігати. Я спробував наступне;

checkout_cart_save_after(виходячи з цього -> https://stackoverflow.com/questions/14362702/magento-programatic-update-cart-via-event )

checkout_cart_update_items_after(виходячи з цього -> https://stackoverflow.com/questions/5104482/programmatic-add-product-to-cart-with-price-change )

sales_quote_save_before(на основі цього -> https://stackoverflow.com/questions/7638858/magento-recalculate-cart-total-in-observer )

Проблема 2:

Я можу отримати доступ до цитатних предметів з кошика, є безліч способів зробити так, як здається. Я також можу переглядати окремі предмети у кошику, оновлювати властивості цих предметів, а потім зберігати елементи (принаймні тимчасово). Однак я не в змозі зберегти ціну та перерахувати податки в касі.

Частина причини полягає в тому, що, хоча я можу отримати доступ до цитати кошика, я не впевнений, який метод використовувати, щоб мати можливість писати на нього.

Що я пробував:

Те, що я спробував у доступі до вмісту кошика, залежало від події, яку я спостерігав, але я спробував усе наступне;

1. 
$item = $observer->getQuoteItem;

2.
$cart = Mage::getSingleton('checkout/cart');
$cartItems = $cart->getCart()->getItems(); 

3.
$cart = $observer->getData('cart');
$quote = $cart->getData('quote');
$cartItems = $quote->getAllVisibleItems();

4.
$cartHelper = Mage::helper('checkout/cart');
$cartItems = $cartHelper->getCart()->getItems(); 

5.
$quote = Mage::getModel('checkout/cart');
$cartItems = $quote->getItems(); 

Той, який, здається, принаймні дозволяє мені отримати доступ до цитат, пробігати їх та оновлювати елементи

6.
$quote = Mage::getSingleton('checkout/session')->getQuote();
$cartItems = $quote->getAllVisibleItems();

Це дозволяє мені оновлювати кожен пункт цитати, коли я повторюю (я вважаю, що використовую магічні сеттери, оскільки не можу знайти відповідних методів). Я сподівався, що зможу оновити ідентифікаційний номер податкового класу для товару, а потім перерахувати податки. Якщо я використовую наступне (де $ taxClassId відрізняється від того, який уже використав кожен пункт цитати);

$item->setTaxClassId( $taxClassId );
$item->getProduct()->setIsSuperMode(true);
$item->save;

А потім запишіть результати;

Mage::log($item->debug(), null,'taxobserver.log', true);

Це свідчить про те, що я дійсно оновив цей пункт пропозицій та змінив податковий ідентифікатор. Однак якщо я потім перейду і намагаюся зберегти змінену цитату;

$quote->setTotalsCollectedFlag(false)->collectTotals();
$quote->save();     

А потім знову налагоджувати;

Mage::log($item->debug(), null,'taxobserver.log', true);

Мої зміни не збережено, зміна елемента котирування було скинуто, а загальна кількість кошиків не перераховується. Починаючи замислюватися, чи можна знайти високу споруду, щоб скочити, може бути рішенням для цього.


будь ласка, будь-хто допоможе мені вирішити це: stackoverflow.com/questions/27978781/… дякую.
сатис

Відповіді:


35

Моя пропозиція полягала б у тому, щоб поставити спостерігача за sales_quote_collect_totals_beforeподією, яку розстрілюють Mage_Sales_Model_Quote::collectTotalsметодом, перш ніж вона розпочне загальний процес збору. Потім зсередини цього методу спостереження повторіть статті котирувань та змініть податковий клас на (вже завантажений) товарний об’єкт, який ви можете отримати з позиції котирування.

Після того, як ви встановите інформацію на об’єкт продукту, що б ви не робили, НЕ намагайтеся зберігати їх у базі даних. Якщо встановити в пам'яті податковий клас, необхідний для об'єкта товару, буде досить добре, щоб у підході виявилася логіка збирання підсумків, на Mage_Tax_Model_Sales_Total_Quote_Taxякому податковому класі він повинен базуватися. Збереження продукту (як ви, як здається, намагаєтеся зробити у вашому зразку коду вище), спричинить серйозні проблеми з продуктивністю, створить перегонові умови в процесі обчислення і просто не є хорошою практикою.

Причина того, що події, з якими ви намагаєтеся працювати, не дають змоги виконати те, що ви намагаєтеся здійснити, полягає в тому, що всі вони настають після повного обчислення, процесу, який запускається лише один раз перед збереженням цитати.

Варто зазначити, що процес збирання підсумків полягає в тому, що після запуску, не виконуючи зайвих робіт, ви не можете його знову зателефонувати, щоб повторно обчислити на основі змін, внесених у цитати. Дивіться цей біт-біт, який я взяв із серії блогу, мою колекцію, яку нещодавно зібрали в процесі збирання підсумків:

Тепер, коли ви розумієте, що відбувається під час збору підсумків, вам може здатися зручним або необхідним зателефонувати безпосередньо. Перш ніж ви почнете почувати себе надто впевнено, використовуючи збирання колекцій для власних цілей, пам’ятайте про таке правило:

Продукти не можуть бути додані до котирування після запуску collectionTotals!

. . . якщо тільки не очищено кеші елементів цитатних адрес.

Майже кожна загальна методика "збирання" загальної моделі покладається на отримання цитатних елементів з адреси та прокручування їх. Перший раз, коли getAllItems запускається за адресою котирування, колекція елементів насправді кешується унікальним ключем, і саме ця кешована колекція повертається при наступних дзвінках.

Якщо у вас трапляється по-справжньому зануритися в глибину того, як працює процес збору підсумків, ви можете ознайомитись з першою з чотирьох серій частин із загальної колекції тут для більш поглибленого читання: Розгадування колекції MagentoTotals: Вступ

Підводячи підсумок, вам потрібно зафіксувати подію, яка запускається до того, як процес збору підсумків збирається (і перед тим, як getAllItems буде викликаний за адресами цитат), щоб зміни, внесені вами до елементів, використовувались загальними колекціонерами. Я не переконався, що запропонована sales_quote_collect_totals_beforeподія працює перед будь-якими дзвінками getAllItemsна адресу цитати, але я майже впевнений, що вона працюватиме для того, що вам потрібно. Але якщо ні, то, сподіваємось, я забезпечив вам достатньо контексту, щоб зрозуміти, яку подію вам потрібно спіймати, щоб вона спрацювала.


Ця відповідь набагато виходить за те, на що я сподівався. Блискуче, дякую, що знайшли час. Фантастична відповідь.
McNab

Арг! Провівши цілий день на це і не діставши його до роботи II, нарешті зрозумів, що воно зводиться до погано переписаної моделі в іншому місці модуля. Це прекрасно працює, і я навчився з нього навантажень, ще раз дякую Давидові.
McNab

@McNab Радий почути, що ви працюєте. Безумовно, одна з найскладніших областей Магенто, з якою йдеться. :)
davidalger

+1 у пов’язаному блозі. Я проігнорував це перші кілька разів, коли прочитав. Це велика допомога.
pspahn

6

Є ще одна подія: sales_quote_item_set_productу Mage_Sales_Model_Quote_Item :: setProduct

Mage::dispatchEvent('sales_quote_item_set_product', array(
            'product' => $product,
            'quote_item'=>$this
        ));

Ви можете змінити податковий клас на продукт, використовуючи цю подію. Використовуйте метод quoItem getQty, щоб знайти кількість, додану до кошика.


Дякую за це, корисно знати - я розумію, виходячи з відповіді @ davidalger, що я не повинен змінювати податковий клас товару, а модель котирування. Добре знати, хоча.
McNab

Що ж, ви можете фактично змінити податковий клас позиції котирування, ви також маєте доступ у випадку події до об'єкта quoItem.
PandaWebStudio

Ах гаразд - я неправильно зрозумів. Дякую за уточнення :)
McNab

@PandaWebStudio, як встановити власну суму податку для товару? ось моє запитання, magento.stackexchange.com/questions/274520/…
jafar pinjar

2

Можливо, спроба змінити податковий клас може бути не найкращим підходом. Чому б не створити подібний продукт для тих товарів, які використовують вищий податковий клас і встановити мінімальний кількість у кошику для цього продукту. Тоді використовуйте checkout_cart_update_items_afterдля обміну продуктами навколо, виходячи із загальної кількості в кошику?

Це, безумовно, не є «найкращою практикою», але це може допомогти вам подумати в іншому напрямку.

Крім того, спробуйте налаштувати щось за допомогою http://www.mageworx.com/multi-fees-magento-extension.html, де ви додасте "плату" за додатковий податок. Насправді це може бути приємніший спосіб зробити це, але він не відображатиметься в сумах податків, більше як сума додаткової суми замовлення.


Дякуємо за відповідь Сандер. Це гарна ідея, і я не думав про це. Я скажу вам, чому я цього не уявляю - основні продукти працюють усі, хоча пакет урмаркетів Unirgy, і це завдання було дістати його туди, де він працює, як сайт порівняння цін. Я думаю, що це може бути великою роботою. Якщо я не можу оновлювати цей пункт цитати, мені доведеться переглянути його.
McNab

Чорт, я навіть не можу відповісти на вашу відповідь, оскільки я витратив всю свою репутацію на цю щедрість! +1 :) Оголошу, коли отримаю ще трохи.
McNab

ха-ха, ніяких проблем, я розумію, що це не було б гарним рішенням для справи. Я, мабуть, пішов би з мультифішем тоді, це "чистіше" рішення
Sander Mangel

FWIW, я б не пропонував цей маршрут… хоча б тому, що це зробить облік продажів та відстеження товарних запасів потенційним кошмаром. Як сказав ОП, це не найкраща практика, але я додам: це спричинить більше проблем, ніж вирішить.
davidalger

0

Використовуй це <sales_quote_collect_totals_before>

і у вашій функції робите так

 public function quoteCollectTotalsBefore(Varien_Event_Observer $observer)
    $quote = $observer->getQuote();
    foreach ($quote->getAllItems() as $item)
    {
        $product = $item->getProduct();
        $product->setTaxClassId($product_tax_class_id);
    }
 }

Я сподіваюся, що це спрацює рішуче

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.