Subversion Repositories SmartDukaan

Rev

Rev 20418 | Rev 20420 | 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
20392 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'})
20412 amit.gupta 146
                        orderTrackingDet = str(orderTrackingDetDiv.find("div", "tracking-remark").text)
14398 amit.gupta 147
                        updateMap["subOrders.$.detailedStatus"] = orderTrackingDet
20417 amit.gupta 148
                        '''status = self._getStatusFromDetailedStatus(orderTrackingDet)'''
14398 amit.gupta 149
                        tr = orderTracking.findAll("div",{"class":"tap-bullet-area c-tab-trigger"})
20417 amit.gupta 150
                        cashbackStatus = subOrder.get("cashBackStatus")
14398 amit.gupta 151
 
20417 amit.gupta 152
                        tr = orderTracking.findAll("div",{"class":"tap-bullet-area c-tab-trigger"})
153
 
20418 amit.gupta 154
                        if "approveDetails-ongoing" in str(tr) or "processingDetails-ongoing" in str(tr):
20417 amit.gupta 155
                            status=MStore.ORDER_PLACED
156
                        elif "shippingDetails-ongoing" in str(tr):
157
                            status = MStore.ORDER_SHIPPED
158
                        elif "delivery-complete" in str(tr):
159
                            status = MStore.ORDER_DELIVERED
160
                            if cashbackStatus == Store.CB_PENDING:
161
                                cashbackStatus = Store.CB_APPROVED
162
                            closedStatus = True
163
                        if "dead" in str(tr) or "shippingDetails-returnOngoing" in str(tr) or "shippingDetails-return" in str(tr):
14398 amit.gupta 164
                            status = MStore.ORDER_CANCELLED
165
                            closedStatus = True
166
                            if cashbackStatus == Store.CB_PENDING:
167
                                cashbackStatus = Store.CB_CANCELLED
20417 amit.gupta 168
                        print "Sub Order Status " + str(status)
14398 amit.gupta 169
 
170
                        updateMap["subOrders.$.cashBackStatus"] = cashbackStatus
171
                        updateMap["subOrders.$.status"] = status
172
                        updateMap["subOrders.$.closed"] = closedStatus
173
                        if closed:
174
                            closed = closedStatus
175
                        bulk.find(findMap).update({'$set' : updateMap})
14692 amit.gupta 176
                bulk.find({'orderId': order['orderId']}).update({'$set':{'closed': closed, 'parseError':False}})
14398 amit.gupta 177
                bulk.execute()            
178
            except:
14692 amit.gupta 179
                self.db.merchantOrder.update({"orderId":order['orderId']}, {"$set":{"parseError":True}})
14847 amit.gupta 180
                tprint("Could not update " + str(order['orderId']) + ' for store ' + self.getName())
14398 amit.gupta 181
                traceback.print_exc()
17238 amit.gupta 182
 
183
    def scrapeAffiliate(self, deltaDays=0):
184
        if deltaDays is None:
185
            deltaDays=0
186
        endDate=date.today() - timedelta(days=1)
187
        startDate = endDate - timedelta(days=deltaDays)
15539 amit.gupta 188
 
17238 amit.gupta 189
        endDate = datetime.strftime(endDate, "%Y-%m-%d")
190
        startDate = datetime.strftime(startDate, "%Y-%m-%d")
17241 amit.gupta 191
        url  = "https://affiliate-api.flipkart.net/affiliate/report/orders/detail/json?startDate=%s&endDate=%s&status=%s&offset=0"
17238 amit.gupta 192
 
193
        for status in statuses:
17241 amit.gupta 194
            nextUrl = url%(startDate, endDate, status)
195
            while nextUrl:
17243 amit.gupta 196
                req = urllib2.Request(nextUrl)
17242 amit.gupta 197
                nextUrl=''
17238 amit.gupta 198
                req.add_header('Fk-Affiliate-Id', 'saholic1g')
199
                req.add_header('Fk-Affiliate-Token', 'a757444e260c46be8c4aeb20352246ac')
200
                resp = urllib2.urlopen(req)
201
                resString = json.loads(resp.read())
