Subversion Repositories SmartDukaan

Rev

Rev 16968 | Rev 16975 | 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
16946 amit.gupta 15
from dtr.utils import utils
14758 amit.gupta 16
from dtr.utils.utils import fetchResponseUsingProxy
13662 amit.gupta 17
from pprint import pprint
13569 amit.gupta 18
from pymongo import MongoClient
15350 amit.gupta 19
from urlparse import urlparse, parse_qs
16946 amit.gupta 20
from xlrd import open_workbook
13569 amit.gupta 21
import json
16946 amit.gupta 22
import os.path
13569 amit.gupta 23
import pymongo
24
import re
14443 amit.gupta 25
import time
13662 amit.gupta 26
import traceback
13569 amit.gupta 27
import urllib
16946 amit.gupta 28
import csv
13603 amit.gupta 29
 
13721 amit.gupta 30
USERNAME='profittill2@gmail.com'
13569 amit.gupta 31
PASSWORD='spice@2020'
16946 amit.gupta 32
AFFILIATE_URL='http://affiliate.snapdeal.com/login/'
13569 amit.gupta 33
POST_URL='https://api-p03.hasoffers.com/v3/Affiliate_Report.json'
34
ORDER_TRACK_URL='https://m.snapdeal.com/orderSummary'
35
CONFIG_URL='http://affiliate.snapdeal.com/publisher/js/config.php'
36
 
16946 amit.gupta 37
NEW_REPORT_URI_TEMPLATE = "http://affiliate.snapdeal.com/affiliate/reports/orders/report/?fromDate=%s&toDate=%s&dump_report=True&request_type=product&status=%s"
38
#"http://affiliate.snapdeal.com/affiliate/reports/orders/report/?fromDate=2015-04-01&toDate=2015-09-15&dump_report=True&request_type=product&status=cancelled
39
#"http://affiliate.snapdeal.com/affiliate/reports/orders/report/?fromDate=07-09-2015&toDate=13-09-2015&dump_report=True&request_type=product&status=cancelled
40
 
13662 amit.gupta 41
class Store(MStore):
13569 amit.gupta 42
 
43
    '''
44
    This is to map order statuses of our system to order statuses of snapdeal.
45
    And our statuses will change accordingly.
46
 
47
    '''
48
    OrderStatusMap = {
16968 amit.gupta 49
                      MStore.ORDER_PLACED : ['in progress', 'pending for verification', 'not available', 'in process', 'processing', 'processed', 'under verification'],
14678 amit.gupta 50
                      MStore.ORDER_DELIVERED : ['delivered'],
14861 amit.gupta 51
                      MStore.ORDER_SHIPPED : ['in transit', 'dispatched'],
16968 amit.gupta 52
                      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', 'closed']
13569 amit.gupta 53
                      }
13662 amit.gupta 54
 
55
    CONF_CB_AMOUNT = MStore.CONF_CB_DISCOUNTED_PRICE
13569 amit.gupta 56
    def __init__(self,store_id):
57
        super(Store, self).__init__(store_id)
58
 
59
    def getName(self):
60
        return "snapdeal"
61
 
62
    def scrapeAffiliate(self, startDate=None, endDate=None):
63
        br = getBrowserObject()
64
        br.open(AFFILIATE_URL)
65
        br.select_form(nr=0)
16946 amit.gupta 66
        #br.form['data[User][password]'] = PASSWORD 
67
        #br.form['data[User][email]'] = USERNAME
68
        br.form['email'] =  USERNAME
69
        br.form['password'] = PASSWORD
13569 amit.gupta 70
        br.submit()
71
 
16946 amit.gupta 72
        #after logged in successfully
73
 
74
        #response = br.open(CONFIG_URL)
75
        #find token to fetch api
76
        #token =  re.findall('"session_token":"(.*?)"', ungzipResponse(response), re.IGNORECASE)[0]
77
        #print token
78
        #allOffers = self._getAllOffers(br, token)
79
 
80
        #fetch api using new report uri
81
        endDate=date.today() + timedelta(days=1)
82
        if startDate is None:
83
            startDate=endDate - timedelta(days=31)
84
 
85
        endDate = endDate.strftime('%d-%m-%Y')
86
        startDate = startDate.strftime('%d-%m-%Y')
87
        statuses=['cancelled', 'approved']
88
        directory = "/SnapAff/"
89
        curDate = directory + datetime.now().strftime('%Y-%m-%d')
90
        if not os.path.exists(directory):
91
            os.makedirs(directory)
92
        for status in statuses:
93
            reportUrl = NEW_REPORT_URI_TEMPLATE%(startDate, endDate, status)
94
            print reportUrl
95
            filename=curDate + "-" + status
96
            fileobj = open(filename,"wb")
97
            fileobj.write(utils.ungzipResponse(br.open(reportUrl)))
98
            fileobj.close()
99
            with open(filename, 'rb') as csvfile:
100
                reader = csv.reader(csvfile)
101
                self._saveToAffiliate(reader)
13569 amit.gupta 102
 
13662 amit.gupta 103
    def _setLastSaleDate(self, saleDate):
13680 amit.gupta 104
        self.db.lastSaleDtate.update({'storeId':self.store_id}, {'$set':{'saleDate':saleDate}})
13569 amit.gupta 105
 
