Subversion Repositories SmartDukaan

Rev

Rev 14832 | Rev 16189 | 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:
14832 amit.gupta 132
            connection = urllib2.urlopen(orderRequest)
133
            response = connection.read()
134
            connection.close()
14220 amit.gupta 135
            response = json.loads(response)['response']
136
            payment = response['payment']
14246 amit.gupta 137
            subOrders = []
14220 amit.gupta 138
            orders = response['orders']
14228 amit.gupta 139
            items = response['itemsMap']
14220 amit.gupta 140
            merchantOrder = Order(orderId, userId, subTagId, self.store_id, orderSuccessUrl)
141
            merchantOrder.merchantOrderId = payment['merchantTxnId']
142
            merchantOrder.paidAmount = payment['amount']
14246 amit.gupta 143
 
14220 amit.gupta 144
            for o in orders:
14246 amit.gupta 145
                subOrders.append(self.createSubOrder(o, items))
14247 amit.gupta 146
            merchantOrder.subOrders = subOrders
14266 amit.gupta 147
            merchantOrder.placedOn = merchantOrder.subOrders[0].placedOn
14246 amit.gupta 148
            s = todict(merchantOrder)
149
            s['sUserId'] = orders[0]['customer_id']
14267 amit.gupta 150
            if self._saveToOrder(s):
151
                resp['result'] = 'ORDER_CREATED'
152
            else:
153
                #Order already created
14312 amit.gupta 154
                resp['result'] = 'ORDER_ALREADY_CREATED_IGNORED'
14220 amit.gupta 155
        except:
14227 amit.gupta 156
            traceback.print_exc()
14312 amit.gupta 157
            resp['result'] = 'ORDER_NOT_CREATED'
14227 amit.gupta 158
        return resp
14246 amit.gupta 159
 
160
    def createSubOrder(self, order, items):
161
            lineitem = order['lineitems'][0]
162
 
163
            item = items[str(lineitem['item_id'])]
164
            brand = lineitem.get('brand')
165
            modelNumber = lineitem.get('model_number')
166
            modelName = lineitem.get('model_name')
167
            color = lineitem.get('color')
168
            productTitle = brand + (" " + modelName if modelName else "") + (" "  + modelNumber if modelNumber is not None else "") + ("(" + color +")" if color else "")
169
            amountPaid = order['total_amount']- order['gvAmount']
170
            subOrder = SubOrder(productTitle, None, datetime.strftime(datetime.fromtimestamp(order['created_timestamp']/1000),"%d %B %Y"), amountPaid)
171
            subOrder.merchantSubOrderId = str(order['id'])
172
            subOrder.orderDetailUrl = "http://m.saholic.com/order/" + subOrder.merchantSubOrderId 
173
 
174
            subOrder.estimatedDeliveryDate = datetime.strftime(datetime.fromtimestamp(order['promised_delivery_time']/1000),"%d %B %Y")
175
            subOrder.imgUrl = item['imgUrl'] 
176
            subOrder.productUrl = "http://m.saholic.com/" + item['url']
14301 amit.gupta 177
            subOrder.productCode = item['url'].split('-')[-1]
14246 amit.gupta 178
            subOrder.detailedStatus = order['statusDescription']
179
            (cashbackAmount, percentage) = self.getCashbackAmount(subOrder.productCode, amountPaid)
180
            cashbackStatus = Store.CB_PENDING
181
            if cashbackAmount <= 0:
182
                cashbackStatus = Store.CB_NA
183
            subOrder.cashBackStatus = cashbackStatus
184
            subOrder.cashBackAmount = cashbackAmount
185
            if percentage > 0:
186
                subOrder.cashBackPercentage = percentage
187
            return subOrder
14220 amit.gupta 188
    def _getStatusFromDetailedStatus(self, detailedStatus):
189
        for key, value in Store.OrderStatusMap.iteritems():
190
            if detailedStatus in value:
191
                return key
14349 amit.gupta 192
        print "Detailed Status need to be mapped", detailedStatus
14220 amit.gupta 193
        raise ParseException("_getStatusFromDetailedStatus", "Found new order status" + detailedStatus)
194
 
195
 
196
    def scrapeStoreOrders(self,):
14278 amit.gupta 197
        trs = self._getActiveOrders(collectionMap={'merchantOrderId':1, 'sUserId':1})
14267 amit.gupta 198
        bulk = self.db.merchantOrder.initialize_ordered_bulk_op()
14246 amit.gupta 199
        for tr in trs:
200
            try:
201
                orderRequest = urllib2.Request(SAHOLIC_ORDER_URL_TR %(tr['merchantOrderId'], tr['sUserId']), headers=headers)
202
                response = urllib2.urlopen(orderRequest).read()
14275 amit.gupta 203
                print response
14246 amit.gupta 204
                response = json.loads(response)['response']
205
                items = response['itemsMap']
206
                orders = response['orders']
207
                closed = True
208
                for order in orders:
14272 amit.gupta 209
                    print "orderid---", order['id']
14269 amit.gupta 210
                    orderId = str(order['id'])
211
                    subOrder = self._isSubOrderActive(tr, orderId)
14246 amit.gupta 212
                    if subOrder:
213
                        if subOrder['closed']:
214
                            continue
215
                        else:
14270 amit.gupta 216
                            findMap = {"orderId": tr['orderId'], "subOrders.merchantSubOrderId": orderId}
14246 amit.gupta 217
                            updateMap = {}
218
                            updateMap["subOrders.$.detailedStatus"] = order['statusDescription']
219
                            status = self._getStatusFromDetailedStatus(ORDERSTATUS[order['status']]) 
220
                            closedStatus = status in [Store.ORDER_DELIVERED, Store.ORDER_CANCELLED]
