Magento Gutscheine für vollständig kostenlose Produkte

Es gibt bereits eine Vielzahl von Anleitungen, um in Magento Gutscheine zu erstellen. In den meisten Beispielen handelt es sich jedoch nur um einen Rabatt. Möchte man Gutscheine erstellen, mit denen ein Produkt vollständig kostenlos wird, funktioniert das auch bis hin zur Bestellbestätigungsemail reibungslos.

In diesem Beispiel kostet das Produkt 128,00 € und hat eine Mwst. von 19%:

Nettobetrag € 107,56
Versandkosten € 0,00
Rabatt (DD0QDM4YWV5L) -€ 128,00
Steuer € 0,00
Gesamtsumme € 0,00

Erstellt man nun die Rechnung, fällt auf, dass der Gesamtbetrag die negative Steuer beträgt:

Nettobetrag € 107,56
Versandkosten € 0,00
Rabatt (DD0QDM4YWV5L) -€ 128,00
Steuer € 0,00
Gesamtsumme € 20,44

Sobald der Rabattbetrag kleiner als der Preis des Produktes ist, also noch etwas zu zahlen übrig bleibt, stimmt die Rechnung wieder.

Grund hierfür ist ein Bug in Magento.

Der Preis wird folgendermaßen zusammenaddiert:

+ Nettopreis der Produkte
- Rabatt
+ Steuern

d.h. 107,56€ – 128€ = -20,44€

Jetzt müssten nur noch die Steuern addiert werden und es würde stimmen –  jedoch gibt es einen kleinen Bug:

app/code/core/Mage/Sales/Model/Order/Invoice/Total/Tax.php

   foreach ($invoice->getAllItems() as $item) {
            $orderItem = $item->getOrderItem();
            $orderItemQty = $orderItem->getQtyOrdered();

            if ($orderItem->getTaxAmount() && $orderItemQty) {
                if ($item->getOrderItem()->isDummy()) {
                    continue;
                }

Diese Schleife zählt die Steuern der Positionen auf der Rechnung zusammen. Hierfür gibt es zwei Variablentypen $totalTax und $totalHiddenTax. Da unser Produkt kostenlos ist, taucht die Steuer hierfür nur in der Variable $totalHiddenTax auf.

Jedoch wird der Code nur durchlaufen, wenn die sichtbaren Steuern größer als 0 sind. Dies ist nicht der Fall, wenn der Rabatt=Produktpreis ist.

Zum Schluss werden die Steuern auf die Gesammtsumme addiert:

$invoice->setGrandTotal(
       $invoice->getGrandTotal() + $totalTax + $totalHiddenTax
);

Da die $hiddenTax unserer Position aber nicht auf $totalHiddenTax drauf gerechnet wurde, fehlt diese.

Die „sauberste“ Lösung war für mich das Model „Mage_Sales_Model_Order_Invoice_Total_Tax“ mit dem üblichen Magento-Mechanismus zu überschreiben und die if-Abfrage entsprechend zu ändern:

if ( /*$orderItem->getTaxAmount() &&*/ $orderItemQty) {