Subversion Repositories SmartDukaan

Rev

Rev 21273 | Rev 21311 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
13569 amit.gupta 1
'''
2
Created on Jan 15, 2015
3
 
4
@author: amit
5
'''
13690 amit.gupta 6
from BeautifulSoup import BeautifulSoup
13721 amit.gupta 7
from datetime import datetime, date, timedelta
13569 amit.gupta 8
from dtr import main
14412 amit.gupta 9
from dtr.dao import AffiliateInfo, Order, SubOrder, FlipkartAffiliateInfo
13690 amit.gupta 10
from dtr.main import getBrowserObject, getStore, ParseException, ungzipResponse, \
14398 amit.gupta 11
    Store as MStore, sourceMap, tprint
21246 amit.gupta 12
from dtr.storage.DataService import Clicks, Users, FlipkartOrders, OrdersRaw
16209 amit.gupta 13
from dtr.utils import utils
21310 amit.gupta 14
from dtr.utils.utils import fetchResponseUsingProxy, todict, getSkuData, \
20395 amit.gupta 15
    ORDER_PLACED
15539 amit.gupta 16
from elixir import *
13690 amit.gupta 17
from pprint import pprint
18
from pymongo.mongo_client import MongoClient
21310 amit.gupta 19
from urlparse import urlparse
17238 amit.gupta 20
import StringIO
21
import csv
13690 amit.gupta 22
import hashlib
13658 manas 23
import importlib
13690 amit.gupta 24
import json
25
import mechanize
14412 amit.gupta 26
import pymongo
13658 manas 27
import re
21310 amit.gupta 28
import time
14338 amit.gupta 29
import traceback
13658 manas 30
import urllib
18156 amit.gupta 31
import urllib2
17238 amit.gupta 32
import zipfile
13658 manas 33
USERNAME='saholic1@gmail.com'
34
PASSWORD='spice@2020'
21264 amit.gupta 35
ORDER_TRACK_URL='https://www.flipkart.com/order_details?src=or&pr=1&type=physical&'
17238 amit.gupta 36
AFFILIATE_URL='https://affiliate.flipkart.com/'
37
AFFILIATE_LOGIN_URL='https://affiliate.flipkart.com/a_login'
38
AFF_REPORT_URL = "https://affiliate.flipkart.com/downloads/a_downloadRequest?type=OrdersReport&parameters=%s"
39
AFF_DOWNLOAD_URL="https://affiliate.flipkart.com/downloads/file?id=%s"
13690 amit.gupta 40
AFF_STATUS_CANCELLED='cancelled'
41
AFF_STATUS_APPROVED='approved'
42
AFF_STATUS_DISAPPROVED='disapproved'
43
AFF_STATUS_PENDING='pending'
17238 amit.gupta 44
statuses = [AFF_STATUS_CANCELLED, AFF_STATUS_APPROVED, AFF_STATUS_DISAPPROVED,AFF_STATUS_PENDING ]
15539 amit.gupta 45
categoryMap = {3:"Mobiles", 5:"Tablets"}
21269 amit.gupta 46
mobileAgent = 'Mozilla/5.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/600.1.3 (KHTML, like Gecko) Version/8.0 Mobile/12A4345d Safari/600.1.4'
13658 manas 47
 
21266 amit.gupta 48
headers = { 
21269 amit.gupta 49
            'User-Agent':'Mozilla/5.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/600.1.3 (KHTML, like Gecko) Version/8.0 Mobile/12A4345d Safari/600.1.4',
21266 amit.gupta 50
            'Accept' : 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',      
51
            'Accept-Language' : 'en-US,en;q=0.8',                     
52
            'Accept-Charset' : 'ISO-8859-1,utf-8;q=0.7,*;q=0.3',
53
            'Connection':'keep-alive',
54
            'Accept-Encoding' : 'gzip,deflate,sdch'
55
        }
56
 
