Subversion Repositories SmartDukaan

Rev

Rev 15346 | Rev 15474 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
13774 amit.gupta 1
# coding=utf-8
13569 amit.gupta 2
'''
3
Created on Jan 15, 2015
4
 
5
@author: amit
6
'''
13774 amit.gupta 7
from base64 import encode
8
from bs4 import BeautifulSoup
14650 amit.gupta 9
from datetime import datetime, timedelta
10
from dtr.dao import Order, SubOrder, AmazonAffiliateInfo
14464 amit.gupta 11
from dtr.main import getStore, Store as MStore, ParseException, getBrowserObject, \
14624 amit.gupta 12
    ungzipResponse, tprint
14650 amit.gupta 13
from dtr.sources.flipkart import todict, AFF_REPORT_URL
14749 amit.gupta 14
from dtr.utils.utils import fetchResponseUsingProxy
14162 amit.gupta 15
from paramiko import sftp
16
from paramiko.client import SSHClient
17
from paramiko.sftp_client import SFTPClient
14650 amit.gupta 18
import base64
19
import gzip
14624 amit.gupta 20
import mechanize
14285 amit.gupta 21
import os.path
14162 amit.gupta 22
import paramiko
13774 amit.gupta 23
import re
14033 amit.gupta 24
import time
13809 amit.gupta 25
import traceback
14650 amit.gupta 26
import urllib2
15346 amit.gupta 27
from dtr.storage.Mongo import getDealRank
13774 amit.gupta 28
 
29
ORDER_REDIRECT_URL = 'https://www.amazon.in/gp/css/summary/edit.html?orderID=%s'
13810 amit.gupta 30
ORDER_SUCCESS_URL = 'https://www.amazon.in/gp/buy/spc/handlers/static-submit-decoupled.html'
13823 amit.gupta 31
THANKYOU_URL = 'https://www.amazon.in/gp/buy/thankyou/handlers/display.html'
14624 amit.gupta 32
AMAZON_AFF_URL = 'https://assoc-datafeeds-eu.amazon.com/datafeed/listReports'
14650 amit.gupta 33
AMAZON_AFF_FILE_URL = 'https://assoc-datafeeds-eu.amazon.com/datafeed/getReport?filename=saholic-21-orders-report-%s.tsv.gz'
13774 amit.gupta 34
class Store(MStore):
13821 amit.gupta 35
 
14032 amit.gupta 36
    orderStatusRegexMap = { MStore.ORDER_PLACED : ['ordered from', 'not yet dispatched','dispatching now', 'preparing for dispatch'],
14064 amit.gupta 37
                            MStore.ORDER_SHIPPED : ['dispatched on','dispatched', 'on the way', 'out for delivery', 'Out for delivery'],
14032 amit.gupta 38
                            MStore.ORDER_CANCELLED : ['return complete', 'refunded', 'cancelled'],
39
                            MStore.ORDER_DELIVERED : ['delivered']
13821 amit.gupta 40
                           }
13774 amit.gupta 41
 
42
    def __init__(self,store_id):
43
        super(Store, self).__init__(store_id)
44
 
45
    def getName(self):
14749 amit.gupta 46
        return "amazon"
13774 amit.gupta 47
 
14945 amit.gupta 48
    def parseOrderRawHtml(self, orderId, subTagId, userId, rawHtml, orderSuccessUrl, track=False):
14958 amit.gupta 49
        parseString = "Tracking" if track else "Transacted"
50
        print parseString, "Order Id to be parsed is :", orderId
13796 amit.gupta 51
        resp = {}
14813 amit.gupta 52
        resp['result'] = 'ORDER_NOT_CREATED'
13821 amit.gupta 53
        if ORDER_SUCCESS_URL in orderSuccessUrl or THANKYOU_URL in orderSuccessUrl:
13774 amit.gupta 54
            try:
55
                soup = BeautifulSoup(rawHtml)
14608 amit.gupta 56
                try:
57
                    orderUrl = soup.find('div', {"id":"thank-you-box-wrapper"}).div.findAll('div', recursive=False)[1].a['href']
58
                    merchantOrderId = re.findall(r'.*&oid=(.*)&?.*?', orderUrl)[0]
59
                except:
60
                    merchantOrderId = soup.find(id="orders-list").div.span.b.text
14699 amit.gupta 61
                order = Order(orderId, userId, subTagId, self.store_id, orderSuccessUrl, True)
14972 amit.gupta 62
                order.orderTrackingUrl = ORDER_REDIRECT_URL % (merchantOrderId)
63
                order.orderSuccessUrl = orderSuccessUrl
14211 amit.gupta 64
                order.merchantOrderId = merchantOrderId
14291 amit.gupta 65
                order.requireDetail = True
14698 amit.gupta 66
                order.status = 'html_required'
14297 amit.gupta 67
                order.closed = None
14312 amit.gupta 68
                if self._saveToOrder(todict(order)):
69
                    resp['result'] = 'ORDER_CREATED'
70
                    resp["url"] = ORDER_REDIRECT_URL % (merchantOrderId)
71
                    resp["htmlRequired"] = True
72
                    resp['orderId'] = orderId