14271 amit.gupta 221
                            print "status---", status, order['status']
14246 amit.gupta 222
                            updateMap["subOrders.$.status"] = status
223
                            if closedStatus:
224
                                #if status is closed then change the paybackStatus accordingly
225
                                updateMap["subOrders.$.closed"] = True
226
                                if status == Store.ORDER_DELIVERED:
227
                                    deliveredOn = datetime.strftime(datetime.fromtimestamp(order['delivery_timestamp']/1000),"%A %d %B %Y")
228
                                    updateMap['subOrders.$.deliveredOn'] = deliveredOn
229
                                    if subOrder.get("cashBackStatus") == Store.CB_PENDING:
230
                                        updateMap["subOrders.$.cashBackStatus"] = Store.CB_APPROVED
231
                                elif status == Store.ORDER_CANCELLED:
232
                                    if subOrder.get("cashBackStatus") == Store.CB_PENDING:
233
                                        updateMap["subOrders.$.cashBackStatus"] = Store.CB_CANCELLED
234
                            else:
235
                                expectedDelivery = datetime.strftime(datetime.fromtimestamp(order['promised_delivery_time']/1000),"%A %d %B %Y")
236
                                updateMap["subOrders.$.estimatedDeliveryDate"] = expectedDelivery
237
                                closed = False
238
                            bulk.find(findMap).update({'$set' : updateMap})
239
                    else:
240
                        subOrder = self.parseSubOrder(order, items)
14269 amit.gupta 241
                        self.db.merchantOrder.update({"orderId":tr['orderId']},{'$push':{"subOrders":todict(subOrder)}})
14246 amit.gupta 242
                        print "Added new suborder with subOrder Id:", subOrder.merchantSubOrderId
243
                        closed = False
14283 amit.gupta 244
                bulk.find({"orderId":tr['orderId']}).update({'$set' : {'closed':closed}})
14246 amit.gupta 245
            except:
14277 amit.gupta 246
                traceback.print_exc()
14870 amit.gupta 247
        try:
248
            bulk.execute()
249
        except:
250
            traceback.print_exc()
14246 amit.gupta 251
 
252
 
253
 
14220 amit.gupta 254
 
255
    def _saveToAffiliate(self, offers):
256
        if offers is None or len(offers)==0:
257
            print "no affiliate have been pushed"
258
            return
259
        collection = self.db.snapdealOrderAffiliateInfo
260
        try:
261
            collection.insert(offers,continue_on_error=True)
262
        except pymongo.errors.DuplicateKeyError as e:
263
            print e.details
264
 
265
 
266
    def covertToObj(self,offer):
267
        offerData = offer['Stat']
268
        offer1 = AffiliateInfo(offerData['affiliate_info1'], self.store_id, offerData['conversion_status'], offerData['ad_id'], 
269
                              offerData['datetime'], offerData['payout'], offer['Offer']['name'], offerData['ip'], offerData['conversion_sale_amount'])
270
 
271
        return offer1
272
def getPostData(token, page = 1, limit= 20, startDate=None, endDate=None):
273
    endDate=date.today() + timedelta(days=1)
274
    startDate=endDate - timedelta(days=31)
275
 
276
    parameters = (
277
        ("page",str(page)),
278
        ("limit",str(limit)),
279
        ("fields[]","Stat.offer_id"),
280
        ("fields[]","Stat.datetime"),
281
        ("fields[]","Offer.name"),
282
        ("fields[]","Stat.conversion_status"),
283
        ("fields[]","Stat.conversion_sale_amount"),
284
        ("fields[]","Stat.payout"),
285
        ("fields[]","Stat.ip"),
286
        ("fields[]","Stat.ad_id"),
287
        ("fields[]","Stat.affiliate_info1"),
288
        ("sort[Stat.datetime]","desc"),
289
        ("filters[Stat.date][conditional]","BETWEEN"),
290
        ("filters[Stat.date][values][]",startDate.strftime('%Y-%m-%d')),
291
        ("filters[Stat.date][values][]",endDate.strftime('%Y-%m-%d')),
292
        ("data_start",startDate.strftime('%Y-%m-%d')),
293
        ("data_end",endDate.strftime('%Y-%m-%d')),
294
        ("Method","getConversions"),
295
        ("NetworkId","jasper"),
296
        ("SessionToken",token),
297
    )
298
    #Encode the parameters
299
    return urllib.urlencode(parameters)
300
 
301
def main():
302
 
14301 amit.gupta 303
    store = getStore(4)
14220 amit.gupta 304
    #store.scrapeStoreOrders()
305
    #store._isSubOrderActive(8, "5970688907")
306
    #store.scrapeAffiliate()
14301 amit.gupta 307
    #store.parseOrderRawHtml(12345, "subtagId", 122323,  "html", 'http://www.saholic.com/pay-success?paymentId=1528903')
308
    print store.getCashbackAmount('1011378', 500)
14220 amit.gupta 309
 
310
 
311
if __name__ == '__main__':
312
    main()
313
 
314
def todict(obj, classkey=None):
315
    if isinstance(obj, dict):
316
        data = {}
317
        for (k, v) in obj.items():
318
            data[k] = todict(v, classkey)
319
        return data
320
    elif hasattr(obj, "_ast"):
321
        return todict(obj._ast())
322
    elif hasattr(obj, "__iter__"):
323
        return [todict(v, classkey) for v in obj]
324
    elif hasattr(obj, "__dict__"):
325
        data = dict([(key, todict(value, classkey)) 
326
            for key, value in obj.__dict__.iteritems() 
327
            if not callable(value) and not key.startswith('_')])
328
        if classkey is not None and hasattr(obj, "__class__"):
329
            data[classkey] = obj.__class__.__name__
330
        return data
331
    else:
332
        return obj