Subversion Repositories SmartDukaan

Rev

Rev 17304 | Rev 17498 | 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 pyshorteners.shorteners  import Shortener
from dtr import main
from dtr.config import PythonPropertyReader
from dtr.storage import Mongo
from dtr.storage.DataService import Retailers, Users, CallHistory, RetryConfig, \
    RetailerLinks, Activation_Codes, Agents, Agent_Roles, AgentLoginTimings, \
    FetchDataHistory, RetailerContacts, Orders, OnboardedRetailerChecklists,\
    RetailerAddresses, Pincodeavailability, app_offers, appmasters, user_app_cashbacks, user_app_installs
from dtr.storage.Mongo import get_mongo_connection
from dtr.storage.Mysql import fetchResult
from dtr.utils import FetchLivePrices, DealSheet as X_DealSheet, \
    UserSpecificDeals
from dtr.utils.utils import getLogger
from elixir import *
from operator import and_
from sqlalchemy.sql.expression import func, func, or_, desc, asc, case
from urllib import urlencode
import contextlib
import falcon
import json
import re
import string
import traceback
import urllib
import urllib2
import uuid
import gdshortener
from dtr.dao import AppOfferObj, UserAppBatchDrillDown, UserAppBatchDateDrillDown

alphalist = list(string.uppercase)
alphalist.remove('O')
numList = ['1','2','3','4','5','6','7','8','9']
codesys = [alphalist, alphalist, numList, numList, numList]
CONTACT_PRIORITY = ['sms', 'called', 'ringing']
RETRY_MAP = {'fresh':'retry', 'followup':'fretry', 'onboarding':'oretry'}
ASSIGN_MAP = {'retry':'assigned', 'fretry':'fassigned', 'oretry':'oassigned'}

sticky_agents = [17]

def getNextCode(codesys, code=None):
    if code is None:
        code = []
        for charcode in codesys:
            code.append(charcode[0])
        return string.join(code, '')
    carry = True
    code = list(code)
    lastindex = len(codesys) - 1
    while carry:
        listChar = codesys[lastindex]
        newIndex = (listChar.index(code[lastindex])+1)%len(listChar)
        print newIndex
        code[lastindex] = listChar[newIndex]
        if newIndex != 0:
            carry = False
        lastindex -= 1
        if lastindex ==-1:
            raise BaseException("All codes are exhausted")
        
    return string.join(code, '')
        
        


global RETAILER_DETAIL_CALL_COUNTER
RETAILER_DETAIL_CALL_COUNTER = 0

lgr = getLogger('/var/log/retailer-acquisition-api.log')
DEALER_RETRY_FACTOR = int(PythonPropertyReader.getConfig('DEALER_RETRY_FACTOR'))
DEALER_FRESH_FACTOR = int(PythonPropertyReader.getConfig('DEALER_FRESH_FACTOR'))
TOTAL = DEALER_RETRY_FACTOR + DEALER_FRESH_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)
        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)
        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)
        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)
        resp.body = dumps(result) 

class MasterData():
    def on_get(self,req, resp, skuId):
        showDp = req.get_param_as_int("showDp")
        result = Mongo.getItem(skuId, showDp)
        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)
        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)
        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 DealRank():
    
    def on_get(self, req, resp):
        identifier = req.get_param("identifier")
        source_id = req.get_param_as_int("source_id")
        user_id = req.get_param_as_int("user_id")
        result = Mongo.getDealRank(identifier, source_id, user_id)
        json_docs = json.dumps(result, default=json_util.default)
        resp.body = json_docs
        
    
class OrderedOffers():
    def on_get(self, req, resp, storeId, storeSku):
        storeId = int(storeId)
        result = Mongo.getBundleBySourceSku(storeId, storeSku)
        json_docs = json.dumps(result, default=json_util.default)
        resp.body = json_docs

