Wer schon einmal einen Magento-Shop betreut hat, der ist mit hoher Wahrscheinlichkeit auf das Rundungsproblem gestoßen, bei dem immer wieder Rundungsdifferenzen von +/- 1 Cent auftreten. Das Problem ist bereits seit langer Zeit bekannt, und wurde vor kurzem laut Hersteller in der neuesten Version 1.8 beseitigt. Wer sich bereits einmal die Fingern bei einem Magento-Update (sogar bei vermeintlichen kleinen Versionssprüngen) verbrannt hat, für den ist ein Update oftmals keine echte Option. Das erhöhte Risiko, dass - mangels Codequalität im Core und insbesondere von diversen Extensions - andere Fehler auftreten und zumindest Teile des Shops nicht mehr richtig funktionieren, schreckt zu sehr ab. Selbst, wenn man ein Update plant, sollte man sich genügend Zeit dafür reservieren. Wenn also eine schnelle Lösung gefunden werden muss, ist ein Update keine Option.
Auf der Suche nach einer Lösung für 1.7
Sucht man in Google nach diesem Problem, erhält man eine Unmenge an verzweifelten Fragen, sowie Problemlösungsvorschläge. Sie alle zielen darauf ab, die Genauigkeit der Rundungen von normalerweise 2 auf 4 Nachkommastellen zu erhöhen. Datenbankseitig sind alle Preis-Spalten ohnehin auf 4 Nachkommastellen vorbereitet. In der Mage_Core_Model_Store Klasse werden die Zahlen aber hardcodiert immer auf 2 Nachkommastellen gerundet. Damit werden aber wieder Probleme mit PayPal-Zahlungen ausgelöst.
Mittlerweile gibt es eine gratis Extension, die sowohl die Rundungsgenauigkeit erhöht, als auch das damit verbundene PayPal-Problem löst. Aber sind damit tatsächlich alle Probleme gelöst? Die Antwort lautet: leider nein!
...Nettosumme immer noch falsch...
Die Extension sorgte bei unserem Kunden tatsächlich für richtige Gesamt- und Steuerbeträge. Allerdings wurde des öfteren die Nettosumme falsch berechnet. Denn sie war in diesen Fällen immer noch um einen Cent zu hoch! Das Problem trat immer dann auf, wenn die dritte Nachkommastelle bei der Steuer "5" betrug. So wurde vom Gesamtbetrag der ungerundete Steuerbetrag abgezogen, sodass die auch eine "5" an dritter Nachkommastelle hatte. Im Warenkorb, Bestellbestätigung und auf der Rechnung werden diese Beträge aber wieder gerundet angezeigt. Beide Beträge wurden somit fälschlicherweise aufgerundet. Gleiches Problem ergab sich auch mit Rabatten.
Bei unserem Kunden trat das Problem relativ häufig auf, da viele Brutto-Preise als auch die Standardversandkosten auf 99 Cent enden, und die Produkte auch dem österreichischen Mehrwertsteuersatz von 20% unterliegen. Beispiel: EUR 9,99 brutto ergibt ungerundet 8,325 + 1.665.
Problemlösung
Rechnerisch richtig wäre, den gerundeten Steuerbetrag von der Gesamtsumme zu subtrahieren. Dann erhält man auch eine gerundete und richtige Nettosumme. In Magento sind dann noch folgende Anpassungen notwendig:
Zuerst sollte man die bereits erwähnte Xonu RoundingErrorFix Extension installieren. Diese Extension muss leicht modifiziert werden, um die Rabatte richtig zu berücksichtigen. Und zwar sollte die Datei app/code/community/Xonu/RoundingErrorFix/Model/Store.php folgendermaßen verändert werden:
Im Konstruktor:
$this->classList[] = get_class(Mage::getSingleton('salesrule/quote_discount'));
Und dann noch in der foundPrice() Funktion die if-Bedingung durch folgende ersetzen:
if(!empty($trace[$depth]['class']) && in_array($trace[$depth]['class'], $this->classList)) {
Das Hauptproblem in Zusammenhang mit der Steuer wird so aber leider nicht behoben. Denn hier muss man quer verstreut durch den Code alle Stellen ausfindig machen, die die Nettosumme als Gesamtbetrag - Steuerbetrag ausrechnet, und zuvor den Steuerbetrag auf 2 Stellen runden. So muss z.B. die Mage_Tax_Block_Sales_Order_Tax Klasse angepasst werden, sodass in der _initGrandTotal() Funktion die $baseGrandtotalExcl und $grandtotalExcl Variablen mit gerundeten Steuerbeträgen errechnet werden:
$grandtotalExcl = $grandtotal - round($this->_source->getTaxAmount(), 2);
$baseGrandtotalExcl = $baseGrandtotal - round($this->_source->getBaseTaxAmount(), 2)
Weitere Dateien, die berücksichtigt werden müssen:
- Mage_Tax_Model_Sales_Pdf_Grandtotal
- Mage_Adminhtml_Block_Sales_Order_Create_Totals_Grandtotal
- Mage_Tax_Block_Checkout_Grandtotal
Mit diesen Anpassungen sollte das Rundungsproblem (hoffentlich) endgültig Geschichte sein!
Hallo, welche Anpassungen sind denn in den genannten weiteren Dateien vorzunehmen?
... es ist nicht schwer herauszufinden - überall, wo die Gesamtsumme dort ausgerechnet wird. Die Zeilen sehen eh sehr ähnlich aus
Hi,
Danke für die tolle Beschreibung. Ich habe die Extension in meinem 1.7.0.2 Store installiert und benötige keine Änderungen damit Rabattcodes / PayPal etc funktionieren. Kann das sein?
Freue mich auf eine Antwort.
LG
P
Bei dieser Thematik spielen einige Faktoren mit: zum einen hängt es natürlich von der Shop-Konfiguration ab (Steuerberechnungsmethode, Brutto- oder Nettopreise, etc.), in weiterer Folge auch von den Preisen, Rabatt- und Steuersätzen selbst. Denn auch wenn hier im Shopsystem Programmierfehler vorliegen bzw die Herangehensweise bei der Berechnung nicht richtig und konsistent ist, ist es letztendlich auch ein mathematisches Problem.
/** * Round price * * @param mixed $price * @param int|NULL $precision * @return double */ public function roundPrice($price,$precision = NULL) { if (NULL!==$precision) { return round($price, $precision); } $precision_ret = 2; $trace = debug_backtrace(); $depth = 2; // if(in_array($trace[$depth]['class'], $this->classList)) // if(array_key_exists('class', $trace[$depth]) && $trace[$depth]['class'] == $this->classList[0]) if( empty($trace[$depth]['class']) || !in_array($trace[$depth]['class'], $this->classList) ) { $precision_ret = 4; } return round($price, $precision_ret); }
Und in Mage_Adminhtml_Block_Sales_Order_Creditmemo_Create_Adjustments::getShippingAmount Zeile ändern: return Mage::app()->getStore()->roundPrice($shipping,2) * 1; Dann haben es die Kunden einfacher.Der Shop, für den wir diese Lösung entwickelt haben, läuft mittlerweile auch auf einer 1.9er, aber das Problem ist dennoch nicht völlig aus der Welt. Auf Produktebene ist uns nichts aufgefallen, allerdings werden hier überall nur Bruttopreise angezeigt.
Wir hatten aber Probleme mit den Gesamtsummen - sodass Sub Total (exkl. MwSt.) und/oder Grand Total um einen Cent nicht gestimmt hatten. Das Problem haben wir aus der Welt geschafft, in dem wir brutal per Observer auf das sales_quote_adress_collect_totals_after Event die Summen selbst korrigiert haben.
Jetzt treten nur noch unter bestimmten Fällen Probleme auf - und zwar wenn Gutscheine mit Fixpreis-Rabatten eingesetzt werden - hier ist nämlich schon der Sub Total inkl. MwSt manchmal falsch, was eigentlich die Ausgangsbasis für unsere Summenkorrektur ist. Außerdem passen die Beträge bei der Erstellung von Gutschriften manchmal nicht - hier müssten wir vermutlich mit einer ähnlichen Korrektur eingreifen
Wenn ich mich richtig erinnere, sind wir folgendermaßen vorgegangen:
Hallo Gregor,
das ist tatsächlich eine sehr eigenartige Summe. Anhand der Abweichung könnte man jetzt gar keine Position nennen, die evtl doppelt versteuert o.ä. werden würde. Wir haben in Magento noch nie einen Mindermengenzuschlag benötigt. Es würde mich nicht wundern, wenn sich dort ein eigener Bug verstecken würde. Wenn man sich einmal durch die Tiefen der Summen- und Steuerberechnungen von Magento durchgequält hat, wundern einen solche Fehler überhaupt nicht mehr. Da wird überall wild hin- und hergerechnet, nix ist vereinheitlicht. So kommen wir auch bei bestehenden, gut frequentierten Shops auch nach langer Zeit wieder auf neue Probleme, wie z.B. Steuerberechnung bei der Gutschrifterstellung (im Zusammenhang mit Versandkosten). -> da hilft leider nur eines: debuggen, debuggen, debuggen - und nicht verzweifeln dabei ;) :)