Subversion Repositories SmartDukaan

Rev

Rev 15281 | Rev 15283 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
15081 amit.gupta 1
from bson import json_util
2
from bson.json_util import dumps
15096 amit.gupta 3
from datetime import datetime, timedelta
13582 amit.gupta 4
from dtr import main
15081 amit.gupta 5
from dtr.config import PythonPropertyReader
13629 kshitij.so 6
from dtr.storage import Mongo
15132 amit.gupta 7
from dtr.storage.DataService import Retailers, Users, CallHistory, RetryConfig, \
15254 amit.gupta 8
    RetailerLinks, Activation_Codes, Agents, Agent_Roles, AgentLoginTimings, \
9
    FetchDataHistory, RetailerContacts
15081 amit.gupta 10
from dtr.utils import FetchLivePrices, DealSheet as X_DealSheet, \
11
    UserSpecificDeals
15168 amit.gupta 12
from dtr.utils.utils import getLogger
15081 amit.gupta 13
from elixir import *
15254 amit.gupta 14
from operator import and_
15081 amit.gupta 15
from sqlalchemy.sql.expression import or_
15132 amit.gupta 16
from urllib import urlencode
17
import contextlib
13827 kshitij.so 18
import falcon
15081 amit.gupta 19
import json
15254 amit.gupta 20
import string
15081 amit.gupta 21
import traceback
15132 amit.gupta 22
import urllib
23
import urllib2
24
import uuid
15207 amit.gupta 25
 
26
alphalist = list(string.uppercase)
27
alphalist.remove('O')
28
numList = ['1','2','3','4','5','6','7','8','9']
29
codesys = [alphalist, alphalist, numList, numList, numList]
30
 
31
 
32
def getNextCode(codesys, code=None):
33
    if code is None:
34
        code = []
35
        for charcode in codesys:
36
            code.append(charcode[0])
37
        return string.join(code, '')
38
    carry = True
39
    code = list(code)
40
    lastindex = len(codesys) - 1
41
    while carry:
42
        listChar = codesys[lastindex]
43
        newIndex = (listChar.index(code[lastindex])+1)%len(listChar)
44
        print newIndex
45
        code[lastindex] = listChar[newIndex]
46
        if newIndex != 0:
47
            carry = False
48
        lastindex -= 1
49
        if lastindex ==-1:
50
            raise BaseException("All codes are exhausted")
51
 
52
    return string.join(code, '')
53
 
54
 
55
 
56
 
15081 amit.gupta 57
global RETAILER_DETAIL_CALL_COUNTER
58
RETAILER_DETAIL_CALL_COUNTER = 0
13572 kshitij.so 59
 
15168 amit.gupta 60
lgr = getLogger('/var/log/retailer-acquisition-api.log')
15081 amit.gupta 61
DEALER_RETRY_FACTOR = int(PythonPropertyReader.getConfig('DEALER_RETRY_FACTOR'))
13572 kshitij.so 62
class CategoryDiscountInfo(object):
63
 
64
    def on_get(self, req, resp):
65
 
13629 kshitij.so 66
        result = Mongo.getAllCategoryDiscount()
67
        json_docs = [json.dumps(doc, default=json_util.default) for doc in result]
68
        resp.body = json.dumps(json_docs, encoding='utf-8')
13572 kshitij.so 69
 
70
    def on_post(self, req, resp):
71
        try:
72
            result_json = json.loads(req.stream.read(), encoding='utf-8')
73
        except ValueError:
74
            raise falcon.HTTPError(falcon.HTTP_400,
75
                'Malformed JSON',
76
                'Could not decode the request body. The '
77
                'JSON was incorrect.')
78
 
79
        result = Mongo.addCategoryDiscount(result_json)
80
        resp.body = json.dumps(result, encoding='utf-8')
13969 kshitij.so 81
 
82
    def on_put(self, req, resp, _id):
13970 kshitij.so 83
        try:
84
            result_json = json.loads(req.stream.read(), encoding='utf-8')
85
        except ValueError:
86
            raise falcon.HTTPError(falcon.HTTP_400,
87
                'Malformed JSON',
88
                'Could not decode the request body. The '
89
                'JSON was incorrect.')
90
 
91
        result = Mongo.updateCategoryDiscount(result_json, _id)
92
        resp.body = json.dumps(result, encoding='utf-8')
93
 
13966 kshitij.so 94
 
13969 kshitij.so 95
 
13572 kshitij.so 96
class SkuSchemeDetails(object):
97
 
98
    def on_get(self, req, resp):
13629 kshitij.so 99
 
14070 kshitij.so 100
        offset = req.get_param_as_int("offset")
101
        limit = req.get_param_as_int("limit")
102
 
103
        result = Mongo.getAllSkuWiseSchemeDetails(offset, limit)
13629 kshitij.so 104
        json_docs = [json.dumps(doc, default=json_util.default) for doc in result]
105
        resp.body = json.dumps(json_docs, encoding='utf-8')
13572 kshitij.so 106
 
107
 
108
    def on_post(self, req, resp):
109
 
14552 kshitij.so 110
        multi = req.get_param_as_int("multi")
111
 
13572 kshitij.so 112
        try:
113
            result_json = json.loads(req.stream.read(), encoding='utf-8')
114
        except ValueError:
115
            raise falcon.HTTPError(falcon.HTTP_400,
116
                'Malformed JSON',
117
                'Could not decode the request body. The '
118
                'JSON was incorrect.')
119
 
14552 kshitij.so 120
        result = Mongo.addSchemeDetailsForSku(result_json, multi)
13572 kshitij.so 121
        resp.body = json.dumps(result, encoding='utf-8')
122
 
123
class SkuDiscountInfo():
124
 
125
    def on_get(self, req, resp):
13629 kshitij.so 126
 
13970 kshitij.so 127
        offset = req.get_param_as_int("offset")
128
        limit = req.get_param_as_int("limit")
129
        result = Mongo.getallSkuDiscountInfo(offset,limit)
13629 kshitij.so 130
        json_docs = [json.dumps(doc, default=json_util.default) for doc in result]
131
        resp.body = json.dumps(json_docs, encoding='utf-8')
13572 kshitij.so 132
 
133
 
134
    def on_post(self, req, resp):
135
 
14552 kshitij.so 136
        multi = req.get_param_as_int("multi")
137
 
13572 kshitij.so 138
        try:
139
            result_json = json.loads(req.stream.read(), encoding='utf-8')
