Subversion Repositories SmartDukaan

Rev

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