21273 amit.gupta 57
TRACK_URLS = []
58
TRACK_HEADERS = {
59
        "sn":"2.VIBAC8BD9D21024F649B0482FAC385814A.SIE6C5F25D78974A5EB850D89167D52009.VSE7C76F85C2EE463786F89407CA46CA31.1492756338",
60
        "Connection":"keep-alive",
61
        "Referer":"https://www.flipkart.com/rv/orders?link=myAccounts",
62
        "cache-control":"no-cache",
63
        "Accept":"/",
64
        "Accept-Language":"en-US,en;q=0.8",
65
        "content-type":"application/json",
66
        "User-Agent":"Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML:like Gecko) Chrome/48.0.2564.23 Mobile Safari/537.36",
67
        "flipkart_secure":"true",
68
        "sc":"",
69
        "Accept-Encoding":"gzip:deflate:sdch:br",
70
        "x-user-agent":"Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML:like Gecko) Chrome/48.0.2564.23 Mobile Safari/537.36 FKUA/msite/0.0.1/msite/Mobile,Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML:like Gecko) Chrome/48.0.2564.23 Mobile Safari/537.36 FKUA/msite/0.0.1/msite/Mobile",
71
        "pragma":"no-cache",
72
        "issecureresource":"true"
73
}
74
 
75
 
13781 amit.gupta 76
class Store(MStore):
13658 manas 77
    OrderStatusMap = {
14679 amit.gupta 78
                      main.Store.ORDER_PLACED : ['approval', 'processing', 'shipping'],
79
                      main.Store.ORDER_DELIVERED : ['your item has been delivered'],
14680 amit.gupta 80
                      main.Store.ORDER_SHIPPED : ['in transit', 'shipment yet to be delivered'],
81
                      main.Store.ORDER_CANCELLED : ['shipment is returned', 'your item has been returned', 'your shipment has been cancelled', 'your shipment has been cancelled.']
13658 manas 82
 
83
                      }
84
    def __init__(self,store_id):
85
        client = MongoClient('mongodb://localhost:27017/')
86
        self.db = client.dtr
87
        super(Store, self).__init__(store_id)
88
 
13569 amit.gupta 89
    def getName(self):
90
        return "flipkart"
91
 
21310 amit.gupta 92
    def _parseJSON(self,merchantOrder, transaction):
93
        update = False
94
        if not merchantOrder.subOrders:
95
            merchantOrder.placedOn = transaction['orderDate'] 
96
            merchantOrder.paidAmount = transaction['amount']
97
            subOrders = []
98
            merchantOrder.subOrders = subOrders
99
            for shipment in transaction['groupedItems']:
100
                for item in shipment:
101
                    productUrl = "https://www.flipkart.com/" + item['itemMetadata']
102
                    merchantsubOrder = SubOrder(item['title']+ item['itemMetadata']['color'], productUrl, merchantOrder.placedOn, item['amount'],MStore.ORDER_PLACED, item['quantity'])
103
                    merchantsubOrder.merchantSubOrderId = item['orderItemId']
104
                    merchantsubOrder.imgUrl  = item['itemMetadata']['images']['1000x1000']
105
                    productCode=productUrl.split("pid=")[1]
106
                    merchantsubOrder.productCode = productCode
107
                    merchantsubOrder.merchantSubOrderId = item['orderItemId']
108
                    merchantsubOrder.amount = item['sellingPrice']*merchantsubOrder.quantity
109
                    merchantsubOrder.unitPrice = item['sellingPrice']
110
                    merchantsubOrder.detailedStatus = item['desktopSubStatus']
111
                    subOrders.append(merchantsubOrder)
112
        else:
113
            update = True
114
            for shipment in transaction['groupedItems']:
115
                for item in shipment:
116
                    subOrder = self._isSubOrderActive(merchantOrder,  item['orderItemId'])
117
                    if subOrder:
118
                        subOrder.detailedStatus = item['desktopSubStatus']
119
 
120
        self.populateDerivedFields(merchantOrder, update)
121
 
122
    def _getActiveOrders(self, searchMap={}, collectionMap={}):
123
        collection = self.db.merchantOrder
124
        searchMap = dict(searchMap.items()+ {"closed": False, "storeId" : self.store_id}.items()) 
125
        #collectionMap =  dict(collectionMap.items() + {"orderSuccessUrl":1, "orderId":1,"subOrders":1, "placedOn":1, "orderTracking"}.items())
