Subversion Repositories SmartDukaan

Rev

Rev 18055 | Rev 18254 | 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],
16967 amit.gupta 124
                      MStore.ORDER_CANCELLED : [1,6,11,14,15,18,19,31,34,28,53,54,55,56,20,21,77,79]
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 "")
18055 amit.gupta 171
            amountPaid = order['total_amount'] 
14246 amit.gupta 172
            subOrder = SubOrder(productTitle, None, datetime.strftime(datetime.fromtimestamp(order['created_timestamp']/1000),"%d %B %Y"), amountPaid)
18055 amit.gupta 173
            subOrder.amount = amountPaid - order['gvAmount']
14246 amit.gupta 174
            subOrder.merchantSubOrderId = str(order['id'])
175
            subOrder.orderDetailUrl = "http://m.saholic.com/order/" + subOrder.merchantSubOrderId 
17677 amit.gupta 176
            subOrder.quantity = int(lineitem['quantity'])
14246 amit.gupta 177
            subOrder.estimatedDeliveryDate = datetime.strftime(datetime.fromtimestamp(order['promised_delivery_time']/1000),"%d %B %Y")
18055 amit.gupta 178
            subOrder.imgUrl = item.get("imgUrl") 
14246 amit.gupta 179
            subOrder.productUrl = "http://m.saholic.com/" + item['url']
14301 amit.gupta 180
            subOrder.productCode = item['url'].split('-')[-1]
14246 amit.gupta 181
            subOrder.detailedStatus = order['statusDescription']
17677 amit.gupta 182
            (cashbackAmount, percentage) = self.getCashbackAmount(subOrder.productCode, amountPaid/subOrder.quantity)
16189 amit.gupta 183
            dealRank = getDealRank(subOrder.productCode, self.store_id, self.userId)
184
            subOrder.dealRank = dealRank.get('rank')
185
            subOrder.rankDesc = dealRank.get('description')
16283 amit.gupta 186
            subOrder.maxNlc = dealRank.get('maxNlc')
187
            subOrder.minNlc = dealRank.get('minNlc')
188
            subOrder.db = dealRank.get('dp')
189
            subOrder.itemStatus = dealRank.get('status')
14246 amit.gupta 190
            cashbackStatus = Store.CB_PENDING
191
            if cashbackAmount <= 0:
192
                cashbackStatus = Store.CB_NA
193
            subOrder.cashBackStatus = cashbackStatus
17677 amit.gupta 194
            subOrder.cashBackAmount = cashbackAmount*subOrder.quantity
14246 amit.gupta 195
            if percentage > 0:
196
                subOrder.cashBackPercentage = percentage
197
            return subOrder
14220 amit.gupta 198
    def _getStatusFromDetailedStatus(self, detailedStatus):
199
        for key, value in Store.OrderStatusMap.iteritems():
200
            if detailedStatus in value:
201
                return key
14349 amit.gupta 202
        print "Detailed Status need to be mapped", detailedStatus
16189 amit.gupta 203
        raise ParseException("_getStatusFromDetailedStatus", "Found new order status" + str(detailedStatus))
14220 amit.gupta 204
 
205
 
206
    def scrapeStoreOrders(self,):
18085 amit.gupta 207
        trs = self._getActiveOrders(collectionMap={'merchantOrderId':1, 'sUserId':1, 'userId':1})
14267 amit.gupta 208
        bulk = self.db.merchantOrder.initialize_ordered_bulk_op()
14246 amit.gupta 209
        for tr in trs:
18085 amit.gupta 210
            self.userId = tr['userId']
14246 amit.gupta 211
            try:
212
                orderRequest = urllib2.Request(SAHOLIC_ORDER_URL_TR %(tr['merchantOrderId'], tr['sUserId']), headers=headers)
213
                response = urllib2.urlopen(orderRequest).read()
14275 amit.gupta 214
                print response
14246 amit.gupta 215
                response = json.loads(response)['response']
216
                items = response['itemsMap']
217
                orders = response['orders']
218
                closed = True
219
                for order in orders:
14272 amit.gupta 220
                    print "orderid---", order['id']
14269 amit.gupta 221
                    orderId = str(order['id'])
222
                    subOrder = self._isSubOrderActive(tr, orderId)
14246 amit.gupta 223
                    if subOrder:
224
                        if subOrder['closed']:
225
                            continue
226
                        else:
14270 amit.gupta 227
                            findMap = {"orderId": tr['orderId'], "subOrders.merchantSubOrderId": orderId}
14246 amit.gupta 228
                            updateMap = {}
229
                            updateMap["subOrders.$.detailedStatus"] = order['statusDescription']
230
                            status = self._getStatusFromDetailedStatus(ORDERSTATUS[order['status']]) 
231
                            closedStatus = status in [Store.ORDER_DELIVERED, Store.ORDER_CANCELLED]
14271 amit.gupta 232
                            print "status---", status, order['status']
14246 amit.gupta 233
                            updateMap["subOrders.$.status"] = status
234
                            if closedStatus:
235
                                #if status is closed then change the paybackStatus accordingly
236
                                updateMap["subOrders.$.closed"] = True
237
                                if status == Store.ORDER_DELIVERED:
238
                                    deliveredOn = datetime.strftime(datetime.fromtimestamp(order['delivery_timestamp']/1000),"%A %d %B %Y")
