Subversion Repositories SmartDukaan

Rev

Rev 15123 | Rev 15139 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

from bson import json_util
from bson.json_util import dumps
from datetime import datetime, timedelta
from dtr import main
from dtr.config import PythonPropertyReader
from dtr.storage import Mongo
from dtr.storage.DataService import Retailers, Users, CallHistory, RetryConfig, \
    RetailerLinks
from dtr.utils import FetchLivePrices, DealSheet as X_DealSheet, \
    UserSpecificDeals
from elixir import *
from sqlalchemy.sql.expression import or_
from urllib import urlencode
import contextlib
import falcon
import json
import traceback
import urllib
import urllib2
import uuid
global RETAILER_DETAIL_CALL_COUNTER
RETAILER_DETAIL_CALL_COUNTER = 0

DEALER_RETRY_FACTOR = int(PythonPropertyReader.getConfig('DEALER_RETRY_FACTOR'))
class CategoryDiscountInfo(object):
    
    def on_get(self, req, resp):
        
        result = Mongo.getAllCategoryDiscount()
        json_docs = [json.dumps(doc, default=json_util.default) for doc in result]
        resp.body = json.dumps(json_docs, encoding='utf-8')
    
    def on_post(self, req, resp):
        try:
            result_json = json.loads(req.stream.read(), encoding='utf-8')
        except ValueError:
            raise falcon.HTTPError(falcon.HTTP_400,
                'Malformed JSON',
                'Could not decode the request body. The '
                'JSON was incorrect.')
            
        result = Mongo.addCategoryDiscount(result_json)
        resp.body = json.dumps(result, encoding='utf-8')
    
    def on_put(self, req, resp, _id):
        try:
            result_json = json.loads(req.stream.read(), encoding='utf-8')
        except ValueError:
            raise falcon.HTTPError(falcon.HTTP_400,
                'Malformed JSON',
                'Could not decode the request body. The '
                'JSON was incorrect.')
            
        result = Mongo.updateCategoryDiscount(result_json, _id)
        resp.body = json.dumps(result, encoding='utf-8')
            
        
        
class SkuSchemeDetails(object):
    
    def on_get(self, req, resp):
        
        offset = req.get_param_as_int("offset")
        limit = req.get_param_as_int("limit")
        
        result = Mongo.getAllSkuWiseSchemeDetails(offset, limit)
        json_docs = [json.dumps(doc, default=json_util.default) for doc in result]
        resp.body = json.dumps(json_docs, encoding='utf-8')

    
    def on_post(self, req, resp):
        
        multi = req.get_param_as_int("multi")
        
        try:
            result_json = json.loads(req.stream.read(), encoding='utf-8')
        except ValueError:
            raise falcon.HTTPError(falcon.HTTP_400,
                'Malformed JSON',
                'Could not decode the request body. The '
                'JSON was incorrect.')
            
        result = Mongo.addSchemeDetailsForSku(result_json, multi)
        resp.body = json.dumps(result, encoding='utf-8')
        
class SkuDiscountInfo():
    
    def on_get(self, req, resp):
        
        offset = req.get_param_as_int("offset")
        limit = req.get_param_as_int("limit")
        result = Mongo.getallSkuDiscountInfo(offset,limit)
        json_docs = [json.dumps(doc, default=json_util.default) for doc in result]
        resp.body = json.dumps(json_docs, encoding='utf-8')

    
    def on_post(self, req, resp):
        
        multi = req.get_param_as_int("multi")
        
        try:
            result_json = json.loads(req.stream.read(), encoding='utf-8')
        except ValueError:
            raise falcon.HTTPError(falcon.HTTP_400,
                'Malformed JSON',
                'Could not decode the request body. The '
                'JSON was incorrect.')
            
        result = Mongo.addSkuDiscountInfo(result_json, multi)
        resp.body = json.dumps(result, encoding='utf-8')
        
    def on_put(self, req, resp, _id):
        try:
            result_json = json.loads(req.stream.read(), encoding='utf-8')
        except ValueError:
            raise falcon.HTTPError(falcon.HTTP_400,
                'Malformed JSON',
                'Could not decode the request body. The '
                'JSON was incorrect.')
            
        result = Mongo.updateSkuDiscount(result_json, _id)
        resp.body = json.dumps(result, encoding='utf-8')

