Subversion Repositories SmartDukaan

Rev

Rev 16946 | Rev 16969 | 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
484
 
485
 
486
                                    if closedStatus:
487
                                        #if status is closed then change the paybackStatus accordingly
488
                                        updateMap["subOrders.$.closed"] = True
489
                                        if status == Store.ORDER_DELIVERED:
490
                                            if subOrder.get("cashBackStatus") == Store.CB_PENDING:
491
                                                updateMap["subOrders.$.cashBackStatus"] = Store.CB_APPROVED
492
                                        elif status == Store.ORDER_CANCELLED:
493
                                            if subOrder.get("cashBackStatus") == Store.CB_PENDING:
494
                                                updateMap["subOrders.$.cashBackStatus"] = Store.CB_CANCELLED
495
 
14398 amit.gupta 496
                                    else:
14861 amit.gupta 497
                                        closed = False
498
                                elif "Est. Shipping Date" in line:
499
                                    estimatedShippingDate = line.split(":")[1].strip()
500
                                    updateMap["subOrders.$.estimatedShippingDate"] = estimatedShippingDate
501
                                elif "Est. Delivery Date" in line:
502
                                    estimatedDeliveryDate = line.split(":")[1].strip()
503
                                    updateMap["subOrders.$.estimatedDeliveryDate"] = estimatedDeliveryDate
504
                                elif "Courier Name" in line:
505
                                    courierName = line.split(":")[1].strip()
506
                                    updateMap["subOrders.$.courierName"] = courierName
507
                                elif "Tracking No" in line:
508
                                    trackingNumber = line.split(":")[1].strip()
509
                                    updateMap["subOrders.$.trackingNumber"] = trackingNumber
510
 
511
                            if breakFlag:
512
                                continue
513
 
514
                            bulk.find(findMap).update({'$set' : updateMap})
515
                        bulk.find({'orderId': order['orderId']}).update({'$set':{'closed': closed,"parseError":False}})
516
                    result = bulk.execute()
517
                    tprint(result)
14398 amit.gupta 518
            except:
14847 amit.gupta 519
                tprint("Could not update " + str(order['orderId']) + "For store " + self.getName())
14692 amit.gupta 520
                self.db.merchantOrder.update({"orderId":order['orderId']}, {"$set":{"parseError":True}})
14398 amit.gupta 521
                traceback.print_exc()                
13576 amit.gupta 522
 
14854 amit.gupta 523
    def tryBParsing(self, order, soup):
524
        orderDetailContainerDivs = soup.body.find("div", {'class':'cardLayoutWrap'}).findAll('div', recursive=False)
525
        orderDetailDiv = orderDetailContainerDivs.pop(0)
526
        placedOn = orderDetailDiv.span.text.split(':')[1].strip()
527
 
528
        orderDetailContainerDivs.pop(0)
529
 
530
        subOrders = orderDetailContainerDivs
531
        bulk = self.db.merchantOrder.initialize_ordered_bulk_op()
532
        closed = True
533
        for subOrderElement in subOrders:
534
            prodDivs = subOrderElement.findAll('div', recursive=False)
535
            merchantSubOrderId = prodDivs[0].text.split(':')[1].strip()
536
            subOrder = None
14861 amit.gupta 537
            subOrder =  self._isSubOrderActive(order, merchantSubOrderId)
538
            if subOrder is None:
14864 amit.gupta 539
                try:
14883 amit.gupta 540
                    subOrder = self.parseSubOrderB(subOrderElement, placedOn)
541
                    if subOrder is None:
542
                        continue
543
                    self.db.merchantOrder.update({"orderId":order['orderId']},{'$push':{"subOrders":{"$each":todict([subOrder])}}})
14864 amit.gupta 544
                    print "Added new suborders to Order id - ", order['orderId']
545
                    closed = False
546
                except:
547
                    pass
14861 amit.gupta 548
                continue
549
            elif subOrder['closed']:
550
                continue
551
            else: 
14864 amit.gupta 552
                prodDetailDiv = prodDivs[1].findAll('div', recursive=False)
553
                otherDiv = prodDetailDiv[1]
554
                trackBlock = subOrderElement.find('div',{'class':'trackingDetailsBlock'})
14861 amit.gupta 555
                findMap = {"orderId": order['orderId'], "subOrders.merchantSubOrderId": merchantSubOrderId}
556
                updateMap = {}
557
                detailedStatus = otherDiv.find('div',{'class':'orderStatus'}).span.text.strip()
16298 amit.gupta 558
 
15882 amit.gupta 559
                if 'A new order placed with a different seller' in str(trackBlock):
14861 amit.gupta 560
                    #if it is more than 6hours mark closed.
561
                    closeAt = subOrder.get("closeAt") 
562
                    if closeAt is None:
563
                        closeAt = datetime.now() + timedelta(hours=6)
