Subversion Repositories SmartDukaan

Rev

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

import urllib2
import simplejson as json
import pymongo
from dtr.utils.utils import to_java_date, getNlcPoints
from datetime import datetime, timedelta
from operator import itemgetter
from dtr.utils.AmazonPriceOnlyScraper import AmazonScraper
from dtr.utils import AmazonDealScraper
from dtr.utils import FlipkartScraper,NewFlipkartScraper
from dtr.storage.MemCache import MemCache
from functools import partial
import threading
from dtr.utils.utils import getCashBack
import traceback
from shop2020.config.client.ConfigClient import ConfigClient

config_client = ConfigClient()
host_memCache = config_client.get_property('mem_cache_host_dtr')
host = config_client.get_property('mongo_dtr_host')

mc = MemCache(host_memCache)


con = None
SOURCE_MAP = {'AMAZON':1,'FLIPKART':2,'SNAPDEAL':3,'SAHOLIC':4}

headers = { 
           'User-agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11',
            'Accept' : 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',      
            'Accept-Language' : 'en-US,en;q=0.8',                     
            'Accept-Charset' : 'ISO-8859-1,utf-8;q=0.7,*;q=0.3'
        }

ignoreItems = []

def get_mongo_connection(port=27017):
    global con
    if con is None:
        print "Establishing connection %s host and port %d" %(host,port)
        try:
            con = pymongo.MongoClient(host, port)
        except Exception, e:
            print e
            return None
    return con

