1つのチェックアウトまたは注文分割でのMagentoの複数注文


10

ストア製品はさまざまなベンダーから提供されます。1回のチェックアウト中にカート内の製品に基づいて、すべてのベンダーに対して複数の注文を作成する必要があります。このタスクを達成するための拡張機能はありますか、またはカスタムチェックアウトモジュールの開発を開始する必要がありますか?Magentoの経験豊富な開発者のそのような拡張ビジョンを作成するためのホットポイントはどうですか?簡単なチェックアウトフローアーキテクチャMagentoフレンドリー(可能な限りコードレベル)を説明してくれませんか?どうもありがとう!


magentoが標準で提供するマルチシッピングをご覧ください。そしてドロップシップがありますが、それが良いのか、それが何をすることができるのか私にはわかりません。unirgy.com/products/udropship
Fabian Blechschmidt 2013年

@mageUz、あなたは答えの下で働きましたか?それは私のために働いていません。あなたのコードを投稿できますか?
Manoj Kumar

@ManojKumar、はい、私はすでにマルチアドレスチェックアウトロジックを使用して注文分割を実装しています。以下に示すロジックも完全に機能するはずです。
mageUz 2014

@mageUz、このコードを使用すると、ショッピングカートは空で表示されます。任意の提案..
Manoj Kumar 14

こんにちは、marketplace分割カートモジュール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()。これはサンプルコードで修正されています。


私の同様の質問を見ていただければ幸いです!magento.stackexchange.com/questions/6974/...
CaitlinHavener

私は同じことをやろうとしたがいますように、コードの上に使用して順序を分割することができましたない運なし
ディーパックMallah

1
もちろん、元のクラスを拡張して親になる必要がありますが、これは単純なPHPであり、Magentoとは関係ありません。このメソッドsaveOrderは、Magento CE 1.9でも以前と同様に存在し、アクティブです。
ビナイ

3
2つの注文の総計と小計が注文全体と等しいため、このスニペットに問題がありました。デバッグした後、アイテムを削除して再度追加した場合でも、アドレスからTotalを収集した後、アドレスキャッシュされたアイテムを使用することがわかりました...解決するには、アドレスごとにアイテムキャッシュをクリアします。$ 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 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;
    }
}

重要見積もりから総計を取得するには、支払い方法をカスタマイズする必要があります。


動いています。ありがとう。ベンダーごとにカート見積もりをグループ化する方法は?その他の場合は、「//注文ごとに1つのアイテム」..
Syed Ibrahim

1
$group[] = $item; // all other items in one order注文ごとに複数のアイテムを保持できるため、各ベンダーが独自のを持つように簡単に変更できます$group
kiatng 2018

更新され、動作しています。ただし、支払いは最後の注文に対してのみキャプチャされます(複数の注文を分割する場合)。これをどのように更新する必要がありますか?合計の支払い額を集める必要があります。
サイドイブラヒム

合計金額は見積オブジェクトにあり、でロードできます$quote->Mage::getModel('sales/quote')->load($lastOrder->getQuoteId())。次に、そこから取得できる合計が多数あります。その$quoteうちの1つは、$quote->getGrandTotal()
8:46にkiatngです。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.