Несколько заказов Magento на одну кассу или разделение заказа

10

Магазинная продукция поставляется от разных поставщиков. Требуется создать несколько заказов для каждого поставщика на основе его товаров в корзине за один заказ. Есть ли расширение для решения этой задачи, или я должен начать разрабатывать пользовательский модуль проверки. А как насчет горячих точек для создания такого расширенного видения опытных разработчиков Magento? Можете ли вы объяснить мне краткую архитектуру потока покупок? Спасибо намного больше!

mageUz
источник
Посмотрите на Multishipping, которую предлагает magento из коробки. И есть дропшип, но я понятия не имею, хорошо ли это или что он может сделать. unirgy.com/products/udropship
Фабиан Блехшмидт,
@mageUz, ты работал ниже ответа? это не работает для меня .. Можете опубликовать свой код?
Манодж Кумар
@ManojKumar, да, я уже реализовал разделение порядка, используя логику многоадресного извлечения, я уверен, что приведенная ниже логика также отлично работает.
mageUz
@mageUz, при использовании этого кода в корзине пусто отображается .. Любые предложения ..
Манодж Кумар
Привет, это можно сделать с помощью модуля разделенной корзины на рынке store.webkul.com/Magento-Marketplace-Split-Cart.html . Спасибо
webkul

Ответы:

9

Это легко выполнимо с переписать checkout/type_onepageмодель.
В этом классе переопределите saveOrder()метод следующим образом:

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

Но имейте в виду, что в Magento платеж связан со счетом, а каждый счет связан с заказом.

Следовательно, это означает, что как только у вас будет несколько заказов, вы также разделите платежи . Так что это возможно только в том случае, если способ оплаты не требует взаимодействия с пользователем во время оплаты.

ОБНОВЛЕНИЕ : оригинальный ответ, делегированный на parent::save()который должен был быть parent:saveOrder(). Это исправлено в примере кода.

Vinai
источник
Буду признателен, если вы посмотрите на мой аналогичный вопрос! magento.stackexchange.com/questions/6974/…
CaitlinHavener
если бы вы смогли разделить заказ, используя приведенный выше код, как я пытаюсь сделать то же самое, но не без удачи
Дипак Малла
1
Рой, конечно, ты должен расширить исходный класс, чтобы быть родителем, но это простой PHP, он не имеет ничего общего с Magento. Метод saveOrderвсе еще присутствует и активен в Magento CE 1.9, как и всегда.
Винай
3
У меня была проблема с этим фрагментом, поскольку у 2-го порядка гранд-итоги и промежуточные итоги равны всему заказу. После отладки я обнаружил, что даже при удалении и повторном добавлении элементов он будет просто использовать элементы, кэшированные в адресе, после сбора Total из адреса ... Чтобы решить эту проблему, просто очистите для каждого адреса кэш элементов: $ address-> unsetData (' cached_items_all '); $ адресно> unsetData ( 'cached_items_nominal'); $ адресно> unsetData ( 'cached_items_nonnominal');
Диого Сантьяго
1
@Vinai $ quote-> addItem ($ item); этот код не работает. После добавления элемента я повторяю $ quote-> getAllItems () с помощью цикла foreach. Но не было ничего. Можете ли вы помочь мне в этом, пожалуйста?
Амит Бера
1

Следующее проверено в 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;
    }
}

ВАЖНО! Вам нужно настроить способы оплаты, чтобы получить общую сумму из предложения.

kiatng
источник
Это работает. Спасибо. Как сгруппировать котировки по поставщикам? другие, то есть "// один предмет на заказ" ..
Сайед Ибрагим
1
$group[] = $item; // all other items in one orderможно хранить несколько позиций на заказ, вы можете легко изменить так, чтобы у каждого поставщика был свой $group.
kiatng,
Обновился и работает. Но оплата взимается только за последний заказ (если мы разделим несколько заказов). Как нам нужно обновить это? Мне нужно собрать общую сумму оплаты.
Сайед Ибрагим
Общая сумма в объекте цитаты, вы можете загрузить его $quote->Mage::getModel('sales/quote')->load($lastOrder->getQuoteId()). Тогда есть много итогов $quote, из которых вы можете получить , один из которых$quote->getGrandTotal()
kiatng