73
                else:
74
                    resp['result'] = 'ORDER_ALREADY_CREATED_IGNORED'
75
 
13774 amit.gupta 76
            except:
14813 amit.gupta 77
                #Write all cases here for Order Not created Known
14809 amit.gupta 78
                try:
14815 amit.gupta 79
                    if 'Securely redirecting you' in soup.h3.text.strip():
14813 amit.gupta 80
                        resp['result'] = 'ORDER_NOT_CREATED_KNOWN'
14809 amit.gupta 81
                    else:
14813 amit.gupta 82
                        raise
14809 amit.gupta 83
                except:
14814 amit.gupta 84
                    try:
14815 amit.gupta 85
                        if soup.h1.text.strip() in ['This is a duplicate order', 'There was a problem with your payment.']:
14814 amit.gupta 86
                            resp['result'] = 'ORDER_NOT_CREATED_KNOWN'
87
                        else:
88
                            raise
89
                    except:
15046 amit.gupta 90
                        try:
91
                            if soup.h2.text.strip() == 'Web page not available':
92
                                resp['result'] = 'ORDER_NOT_CREATED_KNOWN'
93
                            else:
94
                                raise
95
                        except:
96
                            resp['result'] = 'ORDER_NOT_CREATED_UNKNOWN'
13774 amit.gupta 97
        else:
13781 amit.gupta 98
            try:
14722 amit.gupta 99
                mo = self.db.merchantOrder.find_one({"orderId":orderId})
100
                if mo is not None:
14749 amit.gupta 101
                    merchantOrder = Order(orderId, userId, subTagId, self.store_id, orderSuccessUrl, False)
14722 amit.gupta 102
                    merchantOrder.createdOn = mo.get("createdOn")
103
                    merchantOrder.createdOnInt =  mo.get("createdOnInt")
104
                else:
14945 amit.gupta 105
                    print "Could not find amazon order with order Id", orderId
14749 amit.gupta 106
                    merchantOrder = Order(orderId, userId, subTagId, self.store_id, orderSuccessUrl)
14464 amit.gupta 107
                soup = BeautifulSoup(rawHtml)
108
                try:
14961 amit.gupta 109
                    self.parseNewStlye(merchantOrder, soup)
15046 amit.gupta 110
                    resp['result'] = 'DETAIL_CREATED'
14464 amit.gupta 111
                except:
14545 amit.gupta 112
                    try:
14566 amit.gupta 113
                        traceback.print_exc()
14961 amit.gupta 114
                        self.parseOldStlye(merchantOrder, soup)
15046 amit.gupta 115
                        resp['result'] = 'DETAIL_CREATED'
14545 amit.gupta 116
                    except:
14566 amit.gupta 117
                        traceback.print_exc()
15056 amit.gupta 118
                        try:
119
                            self.parseCancelled(merchantOrder, soup)
120
                            resp['result'] = 'ORDER_CANCELLED'
121
                        except:
15059 amit.gupta 122
                            try:
123
                                if soup.h1.span.text=="Account":
124
                                    resp['result'] = 'DETAIL_NOT_CREATED_KNOWN'
125
                                else:
126
                                    raise
127
                            except:
128
                                if soup.find(id="ap_signin_pagelet_title").h1.text.strip()=="Sign In":
129
                                    resp['result'] = 'DETAIL_NOT_CREATED_KNOWN'
130
                                else:
131
                                    raise
13781 amit.gupta 132
            except:
14813 amit.gupta 133
                order = self.db.merchantOrder.find_one({"orderId":orderId})
134
                if order is not None:
135
                    self.db.merchantOrder.update({"orderId":orderId}, {"$set":{"status":"parse_failed"}})
136
                print "Error occurred"
15046 amit.gupta 137
                resp['result'] = 'DETAIL_NOT_CREATED_UNKNOWN'
14813 amit.gupta 138
                traceback.print_exc()
15046 amit.gupta 139
        return resp    
13774 amit.gupta 140
 
13868 amit.gupta 141
    #This should be exposed from api for specific sources
142
    def scrapeStoreOrders(self):
14624 amit.gupta 143
        orders = self.db.merchantOrder.find({"storeId":1, "closed":False, "subOrders.closed":False, "subOrders.trackingUrl":{"$exists":True}})
144
        for merchantOrder in orders:
14981 amit.gupta 145
            executeBulk = False
14624 amit.gupta 146
            try:
147
                bulk = self.db.merchantOrder.initialize_ordered_bulk_op()
148
                closed = True
149
                map1 = {}
150
                for subOrder in merchantOrder.get("subOrders"):
151
                    if subOrder.get("closed"):
152
                        continue
153
                    elif subOrder.get("trackingUrl") is None:
154
                        closed = False
155
                        continue
14981 amit.gupta 156
                    executeBulk = True
14624 amit.gupta 157
                    findMap = {"orderId":merchantOrder.get("orderId"), "subOrders.merchantSubOrderId":subOrder.get("merchantSubOrderId")} 
158
                    trackingUrl = subOrder.get("trackingUrl")
159
                    if not map1.has_key(trackingUrl):
14749 amit.gupta 160
                        map1[trackingUrl] = self.parseTrackingUrl(trackingUrl)
