Subversion Repositories SmartDukaan

Rev

Rev 20422 | Rev 21246 | 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 = {}
14692 amit.gupta 124
                    ul = subOrder.find("ul")
125
                    if ul is None:
126
                        ul = subOrder.findAll("div", recursive=False)[0].div.div
127
                    orderItems = ul.findAll("div", recursive=False)
14398 amit.gupta 128
                    for orderItem in orderItems:
129
                        closedStatus = False
20422 amit.gupta 130
                        divs = orderItem.findAll('div', recursive=False)
131
                        orderTracking = divs[2]
132
                        merchantSubOrderId = divs[3].get('id')
14398 amit.gupta 133
                        subOrder =  self._isSubOrderActive(order, merchantSubOrderId)
134
                        if subOrder is None:
135
                            break
14460 amit.gupta 136
                        elif subOrder['closed']:
137
                            break
14398 amit.gupta 138
                        findMap = {"orderId": order['orderId'], "subOrders.merchantSubOrderId": merchantSubOrderId}
139
                        orderTrackingDetDiv = divs[3].find('div',{'class':'c-tabs-content m-top active'})
20422 amit.gupta 140
                        cashbackStatus = subOrder.get("cashBackStatus")
20420 amit.gupta 141
                        if orderTrackingDetDiv is not None:
142
                            orderTrackingDet = str(orderTrackingDetDiv.find("div", "tracking-remark").text)
143
                            updateMap["subOrders.$.detailedStatus"] = orderTrackingDet
144
                            tr = orderTracking.findAll("div",{"class":"tap-bullet-area c-tab-trigger"})
145
 
146
                            tr = orderTracking.findAll("div",{"class":"tap-bullet-area c-tab-trigger"})
147
 
148
                            if "approveDetails-ongoing" in str(tr) or "processingDetails-ongoing" in str(tr):
149
                                status=MStore.ORDER_PLACED
150
                            elif "shippingDetails-ongoing" in str(tr):
151
                                status = MStore.ORDER_SHIPPED
152
                            elif "delivery-complete" in str(tr):
153
                                status = MStore.ORDER_DELIVERED
20421 amit.gupta 154
                                if cashbackStatus != Store.CB_NA:
20420 amit.gupta 155
                                    cashbackStatus = Store.CB_APPROVED
156
                                closedStatus = True
157
                            if "dead" in str(tr) or "shippingDetails-returnOngoing" in str(tr) or "shippingDetails-return" in str(tr):
158
                                status = MStore.ORDER_CANCELLED
159
                                closedStatus = True
160
                                if cashbackStatus == Store.CB_PENDING:
161
                                    cashbackStatus = Store.CB_CANCELLED
162
                        else:
163
                            updateMap["subOrders.$.detailedStatus"] = "Refunded"
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
            for subOrder in fkSubOrders:
20392 amit.gupta 317
                orderItems = subOrder.findAll("div", "product-list-item", recursive=True)
13781 amit.gupta 318
                for orderItem in orderItems:
20422 amit.gupta 319
                    if not orderItem.has_key("id"):
320
                        continue
13781 amit.gupta 321
                    divs = orderItem.findAll('div', recursive=False)
322
                    content = divs[0]
323
                    orderTracking = divs[2]
20422 amit.gupta 324
                    merchantSubOrderId = divs[3].get('id')
13781 amit.gupta 325
                    imgUrl = content.find('img')['src']
326
                    lineDet = content.find("div",{"class":"product-info"})
327
                    productTitle = lineDet.find("a",{"class":"product-title"}).text
328
                    productUrl =  str(lineDet.find("a")['href'])
329
 
330
                    start='pid='
331
                    s=str(lineDet.find("a")['href'])
14339 amit.gupta 332
                    productCode = re.findall(re.escape(start)+"(.*)",s)[0].strip()
13781 amit.gupta 333
                    mname = lineDet.findAll("span")
334
                    k=0
335
                    while k<len(mname):
336
                        if "note" in str(mname[k]):
337
                            if "Color:" in str(mname[k]):
338
                                productTitle = productTitle + " " + mname[k+1].text
339
 
340
                            elif "Qty:" in str(mname[k]):
341
                                quantity = int(mname[k+1].text)
342
                            elif "Subtotal:" in str(mname[k]):
14343 amit.gupta 343
                                amountPaid = int(re.findall(r'\d+', mname[k+1].text)[0])
13781 amit.gupta 344
                            elif "Delivery:" in str(mname[k]):
345
                                #Delivery Date for sub order
346
                                print "Delivery Date " +mname[k+1].text
347
                        k=k+1
14343 amit.gupta 348
                    merchantsubOrder = SubOrder(productTitle, productUrl, merchantOrder.placedOn, amountPaid,MStore.ORDER_PLACED, quantity)
13781 amit.gupta 349
                    merchantsubOrder.imgUrl  = imgUrl
