Steuersatz für Warenkorb-Angebotspositionen ändern und neu berechnen


31

Ich habe eine Kategorie von Produkten, deren Steuersatz (rechtlich) geändert werden muss, wenn Sie mehr als eine bestimmte Menge bestellen. Ich habe die verschiedenen Steuermodelle erweitert, damit dies funktioniert, wenn Sie ein neues Produkt in den Warenkorb legen. Es treten jedoch Probleme auf, wenn der Benutzer die Mengen im Warenkorb aktualisiert oder zusätzliche Produkte hinzufügt, die die bereits im Warenkorb befindlichen Mengen über den Schwellenwert bringen Menge.

Problem 1:

Zuallererst bin ich nicht zu 100% der zu beobachtenden Ereignisse. Ich habe folgendes versucht;

checkout_cart_save_after(basierend auf -> https://stackoverflow.com/questions/14362702/magento-programatically-update-cart-via-event )

checkout_cart_update_items_after(basierend auf -> https://stackoverflow.com/questions/5104482/programmatisch-Produkt-zum-Warenkorb-mit-Preisänderung hinzufügen )

sales_quote_save_before(basierend auf -> https://stackoverflow.com/questions/7638858/magento-recalculate-cart-total-in-observer )

Problem 2:

Ich bin in der Lage, auf die Angebote aus dem Warenkorb zuzugreifen. Es gibt viele Möglichkeiten, dies zu tun. Ich kann auch die einzelnen Artikel im Einkaufswagen durchlaufen, die Eigenschaften dieser Artikel aktualisieren und die Artikel dann (zumindest vorübergehend) speichern. In diesem Fall kann ich das Angebot jedoch nicht speichern und die Steuern an der Kasse neu berechnen.

Ein Grund dafür ist, dass ich zwar auf das Warenkorbangebot zugreifen kann, aber nicht sicher bin, welche Methode ich verwenden soll, um darauf schreiben zu können.

Was ich versucht habe:

Was ich versucht habe, um auf den Inhalt des Einkaufswagens zuzugreifen, hing von dem Ereignis ab, das ich beobachtet habe, aber ich habe Folgendes versucht:

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

Die, die es mir zumindest zu ermöglichen scheint, auf das Angebot zuzugreifen, es durchzugehen und die Artikel zu aktualisieren, ist

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

Auf diese Weise kann ich jedes Angebotselement aktualisieren, wenn ich es durchlaufe (ich glaube, ich verwende Magic Setter, da ich keine entsprechenden Methoden finde). Ich hatte gehofft, die Steuerklassen-ID für den Angebotsposten aktualisieren und dann die Steuern neu berechnen zu können. Wenn ich Folgendes verwende (wobei sich $ taxClassId von der bereits von jedem Anführungszeichen verwendeten unterscheidet);

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

Und dann die Ergebnisse protokollieren;

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

Es zeigt, dass ich diesen Angebotsposten tatsächlich aktualisiert und die Steuernummer geändert habe. Wenn ich dann jedoch nachverfolge und versuche, das geänderte Zitat zu speichern,

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

Und dann erneut debuggen;

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

Meine Änderungen wurden nicht gespeichert, die Angebotsartikeländerung wurde zurückgesetzt und die Warenkorbsummen werden nicht neu berechnet. Man beginnt sich zu fragen, ob es die Lösung für dieses Problem sein könnte, ein hohes Gebäude zu finden, von dem man abspringen kann.


Bitte helfen Sie mir, dieses Problem zu lösen: stackoverflow.com/questions/27978781/… Vielen Dank.
Satish

Antworten:


35

Mein Vorschlag wäre, einen Beobachter auf das sales_quote_collect_totals_beforeEreignis zu setzen, das in der Mage_Sales_Model_Quote::collectTotalsMethode ausgelöst wird, bevor der gesamte Erfassungsprozess gestartet wird. Anschließend iterieren Sie in dieser Observer-Methode die Angebotspositionen und ändern die Steuerklasse für das (bereits geladene) Produktobjekt, das Sie aus der Angebotsposition abrufen können.

Versuchen Sie nach dem Festlegen der Informationen für das Produktobjekt NICHT, diese in der Datenbank zu speichern. Wenn die Steuerklasse für das Produktobjekt im Speicher nach Bedarf festgelegt ist, ist dies ausreichend, um die Logik für die Erfassung der Gesamtsummen zu verwenden, die in Mage_Tax_Model_Sales_Total_Quote_Taxder Ermittlung der Steuerklasse gefunden wird, auf der die Berechnungen basieren sollen. Das Speichern des Produkts (wie Sie es anscheinend in Ihrem obigen Codebeispiel versucht haben) führt zu schwerwiegenden Leistungsproblemen, schafft Rennbedingungen im Berechnungsprozess und ist einfach keine gute Praxis.

Der Grund dafür, dass Sie mit den Ereignissen, mit denen Sie arbeiten möchten, nicht das erreichen können, was Sie erreichen möchten, ist, dass alle Ereignisse nach der Gesamtberechnung ablaufen. Dieser Vorgang wird nur einmal ausgeführt, bevor das Angebot gespeichert wird.

In Bezug auf den Vorgang zum Sammeln von Gesamtsummen sollte darauf hingewiesen werden, dass Sie ihn nach dem Ausführen ohne zusätzliche Arbeit nicht erneut aufrufen können, um ihn basierend auf den Änderungen, die Sie an den Angebotselementen vorgenommen haben, neu berechnen zu lassen. Sehen Sie sich dieses Beispiel aus der Blog-Serie an, die ein Kollege von mir vor kurzem für den Vorgang zum Sammeln von Gesamtsummen zusammengestellt hat:

Nachdem Sie nun verstanden haben, was während des Prozesses der Erfassung von Summen geschieht, können Sie es als zweckmäßig oder notwendig erachten, sie direkt selbst aufzurufen. Beachten Sie jedoch die folgenden Regeln, bevor Sie sich zu sicher fühlen, collectTotals für Ihre eigenen Zwecke zu verwenden:

Produkte können nicht zum Angebot hinzugefügt werden, nachdem collectTotals ausgeführt wurde!

. . . es sei denn, die Artikel-Caches der Angebotsadressen werden gelöscht.

Die "Collect" -Methode jedes Gesamtmodells beruht darauf, dass die Angebotselemente aus der Adresse abgerufen und in einer Schleife durchlaufen werden. Wenn getAllItems zum ersten Mal für eine Angebotsadresse ausgeführt wird, wird die Artikelsammlung tatsächlich mit einem eindeutigen Schlüssel zwischengespeichert. Diese zwischengespeicherte Sammlung wird bei nachfolgenden Aufrufen zurückgegeben.

Wenn Sie eine Ahnung davon haben, wie der Vorgang zum Sammeln von Gesamtsummen wirklich funktioniert, können Sie die erste der vier Teilreihen zum Gesamtsammeln hier genauer lesen: Enträtseln von Magentos collectTotals: Einführung

Zusammenfassend muss ein Ereignis erfasst werden, das vor dem Vorgang zum Erfassen der Gesamtsummen ausgeführt wird (und bevor getAllItems für die Angebotsadressen aufgerufen wird), damit Änderungen, die Sie an den Elementen vornehmen, von den Gesamtsammlern verwendet werden. Ich habe nicht überprüft, ob das vorgeschlagene sales_quote_collect_totals_beforeEreignis ausgeführt wird, bevor Anrufe an die getAllItemsunter der Angebotsadresse angegebene Adresse gesendet wurden, aber ich bin mir fast sicher, dass es für die von Ihnen gewünschten Anforderungen funktioniert. Wenn nicht, habe ich hoffentlich genug Kontext bereitgestellt, damit Sie herausfinden können, welches Ereignis Sie abfangen müssen, damit es funktioniert.


Diese Antwort geht weit über das hinaus, was ich mir erhofft hatte. Genial, danke, dass du dir die Zeit genommen hast. Fantastische Antwort.
McNab

Argh! Nachdem ich den ganzen Tag damit verbracht hatte und es nicht zum Laufen gebracht hatte, bemerkte ich schließlich, dass es sich um ein schlecht umgeschriebenes Modell an einer anderen Stelle im Modul handelte. Das funktioniert perfekt und ich habe eine Menge daraus gelernt, nochmals vielen Dank, David.
McNab

@McNab Freut mich zu hören, dass es funktioniert. Auf jeden Fall einer der komplexeren Bereiche von Magento, mit denen man sich befasst. :)
Davidalger

+1 auf dem verlinkten Blog. Ich habe es die ersten Male übersehen, als ich es durchgelesen habe. Das ist eine große Hilfe.
Pspahn

6

Es gibt ein anderes Ereignis: sales_quote_item_set_productin Mage_Sales_Model_Quote_Item :: setProduct

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

Mit diesem Ereignis können Sie die Produktsteuerklasse ändern. Verwenden Sie die Methode quoteItem getQty, um die Menge zu ermitteln, die dem Einkaufswagen hinzugefügt wurde.


Vielen Dank dafür, es ist nützlich zu wissen - ich erkenne aufgrund der Antwort von @ davidalger, dass ich jetzt nicht die Steuerklasse des Produkts ändern sollte, sondern das Angebotsmodell. Gut zu wissen.
McNab

Nun, Sie können die Steuerklasse für den Angebotsposten tatsächlich ändern. Sie haben auch im Ereignis Zugriff auf das quoteItem-Objekt.
PandaWebStudio

Ah ok - ich habe falsch verstanden. Vielen Dank für die Klarstellung :)
McNab

@PandaWebStudio, wie wird der benutzerdefinierte Steuerbetrag für den Angebotsposten festgelegt? hier ist meine frage
jafar pinjar

2

Vielleicht ist der Versuch, die Steuerklasse zu ändern, nicht der beste Ansatz. Erstellen Sie ein ähnliches Produkt für Produkte, die die höhere Steuerklasse verwenden, und legen Sie für dieses Produkt eine Mindestmenge im Warenkorb fest. Dann verwenden Sie die checkout_cart_update_items_after, um Produkte basierend auf der Gesamtmenge im Warenkorb zu tauschen.

Dies ist definitiv keine "Best Practice", aber es könnte Ihnen helfen, in eine andere Richtung zu denken.

Alternativ können Sie unter http://www.mageworx.com/multi-fees-magento-extension.html eine Option einrichten, bei der Sie eine Gebühr für die zusätzliche Steuer hinzufügen. Dies könnte tatsächlich eine schönere Methode sein, wird aber nicht in den Steuersummen angezeigt, sondern eher als zusätzliche Gesamtsumme der Bestellungen.


Danke für die Antwort Sander. Es ist eine gute Idee und ich hatte nicht daran gedacht. Ich sage Ihnen, warum ich mir das nicht vorstellen kann - die zugrunde liegenden Produkte werden alle über die uMarketplace-Suite von Unirgy ausgeführt, und es war eine gewaltige Aufgabe, sie dahin zu bringen, wo sie als Preisvergleichsseite ausgeführt wird. Ich denke, das könnte eine große Aufgabe sein. Wenn ich diesen Angebotseintrag nicht aktualisieren kann, muss ich ihn mir allerdings ansehen.
McNab

Verdammt, ich kann deine Antwort nicht einmal unterstützen, da ich meinen ganzen Repräsentanten für dieses Kopfgeld ausgegeben habe! +1 :) Werde positiv stimmen, wenn ich mehr bekomme.
McNab

haha kein problem, ich verstehe das problem und das wäre keine gute lösung für den fall. Ich würde dann wahrscheinlich mit den Multifees gehen, das ist eine "sauberere" Lösung
Sander Mangel

FWIW, ich würde diese Route nicht vorschlagen ... schon allein, weil dadurch die Erfassung von Verkäufen und die Verfolgung von Lagerbeständen zu einem potenziellen Albtraum werden. Wie das OP sagte, nicht die beste Praxis, aber ich werde hinzufügen: Es wird mehr Probleme verursachen, als es lösen würde.
Davidalger

0

Benutze das <sales_quote_collect_totals_before>

und in deiner Funktion gerne

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

Ich hoffe das wird definitiv funktionieren

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.