Subversion Repositories SmartDukaan

Rev

Rev 17677 | Rev 18085 | 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,):
14278 amit.gupta 207
        trs = self._getActiveOrders(collectionMap={'merchantOrderId':1, 'sUserId':1})
14267 amit.gupta 208
        bulk = self.db.merchantOrder.initialize_ordered_bulk_op()
14246 amit.gupta 209
        for tr in trs:
210
            try:
211
                orderRequest = urllib2.Request(SAHOLIC_ORDER_URL_TR %(tr['merchantOrderId'], tr['sUserId']), headers=headers)
212
                response = urllib2.urlopen(orderRequest).read()
14275 amit.gupta 213
                print response
14246 amit.gupta 214
                response = json.loads(response)['response']
215
                items = response['itemsMap']
216
                orders = response['orders']
217
                closed = True
218
                for order in orders:
14272 amit.gupta 219
                    print "orderid---", order['id']
14269 amit.gupta 220
                    orderId = str(order['id'])
221
                    subOrder = self._isSubOrderActive(tr, orderId)
14246 amit.gupta 222
                    if subOrder:
223
                        if subOrder['closed']:
224
                            continue
225
                        else:
14270 amit.gupta 226
                            findMap = {"orderId": tr['orderId'], "subOrders.merchantSubOrderId": orderId}
14246 amit.gupta 227
                            updateMap = {}
228
                            updateMap["subOrders.$.detailedStatus"] = order['statusDescription']
229
                            status = self._getStatusFromDetailedStatus(ORDERSTATUS[order['status']]) 
230
                            closedStatus = status in [Store.ORDER_DELIVERED, Store.ORDER_CANCELLED]
14271 amit.gupta 231
                            print "status---", status, order['status']
14246 amit.gupta 232
                            updateMap["subOrders.$.status"] = status
233
                            if closedStatus:
234
                                #if status is closed then change the paybackStatus accordingly
235
                                updateMap["subOrders.$.closed"] = True
236
                                if status == Store.ORDER_DELIVERED:
237
                                    deliveredOn = datetime.strftime(datetime.fromtimestamp(order['delivery_timestamp']/1000),"%A %d %B %Y")
238
                                    updateMap['subOrders.$.deliveredOn'] = deliveredOn
239
                                    if subOrder.get("cashBackStatus") == Store.CB_PENDING:
240
                                        updateMap["subOrders.$.cashBackStatus"] = Store.CB_APPROVED
241
                                elif status == Store.ORDER_CANCELLED:
242
                                    if subOrder.get("cashBackStatus") == Store.CB_PENDING:
243
                                        updateMap["subOrders.$.cashBackStatus"] = Store.CB_CANCELLED
244
                            else:
245
                                expectedDelivery = datetime.strftime(datetime.fromtimestamp(order['promised_delivery_time']/1000),"%A %d %B %Y")
246
                                updateMap["subOrders.$.estimatedDeliveryDate"] = expectedDelivery
247
                                closed = False
248
                            bulk.find(findMap).update({'$set' : updateMap})
249
                    else:
16967 amit.gupta 250
                        subOrder = self.createSubOrder(order, items)
14269 amit.gupta 251
                        self.db.merchantOrder.update({"orderId":tr['orderId']},{'$push':{"subOrders":todict(subOrder)}})
14246 amit.gupta 252
                        print "Added new suborder with subOrder Id:", subOrder.merchantSubOrderId
253
                        closed = False
14283 amit.gupta 254
                bulk.find({"orderId":tr['orderId']}).update({'$set' : {'closed':closed}})
14246 amit.gupta 255
            except:
14277 amit.gupta 256
                traceback.print_exc()
14870 amit.gupta 257
        try:
258
            bulk.execute()
259
        except:
260
            traceback.print_exc()
14246 amit.gupta 261
 
262
 
263
 
14220 amit.gupta 264
 
265
    def _saveToAffiliate(self, offers):
266
        if offers is None or len(offers)==0:
267
            print "no affiliate have been pushed"
268
            return
269
        collection = self.db.snapdealOrderAffiliateInfo
270
        try:
271
            collection.insert(offers,continue_on_error=True)
272
        except pymongo.errors.DuplicateKeyError as e:
273
            print e.details
274
 
275
 
276
    def covertToObj(self,offer):
277
        offerData = offer['Stat']
278
        offer1 = AffiliateInfo(offerData['affiliate_info1'], self.store_id, offerData['conversion_status'], offerData['ad_id'], 
279
                              offerData['datetime'], offerData['payout'], offer['Offer']['name'], offerData['ip'], offerData['conversion_sale_amount'])
280
 
281
        return offer1
282
def getPostData(token, page = 1, limit= 20, startDate=None, endDate=None):
283
    endDate=date.today() + timedelta(days=1)
284
    startDate=endDate - timedelta(days=31)
285
 
286
    parameters = (
287
        ("page",str(page)),
288
        ("limit",str(limit)),
289
        ("fields[]","Stat.offer_id"),
290
        ("fields[]","Stat.datetime"),
291
        ("fields[]","Offer.name"),
292
        ("fields[]","Stat.conversion_status"),
293
        ("fields[]","Stat.conversion_sale_amount"),
294
        ("fields[]","Stat.payout"),
295
        ("fields[]","Stat.ip"),
296
        ("fields[]","Stat.ad_id"),
297
        ("fields[]","Stat.affiliate_info1"),
298
        ("sort[Stat.datetime]","desc"),
299
        ("filters[Stat.date][conditional]","BETWEEN"),
300
        ("filters[Stat.date][values][]",startDate.strftime('%Y-%m-%d')),
301
        ("filters[Stat.date][values][]",endDate.strftime('%Y-%m-%d')),
302
        ("data_start",startDate.strftime('%Y-%m-%d')),
303
        ("data_end",endDate.strftime('%Y-%m-%d')),
304
        ("Method","getConversions"),
305
        ("NetworkId","jasper"),
306
        ("SessionToken",token),
307
    )
308
    #Encode the parameters
309
    return urllib.urlencode(parameters)
310
 
311
def main():
312
 
14301 amit.gupta 313
    store = getStore(4)
14220 amit.gupta 314
    #store.scrapeStoreOrders()
315
    #store._isSubOrderActive(8, "5970688907")
316
    #store.scrapeAffiliate()
17677 amit.gupta 317
    store.parseOrderRawHtml(112345, "subtagId", 1122323,  "html", 'http://www.saholic.com/pay-success?paymentId=1798123')
16967 amit.gupta 318
    #print store.getCashbackAmount('1011378', 500)
14220 amit.gupta 319
 
320
 
321
if __name__ == '__main__':
322
    main()
323
 
324
def todict(obj, classkey=None):
325
    if isinstance(obj, dict):
326
        data = {}
327
        for (k, v) in obj.items():
328
            data[k] = todict(v, classkey)
329
        return data
330
    elif hasattr(obj, "_ast"):
331
        return todict(obj._ast())
332
    elif hasattr(obj, "__iter__"):
333
        return [todict(v, classkey) for v in obj]
334
    elif hasattr(obj, "__dict__"):
335
        data = dict([(key, todict(value, classkey)) 
336
            for key, value in obj.__dict__.iteritems() 
337
            if not callable(value) and not key.startswith('_')])
338
        if classkey is not None and hasattr(obj, "__class__"):
339
            data[classkey] = obj.__class__.__name__
340
        return data
341
    else:
342
        return obj