14624 amit.gupta 161
                    newOrder = map1.get(trackingUrl)
162
                    newOrder['cashBackStatus'] = subOrder.get('cashBackStatus')
163
                    updateMap = self.getUpdateMap(newOrder)
164
                    print findMap, "\n", updateMap
165
                    bulk.find(findMap).update({'$set' : updateMap})
166
                    closed = closed and newOrder['closed']
14981 amit.gupta 167
                if executeBulk:
14697 amit.gupta 168
                    bulk.find({"orderId":merchantOrder.get("orderId")}).update({"$set":{"closed":closed, "parseError":False}})
14981 amit.gupta 169
                    bulk.execute()
14624 amit.gupta 170
            except:
14847 amit.gupta 171
                tprint("Could not update " + str(merchantOrder['orderId']) + " For store " + self.getName())
14692 amit.gupta 172
                self.db.merchantOrder.update({"orderId":merchantOrder['orderId']}, {"$set":{"parseError":True}})
14624 amit.gupta 173
                traceback.print_exc()
174
 
14608 amit.gupta 175
 
176
 
14771 amit.gupta 177
    def parserest(self, soup):
178
        print "Hi"
179
        if soup.find('h1'):
180
            print "OK"
14608 amit.gupta 181
 
14464 amit.gupta 182
    def parseOldStlye(self, merchantOrder, soup):
183
        merchantOrder.orderTrackingUrl = merchantOrder.orderSuccessUrl
184
        table = soup.body.findAll("table", recursive=False)[1]
185
        #print table
186
        tables = table.tr.td.findAll("table", recursive=False)
187
        for tr in tables[2].findAll("tr"):
188
            boldElement = tr.td.b
189
            if "Order Placed" in str(boldElement):
190
                merchantOrder.placedOn = boldElement.next_sibling.strip()
191
            if "order number" in str(boldElement):
192
                merchantOrder.merchantOrderId = boldElement.next_sibling.strip()
193
            if "Order Total" in str(boldElement):
194
                merchantOrder.paidAmount = int(float(boldElement.find('span').contents[-1].replace(',','')))
195
        anchors = table.tr.td.findAll("a", recursive=False)
196
        paymentAnchor = anchors.pop(-1)
197
 
198
        count = 0
199
        subOrders = []
200
        merchantOrder.subOrders = subOrders
201
        counter = 0 
202
        for anchor in anchors:
203
            count += 1
204
            tab = anchor.next_sibling
205
            status = MStore.ORDER_PLACED
206
            subStr = "Delivery #" + str(count) + ":"
207
            if subStr in  tab.find("b").text:
208
                detailedStatus = tab.find("b").text.replace(subStr, '').strip()
209
 
210
            tab = tab.next_sibling.next_sibling
211
            trs = tab.find("table").find('tbody').findAll("tr", recursive = False)
212
 
213
            estimatedDelivery = trs[0].td.find("b").next_sibling.strip()
214
 
215
            orderItemTrs = trs[1].findAll("td", recursive=False)[1].table.tbody.findAll("tr", recursive = False)
216
            i = -1
217
            for orderItemTr in orderItemTrs:
218
                i += 1
219
                if i%2 == 0:
220
                    continue
221
                counter += 1
222
                quantity =  int(re.findall(r'\d+', orderItemTr.td.contents[0])[0])
223
 
224
                productUrl = orderItemTr.td.contents[1].a["href"]
225
                productTitle = orderItemTr.td.contents[1].a.text
226
 
227
                unitPrice = int(float(orderItemTr.findAll('td')[1].span.text.replace('Rs. ','').replace(',','')))
228
 
229
 
230
                subOrder = SubOrder(productTitle, productUrl, merchantOrder.placedOn, unitPrice*quantity, status, quantity)
231
                subOrder.merchantSubOrderId = str(counter) + " of " + merchantOrder.merchantOrderId
232
                subOrder.estimatedDeliveryDate = estimatedDelivery
14722 amit.gupta 233
                estDlvyTime = datetime.strptime(estimatedDelivery.split('-')[0].strip(), "%A %d %B %Y")
234
                createdOn = datetime.fromtimestamp(merchantOrder.createdOnInt)
235
                subOrder.trackAfter = int(time.mktime(max(estDlvyTime-timedelta(days=4),createdOn + timedelta(days=3)).timetuple()))
14464 amit.gupta 236
                subOrder.productCode = productUrl.split('/')[5]
237
                subOrder.detailedStatus = detailedStatus
238
                (cashbackAmount, percentage) = self.getCashbackAmount(subOrder.productCode, unitPrice*quantity)
15346 amit.gupta 239
                dealRank = getDealRank(subOrder.productCode, self.store_id, merchantOrder.userId)
240
                subOrder.dealRank = dealRank.get('rank')
241
                subOrder.rankDesc = dealRank.get('description')
14464 amit.gupta 242
                cashbackStatus = Store.CB_PENDING
243
                if cashbackAmount <= 0:
244
                    cashbackStatus = Store.CB_NA
245
                subOrder.cashBackStatus = cashbackStatus