13662 amit.gupta 106
 
107
 
108
    def _getLastSaleDate(self,):
109
        lastDaySaleObj = self.db.lastDaySale.find_one({"storeId":self.store_id})
110
        if lastDaySaleObj is None:
111
            return datetime.min
112
 
14854 amit.gupta 113
 
114
 
115
    def _parseB(self, orderId, subTagId, userId, page, orderSuccessUrl):
116
        soup = BeautifulSoup(page)
117
 
118
        orderDetailContainerDivs = soup.body.find("div", {'class':'cardLayoutWrap'}).findAll('div', recursive=False)
119
        orderDetailDiv = orderDetailContainerDivs.pop(0)
120
        paymentDetailDiv  = orderDetailContainerDivs.pop(0)
121
        subOrders = orderDetailContainerDivs
122
 
123
        placedOn = orderDetailDiv.span.text.split(':')[1].strip()
124
        merchantOrder = Order(orderId, userId, subTagId, self.store_id, orderSuccessUrl)
125
        merchantOrder.placedOn = placedOn
126
        merchantOrder.merchantOrderId = parse_qs(urlparse(orderSuccessUrl).query)['order'][0]
127
 
128
        paymentDivs = paymentDetailDiv.findAll('div', recursive=False)
129
        paymentDivs.pop(0)
130
        for orderTr in paymentDivs:
131
            orderTrString = str(orderTr)
132
            if "Total Amount Paid" in orderTrString:
133
                amountPaid = orderTr.div.find('div', {'class':'detailBlock'}).text.strip()
134
                merchantOrder.paidAmount = int(re.findall(r'\d+', amountPaid)[0])
135
            elif "Total Amount" in orderTrString:
136
                merchantOrder.totalAmount = re.findall(r'\d+', orderTrString)[0]
137
            elif "Delivery Charges" in orderTrString:
138
                merchantOrder.deliveryCharges = re.findall(r'\d+', orderTrString)[0]
139
            elif "Discount Applied" in orderTrString:
140
                merchantOrder.discountApplied = re.findall(r'\d+', orderTrString)[0]
141
            elif "Offer Discount" in orderTrString:
142
                merchantOrder.discountApplied = re.findall(r'\d+', orderTrString)[0]
143
 
144
        merchantSubOrders = []
145
        for subOrderElement in subOrders:
14883 amit.gupta 146
            subOrder = self.parseSubOrderB(subOrderElement, placedOn)
147
            if subOrder is not None:
15350 amit.gupta 148
                dealRank = getDealRank(subOrder.productCode, self.store_id, merchantOrder.userId)
149
                subOrder.dealRank = dealRank.get('rank')
150
                subOrder.rankDesc = dealRank.get('description')
16283 amit.gupta 151
                subOrder.maxNlc = dealRank.get('maxNlc')
152
                subOrder.minNlc = dealRank.get('minNlc')
153
                subOrder.db = dealRank.get('dp')
154
                subOrder.itemStatus = dealRank.get('status')
14883 amit.gupta 155
                merchantSubOrders.append(subOrder)
14854 amit.gupta 156
        merchantOrder.subOrders = merchantSubOrders
157
        return merchantOrder
158
 
13760 amit.gupta 159
    def _parse(self, orderId, subTagId, userId, page, orderSuccessUrl):
13662 amit.gupta 160
 
13760 amit.gupta 161
        #page=page.decode("utf-8")
14854 amit.gupta 162
        soup = BeautifulSoup(page)
13760 amit.gupta 163
        #orderHead = soup.find(name, attrs, recursive, text)
164
        sections = soup.findAll("section")
165
 
166
        #print sections
167
 
168
        order = sections[1]
169
        orderTrs = order.findAll("tr")
170
 
171
        placedOn = str(orderTrs[0].findAll("td")[1].text)
172
 
173
        #Pop two section elements
174
        sections.pop(0) 
175
        sections.pop(0)
176
        subOrders = sections
177
 
178
 
179
        merchantSubOrders = []
180
 
181
        merchantOrder = Order(orderId, userId, subTagId, self.store_id, orderSuccessUrl)
14447 amit.gupta 182
        merchantOrder.placedOn = placedOn
14023 amit.gupta 183
        merchantOrder.merchantOrderId = re.findall(r'\d+', str(soup.find("div", {"class":"deals_heading"})))[1]
13760 amit.gupta 184
        for orderTr in orderTrs:
185
            orderTrString = str(orderTr)
186
            if "Total Amount" in orderTrString:
187
                merchantOrder.totalAmount = re.findall(r'\d+', orderTrString)[0]
188
            elif "Delivery Charges" in orderTrString:
189
                merchantOrder.deliveryCharges = re.findall(r'\d+', orderTrString)[0]
190
            elif "Discount Applied" in orderTrString:
191
                merchantOrder.discountApplied = re.findall(r'\d+', orderTrString)[0]
192
            elif "Paid Amount" in orderTrString:
193
                merchantOrder.paidAmount = re.findall(r'\d+', orderTrString)[0]
194
 
195
        for subOrderElement in subOrders:
13809 amit.gupta 196
            subOrders = self.parseSubOrder(subOrderElement, placedOn)                           
197
            merchantSubOrders.extend(subOrders)   
13760 amit.gupta 198
 
