Magento Mehrfachbestellung an einer Kasse oder Auftragsaufteilung

10

Ladenprodukte werden von verschiedenen Anbietern geliefert. Es ist erforderlich, für jeden Lieferanten mehrere Bestellungen basierend auf seinen Produkten im Warenkorb während einer Kaufabwicklung zu erstellen. Gibt es eine Erweiterung, um diese Aufgabe zu erfüllen, oder sollte ich mit der Entwicklung eines benutzerdefinierten Checkout-Moduls beginnen? Was ist mit Hot Points für die Erstellung einer solchen Erweiterungsvision von erfahrenen Entwicklern von Magento? Können Sie mir eine kurze Checkout-Ablaufarchitektur erklären, die Magento-freundlich ist (so gut wie Codeebene)? Vielen Dank!

mageUz
quelle
Schauen Sie sich das Multishipping an, das Magento sofort anbietet. Und es gibt ein Landungsschiff, aber ich habe keine Ahnung, ob es gut ist oder was es kann. unirgy.com/products/udropship
Fabian Blechschmidt
@mageUz, hast du unten Antwort gearbeitet?. es hat bei mir nicht funktioniert .. Kannst du deinen Code posten?
Manoj Kumar
@ManojKumar, ja, ich habe bereits eine Auftragsaufteilung mithilfe der Multiadress-Checkout-Logik implementiert. Ich bin sicher, dass die unten angegebene Logik auch einwandfrei funktioniert.
MagierUz
@mageUz, wenn Sie diesen Code verwenden Der Einkaufswagen ist leer und zeigt .. Irgendwelche Vorschläge ..
Manoj Kumar
Hallo, das kann mit dem Marktplatz-Split-Cart-Modul store.webkul.com/Magento-Marketplace-Split-Cart.html gemacht werden . Danke
Webkul

Antworten:

9

Mit einem Umschreiben des checkout/type_onepageModells ist dies recht einfach möglich .
In dieser Klasse überschreiben Sie die saveOrder()Methode wie folgt:

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

Beachten Sie jedoch, dass in Magento eine Zahlung mit einer Rechnung verknüpft ist und jede Rechnung mit einer Bestellung verknüpft ist.

Infolgedessen bedeutet dies, dass Sie, sobald Sie mehrere Bestellungen haben, auch die Zahlungen aufgeteilt haben . Dies ist also nur möglich, wenn die Zahlungsmethode keine Benutzerinteraktion während der Zahlung erfordert.

UPDATE : Die delegierte parent::save()ursprüngliche Antwort, an die gesendet werden musste parent:saveOrder(). Es ist jetzt im Beispielcode behoben.

Vinai
quelle
Würde mich freuen, wenn Sie sich meine ähnliche Frage ansehen könnten! magento.stackexchange.com/questions/6974/…
CaitlinHavener
Konnten Sie die Reihenfolge mit dem obigen Code aufteilen, da ich das gleiche versuche, aber nicht ohne Glück
Deepak Mallah
1
Roy, natürlich muss man die ursprüngliche Klasse erweitern, damit es ein Elternteil gibt, aber das ist einfaches PHP, es hat nichts mit Magento zu tun. Die Methode saveOrderist in Magento CE 1.9 immer noch vorhanden und aktiv, so wie es immer war.
Vinai
3
Ich hatte ein Problem mit diesem Snippet, da bei der 2-Reihenfolge die Gesamtsumme und die Zwischensumme der gesamten Reihenfolge entsprechen. Nach dem Debuggen stellte ich fest, dass selbst beim Entfernen und erneuten Hinzufügen der Elemente nur zwischengespeicherte Adresselemente verwendet werden, nachdem die Gesamtsumme der Adresse erfasst wurde. cached_items_all '); $ address-> unsetData ('cached_items_nominal'); $ address-> unsetData ('cached_items_nonnominal');
Diogo Santiago
1
@Vinai $ quote-> addItem ($ item); Dieser Code funktioniert nicht. Nach dem Hinzufügen eines Elements gebe ich $ quote-> getAllItems () mit Hilfe der foreach-Schleife wieder. Aber es gab keinen Gegenstand. Können Sie mir bitte dabei helfen?
Amit Bera
1

Folgendes wird in CE Version 1.9.0.x getestet

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

WICHTIG Sie müssen Ihre Zahlungsmethoden anpassen, um die Gesamtsumme aus dem Angebot abzurufen.

kiatng
quelle
Es funktioniert. Vielen Dank. Wie gruppiere ich das Warenkorbangebot nach Lieferanten? andere als "// ein Artikel pro Bestellung" ..
Syed Ibrahim
1
$group[] = $item; // all other items in one orderKann mehrere Artikel pro Bestellung enthalten, können Sie einfach so ändern, dass jeder Anbieter seinen eigenen hat $group.
Kiatng
Aktualisiert und es funktioniert. Die Zahlung wird jedoch nur für die letzte Bestellung erfasst (wenn wir mehrere Bestellungen aufteilen). Wie müssen wir das aktualisieren? Ich muss die kombinierte Zahlungssumme einziehen.
Syed Ibrahim
Der Gesamtbetrag befindet sich im Angebotsobjekt, mit dem Sie ihn laden können $quote->Mage::getModel('sales/quote')->load($lastOrder->getQuoteId()). Dann gibt es viele Summen $quote, von denen Sie abrufen können , von denen eine ist$quote->getGrandTotal()
Kiatng