246
                subOrder.cashBackAmount = cashbackAmount
247
                if percentage > 0:
248
                    subOrder.cashBackPercentage = percentage
249
                subOrders.append(subOrder)
250
        priceList = paymentAnchor.next_sibling.next_sibling.next_sibling.table.table.tbody.tbody.tbody.findAll('tr', recursive=False)
251
        totalAmount = 0
252
        grandAmount = 0
253
        for price in priceList:
254
            labelTd = price.td
255
            if 'Subtotal:' in labelTd.text:
256
                totalAmount += int(float(labelTd.next_sibling.next_sibling.find('span').contents[-1].replace(',','')))
257
            elif 'Grand Total:' in labelTd.text:
258
                grandAmount += int(float(labelTd.next_sibling.next_sibling.find('span').contents[-1].replace(',','')))
259
        if grandAmount < totalAmount:
260
            diff = totalAmount - grandAmount
261
            for subOrder in merchantOrder.subOrders:
262
                subOrder.amountPaid -= int(diff*(1-subOrder.amountPaid/totalAmount))
14698 amit.gupta 263
        merchantOrder.status='success'
14464 amit.gupta 264
        self._updateToOrder(todict(merchantOrder))
265
 
266
    def parseNewStlye(self, merchantOrder, soup):
267
        merchantOrder.orderTrackingUrl = merchantOrder.orderSuccessUrl
268
        orderDetailsContainer = soup.body.find(id="orderDetails")
14566 amit.gupta 269
        divAfterH1 = orderDetailsContainer.h1.next_sibling.next_sibling
270
        orderLeftDiv = divAfterH1.div
14464 amit.gupta 271
        placedOnSpan = orderLeftDiv.find("span", {'class':'order-date-invoice-item'})
272
        merchantOrder.placedOn =placedOnSpan.text.split('Ordered on')[1].strip()
273
        merchantOrder.merchantOrderId = placedOnSpan.next_sibling.next_sibling.text.split('Order#')[1].strip()
14566 amit.gupta 274
        priceBox = divAfterH1.next_sibling.next_sibling.next_sibling.next_sibling.find("div", {"class":"a-box-inner"}).div.div.findAll('div', recursive=False)[-1]
14464 amit.gupta 275
        priceRows = priceBox.findAll('div', {'class':'a-row'})
276
        subTotal = 0
14566 amit.gupta 277
        shippingPrice = 0   
14464 amit.gupta 278
        promoApplied = 0
279
        for priceRow in priceRows:
280
            if "Item(s) Subtotal:" in str(priceRow):
281
                subTotal = int(float(priceRow.div.next_sibling.next_sibling.span.span.text.replace('Rs.','').replace(',', '')))
282
            elif "Shipping:" in str(priceRow):
283
                shippingPrice  = int(float(priceRow.div.next_sibling.next_sibling.span.span.text.replace('Rs.','').replace(',', '')))
284
            elif "Grand Total:" in str(priceRow):
285
                grandPrice  = int(float(priceRow.div.next_sibling.next_sibling.span.span.text.replace('Rs.','').replace(',', '')))
286
                merchantOrder.paidAmount = grandPrice
287
            elif "Total:" in str(priceRow):
288
                totalPrice  = int(float(priceRow.div.next_sibling.next_sibling.span.span.text.replace('Rs.','').replace(',', '')))
289
            elif "Promotion Applied:" in str(priceRow):
290
                promoApplied  += int(float(priceRow.div.next_sibling.next_sibling.span.span.text.replace('Rs.','').replace(',', '')))
291
        totalPaid = subTotal        
292
        if promoApplied > 0:
293
            totalPaid -= promoApplied
294
            if shippingPrice <= promoApplied:
295
                totalPaid  += shippingPrice
15473 amit.gupta 296
 
297
        try:
298
            shipmentDivs = orderDetailsContainer.find('div', class_='shipment').findAll('div', recursive = False)
299
 
14464 amit.gupta 300
        subOrders = []
301
        merchantOrder.subOrders = subOrders
302
        i=1
15473 amit.gupta 303
        closedStatus = True
14464 amit.gupta 304
        for shipmentDiv in shipmentDivs:
305
            innerBoxes = shipmentDiv.findAll('div', recursive = False)
306
            statusDiv = innerBoxes[0]
307
            subOrderStatus = statusDiv.div.span.text.strip()
14566 amit.gupta 308
            deliverySpan = statusDiv.div.div.find_next_sibling('div').span
14464 amit.gupta 309
            productDivs = innerBoxes[-1].div.div.div.findAll('div', recursive=False)
310
            subOrders = []
311
            merchantOrder.subOrders = subOrders
312
            for i, productDiv in enumerate(productDivs):
313
                i +=1 
314
                imgDiv  = productDiv.div.div
315
                detailDiv = imgDiv.find_next_sibling('div')
316
                detailDivs = detailDiv.findAll('div', recursive=False)
317
                arr = detailDivs[0].a.text.strip().split(" of ", 1)
14465 amit.gupta 318
                (productTitle, quantity) = (arr[-1], (1 if len(arr)==1 else int(arr[0])) )
14820 amit.gupta 319
                try:
320
                    unitPrice = int(float(detailDivs[2].span.text.replace('Rs. ','').replace(',','')))
321
                except:
322
                    unitPrice = int(float(detailDivs[3].span.text.replace('Rs. ','').replace(',','')))
14464 amit.gupta 323
                amountPaid = int((unitPrice*quantity*totalPaid)/subTotal)
324
                productUrl = "http://www.amazon.in" + detailDivs[0].a.get('href')
325
                subOrder = SubOrder(productTitle, productUrl, merchantOrder.placedOn, amountPaid, MStore.ORDER_PLACED, quantity)
326
                subOrder.productCode = productUrl.split('/')[5]
327
                subOrder.unitPrice = unitPrice
14566 amit.gupta 328
                subOrder.merchantSubOrderId = str(i) + " of " + merchantOrder.merchantOrderId
14722 amit.gupta 329
                estDlvyTime = datetime.now()
14566 amit.gupta 330
                if deliverySpan is not None:
14756 amit.gupta 331
                    try:
332
                        subOrder.estimatedDeliveryDate = deliverySpan.span.text.strip()
333
                        estDate = subOrder.estimatedDeliveryDate.split("-")[0].strip()
334
                        subOrder.estimatedDeliveryInt = int(time.mktime((datetime.strptime(estDate, "%A %d %B %Y")).timetuple()))
335
                        estDlvyTime = datetime.strptime(estDate, "%A %d %B %Y")
336
                    except:
15473 amit.gupta 337
                        if "Delivered on" in deliverySpan.text:
338
                            subOrder.deliveredOn = deliverySpan.text.split(":")[1].strip() 
14756 amit.gupta 339
                        subOrder.estimatedDeliveryDate = "Not available"
15473 amit.gupta 340
 
14722 amit.gupta 341
                createdOn = datetime.fromtimestamp(merchantOrder.createdOnInt)
14756 amit.gupta 342
                subOrder.trackAfter = int(time.mktime(max(estDlvyTime-timedelta(days=4),createdOn + timedelta(days=3)).timetuple()))
14464 amit.gupta 343
                subOrder.detailedStatus = subOrderStatus
344
                subOrder.deliveryCharges = shippingPrice
14466 amit.gupta 345
                subOrder.imgUrl = imgDiv.img["src"]
14464 amit.gupta 346
                (cashbackAmount, percentage) = self.getCashbackAmount(subOrder.productCode, amountPaid)
15346 amit.gupta 347
                dealRank = getDealRank(subOrder.productCode, self.store_id, merchantOrder.userId)
348
                subOrder.dealRank = dealRank.get('rank')
349
                subOrder.rankDesc = dealRank.get('description')
14464 amit.gupta 350
                cashbackStatus = Store.CB_PENDING
351
                if cashbackAmount <= 0:
352
                    cashbackStatus = Store.CB_NA
353
                subOrder.cashBackStatus = cashbackStatus
354
                subOrder.cashBackAmount = cashbackAmount
355
                if percentage > 0:
356
                    subOrder.cashBackPercentage = percentage
15473 amit.gupta 357
                if hasattr(subOrder, 'deliveredOn'):                               
358
                    subOrder.status = Store.ORDER_DELIVERED
359
                    subOrder.closed = True
360
                    if subOrder.cashBackStatus == Store.CB_PENDING:
361
                        subOrder.cashBackStatus = Store.CB_APPROVED
362
                elif closedStatus:
363
                    closedStatus= False
14464 amit.gupta 364
                subOrders.append(subOrder)
14698 amit.gupta 365
        merchantOrder.status='success'
15473 amit.gupta 366
        merchantOrder.closed = closedStatus
14464 amit.gupta 367
        self._updateToOrder(todict(merchantOrder))
14545 amit.gupta 368
 
369
    def parseCancelled(self, merchantOrder,soup):
14722 amit.gupta 370
        try:
371
            fonts = soup.body.findAll("table", recursive=False)[1].findAll("font")
372
            if fonts[0].text == "Important Message":
373
                if fonts[1].text=="This order has been cancelled.":
374
                    merchantOrder.closed = True
375
                    merchantOrder.status = "cancelled"
376
                    merchantOrder.requireDetail = False
377
                    self._updateToOrder(todict(merchantOrder))
378
                    return
379
                else:
380
                    raise ParseException("parseCancelled", "Found detailed status" + fonts[1].text)
14545 amit.gupta 381
            else:
382
                raise ParseException("parseCancelled", "Found detailed status" + fonts[1].text)
14722 amit.gupta 383
        except:
14549 amit.gupta 384
            orderDetails = soup.body.find(id="orderDetails")
385
            if orderDetails is not None and orderDetails.h4.text == "This order has been cancelled.":
386
                merchantOrder.closed = True
14698 amit.gupta 387
                merchantOrder.status = "cancelled"
14549 amit.gupta 388
                merchantOrder.requireDetail = False
389
                self._updateToOrder(todict(merchantOrder))
390
            else:
391
                raise ParseException("parseCancelled", "Found detailed status" + fonts[1].text)
14464 amit.gupta 392
 
13868 amit.gupta 393
    def getTrackingUrls(self, userId):
