Subversion Repositories SmartDukaan

Rev

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