199
        merchantOrder.subOrders = merchantSubOrders
200
        return merchantOrder
201
 
202
    def parseSubOrder(self, subOrderElement, placedOn):
13809 amit.gupta 203
        subOrders = []
13760 amit.gupta 204
        productUrl = str(subOrderElement.find("a")['href'])
205
        subTable = subOrderElement.find("table", {"class":"lrPad"})
206
        subTrs = subTable.findAll("tr")
207
        unitPrice=None
14458 amit.gupta 208
        offerDiscount = 0
13760 amit.gupta 209
        deliveryCharges = None
210
        amountPaid = None
14458 amit.gupta 211
        amount = 0
14473 amit.gupta 212
        sdCash = 0
213
        unitPrice = 0
13760 amit.gupta 214
        for subTr in subTrs:
215
            subTrString = str(subTr)
216
            if "Unit Price" in subTrString:
14473 amit.gupta 217
                unitPrice = int(re.findall(r'\d+', subTrString)[0])
13760 amit.gupta 218
            if "Quantity" in subTrString:
14458 amit.gupta 219
                qty = int(re.findall(r'\d+', subTrString)[0])
13760 amit.gupta 220
            elif "Offer Discount" in subTrString:
14458 amit.gupta 221
                offerDiscount +=   int(re.findall(r'\d+', subTrString)[0])
14861 amit.gupta 222
            elif "SD Cash" in subTrString:
14473 amit.gupta 223
                sdCash =   int(re.findall(r'\d+', subTrString)[0])
13760 amit.gupta 224
            elif "Delivery Charges" in subTrString:
14473 amit.gupta 225
                deliveryCharges =   int(re.findall(r'\d+', subTrString)[0])
13760 amit.gupta 226
            elif "Subtotal" in subTrString:
227
                if int(qty) > 0:
14459 amit.gupta 228
                    amountPaid =   int(re.findall(r'\d+', subTrString)[0])/qty
13760 amit.gupta 229
                else:
14459 amit.gupta 230
                    amountPaid =   0
14458 amit.gupta 231
        if qty>0:
14473 amit.gupta 232
            amount = unitPrice - offerDiscount - sdCash
233
            amount = 0 if amount < 0 else amount
13760 amit.gupta 234
 
14459 amit.gupta 235
        div1 = subOrderElement.find("div", {"class": "blk lrPad subordrs"})
236
        if div1 is None:
13760 amit.gupta 237
            raise ParseException("subOrder", "Could not Parse suborders for Snapdeal")
238
 
14459 amit.gupta 239
        for strDiv in str(div1).split("<div class=\"seperator\"></div>"):
240
            div = BeautifulSoup(strDiv)
13760 amit.gupta 241
            productTitle = str(subOrderElement.find("a").text)
242
            productUrl = "http://m.snapdeal.com/" + productUrl 
243
            subOrder = SubOrder(productTitle, productUrl, placedOn, amountPaid)
244
 
245
            subOrder.amountPaid = amountPaid
246
            subOrder.deliveryCharges = deliveryCharges
247
            subOrder.offerDiscount = offerDiscount
13809 amit.gupta 248
            subOrder.unitPrice = int(unitPrice)
13760 amit.gupta 249
            subOrder.productCode = re.findall(r'\d+$', productUrl)[0]
14415 amit.gupta 250
            subOrder.imgUrl = Mongo.getImgSrc(subOrder.productCode, self.store_id).get('thumbnail')
14458 amit.gupta 251
            cashbackStatus = Store.CB_NA
252
            cashbackAmount = 0
253
            percentage = 0
254
            if amount > 0:
255
                (cashbackAmount, percentage) = self.getCashbackAmount(subOrder.productCode, amount)
14473 amit.gupta 256
                if cashbackAmount > 0:
14476 amit.gupta 257
                    cashbackStatus = Store.CB_PENDING
13760 amit.gupta 258
            subOrder.cashBackStatus = cashbackStatus
259
            subOrder.cashBackAmount = cashbackAmount
14458 amit.gupta 260
            subOrder.cashBackPercentage = percentage
13760 amit.gupta 261
 
262
 
263
            trackAnchor = div.find("a")   
264
            if trackAnchor is not None:
265
                subOrder.tracingkUrl = str(trackAnchor['href'])
266
 
267
            divStr = str(div)
268
            divStr = divStr.replace("\n","").replace("\t", "")
269
 
270
            for line in divStr.split("<br />"):
271
                if "Suborder ID" in line:
272
                    subOrder.merchantSubOrderId = re.findall(r'\d+', line)[0]   
273
                elif "Status" in line:
14402 amit.gupta 274
                    print line
13760 amit.gupta 275
                    subOrder.detailedStatus = re.findall('>(.*?)</span>', line, re.IGNORECASE)[0]
276
                elif "Est. Shipping Date" in line:
277
                    subOrder.estimatedShippingDate = line.split(":")[1].strip()
278
                elif "Est. Delivery Date" in line:
279
                    subOrder.estimatedDeliveryDate = line.split(":")[1].strip()
280
                elif "Courier Name" in line:
281
                    subOrder.courierName = line.split(":")[1].strip()
282
                elif "Tracking No" in line:
283
                    subOrder.trackingNumber = line.split(":")[1].strip()