def returnLatestPrice(data, source_id, ignoreLastUpdated = True):
    now = datetime.now()
    if source_id == 1:
        try:
            if data['identifier'] is None or len(data['identifier'].strip())==0:
                return {}
            
            if data['_id'] in ignoreItems:
                print "Ignored items returning for %d"%(data['_id'])
                return {'_id':data['_id'],'available_price':data['available_price'],'in_stock':data['in_stock'],'source_id':1,'source_product_name':data['source_product_name'],'marketPlaceUrl':data['marketPlaceUrl'],'thumbnail':data['thumbnail']}
            
            
            if data['dealFlag'] ==1 and data['dealType'] ==1:
                data['marketPlaceUrl'] = "http://www.amazon.in/dp/%s"%(data['identifier'].strip())
            
            try:
                if ignoreLastUpdated and data['priceUpdatedOn'] > to_java_date(now - timedelta(minutes=5)):
                    print "sku id is already updated",data['_id'] 
                    return {'_id':data['_id'],'available_price':data['available_price'],'in_stock':data['in_stock'],'source_id':1,'source_product_name':data['source_product_name'],'marketPlaceUrl':data['marketPlaceUrl'],'thumbnail':data['thumbnail']}
            except:
                pass
            
            
            url = "http://www.amazon.in/gp/offer-listing/%s/ref=olp_sort_ps"%(data['identifier'])
            lowestPrice = 0.0
            try:
                if data['dealFlag'] ==1 and data['dealType'] ==1:
                    print "Inside deal"
                    deal_url = "http://www.amazon.in/dp/%s"%(data['identifier'].strip())
                    print deal_url
                    dealScraperAmazon = AmazonDealScraper.AmazonScraper(True)
                    lowestPrice = dealScraperAmazon.read(deal_url)
                    print lowestPrice
                    if lowestPrice == 0:
                        raise
                else:    
                    scraperAmazon = AmazonScraper(True)
                    lowestPrice = scraperAmazon.read(url)
            except Exception as e:
                print e
                scraperAmazon = AmazonScraper(True)
                lowestPrice = scraperAmazon.read(url)
            print "LowestPrice ",lowestPrice
            inStock = 0
            if lowestPrice > 0:
                inStock = 1
            if lowestPrice > 0:
                get_mongo_connection().Catalog.MasterData.update({'_id':data['_id']}, {'$set' : {'available_price':lowestPrice,'updatedOn':to_java_date(now),'priceUpdatedOn':to_java_date(now),'in_stock':inStock}}, multi=True)
                get_mongo_connection().Catalog.Deals.update({'_id':data['_id']}, {'$set' : {'available_price':lowestPrice , 'in_stock':inStock,'dealType':data['dealType']}}, multi=True)
            else:
                lowestPrice = data['available_price']
                get_mongo_connection().Catalog.MasterData.update({'_id':data['_id']}, {'$set' : {'updatedOn':to_java_date(now),'in_stock':0,'priceUpdatedOn':to_java_date(now)}}, multi=True)
                get_mongo_connection().Catalog.Deals.update({'_id':data['_id']}, {'$set' : {'in_stock':0,'dealType':data['dealType']}}, multi=True)
            
            return {'_id':data['_id'],'available_price':lowestPrice,'in_stock':inStock,'source_id':1,'source_product_name':data['source_product_name'],'marketPlaceUrl':data['marketPlaceUrl'],'thumbnail':data['thumbnail']}
        except Exception as e:
            print "Exception for _id %d and source %s"%(data['_id'], source_id)
            print e
            return {'_id':data['_id'],'available_price':data['available_price'],'in_stock':data['in_stock'],'source_id':1,'source_product_name':data['source_product_name'],'marketPlaceUrl':data['marketPlaceUrl'],'thumbnail':data['thumbnail']}
        
    elif source_id ==4:
        
        try:
            if data['identifier'] is None or len(data['identifier'].strip())==0:
                return {}
            
            try:
                if ignoreLastUpdated and data['priceUpdatedOn'] > to_java_date(now - timedelta(minutes=5)):
                    print "sku id is already updated",data['_id'] 
                    return {'_id':data['_id'],'available_price':data['available_price'],'in_stock':data['in_stock'],'source_id':4,'source_product_name':data['source_product_name'],'marketPlaceUrl':data['marketPlaceUrl'],'thumbnail':data['thumbnail']}
            except:
                pass
            
            url = "http://50.116.3.101:8080/mobileapi/dtr-pricing?id=%s"%(data['identifier'])
            lowestPrice = 0.0
            instock = 0
            req = urllib2.Request(url,headers=headers)
            response = urllib2.urlopen(req)
            json_input = response.read()
            response.close()
            priceInfo = json.loads(json_input)
            lowestPrice = priceInfo['response']['sellingPrice']
            if lowestPrice > 0:
                instock = 1
            if instock  == 1:
                get_mongo_connection().Catalog.MasterData.update({'_id':data['_id']}, {'$set' : {'available_price':lowestPrice,'updatedOn':to_java_date(now),'priceUpdatedOn':to_java_date(now),'in_stock':instock}}, multi=True)
                get_mongo_connection().Catalog.Deals.update({'_id':data['_id']}, {'$set' : {'available_price':lowestPrice , 'in_stock':instock}}, multi=True)
            else:
                lowestPrice = data['available_price']
                get_mongo_connection().Catalog.MasterData.update({'_id':data['_id']}, {'$set' : {'updatedOn':to_java_date(now),'in_stock':instock,'priceUpdatedOn':to_java_date(now)}}, multi=True)
                get_mongo_connection().Catalog.Deals.update({'_id':data['_id']}, {'$set' : {'in_stock':instock}}, multi=True)
            
            return {'_id':data['_id'],'available_price':lowestPrice,'in_stock':instock,'source_id':4,'source_product_name':data['source_product_name'],'marketPlaceUrl':data['marketPlaceUrl'],'thumbnail':data['thumbnail']}
        
        except Exception as e:
            print "Exception for _id %d and source %s"%(data['_id'], source_id)
            print e
            return {'_id':data['_id'],'available_price':data['available_price'],'in_stock':data['in_stock'],'source_id':4,'source_product_name':data['source_product_name'],'marketPlaceUrl':data['marketPlaceUrl'],'thumbnail':data['thumbnail']}
        
        
    elif source_id ==3:
        try:
            if data['identifier'] is None or len(data['identifier'].strip())==0:
                return {}
            
            try:
                if ignoreLastUpdated and data['priceUpdatedOn'] > to_java_date(now - timedelta(minutes=5)):
                    print "sku id is already updated",data['_id']
                    return {'_id':data['_id'],'available_price':data['available_price'],'in_stock':data['in_stock'],'source_id':3,'source_product_name':data['source_product_name'],'marketPlaceUrl':data['marketPlaceUrl'],'thumbnail':data['thumbnail']}
                
            except Exception as e:
                print "Exception snapdeal"
                print e
            
            url="http://www.snapdeal.com/acors/json/gvbps?supc=%s&catId=175"%(data['identifier'])
            req = urllib2.Request(url,headers=headers)
            response = urllib2.urlopen(req)
            json_input = response.read()
            response.close()
            vendorInfo = json.loads(json_input)
            lowestOfferPrice = 0
            inStock = 0
            buyBoxPrice = 0
            isBuyBox = 1
            for vendor in vendorInfo:
                buyBoxPrice = float(vendor['sellingPrice'])
                try:
                    buyBoxStock = vendor['buyableInventory']
                except:
                    buyBoxStock = 0
                if buyBoxStock > 0 and buyBoxPrice > 0:
                    break
                
            sortedVendorsData = sorted(vendorInfo, key=itemgetter('sellingPrice'))
            for sortedVendorData in sortedVendorsData:
                lowestOfferPrice = float(sortedVendorData['sellingPrice'])
                try:
                    stock = sortedVendorData['buyableInventory']
                except:
                    stock = 0
                if stock > 0 and lowestOfferPrice > 0:
                    inStock = 1
                    break
                    
            print lowestOfferPrice
            print inStock
            print "*************"
            
            if buyBoxPrice != lowestOfferPrice:
                isBuyBox = 0
            
            if inStock  == 1:
                get_mongo_connection().Catalog.MasterData.update({'_id':data['_id']}, {'$set' : {'available_price':lowestOfferPrice,'updatedOn':to_java_date(now),'priceUpdatedOn':to_java_date(now),'in_stock':inStock,'buyBoxFlag':isBuyBox}}, multi=True)
                get_mongo_connection().Catalog.Deals.update({'_id':data['_id']}, {'$set' : {'available_price':lowestOfferPrice , 'in_stock':inStock}}, multi=True)
            else:
                lowestOfferPrice = data['available_price']
                get_mongo_connection().Catalog.MasterData.update({'_id':data['_id']}, {'$set' : {'updatedOn':to_java_date(now),'in_stock':inStock,'priceUpdatedOn':to_java_date(now),'buyBoxFlag':isBuyBox}}, multi=True)
                get_mongo_connection().Catalog.Deals.update({'_id':data['_id']}, {'$set' : {'in_stock':inStock}}, multi=True)
            
            return {'_id':data['_id'],'available_price':lowestOfferPrice,'in_stock':inStock,'source_id':3,'source_product_name':data['source_product_name'],'marketPlaceUrl':data['marketPlaceUrl'],'thumbnail':data['thumbnail']}
        except Exception as e:
            print traceback.print_exc()
            print "Exception for _id %d and source %s"%(data['_id'], source_id)
            print e
            return {'_id':data['_id'],'available_price':data['available_price'],'in_stock':data['in_stock'],'source_id':3,'source_product_name':data['source_product_name'],'marketPlaceUrl':data['marketPlaceUrl'],'thumbnail':data['thumbnail']}
        
    elif source_id == 2:
        try:
            if data['identifier'] is None or len(data['identifier'].strip())==0:
                return {}
            
            if data['_id'] in ignoreItems:
                print "Ignored items returning for %d"%(data['_id'])
                return {'_id':data['_id'],'available_price':data['available_price'],'in_stock':data['in_stock'],'source_id':2,'source_product_name':data['source_product_name'],'marketPlaceUrl':data['marketPlaceUrl'],'thumbnail':data['thumbnail']}
            
            try:
                if ignoreLastUpdated and data['priceUpdatedOn'] > to_java_date(now - timedelta(minutes=5)):
                    print "sku id is already updated",data['_id']
                    return {'_id':data['_id'],'available_price':data['available_price'],'in_stock':data['in_stock'],'source_id':2,'source_product_name':data['source_product_name'],'marketPlaceUrl':data['marketPlaceUrl'],'thumbnail':data['thumbnail']} 
            except:
                pass
            
            lowestSp = 0
            inStock = 0
            buyBoxPrice = 0
            isBuyBox = 0
            scraperProductPage = NewFlipkartScraper.FlipkartProductPageScraper()
            try:
                if data['marketPlaceUrl']!="" or data['marketPlaceUrl'] !="http://www.flipkart.com/ps/%s"%(data['identifier']):
                    result = scraperProductPage.read(data['marketPlaceUrl'])
                    print result
                    if result.get('lowestSp')!=0:
                        lowestSp = result.get('lowestSp')
                        inStock = result.get('inStock')
                        buyBoxPrice = result.get('buyBoxPrice')
            except:
                print "Unable to scrape product page ",data['identifier']
            if lowestSp ==0:
                url = "http://www.flipkart.com/ps/%s"%(data['identifier'])
                scraperFk = FlipkartScraper.FlipkartScraper()
                vendorsData, buyBoxInfo = (scraperFk.read(url))
                sortedVendorsData = []
                sortedVendorsData = sorted(vendorsData, key=itemgetter('sellingPrice'))
                print "data",sortedVendorsData
                for vData in sortedVendorsData:
                    lowestSp = vData['sellingPrice']
                    break
                if lowestSp > 0:
                    inStock = 1
                buyBoxPrice = buyBoxInfo[0].get('sellingPrice')
            print lowestSp
            print inStock
            if buyBoxPrice is not None and buyBoxPrice == lowestSp:
                isBuyBox = 1
            if lowestSp > 0:
                get_mongo_connection().Catalog.MasterData.update({'_id':data['_id']}, {'$set' : {'available_price':lowestSp,'updatedOn':to_java_date(now),'priceUpdatedOn':to_java_date(now),'in_stock':inStock,'buyBoxFlag':isBuyBox}}, multi=True)
                get_mongo_connection().Catalog.Deals.update({'_id':data['_id']}, {'$set' : {'available_price':lowestSp , 'in_stock':inStock}}, multi=True)
            else:
                lowestSp = data['available_price']
                get_mongo_connection().Catalog.MasterData.update({'_id':data['_id']}, {'$set' : {'updatedOn':to_java_date(now),'in_stock':inStock,'priceUpdatedOn':to_java_date(now),'buyBoxFlag':isBuyBox}}, multi=True)
                get_mongo_connection().Catalog.Deals.update({'_id':data['_id']}, {'$set' : {'in_stock':inStock}}, multi=True)
                
            return {'_id':data['_id'],'available_price':lowestSp,'in_stock':inStock,'source_id':2,'source_product_name':data['source_product_name'],'marketPlaceUrl':data['marketPlaceUrl'],'thumbnail':data['thumbnail']}
            
        except Exception as e:
            print "Exception for _id %d and source %s"%(data['_id'], source_id)
            print e
            return {'_id':data['_id'],'available_price':data['available_price'],'in_stock':data['in_stock'],'source_id':2,'source_product_name':data['source_product_name'],'marketPlaceUrl':data['marketPlaceUrl'],'thumbnail':data['thumbnail']}
    else:
        return {}

