Question

I have an order flow outside of Magento that uses both Magento's direct methods and API SOAP methods to create an order. (The API was used completely at first until we found out it wouldn't pass the payment on order completion) For the most part, it works great, except when it comes to bundle products. Our bundle products have 2 simple products with in, and when the order completes, one of the products is in the bundle, and the other is added separately. I've tracked it down to when my custom class gets the re-fetches the quote instead of using the existing quote, but then the shipping doesn't get added, even though it does go through the shipping methods. I can't figure out what would cause that to happen.

My custom class:

class createOrder{
    // Variables, construct, and address stuff here
    function getParams($item){
        $super_group = array();
        $parentId = $item['parentID'];
        $children = array($item['childID']);
        $child_qty = $item['qty'];
        foreach($children as $child){
            if(intval($child)){
                $super_group[$child] = $child_qty;
            }
        }
        // set params for product
        if (!empty($super_group)) {
            $params = array('super_group' => $super_group);
        }
        else {
            // bundled product
            if ($parentId == 121) { //Product1:
                $params = array(
                    'product' => '121',
                    'related_product' => '',
                    'qty' => "{$item['qty']}",
                    'bundle_option' => array(7=>'3',8=>'14'),
                    'bundle_option_qty' => array(7=>'1',8=>'1'),
                );
            }
            else if ($parentId == 120) { //Product2:
                $params = array(
                    'product' => '120',
                    'related_product' => '',
                    'qty' =>"{$item['qty']}",
                    'bundle_option' => array(5=>"1",6=>"2"),
                );
            }
            else if ($parentId == 146) { //Product3:
                $params = array(
                    'product' => '146',
                    'related_product' => '',
                    'qty' => "{$item['qty']}",
                    'bundle_option' => array(13=>'9',14=>'10'),
                );
            }
            else if($parentId == 382){ //Product4:
                $params = array(
                    'product' => '382',
                    'related_product' => '',
                    'qty' => "{$item['qty']}",
                    'bundle_option' => array(15=>'11',16=>'12'),
                    'bundle_option_qty'=>array(15=>'1',16=>'1'),
                );
            }   
        }
        return $params;
    }