13809 amit.gupta 284
            subOrders.append(subOrder)
285
        return subOrders
13760 amit.gupta 286
 
14854 amit.gupta 287
    def parseSubOrderB(self, subOrderElement, placedOn):
288
        subOrders = []
289
        prodDivs = subOrderElement.findAll('div', recursive=False)
290
        prodDetailDiv = prodDivs[1].findAll('div', recursive=False)
291
 
292
        offerDiscount = 0
293
        deliveryCharges = None
294
        amountPaid = 0
295
        sdCash = 0
296
        unitPrice = 0
297
 
298
        paymentDivs = prodDivs[2].findAll('div', recursive=False)
299
        for paymentDiv in paymentDivs:
300
            strPaymentDiv = str(paymentDiv)
301
            if "Unit Price" in strPaymentDiv:
14883 amit.gupta 302
                try:
303
                    unitPrice = int(re.findall(r'\d+', strPaymentDiv)[0])
304
                except:
305
                    return None
14872 amit.gupta 306
            elif "Offer Discount" in strPaymentDiv:
307
                offerDiscount += int(re.findall(r'\d+', strPaymentDiv)[0])
308
            elif "Discount" in strPaymentDiv:
309
                offerDiscount += int(re.findall(r'\d+', strPaymentDiv)[0])
14861 amit.gupta 310
            elif "SD Cash" in strPaymentDiv:
14854 amit.gupta 311
                sdCash =   int(re.findall(r'\d+', strPaymentDiv)[0])
312
            elif "Delivery Charges" in strPaymentDiv:
313
                deliveryCharges =   int(re.findall(r'\d+', strPaymentDiv)[0])
314
            elif "Subtotal" in strPaymentDiv:
315
                amountPaid =   int(re.findall(r'\d+', paymentDiv.find('div', {'class':'itemPriceDetail'}).text)[0])
316
 
317
        amount = unitPrice - offerDiscount - sdCash
318
 
319
        imgDiv = prodDetailDiv[0]
320
        otherDiv = prodDetailDiv[1]
321
        productTitle = otherDiv.find('div',{'class':'orderName'}).text.strip()
322
 
323
        productUrl = imgDiv.a['href']
324
        subOrder = SubOrder(productTitle, productUrl, placedOn, amountPaid)
14863 amit.gupta 325
        subOrder.merchantSubOrderId = prodDivs[0].text.split(':')[1].strip()
14854 amit.gupta 326
        subOrder.detailedStatus = otherDiv.find('div',{'class':'orderStatus'}).span.text.strip()
15882 amit.gupta 327
        if subOrder.detailedStatus.lower() == "processing":
328
            processingDetailedStatus = subOrderElement.find('div', {'class':'trackingMessage'}).text.strip()
329
            if processingDetailedStatus.lower() == 'a new order placed with a different seller':
330
                subOrder.detailedStatus = processingDetailedStatus
14854 amit.gupta 331
        deliveryStatus = otherDiv.find('div',{'class':'orderDelivery'})
332
        if deliveryStatus is not None:
333
            delString = deliveryStatus.text.strip()
334
            arr = delString.split(':')
335
            if "On" in arr[0]:
336
                subOrder.deliveredOn = arr[1].strip()
337
            elif "Exp. Delivery by" in arr[0]:
338
                subOrder.estimatedDeliveryDate = arr[1].strip()
15877 amit.gupta 339
            elif "Est. delivery between" in arr[0]:
15880 amit.gupta 340
                subOrder.estimatedDeliveryDate = arr[0].split("between")[1].strip()
15881 amit.gupta 341
            elif "Est. shipping between" in arr[0]:
342
                subOrder.estimatedShippingDate = arr[0].split("between")[1].strip()
14854 amit.gupta 343
            else:
344
                subOrder.estimatedShippingDate = arr[1].strip()
345
 
346
        subOrder.imgUrl = imgDiv.a.img['src']
347
        subOrder.productCode = re.findall(r'\d+$', productUrl)[0]
348
        subOrder.deliveryCharges = deliveryCharges
349
        subOrder.offerDiscount = offerDiscount
350
        subOrder.unitPrice = int(unitPrice)
351
        cashbackStatus = Store.CB_NA
352
        cashbackAmount = 0
353
        percentage = 0
354
        if amountPaid > 0:
355
            (cashbackAmount, percentage) = self.getCashbackAmount(subOrder.productCode, amount)
356
            if cashbackAmount > 0:
357
                cashbackStatus = Store.CB_PENDING
358
        subOrder.cashBackStatus = cashbackStatus
359
        subOrder.cashBackAmount = cashbackAmount
360
        subOrder.cashBackPercentage = percentage
361
 
362
 
363
        courierDet = subOrderElement.find('div', {'class':'courierDetail'})
364
        if courierDet is not None:
365
            subOrder.courierName = courierDet.span.text.strip()
366
        trackingDet = subOrderElement.find('div', {'class':'trackingNo'})
367
        if trackingDet is not None:
368
            subOrder.trackingUrl = trackingDet.span.a['href']
369
            subOrder.trackingNumber = trackingDet.span.a.text.strip()
370
 
371
        subOrders.append(subOrder)
372
        return subOrder
373
 
