Subversion Repositories SmartDukaan

Rev

Rev 14847 | Rev 14861 | 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
'''
14854 amit.gupta 6
from bs4 import BeautifulSoup
13569 amit.gupta 7
from bson.binary import Binary
13680 amit.gupta 8
from datetime import datetime, date, timedelta
13569 amit.gupta 9
from dtr import main
13576 amit.gupta 10
from dtr.dao import AffiliateInfo, Order, SubOrder
14398 amit.gupta 11
from dtr.main import getBrowserObject, ScrapeException, getStore, ParseException, \
12
    Store as MStore, ungzipResponse, tprint
14415 amit.gupta 13
from dtr.storage import Mongo
14
from dtr.storage.Mongo import getImgSrc
14758 amit.gupta 15
from dtr.utils.utils import fetchResponseUsingProxy
13662 amit.gupta 16
from pprint import pprint
13569 amit.gupta 17
from pymongo import MongoClient
18
import json
19
import pymongo
20
import re
14443 amit.gupta 21
import time
13662 amit.gupta 22
import traceback
13569 amit.gupta 23
import urllib
14854 amit.gupta 24
from urlparse import urlparse, parse_qs
13603 amit.gupta 25
 
13721 amit.gupta 26
USERNAME='profittill2@gmail.com'
13569 amit.gupta 27
PASSWORD='spice@2020'
28
AFFILIATE_URL='http://affiliate.snapdeal.com'
29
POST_URL='https://api-p03.hasoffers.com/v3/Affiliate_Report.json'
30
ORDER_TRACK_URL='https://m.snapdeal.com/orderSummary'
31
CONFIG_URL='http://affiliate.snapdeal.com/publisher/js/config.php'
32
 
13662 amit.gupta 33
class Store(MStore):
13569 amit.gupta 34
 
35
    '''
36
    This is to map order statuses of our system to order statuses of snapdeal.
37
    And our statuses will change accordingly.
38
 
