Wielokrotne zamówienie Magento przy jednym kasie lub podziale zamówienia

10

Produkty sklepowe są dostarczane od różnych dostawców. Konieczne jest utworzenie wielu zamówień dla każdego dostawcy na podstawie jego produktów w koszyku podczas jednej transakcji. Czy jest jakieś rozszerzenie do realizacji tego zadania, czy powinienem zacząć opracowywać niestandardowy moduł kasy. Co z gorącymi punktami do stworzenia takiej wizji rozszerzenia doświadczonych programistów Magento? Czy możesz mi wyjaśnić architekturę przepływów gotowych do użycia w Magento (możliwie jak na poziomie kodu)? Wielkie dzięki!

mageUz
źródło
Zobacz Multishipping, który Magento oferuje po wyjęciu z pudełka. I jest dropship, ale nie mam pojęcia, czy jest dobry, czy co jest w stanie zrobić. unirgy.com/products/udropship
Fabian Blechschmidt
@ magUz, czy pracowałeś poniżej odpowiedzi? dla mnie to nie zadziałało. Czy możesz opublikować swój kod?
Manoj Kumar,
@ManojKumar, tak. Wdrożyłem już podział zamówień za pomocą logiki kasy wieloadresowej, jestem pewien, że logika podana poniżej również działa idealnie.
mageUz
@mageUz, gdy używasz tego kodu Koszyk jest pusty, pokazuje .. Wszelkie sugestie ..
Manoj Kumar,
Cześć, można tego dokonać za pomocą marketplace split cart module store.webkul.com/Magento-Marketplace-Split-Cart.html . Dzięki
webkul

Odpowiedzi:

9

Jest to wykonalne dość łatwo dzięki przepisaniu checkout/type_onepagemodelu.
W tej klasie przesłoń saveOrder()metodę w następujący sposób:

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

Pamiętaj jednak, że w Magento płatność jest powiązana z fakturą, a każda faktura jest powiązana z zamówieniem.

W konsekwencji oznacza to, że jak tylko będziesz mieć wiele zamówień, rozdzielisz również płatności . Jest to możliwe tylko wtedy, gdy metoda płatności nie wymaga interakcji użytkownika podczas płatności.

AKTUALIZACJA : Oryginalna odpowiedź przekazana do parent::save()której musiała być parent:saveOrder(). Zostało to teraz naprawione w przykładowym kodzie.

Vinai
źródło
Byłbym wdzięczny, gdybyś mógł spojrzeć na moje podobne pytanie! magento.stackexchange.com/questions/6974/…
CaitlinHavener
czy byłeś w stanie podzielić zamówienie za pomocą powyższego kodu, ponieważ próbuję zrobić to samo, ale nie bez powodzenia
Deepak Mallah
1
Roy, oczywiście, musisz rozszerzyć oryginalną klasę, aby być rodzicem, ale to proste PHP, nie ma to nic wspólnego z Magento. Metoda saveOrderjest nadal obecna i aktywna w Magento CE 1.9, tak jak zawsze była.
Vinai
3
Miałem problem z tym fragmentem, ponieważ porządek 2 ma sumę częściową i sumę częściową równe całemu zamówieniu. Po debugowaniu dowiedziałem się, że nawet usunięcie i ponowne dodanie elementów po prostu użyłoby adresów z pamięci podręcznej adresów po zebraniu Razem z adresu ... Aby to rozwiązać, wyczyść dla każdego adresu pamięć podręczną elementów: $ address-> unsetData (' cached_items_all '); $ address-> unsetData ('cached_items_nominal'); $ address-> unsetData ('cached_items_nonnominal');
Diogo Santiago,
1
@Vinai $ quote-> addItem ($ item); ten kod nie działa. Po dodaniu elementu echo $ quote-> getAllItems () za pomocą pętli foreach. Ale nie było przedmiotu. Czy możesz mi w tym pomóc?
Amit Bera
1

Poniższe jest testowane w CE wer. 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;
    }
}

WAŻNE Musisz dostosować metody płatności, aby odzyskać całkowitą kwotę z oferty.

kiatng
źródło
To działa. Dzięki. Jak zgrupować ofertę koszyka według dostawcy? inne niż „// jeden przedmiot na zamówienie” ..
Syed Ibrahim
1
$group[] = $item; // all other items in one ordermoże pomieścić wiele elementów na zamówienie, możesz łatwo modyfikować, tak aby każdy sprzedawca miał swój własny $group.
kat.
Zaktualizowano i działa. Ale płatność jest rejestrowana tylko dla ostatniego zamówienia (jeśli podzielimy wiele zamówień). Jak musimy to zaktualizować? Muszę zebrać łączną sumę płatności.
Syed Ibrahim
Całkowita kwota znajduje się w obiekcie wyceny, można go załadować $quote->Mage::getModel('sales/quote')->load($lastOrder->getQuoteId()). Wtedy istnieje wiele sumy można pobrać z $quote, z których jeden jest$quote->getGrandTotal()
kiatng