Subversion Repositories SmartDukaan

Rev

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