39
    '''
40
    OrderStatusMap = {
14846 amit.gupta 41
                      MStore.ORDER_PLACED : ['in progress', 'pending for verification', 'not available', 'in process'],
14678 amit.gupta 42
                      MStore.ORDER_DELIVERED : ['delivered'],
43
                      MStore.ORDER_SHIPPED : ['in transit'],
14830 amit.gupta 44
                      MStore.ORDER_CANCELLED : ['closed for vendor reallocation', 'cancelled', 'product returned by courier', 'returned', 'n/a']
13569 amit.gupta 45
                      }
13662 amit.gupta 46
 
47
    CONF_CB_AMOUNT = MStore.CONF_CB_DISCOUNTED_PRICE
13569 amit.gupta 48
    def __init__(self,store_id):
49
        super(Store, self).__init__(store_id)
50
 
51
    def getName(self):
52
        return "snapdeal"
53
 
54
    def scrapeAffiliate(self, startDate=None, endDate=None):
55
        br = getBrowserObject()
56
        br.open(AFFILIATE_URL)
57
        br.select_form(nr=0)
58
        br.form['data[User][password]'] = PASSWORD 
59
        br.form['data[User][email]'] = USERNAME
60
        br.submit()
61
        response = br.open(CONFIG_URL)
62
 
13680 amit.gupta 63
        token =  re.findall('"session_token":"(.*?)"', ungzipResponse(response), re.IGNORECASE)[0]
14145 amit.gupta 64
        print token
13569 amit.gupta 65
        allOffers = self._getAllOffers(br, token)
14443 amit.gupta 66
        self._saveToAffiliate(allOffers)
13569 amit.gupta 67
 
13662 amit.gupta 68
    def _setLastSaleDate(self, saleDate):
13680 amit.gupta 69
        self.db.lastSaleDtate.update({'storeId':self.store_id}, {'$set':{'saleDate':saleDate}})
13569 amit.gupta 70
 
13662 amit.gupta 71
 
72
 
73
    def _getLastSaleDate(self,):
74
        lastDaySaleObj = self.db.lastDaySale.find_one({"storeId":self.store_id})
75
        if lastDaySaleObj is None:
76
            return datetime.min
77
 
14854 amit.gupta 78
 
79
 
80
    def _parseB(self, orderId, subTagId, userId, page, orderSuccessUrl):
81
        soup = BeautifulSoup(page)
82
 
83
        orderDetailContainerDivs = soup.body.find("div", {'class':'cardLayoutWrap'}).findAll('div', recursive=False)
84
        orderDetailDiv = orderDetailContainerDivs.pop(0)
85
        paymentDetailDiv  = orderDetailContainerDivs.pop(0)
86
        subOrders = orderDetailContainerDivs
87
 
88
        placedOn = orderDetailDiv.span.text.split(':')[1].strip()
89
        merchantOrder = Order(orderId, userId, subTagId, self.store_id, orderSuccessUrl)
90
        merchantOrder.placedOn = placedOn
91
        merchantOrder.merchantOrderId = parse_qs(urlparse(orderSuccessUrl).query)['order'][0]
92
 
93
        paymentDivs = paymentDetailDiv.findAll('div', recursive=False)
94
        paymentDivs.pop(0)
95
        for orderTr in paymentDivs:
96
            orderTrString = str(orderTr)
97
            if "Total Amount Paid" in orderTrString:
98
                amountPaid = orderTr.div.find('div', {'class':'detailBlock'}).text.strip()
99
                merchantOrder.paidAmount = int(re.findall(r'\d+', amountPaid)[0])
100
            elif "Total Amount" in orderTrString:
101
                merchantOrder.totalAmount = re.findall(r'\d+', orderTrString)[0]
102
            elif "Delivery Charges" in orderTrString:
103
                merchantOrder.deliveryCharges = re.findall(r'\d+', orderTrString)[0]
104
            elif "Discount Applied" in orderTrString:
105
                merchantOrder.discountApplied = re.findall(r'\d+', orderTrString)[0]
106
            elif "Offer Discount" in orderTrString:
107
                merchantOrder.discountApplied = re.findall(r'\d+', orderTrString)[0]
108
 
109
        merchantSubOrders = []
110
        for subOrderElement in subOrders:
111
            subOrder = self.parseSubOrderB(subOrderElement, placedOn)                           
112
            merchantSubOrders.append(subOrder)
113
        merchantOrder.subOrders = merchantSubOrders
114
        return merchantOrder
115
 
13760 amit.gupta 116
    def _parse(self, orderId, subTagId, userId, page, orderSuccessUrl):
13662 amit.gupta 117
 
13760 amit.gupta 118
        #page=page.decode("utf-8")
14854 amit.gupta 119
        soup = BeautifulSoup(page)
13760 amit.gupta 120
        #orderHead = soup.find(name, attrs, recursive, text)
121
        sections = soup.findAll("section")
122
 
123
        #print sections
124
 
125
        order = sections[1]
126
        orderTrs = order.findAll("tr")
127
 
128
        placedOn = str(orderTrs[0].findAll("td")[1].text)
129
 
130
        #Pop two section elements
131
        sections.pop(0) 
132
        sections.pop(0)
133
        subOrders = sections
134
 
135
 
136
        merchantSubOrders = []
137
 
138
        merchantOrder = Order(orderId, userId, subTagId, self.store_id, orderSuccessUrl)
14447 amit.gupta 139
        merchantOrder.placedOn = placedOn
14023 amit.gupta 140
        merchantOrder.merchantOrderId = re.findall(r'\d+', str(soup.find("div", {"class":"deals_heading"})))[1]
13760 amit.gupta 141
        for orderTr in orderTrs:
142
            orderTrString = str(orderTr)
143
            if "Total Amount" in orderTrString:
144
                merchantOrder.totalAmount = re.findall(r'\d+', orderTrString)[0]
145
            elif "Delivery Charges" in orderTrString:
146
                merchantOrder.deliveryCharges = re.findall(r'\d+', orderTrString)[0]
147
            elif "Discount Applied" in orderTrString:
148
                merchantOrder.discountApplied = re.findall(r'\d+', orderTrString)[0]
149
            elif "Paid Amount" in orderTrString:
150
                merchantOrder.paidAmount = re.findall(r'\d+', orderTrString)[0]
151
 
152
        for subOrderElement in subOrders:
13809 amit.gupta 153
            subOrders = self.parseSubOrder(subOrderElement, placedOn)                           
154
            merchantSubOrders.extend(subOrders)   
13760 amit.gupta 155
 
156
        merchantOrder.subOrders = merchantSubOrders
157
        return merchantOrder
158
 
159
    def parseSubOrder(self, subOrderElement, placedOn):
13809 amit.gupta 160
        subOrders = []
13760 amit.gupta 161
        productUrl = str(subOrderElement.find("a")['href'])
162
        subTable = subOrderElement.find("table", {"class":"lrPad"})
163
        subTrs = subTable.findAll("tr")
164
        unitPrice=None
14458 amit.gupta 165
        offerDiscount = 0
13760 amit.gupta 166
        deliveryCharges = None
167
        amountPaid = None
14458 amit.gupta 168
        amount = 0
14473 amit.gupta 169
        sdCash = 0
170
        unitPrice = 0
13760 amit.gupta 171
        for subTr in subTrs:
172
            subTrString = str(subTr)
173
            if "Unit Price" in subTrString:
14473 amit.gupta 174
                unitPrice = int(re.findall(r'\d+', subTrString)[0])
13760 amit.gupta 175
            if "Quantity" in subTrString:
14458 amit.gupta 176
                qty = int(re.findall(r'\d+', subTrString)[0])
13760 amit.gupta 177
            elif "Offer Discount" in subTrString:
14458 amit.gupta 178
                offerDiscount +=   int(re.findall(r'\d+', subTrString)[0])
14473 amit.gupta 179
            elif "SD Cash:" in subTrString:
180
                sdCash =   int(re.findall(r'\d+', subTrString)[0])
13760 amit.gupta 181
            elif "Delivery Charges" in subTrString:
14473 amit.gupta 182
                deliveryCharges =   int(re.findall(r'\d+', subTrString)[0])
13760 amit.gupta 183
            elif "Subtotal" in subTrString:
184
                if int(qty) > 0:
14459 amit.gupta 185
                    amountPaid =   int(re.findall(r'\d+', subTrString)[0])/qty
13760 amit.gupta 186
                else:
14459 amit.gupta 187
                    amountPaid =   0
14458 amit.gupta 188
        if qty>0:
14473 amit.gupta 189
            amount = unitPrice - offerDiscount - sdCash
190
            amount = 0 if amount < 0 else amount
13760 amit.gupta 191
 
14459 amit.gupta 192
        div1 = subOrderElement.find("div", {"class": "blk lrPad subordrs"})
193
        if div1 is None:
13760 amit.gupta 194
            raise ParseException("subOrder", "Could not Parse suborders for Snapdeal")
195
 
14459 amit.gupta 196
        for strDiv in str(div1).split("<div class=\"seperator\"></div>"):
197
            div = BeautifulSoup(strDiv)
13760 amit.gupta 198
            productTitle = str(subOrderElement.find("a").text)
199
            productUrl = "http://m.snapdeal.com/" + productUrl 
200
            subOrder = SubOrder(productTitle, productUrl, placedOn, amountPaid)
201
 
202
            subOrder.amountPaid = amountPaid
203
            subOrder.deliveryCharges = deliveryCharges
204
            subOrder.offerDiscount = offerDiscount
13809 amit.gupta 205
            subOrder.unitPrice = int(unitPrice)
13760 amit.gupta 206
            subOrder.productCode = re.findall(r'\d+$', productUrl)[0]
14415 amit.gupta 207
            subOrder.imgUrl = Mongo.getImgSrc(subOrder.productCode, self.store_id).get('thumbnail')
14458 amit.gupta 208
            cashbackStatus = Store.CB_NA
209
            cashbackAmount = 0
210
            percentage = 0
211
            if amount > 0:
212
                (cashbackAmount, percentage) = self.getCashbackAmount(subOrder.productCode, amount)
14473 amit.gupta 213
                if cashbackAmount > 0:
14476 amit.gupta 214
                    cashbackStatus = Store.CB_PENDING
13760 amit.gupta 215
            subOrder.cashBackStatus = cashbackStatus
216
            subOrder.cashBackAmount = cashbackAmount
14458 amit.gupta 217
            subOrder.cashBackPercentage = percentage
13760 amit.gupta 218
 
219
 
220
            trackAnchor = div.find("a")   
221
            if trackAnchor is not None:
222
                subOrder.tracingkUrl = str(trackAnchor['href'])
223
 
224
            divStr = str(div)
225
            divStr = divStr.replace("\n","").replace("\t", "")
226
 
227
            for line in divStr.split("<br />"):
228
                if "Suborder ID" in line:
229
                    subOrder.merchantSubOrderId = re.findall(r'\d+', line)[0]   
230
                elif "Status" in line:
14402 amit.gupta 231
                    print line
13760 amit.gupta 232
                    subOrder.detailedStatus = re.findall('>(.*?)</span>', line, re.IGNORECASE)[0]
233
                elif "Est. Shipping Date" in line:
234
                    subOrder.estimatedShippingDate = line.split(":")[1].strip()
235
                elif "Est. Delivery Date" in line:
236
                    subOrder.estimatedDeliveryDate = line.split(":")[1].strip()
237
                elif "Courier Name" in line:
238
                    subOrder.courierName = line.split(":")[1].strip()
239
                elif "Tracking No" in line:
240
                    subOrder.trackingNumber = line.split(":")[1].strip()
13809 amit.gupta 241
            subOrders.append(subOrder)
242
        return subOrders
13760 amit.gupta 243
 
14854 amit.gupta 244
    def parseSubOrderB(self, subOrderElement, placedOn):
245
        subOrders = []
246
        prodDivs = subOrderElement.findAll('div', recursive=False)
247
        prodDetailDiv = prodDivs[1].findAll('div', recursive=False)
248
 
249
        offerDiscount = 0
250
        deliveryCharges = None
251
        amountPaid = 0
252
        sdCash = 0
253
        unitPrice = 0
254
 
255
        paymentDivs = prodDivs[2].findAll('div', recursive=False)
256
        for paymentDiv in paymentDivs:
257
            strPaymentDiv = str(paymentDiv)
258
            if "Unit Price" in strPaymentDiv:
259
                unitPrice = int(re.findall(r'\d+', strPaymentDiv)[0])
260
            if "Offer Discount" in strPaymentDiv:
261
                offerDiscount = int(re.findall(r'\d+', strPaymentDiv)[0])
262
            elif "SD Cash:" in strPaymentDiv:
263
                sdCash =   int(re.findall(r'\d+', strPaymentDiv)[0])
264
            elif "Delivery Charges" in strPaymentDiv:
265
                deliveryCharges =   int(re.findall(r'\d+', strPaymentDiv)[0])
266
            elif "Subtotal" in strPaymentDiv:
267
                amountPaid =   int(re.findall(r'\d+', paymentDiv.find('div', {'class':'itemPriceDetail'}).text)[0])
268
 
269
        amount = unitPrice - offerDiscount - sdCash
270
 
271
        imgDiv = prodDetailDiv[0]
272
        otherDiv = prodDetailDiv[1]
273
        productTitle = otherDiv.find('div',{'class':'orderName'}).text.strip()
274
 
275
        productUrl = imgDiv.a['href']
276
        subOrder = SubOrder(productTitle, productUrl, placedOn, amountPaid)
277
 
278
        subOrder.detailedStatus = otherDiv.find('div',{'class':'orderStatus'}).span.text.strip()
279
        deliveryStatus = otherDiv.find('div',{'class':'orderDelivery'})
280
        if deliveryStatus is not None:
281
            delString = deliveryStatus.text.strip()
282
            arr = delString.split(':')
283
            if "On" in arr[0]:
284
                subOrder.deliveredOn = arr[1].strip()
285
            elif "Exp. Delivery by" in arr[0]:
286
                subOrder.estimatedDeliveryDate = arr[1].strip()
287
            else:
288
                subOrder.estimatedShippingDate = arr[1].strip()
289
 
290
        subOrder.imgUrl = imgDiv.a.img['src']
291
        subOrder.productCode = re.findall(r'\d+$', productUrl)[0]
292
        subOrder.deliveryCharges = deliveryCharges
293
        subOrder.offerDiscount = offerDiscount
294
        subOrder.unitPrice = int(unitPrice)
295
        cashbackStatus = Store.CB_NA
296
        cashbackAmount = 0
297
        percentage = 0
298
        if amountPaid > 0:
299
            (cashbackAmount, percentage) = self.getCashbackAmount(subOrder.productCode, amount)
300
            if cashbackAmount > 0:
301
                cashbackStatus = Store.CB_PENDING
302
        subOrder.cashBackStatus = cashbackStatus
303
        subOrder.cashBackAmount = cashbackAmount
304
        subOrder.cashBackPercentage = percentage
305
 
306
 
307
        courierDet = subOrderElement.find('div', {'class':'courierDetail'})
308
        if courierDet is not None:
309
            subOrder.courierName = courierDet.span.text.strip()
310
        trackingDet = subOrderElement.find('div', {'class':'trackingNo'})
311
        if trackingDet is not None:
312
            subOrder.trackingUrl = trackingDet.span.a['href']
313
            subOrder.trackingNumber = trackingDet.span.a.text.strip()
314
 
315
        subOrders.append(subOrder)
316
        return subOrder
317
 
13576 amit.gupta 318
    def parseOrderRawHtml(self, orderId, subTagId, userId, rawHtml, orderSuccessUrl):
13760 amit.gupta 319
                    #print merchantOrder
13796 amit.gupta 320
        resp = {}
13582 amit.gupta 321
        try:
322
            br = getBrowserObject()
323
            url = ORDER_TRACK_URL + re.findall('.*(\?.*?)$', orderSuccessUrl,re.IGNORECASE)[0]
13791 amit.gupta 324
            page = br.open(url)
325
            page = ungzipResponse(page)
14854 amit.gupta 326
            try:
327
                merchantOrder = self._parseB(orderId, subTagId, userId, page, orderSuccessUrl)
328
            except:
329
                merchantOrder = self._parse(orderId, subTagId, userId, page, orderSuccessUrl)
330
 
14312 amit.gupta 331
            merchantOrder.orderTrackingUrl = url
332
 
333
            if self._saveToOrder(todict(merchantOrder)):
334
                resp['result'] = 'ORDER_CREATED'
335
            else:
336
                resp['result'] = 'ORDER_ALREADY_CREATED_IGNORED'
337
 
13796 amit.gupta 338
            return resp
13582 amit.gupta 339
        except:
340
            print "Error occurred"
13603 amit.gupta 341
            traceback.print_exc()
14312 amit.gupta 342
            resp['result'] = 'ORDER_NOT_CREATED'
13796 amit.gupta 343
            return resp
13781 amit.gupta 344
 
13569 amit.gupta 345
 
346
        #soup = BeautifulSoup(rawHtml,convertEntities=BeautifulSoup.HTML_ENTITIES)
347
        #soup.find(name, attrs, recursive, text)
13576 amit.gupta 348
 
349
    def _getStatusFromDetailedStatus(self, detailedStatus):
350
        for key, value in Store.OrderStatusMap.iteritems():
14678 amit.gupta 351
            if detailedStatus.lower() in value:
13576 amit.gupta 352
                return key
14675 amit.gupta 353
        print "Detailed Status need to be mapped", detailedStatus, self.store_id
13576 amit.gupta 354
        raise ParseException("_getStatusFromDetailedStatus", "Found new order status" + detailedStatus)
13569 amit.gupta 355
 
13610 amit.gupta 356
 
13569 amit.gupta 357
    def scrapeStoreOrders(self,):
13760 amit.gupta 358
        #collectionMap = {'palcedOn':1}
13576 amit.gupta 359
        orders = self._getActiveOrders()
360
        for order in orders:
14696 amit.gupta 361
            print "Order", self.store_name, order['orderId']
14398 amit.gupta 362
            try:
363
                url = ORDER_TRACK_URL + re.findall('.*(\?.*?)$', order['orderSuccessUrl'],re.IGNORECASE)[0]
14758 amit.gupta 364
                page = fetchResponseUsingProxy(url)
14398 amit.gupta 365
                #page=page.decode("utf-8")
366
                soup = BeautifulSoup(page,convertEntities=BeautifulSoup.HTML_ENTITIES)
367
                sections = soup.findAll("section")
368
                orderEl = sections[1]
369
                orderTrs = orderEl.findAll("tr")
370
 
371
                placedOn = str(orderTrs[0].findAll("td")[1].text)
372
                sections.pop(0)
373
                sections.pop(0)
374
 
375
                subOrders = sections
376
                bulk = self.db.merchantOrder.initialize_ordered_bulk_op()
14463 amit.gupta 377
                closed = True
14398 amit.gupta 378
                for subOrderElement in subOrders:
14463 amit.gupta 379
                    div1 = subOrderElement.findAll("div", {"class": "blk lrPad subordrs"})
380
                    if len(div1)<=0:
14398 amit.gupta 381
                        raise ParseException("subOrder", "Could not Parse suborders for Snapdeal")
382
                    subOrder = None
383
                    breakFlag = False
14463 amit.gupta 384
                    for strDiv in str(div1).split("<div class=\"seperator\"></div>"):
385
                        div = BeautifulSoup(strDiv)
14398 amit.gupta 386
                        divStr = str(div)
387
                        divStr = divStr.replace("\n","").replace("\t", "")
388
                        updateMap = {}
389
                        for line in divStr.split("<br />"):
390
                            if "Suborder ID" in line:
391
                                merchantSubOrderId = re.findall(r'\d+', line)[0]
392
                                #break if suborder is inactive   
393
                                subOrder =  self._isSubOrderActive(order, merchantSubOrderId)
394
                                if subOrder is None:
395
                                    subOrders = self.parseSubOrder(subOrderElement, placedOn)
396
                                    self.db.merchantOrder.update({"orderId":order['orderId']},{'$push':{"subOrders":{"$each":todict(subOrders)}}})
397
                                    print "Added new suborders to Order id - " + order['orderId']
398
                                    closed = False
399
                                    breakFlag = True
400
                                    break
401
                                elif subOrder['closed']:
402
                                    breakFlag = True
403
                                    break
404
                                else: 
405
                                    findMap = {"orderId": order['orderId'], "subOrders.merchantSubOrderId": merchantSubOrderId}
14406 amit.gupta 406
                            elif "Status :" in line:
14398 amit.gupta 407
                                detailedStatus = re.findall('>(.*?)</span>', line, re.IGNORECASE)[0]
408
                                updateMap["subOrders.$.detailedStatus"] = detailedStatus
409
                                status = self._getStatusFromDetailedStatus(detailedStatus) 
410
                                closedStatus = status in [Store.ORDER_DELIVERED, Store.ORDER_CANCELLED]
411
                                updateMap["subOrders.$.status"] = status
412
                                if detailedStatus == 'Closed For Vendor Reallocation':
413
                                    #if it is more than 6hours mark closed.
414
                                    closeAt = subOrder.get("closeAt") 
415
                                    if closeAt is None:
416
                                        closeAt = datetime.now() + timedelta(hours=6)
417
                                        updateMap["subOrders.$.closeAt"] = datetime.strftime(closeAt,"%Y-%m-%d %H:%M:%S")
418
                                    else:
419
                                        closeAt = datetime.strptime(closeAt,"%Y-%m-%d %H:%M:%S")
420
                                        if datetime.now() > closeAt:
421
                                            closedStatus = True
422
 
423
 
424
                                if closedStatus:
425
                                    #if status is closed then change the paybackStatus accordingly
426
                                    updateMap["subOrders.$.closed"] = True
427
                                    if status == Store.ORDER_DELIVERED:
428
                                        if subOrder.get("cashBackStatus") == Store.CB_PENDING:
429
                                            updateMap["subOrders.$.cashBackStatus"] = Store.CB_APPROVED
430
                                    elif status == Store.ORDER_CANCELLED:
431
                                        if subOrder.get("cashBackStatus") == Store.CB_PENDING:
432
                                            updateMap["subOrders.$.cashBackStatus"] = Store.CB_CANCELLED
433
 
13760 amit.gupta 434
                                else:
14398 amit.gupta 435
                                    closed = False
436
                            elif "Est. Shipping Date" in line:
437
                                estimatedShippingDate = line.split(":")[1].strip()
438
                                updateMap["subOrders.$.estimatedShippingDate"] = estimatedShippingDate
439
                            elif "Est. Delivery Date" in line:
440
                                estimatedDeliveryDate = line.split(":")[1].strip()
441
                                updateMap["subOrders.$.estimatedDeliveryDate"] = estimatedDeliveryDate
442
                            elif "Courier Name" in line:
443
                                courierName = line.split(":")[1].strip()
444
                                updateMap["subOrders.$.courierName"] = courierName
445
                            elif "Tracking No" in line:
446
                                trackingNumber = line.split(":")[1].strip()
447
                                updateMap["subOrders.$.trackingNumber"] = trackingNumber
448
 
449
                        if breakFlag:
14653 amit.gupta 450
                            continue
14398 amit.gupta 451
 
452
                        bulk.find(findMap).update({'$set' : updateMap})
14696 amit.gupta 453
                    bulk.find({'orderId': order['orderId']}).update({'$set':{'closed': closed,"parseError":False}})
14398 amit.gupta 454
                result = bulk.execute()
14625 amit.gupta 455
                tprint(result)
14398 amit.gupta 456
            except:
14847 amit.gupta 457
                tprint("Could not update " + str(order['orderId']) + "For store " + self.getName())
14692 amit.gupta 458
                self.db.merchantOrder.update({"orderId":order['orderId']}, {"$set":{"parseError":True}})
14398 amit.gupta 459
                traceback.print_exc()                
13576 amit.gupta 460
 
14854 amit.gupta 461
    def tryBParsing(self, order, soup):
462
        orderDetailContainerDivs = soup.body.find("div", {'class':'cardLayoutWrap'}).findAll('div', recursive=False)
463
        orderDetailDiv = orderDetailContainerDivs.pop(0)
464
        placedOn = orderDetailDiv.span.text.split(':')[1].strip()
465
 
466
        orderDetailContainerDivs.pop(0)
467
 
468
        subOrders = orderDetailContainerDivs
469
        bulk = self.db.merchantOrder.initialize_ordered_bulk_op()
470
        closed = True
471
        for subOrderElement in subOrders:
472
            prodDivs = subOrderElement.findAll('div', recursive=False)
473
            merchantSubOrderId = prodDivs[0].text.split(':')[1].strip()
474
            prodDetailDiv = prodDivs[1].findAll('div', recursive=False)
475
            imgDiv = prodDetailDiv[0]
476
            otherDiv = prodDetailDiv[1]
477
 
478
            subOrder = None
479
            breakFlag = False
480
 
481
            div = None
482
            divStr = str(div)
483
            divStr = divStr.replace("\n","").replace("\t", "")
484
            updateMap = {}
485
            for line in divStr.split("<br />"):
486
                if "Suborder ID" in line:
487
                    merchantSubOrderId = re.findall(r'\d+', line)[0]
488
                    #break if suborder is inactive   
489
                    subOrder =  self._isSubOrderActive(order, merchantSubOrderId)
490
                    if subOrder is None:
491
                        subOrders = self.parseSubOrder(subOrderElement, placedOn)
492
                        self.db.merchantOrder.update({"orderId":order['orderId']},{'$push':{"subOrders":{"$each":todict(subOrders)}}})
493
                        print "Added new suborders to Order id - " + order['orderId']
494
                        closed = False
495
                        breakFlag = True
496
                        break
497
                    elif subOrder['closed']:
498
                        breakFlag = True
499
                        break
500
                    else: 
501
                        findMap = {"orderId": order['orderId'], "subOrders.merchantSubOrderId": merchantSubOrderId}
502
                elif "Status :" in line:
503
                    detailedStatus = re.findall('>(.*?)</span>', line, re.IGNORECASE)[0]
504
                    updateMap["subOrders.$.detailedStatus"] = detailedStatus
505
                    status = self._getStatusFromDetailedStatus(detailedStatus) 
506
                    closedStatus = status in [Store.ORDER_DELIVERED, Store.ORDER_CANCELLED]
507
                    updateMap["subOrders.$.status"] = status
508
                    if detailedStatus == 'Closed For Vendor Reallocation':
509
                        #if it is more than 6hours mark closed.
510
                        closeAt = subOrder.get("closeAt") 
511
                        if closeAt is None:
512
                            closeAt = datetime.now() + timedelta(hours=6)
513
                            updateMap["subOrders.$.closeAt"] = datetime.strftime(closeAt,"%Y-%m-%d %H:%M:%S")
514
                        else:
515
                            closeAt = datetime.strptime(closeAt,"%Y-%m-%d %H:%M:%S")
516
                            if datetime.now() > closeAt:
517
                                closedStatus = True
518
 
519
 
520
                    if closedStatus:
521
                        #if status is closed then change the paybackStatus accordingly
522
                        updateMap["subOrders.$.closed"] = True
523
                        if status == Store.ORDER_DELIVERED:
524
                            if subOrder.get("cashBackStatus") == Store.CB_PENDING:
525
                                updateMap["subOrders.$.cashBackStatus"] = Store.CB_APPROVED
526
                        elif status == Store.ORDER_CANCELLED:
527
                            if subOrder.get("cashBackStatus") == Store.CB_PENDING:
528
                                updateMap["subOrders.$.cashBackStatus"] = Store.CB_CANCELLED
529
 
530
                    else:
531
                        closed = False
532
                elif "Est. Shipping Date" in line:
533
                    estimatedShippingDate = line.split(":")[1].strip()
534
                    updateMap["subOrders.$.estimatedShippingDate"] = estimatedShippingDate
535
                elif "Est. Delivery Date" in line:
536
                    estimatedDeliveryDate = line.split(":")[1].strip()
537
                    updateMap["subOrders.$.estimatedDeliveryDate"] = estimatedDeliveryDate
538
                elif "Courier Name" in line:
539
                    courierName = line.split(":")[1].strip()
540
                    updateMap["subOrders.$.courierName"] = courierName
541
                elif "Tracking No" in line:
542
                    trackingNumber = line.split(":")[1].strip()
543
                    updateMap["subOrders.$.trackingNumber"] = trackingNumber
544
 
545
            if breakFlag:
546
                continue
547
 
548
            bulk.find(findMap).update({'$set' : updateMap})
549
        bulk.find({'orderId': order['orderId']}).update({'$set':{'closed': closed,"parseError":False}})
550
        result = bulk.execute()
551
        tprint(result)
552
 
13576 amit.gupta 553
 
13569 amit.gupta 554
    def _saveToAffiliate(self, offers):
13576 amit.gupta 555
        collection = self.db.snapdealOrderAffiliateInfo
14443 amit.gupta 556
        mcollection = self.db.merchantOrder
557
        for offer in offers:
558
            offer = self.covertToObj(offer)
559
            collection.update({"adId":offer.adId, "saleAmount":offer.saleAmount, "payOut":offer.payOut},{"$set":todict(offer)}, upsert=True)
14446 amit.gupta 560
            mcollection.update({"subTagId":offer.subTagId, "storeId":self.store_id, "subOrders.missingAff":True}, {"$set":{"subOrders.$.missingAff":False}})
13569 amit.gupta 561
 
562
 
563
    def _getAllOffers(self, br, token):
564
        allOffers = []
565
        nextPage = 1  
566
        while True:
567
            data = getPostData(token, nextPage)
568
            response = br.open(POST_URL, data)
13680 amit.gupta 569
            rmap = json.loads(ungzipResponse(response))
13569 amit.gupta 570
            if rmap is not None:
571
                rmap = rmap['response']
14492 amit.gupta 572
                print rmap
13569 amit.gupta 573
                if rmap is not None and len(rmap['errors'])==0:
574
                    allOffers += rmap['data']['data']
575
            nextPage += 1
576
            if rmap['data']['pageCount']<nextPage:
577
                break
578
 
579
        return allOffers
580
 
581
    def covertToObj(self,offer):
582
        offerData = offer['Stat']
583
        offer1 = AffiliateInfo(offerData['affiliate_info1'], self.store_id, offerData['conversion_status'], offerData['ad_id'], 
14576 amit.gupta 584
                              offerData['datetime'], int(float(offerData['payout'])), offer['Offer']['name'], offerData['ip'], int(float(offerData['conversion_sale_amount'])))
14443 amit.gupta 585
        offer1.saleTime = int(time.mktime(datetime.strptime(offer1.saleDate, "%Y-%m-%d %H:%M:%S").timetuple()))
13569 amit.gupta 586
        return offer1
587
def getPostData(token, page = 1, limit= 20, startDate=None, endDate=None):
13680 amit.gupta 588
    endDate=date.today() + timedelta(days=1)
589
    startDate=endDate - timedelta(days=31)
13569 amit.gupta 590
 
591
    parameters = (
592
        ("page",str(page)),
593
        ("limit",str(limit)),
594
        ("fields[]","Stat.offer_id"),
595
        ("fields[]","Stat.datetime"),
596
        ("fields[]","Offer.name"),
597
        ("fields[]","Stat.conversion_status"),
598
        ("fields[]","Stat.conversion_sale_amount"),
599
        ("fields[]","Stat.payout"),
600
        ("fields[]","Stat.ip"),
601
        ("fields[]","Stat.ad_id"),
602
        ("fields[]","Stat.affiliate_info1"),
603
        ("sort[Stat.datetime]","desc"),
604
        ("filters[Stat.date][conditional]","BETWEEN"),
605
        ("filters[Stat.date][values][]",startDate.strftime('%Y-%m-%d')),
606
        ("filters[Stat.date][values][]",endDate.strftime('%Y-%m-%d')),
607
        ("data_start",startDate.strftime('%Y-%m-%d')),
608
        ("data_end",endDate.strftime('%Y-%m-%d')),
609
        ("Method","getConversions"),
610
        ("NetworkId","jasper"),
611
        ("SessionToken",token),
612
    )
613
    #Encode the parameters
614
    return urllib.urlencode(parameters)
615
 
616
def main():
14458 amit.gupta 617
    #print todict([1,2,"3"])
14402 amit.gupta 618
    store = getStore(3)
14854 amit.gupta 619
    store.parseOrderRawHtml(33222, "32323", 2, "323243", "https://m.snapdeal.com/purchaseMobileComplete?code=561009a4a0c043e2f537f558c8531580&order=5822820967")
14443 amit.gupta 620
    #store.scrapeStoreOrders()
13662 amit.gupta 621
    #store._isSubOrderActive(8, "5970688907")
14653 amit.gupta 622
    #store.scrapeAffiliate()
14758 amit.gupta 623
    #store.scrapeStoreOrders()
13569 amit.gupta 624
 
625
 
14459 amit.gupta 626
 
13576 amit.gupta 627
def todict(obj, classkey=None):
628
    if isinstance(obj, dict):
629
        data = {}
630
        for (k, v) in obj.items():
631
            data[k] = todict(v, classkey)
632
        return data
633
    elif hasattr(obj, "_ast"):
634
        return todict(obj._ast())
635
    elif hasattr(obj, "__iter__"):
636
        return [todict(v, classkey) for v in obj]
637
    elif hasattr(obj, "__dict__"):
638
        data = dict([(key, todict(value, classkey)) 
639
            for key, value in obj.__dict__.iteritems() 
640
            if not callable(value) and not key.startswith('_')])
641
        if classkey is not None and hasattr(obj, "__class__"):
642
            data[classkey] = obj.__class__.__name__
643
        return data
644
    else:
645
        return obj
14239 amit.gupta 646
 
647
if __name__ == '__main__':
648
    main()