Subversion Repositories SmartDukaan

Rev

Rev 21266 | Rev 21269 | 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:
20392 amit.gupta 286
            url = ORDER_TRACK_URL + urlparse(orderSuccessUrl).query 
13781 amit.gupta 287
 
21267 amit.gupta 288
            page = fetchResponseUsingProxy(url, headers)
13781 amit.gupta 289
 
290
            merchantOrderId = re.findall('reference_id=(.*?)&', orderSuccessUrl,re.IGNORECASE)[0]
291
            print merchantOrderId
292
 
293
            soup = BeautifulSoup(page,convertEntities=BeautifulSoup.HTML_ENTITIES)
294
 
295
            sections = soup.findAll("div", {"class":"ui-app-card-body"})
296
            sections.pop(1)
297
 
298
            merchantOrder = Order(orderId, userId, subTagId, self.store_id, orderSuccessUrl)
20417 amit.gupta 299
            merchantOrder.closed = True
14145 amit.gupta 300
            merchantOrder.orderTrackingUrl = url
13781 amit.gupta 301
            for data in sections:
302
                name = data.findAll("span")
303
                i=0
304
                while i< len(name):
305
                    if "key" in str(name[i]):
306
                        if "Grand Total" in str(name[i]):
307
                            #Total Amount
308
                            merchantOrder.paidAmount = int(re.findall(r'\d+', name[i+1].text)[0])
309
                        elif "Order Date" in str(name[i]):
310
                            merchantOrder.placedOn = name[i+1].text 
311
                    i=i+1    
312
 
313
            merchantOrder.merchantOrderId = merchantOrderId
314
 
315
            mainOrder = soup.find("ul",{"class":"m-bottom p-cart"})
316
            fkSubOrders = mainOrder.findAll("li")
317
            #remove unwanted list
318
            fkSubOrders.pop(-1)
319
            subOrders = []
320
            merchantOrder.subOrders = subOrders
321
 
322
            for subOrder in fkSubOrders:
20392 amit.gupta 323
                orderItems = subOrder.findAll("div", "product-list-item", recursive=True)
13781 amit.gupta 324
                for orderItem in orderItems:
20422 amit.gupta 325
                    if not orderItem.has_key("id"):
326
                        continue
13781 amit.gupta 327
                    divs = orderItem.findAll('div', recursive=False)
328
                    content = divs[0]
329
                    orderTracking = divs[2]
20422 amit.gupta 330
                    merchantSubOrderId = divs[3].get('id')
13781 amit.gupta 331
                    imgUrl = content.find('img')['src']
332
                    lineDet = content.find("div",{"class":"product-info"})
333
                    productTitle = lineDet.find("a",{"class":"product-title"}).text
334
                    productUrl =  str(lineDet.find("a")['href'])
335
 
336
                    start='pid='
337
                    s=str(lineDet.find("a")['href'])
14339 amit.gupta 338
                    productCode = re.findall(re.escape(start)+"(.*)",s)[0].strip()
13781 amit.gupta 339
                    mname = lineDet.findAll("span")
340
                    k=0
341
                    while k<len(mname):
342
                        if "note" in str(mname[k]):
343
                            if "Color:" in str(mname[k]):
344
                                productTitle = productTitle + " " + mname[k+1].text
345
 
346
                            elif "Qty:" in str(mname[k]):
347
                                quantity = int(mname[k+1].text)
348
                            elif "Subtotal:" in str(mname[k]):
14343 amit.gupta 349
                                amountPaid = int(re.findall(r'\d+', mname[k+1].text)[0])
13781 amit.gupta 350
                            elif "Delivery:" in str(mname[k]):
351
                                #Delivery Date for sub order
352
                                print "Delivery Date " +mname[k+1].text
353
                        k=k+1
14343 amit.gupta 354
                    merchantsubOrder = SubOrder(productTitle, productUrl, merchantOrder.placedOn, amountPaid,MStore.ORDER_PLACED, quantity)
13781 amit.gupta 355
                    merchantsubOrder.imgUrl  = imgUrl
356
                    merchantsubOrder.productCode = productCode
357
                    merchantsubOrder.merchantSubOrderId = merchantSubOrderId
14337 amit.gupta 358
                    print "productCode", productCode
14340 amit.gupta 359
                    print "amountPaid", amountPaid