140
        except ValueError:
141
            raise falcon.HTTPError(falcon.HTTP_400,
142
                'Malformed JSON',
143
                'Could not decode the request body. The '
144
                'JSON was incorrect.')
145
 
14552 kshitij.so 146
        result = Mongo.addSkuDiscountInfo(result_json, multi)
13572 kshitij.so 147
        resp.body = json.dumps(result, encoding='utf-8')
13970 kshitij.so 148
 
149
    def on_put(self, req, resp, _id):
150
        try:
151
            result_json = json.loads(req.stream.read(), encoding='utf-8')
152
        except ValueError:
153
            raise falcon.HTTPError(falcon.HTTP_400,
154
                'Malformed JSON',
155
                'Could not decode the request body. The '
156
                'JSON was incorrect.')
157
 
158
        result = Mongo.updateSkuDiscount(result_json, _id)
159
        resp.body = json.dumps(result, encoding='utf-8')
13572 kshitij.so 160
 
161
class ExceptionalNlc():
162
 
163
    def on_get(self, req, resp):
13629 kshitij.so 164
 
13970 kshitij.so 165
        offset = req.get_param_as_int("offset")
166
        limit = req.get_param_as_int("limit")
167
 
168
        result = Mongo.getAllExceptionlNlcItems(offset, limit)
13629 kshitij.so 169
        json_docs = [json.dumps(doc, default=json_util.default) for doc in result]
170
        resp.body = json.dumps(json_docs, encoding='utf-8')
13572 kshitij.so 171
 
172
    def on_post(self, req, resp):
173
 
14552 kshitij.so 174
        multi = req.get_param_as_int("multi")
175
 
13572 kshitij.so 176
        try:
177
            result_json = json.loads(req.stream.read(), encoding='utf-8')
178
        except ValueError:
179
            raise falcon.HTTPError(falcon.HTTP_400,
180
                'Malformed JSON',
181
                'Could not decode the request body. The '
182
                'JSON was incorrect.')
183
 
14552 kshitij.so 184
        result = Mongo.addExceptionalNlc(result_json, multi)
13572 kshitij.so 185
        resp.body = json.dumps(result, encoding='utf-8')
13970 kshitij.so 186
 
187
    def on_put(self, req, resp, _id):
188
        try:
189
            result_json = json.loads(req.stream.read(), encoding='utf-8')
190
        except ValueError:
191
            raise falcon.HTTPError(falcon.HTTP_400,
192
                'Malformed JSON',
193
                'Could not decode the request body. The '
194
                'JSON was incorrect.')
195
 
196
        result = Mongo.updateExceptionalNlc(result_json, _id)
197
        resp.body = json.dumps(result, encoding='utf-8')
13572 kshitij.so 198
 
13772 kshitij.so 199
class Deals():
13779 kshitij.so 200
    def on_get(self,req, resp, userId):
201
        categoryId = req.get_param_as_int("categoryId")
202
        offset = req.get_param_as_int("offset")
203
        limit = req.get_param_as_int("limit")
13798 kshitij.so 204
        sort = req.get_param("sort")
13802 kshitij.so 205
        direction = req.get_param_as_int("direction")
14853 kshitij.so 206
        filterData = req.get_param('filterData')
207
        result = Mongo.getNewDeals(int(userId), categoryId, offset, limit, sort, direction, filterData)
13772 kshitij.so 208
        json_docs = [json.dumps(doc, default=json_util.default) for doc in result]
13966 kshitij.so 209
        resp.body = json.dumps(json_docs, encoding='utf-8')
13790 kshitij.so 210
 
211
class MasterData():
212
    def on_get(self,req, resp, skuId):
213
        result = Mongo.getItem(skuId)
13798 kshitij.so 214
        try:
215
            json_docs = [json.dumps(doc, default=json_util.default) for doc in result]
13966 kshitij.so 216
            resp.body = json.dumps(json_docs, encoding='utf-8')
13798 kshitij.so 217
        except:
218
            json_docs = [json.dumps(doc, default=json_util.default) for doc in result]
13966 kshitij.so 219
            resp.body = json.dumps(json_docs, encoding='utf-8')
13790 kshitij.so 220
 
14586 kshitij.so 221
    def on_post(self,req, resp):
222
 
223
        addNew = req.get_param_as_int("addNew")
224
        update = req.get_param_as_int("update")
225
        addToExisting = req.get_param_as_int("addToExisting")
226
        multi = req.get_param_as_int("multi")
227
 
14589 kshitij.so 228
        try:
14592 kshitij.so 229
            result_json = json.loads(req.stream.read(), encoding='utf-8')
230
        except ValueError:
231
            raise falcon.HTTPError(falcon.HTTP_400,
232
                'Malformed JSON',
233
                'Could not decode the request body. The '
234
                'JSON was incorrect.')
235
 
236
        if addNew == 1:
237
            result = Mongo.addNewItem(result_json)
238
        elif update == 1:
239
            result = Mongo.updateMaster(result_json, multi)
240
        elif addToExisting == 1:
241
            result = Mongo.addItemToExistingBundle(result_json)
242
        else:
243
            raise
244
        resp.body = dumps(result)
14586 kshitij.so 245
 
13827 kshitij.so 246
class LiveData():
247
    def on_get(self,req, resp):
13865 kshitij.so 248
        if req.get_param_as_int("id") is not None:
249
            print "****getting only for id"
250
            id = req.get_param_as_int("id")
251
            try:
252
                result = FetchLivePrices.getLatestPriceById(id)
13867 kshitij.so 253
                json_docs = json.dumps(result, default=json_util.default)
13966 kshitij.so 254
                resp.body = json.dumps(json_docs, encoding='utf-8')
13865 kshitij.so 255
            except:
256
                json_docs = json.dumps({}, default=json_util.default)
13966 kshitij.so 257
                resp.body = json.dumps(json_docs, encoding='utf-8')
13834 kshitij.so 258
 
13865 kshitij.so 259
        else:
260
            print "****getting only for skuId"
261
            skuBundleId = req.get_param_as_int("skuBundleId")
262
            source_id = req.get_param_as_int("source_id")
263
            try:
264
                result = FetchLivePrices.getLatestPrice(skuBundleId, source_id)
265
                json_docs = [json.dumps(doc, default=json_util.default) for doc in result]
13966 kshitij.so 266
                resp.body = json.dumps(json_docs, encoding='utf-8')
