한 번의 결제 또는 주문 분할에서 Magento 복수 주문


10

상점 제품은 다른 공급 업체에서 제공합니다. 한 번의 체크 아웃 중에 장바구니에있는 제품을 기반으로 모든 공급 업체에 대해 여러 주문을 작성해야합니다. 이 작업을 수행 할 수있는 확장 기능이 있습니까? 아니면 사용자 지정 체크 아웃 모듈을 개발해야합니다. 숙련 된 Magento 개발자의 확장 비전을 만들기위한 핫 포인트는 어떻습니까? Magento에 대해 간단한 체크 아웃 흐름 아키텍처를 설명 할 수 있습니까 (가능한 코드 수준)? 훨씬 더 감사합니다!


magento가 제공하는 Multishipping을 살펴보십시오. 그리고 수송선이 있지만 그것이 좋은지 또는 할 수 있는지 모르겠습니다. unirgy.com/products/udropship
Fabian Blechschmidt 2012 년

@ 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는 다음 orginal 한 대답에 위임 parent::save()하는 것으로했다 parent:saveOrder(). 이제 예제 코드에서 수정되었습니다.


내 비슷한 질문을 볼 수 있다면 감사하겠습니다! magento.stackexchange.com/questions/6974/…
CaitlinHavener

좋게도

1
Roy, 물론 부모가 있기 위해 원래 클래스를 확장해야하지만 간단한 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');
Diogo Santiago

1
@Vinai $ quote-> addItem ($ item); 이 코드는 작동하지 않습니다. 항목을 추가 한 후 foreach 루프의 도움으로 $ quote-> getAllItems ()를 에코합니다. 그러나 품목은 없었다. 제발 도와주세요?
Amit Bera

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

중요 견적에서 총계를 검색하려면 지불 방법을 사용자 정의해야합니다.


작동 중입니다. 감사. 공급 업체별로 카트 견적을 그룹화하는 방법은 무엇입니까? 다른 다음 "주문 당 하나의 항목"..
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.