def recomputePoints(item, deal):
    try:
        nlcPoints = getNlcPoints(item, deal['minNlc'], deal['maxNlc'], deal['available_price'])
    except:
        print traceback.print_exc()
        nlcPoints = deal['nlcPoints']
    if item['manualDealThresholdPrice'] >= deal['available_price']:
        dealPoints = item['dealPoints']
    else:
        dealPoints = 0
    get_mongo_connection().Catalog.Deals.update({'_id':deal['_id']},{"$set":{'totalPoints':deal['totalPoints'] - deal['nlcPoints'] + nlcPoints - deal['dealPoints'] +dealPoints , 'nlcPoints': nlcPoints, 'dealPoints': dealPoints, 'manualDealThresholdPrice': item['manualDealThresholdPrice']}})


def populateNegativeDeals():
    negativeDeals = get_mongo_connection().Catalog.NegativeDeals.find().distinct('sku')
    mc.set("negative_deals", negativeDeals, 600)

def recomputeDeal(item):
    """Lets recompute deal for this bundle"""
    print "Recomputing for bundleId",item.get('skuBundleId')
    skuBundleId = item['skuBundleId']
    
    similarItems = list(get_mongo_connection().Catalog.Deals.find({'skuBundleId':skuBundleId}).sort([('available_price',pymongo.ASCENDING)]))
    bestPrice = float("inf")
    bestOne = None
    bestSellerPoints = 0
    toUpdate = []
    for similarItem in similarItems:
        if similarItem['_id'] == item['_id']:
            recomputePoints(item, similarItem)
        if mc.get("negative_deals") is None:
            populateNegativeDeals()
        if similarItem['in_stock'] == 0 or similarItem['maxprice'] is None or similarItem['maxprice'] < similarItem['available_price'] or similarItem['_id'] in mc.get("negative_deals"):
            get_mongo_connection().Catalog.Deals.update({ '_id' : similarItem['_id'] }, {'$set':{'showDeal':0 }})
            continue
        if similarItem['available_price'] < bestPrice:
            bestOne = similarItem
            bestPrice = similarItem['available_price']
            bestSellerPoints = similarItem['bestSellerPoints']
        elif similarItem['available_price'] == bestPrice and bestSellerPoints < similarItem['bestSellerPoints']:
            bestOne = similarItem
            bestPrice = similarItem['available_price']
            bestSellerPoints = similarItem['bestSellerPoints']
        else:
            pass
    if bestOne is not None:
        for similarItem in similarItems:
            toUpdate.append(similarItem['_id'])
        toUpdate.remove(bestOne['_id'])
        get_mongo_connection().Catalog.Deals.update({ '_id' : bestOne['_id'] }, {'$set':{'showDeal':1 }})
    if len(toUpdate) > 0:
        get_mongo_connection().Catalog.Deals.update({ '_id' : { "$in": toUpdate } }, {'$set':{'showDeal':0 }},upsert=False, multi=True)
    
    print "Done with recomputing"