class RetailerDetail():
    global RETAILER_DETAIL_CALL_COUNTER
    def getRetryRetailer(self,failback=True):
        status = RETRY_MAP.get(self.callType)
        retailer = session.query(Retailers).filter_by(status=status).filter(Retailers.next_call_time<=datetime.now()).filter(or_(Retailers.agent_id==self.agentId, Retailers.agent_id==None)).order_by(Retailers.agent_id.desc(),Retailers.call_priority).order_by(Retailers.next_call_time).with_lockmode("update").first()
        
        if retailer is not None:
            lgr.info( "getRetryRetailer " + str(retailer.id))
        else:
            if failback:
                retailer = self.getNewRetailer(False)
                return retailer
            else:
                #No further calls for now
                return None
        retailer.status = ASSIGN_MAP.get(status)
        retailer.next_call_time = None
        lgr.info( "getRetryRetailer " + str(retailer.id))
        return retailer
            
    def getNotActiveRetailer(self):
        try:
            user = session.query(Users).filter_by(activated=0).filter_by(status=1).filter(Users.mobile_number != None).filter(~Users.mobile_number.like("0%")).filter(Users.created>datetime(2015,06,29)).order_by(Users.created.desc()).with_lockmode("update").first()
            if user is None: 
                return None
            else:
                retailerContact = session.query(RetailerContacts).filter_by(mobile_number=user.mobile_number).first()
                if retailerContact is not None:
                    retailer = session.query(Retailers).filter_by(id=retailerContact.retailer_id).first()
                else:
                    retailer = session.query(Retailers).filter_by(contact1=user.mobile_number).first()
                    if retailer is None:
                        retailer = session.query(Retailers).filter_by(contact2=user.mobile_number).first()
                        if retailer is None:
                            retailer = Retailers()
                            retailer.contact1 = user.mobile_number
                            retailer.status = 'assigned'
                            retailer.retry_count = 0
                            retailer.invalid_retry_count = 0
                            retailer.is_elavated=1
                user.status = 2
                session.commit()
                print "retailer id", retailer.id
                retailer.contact = user.mobile_number
                return retailer
        finally:
            session.close()
            
    def getNewRetailer(self,failback=True):
        if self.callType == 'fresh':
            retailer = self.getNotActiveRetailer()
            if retailer is not None:
                return retailer
        retry = True
        retailer = None 
        try:
            while(retry):
                lgr.info( "Calltype " + self.callType)
                status=self.callType
                query = session.query(Retailers).filter(Retailers.status==status).filter(or_(Retailers.agent_id==self.agentId, Retailers.agent_id==None))
                if status=='fresh':
                    query = query.filter_by(is_or=False, is_std=False).filter(Retailers.pin==Pincodeavailability.code).filter(Pincodeavailability.amount > 19999).order_by(Retailers.is_elavated.desc(), Retailers.agent_id.desc())
                elif status=='followup':
                    query = query.filter(Retailers.next_call_time<=datetime.now()).order_by(Retailers.agent_id.desc(),Retailers.next_call_time)
                else:
                    query = query.filter(Retailers.modified<=datetime.now()).order_by(Retailers.agent_id.desc(), Retailers.modified)
                    
                retailer = query.with_lockmode("update").first()
                if retailer is not None:
                    lgr.info( "retailer " +str(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'
                            lgr.info( "retailer.status " + retailer.status)
                            session.commit()
                            continue
                        retailer.status = 'assigned'
                    elif status=='followup':
                        if isActivated(retailer.id):
                            print "Retailer Already %d activated and marked onboarded"%(retailer.id)
                            continue
                        retailer.status = 'fassigned'
                    else:
                        retailer.status = 'oassigned'
                    retailer.retry_count = 0
                    retailer.invalid_retry_count = 0
                    lgr.info( "Found Retailer " +  str(retailer.id) + " with status " + status + " assigned to " + str(self.agentId))
                        
                else:
                    lgr.info( "No fresh/followup retailers found")
                    if failback:
                        retailer = self.getRetryRetailer(False)
                        return retailer
                retry=False
        except:
            print traceback.print_exc()
        return retailer
    
    def on_get(self, req, resp, agentId, callType=None, retailerId=None):
        try:
            global RETAILER_DETAIL_CALL_COUNTER
            RETAILER_DETAIL_CALL_COUNTER += 1
            lgr.info( "RETAILER_DETAIL_CALL_COUNTER " +  str(RETAILER_DETAIL_CALL_COUNTER))
            self.agentId = int(agentId)
            self.callType = callType
            if retailerId is not None:
                self.retailerId = int(retailerId)
                retailerLink = session.query(RetailerLinks).filter_by(retailer_id=self.retailerId).first()
                if retailerLink is not None:
                    code = retailerLink.code
                else: 
                    code = self.getCode()
                    retailerLink = RetailerLinks()
                    retailerLink.code = code
                    retailerLink.agent_id = self.agentId
                    retailerLink.retailer_id = self.retailerId
                    
                    activationCode=Activation_Codes()
                    activationCode.code = code
                    session.commit()
                session.close()
                resp.body =  json.dumps({"result":{"code":code,"link":make_tiny(code)}}, encoding='utf-8')
                return 
            retryFlag = False 
            if RETAILER_DETAIL_CALL_COUNTER % TOTAL >= DEALER_FRESH_FACTOR:
                retryFlag=True
            try:
                if retryFlag:
                    retailer = self.getRetryRetailer()
                else:
                    retailer = self.getNewRetailer()
                if retailer is None:
                    resp.body = "{}"
                    return
                fetchInfo = FetchDataHistory()
                fetchInfo.agent_id = self.agentId
                fetchInfo.call_type = self.callType
                agent = session.query(Agents).filter_by(id=self.agentId).first()
                last_disposition = session.query(CallHistory).filter_by(agent_id=self.agentId).order_by(CallHistory.id.desc()).first()
                if last_disposition is None or last_disposition.created < agent.last_login:
                    fetchInfo.last_action = 'login'
                    fetchInfo.last_action_time = agent.last_login 
                else:
                    fetchInfo.last_action = 'disposition'
                    fetchInfo.last_action_time = last_disposition.created
                fetchInfo.retailer_id = retailer.id
                session.commit()
                
                otherContacts = [r for r, in session.query(RetailerContacts.mobile_number).filter_by(retailer_id=retailer.id).order_by(RetailerContacts.contact_type).all()]
                resp.body = json.dumps(todict(getRetailerObj(retailer, otherContacts, self.callType)), encoding='utf-8')
                
                return
                
            finally:
                session.close()
    
            if retailer is None:
                resp.body = "{}"
            else:
                print "It should never come here"
                resp.body = json.dumps(todict(getRetailerObj(retailer)), encoding='utf-8')
        finally:
            session.close()
        
    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')
        lgr.info( "Request ----\n"  + str(jsonReq))
        self.jsonReq = jsonReq
        invalidNumber = self.invalidNumber
        callLater = self.callLater
        alreadyUser = self.alReadyUser
        verifiedLinkSent = self.verifiedLinkSent
        onboarded = self.onboarded
        self.address = jsonReq.get('address')
        self.retailerId = int(jsonReq.get('retailerid'))
        self.smsNumber = jsonReq.get('smsnumber')
        if self.smsNumber is not None:
            self.smsNumber = self.smsNumber.strip().lstrip("0") 
        try:
            self.retailer = session.query(Retailers).filter_by(id=self.retailerId).first()
            if self.address:
                self.retailer.address_new = self.address
            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.disposition_comments = jsonReq.get('calldispositioncomments')
            lgr.info(self.callHistory.disposition_comments)
            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 = int(jsonReq.get("verified"))
            lastFetchData = session.query(FetchDataHistory).filter_by(agent_id=self.agentId).order_by(FetchDataHistory.id.desc()).first()
            if self.callDisposition == 'onboarded':
                self.checkList = jsonReq.get('checklist')
                
            if lastFetchData is None:
                raise
            self.callHistory.last_fetch_time= lastFetchData.created  
            
            dispositionMap = {  'call_later':callLater,
                        'ringing_no_answer':callLater,
                        'not_reachable':callLater,
                        'switch_off':callLater,
                        'not_retailer':invalidNumber,
                        'invalid_no':invalidNumber,
                        'wrong_no':invalidNumber,
                        'hang_up':invalidNumber,
                        'retailer_not_interested':invalidNumber,
                        'recharge_retailer':invalidNumber,
                        'accessory_retailer':invalidNumber,
                        'service_center_retailer':invalidNumber,
                        'alreadyuser':alreadyUser,
                        'verified_link_sent':verifiedLinkSent,
                        'onboarded':onboarded
                      }
            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
        elif self.callDisposition == 'recharge_retailer':
            self.retailer.status='failed'
            self.callHistory.disposition_description = 'Recharge related. Not a retailer '
        elif self.callDisposition == 'accessory_retailer':
            self.retailer.status='failed'
            self.callHistory.disposition_description = 'Accessory related. Not a retailer'
        elif self.callDisposition == 'service_center_retailer':
            self.retailer.status='failed'
            self.callHistory.disposition_description = 'Service Center related. Not a retailer'
        elif self.callDisposition == 'not_retailer':
            self.retailer.status='failed'
            self.callHistory.disposition_description = 'Not a retailer'    
        session.commit()
        return True   
        
    def getCode(self,):
        newCode = None
        lastLink = session.query(RetailerLinks).order_by(RetailerLinks.id.desc()).with_lockmode("update").first()
        if lastLink is not None:
            if len(lastLink.code)==len(codesys):
                newCode=lastLink.code
        return getNextCode(codesys, newCode)
    
    
    def callLater(self,):
        self.retailer.status = RETRY_MAP.get(self.callType)
        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,):
        if self.callType == 'fresh':
            self.retailer.status = 'followup'
            if self.retailer.agent_id not in sticky_agents:
                self.retailer.agent_id = None
            self.retailer.next_call_time = self.callHistory.call_time + timedelta(days=1)
            self.callHistory.disposition_description = 'App link sent via ' + self.callHistory.disposition_description+ '. followup on' + datetime.strftime(self.retailer.next_call_time, '%d/%m/%Y %H:%M:%S') 
        else:
            self.retailer.status = 'followup'
            if self.retailer.agent_id not in sticky_agents:
                self.retailer.agent_id = None
            self.retailer.next_call_time = self.callHistory.call_time + timedelta(days=7)
            self.callHistory.disposition_description = 'App link sent via' + self.callHistory.disposition_description + '. Followup again on ' + datetime.strftime(self.retailer.next_call_time, '%d/%m/%Y %H:%M:%S')
        addContactToRetailer(self.agentId, self.retailerId, self.smsNumber, self.callType, 'sms')     
        session.commit()
        return True
    def onboarded(self,):
        self.retailer.status = self.callDisposition
        checkList = OnboardedRetailerChecklists()
        checkList.contact_us = self.checkList.get('contactus')
        checkList.doa_return_policy = self.checkList.get('doareturnpolicy')
        checkList.number_verification = self.checkList.get('numberverification')
        checkList.payment_option = self.checkList.get('paymentoption')
        checkList.preferences = self.checkList.get('preferences')
        checkList.product_info = self.checkList.get('productinfo')
        checkList.redeem = self.checkList.get('redeem')
        checkList.retailer_id = self.retailerId
        session.commit()
        return True
        
        
def isActivated(retailerId):
    retailerLink = session.query(RetailerLinks).filter_by(retailer_id=retailerId).first()
    user = session.query(Users).filter(or_(func.lower(Users.referrer)==retailerLink.code.lower(), Users.utm_campaign==retailerLink.code)).first()
    if user is None:
        mobileNumbers = list(session.query(RetailerContacts.mobile_number).filter_by(retailer_id=retailerId).all())
        user = session.query(Users).filter(Users.mobile_number.in_(mobileNumbers)).first()
        if user is None:
            if retailerLink.created < datetime(2015,5,26):
                historyNumbers = [number for number, in session.query(CallHistory.mobile_number).filter_by(retailer_id = retailerId).all()]
                user = session.query(Users).filter(Users.mobile_number.in_(historyNumbers)).first()
                if user is None:
                    return False
                else:
                    mapped_with = 'contact'
            else:
                return False
        else:
            mapped_with = 'contact'
    else:
        mapped_with = 'code'
    retailerLink.mapped_with = mapped_with
    if user.activation_time is not None:
        retailerLink.activated = user.activation_time
    retailerLink.activated = user.created
    retailerLink.user_id = user.id
    retailer = session.query(Retailers).filter_by(id=retailerId).first()
    if retailer.status == 'followup' or retailer.status == 'fretry':
        retailer.status = 'onboarding'
        if retailer.agent_id not in sticky_agents:
                retailer.agent_id = None
        retailer.call_priority = None
        retailer.next_call_time = None
        retailer.retry_count = 0
        retailer.invalid_retry_count = 0
    session.commit()
    print "retailerLink.retailer_id", retailerLink.retailer_id
    print "retailer", retailer.id
    session.close()
    return True
    
class AddContactToRetailer():
    def on_post(self,req,resp, agentId):
        agentId = int(agentId)
        try:
            jsonReq = json.loads(req.stream.read(), encoding='utf-8')
            retailerId = int(jsonReq.get("retailerid"))
            mobile = jsonReq.get("mobile")
            callType = jsonReq.get("calltype")
            contactType = jsonReq.get("contacttype")
            addContactToRetailer(agentId, retailerId, mobile, callType, contactType)
            session.commit()
        finally:
            session.close()

class AddAddressToRetailer():
    def on_post(self,req,resp, agentId):
        agentId = int(agentId)
        jsonReq = json.loads(req.stream.read(), encoding='utf-8')
        retailerId = int(jsonReq.get("retailerid"))
        address = str(jsonReq.get("address"))
        storeName = str(jsonReq.get("storename"))
        pin = str(jsonReq.get("pin"))
        city = str(jsonReq.get("city"))
        state = str(jsonReq.get("state"))
        updateType = str(jsonReq.get("updatetype"))
        addAddressToRetailer(agentId, retailerId, address, storeName, pin, city,state, updateType)
            
def addContactToRetailer(agentId, retailerId, mobile, callType, contactType):
    retailerContact = session.query(RetailerContacts).filter_by(retailer_id=retailerId).filter_by(mobile_number=mobile).first()
    if retailerContact is None:
        retailerContact = RetailerContacts()
        retailerContact.retailer_id = retailerId
        retailerContact.agent_id = agentId
        retailerContact.call_type = callType
        retailerContact.contact_type = contactType
        retailerContact.mobile_number = mobile
    else:
        if CONTACT_PRIORITY.index(retailerContact.contact_type) > CONTACT_PRIORITY.index(contactType):
            retailerContact.contact_type = contactType

def addAddressToRetailer(agentId, retailerId, address, storeName, pin, city,state, updateType):
    print "I am in addAddress"
    print agentId, retailerId, address, storeName, pin, city, state, updateType
    try:
        if updateType=='new':
            retailer = session.query(Retailers).filter_by(id=retailerId).first()
            retailer.address = address
            retailer.title = storeName
            retailer.city = city
            retailer.state = state
            retailer.pin = pin
        raddress = RetailerAddresses()
        raddress.address = address
        raddress.title = storeName
        raddress.agent_id = agentId
        raddress.city = city
        raddress.pin = pin
        raddress.retailer_id = retailerId
        raddress.state = state
        session.commit()
    finally:
        session.close() 
        
        
class Login():
    
    def on_get(self, req, resp, agentId, role):
        try:
            self.agentId = int(agentId)
            self.role = role
            print str(self.agentId) + self.role;
            agents=AgentLoginTimings()
            lastLoginTime = session.query(Agents).filter(Agents.id==self.agentId).first()
            print 'lastLogintime' + str(lastLoginTime)
            agents.loginTime=lastLoginTime.last_login
            agents.logoutTime=datetime.now()
            agents.role =self.role
            agents.agent_id = self.agentId
            session.add(agents)    
            session.commit()
            resp.body =  json.dumps({"result":{"success":"true","message":"Success"}}, encoding='utf-8')
        finally:
            session.close()        
        
    def on_post(self,req,resp):
        try:
            jsonReq = json.loads(req.stream.read(), encoding='utf-8')
            lgr.info( "Request ----\n"  + str(jsonReq))
            email=jsonReq.get('email')
            password = jsonReq.get('password')
            role=jsonReq.get('role')    
            agent = session.query(Agents).filter(and_(Agents.email==email,Agents.password==password)).first()
            if agent is None:
                resp.body =  json.dumps({"result":{"success":"false","message":"Invalid User"}}, encoding='utf-8')
            else:
                print agent.id
                checkRole = session.query(Agent_Roles.id).filter(and_(Agent_Roles.agent_id==agent.id,Agent_Roles.role==role)).first()
                if checkRole is None:
                    resp.body =  json.dumps({"result":{"success":"false","message":"Invalid Role"}}, encoding='utf-8')
                else:
                    agent.last_login = datetime.now()
                    agent.login_type = role
                    resp.body =  json.dumps({"result":{"success":"true","message":"Valid User","id":agent.id}}, encoding='utf-8')
                    session.commit()
                    #session.query(Agents).filter_by(id = checkUser[0]).    
        finally:
            session.close()    
            
    def test(self,email,password,role):
        checkUser = session.query(Agents.id).filter(and_(Agents.email==email,Agents.password==password)).first()
        if checkUser is None:
            print checkUser

        else:
            print checkUser[0]
            checkRole = session.query(Agent_Roles.id).filter(and_(Agent_Roles.agent_id==checkUser[0],Agent_Roles.role==role)).first()
            if checkRole is None:
                pass
            else:
                agents=AgentLoginTimings()
                agents.loginTime=datetime.now()
                agents.logoutTime=datetime.now()
                agents.role =role
                agents.agent_id = 2
                #session.query(AgentLoginTimings).filter_by(id = checkUser[0]).update({"last_login":datetime.now()}, synchronize_session=False)
                session.add(agents)    
                session.commit()
                session.close()
                
                #session.query(Agents).filter(Agents.id==checkUser[0]).update({"last_login":Agents.last_login})

class RetailerActivation():
    def on_get(self, req, resp, userId):
        res =  markDealerActivation(int(userId))
        if res:
            resp.body = "{\"activated\":true}"
        else:
            resp.body = "{\"activated\":false}"
            

def markDealerActivation(userId):
    try:
        user = session.query(Users).filter_by(id=userId).first()
        result = False                
        mappedWith = 'contact'
        retailer = None
        if user is not None:
            referrer = None if user.referrer is None else user.referrer.upper()
            retailerLink = session.query(RetailerLinks).filter(or_(RetailerLinks.code==referrer, RetailerLinks.code==user.utm_campaign)).first()
            if retailerLink is None:
                if user.mobile_number is not None:
                    retailerContact = session.query(RetailerContacts).filter_by(mobile_number=user.mobile_number).first()
                    if retailerContact is None:
                        retailer = session.query(Retailers).filter(Retailers.status.in_(['followup', 'fretry', 'fdone'])).filter(or_(Retailers.contact1==user.mobile_number,Retailers.contact2==user.mobile_number)).first()
                    else:
                        retailer = session.query(Retailers).filter_by(id = retailerContact.retailer_id).first()
            else:
                retailer = session.query(Retailers).filter_by(id = retailerLink.retailer_id).first()
                mappedWith='code'
            if retailer is not None:
                retailerLink = session.query(RetailerLinks).filter_by(retailer_id=retailer.id).first()
                if retailerLink is not None:
                    retailerLink.user_id = user.id
                    retailerLink.mapped_with=mappedWith
                    retailer.status = 'onboarding'
                    result = True
                    session.commit()
        return result
    finally:
        session.close()
                    
            
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, otherContacts1=None, callType=None):
    print "before otherContacts1",otherContacts1
    otherContacts = [] if otherContacts1 is None else otherContacts1
    print "after otherContacts1",otherContacts
    obj = Mock()
    obj.id = retailer.id
    
        
    if retailer.contact1 is not None and retailer.contact1 not in otherContacts:
        otherContacts.append(retailer.contact1)
    if retailer.contact2 is not None and retailer.contact2 not in otherContacts:
        otherContacts.append(retailer.contact2)
    obj.contact1 = None if len(otherContacts)==0 else otherContacts[0]
    if obj.contact1 is not None:
        obj.contact2 = None if len(otherContacts)==1 else otherContacts[1]
    obj.scheduled = (retailer.call_priority is not None)
    address = None
    try:
        address = session.query(RetailerAddresses).filter_by(retailer_id=retailer.id).order_by(RetailerAddresses.created.desc()).first()
    finally:
        session.close()
    if address is not None:
        obj.address = address.address
        obj.title = address.title
        obj.city = address.city
        obj.state = address.state
        obj.pin = address.pin 
    else:
        obj.address = retailer.address_new if retailer.address_new is not None else retailer.address
        obj.title = retailer.title
        obj.city = retailer.city
        obj.state = retailer.state
        obj.pin = retailer.pin 
    obj.status = retailer.status
        
    if hasattr(retailer, 'contact'):
        obj.contact = retailer.contact
    if callType == 'onboarding':
        try:
            userId, activatedTime = session.query(RetailerLinks.user_id, RetailerLinks.activated).filter(RetailerLinks.retailer_id==retailer.id).first()
            activated, = session.query(Users.activation_time).filter(Users.id==userId).first()
            if activated is not None:
                activatedTime = activated
            obj.user_id = userId
            obj.created = datetime.strftime(activatedTime, '%d/%m/%Y %H:%M:%S')
            result = fetchResult("select * from useractive where user_id=%d"%(userId))
            if result == ():
                obj.last_active = None
            else:
                obj.last_active =datetime.strftime(result[0][1], '%d/%m/%Y %H:%M:%S')
            ordersCount = session.query(Orders).filter_by(user_id = userId).filter(~Orders.status.in_(['ORDER_NOT_CREATED_KNOWN', 'ORDER_ALREADY_CREATED_IGNORED'])).count()
            obj.orders = ordersCount
        finally:
            session.close()
    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
    #url='https://play.google.com/store/apps/details?id=com.saholic.profittill&referrer=utm_source=0&utm_medium=CRM&utm_term=001&utm_campaign='+code
    #marketUrl='market://details?id=com.saholic.profittill&referrer=utm_source=0&utm_medium=CRM&utm_term=001&utm_campaign='+code
    #url = urllib.quote(marketUrl)
    #request_url = ('http://tinyurl.com/api-create.php?' + urlencode({'url':url}))
    #filehandle = urllib2.Request(request_url)
    #x= urllib2.urlopen(filehandle)
    try:
        shortener = Shortener('TinyurlShortener')
        returnUrl =  shortener.short(url)
    except:
        shortener = Shortener('SentalaShortener')
        returnlUrl =  shortener.short(url)
    return returnUrl