13576 amit.gupta 374
    def parseOrderRawHtml(self, orderId, subTagId, userId, rawHtml, orderSuccessUrl):
13760 amit.gupta 375
                    #print merchantOrder
13796 amit.gupta 376
        resp = {}
13582 amit.gupta 377
        try:
378
            br = getBrowserObject()
379
            url = ORDER_TRACK_URL + re.findall('.*(\?.*?)$', orderSuccessUrl,re.IGNORECASE)[0]
13791 amit.gupta 380
            page = br.open(url)
381
            page = ungzipResponse(page)
14854 amit.gupta 382
            try:
383
                merchantOrder = self._parseB(orderId, subTagId, userId, page, orderSuccessUrl)
384
            except:
14861 amit.gupta 385
                traceback.print_exc()
14854 amit.gupta 386
                merchantOrder = self._parse(orderId, subTagId, userId, page, orderSuccessUrl)
387
 
14312 amit.gupta 388
            merchantOrder.orderTrackingUrl = url
389
 
390
            if self._saveToOrder(todict(merchantOrder)):
391
                resp['result'] = 'ORDER_CREATED'
392
            else:
393
                resp['result'] = 'ORDER_ALREADY_CREATED_IGNORED'
394
 
13796 amit.gupta 395
            return resp
13582 amit.gupta 396
        except:
397
            print "Error occurred"
13603 amit.gupta 398
            traceback.print_exc()
14312 amit.gupta 399
            resp['result'] = 'ORDER_NOT_CREATED'
13796 amit.gupta 400
            return resp
13781 amit.gupta 401
 
13569 amit.gupta 402
 
403
        #soup = BeautifulSoup(rawHtml,convertEntities=BeautifulSoup.HTML_ENTITIES)
404
        #soup.find(name, attrs, recursive, text)
13576 amit.gupta 405
 
406
    def _getStatusFromDetailedStatus(self, detailedStatus):
407
        for key, value in Store.OrderStatusMap.iteritems():
14678 amit.gupta 408
            if detailedStatus.lower() in value:
13576 amit.gupta 409
                return key
14675 amit.gupta 410
        print "Detailed Status need to be mapped", detailedStatus, self.store_id
14861 amit.gupta 411
        return None
13569 amit.gupta 412
 
13610 amit.gupta 413
 
13569 amit.gupta 414
    def scrapeStoreOrders(self,):
13760 amit.gupta 415
        #collectionMap = {'palcedOn':1}
13576 amit.gupta 416
        orders = self._getActiveOrders()
417
        for order in orders:
14696 amit.gupta 418
            print "Order", self.store_name, order['orderId']
14398 amit.gupta 419
            try:
420
                url = ORDER_TRACK_URL + re.findall('.*(\?.*?)$', order['orderSuccessUrl'],re.IGNORECASE)[0]
14758 amit.gupta 421
                page = fetchResponseUsingProxy(url)
14398 amit.gupta 422
                #page=page.decode("utf-8")
14861 amit.gupta 423
                soup = BeautifulSoup(page)
424
                try:
425
                    self.tryBParsing(order, soup)
426
                except:
427
                    traceback.print_exc()
428
                    sections = soup.findAll("section")
429
                    orderEl = sections[1]
430
                    orderTrs = orderEl.findAll("tr")
431
 
432
                    placedOn = str(orderTrs[0].findAll("td")[1].text)
433
                    sections.pop(0)
434
                    sections.pop(0)
435
 
436
                    subOrders = sections
437
                    bulk = self.db.merchantOrder.initialize_ordered_bulk_op()
438
                    closed = True
439
                    for subOrderElement in subOrders:
440
                        div1 = subOrderElement.findAll("div", {"class": "blk lrPad subordrs"})
441
                        if len(div1)<=0:
442
                            raise ParseException("subOrder", "Could not Parse suborders for Snapdeal")
443
                        subOrder = None
444
                        breakFlag = False
445
                        for strDiv in str(div1).split("<div class=\"seperator\"></div>"):
446
                            div = BeautifulSoup(strDiv)
447
                            divStr = str(div)
448
                            divStr = divStr.replace("\n","").replace("\t", "")
449
                            updateMap = {}
450
                            for line in divStr.split("<br />"):
451
                                if "Suborder ID" in line:
452
                                    merchantSubOrderId = re.findall(r'\d+', line)[0]
453
                                    #break if suborder is inactive   
454
                                    subOrder =  self._isSubOrderActive(order, merchantSubOrderId)
455
                                    if subOrder is None:
456
                                        subOrders = self.parseSubOrder(subOrderElement, placedOn)
457
                                        self.db.merchantOrder.update({"orderId":order['orderId']},{'$push':{"subOrders":{"$each":todict(subOrders)}}})
458
                                        print "Added new suborders to Order id - ", order['orderId']
459
                                        closed = False
460
                                        breakFlag = True
461
                                        break
462
                                    elif subOrder['closed']:
463
                                        breakFlag = True
464
                                        break
465
                                    else: 
466
                                        findMap = {"orderId": order['orderId'], "subOrders.merchantSubOrderId": merchantSubOrderId}
467
                                elif "Status :" in line:
468
                                    detailedStatus = re.findall('>(.*?)</span>', line, re.IGNORECASE)[0]
469
                                    updateMap["subOrders.$.detailedStatus"] = detailedStatus