13865 kshitij.so 267
            except:
268
                json_docs = [json.dumps(doc, default=json_util.default) for doc in [{}]]
13966 kshitij.so 269
                resp.body = json.dumps(json_docs, encoding='utf-8')
13865 kshitij.so 270
 
13834 kshitij.so 271
class CashBack():
272
    def on_get(self,req, resp):
273
        identifier = req.get_param("identifier")
274
        source_id = req.get_param_as_int("source_id")
275
        try:
13838 kshitij.so 276
            result = Mongo.getCashBackDetails(identifier, source_id)
13837 kshitij.so 277
            json_docs = json.dumps(result, default=json_util.default)
13964 kshitij.so 278
            resp.body = json_docs
13834 kshitij.so 279
        except:
13837 kshitij.so 280
            json_docs = json.dumps({}, default=json_util.default)
13963 kshitij.so 281
            resp.body = json_docs
13892 kshitij.so 282
 
14398 amit.gupta 283
class ImgSrc():
284
    def on_get(self,req, resp):
285
        identifier = req.get_param("identifier")
286
        source_id = req.get_param_as_int("source_id")
287
        try:
288
            result = Mongo.getImgSrc(identifier, source_id)
289
            json_docs = json.dumps(result, default=json_util.default)
290
            resp.body = json_docs
291
        except:
292
            json_docs = json.dumps({}, default=json_util.default)
293
            resp.body = json_docs
294
 
13892 kshitij.so 295
class DealSheet():
296
    def on_get(self,req, resp):
13895 kshitij.so 297
        X_DealSheet.sendMail()
13897 kshitij.so 298
        json_docs = json.dumps({'True':'Sheet generated, mail sent.'}, default=json_util.default)
13966 kshitij.so 299
        resp.body = json.dumps(json_docs, encoding='utf-8')
13892 kshitij.so 300
 
13970 kshitij.so 301
class DealerPrice():
302
 
303
    def on_get(self, req, resp):
304
 
305
        offset = req.get_param_as_int("offset")
306
        limit = req.get_param_as_int("limit")
307
        result = Mongo.getAllDealerPrices(offset,limit)
308
        json_docs = [json.dumps(doc, default=json_util.default) for doc in result]
309
        resp.body = json.dumps(json_docs, encoding='utf-8')
310
 
311
    def on_post(self, req, resp):
312
 
14552 kshitij.so 313
        multi = req.get_param_as_int("multi")
314
 
13970 kshitij.so 315
        try:
316
            result_json = json.loads(req.stream.read(), encoding='utf-8')
317
        except ValueError:
318
            raise falcon.HTTPError(falcon.HTTP_400,
319
                'Malformed JSON',
320
                'Could not decode the request body. The '
321
                'JSON was incorrect.')
322
 
14552 kshitij.so 323
        result = Mongo.addSkuDealerPrice(result_json, multi)
13970 kshitij.so 324
        resp.body = json.dumps(result, encoding='utf-8')
325
 
326
    def on_put(self, req, resp, _id):
327
        try:
328
            result_json = json.loads(req.stream.read(), encoding='utf-8')
329
        except ValueError:
330
            raise falcon.HTTPError(falcon.HTTP_400,
331
                'Malformed JSON',
332
                'Could not decode the request body. The '
333
                'JSON was incorrect.')
334
 
335
        result = Mongo.updateSkuDealerPrice(result_json, _id)
336
        resp.body = json.dumps(result, encoding='utf-8')
337
 
338
 
14041 kshitij.so 339
class ResetCache():
340
 
341
    def on_get(self,req, resp, userId):
14044 kshitij.so 342
        result = Mongo.resetCache(userId)
14046 kshitij.so 343
        resp.body = json.dumps(result, encoding='utf-8')
344
 
345
class UserDeals():
346
    def on_get(self,req,resp,userId):
347
        UserSpecificDeals.generateSheet(userId)
348
        json_docs = json.dumps({'True':'Sheet generated, mail sent.'}, default=json_util.default)
349
        resp.body = json.dumps(json_docs, encoding='utf-8')
14075 kshitij.so 350
 
351
class CommonUpdate():
352
 
353
    def on_post(self,req,resp):
14575 kshitij.so 354
 
355
        multi = req.get_param_as_int("multi")
356
 
14075 kshitij.so 357
        try:
358
            result_json = json.loads(req.stream.read(), encoding='utf-8')
359
        except ValueError:
360
            raise falcon.HTTPError(falcon.HTTP_400,
361
                'Malformed JSON',
362
                'Could not decode the request body. The '
363
                'JSON was incorrect.')
364
 
14575 kshitij.so 365
        result = Mongo.updateCollection(result_json, multi)
14075 kshitij.so 366
        resp.body = json.dumps(result, encoding='utf-8')
14106 kshitij.so 367
        resp.content_type = "application/json; charset=utf-8"
14481 kshitij.so 368
 
369
class NegativeDeals():
370
 
371
    def on_get(self, req, resp):
372
 
373
        offset = req.get_param_as_int("offset")
374
        limit = req.get_param_as_int("limit")
375
 
376
        result = Mongo.getAllNegativeDeals(offset, limit)
14483 kshitij.so 377
        resp.body = dumps(result) 
14481 kshitij.so 378
 
379
 
380
    def on_post(self, req, resp):
381
 
14552 kshitij.so 382
        multi = req.get_param_as_int("multi")
383
 
14481 kshitij.so 384
        try:
385
            result_json = json.loads(req.stream.read(), encoding='utf-8')
386
        except ValueError:
387
            raise falcon.HTTPError(falcon.HTTP_400,
388
                'Malformed JSON',
389
                'Could not decode the request body. The '
390
                'JSON was incorrect.')
391
 
14552 kshitij.so 392
        result = Mongo.addNegativeDeals(result_json, multi)
14481 kshitij.so 393
        resp.body = json.dumps(result, encoding='utf-8')
394
 
395
class ManualDeals():
396
 
397
    def on_get(self, req, resp):
398
 
399
        offset = req.get_param_as_int("offset")
400
        limit = req.get_param_as_int("limit")
401
 
402
        result = Mongo.getAllManualDeals(offset, limit)
14483 kshitij.so 403
        resp.body = dumps(result)
14481 kshitij.so 404
 
405
 
406
    def on_post(self, req, resp):
407
 
14552 kshitij.so 408
        multi = req.get_param_as_int("multi")