126
        stores = collection.find(searchMap)
127
        return [store for store in stores]    
128
 
129
 
21273 amit.gupta 130
    def trackOrdersForUser(self, userId, url, rawHtml):
131
        rawHtml = re.sub(r'[^\x00-\x7F]+',' ', rawHtml)
132
        if url not in TRACK_URLS:
133
            for lis in re.findall('SN:"(.*?)"', rawHtml):
134
                TRACK_HEADERS['sn'] = lis
135
                break
136
            for lis in re.findall('SN:"(.*?)"', rawHtml):
137
                TRACK_HEADERS['User-Agent'] = lis.split(" fkUA")[0]
138
                TRACK_HEADERS['x-user-agent'] = lis
139
                break
21310 amit.gupta 140
            if self._getActiveOrders({"createdOnInt":int(time.mktime(datetime.now().timetuple()))}):
141
                return {"headers":TRACK_HEADERS, "urls":TRACK_URLS}
142
            else:
143
                return {"headers":TRACK_HEADERS, "urls":[]}
21273 amit.gupta 144
        else:
21310 amit.gupta 145
            jsonObject = json.loads(rawHtml)
146
            #Get only orders less than one month old
147
            activeOrders = self._getActiveOrders({"createdOnInt":{"$gt":int(time.mktime(datetime.now().timetuple() - 30*86400))}})
148
            for order in activeOrders:
149
                for transaction in jsonObject['RESPONSE']['orderGranularDetails']:
150
                    if transaction['orderId'][:-3] == order["mechantOrderId"]:
151
                        self._parseJSON(order, transaction)
152
                        break
153
 
154
 
155
 
21273 amit.gupta 156
            return 'PARSED_SUCCESS'
157
 
17238 amit.gupta 158
 
159
    def requestDownload(self):
160
    #"https://affiliate.flipkart.com/downloads/a_downloadRequest?type=OrdersReport&parameters=%7B%22filter%22%3A%22approved%22%2C%22till%22%3A%222015-10-03%22%2C%22from%22%3A%222015-04-03%22%7D"
161
        requestReportUrl = "https://affiliate.flipkart.com/downloads/a_downloadRequest?type=OrdersReport&parameters=%s"
162
        br = getBrowserObject()
163
        br.set_debug_responses(True)
164
        br.open(AFFILIATE_URL)
165
        response = br.response()  # copy
166
        #token =  re.findall('window.__FK = "(.*?)"', utils.ungzipResponse(response), re.IGNORECASE)[0]
167
        data = {
168
                    'j_username':'saholic1@gmail.com',
169
                    'j_password':'spice@2020'
170
            }
171
        print utils.ungzipResponse(br.open(AFFILIATE_LOGIN_URL, urllib.urlencode(data)))
172
        till = datetime.strftime(date.today(),"%Y-%m-%d")
173
        start = datetime.strftime(date.today() - timedelta(4), "%Y-%m-%d")
174
        #target = open("dowloadreportids", 'w')
175
        #target.truncate()
176
        for status in statuses:
177
            #try:
178
                data = {"till":till, "from":start, "filter":status}
179
                print json.dumps(data)
180
                request = requestReportUrl%(urllib.quote_plus(json.dumps(data).replace(" ", "")))
181
                print request
182
                response = utils.ungzipResponse(br.open(request))
183
                response = json.loads(response)
184
                print response
185
                if(response['status']=="OK"):
186
                    self.db.flipkartdownloadids.save(response)
187
                else:
188
                    utils.sendmail(['amit.gupta@shop2020.in'], '', "Could not get request data for Flipkart Affiliate downlaod")
189
                    #break 
190
            #except:
191
                utils.sendmail(['amit.gupta@shop2020.in'], '', "Could not get request data for Flipkart Affiliate downlaod due to Internal Server Error")
192
                #break 
193
 
194
 
13690 amit.gupta 195
    def scrapeStoreOrders(self,):
196
        orders = self._getActiveOrders()
13721 amit.gupta 197
        for order in orders:
14692 amit.gupta 198
            print "Order", self.store_name, order['orderId']
14398 amit.gupta 199
            try:
200
                closed = True
20421 amit.gupta 201
                url = ORDER_TRACK_URL + urlparse(order['orderSuccessUrl']).query    
21266 amit.gupta 202
                page = fetchResponseUsingProxy(url, headers)
14398 amit.gupta 203
                soup = BeautifulSoup(page,convertEntities=BeautifulSoup.HTML_ENTITIES)
204
 
205
                sections = soup.findAll("div", {"class":"ui-app-card-body"})
206
                sections.pop(1)
13721 amit.gupta 207
 
14398 amit.gupta 208
                mainOrder = soup.find("ul",{"class":"m-bottom p-cart"})
209
                fkSubOrders = mainOrder.findAll("li")
210
 
211
                #remove unwanted list
212
                fkSubOrders.pop(-1)
213
 
214
 
215
                bulk = self.db.merchantOrder.initialize_ordered_bulk_op()
216
                #fetching suborders details
217
                for subOrder in fkSubOrders:
218
                    updateMap = {}
14692 amit.gupta 219
                    ul = subOrder.find("ul")
220
                    if ul is None:
221
                        ul = subOrder.findAll("div", recursive=False)[0].div.div
222
                    orderItems = ul.findAll("div", recursive=False)
14398 amit.gupta 223
                    for orderItem in orderItems:
224
                        closedStatus = False
20422 amit.gupta 225
                        divs = orderItem.findAll('div', recursive=False)
226
                        orderTracking = divs[2]
227
                        merchantSubOrderId = divs[3].get('id')
14398 amit.gupta 228
                        subOrder =  self._isSubOrderActive(order, merchantSubOrderId)
229
                        if subOrder is None:
230
                            break
14460 amit.gupta 231
                        elif subOrder['closed']:
232
                            break
14398 amit.gupta 233
                        findMap = {"orderId": order['orderId'], "subOrders.merchantSubOrderId": merchantSubOrderId}
234
                        orderTrackingDetDiv = divs[3].find('div',{'class':'c-tabs-content m-top active'})
20422 amit.gupta 235
                        cashbackStatus = subOrder.get("cashBackStatus")
20420 amit.gupta 236
                        if orderTrackingDetDiv is not None:
237
                            orderTrackingDet = str(orderTrackingDetDiv.find("div", "tracking-remark").text)
238
                            updateMap["subOrders.$.detailedStatus"] = orderTrackingDet
239
                            tr = orderTracking.findAll("div",{"class":"tap-bullet-area c-tab-trigger"})
240
 
241
                            tr = orderTracking.findAll("div",{"class":"tap-bullet-area c-tab-trigger"})
242
 
243
                            if "approveDetails-ongoing" in str(tr) or "processingDetails-ongoing" in str(tr):
244
                                status=MStore.ORDER_PLACED
245
                            elif "shippingDetails-ongoing" in str(tr):
246
                                status = MStore.ORDER_SHIPPED
247
                            elif "delivery-complete" in str(tr):
248
                                status = MStore.ORDER_DELIVERED
20421 amit.gupta 249
                                if cashbackStatus != Store.CB_NA:
20420 amit.gupta 250
                                    cashbackStatus = Store.CB_APPROVED
251
                                closedStatus = True
252
                            if "dead" in str(tr) or "shippingDetails-returnOngoing" in str(tr) or "shippingDetails-return" in str(tr):
253
                                status = MStore.ORDER_CANCELLED
254
                                closedStatus = True
255
                                if cashbackStatus == Store.CB_PENDING:
256
                                    cashbackStatus = Store.CB_CANCELLED
257
                        else:
258
                            updateMap["subOrders.$.detailedStatus"] = "Refunded"
14398 amit.gupta 259
                            status = MStore.ORDER_CANCELLED
260
                            closedStatus = True
261
                            if cashbackStatus == Store.CB_PENDING:
262
                                cashbackStatus = Store.CB_CANCELLED
20417 amit.gupta 263
                        print "Sub Order Status " + str(status)
14398 amit.gupta 264
 