class SearchUser():
            
    def on_post(self, req, resp, agentId, searchType):
        retailersJsonArray = []
        try:
            jsonReq = json.loads(req.stream.read(), encoding='utf-8')
            lgr.info( "Request in Search----\n"  + str(jsonReq))
            contact=jsonReq.get('searchTerm')
            if(searchType=="number"):
                retailer_ids = session.query(RetailerContacts.retailer_id).filter_by(mobile_number=contact).all()
                retailer_ids = [r for r, in retailer_ids]    
                anotherCondition = or_(Retailers.contact1==contact,Retailers.contact2==contact, Retailers.id.in_(retailer_ids))
            else:
                m = re.match("(.*?)(\d{6})(.*?)", contact)
                if m is not None:
                    pin = m.group(2)
                    contact = m.group(1) if m.group(1) != '' else m.group(3)
                    anotherCondition = and_(Retailers.title.ilike('%%%s%%'%(contact)), Retailers.pin==pin)
                else:
                    anotherCondition = Retailers.title.ilike('%%%s%%'%(contact))
            
            retailers = session.query(Retailers).filter(anotherCondition).limit(20).all()
            if retailers is None:
                resp.body = json.dumps("{}")
            else:
                for retailer in retailers:
                    otherContacts = [r for r, in session.query(RetailerContacts.mobile_number).filter_by(retailer_id=retailer.id).order_by(RetailerContacts.contact_type).all()]
                    retailersJsonArray.append(todict(getRetailerObj(retailer, otherContacts)))    
            resp.body = json.dumps({"Retailers":retailersJsonArray}, encoding='utf-8')
            return
        finally:
            session.close()

    
