Tuesday, May 26, 2015

Create Buy 1 Get 1 Free Promotion in Magento

Recently I was working on Magento admin where we have to create promotions like Buy 1 Get 1 Free. Initially I had a trouble setting it as I don't know much about Magento admin. So In this blog I am going to explain how to do it in 10 simple steps so it can save your time.

Step 1:
First of login to Magento Admin and Go to Promotions -> Shopping Cart Price Rules

Step 2:
Click on Add New Rule. (Button on top right corner)

Step 3:
Add a rule name and descriptions. Select customer groups.

Step 4:
Go to conditions tab.

Step 5:
Click on green + button and select option "Product Attribute Combination"

Step 6:
Now it should show you "If an item is FOUND  in the cart with ALL  of these conditions true:" Now click again on new + button at bottom of this text and select SKU from the drop down.

Step : 7
Now it should show you "SKU  is  ... " Click on three dots and Search the SKU of the product for which you want to set offer.

Step: 8
Now go to actions tab and select option "Percent of product price discount" from the Apply drop down.

Step: 9
Set 50 as value in Discount Amount Textbox.

Step 10:
Set two as value in Maximum Qty Discount is Applied To Textbox and save the rule.

That's it basically we gave 50% discount on total if there are product with 2 quantity in cart. This is how user has to pay for only one item and they get other item as free. Hope this helps you.

Monday, May 25, 2015

Magento API Add Promo Item To Cart

Hello,

Recently I was working on a project where we were working with MAgento API. There was a requirement to show promotions to user. I have published a post on this. You can check it from here

Now we had another requirement to add items of promo to cart when user purchase an item. Here in this blog I will explain how to do this. Please note this logic will work for Buy X and get Y product free and Buy X and get Y Free logic.

So in API we were passing rule_id. First we will get rule information.

Mage::app()->setCurrentStore($_storeId);
$rule = Mage::getModel('salesrule/rule')->load($_POST['rule_id']);

Now we will get all the rules conditions.

$conditions = $rule->getConditions()
$conditions = $rule->getConditions()->asArray();

Now we will get all the product SKUs  and qty involved in condition.

$conditionSkus = array();
$conditionQty = array();

foreach( $conditions['conditions'] as $_conditions ){
foreach( $_conditions['conditions'] as $_condition ){
if($_condition['attribute'] == 'sku'){
$string = explode(',', $_condition['value']);
for ($i=0; $i $conditionSkus[] = trim($string[$i]);
}
}else if($_condition['attribute'] == 'quote_item_qty'){
$string = explode(',', $_condition['value']);
for ($i=0; $i $conditionQty[] = trim($string[$i]);
}
}
}
}

As you can see above we have conditions as array and we get sku and number of qty. Number of qty will be useful if you have promos like Buy 2 get 1 Free.

$actions = $rule->getActions();
$actions = $rule->getActions()->asArray();
$actionSkus = array();
$actionQty = null;
if(isset($actions['conditions'])){
foreach( $actions['conditions'] as $_actions ){
$string = explode(',', $_actions['value']);
for ($i=0; $i $actionSkus[] = trim($string[$i]);
}
}
}
else{
$actionQty = $rule->discount_step;
}

In above code as you can see we are checking if there are any skus specified as free products. If there are not skus then it's buy x and get y offers so we are getting free qty from discount_step.

That's it now we just have to loop through array and add item to cart.

$arrProducts= array();
foreach($conditionSkus as $sku){
//load product from sku and get id
$qty = 1;
if(count($conditionQty) != 0){
$qty= $conditionQty[0];
}else if(isset($actionQty)){
$qty = $actionQty;
}
$product = Mage::getModel('catalog/product')->loadByAttribute('sku',$sku);
$product = Mage::getModel('catalog/product')->load($product->getId());
$arrProducts[] =  array(
"product_id" => $product->getId(),
"qty" => $qty
);
}

foreach($actionSkus as $sku){
//load product from sku and get id
$qty = 1;
$product = Mage::getModel('catalog/product')->loadByAttribute('sku',$sku);
$product = Mage::getModel('catalog/product')->load($product->getId());
$arrProducts[] =  array(
"product_id" => $product->getId(),
"qty" => $qty
);
}

$resultCartProductAdd = $client->call(
$session,
"cart_product.add",
array(
$quote_id,
$arrProducts
)
);

That's it and now promot items will be added to cart.


Friday, May 22, 2015

Magento API Get All Promotions

Hello,

Recently in one of my project we were building mobile app where we have backend as Magento. In this app we have to show all the promotions added in Magento as shopping cart rules. Also there was a requirement to get all the coupons. There is no API for that in default Magento API so I decided to write an API. Here is how to do this.

