Magento ordine multiplo su un checkout o suddivisione dell'ordine


10

I prodotti del negozio sono forniti da diversi fornitori. È necessario creare un ordine multiplo per ogni fornitore in base ai suoi prodotti nel carrello durante un checkout. C'è qualche estensione per raggiungere questo compito o dovrei iniziare a sviluppare il modulo di pagamento personalizzato. Che dire di hot points per la creazione di tale visione di estensione di sviluppatori esperti di Magento? Potete spiegarmi breve architettura del flusso di checkout Magento amichevole (possibile come livello di codice)? Grazie mille di più!


Dai un'occhiata al Multishipping che magento offre immediatamente. E c'è dropship ma non ho idea se sia buono o cosa sia in grado di fare. unirgy.com/products/udropship
Fabian Blechschmidt,

@mageUz, hai lavorato sotto la risposta ?. non ha funzionato per me .. Puoi pubblicare il tuo codice?
Manoj Kumar,

@ManojKumar, sì, ho già implementato la suddivisione degli ordini utilizzando la logica di checkout multiadress, sono sicuro che anche la logica fornita di seguito funzioni perfettamente.
mago Uz,

@mageUz, quando si utilizza questo codice il carrello è vuoto mostrando .. Eventuali suggerimenti ..
Manoj Kumar

Salve, può essere fatto utilizzando il modulo del carrello diviso marketplace store.webkul.com/Magento-Marketplace-Split-Cart.html . Grazie
webkul il

Risposte:


9

È fattibile abbastanza facilmente con una riscrittura del checkout/type_onepagemodello.
In quella classe sovrascrivi il saveOrder()metodo come segue:

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;
}

Ma tieni presente che in Magento un pagamento è associato a una fattura e ogni fattura è associata a un ordine.

Di conseguenza questo significa che non appena avrai più ordini, avrai anche diviso i pagamenti . Quindi questo è possibile solo se il metodo di pagamento non richiede l'interazione dell'utente durante il pagamento.

AGGIORNAMENTO : la risposta originale delegata a parent::save()cui doveva essere parent:saveOrder(). Ora è stato corretto nel codice di esempio.


Gradirei se potessi dare un'occhiata alla mia domanda simile! magento.stackexchange.com/questions/6974/…
CaitlinHavener

sei stato in grado di dividere l'ordine usando il codice sopra, poiché sto cercando di fare lo stesso ma non senza fortuna
Deepak Mallah,

1
Roy, ovviamente devi estendere la classe originale perché ci sia un genitore, ma questo è semplice PHP, non ha nulla a che fare con Magento. Il metodo saveOrderè ancora presente e attivo in Magento CE 1.9 proprio come è sempre stato.
Vinai,

3
Ho avuto un problema con questo frammento poiché il 2 ° ordine ha il totale e il totale parziale uguali all'intero ordine. Dopo aver eseguito il debug ho scoperto che anche rimuovendo e aggiungendo nuovamente gli articoli, avrebbe semplicemente utilizzato gli indirizzi nella cache degli indirizzi dopo aver raccolto il totale dall'indirizzo ... Per risolverlo basta cancellare per ogni indirizzo la cache degli oggetti: $ address-> unsetData (' cached_items_all '); $ indirizzo-> unsetData ( 'cached_items_nominal'); $ indirizzo-> unsetData ( 'cached_items_nonnominal');
Diogo Santiago,

1
@Vinai $ quote-> addItem ($ item); questo codice non funziona. Dopo aver aggiunto l'elemento echo $ quote-> getAllItems () con l'aiuto del ciclo foreach. Ma non c'era nessun oggetto. Potete aiutarmi su questo per favore?
Amit Bera

1

Quanto segue è testato nella versione CE 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;
    }
}

IMPORTANTE È necessario personalizzare i metodi di pagamento per recuperare il totale generale dal preventivo.


Funziona. Grazie. Come raggruppare il preventivo del carrello per fornitore? altro poi "// un articolo per ordine" ..
Syed Ibrahim,

1
$group[] = $item; // all other items in one orderpuò contenere più articoli per ordine, è possibile modificarli facilmente in modo tale che ogni fornitore ne abbia uno proprio $group.
kiatng,

Aggiornato e funziona. Ma il pagamento viene acquisito solo per l'ultimo ordine (se dividiamo più ordini). Come dobbiamo aggiornarlo? Devo riscuotere il totale dei pagamenti combinati.
Syed Ibrahim,

L'importo totale è nell'oggetto preventivo, con cui puoi caricarlo $quote->Mage::getModel('sales/quote')->load($lastOrder->getQuoteId()). Quindi ci sono molti totali da cui puoi recuperare $quote, uno dei quali è$quote->getGrandTotal()
kiatng
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.