def getLatestPrice(skuBundleId, source_id):
    temp = []
    itemIds = list(get_mongo_connection().Catalog.MasterData.find({'skuBundleId':skuBundleId,'source_id' : source_id}))
    for item in itemIds:
        item['dealFlag'] = 0
        item['dealType'] = 0
        item['dealPoints'] = 0
        item['manualDealThresholdPrice'] = None
        if item['source_id'] ==3:
            item['marketPlaceUrl'] = item['marketPlaceUrl']+'?supc='+item.get('identifier')
        manualDeals = list(get_mongo_connection().Catalog.ManualDeals.find({'startDate':{'$lte':to_java_date(datetime.now())},'endDate':{'$gte':to_java_date(datetime.now())},'source_id':source_id, 'sku':item['_id']}))
        if len(manualDeals) > 0:
            item['dealFlag'] = 1
            item['dealType'] =manualDeals[0]['dealType']
            item['dealPoints'] = manualDeals[0]['dealPoints']
            item['manualDealThresholdPrice'] = manualDeals[0]['dealThresholdPrice']
        info = returnLatestPrice(item, source_id)
        print info
        try:
            cashBack = getCashBack(item['_id'], item['source_id'], item['category_id'], mc, 'localhost')
            print "CashBack is ",cashBack
            if not cashBack or cashBack.get('cash_back_status')!=1:
                info['cash_back_type'] = 0
                info['cash_back'] = 0
            else:
                if cashBack['cash_back_type'] in (1,2):
                    info['cash_back_type'] = cashBack['cash_back_type']
                    info['cash_back'] = float(cashBack['cash_back'])
                else:
                    info['cash_back_type'] = 0
                    info['cash_back'] = 0
        except Exception as cashBackEx:
            traceback.print_exc()
            print "Error calculating cashback."
            info['cash_back_type'] = 0
            info['cash_back'] = 0
        print "info is ",info
        temp.append(info)
    try:
        thread = threading.Thread(target=recomputeDeal, args = (item,))
        thread.daemon = True
        thread.start()    
    except:
        print traceback.print_exc()
        print "Unable to compute deal for ",skuBundleId
    return temp

