EE 1.14.2 / CE 1.9.2: Item kutipan tidak digabungkan dengan benar saat masuk (duplikat produk dalam keranjang)

16

Saya menemukan bug aneh di Magento EE 1.14.2 (juga mempengaruhi CE 1.9.2) dengan troli.

Langkah-langkah untuk mereproduksi:

  1. Masuk sebagai pelanggan A
  2. Tambahkan produk X ke troli
  3. Beralih ke browser lain
  4. Tambahkan produk X ke troli
  5. Masuk sebagai pelanggan A

Troli yang diharapkan:

  • 2 x Produk X

Kereta aktual:

  • 1 x Produk X
  • 1 x Produk X

Yaitu produk tidak digabung.

Alih-alih beralih browser, Anda juga dapat menghapus cookie sesi atau memilih jumlah yang berbeda untuk produk.

Efek samping terburuk dari ini adalah bahwa kuantitas pesanan maksimum diterapkan per item. Dalam kasus saya, ada diskon 100% untuk suatu produk tetapi Anda hanya bisa memesannya satu kali. Dengan sedikit trik ini, Anda dapat memesannya dalam jumlah berapa pun, gratis.

Mengapa ini terjadi dan bagaimana saya bisa mencegahnya?

Fabian Schmengler
sumber

Jawaban:

18

Selesaikan bug di atas, Fabian!

Untuk pengguna lebih lanjut yang akan menemukan bug ini, sudah ada tambalan dari Magento untuk ini.

Sebagai pelanggan Enterprise, Anda dapat meminta / mengunduh PATCH_SUPEE-6190_EE_1.14.2.0_v1.shuntuk memperbaikinya.

Pembaruan 24.02.2016: Ini juga dibahas di patch SUPEE-7405 v 1.1 terbaru. Menurut Fabian di Twitter (lihat ini dan tweet berikut ) ada kemungkinan itu masih belum diselesaikan sepenuhnya. Silakan mengujinya sendiri juga.

Adapun EE 1.14.2.0 solusinya adalah:

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']);
                     }
                 }

Catatan: Biasanya saya tidak akan memposting kode EE di sini, tetapi karena masalah / file adalah sama seperti di CE dan tidak mempengaruhi fitur EE-only, saya harap tidak apa-apa.

Anna Völkl
sumber
4
Saya menyetujui ini.
philwinkle
5
Kami akan membiarkannya.
Tanda
1
Geser itu.
Marius
Ini berfungsi lebih baik daripada perbaikan saya, yang menyebabkan masalah dengan produk bundel. Terima kasih telah berbagi!
Fabian Schmengler
1
Sayangnya ini masih dapat dilewati jika Anda menambahkan produk satu kali melalui daftar produk dan satu kali melalui halaman detail produk, karena parameter "related_products" hanya ada dalam kasus terakhir. Anda bisa menambahkan "related_products" ke unset()panggilan juga, tapi itu masih tidak aman karena parameter POST sewenang-wenang ditambahkan ke opsi buyRequest juga. Saya akan mengabaikan opsi ini sepenuhnya.
Fabian Schmengler
15

Ternyata ini adalah bug Mage_Sales_Model_Quote_Item::compare()yang diperkenalkan di Magento CE 1.9.2 / EE 1.14.2. Metode ini digunakan untuk membandingkan item untuk memutuskan apakah mereka adalah produk yang sama dan dapat digabung (saat login dan ketika menambahkan produk ke troli).

Saat membandingkan semua opsi khusus, itu harus melewati opsi yang tidak representantatif ( _notRepresentOptions), yaitu opsi info_buyRequest .

Dalam versi Magento sebelumnya, tampilannya seperti ini:

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

dan bekerja dengan benar. Sekarang terlihat seperti ini:

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

dan pemeriksaan tambahan untuk hasCustomOptions()penyebab bug yang dijelaskan. Mengapa? Sepertinya cek telah ditambahkan untuk selalu menjaga produk dengan opsi khusus terpisah. Saya pikir itu tidak masuk akal, paling tidak dalam cara penerapannya, tetapi akan ada beberapa alasan untuk itu yang tidak saya sadari.