14336 amit.gupta 360
                    cashbackAmount, cashbackPercent = self.getCashbackAmount(productCode, amountPaid)
13781 amit.gupta 361
                    cashbackStatus = Store.CB_PENDING
362
                    if cashbackAmount <= 0:
363
                        cashbackStatus = Store.CB_NA
364
                    merchantsubOrder.cashBackAmount = cashbackAmount
365
                    merchantsubOrder.cashBackStatus = cashbackStatus      
20395 amit.gupta 366
                    merchantsubOrder.cashBackPercentage = cashbackPercent
20422 amit.gupta 367
                    activePart = orderItem.find("div", "c-tabs-content m-top active")
368
                    if activePart is not None:
369
                        merchantsubOrder.detailedStatus = str(activePart.find("div", "tracking-remark").text)   
13781 amit.gupta 370
 
371
                    #To track shipping details         
20417 amit.gupta 372
                    status=ORDER_PLACED
13781 amit.gupta 373
                    tr = orderTracking.findAll("div",{"class":"tap-bullet-area c-tab-trigger"})
20418 amit.gupta 374
                    if "approveDetails-ongoing" in str(tr) or "processingDetails-ongoing" in str(tr):
20417 amit.gupta 375
                        pass
376
                    elif "shippingDetails-ongoing" in str(tr):
377
                        status = MStore.ORDER_SHIPPED
378
                    elif "delivery-complete" in str(tr):
379
                        status = MStore.ORDER_DELIVERED
20432 amit.gupta 380
                        if cashbackStatus!=MStore.CB_NA:
381
                            merchantsubOrder.cashBackStatus = MStore.CB_APPROVED
20417 amit.gupta 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):
20422 amit.gupta 384
                        status = MStore.ORDER_CANCELLED
385
                        if merchantsubOrder.cashBackStatus != MStore.CB_NA:    
386
                            merchantsubOrder.cashBackStatus = MStore.CB_CANCELLED
20417 amit.gupta 387
                        merchantsubOrder.closed = True
20395 amit.gupta 388
                    print "Sub Order Status " + str(status)
20396 amit.gupta 389
                    merchantsubOrder.status=status
20417 amit.gupta 390
                    if merchantOrder.closed:
391
                        merchantOrder.closed = merchantsubOrder.closed 
20396 amit.gupta 392
                    subOrders.append(merchantsubOrder)
20395 amit.gupta 393
 
14312 amit.gupta 394
            if self._saveToOrder(todict(merchantOrder)):
395
                resp['result'] = 'ORDER_CREATED'
396
            else:
397
                resp['result'] = 'ORDER_ALREADY_CREATED_IGNORED'
398
 
13796 amit.gupta 399
            return resp 
13781 amit.gupta 400
        except:
14338 amit.gupta 401
            traceback.print_exc()
14312 amit.gupta 402
            resp['result'] = 'ORDER_NOT_CREATED'
13796 amit.gupta 403
            return resp 
13781 amit.gupta 404
 
14617 amit.gupta 405
    def _getStatusFromDetailedStatus(self, detailedStatus):
406
        for key, value in Store.OrderStatusMap.iteritems():
14626 amit.gupta 407
            if detailedStatus.lower() in value:
14617 amit.gupta 408
                return key
14676 amit.gupta 409
        print "Detailed Status need to be mapped", detailedStatus, "Store:", self.store_name
20392 amit.gupta 410
        raise ParseException("_getStatusFromDetailedStatus", "Found new order status" + detailedStatus)           
13658 manas 411
 
412
def _saveToOrderFlipkart(self, order):
413
        collection = self.db.merchantOrder
414
        order = collection.insert(order)
415
 
13690 amit.gupta 416
 
417
 
418
def hex_md5(password):
419
    m = hashlib.md5()
420
    print(m.digest())
421
 
13658 manas 422
def main():
16210 amit.gupta 423
    store = getStore(2)
21246 amit.gupta 424
    store.parseOrderRawHtml(1, '1234', 14, '', 'https://www.flipkart.com/rv/orderConfirmation/orderresponse?pr=1&reference_id=OD1088257258903640&src=or&type=physical&token=e0fa1db468ba77bfb8cdac938e051ef3')
425
    #store.scrapeStoreOrders()
13679 manas 426
 
16209 amit.gupta 427
if __name__ == '__main__':
428
        main()
14145 amit.gupta 429