Subversion Repositories SmartDukaan

Rev

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