Subversion Repositories SmartDukaan

Rev

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