Subversion Repositories SmartDukaan

Rev

Rev 14864 | Rev 14883 | 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 = {
14861 amit.gupta 41
                      MStore.ORDER_PLACED : ['in progress', 'pending for verification', 'not available', 'in process', 'processing', 'processed'],
14678 amit.gupta 42
                      MStore.ORDER_DELIVERED : ['delivered'],
14861 amit.gupta 43
                      MStore.ORDER_SHIPPED : ['in transit', 'dispatched'],
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])
14861 amit.gupta 179
            elif "SD Cash" in subTrString:
14473 amit.gupta 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])
14872 amit.gupta 260
            elif "Offer Discount" in strPaymentDiv:
261
                offerDiscount += int(re.findall(r'\d+', strPaymentDiv)[0])
262
            elif "Discount" in strPaymentDiv:
263
                offerDiscount += int(re.findall(r'\d+', strPaymentDiv)[0])
14861 amit.gupta 264
            elif "SD Cash" in strPaymentDiv:
14854 amit.gupta 265
                sdCash =   int(re.findall(r'\d+', strPaymentDiv)[0])
266
            elif "Delivery Charges" in strPaymentDiv:
267
                deliveryCharges =   int(re.findall(r'\d+', strPaymentDiv)[0])
268
            elif "Subtotal" in strPaymentDiv:
269
                amountPaid =   int(re.findall(r'\d+', paymentDiv.find('div', {'class':'itemPriceDetail'}).text)[0])
270
 
271
        amount = unitPrice - offerDiscount - sdCash
272
 
273
        imgDiv = prodDetailDiv[0]
274
        otherDiv = prodDetailDiv[1]
275
        productTitle = otherDiv.find('div',{'class':'orderName'}).text.strip()
276
 
277
        productUrl = imgDiv.a['href']
278
        subOrder = SubOrder(productTitle, productUrl, placedOn, amountPaid)
14863 amit.gupta 279
        subOrder.merchantSubOrderId = prodDivs[0].text.split(':')[1].strip()
14854 amit.gupta 280
        subOrder.detailedStatus = otherDiv.find('div',{'class':'orderStatus'}).span.text.strip()
281
        deliveryStatus = otherDiv.find('div',{'class':'orderDelivery'})
282
        if deliveryStatus is not None:
283
            delString = deliveryStatus.text.strip()
284
            arr = delString.split(':')
285
            if "On" in arr[0]:
286
                subOrder.deliveredOn = arr[1].strip()
287
            elif "Exp. Delivery by" in arr[0]:
288
                subOrder.estimatedDeliveryDate = arr[1].strip()
289
            else:
290
                subOrder.estimatedShippingDate = arr[1].strip()
291
 
292
        subOrder.imgUrl = imgDiv.a.img['src']
293
        subOrder.productCode = re.findall(r'\d+$', productUrl)[0]
294
        subOrder.deliveryCharges = deliveryCharges
295
        subOrder.offerDiscount = offerDiscount
296
        subOrder.unitPrice = int(unitPrice)
297
        cashbackStatus = Store.CB_NA
298
        cashbackAmount = 0
299
        percentage = 0
300
        if amountPaid > 0:
301
            (cashbackAmount, percentage) = self.getCashbackAmount(subOrder.productCode, amount)
302
            if cashbackAmount > 0:
303
                cashbackStatus = Store.CB_PENDING
304
        subOrder.cashBackStatus = cashbackStatus
305
        subOrder.cashBackAmount = cashbackAmount
306
        subOrder.cashBackPercentage = percentage
307
 
308
 
309
        courierDet = subOrderElement.find('div', {'class':'courierDetail'})
310
        if courierDet is not None:
311
            subOrder.courierName = courierDet.span.text.strip()
312
        trackingDet = subOrderElement.find('div', {'class':'trackingNo'})
313
        if trackingDet is not None:
314
            subOrder.trackingUrl = trackingDet.span.a['href']
315
            subOrder.trackingNumber = trackingDet.span.a.text.strip()
316
 
317
        subOrders.append(subOrder)
318
        return subOrder
319
 
13576 amit.gupta 320
    def parseOrderRawHtml(self, orderId, subTagId, userId, rawHtml, orderSuccessUrl):
13760 amit.gupta 321
                    #print merchantOrder
13796 amit.gupta 322
        resp = {}
13582 amit.gupta 323
        try:
324
            br = getBrowserObject()
325
            url = ORDER_TRACK_URL + re.findall('.*(\?.*?)$', orderSuccessUrl,re.IGNORECASE)[0]