class Mock(object):
    pass

def tagActivatedReatilers():
    retailerIds = [r for  r, in session.query(RetailerLinks.retailer_id).filter_by(user_id = None).all()]
    session.close()
    for retailerId in retailerIds:
        isActivated(retailerId)
    session.close()

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

        offset = req.get_param_as_int("offset")
        limit = req.get_param_as_int("limit")
        categoryId = req.get_param_as_int("categoryId")
        direction = req.get_param_as_int("direction")
        
        result = Mongo.getStaticDeals(offset, limit, categoryId, direction)
        resp.body = dumps(result)

class DealNotification():
    
    def on_get(self,req,resp,skuBundleIds):
        result = Mongo.getDealsForNotification(skuBundleIds)
        resp.body = dumps(result)

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

    
    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.addDealPoints(result_json)
        resp.body = json.dumps(result, encoding='utf-8')

class AppAffiliates():
    
    def on_get(self, req, resp, retailerId, appId):
        retailerId = int(retailerId)
        appId = int(appId)
        call_back = req.get_param("callback")
        result = Mongo.generateRedirectUrl(retailerId, appId)
        resp.body = call_back+'('+str(result)+')'

class AffiliatePayout():
    def on_get(self, req, resp):
        payout = req.get_param("payout")
        transaction_id = req.get_param("transaction_id")
        result = Mongo.addPayout(payout, transaction_id)
        resp.body = str(result)
    
