EE 1.14.2 / CE 1.9.2: Artikel werden beim Anmelden nicht korrekt zusammengeführt (doppelte Artikel im Warenkorb)


16

Ich habe einen seltsamen Fehler in Magento EE 1.14.2 (betrifft auch CE 1.9.2) mit dem Warenkorb gefunden.

Schritte zum Reproduzieren:

  1. Melden Sie sich als Kunde A an
  2. Produkt X in den Warenkorb legen
  3. Wechseln Sie zu einem anderen Browser
  4. Produkt X in den Warenkorb legen
  5. Melden Sie sich als Kunde A an

Erwarteter Warenkorb:

  • 2 x Produkt X

Aktueller Warenkorb:

  • 1 x Produkt X
  • 1 x Produkt X

Dh die Produkte werden nicht zusammengeführt.

Anstatt den Browser zu wechseln, können Sie auch das Sitzungscookie löschen oder eine andere Menge für das Produkt auswählen.

Der schlimmste Nebeneffekt ist, dass die maximale Bestellmenge pro Artikel angewendet wird. In meinem Fall gab es einen Rabatt von 100% auf ein Produkt, aber Sie konnten es nur einmal bestellen. Mit diesem kleinen Trick können Sie es in jeder Menge kostenlos bestellen.

Warum passiert das und wie kann ich es verhindern?

Antworten:


18

Nizza Abschluss des oben genannten Fehlers, Fabian!

Für alle weiteren Benutzer, die auf diesen Fehler stoßen, gibt es bereits einen Patch von Magento.

Als Enterprise-Kunde können Sie dies anfordern / herunterladen PATCH_SUPEE-6190_EE_1.14.2.0_v1.sh.

Update 24.02.2016: Dies wurde auch im neuesten SUPEE-7405 v 1.1-Patch behoben. Laut Fabian auf Twitter (siehe diesen und die folgenden Tweets ) besteht die Möglichkeit, dass es immer noch nicht vollständig gelöst ist. Bitte testen Sie es auch selbst.

Wie bei EE 1.14.2.0 lautet die Lösung:

diff --git a/app/code/core/Mage/Sales/Model/Quote/Item.php b/app/code/core/Mage/Sales/Model/Quote/Item.php
index 3554faa..d759249 100644
--- a/app/code/core/Mage/Sales/Model/Quote/Item.php
+++ b/app/code/core/Mage/Sales/Model/Quote/Item.php
@@ -502,8 +502,8 @@ class Mage_Sales_Model_Quote_Item extends Mage_Sales_Model_Quote_Item_Abstract
                         $itemOptionValue = $_itemOptionValue;
                         $optionValue = $_optionValue;
                         // looks like it does not break bundle selection qty
-                        unset($itemOptionValue['qty'], $itemOptionValue['uenc']);
-                        unset($optionValue['qty'], $optionValue['uenc']);
+                        unset($itemOptionValue['qty'], $itemOptionValue['uenc'], $itemOptionValue['form_key']);
+                        unset($optionValue['qty'], $optionValue['uenc'], $optionValue['form_key']);
                     }
                 }

Hinweis: Normalerweise würde ich hier keinen EE-Code posten, aber da das Problem / die Dateien dasselbe sind wie in CE und keine EE-only-Funktion betreffen, hoffe ich, dass es in Ordnung ist.


4
Ich bin damit einverstanden.
Philwinkle

5
Wir werden es rutschen lassen.
benmarks

1
Schieben Sie es dann.
Marius

Dies funktioniert besser als mein Fix, der Probleme mit Bundle-Produkten verursachte. Danke für das Teilen!
Fabian Schmengler

1
Leider kann dies immer noch umgangen werden, wenn Sie das Produkt einmal über die Produktliste und einmal über die Produktdetailseite hinzufügen, da der Parameter "related_products" nur in letzterem Fall vorhanden ist. Sie können den unset()Aufrufen auch "related_products" hinzufügen , dies ist jedoch immer noch nicht sicher, da der buyRequest-Option auch beliebige POST-Parameter hinzugefügt werden. Ich werde diese Option stattdessen komplett ignorieren.
Fabian Schmengler

15

Es stellte sich heraus, dass dies ein Fehler ist Mage_Sales_Model_Quote_Item::compare(), der in Magento CE 1.9.2 / EE 1.14.2 eingeführt wurde. Die Methode wird verwendet, um Artikel zu vergleichen, um zu entscheiden, ob sie dasselbe Produkt sind und zusammengeführt werden können (beim Anmelden und beim Hinzufügen von Produkten zum Warenkorb).

Beim Vergleich aller benutzerdefinierten Optionen sollten die nicht repräsen- tativen Optionen ( _notRepresentOptions), dh die Option info_buyRequest , übersprungen werden .

In früheren Magento-Versionen sah es so aus:

foreach ($this->getOptions() as $option) {
    if (in_array($option->getCode(), $this->_notRepresentOptions)) {
        continue;
    }

und funktionierte richtig. Nun sieht es so aus:

foreach ($this->getOptions() as $option) {
    if (in_array($option->getCode(), $this->_notRepresentOptions)
        && !$item->getProduct()->hasCustomOptions()
    ) {
        continue;
    }

und die zusätzliche Prüfung auf hasCustomOptions()Ursachen den beschriebenen Fehler. Warum? Es sieht so aus, als ob die Prüfung hinzugefügt wurde, um Produkte mit benutzerdefinierten Optionen immer getrennt zu halten. Ich denke nicht, dass es Sinn macht, zumindest nicht in der Art, wie es implementiert wird, aber es wird einen Grund dafür geben, den ich nicht kenne.

Allerdings $item->getProduct()->hasCustomOptions()gibt immer wahr für Zitat Artikel!

Dies ist die Methode:

public function hasCustomOptions()
{
    if (count($this->_customOptions)) {
        return true;
    } else {
        return false;
    }
}

$this->_customOptionsEnthält aber auch die info_buyRequestOption aus dem Angebotsposten.

Für eine unauffällige Lösung habe ich versucht, die info_buyRequestOption von allen Produkten in einem Beobachter zu entfernen sales_quote_merge_before, ohne Erfolg.

Der Grund liegt darin, Mage_Sales_Model_Quote_Item_Abstract::getProduct()dass die Option erneut aus der Angebotsposition selbst kopiert wird:

public function getProduct()
{
    $product = $this->_getData('product');

    [...]

    if (is_array($this->_optionsByCode)) {
        $product->setCustomOptions($this->_optionsByCode);
    }
    return $product;
}

Lösung

Ich habe ein Umschreiben für Mage_Sales_Model_Quote_Itemmit einer Überschreibung für erstellt getProduct(), um die info_buyRequestOption an dieser Stelle nicht einzuschließen:

public function getProduct() { $product = parent::getProduct(); $options = $product->getCustomOptions(); if (isset($options['info_buyRequest'])) { unset($options['info_buyRequest']); $product->setCustomOptions($options); } return $product; }

Dies führte zu Problemen mit Bundle-Produkten, der unten aufgeführten Alternative oder dem von @ AnnaVölkl beschriebenen offiziellen Patch

Alternative

Sie können die störenden Elemente && !$item->getProduct()->hasCustomOptions()in der compare()Methode auch entfernen , wenn Sie das Elementmodell dennoch umschreiben. Ich weiß nicht, welches Problem es zu lösen versuchte, aber es schuf mehr ...

Update 29. Januar 2016

Ich habe dies Magento gemeldet und die Antwort erhalten, dass das Problem nicht reproduziert werden konnte, sodass der Patch nicht in die Community-Edition (Submission APPSEC-1321) aufgenommen werden kann.

Das heißt, wenn Sie das Problem haben, müssen Sie den Enterprise-Patch SUPEE-6190 nach jedem Update anwenden oder stattdessen ein Class Rewrite verwenden.


However, $item->getProduct()->hasCustomOptions() always returns true for quote items!Es überprüft die Produktdaten auf kundenspezifische Wahlen, nicht das Anführungsstricheinzelteil :)
kanevbgbe

1
@kanevbgbe überraschend nein. Magento "bereitet" die mit einem Angebotseintrag verknüpfte Produktinstanz vor und fügt die benutzerdefinierten Optionswerte hinzu
Fabian Schmengler,

Ich weiß, dass bei der Aktion zum Hinzufügen zum Einkaufswagen die Produktinstanz vollständig geladen ist (im Vergleich zur Angebotslast), sodass sie von außerhalb der Algorithmen des Angebots direkt zur Angebotsartikelinstanz durch setProduct () gesetzt wird. Vielleicht hat diese Prüfung dann eine andere Ausgabe .
Kanevbgbe

1

Wie ich sehen kann, ist die obige Antwort bereits in der neuesten Version von Magento verfügbar, aber wir bekamen immer noch das Problem. Es hat nicht funktioniert, weil wir viele Anpassungen vorgenommen haben. Ich dachte daran, die Lösung zu teilen.

Für uns war es sehr einfach, da wir nur einfache Produkte verwenden. Deshalb haben wir die Funktion zum Vergleichen von Quotenzusammenführungen folgendermaßen erweitert:

NS_Module_Model_Sales_Quote_Item erweitert Mage_Sales_Model_Quote_Item {

public function compare($item) {
    if ($this->getProductId() == $item->getProductId()) {
        return true;
    }
    return parent::compare($item);
}

}

und fügte hinzu

<models>
   <sales>
      <rewrite>
         <quote_item>NS_Module_Model_Sales_Quote_Item</quote_item>
      </rewrite>
   </sales>
</models>

aber. Für diejenigen, die auch konfigurierbare Produkte verwenden, ist dies möglicherweise nicht hilfreich. In diesem Fall können Sie beide Arrays drucken: $ itemOptionValue und $ optionValue und den Unterschied sehen. Deaktivieren Sie alle zusätzlichen Schlüssel, die in beiden Arrays nicht gemeinsam sind. Das sollte das Problem lösen.


-1

Sie können dem Produkt im Ereignis sales_quote_add_item einfach eine Option hinzufügen:

$data['microtime'] = microtime(true);
$product->addCustomOption('do_not_merge', serialize($data));
$item->addOption($product->getCustomOption('do_not_merge'));

Referenzlink: Zusammenführung von Warenkorbpositionen deaktivieren?


Dies ist eine Problemumgehung, aber das vollständige Deaktivieren der Elementzusammenführung ist normalerweise nicht wünschenswert.
Fabian Schmengler
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.