Magento multiple order dalam satu checkout atau pemisahan pesanan

10

Produk toko dipasok dari vendor yang berbeda. Anda harus membuat beberapa pesanan untuk setiap vendor berdasarkan produknya di troli selama satu checkout. Apakah ada ekstensi untuk menyelesaikan tugas ini atau haruskah saya mulai mengembangkan modul checkout kustom. Bagaimana dengan hot point untuk menciptakan visi perluasan seperti itu dari pengembang Magento yang berpengalaman? Bisakah Anda jelaskan saya arsitektur aliran checkout singkat yang ramah Magento (mungkin level kode)? Terima kasih banyak lagi!

mageUz
sumber
Lihatlah Multishipping yang ditawarkan magento di luar kotak. Dan ada dropship tetapi saya tidak tahu apakah itu baik atau apa yang bisa dilakukan. unirgy.com/products/udropship
Fabian Blechschmidt
@mageUz, apakah Anda sudah bekerja di bawah ini menjawab ?. itu tidak berfungsi untuk saya .. Bisakah memposting kode Anda?
Manoj Kumar
@ ManojKumar, ya saya sudah menerapkan pemisahan pesanan menggunakan logika checkout multi-alamat, saya yakin bahwa logika yang diberikan di bawah ini juga berfungsi dengan baik.
mageUz
@mageUz, ketika menggunakan kode ini Daftar Belanja kosong menunjukkan .. Ada saran ..
Manoj Kumar
Hai, itu bisa dilakukan dengan menggunakan modul marketplace split cart store.webkul.com/Magento-Marketplace-Split-Cart.html . Terima kasih
webkul

Jawaban:

9

Ini bisa dilakukan dengan cukup mudah dengan menulis ulang checkout/type_onepagemodel.
Di kelas itu timpa saveOrder()metode sebagai berikut:

public function saveOrder()
{
    $quote = $this->getQuote();

    // First build an array with the items split by vendor
    $sortedItems = array();
    foreach ($quote->getAllItems() as $item) {
        $vendor = $item->getProduct()->getVendor(); // <- whatever you need
        if (! isset($sortedItems[$vendor])) {
            $sortedItems[$vendor] = $item;
        }
    }
    foreach ($sortedItems as $vendor => $items) {
        // Empty quote
        foreach ($quote->getAllItems() as $item) {
            $quote->getItemsCollection()->removeItemByKey($item->getId());
        }
        foreach ($items as $item) {
            $quote->addItem($item);
        }
        // Update totals for vendor
        $quote->setTotalsCollectedFlag(false)->collectTotals();

        // Delegate to parent method to place an order for each vendor
        parent::saveOrder();
    }
    return $this;
}

Namun ketahuilah bahwa di Magento pembayaran dikaitkan dengan faktur, dan setiap faktur dikaitkan dengan pesanan.

Karena itu ini berarti bahwa segera setelah Anda memiliki banyak pesanan, Anda juga akan membagi pembayaran . Jadi ini hanya layak jika metode pembayaran tidak memerlukan interaksi pengguna selama pembayaran.

UPDATE : Jawaban asli yang didelegasikan parent::save()harus parent:saveOrder(). Itu diperbaiki dalam kode contoh sekarang.

Vinai
sumber
Sangat menghargai jika Anda bisa melihat pertanyaan serupa saya! magento.stackexchange.com/questions/6974/…
CaitlinHavener
apakah Anda dapat membagi pesanan menggunakan kode di atas, karena saya mencoba melakukan hal yang sama tetapi tidak berhasil
Deepak Mallah
1
Roy, tentu saja Anda harus memperluas kelas asli untuk menjadi orang tua, tapi itu PHP sederhana, itu tidak ada hubungannya dengan Magento. Metode ini saveOrdermasih ada dan aktif di Magento CE 1.9 sama seperti sebelumnya.
Vinai
3
Saya punya masalah dengan cuplikan ini karena urutan 2 memiliki grandtotal dan subtotal sama dengan keseluruhan pesanan. Setelah debugging saya menemukan bahwa bahkan menghapus dan menambahkan kembali item, itu hanya akan menggunakan alamat item di-cache setelah mengumpulkan Total dari alamat ... Untuk menyelesaikannya cukup jelas untuk setiap alamat cache item: $ address-> unsetData (' cached_items_all '); $ address-> unsetData ('cached_items_nominal'); $ address-> unsetData ('cached_items_nonnominal');
Diogo Santiago
1
@Vinai $ quote-> addItem ($ item); kode ini tidak berfungsi. Setelah menambahkan item saya echo $ quote-> getAllItems () dengan bantuan foreach loop. Tapi tidak ada barang. Bisakah Anda membantu saya dalam hal ini?
Amit Bera
1