class ExceptionalNlc():
    
    def on_get(self, req, resp):
        
        offset = req.get_param_as_int("offset")
        limit = req.get_param_as_int("limit")
        
        result = Mongo.getAllExceptionlNlcItems(offset, limit)
        json_docs = [json.dumps(doc, default=json_util.default) for doc in result]
        resp.body = json.dumps(json_docs, encoding='utf-8')
    
    def on_post(self, req, resp):
        
        multi = req.get_param_as_int("multi")
        
        try:
            result_json = json.loads(req.stream.read(), encoding='utf-8')
        except ValueError:
            raise falcon.HTTPError(falcon.HTTP_400,
                'Malformed JSON',
                'Could not decode the request body. The '
                'JSON was incorrect.')
            
        result = Mongo.addExceptionalNlc(result_json, multi)
        resp.body = json.dumps(result, encoding='utf-8')
    
    def on_put(self, req, resp, _id):
        try:
            result_json = json.loads(req.stream.read(), encoding='utf-8')
        except ValueError:
            raise falcon.HTTPError(falcon.HTTP_400,
                'Malformed JSON',
                'Could not decode the request body. The '
                'JSON was incorrect.')
            
        result = Mongo.updateExceptionalNlc(result_json, _id)
        resp.body = json.dumps(result, encoding='utf-8')
        
class Deals():
    def on_get(self,req, resp, userId):
        categoryId = req.get_param_as_int("categoryId")
        offset = req.get_param_as_int("offset")
        limit = req.get_param_as_int("limit")
        sort = req.get_param("sort")
        direction = req.get_param_as_int("direction")
        filterData = req.get_param('filterData')
        result = Mongo.getNewDeals(int(userId), categoryId, offset, limit, sort, direction, filterData)
        json_docs = [json.dumps(doc, default=json_util.default) for doc in result]
        resp.body = json.dumps(json_docs, encoding='utf-8')

class MasterData():
    def on_get(self,req, resp, skuId):
        result = Mongo.getItem(skuId)
        try:
            json_docs = [json.dumps(doc, default=json_util.default) for doc in result]
            resp.body = json.dumps(json_docs, encoding='utf-8')
        except:
            json_docs = [json.dumps(doc, default=json_util.default) for doc in result]
            resp.body = json.dumps(json_docs, encoding='utf-8')
    
    def on_post(self,req, resp):
        
        addNew = req.get_param_as_int("addNew")
        update = req.get_param_as_int("update")
        addToExisting = req.get_param_as_int("addToExisting")
        multi = req.get_param_as_int("multi")
        
        try:
            result_json = json.loads(req.stream.read(), encoding='utf-8')
        except ValueError:
            raise falcon.HTTPError(falcon.HTTP_400,
                'Malformed JSON',
                'Could not decode the request body. The '
                'JSON was incorrect.')
            
        if addNew == 1:
            result = Mongo.addNewItem(result_json)
        elif update == 1:
            result = Mongo.updateMaster(result_json, multi)
        elif addToExisting == 1:
            result = Mongo.addItemToExistingBundle(result_json)
        else:
            raise
        resp.body = dumps(result)
    