409
 
14481 kshitij.so 410
        try:
411
            result_json = json.loads(req.stream.read(), encoding='utf-8')
412
        except ValueError:
413
            raise falcon.HTTPError(falcon.HTTP_400,
414
                'Malformed JSON',
415
                'Could not decode the request body. The '
416
                'JSON was incorrect.')
417
 
14552 kshitij.so 418
        result = Mongo.addManualDeal(result_json, multi)
14481 kshitij.so 419
        resp.body = json.dumps(result, encoding='utf-8')
420
 
421
class CommonDelete():
14482 kshitij.so 422
 
14481 kshitij.so 423
    def on_post(self,req,resp):
424
        try:
425
            result_json = json.loads(req.stream.read(), encoding='utf-8')
426
        except ValueError:
427
            raise falcon.HTTPError(falcon.HTTP_400,
428
                'Malformed JSON',
429
                'Could not decode the request body. The '
430
                'JSON was incorrect.')
431
 
432
        result = Mongo.deleteDocument(result_json)
433
        resp.body = json.dumps(result, encoding='utf-8')
434
        resp.content_type = "application/json; charset=utf-8"
14482 kshitij.so 435
 
436
class SearchProduct():
437
 
438
    def on_get(self,req,resp):
439
        offset = req.get_param_as_int("offset")
440
        limit = req.get_param_as_int("limit")
441
        search_term = req.get_param("search")
442
 
443
        result = Mongo.searchMaster(offset, limit, search_term)
14483 kshitij.so 444
        resp.body = dumps(result) 
14482 kshitij.so 445
 
446
 
14495 kshitij.so 447
class FeaturedDeals():
14482 kshitij.so 448
 
14495 kshitij.so 449
    def on_get(self, req, resp):
450
 
451
        offset = req.get_param_as_int("offset")
452
        limit = req.get_param_as_int("limit")
453
 
454
        result = Mongo.getAllFeaturedDeals(offset, limit)
455
        resp.body = dumps(result)
456
 
457
 
458
    def on_post(self, req, resp):
459
 
14552 kshitij.so 460
        multi = req.get_param_as_int("multi")
461
 
14495 kshitij.so 462
        try:
463
            result_json = json.loads(req.stream.read(), encoding='utf-8')
464
        except ValueError:
465
            raise falcon.HTTPError(falcon.HTTP_400,
466
                'Malformed JSON',
467
                'Could not decode the request body. The '
468
                'JSON was incorrect.')
469
 
14552 kshitij.so 470
        result = Mongo.addFeaturedDeal(result_json, multi)
14495 kshitij.so 471
        resp.body = json.dumps(result, encoding='utf-8')
472
 
14497 kshitij.so 473
 
474
class CommonSearch():
14495 kshitij.so 475
 
14497 kshitij.so 476
    def on_get(self,req,resp):
477
        class_name = req.get_param("class")
478
        sku = req.get_param_as_int("sku")
479
        skuBundleId = req.get_param_as_int("skuBundleId")
14499 kshitij.so 480
 
481
        result = Mongo.searchCollection(class_name, sku, skuBundleId)
14497 kshitij.so 482
        resp.body = dumps(result)
14619 kshitij.so 483
 
484
class CricScore():
485
 
486
    def on_get(self,req,resp):
487
 
488
        result = Mongo.getLiveCricScore()
14853 kshitij.so 489
        resp.body = dumps(result)
490
 
491
class Notification():
492
 
493
    def on_post(self, req, resp):
494
 
495
        try:
496
            result_json = json.loads(req.stream.read(), encoding='utf-8')
497
        except ValueError:
498
            raise falcon.HTTPError(falcon.HTTP_400,
499
                'Malformed JSON',
500
                'Could not decode the request body. The '
501
                'JSON was incorrect.')
502
 
503
        result = Mongo.addBundleToNotification(result_json)
504
        resp.body = json.dumps(result, encoding='utf-8')
505
 
506
    def on_get(self, req, resp):
507
 
508
        offset = req.get_param_as_int("offset")
509
        limit = req.get_param_as_int("limit")
510
 
511
        result = Mongo.getAllNotifications(offset, limit)
512
        resp.body = dumps(result)
513
 
14998 kshitij.so 514
class DealBrands():
14853 kshitij.so 515
 
14998 kshitij.so 516
    def on_get(self, req, resp):
517
 
518
        category_id = req.get_param_as_int("category_id")
519
        result = Mongo.getBrandsForFilter(category_id)
14999 kshitij.so 520
        resp.body = dumps(result)
15161 kshitij.so 521
 
522
class DealRank():
14998 kshitij.so 523
 
15161 kshitij.so 524
    def on_get(self, req, resp):
525
        identifier = req.get_param("identifier")
526
        source_id = req.get_param_as_int("source_id")
527
        user_id = req.get_param_as_int("user_id")
528
        result = Mongo.getDealRank(identifier, source_id, user_id)
529
        json_docs = json.dumps(result, default=json_util.default)
530
        resp.body = json_docs
531
 
532
 
15081 amit.gupta 533
 
534
class RetailerDetail():
535
    global RETAILER_DETAIL_CALL_COUNTER
15105 amit.gupta 536
    def getRetryRetailer(self,failback=True):
15081 amit.gupta 537
        retailer = None
538
        status = 'fretry' if self.callType == 'followup' else 'retry'
15239 amit.gupta 539
        retailer = session.query(Retailers).filter_by(status=status).filter(Retailers.next_call_time<=datetime.now()).order_by(Retailers.call_priority).order_by(Retailers.next_call_time).with_lockmode("update").first()
540
        if retailer is not None:
541
            lgr.info( "getRetryRetailer " + str(retailer.id))
542
        else:
543
            if failback:
544
                retailer = self.getNewRetailer(False)
545
                return retailer
546
        if status=='retry':
547
            retailer.status = 'assigned'
548
        else:
549
            retailer.status = 'fassigned'
550
        lgr.info( "getRetryRetailer " + str(retailer.id))
15081 amit.gupta 551
        return retailer
552
 
553
    def getNewRetailer(self,failback=True):
554
        retry = True
555
        retailer = None 
556
        try:
557
            while(retry):
15168 amit.gupta 558
                lgr.info( "Calltype " + self.callType)
15081 amit.gupta 559
                status=self.callType
560
                query = session.query(Retailers).filter(Retailers.status==status)
561
                if status=='fresh':
