Subversion Repositories SmartDukaan

Rev

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