class AppOffers():
    def on_get(self, req, resp, retailerId):
        try:            
            result = Mongo.getAppOffers(retailerId)
            offerids = result.values()
            if offerids is None or len(offerids)==0:
                resp.body = json.dumps("{}")
            else:
                appOffers = session.query(app_offers.id,app_offers.appmaster_id, app_offers.app_name, app_offers.affiliate_offer_id, app_offers.image_url, app_offers.downloads, app_offers.link, app_offers.offer_price, app_offers.offerCategory, app_offers.package_name, app_offers.promoImage, app_offers.ratings, case([(app_offers.override_payout == True, app_offers.overriden_payout)], else_=app_offers.user_payout).label('user_payout'), case([(appmasters.shortDescription != None, appmasters.shortDescription)], else_=None).label('shortDescription'), case([(appmasters.longDescription != None, appmasters.longDescription)], else_=None).label('longDescription'), appmasters.customerOneLiner, appmasters.retailerOneLiner,appmasters.rank, app_offers.offerCondition, app_offers.location).join((appmasters,appmasters.id==app_offers.appmaster_id)).filter(app_offers.id.in_(tuple(offerids))).all()
                appOffersMap = {}
                jsonOffersArray=[]
                for offer in appOffers:
                    appOffersMap[long(offer[0])]= AppOfferObj(offer[0], offer[1], offer[2], offer[3], offer[4], offer[5], offer[6], offer[7], offer[8], offer[9], offer[10], offer[11], offer[12], offer[13], offer[14], offer[15], offer[16], offer[17], offer[18], offer[19]).__dict__
                for rank in sorted(result):
                    print 'Rank', rank, 'Data', appOffersMap[result[rank]]
                    jsonOffersArray.append(appOffersMap[result[rank]])
            
            resp.body = json.dumps({"AppOffers":jsonOffersArray}, encoding='latin1')
        finally:
            session.close()
            
        