15172 amit.gupta 562
                    query = query.filter_by(is_or=False, is_std=False).filter(or_(Retailers.agent_id==self.agentId, Retailers.agent_id==None)).order_by(Retailers.is_elavated.desc(), -Retailers.agent_id)
15162 amit.gupta 563
                else:
15171 amit.gupta 564
                    query = query.filter(Retailers.next_call_time<=datetime.now())
15081 amit.gupta 565
                retailer = query.with_lockmode("update").first()
566
                if retailer is not None:
15168 amit.gupta 567
                    lgr.info( "retailer " +str(retailer.id))
15081 amit.gupta 568
                    if status=="fresh":
569
                        userquery = session.query(Users)
570
                        if retailer.contact2 is not None:
571
                            userquery = userquery.filter(Users.mobile_number.in_([retailer.contact1,retailer.contact2]))
572
                        else:
573
                            userquery = userquery.filter_by(mobile_number=retailer.contact1)
574
                        user = userquery.first()
575
                        if user is not None:
576
                            retailer.status = 'alreadyuser'
15168 amit.gupta 577
                            lgr.info( "retailer.status " + retailer.status)
15081 amit.gupta 578
                            session.commit()
579
                            continue
580
                        retailer.status = 'assigned'
581
                    else:
15276 amit.gupta 582
                        if isActivated(retailer.id):
583
                            print "Retailer Already %d activated and marked onboarded"%(retailer.id)
584
                            continue
15081 amit.gupta 585
                        retailer.status = 'fassigned'
586
                    retailer.retry_count = 0
15123 amit.gupta 587
                    retailer.invalid_retry_count = 0
15168 amit.gupta 588
                    lgr.info( "Found Retailer " +  str(retailer.id) + " with status " + status + " assigned to " + str(self.agentId))
15081 amit.gupta 589
 
590
                else:
15168 amit.gupta 591
                    lgr.info( "No fresh/followup retailers found")
15081 amit.gupta 592
                    if failback:
593
                        retailer = self.getRetryRetailer(False)
15104 amit.gupta 594
                        return retailer
15148 amit.gupta 595
                retry=False
15081 amit.gupta 596
        except:
597
            print traceback.print_exc()
598
        return retailer
599
 
15132 amit.gupta 600
    def on_get(self, req, resp, agentId, callType=None, retailerId=None):
15081 amit.gupta 601
        global RETAILER_DETAIL_CALL_COUNTER
602
        RETAILER_DETAIL_CALL_COUNTER += 1
15168 amit.gupta 603
        lgr.info( "RETAILER_DETAIL_CALL_COUNTER " +  str(RETAILER_DETAIL_CALL_COUNTER))
15081 amit.gupta 604
        self.agentId = int(agentId)
605
        self.callType = callType
15139 amit.gupta 606
        if retailerId is not None:
607
            self.retailerId = int(retailerId)
15208 amit.gupta 608
            retailerLink = session.query(RetailerLinks).filter_by(retailer_id=self.retailerId).first()
15132 amit.gupta 609
            if retailerLink is not None:
610
                code = retailerLink.code
611
            else: 
612
                code = self.getCode()
613
                retailerLink = RetailerLinks()
614
                retailerLink.code = code
15139 amit.gupta 615
                retailerLink.agent_id = self.agentId
616
                retailerLink.retailer_id = self.retailerId
15135 amit.gupta 617
 
618
                activationCode=Activation_Codes()
619
                activationCode.code = code
15132 amit.gupta 620
                session.commit()
621
            session.close()
15142 amit.gupta 622
            resp.body =  json.dumps({"result":{"code":code,"link":make_tiny(code)}}, encoding='utf-8')
15132 amit.gupta 623
            return 
15081 amit.gupta 624
        retryFlag = False 
625
        if RETAILER_DETAIL_CALL_COUNTER % DEALER_RETRY_FACTOR ==0:
626
            retryFlag=True
15239 amit.gupta 627
        try:
628
            if retryFlag:
629
                retailer = self.getRetryRetailer()
630
            else:
631
                retailer = self.getNewRetailer()
632
            fetchInfo = FetchDataHistory()
633
            fetchInfo.agent_id = self.agentId
634
            fetchInfo.call_type = self.callType
15240 amit.gupta 635
            agent = session.query(Agents).filter_by(id=self.agentId).first()
15239 amit.gupta 636
            last_disposition = session.query(CallHistory).filter_by(agent_id=self.agentId).order_by(CallHistory.id.desc()).first()
637
            if last_disposition is None or last_disposition.created < agent.last_login:
638
                fetchInfo.last_action = 'login'
639
                fetchInfo.last_action_time = agent.last_login 
640
            else:
641
                fetchInfo.last_action = 'disposition'
642
                fetchInfo.last_action_time = last_disposition.created
643
            fetchInfo.retailer_id = retailer.id
644
            session.commit()
15241 amit.gupta 645
 
646
            if retailer is None:
647
                resp.body = "{}"
648
            else:
649
                resp.body = json.dumps(todict(getRetailerObj(retailer)), encoding='utf-8')
650
 
651
            return
652
 
15239 amit.gupta 653
        finally:
654
            session.close()
15241 amit.gupta 655
 
15081 amit.gupta 656
        if retailer is None:
15157 amit.gupta 657
            resp.body = "{}"
15081 amit.gupta 658
        else:
659
            resp.body = json.dumps(todict(getRetailerObj(retailer)), encoding='utf-8')
660
 
15241 amit.gupta 661
 
15081 amit.gupta 662
    def on_post(self, req, resp, agentId, callType):
15112 amit.gupta 663
        returned = False
15081 amit.gupta 664
        self.agentId = int(agentId)
665
        self.callType = callType
666
        jsonReq = json.loads(req.stream.read(), encoding='utf-8')
15169 amit.gupta 667
        lgr.info( "Request ----\n"  + str(jsonReq))
15091 amit.gupta 668
        self.jsonReq = jsonReq
669
        invalidNumber = self.invalidNumber
670
        callLater = self.callLater
15096 amit.gupta 671
        alreadyUser = self.alReadyUser
15091 amit.gupta 672
        verifiedLinkSent = self.verifiedLinkSent
15278 amit.gupta 673
        self.address = jsonReq.get('address')
15096 amit.gupta 674
        self.retailerId = int(jsonReq.get('retailerid'))
15254 amit.gupta 675
        self.smsNumber = jsonReq.get('smsnumber') 
