Subversion Repositories SmartDukaan

Rev

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