13791 amit.gupta 326
            page = br.open(url)
327
            page = ungzipResponse(page)
14854 amit.gupta 328
            try:
329
                merchantOrder = self._parseB(orderId, subTagId, userId, page, orderSuccessUrl)
330
            except:
14861 amit.gupta 331
                traceback.print_exc()
14854 amit.gupta 332
                merchantOrder = self._parse(orderId, subTagId, userId, page, orderSuccessUrl)
333
 
14312 amit.gupta 334
            merchantOrder.orderTrackingUrl = url
335
 
336
            if self._saveToOrder(todict(merchantOrder)):
337
                resp['result'] = 'ORDER_CREATED'
338
            else:
339
                resp['result'] = 'ORDER_ALREADY_CREATED_IGNORED'
340
 
13796 amit.gupta 341
            return resp
13582 amit.gupta 342
        except:
343
            print "Error occurred"
13603 amit.gupta 344
            traceback.print_exc()
14312 amit.gupta 345
            resp['result'] = 'ORDER_NOT_CREATED'
13796 amit.gupta 346
            return resp
13781 amit.gupta 347
 
13569 amit.gupta 348
 
349
        #soup = BeautifulSoup(rawHtml,convertEntities=BeautifulSoup.HTML_ENTITIES)
350
        #soup.find(name, attrs, recursive, text)
13576 amit.gupta 351
 
352
    def _getStatusFromDetailedStatus(self, detailedStatus):
353
        for key, value in Store.OrderStatusMap.iteritems():
14678 amit.gupta 354
            if detailedStatus.lower() in value:
13576 amit.gupta 355
                return key
14675 amit.gupta 356
        print "Detailed Status need to be mapped", detailedStatus, self.store_id
14861 amit.gupta 357
        return None
13569 amit.gupta 358
 
13610 amit.gupta 359
 
13569 amit.gupta 360
    def scrapeStoreOrders(self,):
13760 amit.gupta 361
        #collectionMap = {'palcedOn':1}
13576 amit.gupta 362
        orders = self._getActiveOrders()
363
        for order in orders:
14696 amit.gupta 364
            print "Order", self.store_name, order['orderId']
14398 amit.gupta 365
            try:
366
                url = ORDER_TRACK_URL + re.findall('.*(\?.*?)$', order['orderSuccessUrl'],re.IGNORECASE)[0]
14758 amit.gupta 367
                page = fetchResponseUsingProxy(url)
14398 amit.gupta 368
                #page=page.decode("utf-8")
14861 amit.gupta 369
                soup = BeautifulSoup(page)
370
                try:
371
                    self.tryBParsing(order, soup)
372
                except:
373
                    traceback.print_exc()
374
                    sections = soup.findAll("section")
375
                    orderEl = sections[1]
376
                    orderTrs = orderEl.findAll("tr")
377
 
378
                    placedOn = str(orderTrs[0].findAll("td")[1].text)
379
                    sections.pop(0)
380
                    sections.pop(0)
381
 
382
                    subOrders = sections
383
                    bulk = self.db.merchantOrder.initialize_ordered_bulk_op()
384
                    closed = True
385
                    for subOrderElement in subOrders:
386
                        div1 = subOrderElement.findAll("div", {"class": "blk lrPad subordrs"})
387
                        if len(div1)<=0:
388
                            raise ParseException("subOrder", "Could not Parse suborders for Snapdeal")
389
                        subOrder = None
390
                        breakFlag = False
391
                        for strDiv in str(div1).split("<div class=\"seperator\"></div>"):
392
                            div = BeautifulSoup(strDiv)
393
                            divStr = str(div)
394
                            divStr = divStr.replace("\n","").replace("\t", "")
395
                            updateMap = {}
396
                            for line in divStr.split("<br />"):
397
                                if "Suborder ID" in line:
398
                                    merchantSubOrderId = re.findall(r'\d+', line)[0]
399
                                    #break if suborder is inactive   
400
                                    subOrder =  self._isSubOrderActive(order, merchantSubOrderId)
401
                                    if subOrder is None:
402
                                        subOrders = self.parseSubOrder(subOrderElement, placedOn)
403
                                        self.db.merchantOrder.update({"orderId":order['orderId']},{'$push':{"subOrders":{"$each":todict(subOrders)}}})
404
                                        print "Added new suborders to Order id - ", order['orderId']
405
                                        closed = False
406
                                        breakFlag = True
407
                                        break
408
                                    elif subOrder['closed']:
409
                                        breakFlag = True