14074 amit.gupta 394
 
395
        missingOrderUrls = []
396
        missingOrders = self._getMissingOrders({'userId':userId})
397
        for missingOrder in missingOrders:
398
            missingOrderUrls.append(ORDER_REDIRECT_URL%(missingOrder['merchantOrderId']))
14683 amit.gupta 399
        orders = self._getActiveOrders({'userId':userId, "subOrders.trackingUrl":{"$exists":False} })
13882 amit.gupta 400
        count = len(orders)
13879 amit.gupta 401
        print "count", count
14948 amit.gupta 402
        print "Missing Urls"
403
        print "*************"
404
        print missingOrderUrls
13868 amit.gupta 405
        if count > 0:
14684 amit.gupta 406
            return missingOrderUrls + ['https://www.amazon.in/gp/css/order-history', 'https://www.amazon.in/gp/css/order-history/?orderFilter=cancelled', 'https://www.amazon.in/gp/css/order-history/?orderFilter=cancelled&startIndex=10']
13959 amit.gupta 407
        else: 
14074 amit.gupta 408
            return missingOrderUrls
13927 amit.gupta 409
 
410
    def trackOrdersForUser(self, userId, url, rawHtml):
14985 amit.gupta 411
        directory = "/AmazonTrack/User" + str(userId)
14285 amit.gupta 412
        if not os.path.exists(directory):
413
            os.makedirs(directory)
14173 amit.gupta 414
 
14945 amit.gupta 415
 
13995 amit.gupta 416
        try:
417
            searchMap = {'userId':userId}
418
            collectionMap = {'merchantOrderId':1}
419
            activeOrders = self._getActiveOrders(searchMap, collectionMap)
14033 amit.gupta 420
            datetimeNow = datetime.now()
421
            timestamp = int(time.mktime(datetimeNow.timetuple()))
14009 amit.gupta 422
            print "url----------------", url
14008 amit.gupta 423
 
14320 amit.gupta 424
            if url == 'https://www.amazon.in/gp/css/order-history' or 'https://www.amazon.in/gp/css/order-history/?orderFilter=cancelled' in url:
14945 amit.gupta 425
                if url == 'https://www.amazon.in/gp/css/order-history':
426
                    filename = directory + "/orderSummary" + datetime.strftime(datetime.now(), '%d-%m:%H:%M:%S')
427
                else:   
428
                    filename = directory + "/cancelledSummary" + datetime.strftime(datetime.now(), '%d-%m:%H:%M:%S')   
429
                f = open(filename,'w')
430
                f.write(rawHtml) # python will convert \n to os.linesep
431
                f.close() # you can omit in most cases as the destructor will call if
13995 amit.gupta 432
                soup = BeautifulSoup(rawHtml)
433
                allOrders = soup.find(id="ordersContainer").findAll('div', {'class':'a-box-group a-spacing-base order'})
434
                bulk = self.db.merchantOrder.initialize_ordered_bulk_op()
435
                for activeOrder in activeOrders:
436
                    for orderEle in allOrders:
437
                        orderdiv = orderEle.find('div', {'class':'a-box a-color-offset-background order-info'}).find('div', {'class':'a-fixed-right-grid-col actions a-col-right'})
438
                        merchantOrderId = orderdiv.find('span', {'class':'a-color-secondary value'}).text.strip()
439
                        if merchantOrderId==activeOrder['merchantOrderId']:
440
                            closed = True
441
                            shipments = orderEle.findAll('div',{'class':re.compile('.*?a-box.*?')}, recursive=False)
442
                            shipments.pop(0)
443
                            for shipment in shipments:
444
                                shipdiv = shipment.find('div', {'class':'a-box-inner'})
14050 amit.gupta 445
                                sdivs = shipment.div.div.findAll('div', recursive=False)
14065 amit.gupta 446
                                orderStatus = sdivs[0].span.text.strip()
14050 amit.gupta 447
                                status = self._getStatusFromDetailedStatus(orderStatus)
448
                                if status == MStore.ORDER_DELIVERED:
14299 amit.gupta 449
                                    deliveredOn = sdivs[0].findAll('span')[-1].text.strip()
14962 amit.gupta 450
                                    try:
451
                                        deliveredOn = deliveredOn.split(":")[1].strip()
452
                                    except:
453
                                        deliveredOn = "" 
14335 amit.gupta 454
                                deliveryestimatespan = sdivs[0].find('span', {'class':'a-color-success'})
455
                                deliveryEstimate = None
456
                                if deliveryestimatespan is not None:
457
                                    deliveryEstimate = deliveryestimatespan.find('span', {'class':'a-text-bold'}).text.strip()
458
                                productDivs = shipdiv.find('div', {'class':re.compile('.*?a-spacing-top-medium.*?')}).find('div', {'class':'a-row'}).findAll('div', recursive=False)
13995 amit.gupta 459
                                trackingUrl = None
460
                                for buttonDiv in shipdiv.findAll('span', {'class':'a-button-inner'}):
461
                                    if buttonDiv.find('a').text.strip()=='Track package':
462
                                        trackingUrl = buttonDiv.find('a')['href'].strip()
