Subversion Repositories SmartDukaan

Rev

Rev 21311 | Rev 21316 | 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,):
21311 amit.gupta 196
        pass
13690 amit.gupta 197
        orders = self._getActiveOrders()
13721 amit.gupta 198
        for order in orders:
14692 amit.gupta 199
            print "Order", self.store_name, order['orderId']
14398 amit.gupta 200
            try:
201
                closed = True
20421 amit.gupta 202
                url = ORDER_TRACK_URL + urlparse(order['orderSuccessUrl']).query    
21266 amit.gupta 203
                page = fetchResponseUsingProxy(url, headers)
14398 amit.gupta 204
                soup = BeautifulSoup(page,convertEntities=BeautifulSoup.HTML_ENTITIES)
205
 
206
                sections = soup.findAll("div", {"class":"ui-app-card-body"})
207
                sections.pop(1)
13721 amit.gupta 208
 
14398 amit.gupta 209
                mainOrder = soup.find("ul",{"class":"m-bottom p-cart"})
210
                fkSubOrders = mainOrder.findAll("li")
211
 
212
                #remove unwanted list
213
                fkSubOrders.pop(-1)
214
 
215
 
216
                bulk = self.db.merchantOrder.initialize_ordered_bulk_op()
217
                #fetching suborders details
218
                for subOrder in fkSubOrders:
219
                    updateMap = {}
14692 amit.gupta 220
                    ul = subOrder.find("ul")
221
                    if ul is None:
222
                        ul = subOrder.findAll("div", recursive=False)[0].div.div
223
                    orderItems = ul.findAll("div", recursive=False)
14398 amit.gupta 224
                    for orderItem in orderItems:
225
                        closedStatus = False
20422 amit.gupta 226
                        divs = orderItem.findAll('div', recursive=False)
227
                        orderTracking = divs[2]
228
                        merchantSubOrderId = divs[3].get('id')
14398 amit.gupta 229
                        subOrder =  self._isSubOrderActive(order, merchantSubOrderId)
230
                        if subOrder is None:
231
                            break
14460 amit.gupta 232
                        elif subOrder['closed']:
233
                            break
14398 amit.gupta 234
                        findMap = {"orderId": order['orderId'], "subOrders.merchantSubOrderId": merchantSubOrderId}
235
                        orderTrackingDetDiv = divs[3].find('div',{'class':'c-tabs-content m-top active'})
20422 amit.gupta 236
                        cashbackStatus = subOrder.get("cashBackStatus")
20420 amit.gupta 237
                        if orderTrackingDetDiv is not None:
238
                            orderTrackingDet = str(orderTrackingDetDiv.find("div", "tracking-remark").text)
239
                            updateMap["subOrders.$.detailedStatus"] = orderTrackingDet
240
                            tr = orderTracking.findAll("div",{"class":"tap-bullet-area c-tab-trigger"})
241
 
242
                            tr = orderTracking.findAll("div",{"class":"tap-bullet-area c-tab-trigger"})
243
 
244
                            if "approveDetails-ongoing" in str(tr) or "processingDetails-ongoing" in str(tr):
245
                                status=MStore.ORDER_PLACED
246
                            elif "shippingDetails-ongoing" in str(tr):
247
                                status = MStore.ORDER_SHIPPED
248
                            elif "delivery-complete" in str(tr):
249
                                status = MStore.ORDER_DELIVERED
20421 amit.gupta 250
                                if cashbackStatus != Store.CB_NA:
20420 amit.gupta 251
                                    cashbackStatus = Store.CB_APPROVED
252
                                closedStatus = True
253
                            if "dead" in str(tr) or "shippingDetails-returnOngoing" in str(tr) or "shippingDetails-return" in str(tr):
254
                                status = MStore.ORDER_CANCELLED
255
                                closedStatus = True
256
                                if cashbackStatus == Store.CB_PENDING:
257
                                    cashbackStatus = Store.CB_CANCELLED
258
                        else:
259
                            updateMap["subOrders.$.detailedStatus"] = "Refunded"
14398 amit.gupta 260
                            status = MStore.ORDER_CANCELLED
261
                            closedStatus = True
262
                            if cashbackStatus == Store.CB_PENDING:
