Subversion Repositories SmartDukaan

Rev

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

Rev Author Line No. Line
14220 amit.gupta 1
'''
2
Created on Jan 15, 2015
3
 
4
@author: amit
5
'''
6
from BeautifulSoup import BeautifulSoup
7
from bson.binary import Binary
8
from datetime import datetime, date, timedelta
9
from dtr import main
10
from dtr.config import PythonPropertyReader
11
from dtr.dao import AffiliateInfo, Order, SubOrder
12
from dtr.main import getBrowserObject, ScrapeException, getStore, ParseException, \
13
    Store as MStore, ungzipResponse, tprint
14
from pprint import pprint
15
from pymongo import MongoClient
16
import json
17
import pymongo
18
import re
19
import traceback
20
import urllib
21
import urllib2
22
 
14222 amit.gupta 23
ORDERSTATUS  = {"PAYMENT_PENDING" : 0,
24
"PAYMENT_FAILED" : 1,
25
"COD_VERIFICATION_PENDING" : 2,
26
"SUBMITTED_FOR_PROCESSING" : 3,
27
"ACCEPTED" : 4,
28
"INVENTORY_LOW" : 5,
29
"REJECTED" : 6,
30
"BILLED" : 7,
31
"PAYMENT_FLAGGED" : 8,
32
"SHIPPED_FROM_WH" : 9,
33
"SHIPPED_TO_LOGST" : 10,
34
"PAYMENT_FLAGGED_DENIED" : 11,
35
"DELIVERY_SUCCESS" : 12,
36
"CANCEL_REQUEST_RECEIVED" : 13,
37
"CANCEL_REQUEST_CONFIRMED" : 14,
38
"CANCELLED_ON_CUSTOMER_REQUEST" : 15,
39
"SHIPPED_TO_DESTINATION_CITY" : 16,
40
"REACHED_DESTINATION_CITY" : 17,
41
"COD_VERIFICATION_FAILED" : 18,
42
"FAILED" : 19,
43
"RTO_IN_TRANSIT" : 20,
44
"RTO_RECEIVED_PRESTINE" : 21,
45
"DOA_PICKUP_REQUEST_RAISED" : 22,
46
"DOA_PICKUP_CONFIRMED" : 23,
47
"DOA_RETURN_IN_TRANSIT" : 24,
48
"DOA_RECEIVED_PRESTINE" : 25,
49
"DOA_CERT_INVALID" : 26,
50
"DOA_CERT_VALID" : 27,
51
"RTO_RESHIPPED" : 28,
52
"DOA_INVALID_RESHIPPED" : 29,
53
"DOA_VALID_RESHIPPED" : 30,
54
"RTO_REFUNDED" : 31,
55
"DOA_VALID_REFUNDED" : 32,
56
"DOA_INVALID_REFUNDED" : 33,
57
"CANCELLED_DUE_TO_LOW_INVENTORY" : 34,
58
"LOW_INV_PO_RAISED" : 35,
59
"LOW_INV_REVERSAL_IN_PROCESS" : 36,
60
"LOW_INV_NOT_AVAILABLE_AT_HOTSPOT" : 37,
61
"LOW_INV_PO_RAISED_TIMEOUT" : 38,
62
"LOW_INV_REVERSAL_TIMEOUT" : 39,
63
"FIRST_DELIVERY_ATTEMPT_MADE" : 40,
64
"CAPTURE_IN_PROCESS" : 41,
65
"DOA_REQUEST_RECEIVED" : 42,
66
"DOA_REQUEST_AUTHORIZED" : 43,
67
"DOA_PICKUP_DENIED" : 44,
68
"DOA_RECEIVED_DAMAGED" : 45,
69
"DOA_LOST_IN_TRANSIT" : 46,
70
"DOA_RESHIPPED_RCVD_DAMAGED" : 47,
71
"DOA_REFUNDED_RCVD_DAMAGED" : 48,
72
"DOA_RESHIPPED_LOST_IN_TRANSIT" : 49,
73
"DOA_REFUNDED_LOST_IN_TRANSIT" : 50,
74
"RTO_RECEIVED_DAMAGED" : 51,
75
"RTO_LOST_IN_TRANSIT" : 52,
76
"RTO_DAMAGED_RESHIPPED" : 53,
77
"RTO_DAMAGED_REFUNDED" : 54,
78
"RTO_LOST_IN_TRANSIT_RESHIPPED" : 55,
79
"RTO_LOST_IN_TRANSIT_REFUNDED" : 56,
80
"RTO_INVENTORY_REVERSED" : 57,
81
"RET_REQUEST_RECEIVED" : 58,
82
"RET_REQUEST_AUTHORIZED" : 59,
83
"RET_PICKUP_REQUEST_RAISED" : 60,
84
"RET_PICKUP_DENIED" : 61,
85
"RET_PICKUP_CONFIRMED" : 62,
86
"RET_RETURN_IN_TRANSIT" : 63,
87
"RET_RECEIVED_PRESTINE" : 64,
88
"RET_RECEIVED_DAMAGED" : 65,
89
"RET_LOST_IN_TRANSIT" : 66,
90
"RET_PRODUCT_USABLE" : 67,
91
"RET_PRODUCT_UNUSABLE" : 68,
92
"RET_PRODUCT_USABLE_RESHIPPED" : 69,
93
"RET_PRODUCT_USABLE_REFUNDED" : 70,
94
"RET_PRODUCT_UNUSABLE_RESHIPPED" : 71,
95
"RET_PRODUCT_UNUSABLE_REFUNDED" : 72,
96
"RET_RESHIPPED_RCVD_DAMAGED" : 73,
97
"RET_REFUNDED_RCVD_DAMAGED" : 74,
98
"RET_RESHIPPED_LOST_IN_TRANSIT" : 75,
99
"RET_REFUNDED_LOST_IN_TRANSIT" : 76,
100
"LOST_IN_TRANSIT" : 77,
101
"LOST_IN_TRANSIT_RESHIPPED" : 78,
102
"LOST_IN_TRANSIT_REFUNDED" : 79,
103
"DELIVERED_AT_STORE" : 80,
104
"RECEIVED_AT_STORE" : 81}
14220 amit.gupta 105
headers = { 
106
           'User-agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11',
107
            'Accept' : 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',      
108
            'Accept-Language' : 'en-US,en;q=0.8',                     
109
            'Accept-Charset' : 'ISO-8859-1,utf-8;q=0.7,*;q=0.3'
110
        }