Mage::app()->setCurrentStore($_storeId);
   
    $rules = Mage::getResourceModel('salesrule/rule_collection')->load();

$comboOffers = array();
$coupons = array();
foreach ($rules as $rule) {
    if ($rule->getIsActive() && $rule->coupon_type == 1) {//No coupons only offers.
        $rule = Mage::getModel('salesrule/rule')->load($rule->getId());
        $comboOffers[] = array(
        "rule_id" => $rule->getId(),
        "name" => $rule->getName(),
        "description" => $rule->getDescription()
        );
        }else{
        $rule = Mage::getModel('salesrule/rule')->load($rule->getId());
        $coupons[] = array(
        "rule_id" => $rule->getId(),
        "name" => $rule->getName(),
        "description" => $rule->getDescription(),
        "coupon_code"=> $rule->getCouponCode()
        );
        }
    }

As you can see in above code we are first getting collection of all the sales rule and then loop trough it and separate offers and coupon. In case of offers like buy 1 get 1 free and percent discount there is no coupon code so coupon_type is set to 1 which means "No Coupon".  While for others there are coupons. So just checking by that we populated two different arrays and return it in form of JSON.

$MainArray['offers'] = $comboOffers;
$MainArray['coupons'] = $coupons;
$MainArray['success'] = true;
echo json_encode($MainArray);

That's it and you will have all the coupons and array of offers available in response. You can use this JSON data to display on screen.



Sunday, May 3, 2015

Laravel App Change TimeZone dynamically

Hello,

Recently I was working on mobile app where we have APIs return in Laravel. We were handling some date and times on server side. This dates and time from server side was displayed to mobile users. Now mobile users can be in different timezones and so APIs should set timezones and show dates and time according to timezone. Here is how I implemented it. I saved user's timezone in db and for each API request from that user set timezone from database.

First extend a laravel controller with base controller so we don't need to repeat this code everywhere.

class ApiController extends BaseController {
    public function __construct() {
         parent::__construct();
    }
}

Now go to BaseController and add constructor.

class BaseController {
        $employeeId = null;
        if(Input::has('employee_id')){
              $employeeId = Input::get('employee_id');
        }

        if($employeeId!=null){
            $employeeDetails = EmployeeDetails::find($employeeId);
            if($employeeDetails->timezone != null){
                Config::set('app.timezone', $employeeDetails->timezone);
                date_default_timezone_set($employeeDetails->timezone);
            }
        }
}

That's it and now you will have dynamic timezone as per user.

Sencha Touch Add Loading Mask on Each Ajax Request

Hello,

This is short and quick blog about how to add global logic to show and hide load mask for each Aajx request in Sencha Touch Application.

In Sencha Touch application Ajax request is used in two ways. Either one can call Ajax request with

Ext.Ajax.request({
})

Or in stores you may have Ajax proxy which will generate Ajax request when store is auto loaded or you call load method. Since this is background process you may want to show loading mask to users. For that you can call setMasked method before Ajax request and you remove that mask in success and failure function. This you have to write everywhere in your code. So it's better to add it to single place.

This how you can do it. Add following code to your launch function in your app.js file.

                Ext.Ajax.on("beforerequest", function(){
Ext.Viewport.setMasked(true);
});

Ext.Ajax.on("requestcomplete", function(){
Ext.Viewport.setMasked(false);
});

Ext.Ajax.on("requestexception(", function(){
Ext.Viewport.setMasked(false);
});

Since Ext.Ajax is singleton class we have added event handler for beforerequest, requestcomplete and requestexception.

In beforerequest event handler we are setting mask to viewport and in requestcomplete and requestexception handler we are removing it. That's it and the mask will be displayed every time there is a ajax request.  Hope this helps you. 

Add iOS in App Purchase to Your Cordova Application

Hello,

Recently I was working on cordova application where we have to add in app purchase in iOS. In this blog I am going to explain how to add in app purchase to cordova based application.

First of all open your MainViewController.m file and un comment following function.


- (BOOL) webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType

As we are going to use above function to pass product id to native code from JavaScript with use of this function. Here is how to do this. From your JavaScript file add following code.

window.location.href = 'http://buyproduct.com?productId='+sku.toLowerCase();

This will invoke shouldStartLoadWithRequest delegate. Now in that delegate add following code.