Namun, $item->getProduct()->hasCustomOptions()selalu kembali benar untuk item kutipan!

Inilah metodenya:

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

Tetapi $this->_customOptionsjuga berisi info_buyRequestopsi dari item kutipan.

Untuk solusi yang tidak mengganggu, saya mencoba untuk menghapus info_buyRequestopsi dari semua produk di pengamat sales_quote_merge_before, tanpa hasil.

Alasannya terletak di Mage_Sales_Model_Quote_Item_Abstract::getProduct()mana opsi disalin lagi dari item kutipan itu sendiri:

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

    [...]

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

Larutan

Saya membuat penulisan ulang untuk Mage_Sales_Model_Quote_Itemdengan menimpa getProduct()agar tidak menyertakan info_buyRequestopsi pada saat ini:

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

Ini menyebabkan masalah dengan produk bundel, alternatif di bawah ini atau tambalan resmi seperti yang dijelaskan oleh @ AnnaVölkl adalah solusi yang lebih baik

Alternatif

Anda juga bisa menghapus kesalahan && !$item->getProduct()->hasCustomOptions()dalam compare()metode jika Anda menulis ulang model barang. Saya tidak tahu masalah apa yang coba dipecahkannya, tetapi itu menciptakan lebih banyak ...

Perbarui 29 Jan 2016

Saya melaporkan ini ke Magento dan mendapat tanggapan bahwa mereka tidak dapat mereproduksi masalah, sehingga tambalan tidak akan membuatnya menjadi edisi komunitas (Submission APPSEC-1321).

Ini berarti, jika Anda memiliki masalah, Anda perlu menerapkan patch perusahaan SUPEE-6190 setelah setiap pembaruan atau menggunakan penulisan ulang kelas sebagai gantinya.

Fabian Schmengler
sumber
However, $item->getProduct()->hasCustomOptions() always returns true for quote items!Ini sedang memeriksa data produk untuk opsi kustom bukan item kutipan :)
kanevbgbe
1
@kanevbgbe secara mengejutkan, tidak. Magento "menyiapkan" contoh produk yang terkait dengan item kutipan dan menambahkan nilai opsi
kustomnya
Saya tahu bahwa pada tindakan add to cart, contoh produk dimuat penuh (dibandingkan dengan beban kutipan), sehingga diatur dari luar algoritma kutipan langsung ke contoh item kutipan melalui setProduct (), mungkin kemudian pemeriksaan ini memiliki output yang berbeda .
kanevbgbe
1

Seperti yang saya lihat jawaban di atas sudah tersedia di versi terbaru Magento tapi kami masih mendapatkan masalah. Itu tidak berhasil karena kami telah melakukan banyak penyesuaian. Pikir berbagi solusi.

Bagi kami itu sangat sederhana karena kami hanya menggunakan produk sederhana. Jadi, kami memperluas fungsi membandingkan gabungan kutipan ke ini:

NS_Module_Model_Sales_Quote_Item meluas Mage_Sales_Model_Quote_Item {

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

}

dan ditambahkan

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

tapi. bagi mereka yang menggunakan produk yang dapat dikonfigurasi juga maka itu mungkin tidak membantu Anda. Dalam hal ini Anda dapat mencetak kedua array: $ itemOptionValue dan $ optionValue dan melihat perbedaannya. hapus semua kunci tambahan yang tidak umum di kedua array. Itu harus menyelesaikan masalah.

Arif Ahmad
sumber
-1

Anda bisa menambahkan opsi ke produk di acara sales_quote_add_item:

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

Tautan referensi: Nonaktifkan penggabungan posisi keranjang?

gelanivishal
sumber
Itu solusinya, tapi sepenuhnya menonaktifkan penggabungan item biasanya tidak diinginkan.
Fabian Schmengler