    function completeOrder($shopping_cart_id,$pay,$gift = null,$newOTO = false){
        Mage::log(' -- start completeOrder ---');
        $error = NULL;

        // Get quote and set stuff
        // With this uncommented, products added correctly, but no shipping
        // if(!empty($this->_quote))
            // $quote = $this->_quote;
        // else
            $quote = Mage::getModel('sales/quote')->load($shopping_cart_id);
        $quote->setIsMultiShipping(false);
        $quote->setCheckoutMethod('guest');
        $quote->setCustomerId(null);
        if(isset($_SERVER['REMOTE_ADDR']))
            $quote->setRemoteIp($_SERVER['REMOTE_ADDR']);

        if(isset($_SERVER['HTTP_X_FORWARDED_FOR']))
            $quote->setXForwardedFor($_SERVER['HTTP_X_FORWARDED_FOR']);

        $quote->setCustomerGroupId(Mage_Customer_Model_Group::NOT_LOGGED_IN_ID);
        $quote->reserveOrderId();

        // Add shipping
        $quote->getShippingAddress()->setCollectShippingRates(true);
        $quote->getShippingAddress()->collectShippingRates();

        // $quote->collectTotals();
        $quote->save();

        $payment=$quote->getPayment();
        $convertQuote = Mage::getSingleton('sales/convert_quote');
        $order = $convertQuote->addressToOrder($quote->getShippingAddress());

        $order->setPayment($convertQuote->paymentToOrderPayment($payment));
        $order->getPayment()->setCcNumber($pay['cc_number']);
        $order->getPayment()->setCcType($payment->getCcType());
        $order->getPayment()->setCcExpMonth($payment->getCcExpMonth());
        $order->getPayment()->setCcExpYear($payment->getCcExpYear());
        $order->getPayment()->setCcLast4(substr($pay['cc_number'],-4));

        $order->setBillingAddress($convertQuote->addressToOrderAddress($quote->getBillingAddress()));
        $order->setShippingAddress($convertQuote->addressToOrderAddress($quote->getShippingAddress()));
        foreach($quote->getAllItems() as $item){
            $orderItem = $convertQuote->itemToOrderItem($item);
            if ($item->getParentItem()) {
                $orderItem->setParentItem($order->getItemByQuoteItemId($item->getParentItem()->getId()));
            }
            $order->addItem($orderItem);
        }

        try{
            $order->place();
            $order->save();

            $this->orderID = $order->getIncrementId();
            if($newOTO)
                $order->sendNewOrderEmail();
        } catch (Exception $e){
            Mage::log($e->getMessage());
            Mage::log($e->getTraceAsString());
            if($e->getMessage() == "Error in capturing the payment") {
                $error = "A problem has occured with the credit card you are providing. Please try again, or call us at 1-877-371-1807.";
            }
            else {
                $error = "There has been an error placing your order. Please review the information below.";
            }
        }
        return $error;  
    }

These get called with :

Products and Shipping:

foreach ($_SESSION['cart'] as $item) {
    Mage::log('item');
    $params = $OTOrder->getParams($item);
    $parentId = $item['parentID'];
    $parentIDs[] = $parentId;
    if($parentId) {
        try {
            //Get object of main grouped product
            $product = Mage::getModel('catalog/product')->load($parentId);

            //Check product availability
            if (!$product) {
                Mage::log("Error in product! ".$parentId);
                return;
            }

            //Get cart object
            $cart = Mage::getModel('checkout/cart');
            $quote = Mage::getModel('sales/quote')->load($shopping_cart_id);
            if (!$quote) {
                Mage::log("Error in quote! ".$parentId);
                return;
            }
            //Add product to cart with specified parameters and save the cart object
            $quote->addProduct($product, new Varien_Object($params))->save();
            $quote->collectTotals()->save();
            $OTOrder->setQuote($quote);
            Mage::getSingleton('checkout/session')->setCartWasUpdated(true);

        }
        catch (Mage_Core_Exception $e){
            $_SESSION['orderError'] = 'Error in "'.$item['desc'].'"';
            Mage::log("parentID: ".$e->getMessage());
            if (Mage::getSingleton('checkout/session')->getUseNotice(true)){
                header("Location: OrderForm.php?keycode=" . $keystring);
                exit;
            }
            else{
                $messages = array_unique(explode("\n", $e->getMessage()));
                foreach ($messages as $message) {
                    $_SESSION['orderError'] .= "<br />".$message;
                }
                header("Location: OrderForm.php?keycode=" . $keystring);
                exit;
            }
        }
        catch (Exception $e){
            $_SESSION['orderError'] = 'Error in "'.$item['desc'].'"';
            $_SESSION['orderError'] .= "Cannot add the item to shopping cart.";
            Mage::log("Adding product: ".$e->getMessage());
            header("Location: OrderForm.php?keycode=" . $keystring);
            exit;
        } 
    }
}
    $pass = false;
while(!$pass) {
    try{
        $methods = $soap->shoppingCartShippingList($session_id, $shopping_cart_id);
        foreach($methods as $method){
            if($method->method_title != 'Priority')
                $shipCode = $method->code;              
        }
        if(!empty($shipCode))
            $soap->shoppingCartShippingMethod($session_id, $shopping_cart_id, $shipCode);
        $pass = true;
    }
    catch(Exception $e)
    {
        if($e->getMessage() == 'Error Fetching http headers')
            $pass == false;
        else{
            $_SESSION['orderError'] = "Problem with billing or shipping address.";
            $_SESSION['error'] = true;
            Mage::log("shoppingCartShippingList: ".$e->getMessage());
            header("Location: OrderForm.php?keycode=" . $keystring);
            exit;
        }
    }
}

The order completion is called with:

$err = $OTOrder->completeOrder($shopping_cart_id,$paymentMethod,$giftOption);
Was it helpful?

Solution 2

Since re-fetching the quote at the beginning of my function messed up the bundle products, I just emptied the cart and re-entered all of the products. I created an array:

$allProducts[$parentId] = $params;

Stored that with $OTOrder->setProducts(), and then changed my function to this:

function completeOrder($shopping_cart_id,$pay,$gift = null,$newOTO = false){
    Mage::log(' -- start completeOrder ---');
    $error = NULL;

    $quote = Mage::getModel('sales/quote')->load($shopping_cart_id);

    foreach($quote->getAllItems() as $item){
        $quote->removeItem($item->getId()); 
    }
    $quote->save();
    foreach($this->_products as $parentId=>$params)
    {
        //Get object of main grouped product
        $product = Mage::getModel('catalog/product')->load($parentId);

        //Check product availability
        if (!$product) {
            Mage::log("Error in product! ".$parentId);
            return;
        }

        //Get cart object
        $cart = Mage::getModel('checkout/cart');
        $quote = Mage::getModel('sales/quote')->load($shopping_cart_id);
        if (!$quote) {
            Mage::log("Error in quote! ".$parentId);
            return;
        }
        //Add product to cart with specified parameters and save the cart object
        $quote->addProduct($product, new Varien_Object($params))->save();
        $quote->collectTotals()->save();
        Mage::getSingleton('checkout/session')->setCartWasUpdated(true);
    }

It's bulkier than I'd like, but it seems to work.

OTHER TIPS

I was able to create an order with a bundle product using the following code

<?php

require_once 'app/Mage.php';
define('MAGENTO_ROOT', getcwd());

$compilerConfig = MAGENTO_ROOT . '/includes/config.php';
if (file_exists($compilerConfig)) {
    include $compilerConfig;
}

class JLR_Orders_Create {
  public function CreateOrder2() {

        try {
            $storeObject = Mage::getModel('core/store')->load(4); // Store ID
        }
        catch(Exeception $ex)
        {
            echo $ex->getMessage();
        }


        $cart_api = Mage::getModel('checkout/cart_api');
        $quoteId = $cart_api->create($storeObject->getStoreId());
        $quote = Mage::getModel('sales/quote')->loadByIdWithoutStore($quoteId);

        $product = Mage::getModel('catalog/product');
        $productId = $product->getIdBySku('SBTEMP075'); // Bundle Product SKU

        $params = array(
            'product' =>  $productId,
            'related_product' => null,
            'bundle_option' => array(
                    164 => '3235', // Bundle Options
                    165 => '3240',
                    166 => '3241'

                ),
             'bundle_option_qty' => array(
                    164 => 1, // Bundle Quantities
                    165 => 1,
                    166 => 1
                ),
        );

        $request = new Varien_Object();
        $request->setData($params);

        $_value['Email'] = 'ZsdfsXcrtdfert@gmail.com';
        $_value['First Name'] = 'Jeffrey';
        $_value['Last Name'] = 'Roberts';
        $_value['Address'] = 'Biscayne Blvd';
        $_value['City'] = 'Miami';
        $_value['Post Code'] = '33137';
        $_value['Telephone'] = '305-555-1155';

        // create customer
        $customer = Mage::getModel('customer/customer');
        $password = 'stackexchange';

        $customer->setWebsiteId(4); // Set Website ID
        $customer->loadByEmail($_value['Email']);
        $customer->setWebsiteId(4); // Set Website ID AGAIN!

        if(!$customer->getId()) {
            $customer->setEmail($_value['Email']);
            $customer->setFirstname($_value['First Name']);
            $customer->setLastname($_value['Last Name']);
            $customer->setPassword($password);
            $customer->setMode(Mage_Checkout_Model_Cart_Customer_Api::MODE_REGISTER);
        }
        else
        {
            $customer->setMode(Mage_Checkout_Model_Cart_Customer_Api::MODE_CUSTOMER);
        }

        try {
            $customer->save();
            $customer->setConfirmation(null);
            $customer->save();
        }
        catch (Exception $ex) {
            error_log(var_dump($ex));
        }

        if (! $customer->getId() ){
            return $this;                
        }

        $dataShipping = array(
            'firstname'  => $_value['First Name'],
            'lastname'   => $_value['Last Name'],
            'street'     => $_value['Address'],
            'city'       => $_value['City'],
            'region'     => '',
            'region_id'  => '',
            'postcode'   => $_value['Post Code'],
            'country_id' => 'CZ', //todo: un-hardcode this.
            'telephone'  => $_value['Telephone'],
        );

        $customerAddress = Mage::getModel('customer/address');

        if ($defaultShippingId = $customer->getDefaultShipping()){
             $customerAddress->load($defaultShippingId); 
        } else {   
             $customerAddress
                ->setCustomerId($customer->getId())
                ->setIsDefaultShipping('1')
                ->setSaveInAddressBook('1')
             ;
             $customer->addAddress($customerAddress);
        }            

        try {
            $customerAddress
                ->addData($dataShipping)
                ->save()
            ;           
        } catch(Exception $e){
            Mage::log('Address Save Error::' . $e->getMessage());
        }

        $customer->save();

        $product = new Mage_Catalog_Model_Product();
        $product->load($productId);

        $quote->addProduct($product, $request);
        $quote->setCustomer($customer);
        $quote->assignCustomer($customer);
        $quote->getShippingAddress()->addData($dataShipping)->setShippingMethod('tablerate_bestway');
        $quote->getShippingAddress()->setShippingMethod('tablerate_bestway');
        $quote->getShippingAddress()->setCollectShippingRates(true);
        $quote->getShippingAddress()->collectShippingRates(); 
        $quote->setPayment($quote->getPayment()->setMethod('free'));
        $quote->collectTotals();
        $quote->save();

        $convertQuoteObj = Mage::getModel('sales/convert_quote');
        $orderObj = $convertQuoteObj->toOrder($quote);

        $orderPaymentObj=$convertQuoteObj->paymentToOrderPayment($quote->getPayment());

        $orderObj->setBillingAddress($convertQuoteObj->addressToOrderAddress($quote->getBillingAddress()));
        $orderObj->setPayment($convertQuoteObj->paymentToOrderPayment($quote->getPayment()));
        $orderObj->setShippingAddress($convertQuoteObj->addressToOrderAddress($quote->getShippingAddress()));


        $qty=1;
        foreach ($quote->getShippingAddress()->getAllItems() as $item) {
            //@var $item Mage_Sales_Model_Quote_Item
            $item->setQty($qty);
            $orderItem = $convertQuoteObj->itemToOrderItem($item);
            if ($item->getParentItem()) {
                $orderItem->setParentItem($orderObj->getItemByQuoteItemId($item->getParentItem()->getId()));
            }
            $orderObj->addItem($orderItem);
        }

        $orderObj->setCanShipPartiallyItem(false);

        $totalDue=$orderObj->getTotalDue();
        echo "<p>total due: $totalDue</p>";
        $orderObj->place(); //calls _placePayment
        $orderObj->save();
        $orderId=$orderObj->getId();
        echo "<p>orderId: $orderId</p>";

    }
}

Mage::app();

$JLR = new JLR_Orders_Create();
$JLR->CreateOrder2();
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top