Zmodyfikuj stawkę podatkową na pozycje z wyceną koszyka i ponownie ją oblicz

31

Mam kategorię produktów, które (zgodnie z prawem) wymagają zmiany stawki podatkowej, gdy zamawiasz więcej niż określoną ilość. Rozszerzyłem różne modele podatkowe, aby to działało, gdy dodajesz nowy produkt do koszyka, ale mam problemy, gdy użytkownik aktualizuje ilości w koszyku lub dodaje dodatkowe produkty, które przechylają ilości już w koszyku powyżej progu ilość.

Problem 1:

Przede wszystkim nie jestem w 100% świadomy (-ych) wydarzeń. Próbowałem następujących;

checkout_cart_save_after(w oparciu o to -> https://stackoverflow.com/questions/14362702/magento-programatically-update-cart-via-event )

checkout_cart_update_items_after(w oparciu o to -> https://stackoverflow.com/questions/5104482/programmatically-add-product-to-cart-with-price-change )

sales_quote_save_before(w oparciu o to -> https://stackoverflow.com/questions/7638858/magento-recalculate-cart-total-in-observer )

Problem 2:

Jestem w stanie uzyskać dostęp do artykułów z koszyka, istnieje wiele sposobów, aby to zrobić. Mogę również iterować poszczególne elementy w koszyku, aktualizować właściwości tych przedmiotów, a następnie zapisywać przedmioty (przynajmniej tymczasowo). Jednak nie jestem w stanie zapisać wyceny i przeliczyć podatków w kasie.

Częściowo dlatego, że chociaż mam dostęp do wyceny koszyka, nie jestem pewien, której metody użyć, aby móc do niej napisać.

Co próbowałem:

To, czego próbowałem w zakresie dostępu do zawartości koszyka, zależało od tego, co zaobserwowałem, ale próbowałem wszystkich następujących rzeczy;

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(); 

Wydaje się, że przynajmniej pozwala mi uzyskać dostęp do wyceny, przejrzeć je i zaktualizować elementy

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

To pozwala mi aktualizować każdy element cytatu, gdy wykonuję iterację (wydaje mi się, że używam seterów magii, ponieważ nie mogę znaleźć odpowiednich metod). Miałem nadzieję, że będę w stanie zaktualizować identyfikator klasy podatkowej dla wyceny, a następnie ponownie obliczyć podatki. Jeśli użyję następujących (gdzie $ taxClassId różni się od tego, który jest już używany przez każdą pozycję wyceny);

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

A następnie zaloguj wyniki;

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

To pokazuje, że rzeczywiście zaktualizowałem ten cytat i zmieniłem identyfikator podatkowy. Jeśli jednak przejdę dalej i spróbuję zapisać zmodyfikowany cytat;

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

A następnie ponownie debuguj;

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

Moje zmiany nie zostały zapisane, zmiana pozycji oferty została zresetowana, a sumy koszyka nie są ponownie obliczane. Zaczynam się zastanawiać, czy znalezienie wysokiego budynku do zeskoczenia może być rozwiązaniem tego.

McNab
źródło
proszę, pomóżcie mi rozwiązać ten problem: stackoverflow.com/questions/27978781/... dziękuję.
satish

Odpowiedzi:

35

Moją sugestią byłoby umieszczenie obserwatora na sales_quote_collect_totals_beforezdarzeniu, które jest uruchamiane w Mage_Sales_Model_Quote::collectTotalsmetodzie, zanim rozpocznie się całkowity proces gromadzenia. Następnie z wnętrza tej metody obserwatora, iteruj pozycje wyceny i zmień klasę podatkową na (już załadowany) obiekt produktu, który możesz odzyskać z przedmiotu wyceny.

Po ustawieniu informacji o obiekcie produktu, cokolwiek zrobisz, NIE próbuj zapisywać ich w bazie danych. Posiadanie w pamięci klasy podatkowej ustawionej zgodnie z potrzebami dla obiektu produktu będzie wystarczające, aby logika zbierania sum została znaleziona podczas Mage_Tax_Model_Sales_Total_Quote_Taxpobierania, na której klasie podatkowej powinien opierać swoje obliczenia. Zapisanie produktu (jak się wydaje, co próbujesz zrobić w powyższym przykładzie kodu) spowoduje poważne problemy z wydajnością, stworzy warunki wyścigu w procesie obliczeń i po prostu nie jest dobrą praktyką.

Powodem, dla którego zdarzenia, z którymi próbujesz pracować, nie są możliwe do osiągnięcia tego, co próbujesz osiągnąć, jest to, że wszystkie one powstają po całkowitym obliczeniu, proces ten jest uruchamiany tylko raz przed zapisaniem wyceny.

Warto zwrócić uwagę na proces zbierania sum, że po uruchomieniu, bez wykonywania dodatkowej pracy, nie można wywołać go ponownie, aby ponownie obliczyć na podstawie zmian wprowadzonych do elementów oferty. Zobacz ten fragment, który wziąłem z blogu mojego kolegi, który niedawno zebrał się w procesie zbierania sum:

Teraz, gdy rozumiesz, co dzieje się podczas procesu gromadzenia sum, możesz uznać za wygodne lub konieczne samodzielne wywołanie tego bezpośrednio. Zanim jednak zaczniesz czuć się zbyt pewny korzystania z CollectTotals do własnych celów, pamiętaj o następującej zasadzie:

Produkty nie mogą zostać dodane do oferty po uruchomieniu CollectTotals!

. . . chyba że pamięć podręczna pozycji adresów wyceny zostanie wyczyszczona.

Niemal każda metoda „kolekcjonowania” całego modelu polega na pobieraniu elementów wyceny z adresu i przechodzeniu przez nie. Przy pierwszym uruchomieniu getAllItems pod adresem wyceny kolekcja przedmiotów jest faktycznie buforowana za pomocą unikatowego klucza i to ta kolekcja buforowana jest zwracana przy kolejnych wywołaniach.

Jeśli akurat masz ochotę naprawdę zanurzyć się w głębiny tego, jak działa proces zbierania sum, możesz zapoznać się z pierwszą z czterech serii części dotyczących całkowitego zbierania, aby uzyskać bardziej dogłębną lekturę: Odkrywanie kolekcji Magento Podsumowanie: Wprowadzenie

Podsumowując, musisz wychwycić zdarzenie, które jest uruchamiane przed procesem zbierania sum (i przed wywołaniem getAllItems na adresach wyceny), aby zmiany dokonane w elementach były używane przez wszystkich kolekcjonerów. Nie sprawdziłem, czy sugerowane sales_quote_collect_totals_beforezdarzenie działa przed wywołaniem getAllItemsadresu podanego w wycenie, ale jestem prawie pewien, że zadziała dla potrzeb. Ale jeśli nie, mam nadzieję, że dostarczyłem wystarczającego kontekstu, abyś zorientował się, które wydarzenie musisz złapać, aby zadziałało.

davidalger
źródło
Ta odpowiedź jest znacznie większa niż oczekiwałem. Genialne, dzięki za poświęcenie czasu. Fantastyczna odpowiedź.
McNab,
Argh! Po spędzeniu całego dnia na tym i nieprzygotowaniu go do pracy, w końcu zdałem sobie sprawę, że było to spowodowane źle przepisanym modelem w innym miejscu modułu. Działa to doskonale i nauczyłem się z tego ładunków, jeszcze raz dziękuję David.
McNab,
@McNab Cieszę się, że działasz. Zdecydowanie jeden z bardziej złożonych obszarów Magento, którym się zajmujemy. :)
davidalger
+1 na połączonym blogu. Przeoczyłem to kilka razy, kiedy przeczytałem. To wielka pomoc.
pspahn
6

Jest jeszcze jedno zdarzenie: sales_quote_item_set_productw Mage_Sales_Model_Quote_Item :: setProduct

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

Za pomocą tego zdarzenia możesz zmodyfikować klasę podatku od produktów. Użyj metody quoteItem getQty, aby znaleźć ilość dodaną do koszyka.

PandaWebStudio
źródło
Dzięki za to warto wiedzieć - na podstawie odpowiedzi @ davidalger zdaję sobie sprawę, że nie powinienem teraz modyfikować klasy podatkowej produktu, ale model wyceny. Warto jednak wiedzieć.
McNab,
Cóż, możesz faktycznie zmodyfikować klasę podatkową pozycji wyceny, masz również dostęp w przypadku do obiektu quoteItem.
PandaWebStudio
Ach ok - źle zrozumiałem. Dzięki za wyjaśnienie :)
McNab
@PandaWebStudio, jak ustawić niestandardową kwotę podatku dla pozycji wyceny? oto moje pytanie, magento.stackexchange.com/questions/274520/…
jafar pinjar
2

Może próba zmiany klasy podatkowej może nie być najlepszym podejściem. Dlaczego nie stworzyć podobnego produktu dla produktów korzystających z wyższej klasy podatkowej i ustawić minimalną ilość w koszyku dla tego produktu. Następnie użyć checkout_cart_update_items_afterdo zamiany produktów na podstawie całkowitej ilości w koszyku?

To zdecydowanie nie jest „najlepsza praktyka”, ale może pomóc ci myśleć w innym kierunku.

Alternatywnie spróbuj skonfigurować coś w http://www.mageworx.com/multi-fees-magento-extension.html, gdzie dodajesz „opłatę” za dodatkowy podatek. To może być ładniejszy sposób na zrobienie tego, ale nie pojawi się w sumach podatków, a raczej jako dodatkowa linia sumy zamówień.

Sander Mangel
źródło
Dzięki za odpowiedź Sander. To dobry pomysł i nie pomyślałem o tym. Powiem wam, dlaczego mi się to nie podoba - wszystkie produkty bazowe działają w pakiecie uMarketplace Unirgy i ogromnym wyzwaniem było dotarcie tam, gdzie jest, ponieważ działa jako strona porównująca ceny. Myślę, że to może być świetna robota. Jeśli nie mogę zaktualizować tego cytatu, muszę go jednak zobaczyć.
McNab,
Cholera, nie mogę nawet głosować za twoją odpowiedzią, ponieważ spędziłem cały czas na otrzymaniu nagrody! +1 :) Głosuję, gdy otrzymam więcej.
McNab
haha, nie ma problemu, rozumiem problem i nie byłoby to dobre rozwiązanie w tej sprawie. Prawdopodobnie wybrałbym wtedy multifees, to „czystsze” rozwiązanie
Sander Mangel
FWIW, nie sugerowałbym tej trasy… choćby dlatego, że uczyniłoby to księgowanie sprzedaży i śledzenie zapasów potencjalnym koszmarem. Jak powiedział PO, nie jest to najlepsza praktyka, ale dodam: To spowoduje więcej problemów, niż by to rozwiązało.
davidalger
0

Użyj tego <sales_quote_collect_totals_before>

i w swojej funkcji lubisz

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

Mam nadzieję, że to zadziała zdecydowanie

Mage2Solutions
źródło