Subversion Repositories SmartDukaan

Rev

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