410
                                        break
411
                                    else: 
412
                                        findMap = {"orderId": order['orderId'], "subOrders.merchantSubOrderId": merchantSubOrderId}
413
                                elif "Status :" in line:
414
                                    detailedStatus = re.findall('>(.*?)</span>', line, re.IGNORECASE)[0]
415
                                    updateMap["subOrders.$.detailedStatus"] = detailedStatus
416
                                    status = self._getStatusFromDetailedStatus(detailedStatus) 
417
                                    closedStatus = status in [Store.ORDER_DELIVERED, Store.ORDER_CANCELLED]
418
                                    if status is not None:
419
                                        updateMap["subOrders.$.status"] = status
420
                                    if detailedStatus == 'Closed For Vendor Reallocation':
421
                                        #if it is more than 6hours mark closed.
422
                                        closeAt = subOrder.get("closeAt") 
423
                                        if closeAt is None:
424
                                            closeAt = datetime.now() + timedelta(hours=6)
425
                                            updateMap["subOrders.$.closeAt"] = datetime.strftime(closeAt,"%Y-%m-%d %H:%M:%S")
426
                                        else:
427
                                            closeAt = datetime.strptime(closeAt,"%Y-%m-%d %H:%M:%S")
428
                                            if datetime.now() > closeAt:
429
                                                closedStatus = True
430
 
431
 
432
                                    if closedStatus:
433
                                        #if status is closed then change the paybackStatus accordingly
434
                                        updateMap["subOrders.$.closed"] = True
435
                                        if status == Store.ORDER_DELIVERED:
436
                                            if subOrder.get("cashBackStatus") == Store.CB_PENDING:
437
                                                updateMap["subOrders.$.cashBackStatus"] = Store.CB_APPROVED
438
                                        elif status == Store.ORDER_CANCELLED:
439
                                            if subOrder.get("cashBackStatus") == Store.CB_PENDING:
440
                                                updateMap["subOrders.$.cashBackStatus"] = Store.CB_CANCELLED
441
 
14398 amit.gupta 442
                                    else:
14861 amit.gupta 443
                                        closed = False
444
                                elif "Est. Shipping Date" in line:
445
                                    estimatedShippingDate = line.split(":")[1].strip()
446
                                    updateMap["subOrders.$.estimatedShippingDate"] = estimatedShippingDate
447
                                elif "Est. Delivery Date" in line:
448
                                    estimatedDeliveryDate = line.split(":")[1].strip()
449
                                    updateMap["subOrders.$.estimatedDeliveryDate"] = estimatedDeliveryDate
450
                                elif "Courier Name" in line:
451
                                    courierName = line.split(":")[1].strip()
452
                                    updateMap["subOrders.$.courierName"] = courierName
453
                                elif "Tracking No" in line:
454
                                    trackingNumber = line.split(":")[1].strip()
455
                                    updateMap["subOrders.$.trackingNumber"] = trackingNumber
456
 
457
                            if breakFlag:
458
                                continue
459
 
460
                            bulk.find(findMap).update({'$set' : updateMap})
461
                        bulk.find({'orderId': order['orderId']}).update({'$set':{'closed': closed,"parseError":False}})
462
                    result = bulk.execute()
463
                    tprint(result)
14398 amit.gupta 464
            except:
14847 amit.gupta 465
                tprint("Could not update " + str(order['orderId']) + "For store " + self.getName())
14692 amit.gupta 466
                self.db.merchantOrder.update({"orderId":order['orderId']}, {"$set":{"parseError":True}})
14398 amit.gupta 467
                traceback.print_exc()                
13576 amit.gupta 468
 
14854 amit.gupta 469
    def tryBParsing(self, order, soup):
470
        orderDetailContainerDivs = soup.body.find("div", {'class':'cardLayoutWrap'}).findAll('div', recursive=False)
471
        orderDetailDiv = orderDetailContainerDivs.pop(0)
472
        placedOn = orderDetailDiv.span.text.split(':')[1].strip()
473
 
474
        orderDetailContainerDivs.pop(0)
475
 
476
        subOrders = orderDetailContainerDivs
477
        bulk = self.db.merchantOrder.initialize_ordered_bulk_op()
478
        closed = True
479
        for subOrderElement in subOrders:
480
            prodDivs = subOrderElement.findAll('div', recursive=False)
481
            merchantSubOrderId = prodDivs[0].text.split(':')[1].strip()
482
            subOrder = None
14861 amit.gupta 483
            subOrder =  self._isSubOrderActive(order, merchantSubOrderId)