265
                        updateMap["subOrders.$.cashBackStatus"] = cashbackStatus
266
                        updateMap["subOrders.$.status"] = status
267
                        updateMap["subOrders.$.closed"] = closedStatus
268
                        if closed:
269
                            closed = closedStatus
270
                        bulk.find(findMap).update({'$set' : updateMap})
14692 amit.gupta 271
                bulk.find({'orderId': order['orderId']}).update({'$set':{'closed': closed, 'parseError':False}})
14398 amit.gupta 272
                bulk.execute()            
273
            except:
14692 amit.gupta 274
                self.db.merchantOrder.update({"orderId":order['orderId']}, {"$set":{"parseError":True}})
14847 amit.gupta 275
                tprint("Could not update " + str(order['orderId']) + ' for store ' + self.getName())
14398 amit.gupta 276
                traceback.print_exc()
17238 amit.gupta 277
 
278
    def scrapeAffiliate(self, deltaDays=0):
279
        if deltaDays is None:
280
            deltaDays=0
281
        endDate=date.today() - timedelta(days=1)
282
        startDate = endDate - timedelta(days=deltaDays)
15539 amit.gupta 283
 
17238 amit.gupta 284
        endDate = datetime.strftime(endDate, "%Y-%m-%d")
285
        startDate = datetime.strftime(startDate, "%Y-%m-%d")
17241 amit.gupta 286
        url  = "https://affiliate-api.flipkart.net/affiliate/report/orders/detail/json?startDate=%s&endDate=%s&status=%s&offset=0"
17238 amit.gupta 287
 
288
        for status in statuses:
17241 amit.gupta 289
            nextUrl = url%(startDate, endDate, status)
290
            while nextUrl:
17243 amit.gupta 291
                req = urllib2.Request(nextUrl)
17242 amit.gupta 292
                nextUrl=''
17238 amit.gupta 293
                req.add_header('Fk-Affiliate-Id', 'saholic1g')
294
                req.add_header('Fk-Affiliate-Token', 'a757444e260c46be8c4aeb20352246ac')
295
                resp = urllib2.urlopen(req)
296
                resString = json.loads(resp.read())
297
                orderList = resString["orderList"]
298
                if orderList:
299
                    for order in orderList:
300
                        order['sales'] = int(order['sales']['amount'])
301
                        order['tentativeCommission'] = int(order['tentativeCommission']['amount'])
302
                        subTagId = order.get("affExtParam1")
303
                        userId = None
304
                        email = None
305
                        if subTagId:
306
                            click = session.query(Clicks).filter_by(tag = subTagId).first()
307
                            if click is not None:
308
                                userId= click.user_id 
309
                                user = session.query(Users.email).filter_by(id = userId).first()
310
                                if user is not None:
311
                                    email = user.email
312
 
313
                        flipkartOrder = FlipkartOrders()
314
                        flipkartOrder.subtagId = subTagId
315
                        flipkartOrder.user_id = userId
316
                        flipkartOrder.identifier = order.get("identifier")
317
                        flipkartOrder.email = email
18465 amit.gupta 318
                        flipkartOrder.created = datetime.strptime(order.get("orderDate"), "%d-%m-%Y %H:%M:%S")
17238 amit.gupta 319
                        flipkartOrder.status = order.get("status")
320
                        flipkartOrder.title = order.get("title")
321
                        flipkartOrder.price = order.get("price")
322
                        flipkartOrder.quantity = order.get("quantity")
323
                        flipkartOrder.productCode = order.get("productId")
324
                        flipkartOrder.affiliateOrderItemId = order.get("affiliateOrderItemId")
325
                        flipkartOrder.payOut = order['tentativeCommission']
326
                        flipkartOrder.payOutPercentage = order['commissionRate']
327
                        skuData = getSkuData(2, order.get("productId"))
328
                        if skuData is not None:
329
                            flipkartOrder.catalogId = skuData.get("skuBundleId")
330
                            flipkartOrder.brand = skuData.get("brand")
331
                            flipkartOrder.model = skuData.get("model_name")
332
                            flipkartOrder.category = categoryMap.get(skuData.get("category_id"))