class LiveData():
    def on_get(self,req, resp):
        if req.get_param_as_int("id") is not None:
            print "****getting only for id"
            id = req.get_param_as_int("id")
            try:
                result = FetchLivePrices.getLatestPriceById(id)
                json_docs = json.dumps(result, default=json_util.default)
                resp.body = json.dumps(json_docs, encoding='utf-8')
            except:
                json_docs = json.dumps({}, default=json_util.default)
                resp.body = json.dumps(json_docs, encoding='utf-8')
            
        else:
            print "****getting only for skuId"
            skuBundleId = req.get_param_as_int("skuBundleId")
            source_id = req.get_param_as_int("source_id")
            try:
                result = FetchLivePrices.getLatestPrice(skuBundleId, source_id)
                json_docs = [json.dumps(doc, default=json_util.default) for doc in result]
                resp.body = json.dumps(json_docs, encoding='utf-8')
            except:
                json_docs = [json.dumps(doc, default=json_util.default) for doc in [{}]]
                resp.body = json.dumps(json_docs, encoding='utf-8')
                
class CashBack():
    def on_get(self,req, resp):
        identifier = req.get_param("identifier")
        source_id = req.get_param_as_int("source_id")
        try:
            result = Mongo.getCashBackDetails(identifier, source_id)
            json_docs = json.dumps(result, default=json_util.default)
            resp.body = json_docs
        except:
            json_docs = json.dumps({}, default=json_util.default)
            resp.body = json_docs

class ImgSrc():
    def on_get(self,req, resp):
        identifier = req.get_param("identifier")
        source_id = req.get_param_as_int("source_id")
        try:
            result = Mongo.getImgSrc(identifier, source_id)
            json_docs = json.dumps(result, default=json_util.default)
            resp.body = json_docs
        except:
            json_docs = json.dumps({}, default=json_util.default)
            resp.body = json_docs

class DealSheet():
    def on_get(self,req, resp):
        X_DealSheet.sendMail()
        json_docs = json.dumps({'True':'Sheet generated, mail sent.'}, default=json_util.default)
        resp.body = json.dumps(json_docs, encoding='utf-8')
    
class DealerPrice():
    
    def on_get(self, req, resp):
        
        offset = req.get_param_as_int("offset")
        limit = req.get_param_as_int("limit")
        result = Mongo.getAllDealerPrices(offset,limit)
        json_docs = [json.dumps(doc, default=json_util.default) for doc in result]
        resp.body = json.dumps(json_docs, encoding='utf-8')
    
    def on_post(self, req, resp):
        
        multi = req.get_param_as_int("multi")
        
        try:
            result_json = json.loads(req.stream.read(), encoding='utf-8')
        except ValueError:
            raise falcon.HTTPError(falcon.HTTP_400,
                'Malformed JSON',
                'Could not decode the request body. The '
                'JSON was incorrect.')
            
        result = Mongo.addSkuDealerPrice(result_json, multi)
        resp.body = json.dumps(result, encoding='utf-8')
    
    def on_put(self, req, resp, _id):
        try:
            result_json = json.loads(req.stream.read(), encoding='utf-8')
        except ValueError:
            raise falcon.HTTPError(falcon.HTTP_400,
                'Malformed JSON',
                'Could not decode the request body. The '
                'JSON was incorrect.')
            
        result = Mongo.updateSkuDealerPrice(result_json, _id)
        resp.body = json.dumps(result, encoding='utf-8')

    
class ResetCache():
    
    def on_get(self,req, resp, userId):
        result = Mongo.resetCache(userId)
        resp.body = json.dumps(result, encoding='utf-8')
        
class UserDeals():
    def on_get(self,req,resp,userId):
        UserSpecificDeals.generateSheet(userId)
        json_docs = json.dumps({'True':'Sheet generated, mail sent.'}, default=json_util.default)
        resp.body = json.dumps(json_docs, encoding='utf-8')

class CommonUpdate():
    
    def on_post(self,req,resp):
        
        multi = req.get_param_as_int("multi")
        
        try:
            result_json = json.loads(req.stream.read(), encoding='utf-8')
        except ValueError:
            raise falcon.HTTPError(falcon.HTTP_400,
                'Malformed JSON',
                'Could not decode the request body. The '
                'JSON was incorrect.')
            
        result = Mongo.updateCollection(result_json, multi)
        resp.body = json.dumps(result, encoding='utf-8')
        resp.content_type = "application/json; charset=utf-8"

