Subversion Repositories SmartDukaan

Rev

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