202
                orderList = resString["orderList"]
203
                if orderList:
204
                    for order in orderList:
205
                        order['sales'] = int(order['sales']['amount'])
206
                        order['tentativeCommission'] = int(order['tentativeCommission']['amount'])
207
                        subTagId = order.get("affExtParam1")
208
                        userId = None
209
                        email = None
210
                        if subTagId:
211
                            click = session.query(Clicks).filter_by(tag = subTagId).first()
212
                            if click is not None:
213
                                userId= click.user_id 
214
                                user = session.query(Users.email).filter_by(id = userId).first()
215
                                if user is not None:
216
                                    email = user.email
217
 
218
                        flipkartOrder = FlipkartOrders()
219
                        flipkartOrder.subtagId = subTagId
220
                        flipkartOrder.user_id = userId
221
                        flipkartOrder.identifier = order.get("identifier")
222
                        flipkartOrder.email = email
18465 amit.gupta 223
                        flipkartOrder.created = datetime.strptime(order.get("orderDate"), "%d-%m-%Y %H:%M:%S")
17238 amit.gupta 224
                        flipkartOrder.status = order.get("status")
225
                        flipkartOrder.title = order.get("title")
226
                        flipkartOrder.price = order.get("price")
227
                        flipkartOrder.quantity = order.get("quantity")
228
                        flipkartOrder.productCode = order.get("productId")
229
                        flipkartOrder.affiliateOrderItemId = order.get("affiliateOrderItemId")
230
                        flipkartOrder.payOut = order['tentativeCommission']
231
                        flipkartOrder.payOutPercentage = order['commissionRate']
232
                        skuData = getSkuData(2, order.get("productId"))
233
                        if skuData is not None:
234
                            flipkartOrder.catalogId = skuData.get("skuBundleId")
235
                            flipkartOrder.brand = skuData.get("brand")
236
                            flipkartOrder.model = skuData.get("model_name")
237
                            flipkartOrder.category = categoryMap.get(skuData.get("category_id"))
238
                            flipkartOrder.title =skuData.get("source_product_name")
239
 
240
                    session.commit()
17241 amit.gupta 241
                    nextUrl = resString['next']  
13721 amit.gupta 242
 
14412 amit.gupta 243
    def _saveToAffiliate(self, offers):
17238 amit.gupta 244
        collection = self.db.flipkartOrderAffiliateInfo1
245
        count=0
246
        for row in offers:
247
            if count==0:
248
                count += 1
249
                continue
250
            offer = self.covertToObj(row)
251
            collection.save(offer)
252
 
253
    def covertToObj(self,offer):
254
        affiliateorderitemid,title,productid,category,quantity,sales,price,commissionrate,tentativecommission,status,orderdate,saleschannel,customertype,affextparam1, affextparam2  = offer
255
        saleMap = {
256
               "affiliateorderitemid":affiliateorderitemid,
257
                "title":title,
258
                "productid":productid,
259
                "category":category,
260
                "quantity":quantity,
261
                "saleAmount":sales,
262
                "price":price,
263
                "commissionrate":commissionrate,
264
                "payOut":tentativecommission,
265
                "conversionStatus":status,
266
                "saleDate":orderdate,
267
                "saleschannel":saleschannel,
268
                "customertype":customertype,
269
                "affextparam1":affextparam1,
270
                "_id":affiliateorderitemid
271
        }
272
        return saleMap
14412 amit.gupta 273
 
274
 
13658 manas 275
    def parseOrderRawHtml(self, orderId, subTagId, userId, rawHtml, orderSuccessUrl):
13796 amit.gupta 276
        resp= {}
13781 amit.gupta 277
        try:
278
            br = getBrowserObject()
20392 amit.gupta 279
            url = ORDER_TRACK_URL + urlparse(orderSuccessUrl).query 
13781 amit.gupta 280
 
281
            response = br.open(url)
282
            page = ungzipResponse(response)
283
 
284
            merchantOrderId = re.findall('reference_id=(.*?)&', orderSuccessUrl,re.IGNORECASE)[0]
285
            print merchantOrderId
286
 