class NegativeDeals():
    
    def on_get(self, req, resp):
        
        offset = req.get_param_as_int("offset")
        limit = req.get_param_as_int("limit")
        
        result = Mongo.getAllNegativeDeals(offset, limit)
        resp.body = dumps(result) 

    
    def on_post(self, req, resp):
        
        multi = req.get_param_as_int("multi")
        
        try:
            result_json = json.loads(req.stream.read(), encoding='utf-8')
        except ValueError:
            raise falcon.HTTPError(falcon.HTTP_400,
                'Malformed JSON',
                'Could not decode the request body. The '
                'JSON was incorrect.')
            
        result = Mongo.addNegativeDeals(result_json, multi)
        resp.body = json.dumps(result, encoding='utf-8')

class ManualDeals():
    
    def on_get(self, req, resp):
        
        offset = req.get_param_as_int("offset")
        limit = req.get_param_as_int("limit")
        
        result = Mongo.getAllManualDeals(offset, limit)
        resp.body = dumps(result)

    
    def on_post(self, req, resp):
        
        multi = req.get_param_as_int("multi")
        
        try:
            result_json = json.loads(req.stream.read(), encoding='utf-8')
        except ValueError:
            raise falcon.HTTPError(falcon.HTTP_400,
                'Malformed JSON',
                'Could not decode the request body. The '
                'JSON was incorrect.')
            
        result = Mongo.addManualDeal(result_json, multi)
        resp.body = json.dumps(result, encoding='utf-8')
        
class CommonDelete():
    
    def on_post(self,req,resp):
        try:
            result_json = json.loads(req.stream.read(), encoding='utf-8')
        except ValueError:
            raise falcon.HTTPError(falcon.HTTP_400,
                'Malformed JSON',
                'Could not decode the request body. The '
                'JSON was incorrect.')
            
        result = Mongo.deleteDocument(result_json)
        resp.body = json.dumps(result, encoding='utf-8')
        resp.content_type = "application/json; charset=utf-8"

class SearchProduct():
    
    def on_get(self,req,resp):
        offset = req.get_param_as_int("offset")
        limit = req.get_param_as_int("limit")
        search_term = req.get_param("search")
        
        result = Mongo.searchMaster(offset, limit, search_term)
        resp.body = dumps(result) 

        
class FeaturedDeals():
    
    def on_get(self, req, resp):
        
        offset = req.get_param_as_int("offset")
        limit = req.get_param_as_int("limit")
        
        result = Mongo.getAllFeaturedDeals(offset, limit)
        resp.body = dumps(result)

    
    def on_post(self, req, resp):
        
        multi = req.get_param_as_int("multi")
        
        try:
            result_json = json.loads(req.stream.read(), encoding='utf-8')
        except ValueError:
            raise falcon.HTTPError(falcon.HTTP_400,
                'Malformed JSON',
                'Could not decode the request body. The '
                'JSON was incorrect.')
            
        result = Mongo.addFeaturedDeal(result_json, multi)
        resp.body = json.dumps(result, encoding='utf-8')


class CommonSearch():
    
    def on_get(self,req,resp):
        class_name = req.get_param("class")
        sku = req.get_param_as_int("sku")
        skuBundleId = req.get_param_as_int("skuBundleId")

        result = Mongo.searchCollection(class_name, sku, skuBundleId)
        resp.body = dumps(result)

class CricScore():
    
    def on_get(self,req,resp):

        result = Mongo.getLiveCricScore()
        resp.body = dumps(result)