15112 amit.gupta 676
        try:
677
            self.retailer = session.query(Retailers).filter_by(id=self.retailerId).first()
15281 amit.gupta 678
            if self.address:
15278 amit.gupta 679
                self.retailer.address_new = self.address
15112 amit.gupta 680
            self.callDisposition = jsonReq.get('calldispositiontype')
681
            self.callHistory = CallHistory()
682
            self.callHistory.agent_id=self.agentId
683
            self.callHistory.call_disposition = self.callDisposition
684
            self.callHistory.retailer_id=self.retailerId
15115 amit.gupta 685
            self.callHistory.call_type=self.callType
15112 amit.gupta 686
            self.callHistory.duration_sec = int(jsonReq.get("callduration"))
687
            self.callHistory.disposition_description = jsonReq.get('calldispositiondescritption')
15200 manas 688
            self.callHistory.disposition_comments = jsonReq.get('calldispositioncomments')
689
            lgr.info(self.callHistory.disposition_comments)
15112 amit.gupta 690
            self.callHistory.call_time = datetime.strptime(jsonReq.get("calltime"), '%d/%m/%Y %H:%M:%S')
691
            self.callHistory.mobile_number = jsonReq.get('number')
15145 amit.gupta 692
            self.callHistory.sms_verified = int(jsonReq.get("verified"))
15234 amit.gupta 693
            lastFetchData = session.query(FetchDataHistory).filter_by(agent_id=self.agentId).order_by(FetchDataHistory.id.desc()).first()
694
            if lastFetchData is None:
695
                raise
696
            self.callHistory.last_fetch_time= lastFetchData.created  
15112 amit.gupta 697
 
698
            dispositionMap = {  'call_later':callLater,
699
                        'ringing_no_answer':callLater,
700
                        'not_reachable':callLater,
701
                        'switch_off':callLater,
15202 manas 702
                        'not_retailer':invalidNumber,
15112 amit.gupta 703
                        'invalid_no':invalidNumber,
704
                        'wrong_no':invalidNumber,
705
                        'hang_up':invalidNumber,
706
                        'retailer_not_interested':invalidNumber,
15200 manas 707
                        'recharge_retailer':invalidNumber,
708
                        'accessory_retailer':invalidNumber,
709
                        'service_center_retailer':invalidNumber,
15112 amit.gupta 710
                        'alreadyuser':alreadyUser,
711
                        'verified_link_sent':verifiedLinkSent
712
                      }
713
            returned = dispositionMap[jsonReq.get('calldispositiontype')]()
714
        finally:
715
            session.close()
15096 amit.gupta 716
 
15112 amit.gupta 717
        if returned:
718
            resp.body = "{\"result\":\"success\"}"
719
        else:
720
            resp.body = "{\"result\":\"failed\"}"
15081 amit.gupta 721
 
15091 amit.gupta 722
    def invalidNumber(self,):
15108 manas 723
        #self.retailer.status = 'retry' if self.callType == 'fresh' else 'fretry'
724
        if self.callDisposition == 'invalid_no':
725
            self.retailer.status='failed'
726
            self.callHistory.disposition_description = 'Invalid Number'
727
        elif self.callDisposition == 'wrong_no':
15111 manas 728
            self.retailer.status='failed'
729
            self.callHistory.disposition_description = 'Wrong Number'
730
        elif self.callDisposition == 'hang_up':
731
            self.retailer.status='failed'
732
            self.callHistory.disposition_description = 'Hang Up'
733
        elif self.callDisposition == 'retailer_not_interested':
734
            self.retailer.status='failed'
735
            if self.callHistory.disposition_description is None:
736
                self.callHistory.disposition_description = 'NA'
15200 manas 737
            self.callHistory.disposition_description = 'Reason Retailer Not Interested ' + self.callHistory.disposition_description
738
        elif self.callDisposition == 'recharge_retailer':
739
            self.retailer.status='failed'
740
            self.callHistory.disposition_description = 'Recharge related. Not a retailer '
741
        elif self.callDisposition == 'accessory_retailer':
742
            self.retailer.status='failed'
743
            self.callHistory.disposition_description = 'Accessory related. Not a retailer'
744
        elif self.callDisposition == 'service_center_retailer':
745
            self.retailer.status='failed'
746
            self.callHistory.disposition_description = 'Service Center related. Not a retailer'
15202 manas 747
        elif self.callDisposition == 'not_retailer':
748
            self.retailer.status='failed'
749
            self.callHistory.disposition_description = 'Not a retailer'    
15108 manas 750
        session.commit()
751
        return True   
752
 
15132 amit.gupta 753
    def getCode(self,):
15207 amit.gupta 754
        newCode = None
755
        lastLink = session.query(RetailerLinks).order_by(RetailerLinks.id.desc()).with_lockmode("update").first()
756
        if lastLink is not None:
757
            if len(lastLink.code)==len(codesys):
758
                newCode=lastLink.code
759
        return getNextCode(codesys, newCode)
15108 manas 760
 
15254 amit.gupta 761
 
15091 amit.gupta 762
    def callLater(self,):
15100 amit.gupta 763
        self.retailer.status = 'retry' if self.callType == 'fresh' else 'fretry'
764
        self.retailer.call_priority = None
15096 amit.gupta 765
        if self.callDisposition == 'call_later':
15100 amit.gupta 766
            if self.callHistory.disposition_description is not None:
15102 amit.gupta 767
                self.retailer.call_priority = 'user_initiated'
15096 amit.gupta 768
                self.retailer.next_call_time = datetime.strptime(self.callHistory.disposition_description, '%d/%m/%Y %H:%M:%S')
769
                self.callHistory.disposition_description = 'User requested to call on ' + self.callHistory.disposition_description
770
            else:
15102 amit.gupta 771
                self.retailer.call_priority = 'system_initiated'
15096 amit.gupta 772
                self.retailer.next_call_time = self.callHistory.call_time + timedelta(days=1)
15112 amit.gupta 773
                self.callHistory.disposition_description = 'Call scheduled on ' + datetime.strftime(self.retailer.next_call_time, '%d/%m/%Y %H:%M:%S')
774
        else: 
775
            if self.callDisposition == 'ringing_no_answer':
776
                if self.retailer.disposition == 'ringing_no_answer':
777
                    self.retailer.retry_count += 1
778
                else:
779
                    self.retailer.disposition = 'ringing_no_answer'
