Saturday, June 20, 2015

Magento Get All Products With Special Prices

Hello,

Recently in one of my projects we were working with Magento APIs. Where we have to fetch a list of all products with special prices to display hot deals on site. There are no APIs for this in Magento so I decided to write custom logic for that.

Here is how you can fetch it.

First get product collections.

$productCollection = Mage::getModel('catalog/product')->getCollection();
$productCollection->addAttributeToSelect(array(
        'image',
        'name',
        'price',
        'short_description'
 ))
 ->addFieldToFilter('visibility', array(
        Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH,
        Mage_Catalog_Model_Product_Visibility::VISIBILITY_IN_CATALOG
 ));

Then apply filter on product collection to get products with only special prices.

$productCollection->addAttributeToFilter('special_from_date', array('date' => true, 'to' => $todayDate))
                        ->addAttributeToFilter('special_to_date', array('or'=> array(
                        0 => array('date' => true, 'from' => $tomorrowDate),
                        1 => array('is' => new Zend_Db_Expr('null')))
                        ), 'left');

That's it and now it will give you collections of only those products for which there is a special price set.

Now just loop through it and add to array.

$hotDeals = array();
foreach ($productCollection as $product){
        $product = Mage::getModel('catalog/product')->load($product->getId());
$name = $product->getName();
$productPrice = number_format($product->getPrice(), 2, '.', ',');
$specialPrice = number_format($product->getSpecialPrice(), 2, '.', ',');

        $hotDeals[] = array(
"product_id" => $product->getId(),
"product_name" => $name,
"product_image" =>  ($product['image'] == 'no_selection') ? $skinUrl.'frontend/default/default/images/catalog/product/placeholder/thumbnail.jpg' : (string)Mage::helper('catalog/image')->init($product, 'image')->resize(60),
"product_price" => $productPrice,
"special_price" => $specialPrice
);
}

And return it as JSON array.

$resultArray['success'] = true;
$resultArray['hot_deals'] = $hotDeals;

echo json_encode($resultArray);

Hope this helps you.

Friday, June 19, 2015

Magento Load Quote Generated By API on Frontend

Hello,

Recently in one of my project we were using magento to implement checkout process for third party website. Basically we were using Magento APIs to create quote. Now for the paypal payment we were redirecting users to magento url and start checkout process by redirecting them to paypal and on successful payment redirect back to magento site, place and order and redirect them back to their site. Now the problem is when we redirect user to magento site to start checkout process there is no customer or checkout session hence checkout can not be started as shopping cart was empty. In this blog I am going to explain how to load quote generated by API on frontend and start checkout process.

First of all let me explain why we have to this changes. Magento has its own session management on front end. It will not load cart of there is no checkout session found on front end. So we have to store everything in frontend session so magento can remember it.

First of all you have to pass three params when user is redirecting to magento site. Following are three params required.

customer_id
quote_id
store_id

As on front end we have to set specific store and create customer session with customer_id and load shopping cart. I was using following URL for redirection.

http://yourmagento/paypal/express/start/button/1/?customer_id=1&store_id=3&quote_id=146

As you can see above we are directly starting checkout process and redirecting user to paypal. But before that we have to set store and generate customer session and load quote. So lets go step by step. First of all open following file.


app/code/core/Mage/Core/Controller/Varien/Front.php

and find following function.

/**
     * Init Front Controller
     *
     * @return Mage_Core_Controller_Varien_Front
     */
    public function init()
    {
    }

This function is called first for any magento URL request. So here are going to do some initialization steps.

First let's set up the store for which quote id was generated. Add following code to start of init function.

$storeId = '';
//////////////////////////////////////Setting up store id///////////////////////////
if(isset($_REQUEST['store_id'])){
        $storeId = $_REQUEST['store_id'];
    Mage::getSingleton('core/session')->setStoreId($_REQUEST['store_id']); 
}

if( Mage::getSingleton('core/session')->getStoreId()){
$storeId = Mage::getSingleton('core/session')->getStoreId();
}
switch($storeId){
case "1" : Mage::app()->setCurrentStore('store1');break;
case "2" : Mage::app()->setCurrentStore('store2');break;
default: Mage::app()->setCurrentStore('store1');break;
}
//////////////////////////////////////////////////////////////////////////////////////


First we are checking if there is store id in request then first we are storing it to magento core session. Later we are getting it from session and storing respective store. Please note this is required if you have multiple stores, else you can avoid this. In my case there were multiple stores. 

Now next step is to create customer session. Add following code after above code.

////////////////////////////////////////Setting up customer id////////////////////////
if(isset($_REQUEST['customer_id'])){
Mage::getSingleton('core/session')->setCustomerId($_REQUEST['customer_id']); 
}
        
if( Mage::getSingleton('core/session')->getCustomerId()){
Mage::getSingleton('customer/session')->loginById(Mage::getSingleton('core/session')->getCustomerId());
}
//////////////////////////////////////////////////////////////////////////////////////