470
                                    status = self._getStatusFromDetailedStatus(detailedStatus) 
471
                                    closedStatus = status in [Store.ORDER_DELIVERED, Store.ORDER_CANCELLED]
472
                                    if status is not None:
473
                                        updateMap["subOrders.$.status"] = status
474
                                    if detailedStatus == 'Closed For Vendor Reallocation':
475
                                        #if it is more than 6hours mark closed.
476
                                        closeAt = subOrder.get("closeAt") 
477
                                        if closeAt is None:
478
                                            closeAt = datetime.now() + timedelta(hours=6)
479
                                            updateMap["subOrders.$.closeAt"] = datetime.strftime(closeAt,"%Y-%m-%d %H:%M:%S")
480
                                        else:
481
                                            closeAt = datetime.strptime(closeAt,"%Y-%m-%d %H:%M:%S")
482
                                            if datetime.now() > closeAt:
483
                                                closedStatus = True
16969 amit.gupta 484
                                    #Close if not applicable suborders are not closed
485
                                    if utils.fromTimeStamp(order['createdOnInt'] + 35*86400*1000) < datetime.now() and subOrder['cashBackStatus']==utils.CB_NA:
486
                                        closedStatus=True   
14861 amit.gupta 487
 
488
 
489
                                    if closedStatus:
490
                                        #if status is closed then change the paybackStatus accordingly
491
                                        updateMap["subOrders.$.closed"] = True
492
                                        if status == Store.ORDER_DELIVERED:
493
                                            if subOrder.get("cashBackStatus") == Store.CB_PENDING:
494
                                                updateMap["subOrders.$.cashBackStatus"] = Store.CB_APPROVED
495
                                        elif status == Store.ORDER_CANCELLED:
496
                                            if subOrder.get("cashBackStatus") == Store.CB_PENDING:
497
                                                updateMap["subOrders.$.cashBackStatus"] = Store.CB_CANCELLED
498
 
14398 amit.gupta 499
                                    else:
14861 amit.gupta 500
                                        closed = False
501
                                elif "Est. Shipping Date" in line:
502
                                    estimatedShippingDate = line.split(":")[1].strip()
503
                                    updateMap["subOrders.$.estimatedShippingDate"] = estimatedShippingDate
504
                                elif "Est. Delivery Date" in line:
505
                                    estimatedDeliveryDate = line.split(":")[1].strip()
506
                                    updateMap["subOrders.$.estimatedDeliveryDate"] = estimatedDeliveryDate
507
                                elif "Courier Name" in line:
508
                                    courierName = line.split(":")[1].strip()
509
                                    updateMap["subOrders.$.courierName"] = courierName
510
                                elif "Tracking No" in line:
511
                                    trackingNumber = line.split(":")[1].strip()
512
                                    updateMap["subOrders.$.trackingNumber"] = trackingNumber
513
 
514
                            if breakFlag:
515
                                continue
516
 
517
                            bulk.find(findMap).update({'$set' : updateMap})
518
                        bulk.find({'orderId': order['orderId']}).update({'$set':{'closed': closed,"parseError":False}})
519
                    result = bulk.execute()
520
                    tprint(result)
14398 amit.gupta 521
            except:
14847 amit.gupta 522
                tprint("Could not update " + str(order['orderId']) + "For store " + self.getName())
14692 amit.gupta 523
                self.db.merchantOrder.update({"orderId":order['orderId']}, {"$set":{"parseError":True}})
14398 amit.gupta 524
                traceback.print_exc()                
13576 amit.gupta 525
 
14854 amit.gupta 526
    def tryBParsing(self, order, soup):
527
        orderDetailContainerDivs = soup.body.find("div", {'class':'cardLayoutWrap'}).findAll('div', recursive=False)
528
        orderDetailDiv = orderDetailContainerDivs.pop(0)
529
        placedOn = orderDetailDiv.span.text.split(':')[1].strip()
530
 
531
        orderDetailContainerDivs.pop(0)
532
 
533
        subOrders = orderDetailContainerDivs
534
        bulk = self.db.merchantOrder.initialize_ordered_bulk_op()
535
        closed = True
536
        for subOrderElement in subOrders:
537
            prodDivs = subOrderElement.findAll('div', recursive=False)
538
            merchantSubOrderId = prodDivs[0].text.split(':')[1].strip()
539
            subOrder = None
14861 amit.gupta 540
            subOrder =  self._isSubOrderActive(order, merchantSubOrderId)
541
            if subOrder is None:
14864 amit.gupta 542
                try:
14883 amit.gupta 543
                    subOrder = self.parseSubOrderB(subOrderElement, placedOn)
544
                    if subOrder is None:
545
                        continue
546
                    self.db.merchantOrder.update({"orderId":order['orderId']},{'$push':{"subOrders":{"$each":todict([subOrder])}}})
14864 amit.gupta 547
                    print "Added new suborders to Order id - ", order['orderId']
548
                    closed = False
549
                except:
550
                    pass
14861 amit.gupta 551
                continue
552
            elif subOrder['closed']:
553
                continue
554
            else: 
14864 amit.gupta 555
                prodDetailDiv = prodDivs[1].findAll('div', recursive=False)
556
                otherDiv = prodDetailDiv[1]