class AppUserBatchRefund():
    def on_get(self, req, resp, batchId, userId):
        try:
            batchId = long(batchId)
            userId = long(userId)
            userBatchCashback = user_app_cashbacks.get_by(user_id=userId, batchCreditId=batchId)
            if userBatchCashback is None:
                resp.body = json.dumps("{}")
            else:
                if userBatchCashback.creditedDate is not None:
                    userBatchCashback.creditedDate = str(userBatchCashback.creditedDate)
                resp.body = json.dumps(todict(userBatchCashback), encoding='utf-8')
        finally:
            session.close()
          
class AppUserBatchDrillDown():
    def on_get(self, req, resp, fortNightOfYear, userId, yearVal):
        try:
            fortNightOfYear = long(fortNightOfYear)
            userId = long(userId)
            yearVal = long(yearVal)
            appUserBatchDrillDown = session.query(user_app_installs.transaction_date, func.sum(user_app_installs.installCount).label('downloads'), func.sum(user_app_installs.payoutAmount).label('amount')).join((user_app_cashbacks,user_app_cashbacks.user_id==user_app_installs.user_id)).filter(user_app_cashbacks.fortnightOfYear==user_app_installs.fortnightOfYear).filter(user_app_cashbacks.user_id==userId).filter(user_app_cashbacks.yearVal==yearVal).filter(user_app_cashbacks.fortnightOfYear==fortNightOfYear).group_by(user_app_installs.transaction_date).all()
            cashbackArray = []
            if appUserBatchDrillDown is None or len(appUserBatchDrillDown)==0:
                resp.body = json.dumps("{}")
            else:
                for appcashBack in appUserBatchDrillDown:
                    userAppBatchDrillDown = UserAppBatchDrillDown(str(appcashBack[0]),long(appcashBack[1]), long(appcashBack[2]))
                    cashbackArray.append(todict(userAppBatchDrillDown))
                resp.body = json.dumps({"UserAppCashBackInBatch":cashbackArray}, encoding='utf-8')
        finally:
            session.close()
            