564
                        updateMap["subOrders.$.closeAt"] = datetime.strftime(closeAt,"%Y-%m-%d %H:%M:%S")
16298 amit.gupta 565
                        bulk.find(findMap).update({'$set' : updateMap})
16301 amit.gupta 566
                        closed=False
16298 amit.gupta 567
                        continue
14854 amit.gupta 568
                    else:
14861 amit.gupta 569
                        closeAt = datetime.strptime(closeAt,"%Y-%m-%d %H:%M:%S")
570
                        if datetime.now() > closeAt:
16298 amit.gupta 571
                            detailedStatus = 'A new order placed with a different seller'
14861 amit.gupta 572
 
16298 amit.gupta 573
 
574
                status = self._getStatusFromDetailedStatus(detailedStatus) 
575
                closedStatus = status in [Store.ORDER_DELIVERED, Store.ORDER_CANCELLED]
576
                updateMap["subOrders.$.detailedStatus"] = detailedStatus
577
                if status is not None:
578
                    updateMap["subOrders.$.status"] = status
14861 amit.gupta 579
 
580
                if closedStatus:
581
                    #if status is closed then change the paybackStatus accordingly
582
                    updateMap["subOrders.$.closed"] = True
583
                    if status == Store.ORDER_DELIVERED:
584
                        if subOrder.get("cashBackStatus") == Store.CB_PENDING:
585
                            updateMap["subOrders.$.cashBackStatus"] = Store.CB_APPROVED
586
                    elif status == Store.ORDER_CANCELLED:
587
                        if subOrder.get("cashBackStatus") == Store.CB_PENDING:
588
                            updateMap["subOrders.$.cashBackStatus"] = Store.CB_CANCELLED
589
 
590
                else:
591
                    closed = False
14854 amit.gupta 592
 
14861 amit.gupta 593
                deliveryStatus = otherDiv.find('div',{'class':'orderDelivery'})
594
                if deliveryStatus is not None:
595
                    delString = deliveryStatus.text.strip()
596
                    arr = delString.split(':')    
597
                    if "On" in arr[0]:
598
                        updateMap['subOrders.$.deliveredOn'] = arr[1].strip()
599
                    elif "Exp. Delivery by" in arr[0]:
600
                        updateMap['subOrders.$.estimatedDeliveryDate'] = arr[1].strip()
15877 amit.gupta 601
                    elif "Est. delivery between" in arr[0]:
602
                        updateMap['subOrders.$.estimatedDeliveryDate'] = delString.split("between")[1].strip()
14861 amit.gupta 603
                    else:
604
                        updateMap['subOrders.$.estimatedShippingDate'] = arr[1].strip()
605
                courierDet = subOrderElement.find('div', {'class':'courierDetail'})
606
                if courierDet is not None:
607
                    updateMap['subOrders.$.courierName'] = courierDet.span.text.strip()
608
                trackingDet = subOrderElement.find('div', {'class':'trackingNo'})
609
                if trackingDet is not None:
610
                    updateMap['subOrders.$.trackingUrl'] = trackingDet.span.a['href']
611
                    updateMap['subOrders.$.trackingNumber'] = trackingDet.span.a.text.strip()                    
14854 amit.gupta 612
            bulk.find(findMap).update({'$set' : updateMap})
613
        bulk.find({'orderId': order['orderId']}).update({'$set':{'closed': closed,"parseError":False}})
614
        result = bulk.execute()
615
        tprint(result)
616
 
13576 amit.gupta 617
 
13569 amit.gupta 618
    def _saveToAffiliate(self, offers):
16946 amit.gupta 619
        collection = self.db.snapdealOrderAffiliateInfo1
620
        #mcollection = self.db.merchantOrder
14443 amit.gupta 621
        for offer in offers:
16946 amit.gupta 622
            count = 0
623
            for row in offers:
624
                if count==0:
625
                    count += 1
626
                    continue
627
                offer = self.covertToObj(row)
628
                if offer.orderId:
629
                    collection.insert(todict(offer))
630
#    def _saveToAffiliate(self, offers):
631
#        collection = self.db.snapdealOrderAffiliateInfo
632
#        mcollection = self.db.merchantOrder
633
#        for offer in offers:
634
#            offer = self.covertToObj(offer)
635
#            collection.update({"adId":offer.adId, "saleAmount":offer.saleAmount, "payOut":offer.payOut},{"$set":todict(offer)}, upsert=True)
636
#            mcollection.update({"subTagId":offer.subTagId, "storeId":self.store_id, "subOrders.missingAff":True}, {"$set":{"subOrders.$.missingAff":False}})
13569 amit.gupta 637
 
638
 
639
    def _getAllOffers(self, br, token):
640
        allOffers = []
641
        nextPage = 1  
642
        while True:
643
            data = getPostData(token, nextPage)
644
            response = br.open(POST_URL, data)
13680 amit.gupta 645
            rmap = json.loads(ungzipResponse(response))