333
                            flipkartOrder.title =skuData.get("source_product_name")
334
 
335
                    session.commit()
17241 amit.gupta 336
                    nextUrl = resString['next']  
13721 amit.gupta 337
 
14412 amit.gupta 338
    def _saveToAffiliate(self, offers):
17238 amit.gupta 339
        collection = self.db.flipkartOrderAffiliateInfo1
340
        count=0
341
        for row in offers:
342
            if count==0:
343
                count += 1
344
                continue
345
            offer = self.covertToObj(row)
346
            collection.save(offer)
347
 
348
    def covertToObj(self,offer):
349
        affiliateorderitemid,title,productid,category,quantity,sales,price,commissionrate,tentativecommission,status,orderdate,saleschannel,customertype,affextparam1, affextparam2  = offer
350
        saleMap = {
351
               "affiliateorderitemid":affiliateorderitemid,
352
                "title":title,
353
                "productid":productid,
354
                "category":category,
355
                "quantity":quantity,
356
                "saleAmount":sales,
357
                "price":price,
358
                "commissionrate":commissionrate,
359
                "payOut":tentativecommission,
360
                "conversionStatus":status,
361
                "saleDate":orderdate,
362
                "saleschannel":saleschannel,
363
                "customertype":customertype,
364
                "affextparam1":affextparam1,
365
                "_id":affiliateorderitemid
366
        }
367
        return saleMap
14412 amit.gupta 368
 
369
 
21310 amit.gupta 370
def parseOrderRawHtml(self, orderId, subTagId, userId, rawHtml, orderSuccessUrl):
371
    resp= {}
372
    try:
373
        url = ORDER_TRACK_URL + urlparse(orderSuccessUrl).query 
374
        merchantOrderId = re.findall('reference_id=(.*?)&', orderSuccessUrl,re.IGNORECASE)[0]
13781 amit.gupta 375
 
21310 amit.gupta 376
        merchantOrder = Order(orderId, userId, subTagId, self.store_id, orderSuccessUrl)
377
        merchantOrder.closed = False
378
        merchantOrder.merchantOrderId = merchantOrderId
379
        merchantOrder.orderTrackingUrl = url
380
        merchantOrder.requireDetail = True
381
        if self._saveToOrder(todict(merchantOrder)):
382
            resp['result'] = 'ORDER_CREATED'
383
        else:
384
            resp['result'] = 'ORDER_ALREADY_CREATED_IGNORED'
13781 amit.gupta 385
 
21310 amit.gupta 386
        return resp 
387
    except:
388
        traceback.print_exc()
389
        resp['result'] = 'ORDER_NOT_CREATED'
390
        return resp 
391
 
392
 
393
 
14617 amit.gupta 394
    def _getStatusFromDetailedStatus(self, detailedStatus):
395
        for key, value in Store.OrderStatusMap.iteritems():
14626 amit.gupta 396
            if detailedStatus.lower() in value:
14617 amit.gupta 397
                return key
14676 amit.gupta 398
        print "Detailed Status need to be mapped", detailedStatus, "Store:", self.store_name
20392 amit.gupta 399
        raise ParseException("_getStatusFromDetailedStatus", "Found new order status" + detailedStatus)           
13658 manas 400
 
401
def _saveToOrderFlipkart(self, order):
402
        collection = self.db.merchantOrder
403
        order = collection.insert(order)
404
 
13690 amit.gupta 405
 
406
 
407
def hex_md5(password):
408
    m = hashlib.md5()
409
    print(m.digest())
410
 
13658 manas 411
def main():
16210 amit.gupta 412
    store = getStore(2)
21246 amit.gupta 413
    store.parseOrderRawHtml(1, '1234', 14, '', 'https://www.flipkart.com/rv/orderConfirmation/orderresponse?pr=1&reference_id=OD1088257258903640&src=or&type=physical&token=e0fa1db468ba77bfb8cdac938e051ef3')
414
    #store.scrapeStoreOrders()
13679 manas 415
 
16209 amit.gupta 416
if __name__ == '__main__':
417
        main()
14145 amit.gupta 418