111
SAHOLIC_ORDER_URL=PythonPropertyReader.getConfig('SAHOLIC_ORDER_URL')
14246 amit.gupta 112
SAHOLIC_ORDER_URL_TR=PythonPropertyReader.getConfig('SAHOLIC_ORDER_URL_TR')
14220 amit.gupta 113
class Store(MStore):
114
    '''
115
    This is to map order statuses of our system to order statuses of snapdeal.
116
    And our statuses will change accordingly.
117
 
118
    '''
119
    OrderStatusMap = {
120
                      MStore.ORDER_PLACED : [2,3,4,5,6,7,8,13],
121
                      MStore.ORDER_DELIVERED : [12],
122
                      MStore.ORDER_SHIPPED : [9,10,16,17,20,21,81,80],
123
                      MStore.ORDER_CANCELLED : [6,11,14,15,18,19,31,28,53,54,55,56]
124
                      }
125
 
126
 
127
    def parseOrderRawHtml(self, orderId, subTagId, userId, rawHtml, orderSuccessUrl):
14227 amit.gupta 128
        resp = {}
14237 amit.gupta 129
        paymentId = int(re.findall(r'=(.*)?',orderSuccessUrl)[0])
14220 amit.gupta 130
        orderRequest = urllib2.Request(SAHOLIC_ORDER_URL %(paymentId), headers=headers)
131
        try:
132
            response = urllib2.urlopen(orderRequest).read()
133
            response = json.loads(response)['response']
134
            payment = response['payment']
14246 amit.gupta 135
            subOrders = []
14220 amit.gupta 136
            orders = response['orders']
14228 amit.gupta 137
            items = response['itemsMap']
14220 amit.gupta 138
            merchantOrder = Order(orderId, userId, subTagId, self.store_id, orderSuccessUrl)
139
            merchantOrder.merchantOrderId = payment['merchantTxnId']
140
            merchantOrder.paidAmount = payment['amount']
14246 amit.gupta 141
 
14220 amit.gupta 142
            for o in orders:
14246 amit.gupta 143
                subOrders.append(self.createSubOrder(o, items))
14247 amit.gupta 144
            merchantOrder.subOrders = subOrders
14266 amit.gupta 145
            merchantOrder.placedOn = merchantOrder.subOrders[0].placedOn
14246 amit.gupta 146
            s = todict(merchantOrder)
147
            s['sUserId'] = orders[0]['customer_id']
14267 amit.gupta 148
            if self._saveToOrder(s):
149
                resp['result'] = 'ORDER_CREATED'
150
            else:
151
                #Order already created
14312 amit.gupta 152
                resp['result'] = 'ORDER_ALREADY_CREATED_IGNORED'
14220 amit.gupta 153
        except:
14227 amit.gupta 154
            traceback.print_exc()
14312 amit.gupta 155
            resp['result'] = 'ORDER_NOT_CREATED'
14227 amit.gupta 156
        return resp
14246 amit.gupta 157
 
158
    def createSubOrder(self, order, items):
159
            lineitem = order['lineitems'][0]
160
 
161
            item = items[str(lineitem['item_id'])]
