Subversion Repositories SmartDukaan

Rev

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