Magento一张结帐或订单拆分中的多个订单


10

商店产品由不同的供应商提供。在一次结帐期间,需要根据购物车中的产品为每个供应商创建多个订单。有没有扩展可以实现此任务,还是应该开始开发自定义结帐模块。那么如何为经验丰富的Magento开发人员建立这样的扩展视野的热点呢?您能解释一下Magento友好的简短结帐流程体系结构(可能是代码级别)吗?多谢!


看看magento开箱即用的Multishipping。而且有运输,但是我不知道它是好还是能做。unirgy.com/products/udropship
Fabian Blechschmidt

@mageUz,您是否在回答以下工作?它对我不起作用。可以发布您的代码吗?
Manoj Kumar 2014年

@ManojKumar,是的,我已经使用多地址签出逻辑实现了订单拆分,我相信下面给出的逻辑也可以完美地工作。
mageUz 2014年

@mageUz,使用此代码时,购物车为空显示..任何建议..
Manoj Kumar

嗨,您可以使用市场拆分购物车模块store.webkul.com/Magento-Marketplace-Split-Cart.html来完成 。谢谢
webkul 2015年

Answers:


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 2014年

1
Roy,当然,您必须扩展原始类以使其具有父级,但这是简单的PHP,与Magento无关。该方法saveOrder仍然是在Magento CE 1.9,就像它一直存在并活跃。
维奈2014年

3
我对这个摘要有疑问,因为2阶的大和小计等于整个阶。调试后,我发现即使删除并重新添加项目,在从地址汇总表中收集地址后,它也将仅使用地址缓存的项目...要解决此问题,只需为每个地址清除项目缓存:$ address-> unsetData(' cached_items_all'); $ address-> unsetData('cached_items_nominal'); $ address-> unsetData('cached_items_nonnominal');
圣地亚哥

1
@Vinai $ quote-> addItem($ item); 此代码不起作用。添加项目后,我在foreach循环的帮助下回显$ quote-> getAllItems()。但是没有项目。你能帮我吗?
阿米特·贝拉

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

重要信息您需要自定义付款方式以从报价中检索总计。


这是工作。谢谢。如何按供应商分组购物车报价?其他则“每个订单//一个项目” ..
赛义德·易卜拉欣

1
$group[] = $item; // all other items in one order每个订单可以容纳多个商品,您可以轻松进行修改,使每个供应商都有自己的$group
kiatng

更新,它正在工作。但付款仅针对最后一个订单(如果我们拆分多个订单)。我们该如何更新呢?我需要收集总计的付款。
Syed Ibrahim

总金额在quote对象中,您可以使用加载$quote->Mage::getModel('sales/quote')->load($lastOrder->getQuoteId())。然后,您可以从中找到许多总计$quote,其中之一是$quote->getGrandTotal()
kiatng
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.