Subversion Repositories SmartDukaan

Rev

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