557
                trackBlock = subOrderElement.find('div',{'class':'trackingDetailsBlock'})
14861 amit.gupta 558
                findMap = {"orderId": order['orderId'], "subOrders.merchantSubOrderId": merchantSubOrderId}
559
                updateMap = {}
560
                detailedStatus = otherDiv.find('div',{'class':'orderStatus'}).span.text.strip()
16298 amit.gupta 561
 
15882 amit.gupta 562
                if 'A new order placed with a different seller' in str(trackBlock):
14861 amit.gupta 563
                    #if it is more than 6hours mark closed.
564
                    closeAt = subOrder.get("closeAt") 
565
                    if closeAt is None:
566
                        closeAt = datetime.now() + timedelta(hours=6)
567
                        updateMap["subOrders.$.closeAt"] = datetime.strftime(closeAt,"%Y-%m-%d %H:%M:%S")
16298 amit.gupta 568
                        bulk.find(findMap).update({'$set' : updateMap})
16301 amit.gupta 569
                        closed=False
16298 amit.gupta 570
                        continue
14854 amit.gupta 571
                    else:
14861 amit.gupta 572
                        closeAt = datetime.strptime(closeAt,"%Y-%m-%d %H:%M:%S")
573
                        if datetime.now() > closeAt:
16298 amit.gupta 574
                            detailedStatus = 'A new order placed with a different seller'
14861 amit.gupta 575
 
16298 amit.gupta 576
 
577
                status = self._getStatusFromDetailedStatus(detailedStatus) 
578
                closedStatus = status in [Store.ORDER_DELIVERED, Store.ORDER_CANCELLED]
579
                updateMap["subOrders.$.detailedStatus"] = detailedStatus
580
                if status is not None:
581
                    updateMap["subOrders.$.status"] = status
14861 amit.gupta 582
 
583
                if closedStatus:
584
                    #if status is closed then change the paybackStatus accordingly
585
                    updateMap["subOrders.$.closed"] = True
586
                    if status == Store.ORDER_DELIVERED:
587
                        if subOrder.get("cashBackStatus") == Store.CB_PENDING:
588
                            updateMap["subOrders.$.cashBackStatus"] = Store.CB_APPROVED
589
                    elif status == Store.ORDER_CANCELLED:
590
                        if subOrder.get("cashBackStatus") == Store.CB_PENDING:
591
                            updateMap["subOrders.$.cashBackStatus"] = Store.CB_CANCELLED
592
 
593
                else:
594
                    closed = False
14854 amit.gupta 595
 
14861 amit.gupta 596
                deliveryStatus = otherDiv.find('div',{'class':'orderDelivery'})
597
                if deliveryStatus is not None:
598
                    delString = deliveryStatus.text.strip()
599
                    arr = delString.split(':')    
600
                    if "On" in arr[0]:
601
                        updateMap['subOrders.$.deliveredOn'] = arr[1].strip()
602
                    elif "Exp. Delivery by" in arr[0]:
603
                        updateMap['subOrders.$.estimatedDeliveryDate'] = arr[1].strip()
15877 amit.gupta 604
                    elif "Est. delivery between" in arr[0]:
605
                        updateMap['subOrders.$.estimatedDeliveryDate'] = delString.split("between")[1].strip()
14861 amit.gupta 606
                    else:
607
                        updateMap['subOrders.$.estimatedShippingDate'] = arr[1].strip()
608
                courierDet = subOrderElement.find('div', {'class':'courierDetail'})
609
                if courierDet is not None:
610
                    updateMap['subOrders.$.courierName'] = courierDet.span.text.strip()
611
                trackingDet = subOrderElement.find('div', {'class':'trackingNo'})
612
                if trackingDet is not None:
613
                    updateMap['subOrders.$.trackingUrl'] = trackingDet.span.a['href']
614
                    updateMap['subOrders.$.trackingNumber'] = trackingDet.span.a.text.strip()                    
14854 amit.gupta 615
            bulk.find(findMap).update({'$set' : updateMap})
616
        bulk.find({'orderId': order['orderId']}).update({'$set':{'closed': closed,"parseError":False}})
617
        result = bulk.execute()
618
        tprint(result)
619
 
13576 amit.gupta 620
 
13569 amit.gupta 621
    def _saveToAffiliate(self, offers):
16946 amit.gupta 622
        collection = self.db.snapdealOrderAffiliateInfo1
623
        #mcollection = self.db.merchantOrder
14443 amit.gupta 624
        for offer in offers:
16946 amit.gupta 625
            count = 0
626
            for row in offers:
627
                if count==0:
628
                    count += 1
629
                    continue
630
                offer = self.covertToObj(row)
631
                if offer.orderId:
632
                    collection.insert(todict(offer))
633
#    def _saveToAffiliate(self, offers):
634
#        collection = self.db.snapdealOrderAffiliateInfo
635
#        mcollection = self.db.merchantOrder
636
#        for offer in offers:
637
#            offer = self.covertToObj(offer)
638
#            collection.update({"adId":offer.adId, "saleAmount":offer.saleAmount, "payOut":offer.payOut},{"$set":todict(offer)}, upsert=True)
639
#            mcollection.update({"subTagId":offer.subTagId, "storeId":self.store_id, "subOrders.missingAff":True}, {"$set":{"subOrders.$.missingAff":False}})
13569 amit.gupta 640
 