13569 amit.gupta 646
            if rmap is not None:
647
                rmap = rmap['response']
14492 amit.gupta 648
                print rmap
13569 amit.gupta 649
                if rmap is not None and len(rmap['errors'])==0:
650
                    allOffers += rmap['data']['data']
651
            nextPage += 1
652
            if rmap['data']['pageCount']<nextPage:
653
                break
654
 
655
        return allOffers
656
 
16946 amit.gupta 657
#    def covertToObj(self,offer):
658
#        offerData = offer['Stat']
659
#        offer1 = AffiliateInfo(offerData['affiliate_info1'], self.store_id, offerData['conversion_status'], offerData['ad_id'], 
660
#                              offerData['datetime'], int(float(offerData['payout'])), offer['Offer']['name'], offerData['ip'], int(float(offerData['conversion_sale_amount'])))
661
#        offer1.saleTime = int(time.mktime(datetime.strptime(offer1.saleDate, "%Y-%m-%d %H:%M:%S").timetuple()))
662
#        return offer1
663
 
13569 amit.gupta 664
    def covertToObj(self,offer):
16946 amit.gupta 665
        product,category,order_code,quantity,price,sales,commission_rate,commission_earned,datetime1,affiliate_sub_id1,affiliate_sub_id2 = offer
666
        offer1 = AffiliateInfo(affiliate_sub_id1, 3, None, None,            utils.toTimeStamp(datetime.strptime(datetime1, "%m-%d-%Y %H:%M")),   
667
 
668
        offer1.orderId = order_code if order_code  else None
669
        offer1.productCode = product
670
        offer1.unitPrice = int(float(price))
671
        offer1.quantity = int(quantity)
13569 amit.gupta 672
        return offer1
673
def getPostData(token, page = 1, limit= 20, startDate=None, endDate=None):
13680 amit.gupta 674
    endDate=date.today() + timedelta(days=1)
675
    startDate=endDate - timedelta(days=31)
13569 amit.gupta 676
 
677
    parameters = (
678
        ("page",str(page)),
679
        ("limit",str(limit)),
680
        ("fields[]","Stat.offer_id"),
681
        ("fields[]","Stat.datetime"),
682
        ("fields[]","Offer.name"),
683
        ("fields[]","Stat.conversion_status"),
684
        ("fields[]","Stat.conversion_sale_amount"),
685
        ("fields[]","Stat.payout"),
686
        ("fields[]","Stat.ip"),
687
        ("fields[]","Stat.ad_id"),
688
        ("fields[]","Stat.affiliate_info1"),
689
        ("sort[Stat.datetime]","desc"),
690
        ("filters[Stat.date][conditional]","BETWEEN"),
691
        ("filters[Stat.date][values][]",startDate.strftime('%Y-%m-%d')),
692
        ("filters[Stat.date][values][]",endDate.strftime('%Y-%m-%d')),
693
        ("data_start",startDate.strftime('%Y-%m-%d')),
694
        ("data_end",endDate.strftime('%Y-%m-%d')),
695
        ("Method","getConversions"),
696
        ("NetworkId","jasper"),
697
        ("SessionToken",token),
698
    )
699
    #Encode the parameters
700
    return urllib.urlencode(parameters)
701
 
702
def main():
14458 amit.gupta 703
    #print todict([1,2,"3"])
14402 amit.gupta 704
    store = getStore(3)
15882 amit.gupta 705
    #store.parseOrderRawHtml(332221, "3232311", 2, "32311243", "https://m.snapdeal.com/orderSummary?code=3fbc8a02a1c4d3c4e906f46886de0464&order=5808451506")
16946 amit.gupta 706
    #store.scrapeStoreOrders()
13662 amit.gupta 707
    #store._isSubOrderActive(8, "5970688907")
16946 amit.gupta 708
    store.scrapeAffiliate(datetime(2015,4,1))
14758 amit.gupta 709
    #store.scrapeStoreOrders()
13569 amit.gupta 710
 
711
 
14459 amit.gupta 712
 
13576 amit.gupta 713
def todict(obj, classkey=None):
714
    if isinstance(obj, dict):
715
        data = {}
716
        for (k, v) in obj.items():
717
            data[k] = todict(v, classkey)
718
        return data
719
    elif hasattr(obj, "_ast"):
720
        return todict(obj._ast())
721
    elif hasattr(obj, "__iter__"):
722
        return [todict(v, classkey) for v in obj]
723
    elif hasattr(obj, "__dict__"):
724
        data = dict([(key, todict(value, classkey)) 
725
            for key, value in obj.__dict__.iteritems() 
726
            if not callable(value) and not key.startswith('_')])
727
        if classkey is not None and hasattr(obj, "__class__"):
728
            data[classkey] = obj.__class__.__name__
729
        return data
730
    else:
731
        return obj
14239 amit.gupta 732
 
733
if __name__ == '__main__':
734
    main()