Subversion Repositories SmartDukaan

Rev

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