Subversion Repositories SmartDukaan

Rev

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

Rev Author Line No. Line
14811 amit.gupta 1
'''
2
Created on Apr 12, 2015
3
 
4
@author: amit
5
'''
6
from bs4 import BeautifulSoup
16391 amit.gupta 7
from datetime import datetime, timedelta
14811 amit.gupta 8
from dtr import main
16371 amit.gupta 9
from dtr.dao import Order, SubOrder
14811 amit.gupta 10
from dtr.main import getBrowserObject, getStore, ParseException, ungzipResponse, \
16371 amit.gupta 11
    Store as MStore, sourceMap, tprint, todict
16283 amit.gupta 12
from dtr.sources.amazon import readSSh
16391 amit.gupta 13
from dtr.storage.DataService import paytm_coupon_usages
16421 amit.gupta 14
from dtr.utils.utils import fetchResponseUsingProxy, find_between
16391 amit.gupta 15
from elixir import *
14811 amit.gupta 16
from pymongo.mongo_client import MongoClient
16371 amit.gupta 17
import json
16391 amit.gupta 18
import os
16371 amit.gupta 19
import traceback
14811 amit.gupta 20
 
16374 amit.gupta 21
 
14811 amit.gupta 22
class Store(MStore):
23
    OrderStatusMap = {
16382 amit.gupta 24
                      main.Store.ORDER_PLACED : ['in process', 'ready to be shipped', 'order recieved', 'order received', 'pending confirmation', 'waiting for courier pickup'],
16283 amit.gupta 25
                      main.Store.ORDER_DELIVERED : ['delivered'],
16371 amit.gupta 26
                      main.Store.ORDER_SHIPPED : ['in transit', 'shipped'],
16404 amit.gupta 27
                      main.Store.ORDER_CANCELLED : ['failed', 'payment failed', 'cancelled']
14811 amit.gupta 28
 
29
                      }
30
    def __init__(self,store_id):
31
        client = MongoClient('mongodb://localhost:27017/')
32
        self.db = client.dtr
33
        super(Store, self).__init__(store_id)
34
 
35
    def saveOrder(self, merchantOrder):
36
        MStore.saveOrder(self, merchantOrder)
16371 amit.gupta 37
 
38
    def parseTrackingUrl(self, trackingUrl):
39
        subOrder = {}
40
        page = fetchResponseUsingProxy(trackingUrl)
41
        soup = BeautifulSoup(page)
42
        subOrder['detailedStatus'] = soup.h1.text
43
        subOrder['status'] = self._getStatusFromDetailedStatus(subOrder['detailedStatus'])
14811 amit.gupta 44
 
16371 amit.gupta 45
 
14811 amit.gupta 46
    def scrapeStoreOrders(self):
16371 amit.gupta 47
        orders = self.db.merchantOrder.find({"storeId":1, "closed":False, "subOrders":{"$elemMatch":{"closed":False, "trackingUrl":{"$exists":True}}}})
48
        for merchantOrder in orders:
49
            executeBulk = False
50
            try:
51
                bulk = self.db.merchantOrder.initialize_ordered_bulk_op()
52
                closed = True
53
                map1 = {}
54
                for subOrder in merchantOrder.get("subOrders"):
55
                    if subOrder.get("closed"):
56
                        continue
57
                    elif subOrder.get("trackingUrl") is None:
58
                        closed = False
59
                        continue
60
                    executeBulk = True
61
                    findMap = {"orderId":merchantOrder.get("orderId"), "subOrders.merchantSubOrderId":subOrder.get("merchantSubOrderId")} 
62
                    trackingUrl = subOrder.get("trackingUrl")
63
                    if not map1.has_key(trackingUrl):
64
                        map1[trackingUrl] = self.parseTrackingUrl(trackingUrl)
65
                    newOrder = map1.get(trackingUrl)
66
                    updateMap = self.getUpdateMap(newOrder, subOrder.get('cashBackStatus'))
67
                    print findMap, "\n", updateMap
68
                    bulk.find(findMap).update({'$set' : updateMap})
69
                    closed = closed and newOrder['closed']
70
                if executeBulk:
71
                    bulk.find({"orderId":merchantOrder.get("orderId")}).update({"$set":{"closed":closed, "parseError":False}})
72
                    bulk.execute()
73
            except:
74
                tprint("Could not update " + str(merchantOrder['orderId']) + " For store " + self.getName())
75
                self.db.merchantOrder.update({"orderId":merchantOrder['orderId']}, {"$set":{"parseError":True}})
76
                traceback.print_exc()
14811 amit.gupta 77
 
16371 amit.gupta 78
    def getTrackingUrls(self, userId):
79
        missingOrderUrls = []
80
        #missingOrders = self._getMissingOrders({'userId':userId})
81
        #for missingOrder in missingOrders:
82
        #    missingOrderUrls.append(ORDER_REDIRECT_URL%(missingOrder['merchantOrderId']))
16382 amit.gupta 83
        orders = self._getActiveOrders({'userId':userId, "subOrders.trackingUrl":{"$exists":False} }, {"merchantOrderId":1})
16371 amit.gupta 84
        for order in orders:
16382 amit.gupta 85
            print order
16430 amit.gupta 86
            missingOrderUrls.append({"url":"https://paytm.com/shop/orderdetail/%s?actions=1&channel=web&version=2"%(order.get("merchantOrderId")), "referer":"https://paytm.com/myorders/%s"%order.get("merchantOrderId")}  )
16382 amit.gupta 87
        return missingOrderUrls
16371 amit.gupta 88
 
89
    def trackOrdersForUser(self, userId, url, rawHtml):
16434 amit.gupta 90
        merchantOrderId = find_between(url, "https://paytm.com/shop/orderdetail/","?actions=1&channel=web&version=2")
16391 amit.gupta 91
        directory = "/PaytmTrack/User" + str(userId)
92
        if not os.path.exists(directory):
93
            os.makedirs(directory)
94
 
16382 amit.gupta 95
        executeBulk = False
16391 amit.gupta 96
        filename = directory + "/" + merchantOrderId + "-" +  datetime.strftime(datetime.now(), '%d-%m:%H:%M:%S')   
97
        f = open(filename,'w')
98
        f.write(rawHtml) # python will convert \n to os.linesep
16421 amit.gupta 99
        f.close() # you can omit in most cases as the destructor will call if
16433 amit.gupta 100
        rawHtml = "".join(["{", find_between(rawHtml,">{", "}</pre>"), "}"])
16432 amit.gupta 101
        merchantOrder = self.db.merchantOrder.find_one({"merchantOrderId":merchantOrderId})
16435 amit.gupta 102
        print rawHtml
16421 amit.gupta 103
        if rawHtml == "":
16427 amit.gupta 104
            tprint("Could not update " + str(merchantOrder['orderId']) + " For store " + self.getName())
105
            self.db.merchantOrder.update({"orderId":merchantOrder['orderId']}, {"$set":{"parseError":True}})
16421 amit.gupta 106
            raise    
107
        ordermap = json.loads(rawHtml).get("order")
16388 amit.gupta 108
        try:
109
            bulk = self.db.merchantOrder.initialize_ordered_bulk_op()
110
            closed=True
111
            for item in ordermap.get("items"):
16389 amit.gupta 112
                merchantSubOrderId = str(item.get("id"))
16388 amit.gupta 113
                for subOrder in merchantOrder.get("subOrders"):
114
                    if not subOrder.get("closed"):
16435 amit.gupta 115
                        if merchantSubOrderId == subOrder.get("merchantSubOrderId"):
16388 amit.gupta 116
                            executeBulk = True
117
                            findMap = {"orderId":merchantOrder.get("orderId"), "subOrders.merchantSubOrderId":subOrder.get("merchantSubOrderId")}
118
                            newSub = {}
119
                            detailedStatus = item.get("status_text")
120
                            newSub['detailedStatus'] = detailedStatus
121
                            status  = self._getStatusFromDetailedStatus(detailedStatus)
122
                            newSub['status'] = status if status else subOrder.get("status")  
123
                            updateMap = self.getUpdateMap(newSub, subOrder.get("cashBackStatus"))
124
                            bulk.find(findMap).update({'$set' : updateMap})
125
                            closed = closed and newSub['closed']
126
                            break
127
                        else:
128
                            continue
129
            if executeBulk:
16387 amit.gupta 130
                bulk.find({"orderId":merchantOrder.get("orderId")}).update({"$set":{"closed":closed, "parseError":False}})
131
                bulk.execute()
16388 amit.gupta 132
        except:
16427 amit.gupta 133
            tprint("Could not update " + str(merchantOrder['orderId']) + " For store " + self.getName())
134
            self.db.merchantOrder.update({"orderId":merchantOrder['orderId']}, {"$set":{"parseError":True}})
135
            traceback.print_exc()
136
            raise
16371 amit.gupta 137
 
16283 amit.gupta 138
    def parseOrderRawHtml(self, orderId, subTagId, userId, rawHtml, orderSuccessUrl):
16421 amit.gupta 139
 
140
        #Expected is json
141
        orderSuccessUrl = find_between(orderSuccessUrl, "<pre>", "</pre>")
142
        if orderSuccessUrl != "": 
143
            try:
144
                resp = {}
145
                #orderSuccessUrl = "https://paytm.com/shop/orderdetail/1155961075?actions=1&channel=web&version=2"
146
                ordermap = json.loads(rawHtml).get("order")
147
                if not ordermap.get("need_shipping"):
148
                    resp['result'] = 'RECHARGE_ORDER_IGNORED'