NSURL *url = [request URL];
if([[url hostisEqual: @"buyproduct.com"]){
        NSString *queryString = url.query;
        NSArray* queryStringValues = [queryString componentsSeparatedByString: @"&"];
        NSString* productId = [[[queryStringValues objectAtIndex:0] componentsSeparatedByString: @"="] objectAtIndex:1];
       return NO;
}

This way we get product id in native code and since we returned NO in that delegate, webview will not invoke this url.

Now let's add required library to support in App Purchase. First select project from project explorer and select build phases tab. At bottom where we have linked libraries click on + sign and search for storekit. It will show following framework. Add this to project.


Now open MainViewController.h file and add necessary import statements and delegates. Copy following code.

#import
#import
#import
#import

@interface MainViewController : CDVViewController <SKProductsRequestDelegate, UIAlertViewDelegate, SKPaymentTransactionObserver>
@property (retain, nonatomic) SKProduct* fetchedProduct;
@end
@interface MainCommandDelegate : CDVCommandDelegateImpl
@end

@interface MainCommandQueue : CDVCommandQueue
@end

Now open MainViewController.m file and add necessary callbacks.

#pragma mark -
#pragma mark SKProductsRequestDelegate methods

- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
    
}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    SKPayment * payment = [SKPayment paymentWithProduct:fetchedProduct];
    [[SKPaymentQueue defaultQueue] addPayment:payment];
}

- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
    for (SKPaymentTransaction * transaction in transactions) {
        switch (transaction.transactionState)
        {
            case SKPaymentTransactionStatePurchased:
                [self completeTransaction:transaction];
                break;
            case SKPaymentTransactionStateFailed:
                [self failedTransaction:transaction];
                break;
            case SKPaymentTransactionStateRestored:
                [self restoreTransaction:transaction];
            default:
                break;
        }
    };
}

- (void)completeTransaction:(SKPaymentTransaction *)transaction {
    
}

- (void)restoreTransaction:(SKPaymentTransaction *)transaction {
    NSLog(@"restoreTransaction...");
    //call javascript function to consume product only
    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}

- (void)failedTransaction:(SKPaymentTransaction *)transaction {
    
    NSLog(@"failedTransaction...");
    if (transaction.error.code != SKErrorPaymentCancelled)
    {
        NSLog(@"Transaction error: %@", transaction.error.localizedDescription);
    }
    
    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}

This are necessary functions to support transactions and product request. Now lets first request a product information. Go back to shouldStartLoadWithRequest and add following code at the end.

BOOL productPurchased = [[NSUserDefaults standardUserDefaults] boolForKey:productId];
        if (productPurchased) {
            //call javascript function to consume product
            [self.webView stringByEvaluatingJavaScriptFromString:@"consumePurchasedProduct();"];
        }else{
            SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];
            productsRequest.delegate = self;
            [productsRequest start];
        }

Here we are checking if product already purchased. If already purchased simply call JavaScript function to consume it else start product request. After we get product information we have to show it to user.  Add following code to productRequest delegate.

NSArray *products = response.products;
    fetchedProduct = [products count] == 1 ? [products firstObject] : nil;
    if (fetchedProduct)
    {
        NSLog(@"Product title: %@" , fetchedProduct.localizedTitle);
        NSLog(@"Product description: %@" , fetchedProduct.localizedDescription);
        NSLog(@"Product price: %@" , fetchedProduct.price);
        NSLog(@"Product id: %@" , fetchedProduct.productIdentifier);
        
        NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
        [formatter setNumberStyle:NSNumberFormatterCurrencyStyle];
        [formatter setLocale:[NSLocale currentLocale]];
        NSString *localizedMoneyString = [formatter stringFromNumber:fetchedProduct.price];

        NSString *productPrice = @"Price : ";
        productPrice = [productPrice stringByAppendingString:localizedMoneyString];
        NSString* alertViewContent = fetchedProduct.localizedDescription;
        alertViewContent = [alertViewContent stringByAppendingString:@"\n \n"];
        alertViewContent = [alertViewContent stringByAppendingString:productPrice];
        UIAlertView * alert = [[UIAlertView alloc] initWithTitle:fetchedProduct.localizedTitle message:alertViewContent delegate:self cancelButtonTitle:@"Buy" otherButtonTitles:nil];
        [alert show];
    }

Above function will show alert like this with product information.


As you can see we have a buy button there. When user clicks on Buy it will call clickedButtonAtIndex function added in above code and it will start payment process. One payment is done it will call completeTransaction delegate. Add following code to it.

NSLog(@"completeTransaction...");
    [[NSUserDefaults standardUserDefaults] setBool:YES forKey:fetchedProduct.productIdentifier];
    //call javascript function to consume product
    [self.webView stringByEvaluatingJavaScriptFromString:@"consumePurchasedProduct();"];
    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];

Here we are adding product to user defaults in case network got disconnected before user can consume product. In case of transaction failure other functions will be called.