780
                    self.retailer.retry_count = 1
781
            else:
782
                if self.retailer.disposition == 'ringing_no_answer':
15122 amit.gupta 783
                    pass
15112 amit.gupta 784
                else:
15119 amit.gupta 785
                    self.retailer.disposition = 'not_reachable'
15122 amit.gupta 786
                self.retailer.retry_count += 1
787
                self.retailer.invalid_retry_count += 1
15119 amit.gupta 788
 
15122 amit.gupta 789
            retryConfig = session.query(RetryConfig).filter_by(call_type=self.callType, disposition_type=self.retailer.disposition, retry_count=self.retailer.retry_count).first()
15112 amit.gupta 790
            if retryConfig is not None:
791
                self.retailer.next_call_time = self.callHistory.call_time + timedelta(minutes = retryConfig.minutes_ahead)
15119 amit.gupta 792
                self.callHistory.disposition_description = 'Call scheduled on ' + datetime.strftime(self.retailer.next_call_time, '%d/%m/%Y %H:%M:%S')
15112 amit.gupta 793
            else:
794
                self.retailer.status = 'failed'
795
                self.callHistory.disposition_description = 'Call failed as all attempts exhausted'
15119 amit.gupta 796
 
15101 amit.gupta 797
        session.commit()
798
        return True
15096 amit.gupta 799
 
15100 amit.gupta 800
 
15091 amit.gupta 801
    def alReadyUser(self,):
15112 amit.gupta 802
        self.retailer.status = self.callDisposition
15117 amit.gupta 803
        if self.callHistory.disposition_description is None:
804
            self.callHistory.disposition_description = 'Retailer already user' 
15112 amit.gupta 805
        session.commit()
806
        return True
15091 amit.gupta 807
    def verifiedLinkSent(self,):
15147 amit.gupta 808
        if self.callType == 'fresh':
809
            self.retailer.status = 'followup'
810
            self.retailer.next_call_time = self.callHistory.call_time + timedelta(days=1)
811
            self.callHistory.disposition_description = 'App link sent via ' + self.callHistory.disposition_description+ '. followup on' + datetime.strftime(self.retailer.next_call_time, '%d/%m/%Y %H:%M:%S') 
812
        else:
15224 amit.gupta 813
            self.retailer.status = 'followup'
15147 amit.gupta 814
            self.retailer.next_call_time = self.callHistory.call_time + timedelta(days=7)
15254 amit.gupta 815
            self.callHistory.disposition_description = 'App link sent via' + self.callHistory.disposition_description + '. Followup again on ' + datetime.strftime(self.retailer.next_call_time, '%d/%m/%Y %H:%M:%S')
816
        addContactToRetailer(self.agentId, self.retailerId, self.smsNumber, self.callLater(), 'sms')     
15146 amit.gupta 817
        session.commit()
818
        return True
15254 amit.gupta 819
def isActivated(retailerId):
15276 amit.gupta 820
    retailerLink = session.query(RetailerLinks).filter_by(retailer_id=retailerId).first()
821
    user = session.query(Users).filter_by(referrer=retailerLink.code).first()
822
    if user is None:
823
        mobileNumbers = list(session.query(RetailerContacts.mobile_number).filter_by(retailer_id=retailerId).all())
824
        user = session.query(Users).filter(Users.mobile_number.in_(mobileNumbers)).first()
15254 amit.gupta 825
        if user is None:
15276 amit.gupta 826
            return False
827
        else:
828
            mapped_with = 'contact'
829
    else:
830
        mapped_with = 'code'
831
    retailerLink.mapped_with = mapped_with
832
    retailerLink.user_id = user.id
833
    retailer = session.query(Retailers).filter_by(id=retailerId)
834
    retailer.status = 'onboarded'
835
    session.commit()
836
    session.close()
837
    return True
15254 amit.gupta 838
 
839
class AddContactToRetailer():
840
    def on_post(self,req,resp, agentId):
841
        agentId = int(agentId)
842
        try:
843
            jsonReq = json.loads(req.stream.read(), encoding='utf-8')
844
            retailerId = int(jsonReq.get("retailerid"))
845
            mobile = jsonReq.get("mobile")
846
            callType = jsonReq.get("calltype")
847
            contactType = jsonReq.get("contacttype")
848
            addContactToRetailer(agentId, retailerId, mobile, callType, contactType)
849
            session.commit()
850
        finally:
851
            session.close()
852
 
853
def addContactToRetailer(agentId, retailerId, mobile, callType, contactType):
854
    retailerContacts = session.query(RetailerContacts).filter_by(retailer_id=retailerId).filter_by(mobile_number=mobile).first()
855
    if retailerContacts is None:
856
        retailerContact = RetailerContacts()
15256 amit.gupta 857
        retailerContact.retailer_id = retailerId
15254 amit.gupta 858
        retailerContact.agent_id = agentId
859
        retailerContact.call_type = callType
860
        retailerContact.contact_type = contactType
861
        retailerContact.mobile_number = mobile
862
 
15189 manas 863
class Login():
864
 
865
    def on_get(self, req, resp, agentId, role):
866
        try:
15198 manas 867
            self.agentId = int(agentId)
868
            self.role = role
869
            print str(self.agentId) + self.role;
15199 manas 870
            agents=AgentLoginTimings()
871
            lastLoginTime = session.query(Agents).filter(Agents.id==self.agentId).first()
872
            print 'lastLogintime' + str(lastLoginTime)
873
            agents.loginTime=lastLoginTime.last_login
874
            agents.logoutTime=datetime.now()
875
            agents.role =self.role
15282 amit.gupta 876
            agents.agent_id = self.agentId
15199 manas 877
            session.add(agents)    
878
            session.commit()
879
            resp.body =  json.dumps({"result":{"success":"true","message":"Success"}}, encoding='utf-8')
15189 manas 880
        finally:
881
            session.close()        
15112 amit.gupta 882
 
15189 manas 883
    def on_post(self,req,resp):
884
        try:
885
            jsonReq = json.loads(req.stream.read(), encoding='utf-8')
886
            lgr.info( "Request ----\n"  + str(jsonReq))
887
            email=jsonReq.get('email')
888
            password = jsonReq.get('password')
889
            role=jsonReq.get('role')    
890
            checkUser = session.query(Agents.id).filter(and_(Agents.email==email,Agents.password==password)).first()
891
            if checkUser is None:
892
                print checkUser