287
            soup = BeautifulSoup(page,convertEntities=BeautifulSoup.HTML_ENTITIES)
288
 
289
            sections = soup.findAll("div", {"class":"ui-app-card-body"})
290
            sections.pop(1)
291
 
292
            merchantOrder = Order(orderId, userId, subTagId, self.store_id, orderSuccessUrl)
20417 amit.gupta 293
            merchantOrder.closed = True
14145 amit.gupta 294
            merchantOrder.orderTrackingUrl = url
13781 amit.gupta 295
            for data in sections:
296
                name = data.findAll("span")
297
                i=0
298
                while i< len(name):
299
                    if "key" in str(name[i]):
300
                        if "Grand Total" in str(name[i]):
301
                            #Total Amount
302
                            merchantOrder.paidAmount = int(re.findall(r'\d+', name[i+1].text)[0])
303
                        elif "Order Date" in str(name[i]):
304
                            merchantOrder.placedOn = name[i+1].text 
305
                    i=i+1    
306
 
307
            merchantOrder.merchantOrderId = merchantOrderId
308
 
309
            mainOrder = soup.find("ul",{"class":"m-bottom p-cart"})
310
            fkSubOrders = mainOrder.findAll("li")
311
            #remove unwanted list
312
            fkSubOrders.pop(-1)
313
            subOrders = []
314
            merchantOrder.subOrders = subOrders
315
 
316
            #fetching suborders details
317
            for subOrder in fkSubOrders:
318
                y = subOrder.find("header").findAll("span")
319
                for suborderId in y:
320
                    if "value emp" in str(suborderId):
321
                        merchantSubOrderId = suborderId.text
322
                        break
20392 amit.gupta 323
                orderItems = subOrder.findAll("div", "product-list-item", recursive=True)
13781 amit.gupta 324
                i=0
325
                for orderItem in orderItems:
326
                    merchantOrder.placedOn
327
                    merchantSubOrderId = merchantSubOrderId + str(i)
328
                    divs = orderItem.findAll('div', recursive=False)
329
                    content = divs[0]
330
                    orderTracking = divs[2]
331
                    orderTrackingDet = divs[3]
332
 
333
 
334
                    imgUrl = content.find('img')['src']
335
                    lineDet = content.find("div",{"class":"product-info"})
336
                    productTitle = lineDet.find("a",{"class":"product-title"}).text
337
                    productUrl =  str(lineDet.find("a")['href'])
338
 
339
                    start='pid='
340
                    s=str(lineDet.find("a")['href'])
14339 amit.gupta 341
                    productCode = re.findall(re.escape(start)+"(.*)",s)[0].strip()
13781 amit.gupta 342
                    mname = lineDet.findAll("span")
343
                    k=0
344
                    while k<len(mname):
345
                        if "note" in str(mname[k]):
346
                            if "Color:" in str(mname[k]):
347
                                productTitle = productTitle + " " + mname[k+1].text
348
 
349
                            elif "Qty:" in str(mname[k]):
350
                                quantity = int(mname[k+1].text)
351
                            elif "Subtotal:" in str(mname[k]):
14343 amit.gupta 352
                                amountPaid = int(re.findall(r'\d+', mname[k+1].text)[0])
13781 amit.gupta 353
                            elif "Delivery:" in str(mname[k]):
354
                                #Delivery Date for sub order
355
                                print "Delivery Date " +mname[k+1].text
356
                        k=k+1
14343 amit.gupta 357
                    merchantsubOrder = SubOrder(productTitle, productUrl, merchantOrder.placedOn, amountPaid,MStore.ORDER_PLACED, quantity)
13781 amit.gupta 358
                    merchantsubOrder.imgUrl  = imgUrl
359
                    merchantsubOrder.productCode = productCode
360
                    merchantsubOrder.merchantSubOrderId = merchantSubOrderId
14337 amit.gupta 361
                    print "productCode", productCode
14340 amit.gupta 362
                    print "amountPaid", amountPaid
14336 amit.gupta 363
                    cashbackAmount, cashbackPercent = self.getCashbackAmount(productCode, amountPaid)