484
            if subOrder is None:
14864 amit.gupta 485
                try:
486
                    subOrders = self.parseSubOrderB(subOrderElement, placedOn)
487
                    self.db.merchantOrder.update({"orderId":order['orderId']},{'$push':{"subOrders":{"$each":todict([subOrders])}}})
488
                    print "Added new suborders to Order id - ", order['orderId']
489
                    closed = False
490
                except:
491
                    pass
14861 amit.gupta 492
                continue
493
            elif subOrder['closed']:
494
                continue
495
            else: 
14864 amit.gupta 496
                prodDetailDiv = prodDivs[1].findAll('div', recursive=False)
497
                otherDiv = prodDetailDiv[1]
498
                trackBlock = subOrderElement.find('div',{'class':'trackingDetailsBlock'})
14861 amit.gupta 499
                findMap = {"orderId": order['orderId'], "subOrders.merchantSubOrderId": merchantSubOrderId}
500
                updateMap = {}
501
                detailedStatus = otherDiv.find('div',{'class':'orderStatus'}).span.text.strip()
502
                updateMap["subOrders.$.detailedStatus"] = detailedStatus
503
                status = self._getStatusFromDetailedStatus(detailedStatus) 
504
                closedStatus = status in [Store.ORDER_DELIVERED, Store.ORDER_CANCELLED]
505
                if status is not None:
14854 amit.gupta 506
                    updateMap["subOrders.$.status"] = status
14864 amit.gupta 507
                if 'A New Order Placed With A Different Seller' in str(trackBlock):
14861 amit.gupta 508
                    #if it is more than 6hours mark closed.
509
                    closeAt = subOrder.get("closeAt") 
510
                    if closeAt is None:
511
                        closeAt = datetime.now() + timedelta(hours=6)
512
                        updateMap["subOrders.$.closeAt"] = datetime.strftime(closeAt,"%Y-%m-%d %H:%M:%S")
14854 amit.gupta 513
                    else:
14861 amit.gupta 514
                        closeAt = datetime.strptime(closeAt,"%Y-%m-%d %H:%M:%S")
515
                        if datetime.now() > closeAt:
516
                            closedStatus = True
14864 amit.gupta 517
                            updateMap["subOrders.$.status"] = Store.ORDER_CANCELLED
14861 amit.gupta 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
14854 amit.gupta 532
 
14861 amit.gupta 533
                deliveryStatus = otherDiv.find('div',{'class':'orderDelivery'})
534
                if deliveryStatus is not None:
535
                    delString = deliveryStatus.text.strip()
536
                    arr = delString.split(':')    
537
                    if "On" in arr[0]:
538
                        updateMap['subOrders.$.deliveredOn'] = arr[1].strip()
539
                    elif "Exp. Delivery by" in arr[0]:
540
                        updateMap['subOrders.$.estimatedDeliveryDate'] = arr[1].strip()
541
                    else:
542
                        updateMap['subOrders.$.estimatedShippingDate'] = arr[1].strip()
543
                courierDet = subOrderElement.find('div', {'class':'courierDetail'})
544
                if courierDet is not None:
545
                    updateMap['subOrders.$.courierName'] = courierDet.span.text.strip()
546
                trackingDet = subOrderElement.find('div', {'class':'trackingNo'})
547
                if trackingDet is not None:
548
                    updateMap['subOrders.$.trackingUrl'] = trackingDet.span.a['href']
549
                    updateMap['subOrders.$.trackingNumber'] = trackingDet.span.a.text.strip()                    
14854 amit.gupta 550
            bulk.find(findMap).update({'$set' : updateMap})
551
        bulk.find({'orderId': order['orderId']}).update({'$set':{'closed': closed,"parseError":False}})
552
        result = bulk.execute()
553
        tprint(result)
554
 
13576 amit.gupta 555
 
13569 amit.gupta 556
    def _saveToAffiliate(self, offers):
13576 amit.gupta 557
        collection = self.db.snapdealOrderAffiliateInfo
14443 amit.gupta 558
        mcollection = self.db.merchantOrder
559
        for offer in offers:
560
            offer = self.covertToObj(offer)
561
            collection.update({"adId":offer.adId, "saleAmount":offer.saleAmount, "payOut":offer.payOut},{"$set":todict(offer)}, upsert=True)
14446 amit.gupta 562
            mcollection.update({"subTagId":offer.subTagId, "storeId":self.store_id, "subOrders.missingAff":True}, {"$set":{"subOrders.$.missingAff":False}})