class Notification():
    
    def on_post(self, req, resp):
        
        try:
            result_json = json.loads(req.stream.read(), encoding='utf-8')
        except ValueError:
            raise falcon.HTTPError(falcon.HTTP_400,
                'Malformed JSON',
                'Could not decode the request body. The '
                'JSON was incorrect.')
            
        result = Mongo.addBundleToNotification(result_json)
        resp.body = json.dumps(result, encoding='utf-8')
    
    def on_get(self, req, resp):

        offset = req.get_param_as_int("offset")
        limit = req.get_param_as_int("limit")
        
        result = Mongo.getAllNotifications(offset, limit)
        resp.body = dumps(result)

class DealBrands():
    
    def on_get(self, req, resp):
        
        category_id = req.get_param_as_int("category_id")
        result = Mongo.getBrandsForFilter(category_id)
        resp.body = dumps(result)
    

class RetailerDetail():
    global RETAILER_DETAIL_CALL_COUNTER
    def getRetryRetailer(self,failback=True):
        retailer = None
        status = 'fretry' if self.callType == 'followup' else 'retry'
        try:
            retailer = session.query(Retailers).filter_by(status=status).filter(Retailers.next_call_time<=datetime.now()).order_by(Retailers.call_priority).order_by(Retailers.next_call_time).with_lockmode("update").first()
            if retailer is not None:
                print "getRetryRetailer", retailer.id
            else:
                if failback:
                    retailer = self.getNewRetailer(False)
                    return retailer
            if status=='retry':
                retailer.status = 'assigned'
            else:
                retailer.status = 'fassigned'
            session.commit()
            print "getRetryRetailer", retailer.id
        finally:
            session.close()
        return retailer
            
    def getNewRetailer(self,failback=True):
        retry = True
        retailer = None 
        try:
            while(retry):
                print "Calltype", self.callType
                status=self.callType
                query = session.query(Retailers).filter(Retailers.status==status)
                if status=='fresh':
                    query = query.filter_by(is_or=False, is_std=False).filter(or_(Retailers.agent_id==self.agentId, Retailers.agent_id==None)).order_by(-Retailers.agent_id)
                retailer = query.with_lockmode("update").first()
                if retailer is not None:
                    print "retailer", retailer.id
                    if status=="fresh":
                        userquery = session.query(Users)
                        if retailer.contact2 is not None:
                            userquery = userquery.filter(Users.mobile_number.in_([retailer.contact1,retailer.contact2]))
                        else:
                            userquery = userquery.filter_by(mobile_number=retailer.contact1)
                        user = userquery.first()
                        if user is not None:
                            retailer.status = 'alreadyuser'
                            print "retailer.status", retailer.status
                            session.commit()
                            continue
                        retailer.status = 'assigned'
                    else:
                        retailer.status = 'fassigned'
                    print "Found Retailer", retailer.id, "with status", status,"assigned to", self.agentId
                    retailer.retry_count = 0
                    retailer.invalid_retry_count = 0
                    session.commit()
                    print "-"*50
                    print "Found Retailer", retailer.id, "with status", status,"assigned to", self.agentId
                    retry=False
                        
                else:
                    print "No fresh/followup retailers found"
                    if failback:
                        retailer = self.getRetryRetailer(False)
                        return retailer
        except:
            print traceback.print_exc()
        finally:
            session.close()
        return retailer
    
    def on_get(self, req, resp, agentId, callType=None, retailerId=None):
        global RETAILER_DETAIL_CALL_COUNTER
        RETAILER_DETAIL_CALL_COUNTER += 1
        print "RETAILER_DETAIL_CALL_COUNTER", RETAILER_DETAIL_CALL_COUNTER
        print "I am here"
        self.agentId = int(agentId)
        self.callType = callType
        if callType is None:
            retailerLink = session.query(RetailerLinks).filter_by(id=retailerId)
            if retailerLink is not None:
                code = retailerLink.code
            else: 
                code = self.getCode()
                retailerLink = RetailerLinks()
                retailerLink.code = code
                retailerLink.is_activated = False
                retailerLink.retailer_id = retailerId
                session.commit()
            session.close()
            resp.body =  json.dumps({"result":{"code":code}}, encoding='utf-8')
            return 
        retryFlag = False 
        agentId = int(agentId)
        if RETAILER_DETAIL_CALL_COUNTER % DEALER_RETRY_FACTOR ==0:
            retryFlag=True
        
        if retryFlag:
            retailer = self.getRetryRetailer()
        else:
            retailer = self.getNewRetailer()
        
        if retailer is None:
            resp.body = "{\"result\":{}}"
        else:
            resp.body = json.dumps(todict(getRetailerObj(retailer)), encoding='utf-8')
        
    def on_post(self, req, resp, agentId, callType):
        returned = False
        self.agentId = int(agentId)
        self.callType = callType
        jsonReq = json.loads(req.stream.read(), encoding='utf-8')
        print jsonReq
        self.jsonReq = jsonReq
        invalidNumber = self.invalidNumber
        callLater = self.callLater
        alreadyUser = self.alReadyUser
        verifiedLinkSent = self.verifiedLinkSent
        
        self.retailerId = int(jsonReq.get('retailerid'))
        try:
            self.retailer = session.query(Retailers).filter_by(id=self.retailerId).first()
            self.callDisposition = jsonReq.get('calldispositiontype')
            self.callHistory = CallHistory()
            self.callHistory.agent_id=self.agentId
            self.callHistory.call_disposition = self.callDisposition
            self.callHistory.retailer_id=self.retailerId
            self.callHistory.call_type=self.callType
            self.callHistory.duration_sec = int(jsonReq.get("callduration"))
            self.callHistory.disposition_description = jsonReq.get('calldispositiondescritption')
            self.callHistory.call_time = datetime.strptime(jsonReq.get("calltime"), '%d/%m/%Y %H:%M:%S')
            self.callHistory.mobile_number = jsonReq.get('number')
            self.callHistory.sms_verified = 0
            
            dispositionMap = {  'call_later':callLater,
                        'ringing_no_answer':callLater,
                        'not_reachable':callLater,
                        'switch_off':callLater,
                        'invalid_no':invalidNumber,
                        'wrong_no':invalidNumber,
                        'hang_up':invalidNumber,
                        'retailer_not_interested':invalidNumber,
                        'alreadyuser':alreadyUser,
                        'verified_link_sent':verifiedLinkSent
                      }
            returned = dispositionMap[jsonReq.get('calldispositiontype')]()
        finally:
            session.close()
        
        if returned:
            resp.body = "{\"result\":\"success\"}"
        else:
            resp.body = "{\"result\":\"failed\"}"

    def invalidNumber(self,):
        #self.retailer.status = 'retry' if self.callType == 'fresh' else 'fretry'
        if self.callDisposition == 'invalid_no':
            self.retailer.status='failed'
            self.callHistory.disposition_description = 'Invalid Number'
        elif self.callDisposition == 'wrong_no':
            self.retailer.status='failed'
            self.callHistory.disposition_description = 'Wrong Number'
        elif self.callDisposition == 'hang_up':
            self.retailer.status='failed'
            self.callHistory.disposition_description = 'Hang Up'
        elif self.callDisposition == 'retailer_not_interested':
            self.retailer.status='failed'
            if self.callHistory.disposition_description is None:
                self.callHistory.disposition_description = 'NA'
            self.callHistory.disposition_description = 'Reason Retailer Not Interested ' + self.callHistory.disposition_description        
        session.commit()
        return True   
        
    def getCode(self,):
        prefix = None
        notFound = True
        while notFound:
            code = uuid.uuid4().hex[:10] if prefix is None else prefix + uuid.uuid4().hex[:6]
            notFound = '0' in code and session.query(RetailerLinks).filter_by(code=code).first() is not None
        return code
    
    def callLater(self,):
        self.retailer.status = 'retry' if self.callType == 'fresh' else 'fretry'
        self.retailer.call_priority = None
        if self.callDisposition == 'call_later':
            if self.callHistory.disposition_description is not None:
                self.retailer.call_priority = 'user_initiated'
                self.retailer.next_call_time = datetime.strptime(self.callHistory.disposition_description, '%d/%m/%Y %H:%M:%S')
                self.callHistory.disposition_description = 'User requested to call on ' + self.callHistory.disposition_description
            else:
                self.retailer.call_priority = 'system_initiated'
                self.retailer.next_call_time = self.callHistory.call_time + timedelta(days=1)
                self.callHistory.disposition_description = 'Call scheduled on ' + datetime.strftime(self.retailer.next_call_time, '%d/%m/%Y %H:%M:%S')
        else: 
            if self.callDisposition == 'ringing_no_answer':
                if self.retailer.disposition == 'ringing_no_answer':
                    self.retailer.retry_count += 1
                else:
                    self.retailer.disposition = 'ringing_no_answer'
                    self.retailer.retry_count = 1
            else:
                if self.retailer.disposition == 'ringing_no_answer':
                    pass
                else:
                    self.retailer.disposition = 'not_reachable'
                self.retailer.retry_count += 1
                self.retailer.invalid_retry_count += 1
                    
            retryConfig = session.query(RetryConfig).filter_by(call_type=self.callType, disposition_type=self.retailer.disposition, retry_count=self.retailer.retry_count).first()
            if retryConfig is not None:
                self.retailer.next_call_time = self.callHistory.call_time + timedelta(minutes = retryConfig.minutes_ahead)
                self.callHistory.disposition_description = 'Call scheduled on ' + datetime.strftime(self.retailer.next_call_time, '%d/%m/%Y %H:%M:%S')
            else:
                self.retailer.status = 'failed'
                self.callHistory.disposition_description = 'Call failed as all attempts exhausted'
            
        session.commit()
        return True
            
            
    def alReadyUser(self,):
        self.retailer.status = self.callDisposition
        if self.callHistory.disposition_description is None:
            self.callHistory.disposition_description = 'Retailer already user' 
        session.commit()
        return True
    def verifiedLinkSent(self,):
        self.retailer.status = 'retry' if self.callType == 'fresh' else 'fretry'
        