162
            brand = lineitem.get('brand')
163
            modelNumber = lineitem.get('model_number')
164
            modelName = lineitem.get('model_name')
165
            color = lineitem.get('color')
166
            productTitle = brand + (" " + modelName if modelName else "") + (" "  + modelNumber if modelNumber is not None else "") + ("(" + color +")" if color else "")
167
            amountPaid = order['total_amount']- order['gvAmount']
168
            subOrder = SubOrder(productTitle, None, datetime.strftime(datetime.fromtimestamp(order['created_timestamp']/1000),"%d %B %Y"), amountPaid)
169
            subOrder.merchantSubOrderId = str(order['id'])
170
            subOrder.orderDetailUrl = "http://m.saholic.com/order/" + subOrder.merchantSubOrderId 
171
 
172
            subOrder.estimatedDeliveryDate = datetime.strftime(datetime.fromtimestamp(order['promised_delivery_time']/1000),"%d %B %Y")
173
            subOrder.imgUrl = item['imgUrl'] 
174
            subOrder.productUrl = "http://m.saholic.com/" + item['url']
14301 amit.gupta 175
            subOrder.productCode = item['url'].split('-')[-1]
14246 amit.gupta 176
            subOrder.detailedStatus = order['statusDescription']
177
            (cashbackAmount, percentage) = self.getCashbackAmount(subOrder.productCode, amountPaid)
178
            cashbackStatus = Store.CB_PENDING
179
            if cashbackAmount <= 0:
180
                cashbackStatus = Store.CB_NA
181
            subOrder.cashBackStatus = cashbackStatus
182
            subOrder.cashBackAmount = cashbackAmount
183
            if percentage > 0:
184
                subOrder.cashBackPercentage = percentage
185
            return subOrder
14220 amit.gupta 186
    def _getStatusFromDetailedStatus(self, detailedStatus):
187
        for key, value in Store.OrderStatusMap.iteritems():
188
            if detailedStatus in value:
189
                return key
14349 amit.gupta 190
        print "Detailed Status need to be mapped", detailedStatus
14220 amit.gupta 191
        raise ParseException("_getStatusFromDetailedStatus", "Found new order status" + detailedStatus)
192
 
193
 
194
    def scrapeStoreOrders(self,):
14278 amit.gupta 195
        trs = self._getActiveOrders(collectionMap={'merchantOrderId':1, 'sUserId':1})
14267 amit.gupta 196
        bulk = self.db.merchantOrder.initialize_ordered_bulk_op()
14246 amit.gupta 197
        for tr in trs:
198
            try:
199
                orderRequest = urllib2.Request(SAHOLIC_ORDER_URL_TR %(tr['merchantOrderId'], tr['sUserId']), headers=headers)
200
                response = urllib2.urlopen(orderRequest).read()
14275 amit.gupta 201
                print response
14246 amit.gupta 202
                response = json.loads(response)['response']
203
                items = response['itemsMap']
204
                orders = response['orders']
205
                closed = True
206
                for order in orders:
14272 amit.gupta 207
                    print "orderid---", order['id']
14269 amit.gupta 208
                    orderId = str(order['id'])
209
                    subOrder = self._isSubOrderActive(tr, orderId)
14246 amit.gupta 210
                    if subOrder:
211
                        if subOrder['closed']:
212
                            continue
213
                        else:
14270 amit.gupta 214
                            findMap = {"orderId": tr['orderId'], "subOrders.merchantSubOrderId": orderId}
14246 amit.gupta 215
                            updateMap = {}
216
                            updateMap["subOrders.$.detailedStatus"] = order['statusDescription']
217
                            status = self._getStatusFromDetailedStatus(ORDERSTATUS[order['status']]) 
218
                            closedStatus = status in [Store.ORDER_DELIVERED, Store.ORDER_CANCELLED]
14271 amit.gupta 219
                            print "status---", status, order['status']
14246 amit.gupta 220
                            updateMap["subOrders.$.status"] = status
221
                            if closedStatus:
222
                                #if status is closed then change the paybackStatus accordingly
223
                                updateMap["subOrders.$.closed"] = True
224
                                if status == Store.ORDER_DELIVERED:
225
                                    deliveredOn = datetime.strftime(datetime.fromtimestamp(order['delivery_timestamp']/1000),"%A %d %B %Y")
226
                                    updateMap['subOrders.$.deliveredOn'] = deliveredOn
227
                                    if subOrder.get("cashBackStatus") == Store.CB_PENDING:
228
                                        updateMap["subOrders.$.cashBackStatus"] = Store.CB_APPROVED
229
                                elif status == Store.ORDER_CANCELLED:
230
                                    if subOrder.get("cashBackStatus") == Store.CB_PENDING:
231
                                        updateMap["subOrders.$.cashBackStatus"] = Store.CB_CANCELLED
