Magento багаторазове замовлення на одну касу або розбиття замовлень


10

Продукція магазину постачається від різних постачальників. Потрібно створити кілька замовлень для кожного постачальника на основі його товарів у кошику протягом однієї каси. Чи є якесь розширення для досягнення цього завдання або я повинен почати розробляти спеціальний модуль оформлення замовлення. Як щодо гарячих точок для створення такого бачення розширень досвідчених розробників Magento? Чи можете ви пояснити мені коротку архітектуру потоку оформлення замовлення Magento friendly (наскільки можливий рівень коду)? Спасибі набагато більше!


Погляньте на мультишиппінг, який пропонує магенто з коробки. І є дропшип, але я поняття не маю, добре це чи що він вміє робити. unirgy.com/products/udropship
Fabian Blechschmidt

@mageUz, ти працював нижче відповіді ?. це не працює для мене .. Чи можете розмістити свій код?
Маной Кумар

@ManojKumar, так, я вже реалізував розділення замовлень за допомогою логіки оформлення замовлення на багато адреси, я впевнений, що логіка, наведена нижче, також працює чудово.
mageUz

@mageUz, при використанні цього коду Кошик порожній із зазначенням .. Будь-які пропозиції ..
Manoj Kumar

Привіт, що можна зробити за допомогою модуля розділених кошиків на ринку market.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(). Він зафіксований у прикладі коду зараз.


Буду вдячний, якщо ви могли поглянути на моє подібне запитання! magento.stackexchange.com/questions/6974/…
CaitlinHavener

чи змогли ви розділити замовлення за допомогою наведеного вище коду, оскільки я намагаюся зробити те саме, але не без удачі
Deepak Mallah

1
Рой, звичайно, ти повинен розширити оригінальний клас, щоб там був батько, але це простий PHP, він не має нічого спільного з Magento. Цей метод saveOrderвсе ще присутній і діє в Magento CE 1.9 так само, як це було завжди.
Vinai

3
У мене виникла проблема з цим фрагментом, оскільки 2 порядку мають грантотальний і субтотальний рівень, який дорівнює цілому. Після налагодження я з'ясував, що навіть видаляючи та повторно додаючи елементи, він буде просто використовувати кешовані адреси адреси після збору загальної форми адреси ... Щоб вирішити це, просто очистіть для кожної адреси кеш елементів: $ address-> unsetData (' cached_items_all '); $ address-> unsetData ('cached_items_nominal'); $ address-> unsetData ('cached_items_nonnominal');
Діого Сантьяго

1
@Vinai $ quote-> addItem ($ item); цей код не працює. Після додавання елемента я повторюю $ quo-> getAllItems () за допомогою циклу foreach. Але пункту не було. Чи можете ви мені допомогти в цьому?
Аміт Бера

1

Далі випробувано в 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;
    }
}

ВАЖЛИВО: Вам потрібно налаштувати свої способи оплати, щоб отримати загальну суму з котирування.


Це працює. Дякую. Як згрупувати котирування кошика від продавця? інше тоді "// один предмет на замовлення" ..
Syed Ibrahim

1
$group[] = $item; // all other items in one orderможе містити кілька предметів за замовлення, ви можете легко змінити такі, щоб кожен постачальник мав свою власну $group.
кіатнг

Оновлено і працює. Але платіж береться лише за останнє замовлення (якщо ми розділимо декілька замовлень). Як нам потрібно це оновити? Мені потрібно зібрати загальну суму сумісних платежів.
Сиед Ібрагім

Загальна сума знаходиться в об'єкті цитування, ви можете завантажити його $quote->Mage::getModel('sales/quote')->load($lastOrder->getQuoteId()). Тоді є багато підсумків, з яких можна отримати $quote, один з яких$quote->getGrandTotal()
кіатнг
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.