Subversion Repositories SmartDukaan

Rev

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