Berikut ini diuji dalam CE ver 1.9.0.x

/**
 * Overwrite core
 */
class Vendor_Module_Model_Checkout_Type_Onepage extends Mage_Checkout_Model_Type_Onepage
{
    protected $_oriAddresses = array();

    /**
     * Prepare order from quote_items  
     *
     * @param   array of Mage_Sales_Model_Quote_Item 
     * @return  Mage_Sales_Model_Order
     * @throws  Mage_Checkout_Exception
     */
    protected function _prepareOrder2($quoteItems)
    {
        $quote = $this->getQuote();
        $quote->unsReservedOrderId();
        $quote->reserveOrderId();

        // new instance of quote address
        $quote->setIsMultiShipping(true); // required for new instance of Mage_Sales_Model_Quote_Address
        $address = Mage::getModel('sales/quote_address');
        $weight = 0;
        $addressType = 'billing';
        foreach ($quoteItems as $quoteItem) {
            $address->addItem($quoteItem, $quoteItem->getQty());
            $weight += $quoteItem->getWeight();
            if (!$quoteItem->getIsVirtual()) {
                $addressType = 'shipping';
            }
        }
        // get original shipping address that contains multiple quote_items
        if (!isset($this->_oriAddresses[$addressType])) {
            $this->_oriAddresses[$addressType] = Mage::getResourceModel('sales/quote_address_collection')
                ->setQuoteFilter($quote->getId())
                ->addFieldToFilter('address_type', $addressType)
                ->getFirstItem();
        }
        Mage::helper('core')->copyFieldset('sales_convert_quote_address', 'to_customer_address', $this->_oriAddresses[$addressType], $address);
        Mage::helper('core')->copyFieldset('sales_convert_quote_address', 'to_order', $this->_oriAddresses[$addressType], $address);
        $address->setQuote($quote)
            ->setWeight($weight)
            ->setSubtotal(0)
            ->setBaseSubtotal(0)
            ->setGrandTotal(0)
            ->setBaseGrandTotal(0)
            ->setCollectShippingRates(true)
            ->collectTotals()
            ->collectShippingRates()        
            ;

        $convertQuote = Mage::getSingleton('sales/convert_quote');
        $order = $convertQuote->addressToOrder($address);
        $order->setBillingAddress(
            $convertQuote->addressToOrderAddress($quote->getBillingAddress())
        );

        if ($address->getAddressType() == 'billing') {
            $order->setIsVirtual(1);
        } else {
            $order->setShippingAddress($convertQuote->addressToOrderAddress($address));
        }

        $order->setPayment($convertQuote->paymentToOrderPayment($quote->getPayment()));
        if (Mage::app()->getStore()->roundPrice($address->getGrandTotal()) == 0) {
            $order->getPayment()->setMethod('free');
        }

        foreach ($quoteItems as $quoteItem) {
            $orderItem = $convertQuote->itemToOrderItem($quoteItem);  // use quote_item to transfer is_qty_decimal
            if ($quoteItem->getParentItem()) {
                $orderItem->setParentItem($order->getItemByQuoteItemId($quoteItem->getParentItem()->getId()));
            }
            $order->addItem($orderItem);
        }

        return $order;
    }

    /**
     * Overwrite core function
     */
    public function saveOrder()
    {
        $quote = $this->getQuote();
        if ($quote->getItemsCount() > 1) {
            $items = $quote->getAllVisibleItems();
            $group = array();
            $split = array();
            foreach ($items as $item) {
                if (Mage::helper('vendor')->checkSku($item->getSku())) {
                    $split[] = array($item); // one item per order
                } else {
                    $group[] = $item; // all other items in one order
                }
            }
            if (count($split)) {
                if (count($group)) {
                    $split[] = $group;
                }
                return $this->_splitQuote($split);
            }
        }
        return parent::saveOrder();
    }