463
                                        if not trackingUrl.startswith("http"):
14608 amit.gupta 464
                                            trackingUrl = "http://www.amazon.in" + trackingUrl
13995 amit.gupta 465
                                        break
466
                                for prodDiv in productDivs:
467
                                    prodDiv.find('div', {'class':'a-fixed-left-grid-inner'})
468
                                    productTitle = prodDiv.find('div', {'class':'a-fixed-left-grid-inner'}).find("div", {'class':'a-row'}).find('a').text.strip()
469
                                    imgUrl = prodDiv.find("img")["src"]
470
                                    for subOrder in activeOrder['subOrders']:
471
                                        if subOrder['productTitle'] == productTitle:
472
                                            findMap = {"orderId": activeOrder['orderId'], "subOrders.merchantSubOrderId": subOrder.get("merchantSubOrderId")}
473
                                            updateMap = {}
474
                                            closedStatus = False
475
                                            updateMap['subOrders.$.imgUrl'] = imgUrl
14033 amit.gupta 476
                                            updateMap['subOrders.$.lastTracked'] = timestamp
13995 amit.gupta 477
                                            updateMap['subOrders.$.detailedStatus'] = orderStatus
478
                                            cashbackStatus = subOrder.get("cashBackStatus")
479
                                            updateMap['subOrders.$.status'] = status 
480
 
481
                                            if status==MStore.ORDER_DELIVERED:                               
14291 amit.gupta 482
                                                updateMap['subOrders.$.deliveredOn'] = deliveredOn
13995 amit.gupta 483
                                                closedStatus = True
484
                                                updateMap['subOrders.$.closed'] = True
485
                                                if cashbackStatus == Store.CB_PENDING:
14607 amit.gupta 486
                                                    updateMap['subOrders.$.cashBackStatus'] = Store.CB_APPROVED
13995 amit.gupta 487
                                            if status==MStore.ORDER_CANCELLED:     
488
                                                closedStatus = True
489
                                                updateMap['subOrders.$.closed'] = True
490
                                                if cashbackStatus == Store.CB_PENDING:
491
                                                    updateMap['subOrders.$.cashBackStatus'] = Store.CB_CANCELLED
492
                                            if status==MStore.ORDER_SHIPPED:   
493
                                                updateMap['subOrders.$.estimatedDeliveryDate'] = deliveryEstimate
494
                                                if trackingUrl is not None:
495
                                                    updateMap['subOrders.$.trackingUrl'] = trackingUrl
496
                                            if not closedStatus:
497
                                                closed = False
498
                                            bulk.find(findMap).update({'$set' : updateMap})
499
                                            break
500
                            bulk.find({'orderId': activeOrder['orderId']}).update({'$set':{'closed': closed}})            
14080 amit.gupta 501
                bulk.execute()
502
                return 'PARSED_SUCCESS'
503
            else:
14086 amit.gupta 504
                merchantOrderId = re.findall(r'https://www.amazon.in/gp/css/summary/edit.html\?orderID=(.*)?', url, re.IGNORECASE)[0] 
14085 amit.gupta 505
                merchantOrder = self.db.merchantOrder.find_one({"merchantOrderId":merchantOrderId})
14945 amit.gupta 506
 
507
                filename = directory + "/" + merchantOrderId   
508
                f = open(filename,'w')
509
                f.write(rawHtml) # python will convert \n to os.linesep
510
                f.close() # you can omit in most cases as the destructor will call if
511
                self.parseOrderRawHtml(merchantOrder['orderId'], merchantOrder['subTagId'], merchantOrder['userId'], rawHtml, url, True)['result']
14080 amit.gupta 512
                return 'PARSED_SUCCESS'
513
                pass
14008 amit.gupta 514
            return 'PARSED_SUCCESS_NO_ORDERS'
13995 amit.gupta 515
        except:
516
            traceback.print_exc()    
517
            return 'PARSED_FAILED'
518
 
519
    def _getStatusFromDetailedStatus(self, detailedStatus):
14061 amit.gupta 520
        if "ordered from" in detailedStatus.lower():
521
            return MStore.ORDER_PLACED 
522
 
13995 amit.gupta 523
        for key, value in self.orderStatusRegexMap.iteritems():
14032 amit.gupta 524
            if detailedStatus.lower() in value:
13995 amit.gupta 525
                return key
526
 
14676 amit.gupta 527
        print "Detailed Status need to be mapped", "Store:", self.store_id
13995 amit.gupta 528
        raise ParseException("_getStatusFromDetailedStatus", "Found new order status" + detailedStatus)
14624 amit.gupta 529
    def scrapeAffiliate(self, startDate=None, endDate=None):
14650 amit.gupta 530
        br = getBrowserObject()
531
        br.add_password('https://assoc-datafeeds-eu.amazon.com', 'Saholic', 'Fnubyvp')
532
        url = AMAZON_AFF_URL
533
        response = br.open(url)
534
        #get data for past 40 days and store it to mongo
535
        dt = datetime.now()
14701 amit.gupta 536
        dat = dt - timedelta(days=2)
14651 amit.gupta 537
        url = AMAZON_AFF_FILE_URL%(datetime.strftime(dat, "%Y%m%d"))