def todict(obj, classkey=None):
    if isinstance(obj, dict):
        data = {}
        for (k, v) in obj.items():
            data[k] = todict(v, classkey)
        return data
    elif hasattr(obj, "_ast"):
        return todict(obj._ast())
    elif hasattr(obj, "__iter__"):
        return [todict(v, classkey) for v in obj]
    elif hasattr(obj, "__dict__"):
        data = dict([(key, todict(value, classkey)) 
            for key, value in obj.__dict__.iteritems() 
            if not callable(value) and not key.startswith('_')])
        if classkey is not None and hasattr(obj, "__class__"):
            data[classkey] = obj.__class__.__name__
        return data
    else:
        return obj
    
def getRetailerObj(retailer):
    obj = Mock()
    obj.title = retailer.title
    obj.contact1 = retailer.contact1
    obj.contact2 = retailer.contact2
    obj.address = retailer.address
    obj.id = retailer.id
    obj.scheduled = (retailer.call_priority is not None)
    return obj

def make_tiny(code):
    url = 'https://play.google.com/store/apps/details?id=com.saholic.profittill&referrer=utm_source%3D0%26utm_medium%3DCRM%26utm_term%3D001%26utm_campaign%3D' + code
    request_url = ('http://tinyurl.com/api-create.php?' + urlencode({'url':url}))
    filehandle = urllib2.Request(request_url)
    x= urllib2.urlopen(filehandle)
    return str(x.read())
    
    
class Mock(object):
    pass
    
def main():
    print make_tiny("http://www.google.com")

if __name__ == '__main__':
        main()