    /**
     * Split quote to multiple orders
     * 
     * @param array of Mage_Sales_Model_Quote_Item
     * @return Mage_Checkout_Model_Type_Onepage
     */
    protected function _splitQuote($split)
    {
        $this->validate();
        $isNewCustomer = false;
        switch ($this->getCheckoutMethod()) {
            case self::METHOD_GUEST:
                $this->_prepareGuestQuote();
                break;
            case self::METHOD_REGISTER:
                $this->_prepareNewCustomerQuote();
                $isNewCustomer = true;
                break;
            default:
                $this->_prepareCustomerQuote();
                break;
        }
        if ($isNewCustomer) {
            try {
                $this->_involveNewCustomer();
            } catch (Exception $e) {
                Mage::logException($e);
            }
        }

        $quote = $this->getQuote()->save();
        $orderIds = array();
        Mage::getSingleton('core/session')->unsOrderIds();
        $this->_checkoutSession->clearHelperData();

        /**
         * a flag to set that there will be redirect to third party after confirmation
         * eg: paypal standard ipn
         */
        $redirectUrl = $quote->getPayment()->getOrderPlaceRedirectUrl();

        foreach ($split as $quoteItems) {
            $order = $this->_prepareOrder2($quoteItems);
            $order->place();
            $order->save();
            Mage::dispatchEvent('checkout_type_onepage_save_order_after',
                array('order'=>$order, 'quote'=>$quote));
            /**
             * we only want to send to customer about new order when there is no redirect to third party
             */
            if (!$redirectUrl && $order->getCanSendNewEmailFlag()) {
                $order->sendNewOrderEmail();
            }
            $orderIds[$order->getId()] = $order->getIncrementId();
        }

        Mage::getSingleton('core/session')->setOrderIds($orderIds);

        // add order information to the session
        $this->_checkoutSession
            ->setLastQuoteId($quote->getId())
            ->setLastSuccessQuoteId($quote->getId())
            ->setLastOrderId($order->getId())
            ->setRedirectUrl($redirectUrl)
            ->setLastRealOrderId($order->getIncrementId());

        // as well a billing agreement can be created
        $agreement = $order->getPayment()->getBillingAgreement();
        if ($agreement) {
            $this->_checkoutSession->setLastBillingAgreementId($agreement->getId());
        }

        // add recurring profiles information to the session
        $service = Mage::getModel('sales/service_quote', $quote);
        $profiles = $service->getRecurringPaymentProfiles();
        if ($profiles) {
            $ids = array();
            foreach ($profiles as $profile) {
                $ids[] = $profile->getId();
            }
            $this->_checkoutSession->setLastRecurringProfileIds($ids);
            // TODO: send recurring profile emails
        }

        Mage::dispatchEvent(
            'checkout_submit_all_after',
            array('order' => $order, 'quote' => $quote, 'recurring_profiles' => $profiles)
        );

        return $this;
    }
}

PENTING Anda perlu menyesuaikan metode pembayaran untuk mengambil grand total dari penawaran.

kiat
sumber
Ini bekerja. Terima kasih. Bagaimana cara mengelompokkan penawaran keranjang berdasarkan vendor? selain itu "// satu item per pesanan" ..
Syed Ibrahim
1
$group[] = $item; // all other items in one orderdapat menyimpan beberapa item per pesanan, Anda dapat dengan mudah memodifikasi sehingga masing-masing vendor memiliki sendiri $group.
kiat
Diperbarui dan berfungsi. Tetapi Pembayaran ditangkap hanya untuk pesanan terakhir (Jika kami membagi beberapa pesanan). Bagaimana kita perlu memperbarui ini? Saya perlu mengumpulkan total pembayaran gabungan.
Syed Ibrahim
Jumlah total dalam objek kutipan, Anda dapat memuatnya $quote->Mage::getModel('sales/quote')->load($lastOrder->getQuoteId()). Lalu ada banyak total yang dapat Anda ambil $quote, salah satunya adalah$quote->getGrandTotal()
kiat