263
                                cashbackStatus = Store.CB_CANCELLED
20417 amit.gupta 264
                        print "Sub Order Status " + str(status)
14398 amit.gupta 265
 
266
                        updateMap["subOrders.$.cashBackStatus"] = cashbackStatus
267
                        updateMap["subOrders.$.status"] = status
268
                        updateMap["subOrders.$.closed"] = closedStatus
269
                        if closed:
270
                            closed = closedStatus
271
                        bulk.find(findMap).update({'$set' : updateMap})
14692 amit.gupta 272
                bulk.find({'orderId': order['orderId']}).update({'$set':{'closed': closed, 'parseError':False}})
14398 amit.gupta 273
                bulk.execute()            
274
            except:
14692 amit.gupta 275
                self.db.merchantOrder.update({"orderId":order['orderId']}, {"$set":{"parseError":True}})
14847 amit.gupta 276
                tprint("Could not update " + str(order['orderId']) + ' for store ' + self.getName())
14398 amit.gupta 277
                traceback.print_exc()
17238 amit.gupta 278
 
279
    def scrapeAffiliate(self, deltaDays=0):
280
        if deltaDays is None:
281
            deltaDays=0
282
        endDate=date.today() - timedelta(days=1)
283
        startDate = endDate - timedelta(days=deltaDays)
15539 amit.gupta 284
 
17238 amit.gupta 285
        endDate = datetime.strftime(endDate, "%Y-%m-%d")
286
        startDate = datetime.strftime(startDate, "%Y-%m-%d")
17241 amit.gupta 287
        url  = "https://affiliate-api.flipkart.net/affiliate/report/orders/detail/json?startDate=%s&endDate=%s&status=%s&offset=0"
17238 amit.gupta 288
 
289
        for status in statuses:
17241 amit.gupta 290
            nextUrl = url%(startDate, endDate, status)
291
            while nextUrl:
17243 amit.gupta 292
                req = urllib2.Request(nextUrl)
17242 amit.gupta 293
                nextUrl=''
17238 amit.gupta 294
                req.add_header('Fk-Affiliate-Id', 'saholic1g')
295
                req.add_header('Fk-Affiliate-Token', 'a757444e260c46be8c4aeb20352246ac')
296
                resp = urllib2.urlopen(req)
297
                resString = json.loads(resp.read())
298
                orderList = resString["orderList"]
299
                if orderList:
300
                    for order in orderList:
301
                        order['sales'] = int(order['sales']['amount'])
302
                        order['tentativeCommission'] = int(order['tentativeCommission']['amount'])
303
                        subTagId = order.get("affExtParam1")
304
                        userId = None
305
                        email = None
306
                        if subTagId:
307
                            click = session.query(Clicks).filter_by(tag = subTagId).first()
308
                            if click is not None:
309
                                userId= click.user_id 
310
                                user = session.query(Users.email).filter_by(id = userId).first()
311
                                if user is not None:
312
                                    email = user.email
313
 
314
                        flipkartOrder = FlipkartOrders()
315
                        flipkartOrder.subtagId = subTagId
316
                        flipkartOrder.user_id = userId
317
                        flipkartOrder.identifier = order.get("identifier")
318
                        flipkartOrder.email = email
18465 amit.gupta 319
                        flipkartOrder.created = datetime.strptime(order.get("orderDate"), "%d-%m-%Y %H:%M:%S")
17238 amit.gupta 320
                        flipkartOrder.status = order.get("status")
321
                        flipkartOrder.title = order.get("title")
322
                        flipkartOrder.price = order.get("price")
323
                        flipkartOrder.quantity = order.get("quantity")
324
                        flipkartOrder.productCode = order.get("productId")
325
                        flipkartOrder.affiliateOrderItemId = order.get("affiliateOrderItemId")
326
                        flipkartOrder.payOut = order['tentativeCommission']
327
                        flipkartOrder.payOutPercentage = order['commissionRate']
328
                        skuData = getSkuData(2, order.get("productId"))
329
                        if skuData is not None:
330
                            flipkartOrder.catalogId = skuData.get("skuBundleId")
331
                            flipkartOrder.brand = skuData.get("brand")