def getLatestPriceById(id):
    item = list(get_mongo_connection().Catalog.MasterData.find({'_id':id}))
    item[0]['dealFlag'] = 0
    item[0]['dealType'] = 0
    item[0]['dealPoints'] = 0
    item[0]['manualDealThresholdPrice'] = None
    manualDeals = list(get_mongo_connection().Catalog.ManualDeals.find({'startDate':{'$lte':to_java_date(datetime.now())},'endDate':{'$gte':to_java_date(datetime.now())},'source_id':item[0]['source_id'], 'sku':item[0]['_id']}))
    if len(manualDeals) > 0:
        item[0]['dealFlag'] = 1
        item[0]['dealType'] =manualDeals[0]['dealType']
        item[0]['dealPoints'] = manualDeals[0]['dealPoints']
        item[0]['manualDealThresholdPrice'] = manualDeals[0]['dealThresholdPrice']
    
    info = returnLatestPrice(item[0], item[0]['source_id'])
    print info
    try:
        cashBack = getCashBack(item[0]['_id'], item[0]['source_id'], item[0]['category_id'], mc, 'localhost')
        print "CashBack is ",cashBack
        if not cashBack or cashBack.get('cash_back_status')!=1:
            info['cash_back_type'] = 0
            info['cash_back'] = 0
        else:
            if cashBack['cash_back_type'] in (1,2):
                info['cash_back_type'] = cashBack['cash_back_type']
                info['cash_back'] = float(cashBack['cash_back'])
            else:
                info['cash_back_type'] = 0
                info['cash_back'] = 0
    except Exception as cashBackEx:
        traceback.print_exc()
        print cashBackEx
        print "Error calculating cashback."
        info['cash_back_type'] = 0
        info['cash_back'] = 0
    try:
        thread = threading.Thread(target=recomputeDeal, args = (item[0],))
        thread.daemon = True
        thread.start()    
    except:
        print "Unable to compute deal for ",item[0]['skuBundleId']
    return info

def updatePriceForNotificationBundles(skuBundleId):
    itemIds = list(get_mongo_connection().Catalog.MasterData.find({'skuBundleId':skuBundleId,'priceUpdatedOn':{'$lte':to_java_date(datetime.now() - timedelta(minutes=2))},'source_id':{"$in":SOURCE_MAP.values()}}))
    for item in itemIds:
        print item['_id']
        item['dealFlag'] = 0
        item['dealType'] = 0
        item['dealPoints'] = 0
        item['manualDealThresholdPrice'] = None
        manualDeals = list(get_mongo_connection().Catalog.ManualDeals.find({'startDate':{'$lte':to_java_date(datetime.now())},'endDate':{'$gte':to_java_date(datetime.now())},'source_id':item['source_id'], 'sku':item['_id']}))
        if len(manualDeals) > 0:
            item['dealFlag'] = 1
            item['dealType'] =manualDeals[0]['dealType']
            item['dealPoints'] = manualDeals[0]['dealPoints']
            item['manualDealThresholdPrice'] = manualDeals[0]['dealThresholdPrice']
        info = returnLatestPrice(item, item['source_id'],False)
        print info

def main():
    print "retuned %s"%(str(getLatestPrice(1132,1)))

if __name__=='__main__':
    main()