893
                resp.body =  json.dumps({"result":{"success":"false","message":"Invalid User"}}, encoding='utf-8')
894
            else:
895
                print checkUser[0]
896
                checkRole = session.query(Agent_Roles.id).filter(and_(Agent_Roles.agent_id==checkUser[0],Agent_Roles.role==role)).first()
897
                if checkRole is None:
898
                    resp.body =  json.dumps({"result":{"success":"false","message":"Invalid Role"}}, encoding='utf-8')
899
                else:
15196 manas 900
                    session.query(Agents).filter_by(id = checkUser[0]).update({"last_login":datetime.now()})
15195 manas 901
                    resp.body =  json.dumps({"result":{"success":"true","message":"Valid User","id":checkUser[0]}}, encoding='utf-8')
902
                    #session.query(Agents).filter_by(id = checkUser[0]).    
15189 manas 903
                    session.commit()
904
        finally:
905
            session.close()    
906
 
15195 manas 907
    def test(self,email,password,role):
15189 manas 908
        checkUser = session.query(Agents.id).filter(and_(Agents.email==email,Agents.password==password)).first()
909
        if checkUser is None:
910
            print checkUser
15195 manas 911
 
15189 manas 912
        else:
913
            print checkUser[0]
914
            checkRole = session.query(Agent_Roles.id).filter(and_(Agent_Roles.agent_id==checkUser[0],Agent_Roles.role==role)).first()
915
            if checkRole is None:
15195 manas 916
                pass
15189 manas 917
            else:
15195 manas 918
                agents=AgentLoginTimings()
919
                agents.loginTime=datetime.now()
920
                agents.logoutTime=datetime.now()
921
                agents.role =role
922
                agents.agent_id = 2
923
                #session.query(AgentLoginTimings).filter_by(id = checkUser[0]).update({"last_login":datetime.now()}, synchronize_session=False)
924
                session.add(agents)    
925
                session.commit()
926
                session.close()
927
 
928
                #session.query(Agents).filter(Agents.id==checkUser[0]).update({"last_login":Agents.last_login})
15275 amit.gupta 929
 
930
class RetailerActivation():
931
    def on_get(self, req, resp, userId):
932
        return markDealerActivation(int(userId))
933
 
934
def markDealerActivation(userId):
935
    try:
936
        user = session.query(Users).filter_by(id=userId)
937
        result = False                
938
        mappedWith = 'contact'
939
        if user is not None:
940
            retailerLink = session.query(RetailerLinks).filter_by(code=user.referrer).first()
941
            if retailerLink is None:
942
                retailerContact = session.query(RetailerContacts).filter_by(mobile_number=user.mobile_number).first()
943
                if retailerContact is None:
944
                    retailer = session.query(Retailers).filter(Retailers.status.in_(['followup', 'fretry'])).filter(or_(Retailers.contact1==user.mobile_number,Retailers.contact2==user.mobile_number)).first()
945
                else:
946
                    retailer = session.query(Retailers).filter_by(id = retailerContact.retailer_id).first()
947
            else:
948
                retailer = session.query(Retailers).filter_by(id = retailerLink.retailer_id).first()
949
                mappedWith='code'
950
            if retailer is not None:
951
                retailerLink = session.query(RetailerLinks).filter_by(retailer_id=retailer.id).first()
952
                if retailerLink is not None:
953
                    retailerLink.user_id = user.id
954
                    retailerLink.mapped_with=mappedWith
955
                    retailer.status = 'onboarded'
956
                    result = True
957
                    session.commit()
958
            return result
959
    finally:
960
        session.close()
961
 
15189 manas 962
 
15081 amit.gupta 963
def todict(obj, classkey=None):
964
    if isinstance(obj, dict):
965
        data = {}
966
        for (k, v) in obj.items():
967
            data[k] = todict(v, classkey)
968
        return data
969
    elif hasattr(obj, "_ast"):
970
        return todict(obj._ast())
971
    elif hasattr(obj, "__iter__"):
972
        return [todict(v, classkey) for v in obj]
973
    elif hasattr(obj, "__dict__"):
974
        data = dict([(key, todict(value, classkey)) 
975
            for key, value in obj.__dict__.iteritems() 
976
            if not callable(value) and not key.startswith('_')])
977
        if classkey is not None and hasattr(obj, "__class__"):
978
            data[classkey] = obj.__class__.__name__
979
        return data
980
    else:
981
        return obj
982
 
15279 amit.gupta 983
def getRetailerObj(retailer, otherContacts=[]):
15081 amit.gupta 984
    obj = Mock()
985
    obj.title = retailer.title
15280 amit.gupta 986
    obj.id = retailer.id
15279 amit.gupta 987
    if retailer.contact1 is not None and retailer.contact1 not in otherContacts:
988
        otherContacts.append(retailer.contact1)
989
    if retailer.contact2 is not None and retailer.contact2 not in otherContacts:
990
        otherContacts.append(retailer.contact2)
15276 amit.gupta 991
    obj.address = retailer.address_new if retailer.address_new is not None else retailer.address
15279 amit.gupta 992
    obj.contact1 = otherContacts[0]
993
    obj.contact2 = None if len(otherContacts)==1 else otherContacts[1]
15096 amit.gupta 994
    obj.scheduled = (retailer.call_priority is not None)
15081 amit.gupta 995
    return obj
15091 amit.gupta 996
 
15132 amit.gupta 997
def make_tiny(code):
998
    url = 'https://play.google.com/store/apps/details?id=com.saholic.profittill&referrer=utm_source%3D0%26utm_medium%3DCRM%26utm_term%3D001%26utm_campaign%3D' + code
999
    request_url = ('http://tinyurl.com/api-create.php?' + urlencode({'url':url}))
1000
    filehandle = urllib2.Request(request_url)
1001
    x= urllib2.urlopen(filehandle)
1002
    return str(x.read())
15171 amit.gupta 1003
 
1004
 
1005
#def update_pin():
15081 amit.gupta 1006
 
15132 amit.gupta 1007
 
15081 amit.gupta 1008
class Mock(object):
1009
    pass
15189 manas 1010
 
15081 amit.gupta 1011
def main():
15207 amit.gupta 1012
    print getNextCode(codesys, 'ZZ999')
15195 manas 1013
 
15081 amit.gupta 1014
if __name__ == '__main__':
15207 amit.gupta 1015
    main()
15091 amit.gupta 1016