350
                    merchantsubOrder.productCode = productCode
351
                    merchantsubOrder.merchantSubOrderId = merchantSubOrderId
14337 amit.gupta 352
                    print "productCode", productCode
14340 amit.gupta 353
                    print "amountPaid", amountPaid
14336 amit.gupta 354
                    cashbackAmount, cashbackPercent = self.getCashbackAmount(productCode, amountPaid)
13781 amit.gupta 355
                    cashbackStatus = Store.CB_PENDING
356
                    if cashbackAmount <= 0:
357
                        cashbackStatus = Store.CB_NA
358
                    merchantsubOrder.cashBackAmount = cashbackAmount
359
                    merchantsubOrder.cashBackStatus = cashbackStatus      
20395 amit.gupta 360
                    merchantsubOrder.cashBackPercentage = cashbackPercent
20422 amit.gupta 361
                    activePart = orderItem.find("div", "c-tabs-content m-top active")
362
                    if activePart is not None:
363
                        merchantsubOrder.detailedStatus = str(activePart.find("div", "tracking-remark").text)   
13781 amit.gupta 364
 
365
                    #To track shipping details         
20417 amit.gupta 366
                    status=ORDER_PLACED
13781 amit.gupta 367
                    tr = orderTracking.findAll("div",{"class":"tap-bullet-area c-tab-trigger"})
20418 amit.gupta 368
                    if "approveDetails-ongoing" in str(tr) or "processingDetails-ongoing" in str(tr):
20417 amit.gupta 369
                        pass
370
                    elif "shippingDetails-ongoing" in str(tr):
371
                        status = MStore.ORDER_SHIPPED
372
                    elif "delivery-complete" in str(tr):
373
                        status = MStore.ORDER_DELIVERED
20432 amit.gupta 374
                        if cashbackStatus!=MStore.CB_NA:
375
                            merchantsubOrder.cashBackStatus = MStore.CB_APPROVED
20417 amit.gupta 376
                        merchantsubOrder.closed = True
14692 amit.gupta 377
                    if "dead" in str(tr) or "shippingDetails-returnOngoing" in str(tr) or "shippingDetails-return" in str(tr):
20422 amit.gupta 378
                        status = MStore.ORDER_CANCELLED
379
                        if merchantsubOrder.cashBackStatus != MStore.CB_NA:    
380
                            merchantsubOrder.cashBackStatus = MStore.CB_CANCELLED
20417 amit.gupta 381
                        merchantsubOrder.closed = True
20395 amit.gupta 382
                    print "Sub Order Status " + str(status)
20396 amit.gupta 383
                    merchantsubOrder.status=status
20417 amit.gupta 384
                    if merchantOrder.closed:
385
                        merchantOrder.closed = merchantsubOrder.closed 
20396 amit.gupta 386
                    subOrders.append(merchantsubOrder)
20395 amit.gupta 387
 
14312 amit.gupta 388
            if self._saveToOrder(todict(merchantOrder)):
389
                resp['result'] = 'ORDER_CREATED'
390
            else:
391
                resp['result'] = 'ORDER_ALREADY_CREATED_IGNORED'
392
 
13796 amit.gupta 393
            return resp 
13781 amit.gupta 394
        except:
14338 amit.gupta 395
            traceback.print_exc()
14312 amit.gupta 396
            resp['result'] = 'ORDER_NOT_CREATED'
13796 amit.gupta 397
            return resp 
13781 amit.gupta 398
 
14617 amit.gupta 399
    def _getStatusFromDetailedStatus(self, detailedStatus):
400
        for key, value in Store.OrderStatusMap.iteritems():
14626 amit.gupta 401
            if detailedStatus.lower() in value:
14617 amit.gupta 402
                return key
14676 amit.gupta 403
        print "Detailed Status need to be mapped", detailedStatus, "Store:", self.store_name
20392 amit.gupta 404
        raise ParseException("_getStatusFromDetailedStatus", "Found new order status" + detailedStatus)           
13658 manas 405
 
406
def _saveToOrderFlipkart(self, order):
407
        collection = self.db.merchantOrder
408
        order = collection.insert(order)
409
 
13690 amit.gupta 410
 
411
 
412
def hex_md5(password):
413
    m = hashlib.md5()
414
    print(m.digest())
415
 
13658 manas 416
def main():
16210 amit.gupta 417
    store = getStore(2)
20422 amit.gupta 418
    #store.parseOrderRawHtml(1, '123', 14, '', '    https://www.flipkart.com/rv/orderConfirmation/orderresponse?reference_id=OD4072085355271530&token=c8a726cb1495232e00338fb0eecb4f40')
20417 amit.gupta 419
    store.scrapeStoreOrders()
13679 manas 420
 
16209 amit.gupta 421
if __name__ == '__main__':
422
        main()
14145 amit.gupta 423