Magento สั่งซื้อหลายครั้งในการชำระเงินหนึ่งครั้งหรือแยกการสั่งซื้อ


10

ผลิตภัณฑ์ของร้านค้านั้นมาจากผู้ขายที่แตกต่างกัน จำเป็นต้องสร้างคำสั่งซื้อหลายรายการสำหรับผู้ขายทุกรายโดยพิจารณาจากผลิตภัณฑ์ในตะกร้าในระหว่างการชำระเงินครั้งเดียว มีส่วนขยายใด ๆ เพื่อให้บรรลุภารกิจนี้หรือฉันควรเริ่มพัฒนาโมดูลการชำระเงินที่กำหนดเอง สิ่งที่เกี่ยวกับจุดร้อนในการสร้างวิสัยทัศน์ส่วนขยายของนักพัฒนาที่มีประสบการณ์ของ Magento? คุณช่วยอธิบายฉันสั้น ๆ เกี่ยวกับสถาปัตยกรรมการชำระเงินแบบย่อ ๆ วีโอไอพีได้มากที่สุดเท่าที่จะทำได้หรือไม่ ขอบคุณมาก ๆ !


ลองดู Multishipping ที่วีโอไอพีนำเสนอนอกกรอบ และมี dropship แต่ฉันไม่รู้ว่ามันดีหรืออะไรที่มันสามารถทำได้ unirgy.com/products/udropship
Fabian Blechschmidt

@mageUz คุณทำงานด้านล่างคำตอบ? มันไม่ทำงานสำหรับฉัน .. สามารถโพสต์รหัสของคุณได้ไหม
Manoj Kumar

@ManojKumar ใช่แล้วฉันได้ดำเนินการแยกคำสั่งโดยใช้ตรรกะการชำระเงินที่มีผู้ส่งหลายคนฉันมั่นใจว่าตรรกะที่ระบุด้านล่างนี้ทำงานได้อย่างสมบูรณ์
mageUz

@mageUz เมื่อใช้รหัสนี้ตะกร้าสินค้าว่างเปล่าแสดง .. ข้อเสนอแนะใด ๆ ..
Manoj Kumar

สวัสดีที่สามารถทำได้โดยใช้ตลาดรถเข็นแยกโมดูล 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 การชำระเงินจะเชื่อมโยงกับใบแจ้งหนี้และใบแจ้งหนี้แต่ละใบจะเชื่อมโยงกับการสั่งซื้อ

ด้วยเหตุนี้หมายความว่าทันทีที่คุณมีคำสั่งซื้อหลายรายการคุณจะได้แบ่งการชำระเงินด้วย ดังนั้นวิธีนี้จะทำได้ก็ต่อเมื่อวิธีการชำระเงินไม่ต้องการการโต้ตอบกับผู้ใช้ในระหว่างการชำระเงิน

UPDATE : คำตอบเดิมมอบหมายให้ซึ่งจะต้องมีการparent::save() parent:saveOrder()มันได้รับการแก้ไขในโค้ดตัวอย่างทันที


จะขอบคุณถ้าคุณสามารถดูคำถามที่คล้ายกันของฉัน! magento.stackexchange.com/questions/6974/…
CaitlinHavener

เป็นคุณสามารถที่จะแยกคำสั่งซื้อโดยใช้รหัสข้างต้นที่ผมกำลังพยายามที่จะทำเช่นเดียวกัน แต่ไม่โชคใด ๆ
Deepak มัลละห์

1
แน่นอนว่าคุณต้องขยายชั้นเรียนดั้งเดิมเพื่อที่จะได้เป็นพ่อแม่ แต่นั่นก็คือ PHP อย่างง่ายมันไม่มีอะไรเกี่ยวข้องกับ Magento วิธีsaveOrderยังคงมีอยู่และใช้งานได้ใน Magento CE 1.9 เช่นเดียวกับที่เคยเป็นมา
Vinai

3
ฉันมีปัญหากับข้อมูลโค้ดนี้เนื่องจากคำสั่งซื้อ 2 รายการมียอดรวมและยอดรวมเท่ากับยอดสั่งซื้อทั้งหมด หลังจากตรวจแก้จุดบกพร่องฉันพบว่าแม้กระทั่งการลบและเพิ่มรายการอีกครั้งมันก็จะใช้ที่อยู่รายการที่เก็บไว้หลังจากที่รวบรวมแบบฟอร์มที่อยู่ ... เพื่อแก้ปัญหาเพียงล้างแต่ละรายการแคชรายการ: $ address-> unsetData (' cached_items_all '); $ อยู่ของ> unsetData ( 'cached_items_nominal'); $ อยู่ของ> unsetData ( 'cached_items_nonnominal');
Diogo Santiago

1
@Vinai $ quote-> addItem ($ item); รหัสนี้ไม่ทำงาน หลังจากเพิ่มรายการฉัน echo $ quote-> getAllItems () ด้วยความช่วยเหลือของ foreach loop แต่ไม่มีรายการ คุณช่วยฉันในเรื่องนี้ได้มั้ย
Amit Bera

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สามารถถือหลายรายการต่อคำสั่งซื้อที่คุณสามารถปรับเปลี่ยนเช่นกันว่าผู้ขายมีของตัวเอง
kiatng

อัปเดตแล้วและใช้งานได้ แต่การชำระเงินจะถูกจับสำหรับการสั่งซื้อครั้งสุดท้ายเท่านั้น (หากเราแยกหลายคำสั่งซื้อ) เราจำเป็นต้องอัพเดทสิ่งนี้อย่างไร ฉันต้องรวบรวมยอดรวมการชำระเงินทั้งหมด
Syed Ibrahim

$quote->Mage::getModel('sales/quote')->load($lastOrder->getQuoteId())จำนวนเงินทั้งหมดที่อยู่ในวัตถุที่อ้างคุณสามารถโหลดมันด้วย จากนั้นมีจำนวนรวมที่คุณสามารถเรียกคืนได้จาก$quoteหนึ่งในนั้นคือ$quote->getGrandTotal()
kiatng
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.