class AppUserBatchDateDrillDown():
    def on_get(self, req, resp, userId, date):
        try:
            userId = long(userId)
            date = str(date)
            date = datetime.strptime(date, '%Y-%m-%d')
            appUserBatchDateDrillDown = session.query(user_app_installs.app_name, func.sum(user_app_installs.installCount).label('downloads'), func.sum(user_app_installs.payoutAmount).label('amount')).filter(user_app_installs.user_id==userId).filter(user_app_installs.transaction_date==date).group_by(user_app_installs.app_name).all()
            cashbackArray = []
            if appUserBatchDateDrillDown is None or len(appUserBatchDateDrillDown)==0:
                resp.body = json.dumps("{}")
            else:
                for appcashBack in appUserBatchDateDrillDown:
                    userAppBatchDateDrillDown = UserAppBatchDateDrillDown(str(appcashBack[0]),long(appcashBack[1]),long(appcashBack[2]))
                    cashbackArray.append(todict(userAppBatchDateDrillDown))
                resp.body = json.dumps({"UserAppCashBackDateWise":cashbackArray}, encoding='utf-8')
        finally:
            session.close()
            
class AppUserCashBack():
    def on_get(self, req, resp, userId, status):
        try:
            userId = long(userId)
            status = str(status)
            appUserApprovedCashBacks = user_app_cashbacks.query.filter(user_app_cashbacks.user_id==userId).filter(user_app_cashbacks.status==status).all()
            cashbackArray = []
            if appUserApprovedCashBacks is None or len(appUserApprovedCashBacks)==0:
                resp.body = json.dumps("{}")
            else:
                totalAmount = 0                
                for appUserApprovedCashBack in appUserApprovedCashBacks:
                    totalAmount = totalAmount + appUserApprovedCashBack.amount
                    if appUserApprovedCashBack.creditedDate is not None:
                        appUserApprovedCashBack.creditedDate = str(appUserApprovedCashBack.creditedDate)  
                    cashbackArray.append(todict(appUserApprovedCashBack)) 
                                    
                resp.body = json.dumps({"UserAppCashBack":cashbackArray,"TotalAmount":totalAmount}, encoding='utf-8')
        finally:
            session.close()
            
