Subversion Repositories SmartDukaan

Rev

Rev 15560 | Rev 15562 | 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']
515
                try:
15560 amit.gupta 516
                    order1 = session.query(OrdersRaw).filter_by(id=merchantOrder['orderId']).first()
517
                    order1.status = result
518
                    order1.rawhtml = rawHtml
15555 amit.gupta 519
                    session.commit()
15561 amit.gupta 520
                except:
521
                    traceback.print_exc()
15555 amit.gupta 522
                finally:
523
                    session.close()
14080 amit.gupta 524
                return 'PARSED_SUCCESS'
525
                pass
14008 amit.gupta 526
            return 'PARSED_SUCCESS_NO_ORDERS'
13995 amit.gupta 527
        except:
528
            traceback.print_exc()    
529
            return 'PARSED_FAILED'
530
 
531
    def _getStatusFromDetailedStatus(self, detailedStatus):
14061 amit.gupta 532
        if "ordered from" in detailedStatus.lower():
533
            return MStore.ORDER_PLACED 
534
 
13995 amit.gupta 535
        for key, value in self.orderStatusRegexMap.iteritems():
14032 amit.gupta 536
            if detailedStatus.lower() in value:
13995 amit.gupta 537
                return key
538
 
14676 amit.gupta 539
        print "Detailed Status need to be mapped", "Store:", self.store_id
13995 amit.gupta 540
        raise ParseException("_getStatusFromDetailedStatus", "Found new order status" + detailedStatus)
14624 amit.gupta 541
    def scrapeAffiliate(self, startDate=None, endDate=None):
14650 amit.gupta 542
        br = getBrowserObject()
543
        br.add_password('https://assoc-datafeeds-eu.amazon.com', 'Saholic', 'Fnubyvp')
544
        url = AMAZON_AFF_URL
545
        response = br.open(url)
546
        #get data for past 40 days and store it to mongo
547
        dt = datetime.now()
14701 amit.gupta 548
        dat = dt - timedelta(days=2)
14651 amit.gupta 549
        url = AMAZON_AFF_FILE_URL%(datetime.strftime(dat, "%Y%m%d"))
550
        response = br.open(url)
551
        page = gzip.GzipFile(fileobj=response, mode='rb').read()
552
        j=-1
553
        for row in page.split("\n"):
554
            j += 1
555
            if j== 0 or j==1:
556
                continue
557
            fields = row.split("\t")
558
            if len(fields)>1:
559
                print fields
560
                amazonAffiliate = AmazonAffiliateInfo(fields[0], fields[1], fields[2], fields[3], fields[4], fields[5], fields[6], fields[7], fields[8], fields[9])
561
                print amazonAffiliate
562
                self.db.amazonAffiliateInfo.insert(todict(amazonAffiliate))
563
            else:
564
                break
14650 amit.gupta 565
 
14608 amit.gupta 566
 
14749 amit.gupta 567
    def parseTrackingUrl(self, trackingUrl):
14624 amit.gupta 568
        subOrder = {}
14749 amit.gupta 569
        page = fetchResponseUsingProxy(trackingUrl)
14624 amit.gupta 570
        soup = BeautifulSoup(page)
571
        alertContainer = soup.find("div", {"class":"a-box-inner a-alert-container"})
572
        if alertContainer is not None:
573
            statusText = alertContainer.h4.span.text
574
            detailedStatus = statusText.split(":")[0].strip()
575
            subOrder['detailedStatus'] = detailedStatus
576
            if detailedStatus.lower() == "in transit":
577
                pass
578
            elif detailedStatus.lower() == "undeliverable":
579
                subOrder['status'] = MStore.ORDER_CANCELLED
580
                return subOrder
581
        else:
582
            summaryLeft = soup.find(id="summaryLeft")
583
            statusText = summaryLeft.h2.text
584
            detailedStatus = statusText.split(":")[0].strip()
585
            subOrder['detailedStatus'] = detailedStatus
586
            if detailedStatus.lower() == "delivered":
587
                subOrder['deliveredOn'] = summaryLeft.findAll("span")[-2].text.strip()
588
                subOrder['status'] = MStore.ORDER_DELIVERED
589
                return subOrder
590
            else:
591
                subOrder['expectedDelivery'] = summaryLeft.findAll("span")[-1].text.strip()
592
        return subOrder
593
 
594
 
595
 
14608 amit.gupta 596
 
597
 
13927 amit.gupta 598
 
599
 
13774 amit.gupta 600
def main():
15346 amit.gupta 601
    #str1 = readSSh("/AmazonTrack/User533/403-3748792-1516356")
15046 amit.gupta 602
    #readSSh("/tmp/User2/404-2225153-7073122")
14962 amit.gupta 603
 
15056 amit.gupta 604
    store = getStore(1)
14756 amit.gupta 605
    #store.scrapeStoreOrders()
14650 amit.gupta 606
#    br = mechanize.Browser()
607
#    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'),
608
#                     ('Accept', 'text/html,application/xhtml+xml,application/json,application/xml;q=0.9,*/*;q=0.8'),
609
#                     ('Accept-Encoding', 'gzip,deflate,sdch'),                  
610
#                     ('Accept-Language', 'en-US,en;q=0.8'),                     
611
#                     ('Accept-Charset', 'ISO-8859-1,utf-8;q=0.7,*;q=0.3')]
612
#    store.scrapeStoreOrders()
15555 amit.gupta 613
    #store.parseOrderRawHtml(3418, "13232", 14, readSSh("/home/amit/3418"), "https://www.amazon.in/gp/css/summary/edit.html?orderID=402-1853822-0778736")
614
    #store.trackOrdersForUser(4355, "https://www.amazon.in/gp/css/summary/edit.html?orderID=171-4824011-7090713", readSSh("~/4355"))
14813 amit.gupta 615
    #readSSh("/tmp/User211/2015-04-12 10:32:41.905765")
14703 amit.gupta 616
    #store.scrapeAffiliate()
15555 amit.gupta 617
    parseDetailNotCreated()
618
 
619
def parseDetailNotCreated():
620
    try:
621
        store=getStore(1)
622
        orders = session.query(OrdersRaw).filter_by(status='DETAIL_NOT_CREATED_UNKNOWN').all()
15558 amit.gupta 623
        session.close()
15555 amit.gupta 624
        for order in orders:
625
            store.trackOrdersForUser(order.id, order.order_url, order.rawhtml)
626
 
627
    finally:
628
        session.close()
629
 
14162 amit.gupta 630
def readSSh(fileName):
631
    try:
15046 amit.gupta 632
        str1 = open(fileName).read()
633
        return str1
14162 amit.gupta 634
    except:
635
        ssh_client = SSHClient()
636
        str1 = ""
637
        ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
15056 amit.gupta 638
        ssh_client.connect('dtr', 22, 'root', 'ecip$dtrMay2014')
14162 amit.gupta 639
        sftp_client = ssh_client.open_sftp()
640
        try:
14299 amit.gupta 641
            if not os.path.exists(os.path.dirname(fileName)):
642
                os.makedirs(os.path.dirname(fileName))
14162 amit.gupta 643
            sftp_client.get(fileName, fileName)
644
            try:
645
                str1 = open(fileName).read()
646
                return str1
647
            finally:
648
                pass
649
        except:
650
            "could not read"
651
        return str1
13774 amit.gupta 652
 
653
 
654
if __name__ == '__main__':
14284 amit.gupta 655
        main()