149
                    return resp
150
                elif ordermap.get("payment_status") == "PROCESSING":
151
                    resp['result'] = 'PAYMENT_PENDING_IGNORED'
152
                    return resp
153
                order = Order(orderId, userId, subTagId, self.store_id, orderSuccessUrl)
154
                order.deliveryCharges = ordermap.get("shipping_charges") - ordermap.get("shipping_discount")
155
                order.merchantOrderId = str(ordermap.get("id"))  
156
                order.discountApplied = ordermap.get("discount_amount")
157
                order.paidAmount = ordermap.get("grandtotal")
158
                order.placedOn = datetime.strftime(getISTDate(ordermap.get("created_at")),"%d-%m-%Y %H:%M:%S") 
159
                order.requireDetail = False
160
                order.status = 'success'
161
                order.totalAmount = ordermap.get("subtotal")
162
                subOrders = []
163
                order.subOrders = subOrders
164
                coupon_code = None
165
                total_cashback = 0
166
                for item in ordermap.get("items"):
167
                    product = item.get("product")
168
                    shareUrl = product.get("seourl").replace("catalog.paytm.com/v1", "paytm.com/shop")
169
                    paytmcashback = 0
170
                    if item.get("promo_code"):
171
                        coupon_code = item.get("promo_code")
172
                        for s in item.get("promo_text").split(): 
173
                            if s.isdigit():
174
                                paytmcashback = int(s)
175
                                total_cashback += paytmcashback
176
                                break
177
                    amountPaid = item.get("subtotal") - paytmcashback 
178
                    detailedStatus = item.get("status_text")
179
                    status = self._getStatusFromDetailedStatus(detailedStatus)
180
                    if status == None:
181
                        status = MStore.ORDER_PLACED
182
                    subOrder = SubOrder(item.get("title"), item.get("product").get(""), ordermap.get("date"), amountPaid, status, item.get("quantity"))
183
                    subOrder.imgUrl = product.get("thumbnail")
184
                    subOrder.detailedStatus = detailedStatus
185
                    subOrder.productUrl = shareUrl
186
                    subOrder.productCode = product.get("url").split("?")[0].split("/")[-1]
187
                    subOrder.merchantSubOrderId = str(item.get("id"))
188
                    if status == MStore.ORDER_PLACED: 
189
                        if item.get("status_flow")[1].get("date"):
190
                            subOrder.estimatedShippingDate = datetime.strftime(getISTDate(item.get("status_flow")[1].get("date")), "%d %b")
191
                        if item.get("status_flow")[2].get("date"):
192
                            subOrder.estimatedDeliveryDate = datetime.strftime(getISTDate(item.get("status_flow")[2].get("date")), "%d %b")
193
                    else:
194
                        subOrder.closed = False
195
                    subOrders.append(subOrder)
196
                if coupon_code:
197
                    usage = paytm_coupon_usages()
198
                    usage.cashback = total_cashback
199
                    usage.coupon = coupon_code
200
                    usage.user_id = userId
201
                    usage.order_id = orderId
202
                    session.commit()
203
                self.populateDerivedFields(order)
204
                if self._saveToOrder(todict(order)):
205
                    resp['result'] = 'ORDER_CREATED'
16382 amit.gupta 206
                else:
16421 amit.gupta 207
                    resp['result'] = 'ORDER_ALREADY_CREATED_IGNORED'
208
            except:
209
                resp['result'] = 'ORDER_NOT_CREATED'
210
 
211
        else:
16382 amit.gupta 212
            resp['result'] = 'ORDER_NOT_CREATED'
16421 amit.gupta 213
        return resp
16382 amit.gupta 214
 
16371 amit.gupta 215
    def _getStatusFromDetailedStatus(self, detailedStatus):
216
        for key, value in Store.OrderStatusMap.iteritems():
217
            if detailedStatus.lower() in value:
218
                return key
16375 amit.gupta 219
        print "Detailed Status-", detailedStatus,  "need to be mapped for Store-", self.store_name
16371 amit.gupta 220
        return None
221
def getISTDate(tzString):
222
    tzDate = datetime.strptime(tzString, "%Y-%m-%dT%H:%M:%S.%fZ") 
223
    tzDate = tzDate + timedelta(0,19800)
224
    return tzDate
225
 
14811 amit.gupta 226
def main():
227
    store = getStore(6)
16283 amit.gupta 228
    #store.scrapeStoreOrders()
16435 amit.gupta 229
    store.trackOrdersForUser(2, "https://paytm.com/shop/orderdetail/1168545614?actions=1&channel=web&version=2", readSSh("/PaytmTrack/User2/1168545614-20-08:12:43:21"))
16383 amit.gupta 230
    #print store.getTrackingUrls(14)
14811 amit.gupta 231
 
232
if __name__ == '__main__':
233
    main()