Subversion Repositories SmartDukaan

Rev

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