641
 
642
    def _getAllOffers(self, br, token):
643
        allOffers = []
644
        nextPage = 1  
645
        while True:
646
            data = getPostData(token, nextPage)
647
            response = br.open(POST_URL, data)
13680 amit.gupta 648
            rmap = json.loads(ungzipResponse(response))
13569 amit.gupta 649
            if rmap is not None:
650
                rmap = rmap['response']
14492 amit.gupta 651
                print rmap
13569 amit.gupta 652
                if rmap is not None and len(rmap['errors'])==0:
653
                    allOffers += rmap['data']['data']
654
            nextPage += 1
655
            if rmap['data']['pageCount']<nextPage:
656
                break
657
 
658
        return allOffers
659
 
16946 amit.gupta 660
#    def covertToObj(self,offer):
661
#        offerData = offer['Stat']
662
#        offer1 = AffiliateInfo(offerData['affiliate_info1'], self.store_id, offerData['conversion_status'], offerData['ad_id'], 
663
#                              offerData['datetime'], int(float(offerData['payout'])), offer['Offer']['name'], offerData['ip'], int(float(offerData['conversion_sale_amount'])))
664
#        offer1.saleTime = int(time.mktime(datetime.strptime(offer1.saleDate, "%Y-%m-%d %H:%M:%S").timetuple()))
665
#        return offer1
666
 
13569 amit.gupta 667
    def covertToObj(self,offer):
16946 amit.gupta 668
        product,category,order_code,quantity,price,sales,commission_rate,commission_earned,datetime1,affiliate_sub_id1,affiliate_sub_id2 = offer
669
        offer1 = AffiliateInfo(affiliate_sub_id1, 3, None, None,            utils.toTimeStamp(datetime.strptime(datetime1, "%m-%d-%Y %H:%M")),   
670
 
671
        offer1.orderId = order_code if order_code  else None
672
        offer1.productCode = product
673
        offer1.unitPrice = int(float(price))
674
        offer1.quantity = int(quantity)
13569 amit.gupta 675
        return offer1
676
def getPostData(token, page = 1, limit= 20, startDate=None, endDate=None):
13680 amit.gupta 677
    endDate=date.today() + timedelta(days=1)
678
    startDate=endDate - timedelta(days=31)
13569 amit.gupta 679
 
680
    parameters = (
681
        ("page",str(page)),
682
        ("limit",str(limit)),
683
        ("fields[]","Stat.offer_id"),
684
        ("fields[]","Stat.datetime"),
685
        ("fields[]","Offer.name"),
686
        ("fields[]","Stat.conversion_status"),
687
        ("fields[]","Stat.conversion_sale_amount"),
688
        ("fields[]","Stat.payout"),
689
        ("fields[]","Stat.ip"),
690
        ("fields[]","Stat.ad_id"),
691
        ("fields[]","Stat.affiliate_info1"),
692
        ("sort[Stat.datetime]","desc"),
693
        ("filters[Stat.date][conditional]","BETWEEN"),
694
        ("filters[Stat.date][values][]",startDate.strftime('%Y-%m-%d')),
695
        ("filters[Stat.date][values][]",endDate.strftime('%Y-%m-%d')),
696
        ("data_start",startDate.strftime('%Y-%m-%d')),
697
        ("data_end",endDate.strftime('%Y-%m-%d')),
698
        ("Method","getConversions"),
699
        ("NetworkId","jasper"),
700
        ("SessionToken",token),
701
    )
702
    #Encode the parameters
703
    return urllib.urlencode(parameters)
704
 
705
def main():
14458 amit.gupta 706
    #print todict([1,2,"3"])
14402 amit.gupta 707
    store = getStore(3)
15882 amit.gupta 708
    #store.parseOrderRawHtml(332221, "3232311", 2, "32311243", "https://m.snapdeal.com/orderSummary?code=3fbc8a02a1c4d3c4e906f46886de0464&order=5808451506")
16946 amit.gupta 709
    #store.scrapeStoreOrders()
13662 amit.gupta 710
    #store._isSubOrderActive(8, "5970688907")
16946 amit.gupta 711
    store.scrapeAffiliate(datetime(2015,4,1))
14758 amit.gupta 712
    #store.scrapeStoreOrders()
13569 amit.gupta 713
 
714
 
14459 amit.gupta 715
 
13576 amit.gupta 716
def todict(obj, classkey=None):
717
    if isinstance(obj, dict):
718
        data = {}
719
        for (k, v) in obj.items():
720
            data[k] = todict(v, classkey)
721
        return data
722
    elif hasattr(obj, "_ast"):
723
        return todict(obj._ast())
724
    elif hasattr(obj, "__iter__"):
725
        return [todict(v, classkey) for v in obj]
726
    elif hasattr(obj, "__dict__"):
727
        data = dict([(key, todict(value, classkey)) 
728
            for key, value in obj.__dict__.iteritems() 
729
            if not callable(value) and not key.startswith('_')])
730
        if classkey is not None and hasattr(obj, "__class__"):
731
            data[classkey] = obj.__class__.__name__
732
        return data
733
    else:
734
        return obj
14239 amit.gupta 735
 
736
if __name__ == '__main__':
737
    main()