538
        response = br.open(url)
539
        page = gzip.GzipFile(fileobj=response, mode='rb').read()
540
        j=-1
541
        for row in page.split("\n"):
542
            j += 1
543
            if j== 0 or j==1:
544
                continue
545
            fields = row.split("\t")
546
            if len(fields)>1:
547
                print fields
548
                amazonAffiliate = AmazonAffiliateInfo(fields[0], fields[1], fields[2], fields[3], fields[4], fields[5], fields[6], fields[7], fields[8], fields[9])
549
                print amazonAffiliate
550
                self.db.amazonAffiliateInfo.insert(todict(amazonAffiliate))
551
            else:
552
                break
14650 amit.gupta 553
 
14608 amit.gupta 554
 
14749 amit.gupta 555
    def parseTrackingUrl(self, trackingUrl):
14624 amit.gupta 556
        subOrder = {}
14749 amit.gupta 557
        page = fetchResponseUsingProxy(trackingUrl)
14624 amit.gupta 558
        soup = BeautifulSoup(page)
559
        alertContainer = soup.find("div", {"class":"a-box-inner a-alert-container"})
560
        if alertContainer is not None:
561
            statusText = alertContainer.h4.span.text
562
            detailedStatus = statusText.split(":")[0].strip()
563
            subOrder['detailedStatus'] = detailedStatus
564
            if detailedStatus.lower() == "in transit":
565
                pass
566
            elif detailedStatus.lower() == "undeliverable":
567
                subOrder['status'] = MStore.ORDER_CANCELLED
568
                return subOrder
569
        else:
570
            summaryLeft = soup.find(id="summaryLeft")
571
            statusText = summaryLeft.h2.text
572
            detailedStatus = statusText.split(":")[0].strip()
573
            subOrder['detailedStatus'] = detailedStatus
574
            if detailedStatus.lower() == "delivered":
575
                subOrder['deliveredOn'] = summaryLeft.findAll("span")[-2].text.strip()
576
                subOrder['status'] = MStore.ORDER_DELIVERED
577
                return subOrder
578
            else:
579
                subOrder['expectedDelivery'] = summaryLeft.findAll("span")[-1].text.strip()
580
        return subOrder
581
 
582
 
583
 
14608 amit.gupta 584
 
585
 
13927 amit.gupta 586
 
587
 
13774 amit.gupta 588
def main():
15346 amit.gupta 589
    #str1 = readSSh("/AmazonTrack/User533/403-3748792-1516356")
15046 amit.gupta 590
    #readSSh("/tmp/User2/404-2225153-7073122")
14962 amit.gupta 591
 
15056 amit.gupta 592
    store = getStore(1)
14756 amit.gupta 593
    #store.scrapeStoreOrders()
14650 amit.gupta 594
#    br = mechanize.Browser()
595
#    br.addheaders = [('User-agent','Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11'),
596
#                     ('Accept', 'text/html,application/xhtml+xml,application/json,application/xml;q=0.9,*/*;q=0.8'),
597
#                     ('Accept-Encoding', 'gzip,deflate,sdch'),                  
598
#                     ('Accept-Language', 'en-US,en;q=0.8'),                     
599
#                     ('Accept-Charset', 'ISO-8859-1,utf-8;q=0.7,*;q=0.3')]
600
#    store.scrapeStoreOrders()
15473 amit.gupta 601
    #store.parseOrderRawHtml(4333, "13232", 14, readSSh("/tmp/4333"), "https://www.amazon.in/gp/buy/thankyou/handlers/display.html?ie=UTF8&from=Visa&fromAnywhere=1&isFromThirdParty=1&purchaseId=404-9350243-7228362&processorId=eJxzSSxJdE4szgAADOkC%2Bg%3D%3D")
602
    store.trackOrdersForUser(1306, "https://www.amazon.in/gp/css/summary/edit.html?orderID=171-0886591-1480333", readSSh("/AmazonTrack/User91/171-0886591-1480333"))
14813 amit.gupta 603
    #readSSh("/tmp/User211/2015-04-12 10:32:41.905765")
14703 amit.gupta 604
    #store.scrapeAffiliate()
14162 amit.gupta 605
def readSSh(fileName):
606
    try:
15046 amit.gupta 607
        str1 = open(fileName).read()
608
        return str1
14162 amit.gupta 609
    except:
610
        ssh_client = SSHClient()
611
        str1 = ""
612
        ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
15056 amit.gupta 613
        ssh_client.connect('dtr', 22, 'root', 'ecip$dtrMay2014')
14162 amit.gupta 614
        sftp_client = ssh_client.open_sftp()
615
        try:
14299 amit.gupta 616
            if not os.path.exists(os.path.dirname(fileName)):
617
                os.makedirs(os.path.dirname(fileName))
14162 amit.gupta 618
            sftp_client.get(fileName, fileName)
619
            try:
620
                str1 = open(fileName).read()
621
                return str1
622
            finally:
623
                pass
624
        except:
625
            "could not read"
626
        return str1
13774 amit.gupta 627
 
628
 
629
if __name__ == '__main__':
14284 amit.gupta 630
        main()