Subversion Repositories SmartDukaan

Rev

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