class GetSaleDetail():
    def on_get(self,req,res,date_val):
        try:
                db = get_mongo_connection()
                sum=0
                count=0
                #print date_val, type(date_val)
                #cursor = db.Dtr.merchantOrder.find({'createdOnInt':{'$lt':long(date_val)},'subOrders':{'$exists':True}})
                cursor = db.Dtr.merchantOrder.find({"$and": [ { "createdOnInt":{"$gt":long(date_val)} }, {"createdOnInt":{"$lt":long(date_val)+86401} } ],"subOrders":{"$exists":True}})
                
                for document in cursor:
                    for doc in document['subOrders']:
                        sum = sum + float(doc['amountPaid'])
                        count = count + int(doc['quantity'])

                data = {"amount":sum , "quantity":count}

                res.body= json.dumps(data,encoding='utf-8')
        finally:
                session.close()

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


        

def main():
    #tagActivatedReatilers()
    a = RetailerDetail()
    retailer = a.getNotActiveRetailer()
    otherContacts = [r for r, in session.query(RetailerContacts.mobile_number).filter_by(retailer_id=retailer.id).order_by(RetailerContacts.contact_type).all()]
    print json.dumps(todict(getRetailerObj(retailer, otherContacts, 'fresh')), encoding='utf-8')
    #print make_tiny("AA")
    
if __name__ == '__main__':
    main()