Now next step is to store quote id in session so it can be used later.

/////////////////////////////////////////Saving Quote Id//////////////////////////////
if(isset($_REQUEST['quote_id'])){
Mage::getSingleton('core/session')->setQuoteId($_REQUEST['quote_id']); 
}
//////////////////////////////////////////////////////////////////////////////////////

Now open following file.

/app/code/core/Mage/Checkout/Model/Session.php

And check following function.

/**
     * Get checkout quote instance by current session
     *
     * @return Mage_Sales_Model_Quote
     */
    public function getQuote()
    {
    }

Add below code to the function after following line.

Mage::dispatchEvent('custom_quote_process', array('checkout_session' => $this));

//////////////////////////////////////////Returning quote stored in session////////////////////////
if(Mage::getSingleton('core/session')->getQuoteId()){
    $this->_quote = Mage::getModel('sales/quote')->setStore(Mage::app()->getStore())->load(Mage::getSingleton('core/session')->getQuoteId());
return $this->_quote;
}
///////////////////////////////////////////////////////////////////////////////////////////////////

That's it and now you can start checkout process with this quote. Hope this helps you. 

Thursday, June 18, 2015

Magento Cart Payment List API, Paypal Not Available

Hello,

Recently we were working on Magento API. Where we were implementing checkout process for a website using Magento platforms. Since we were integrating in third party website which was built on ASP.NET, we were using Magento API. Here we have faced an issue on Select Payment Method step, that Paypal was not coming in list. In this blog I am going to explain how to solve this issue.

Magento API cart_payment.list is the API we were using for this and Paypal was enabled but still were not getting it. The reason was because we were using Paypal Standard Checkout where user is redirected to Paypal website for Payment. Since API is called on backend and there is no UI for that, so there is no point of redirecting to site. Hence this Payment method was ignored in API. Check the following function in app/code/core/Mage/Checkout/Model/Cart/Payment/Api.php file.

/**
     * @param  $method
     * @param  $quote
     * @return bool
     */
    protected function _canUsePaymentMethod($method, $quote)
    {
        if (!($method->isGateway() || $method->canUseInternal())) {
            return false;
        }

        if (!$method->canUseForCountry($quote->getBillingAddress()->getCountry())) {
            return false;
        }

        if (!$method->canUseForCurrency(Mage::app()->getStore($quote->getStoreId())->getBaseCurrencyCode())) {
            return false;
        }

        /**
         * Checking for min/max order total for assigned payment method
         */
        $total = $quote->getBaseGrandTotal();
        $minTotal = $method->getConfigData('min_order_total');
        $maxTotal = $method->getConfigData('max_order_total');

        if ((!empty($minTotal) && ($total < $minTotal)) || (!empty($maxTotal) && ($total > $maxTotal))) {
            return false;
        }

        return true;
    }


Here as you can see It's checking if Payment method is Gateway or can be used internally. Since Paypal standard checkout can not be used in internally as user is redirected to Paypal site. So to solve this issue just comment following code in _canUsePaymentMethod function.

/*if (!($method->isGateway() || $method->canUseInternal())) {
            return false;
}*/

That's it and now cart_payment.list will return you Paypal in list. Please note ideally you have to override this code and should not change in core code.

Sunday, June 7, 2015

Android BroadCast Receiver vs Service

Hello,

Recently in one of my project we had a requirement to perform certain background task and I Was confused what to use for this. I was confused between BroadCast Receiver or Service. So I thought of digging more into it and here I am sharing my thoughts on this. After long time I am writing a blog without any code.

First lets understand what is BroadCast Receiver

BroadCast Receiver is meant to respond to certain events and intent. For example phone restart, or GCM message or certain other system events. So when this event occurs an intent is created and broadcast receiver are notified through this intent. Broadcast receiver will get this in onReceive method and then we can perform certain tasks.

Now let's understand what is service.

Service is meant to perform certain tasks in background without affecting user's activities in foreground. So for example a downloader. User started downloading and that can be handled in service so user don't have to wait for it to be finished. While the background service is running user can do his other activities.

So we can see both BroadCast Receiver and service do the same thing. They perform certain task in background so what shall we use for background task? The answer depends on how much time do you need to perform background tasks.

Broadcast receiver has time limit of 10 seconds. If the tasks is not completed in 10 seconds then this process is eligible to be killed or terminated by systems. So it could be chance that it gets terminated before process is finished.

While service has no time limits it can perform as long as possible and would be terminated only in extreme conditions. Android system will kill services at last only.

So the concept is clear for the time consuming tasks you have to use Service and for less time consuming tasks you shall use BroadCast Receiver. So for tasks like connecting to internet or downloading something so synching data to server a Service is recommended. While for the tasks like adding to local database or storing something to shared preferences or updating UI on certain events a BroadCast Receiver is recommended.

I hope my blog clears your doubt and helps you in choosing right thing for you. Do share your opinion in comments.