332
                            flipkartOrder.model = skuData.get("model_name")
333
                            flipkartOrder.category = categoryMap.get(skuData.get("category_id"))
334
                            flipkartOrder.title =skuData.get("source_product_name")
335
 
336
                    session.commit()
17241 amit.gupta 337
                    nextUrl = resString['next']  
13721 amit.gupta 338
 
14412 amit.gupta 339
    def _saveToAffiliate(self, offers):
17238 amit.gupta 340
        collection = self.db.flipkartOrderAffiliateInfo1
341
        count=0
342
        for row in offers:
343
            if count==0:
344
                count += 1
345
                continue
346
            offer = self.covertToObj(row)
347
            collection.save(offer)
348
 
349
    def covertToObj(self,offer):
350
        affiliateorderitemid,title,productid,category,quantity,sales,price,commissionrate,tentativecommission,status,orderdate,saleschannel,customertype,affextparam1, affextparam2  = offer
351
        saleMap = {
352
               "affiliateorderitemid":affiliateorderitemid,
353
                "title":title,
354
                "productid":productid,
355
                "category":category,
356
                "quantity":quantity,
357
                "saleAmount":sales,
358
                "price":price,
359
                "commissionrate":commissionrate,
360
                "payOut":tentativecommission,
361
                "conversionStatus":status,
362
                "saleDate":orderdate,
363
                "saleschannel":saleschannel,
364
                "customertype":customertype,
365
                "affextparam1":affextparam1,
366
                "_id":affiliateorderitemid
367
        }
368
        return saleMap
14412 amit.gupta 369
 
370
 
21312 amit.gupta 371
    def parseOrderRawHtml(self, orderId, subTagId, userId, rawHtml, orderSuccessUrl):
372
        resp= {}
373
        try:
374
            url = ORDER_TRACK_URL + urlparse(orderSuccessUrl).query 
375
            merchantOrderId = re.findall('reference_id=(.*?)&', orderSuccessUrl,re.IGNORECASE)[0]
21310 amit.gupta 376
 
21312 amit.gupta 377
            merchantOrder = Order(orderId, userId, subTagId, self.store_id, orderSuccessUrl)
378
            merchantOrder.closed = False
379
            merchantOrder.merchantOrderId = merchantOrderId
380
            merchantOrder.orderTrackingUrl = url
381
            merchantOrder.requireDetail = True
382
            if self._saveToOrder(todict(merchantOrder)):
383
                resp['result'] = 'ORDER_CREATED'
384
            else:
385
                resp['result'] = 'ORDER_ALREADY_CREATED_IGNORED'
386
 
387
            return resp 
388
        except:
389
            traceback.print_exc()
390
            resp['result'] = 'ORDER_NOT_CREATED'
391
            return resp 
392
 
21310 amit.gupta 393
 
394
 
14617 amit.gupta 395
    def _getStatusFromDetailedStatus(self, detailedStatus):
396
        for key, value in Store.OrderStatusMap.iteritems():
14626 amit.gupta 397
            if detailedStatus.lower() in value:
14617 amit.gupta 398
                return key
14676 amit.gupta 399
        print "Detailed Status need to be mapped", detailedStatus, "Store:", self.store_name
20392 amit.gupta 400
        raise ParseException("_getStatusFromDetailedStatus", "Found new order status" + detailedStatus)           
13658 manas 401
 
402
def _saveToOrderFlipkart(self, order):
403
        collection = self.db.merchantOrder
404
        order = collection.insert(order)
405
 
13690 amit.gupta 406
 
407
 
408
def hex_md5(password):
409
    m = hashlib.md5()
410
    print(m.digest())
411
 
13658 manas 412
def main():
16210 amit.gupta 413
    store = getStore(2)
21312 amit.gupta 414
    store.parseOrderRawHtml(1, '1234', 14, '', 'https://www.flipkart.com/rv/orderConfirmation/orderresponse?pr=1&reference_id=OD1090350248246880&src=or&type=physical&token=3f720f955fc94219e7fef31992302b38')
21246 amit.gupta 415
    #store.scrapeStoreOrders()
13679 manas 416
 
16209 amit.gupta 417
if __name__ == '__main__':
418
        main()
14145 amit.gupta 419