232
                            else:
233
                                expectedDelivery = datetime.strftime(datetime.fromtimestamp(order['promised_delivery_time']/1000),"%A %d %B %Y")
234
                                updateMap["subOrders.$.estimatedDeliveryDate"] = expectedDelivery
235
                                closed = False
236
                            bulk.find(findMap).update({'$set' : updateMap})
237
                    else:
238
                        subOrder = self.parseSubOrder(order, items)
14269 amit.gupta 239
                        self.db.merchantOrder.update({"orderId":tr['orderId']},{'$push':{"subOrders":todict(subOrder)}})
14246 amit.gupta 240
                        print "Added new suborder with subOrder Id:", subOrder.merchantSubOrderId
241
                        closed = False
14283 amit.gupta 242
                bulk.find({"orderId":tr['orderId']}).update({'$set' : {'closed':closed}})
14246 amit.gupta 243
            except:
14277 amit.gupta 244
                traceback.print_exc()
14267 amit.gupta 245
            try:
246
                bulk.execute()
247
            except:
14277 amit.gupta 248
                traceback.print_exc()
14246 amit.gupta 249
 
250
 
251
 
14220 amit.gupta 252
 
253
    def _saveToAffiliate(self, offers):
254
        if offers is None or len(offers)==0:
255
            print "no affiliate have been pushed"
256
            return
257
        collection = self.db.snapdealOrderAffiliateInfo
258
        try:
259
            collection.insert(offers,continue_on_error=True)
260
        except pymongo.errors.DuplicateKeyError as e:
261
            print e.details
262
 
263
 
264
    def covertToObj(self,offer):
265
        offerData = offer['Stat']
266
        offer1 = AffiliateInfo(offerData['affiliate_info1'], self.store_id, offerData['conversion_status'], offerData['ad_id'], 
267
                              offerData['datetime'], offerData['payout'], offer['Offer']['name'], offerData['ip'], offerData['conversion_sale_amount'])
268
 
269
        return offer1
270
def getPostData(token, page = 1, limit= 20, startDate=None, endDate=None):
271
    endDate=date.today() + timedelta(days=1)
272
    startDate=endDate - timedelta(days=31)
273
 
274
    parameters = (
275
        ("page",str(page)),
276
        ("limit",str(limit)),
277
        ("fields[]","Stat.offer_id"),
278
        ("fields[]","Stat.datetime"),
279
        ("fields[]","Offer.name"),
280
        ("fields[]","Stat.conversion_status"),
281
        ("fields[]","Stat.conversion_sale_amount"),
282
        ("fields[]","Stat.payout"),
283
        ("fields[]","Stat.ip"),
284
        ("fields[]","Stat.ad_id"),
285
        ("fields[]","Stat.affiliate_info1"),
286
        ("sort[Stat.datetime]","desc"),
287
        ("filters[Stat.date][conditional]","BETWEEN"),
288
        ("filters[Stat.date][values][]",startDate.strftime('%Y-%m-%d')),
289
        ("filters[Stat.date][values][]",endDate.strftime('%Y-%m-%d')),
290
        ("data_start",startDate.strftime('%Y-%m-%d')),
291
        ("data_end",endDate.strftime('%Y-%m-%d')),
292
        ("Method","getConversions"),
293
        ("NetworkId","jasper"),
294
        ("SessionToken",token),
295
    )
296
    #Encode the parameters
297
    return urllib.urlencode(parameters)
298
 
299
def main():
300
 
14301 amit.gupta 301
    store = getStore(4)
14220 amit.gupta 302
    #store.scrapeStoreOrders()
303
    #store._isSubOrderActive(8, "5970688907")
304
    #store.scrapeAffiliate()
14301 amit.gupta 305
    #store.parseOrderRawHtml(12345, "subtagId", 122323,  "html", 'http://www.saholic.com/pay-success?paymentId=1528903')
306
    print store.getCashbackAmount('1011378', 500)
14220 amit.gupta 307
 
308
 
309
if __name__ == '__main__':
310
    main()
311
 
312
def todict(obj, classkey=None):
313
    if isinstance(obj, dict):
314
        data = {}
315
        for (k, v) in obj.items():
316
            data[k] = todict(v, classkey)
317
        return data
318
    elif hasattr(obj, "_ast"):
319
        return todict(obj._ast())
320
    elif hasattr(obj, "__iter__"):
321
        return [todict(v, classkey) for v in obj]
322
    elif hasattr(obj, "__dict__"):
323
        data = dict([(key, todict(value, classkey)) 
324
            for key, value in obj.__dict__.iteritems() 
325
            if not callable(value) and not key.startswith('_')])
326
        if classkey is not None and hasattr(obj, "__class__"):
327
            data[classkey] = obj.__class__.__name__
328
        return data
329
    else:
330
        return obj