13781 amit.gupta 364
                    cashbackStatus = Store.CB_PENDING
365
                    if cashbackAmount <= 0:
366
                        cashbackStatus = Store.CB_NA
367
                    merchantsubOrder.cashBackAmount = cashbackAmount
368
                    merchantsubOrder.cashBackStatus = cashbackStatus      
20395 amit.gupta 369
                    merchantsubOrder.cashBackPercentage = cashbackPercent
20411 amit.gupta 370
                    merchantsubOrder.detailedStatus = str(orderItem.find("div", "c-tabs-content m-top active").find("div", "tracking-remark").text)   
13781 amit.gupta 371
 
372
                    #To track shipping details         
20417 amit.gupta 373
                    status=ORDER_PLACED
13781 amit.gupta 374
                    tr = orderTracking.findAll("div",{"class":"tap-bullet-area c-tab-trigger"})
20418 amit.gupta 375
                    if "approveDetails-ongoing" in str(tr) or "processingDetails-ongoing" in str(tr):
20417 amit.gupta 376
                        pass
377
                    elif "shippingDetails-ongoing" in str(tr):
378
                        status = MStore.ORDER_SHIPPED
379
                    elif "delivery-complete" in str(tr):
380
                        status = MStore.ORDER_DELIVERED
381
                        merchantsubOrder.cashBackStatus = MStore.CB_APPROVED
382
                        merchantsubOrder.closed = True
14692 amit.gupta 383
                    if "dead" in str(tr) or "shippingDetails-returnOngoing" in str(tr) or "shippingDetails-return" in str(tr):
13781 amit.gupta 384
                        status = MStore.ORDER_CANCELLED    
20417 amit.gupta 385
                        merchantsubOrder.cashBackStatus = MStore.CB_CANCELLED
386
                        merchantsubOrder.closed = True
20395 amit.gupta 387
                    print "Sub Order Status " + str(status)
20396 amit.gupta 388
                    merchantsubOrder.status=status
20417 amit.gupta 389
                    if merchantOrder.closed:
390
                        merchantOrder.closed = merchantsubOrder.closed 
20396 amit.gupta 391
                    subOrders.append(merchantsubOrder)
20395 amit.gupta 392
 
14312 amit.gupta 393
            if self._saveToOrder(todict(merchantOrder)):
394
                resp['result'] = 'ORDER_CREATED'
395
            else:
396
                resp['result'] = 'ORDER_ALREADY_CREATED_IGNORED'
397
 
13796 amit.gupta 398
            return resp 
13781 amit.gupta 399
        except:
14338 amit.gupta 400
            traceback.print_exc()
14312 amit.gupta 401
            resp['result'] = 'ORDER_NOT_CREATED'
13796 amit.gupta 402
            return resp 
13781 amit.gupta 403
 
14617 amit.gupta 404
    def _getStatusFromDetailedStatus(self, detailedStatus):
405
        for key, value in Store.OrderStatusMap.iteritems():
14626 amit.gupta 406
            if detailedStatus.lower() in value:
14617 amit.gupta 407
                return key
14676 amit.gupta 408
        print "Detailed Status need to be mapped", detailedStatus, "Store:", self.store_name
20392 amit.gupta 409
        raise ParseException("_getStatusFromDetailedStatus", "Found new order status" + detailedStatus)           
13658 manas 410
 
411
def _saveToOrderFlipkart(self, order):
412
        collection = self.db.merchantOrder
413
        order = collection.insert(order)
414
 
13690 amit.gupta 415
 
416
 
417
def hex_md5(password):
418
    m = hashlib.md5()
419
    print(m.digest())
420
 
13658 manas 421
def main():
16210 amit.gupta 422
    store = getStore(2)
20417 amit.gupta 423
    #store.parseOrderRawHtml(1, '123', 14, '', 'https://www.flipkart.com/rv/orderConfirmation/orderresponse?reference_id=OD4072085355271530&token=c8a726cb1495232e00338fb0eecb4f40')
424
    store.scrapeStoreOrders()
13679 manas 425
 
16209 amit.gupta 426
if __name__ == '__main__':
427
        main()
14145 amit.gupta 428