239
                                    updateMap['subOrders.$.deliveredOn'] = deliveredOn
240
                                    if subOrder.get("cashBackStatus") == Store.CB_PENDING:
241
                                        updateMap["subOrders.$.cashBackStatus"] = Store.CB_APPROVED
242
                                elif status == Store.ORDER_CANCELLED:
243
                                    if subOrder.get("cashBackStatus") == Store.CB_PENDING:
244
                                        updateMap["subOrders.$.cashBackStatus"] = Store.CB_CANCELLED
245
                            else:
246
                                expectedDelivery = datetime.strftime(datetime.fromtimestamp(order['promised_delivery_time']/1000),"%A %d %B %Y")
247
                                updateMap["subOrders.$.estimatedDeliveryDate"] = expectedDelivery
248
                                closed = False
249
                            bulk.find(findMap).update({'$set' : updateMap})
250
                    else:
16967 amit.gupta 251
                        subOrder = self.createSubOrder(order, items)
14269 amit.gupta 252
                        self.db.merchantOrder.update({"orderId":tr['orderId']},{'$push':{"subOrders":todict(subOrder)}})
14246 amit.gupta 253
                        print "Added new suborder with subOrder Id:", subOrder.merchantSubOrderId
254
                        closed = False
14283 amit.gupta 255
                bulk.find({"orderId":tr['orderId']}).update({'$set' : {'closed':closed}})
14246 amit.gupta 256
            except:
14277 amit.gupta 257
                traceback.print_exc()
14870 amit.gupta 258
        try:
259
            bulk.execute()
260
        except:
261
            traceback.print_exc()
14246 amit.gupta 262
 
263
 
264
 
14220 amit.gupta 265
 
266
    def _saveToAffiliate(self, offers):
267
        if offers is None or len(offers)==0:
268
            print "no affiliate have been pushed"
269
            return
270
        collection = self.db.snapdealOrderAffiliateInfo
271
        try:
272
            collection.insert(offers,continue_on_error=True)
273
        except pymongo.errors.DuplicateKeyError as e:
274
            print e.details
275
 
276
 
277
    def covertToObj(self,offer):
278
        offerData = offer['Stat']
279
        offer1 = AffiliateInfo(offerData['affiliate_info1'], self.store_id, offerData['conversion_status'], offerData['ad_id'], 
280
                              offerData['datetime'], offerData['payout'], offer['Offer']['name'], offerData['ip'], offerData['conversion_sale_amount'])
281
 
282
        return offer1
283
def getPostData(token, page = 1, limit= 20, startDate=None, endDate=None):
284
    endDate=date.today() + timedelta(days=1)
285
    startDate=endDate - timedelta(days=31)
286
 
287
    parameters = (
288
        ("page",str(page)),
289
        ("limit",str(limit)),
290
        ("fields[]","Stat.offer_id"),
291
        ("fields[]","Stat.datetime"),
292
        ("fields[]","Offer.name"),
293
        ("fields[]","Stat.conversion_status"),
294
        ("fields[]","Stat.conversion_sale_amount"),
295
        ("fields[]","Stat.payout"),
296
        ("fields[]","Stat.ip"),
297
        ("fields[]","Stat.ad_id"),
298
        ("fields[]","Stat.affiliate_info1"),
299
        ("sort[Stat.datetime]","desc"),
300
        ("filters[Stat.date][conditional]","BETWEEN"),
301
        ("filters[Stat.date][values][]",startDate.strftime('%Y-%m-%d')),
302
        ("filters[Stat.date][values][]",endDate.strftime('%Y-%m-%d')),
303
        ("data_start",startDate.strftime('%Y-%m-%d')),
304
        ("data_end",endDate.strftime('%Y-%m-%d')),
305
        ("Method","getConversions"),
306
        ("NetworkId","jasper"),
307
        ("SessionToken",token),
308
    )
309
    #Encode the parameters
310
    return urllib.urlencode(parameters)
311
 
312
def main():
313
 
14301 amit.gupta 314
    store = getStore(4)
14220 amit.gupta 315
    #store.scrapeStoreOrders()
316
    #store._isSubOrderActive(8, "5970688907")
317
    #store.scrapeAffiliate()
17677 amit.gupta 318
    store.parseOrderRawHtml(112345, "subtagId", 1122323,  "html", 'http://www.saholic.com/pay-success?paymentId=1798123')
16967 amit.gupta 319
    #print store.getCashbackAmount('1011378', 500)
14220 amit.gupta 320
 
321
 
322
if __name__ == '__main__':
323
    main()
324
 
325
def todict(obj, classkey=None):
326
    if isinstance(obj, dict):
327
        data = {}
328
        for (k, v) in obj.items():
329
            data[k] = todict(v, classkey)
330
        return data
331
    elif hasattr(obj, "_ast"):
332
        return todict(obj._ast())
333
    elif hasattr(obj, "__iter__"):
334
        return [todict(v, classkey) for v in obj]
335
    elif hasattr(obj, "__dict__"):
336
        data = dict([(key, todict(value, classkey)) 
337
            for key, value in obj.__dict__.iteritems() 
338
            if not callable(value) and not key.startswith('_')])
339
        if classkey is not None and hasattr(obj, "__class__"):
340
            data[classkey] = obj.__class__.__name__
341
        return data
342
    else:
343
        return obj