13569 amit.gupta 563
 
564
 
565
    def _getAllOffers(self, br, token):
566
        allOffers = []
567
        nextPage = 1  
568
        while True:
569
            data = getPostData(token, nextPage)
570
            response = br.open(POST_URL, data)
13680 amit.gupta 571
            rmap = json.loads(ungzipResponse(response))
13569 amit.gupta 572
            if rmap is not None:
573
                rmap = rmap['response']
14492 amit.gupta 574
                print rmap
13569 amit.gupta 575
                if rmap is not None and len(rmap['errors'])==0:
576
                    allOffers += rmap['data']['data']
577
            nextPage += 1
578
            if rmap['data']['pageCount']<nextPage:
579
                break
580
 
581
        return allOffers
582
 
583
    def covertToObj(self,offer):
584
        offerData = offer['Stat']
585
        offer1 = AffiliateInfo(offerData['affiliate_info1'], self.store_id, offerData['conversion_status'], offerData['ad_id'], 
14576 amit.gupta 586
                              offerData['datetime'], int(float(offerData['payout'])), offer['Offer']['name'], offerData['ip'], int(float(offerData['conversion_sale_amount'])))
14443 amit.gupta 587
        offer1.saleTime = int(time.mktime(datetime.strptime(offer1.saleDate, "%Y-%m-%d %H:%M:%S").timetuple()))
13569 amit.gupta 588
        return offer1
589
def getPostData(token, page = 1, limit= 20, startDate=None, endDate=None):
13680 amit.gupta 590
    endDate=date.today() + timedelta(days=1)
591
    startDate=endDate - timedelta(days=31)
13569 amit.gupta 592
 
593
    parameters = (
594
        ("page",str(page)),
595
        ("limit",str(limit)),
596
        ("fields[]","Stat.offer_id"),
597
        ("fields[]","Stat.datetime"),
598
        ("fields[]","Offer.name"),
599
        ("fields[]","Stat.conversion_status"),
600
        ("fields[]","Stat.conversion_sale_amount"),
601
        ("fields[]","Stat.payout"),
602
        ("fields[]","Stat.ip"),
603
        ("fields[]","Stat.ad_id"),
604
        ("fields[]","Stat.affiliate_info1"),
605
        ("sort[Stat.datetime]","desc"),
606
        ("filters[Stat.date][conditional]","BETWEEN"),
607
        ("filters[Stat.date][values][]",startDate.strftime('%Y-%m-%d')),
608
        ("filters[Stat.date][values][]",endDate.strftime('%Y-%m-%d')),
609
        ("data_start",startDate.strftime('%Y-%m-%d')),
610
        ("data_end",endDate.strftime('%Y-%m-%d')),
611
        ("Method","getConversions"),
612
        ("NetworkId","jasper"),
613
        ("SessionToken",token),
614
    )
615
    #Encode the parameters
616
    return urllib.urlencode(parameters)
617
 
618
def main():
14458 amit.gupta 619
    #print todict([1,2,"3"])
14402 amit.gupta 620
    store = getStore(3)
14861 amit.gupta 621
    #store.parseOrderRawHtml(33222, "32323", 2, "323243", "https://m.snapdeal.com/purchaseMobileComplete?code=1131a4add85aefb40a924d71cbf921bd&order=5822561503")
622
    store.scrapeStoreOrders()
13662 amit.gupta 623
    #store._isSubOrderActive(8, "5970688907")
14653 amit.gupta 624
    #store.scrapeAffiliate()
14758 amit.gupta 625
    #store.scrapeStoreOrders()
13569 amit.gupta 626
 
627
 
14459 amit.gupta 628
 
13576 amit.gupta 629
def todict(obj, classkey=None):
630
    if isinstance(obj, dict):
631
        data = {}
632
        for (k, v) in obj.items():
633
            data[k] = todict(v, classkey)
634
        return data
635
    elif hasattr(obj, "_ast"):
636
        return todict(obj._ast())
637
    elif hasattr(obj, "__iter__"):
638
        return [todict(v, classkey) for v in obj]
639
    elif hasattr(obj, "__dict__"):
640
        data = dict([(key, todict(value, classkey)) 
641
            for key, value in obj.__dict__.iteritems() 
642
            if not callable(value) and not key.startswith('_')])
643
        if classkey is not None and hasattr(obj, "__class__"):
644
            data[classkey] = obj.__class__.__name__
645
        return data
646
    else:
647
        return obj
14239 amit.gupta 648
 
649
if __name__ == '__main__':
650
    main()