Subversion Repositories SmartDukaan

Rev

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

Rev Author Line No. Line
1976 varun.gupt 1
'''
2
Created on May 24, 2010
3
@author: Varun Gupta
4
'''
6497 amit.gupta 5
from elixir import session
6
from shop2020.clients.CatalogClient import CatalogClient
1976 varun.gupt 7
from shop2020.clients.UserClient import UserClient
6497 amit.gupta 8
from shop2020.model.v1.user.impl import Dataservice
9
from shop2020.model.v1.user.impl.Dataservice import Promotion, Coupon, \
10
    PromotionTracker, RechargeVoucher
11
from shop2020.model.v1.user.impl.PromotionRuleDataUtilities import \
12
    get_coupon_usage_count, get_coupon_usage_count_by_user
1976 varun.gupt 13
from shop2020.thriftpy.model.v1.user.ttypes import PromotionException
14
from shop2020.utils.Utils import to_py_date
6497 amit.gupta 15
from sqlalchemy.sql.expression import exists
16
from string import Template
17
import datetime
18
import traceback
6250 amit.gupta 19
import uuid
6497 amit.gupta 20
from shop2020.model.v1.user.impl.Converters import to_t_coupon
6736 amit.gupta 21
from shop2020.model.v1.user.promotionrules import rule_specific_emi_discount_on_specific_items
8707 manish.sha 22
import ast
1976 varun.gupt 23
 
24
 
3187 rajveer 25
def initialize(dbname = 'user', db_hostname="localhost"):
26
    Dataservice.initialize(dbname, db_hostname)
1976 varun.gupt 27
 
28
def create_promotion(name, rule_execution_src, start_on, end_on):
29
    promotion = Promotion()
30
    promotion.name = name
31
    promotion.rule_execution_src = rule_execution_src
32
    promotion.start_on = to_py_date(start_on)
33
    promotion.end_on = to_py_date(end_on)
34
    promotion.created_on = datetime.datetime.now()
35
    session.commit()
36
 
37
def get_all_promotions():
38
    return Promotion.query.all()
39
 
40
def generate_coupons_for_promotion(promotion_id, coupon_code):
41
    promotion = Promotion.get_by(id = promotion_id)
42
 
43
    coupon = Coupon()
44
    coupon.promotion = promotion
45
    coupon.coupon_code = coupon_code
46
    coupon.arguments = ""
47
    session.commit()
7746 amit.gupta 48
 
49
def remove_all_coupons_by_promotion_id(promotion_id):
50
    promotion = Promotion.get_by(id=promotion_id)
51
    if(promotion is None):
52
        raise PromotionException(101, 'Could not find Promotion for id' + str(promotion_id))
53
    elif(promotion.end_on > datetime.datetime.now()):
54
        raise PromotionException(111, 'This promotion is still running. Promotion id' + str(promotion_id))
55
    deletecount = Coupon.query.filter_by(promotion_id = promotion_id).delete()
56
    session.commit()
57
    return deletecount
1976 varun.gupt 58
 
8707 manish.sha 59
def create_coupon(promotionId, couponCategory, couponCode, arguments, isCod, prefix=None):
6649 amit.gupta 60
    if promotionId not in (26,27,28):
6367 amit.gupta 61
        raise PromotionException(101, 'Only promotion ids 26 and 27 are expected')
6250 amit.gupta 62
    promotion = Promotion.get_by(id = promotionId)
6730 anupam.sin 63
    if promotion:
64
        if couponCode == '':
8859 manish.sha 65
            coupon_code = uuid.uuid4().hex[:10] if prefix is None else prefix + uuid.uuid4().hex[:6]
6730 anupam.sin 66
        else:
67
            coupon_code = couponCode
6250 amit.gupta 68
        coupon = Coupon.get_by(coupon_code = coupon_code)
69
        while coupon is not None:
8859 manish.sha 70
            coupon_code = uuid.uuid4().hex[:10] if prefix is None else prefix + uuid.uuid4().hex[:6]
6250 amit.gupta 71
            coupon = Coupon.get_by(coupon_code = coupon_code)
8707 manish.sha 72
 
73
        arguments_map= ast.literal_eval(arguments)
74
        if arguments_map.has_key('orderId'):
8859 manish.sha 75
            coupon_code = coupon_code + 'Id' +str(arguments_map['orderId'])
6250 amit.gupta 76
        coupon = Coupon()
77
        coupon.promotion = promotion
78
        coupon.coupon_code = coupon_code
6679 anupam.sin 79
        coupon.arguments = arguments
8707 manish.sha 80
        coupon.coupon_category = couponCategory
6250 amit.gupta 81
        session.commit()
82
        return coupon_code
83
    else:
84
        raise PromotionException(101, 'Could not find Promotion for id' + str(promotionId))
6301 amit.gupta 85
 
86
def get_coupon(coupon_code):
87
    return Coupon.get_by(coupon_code = coupon_code)
6250 amit.gupta 88
 
6433 anupam.sin 89
def apply_recharge_coupon(coupon_code, total_amount, user_id):
90
    coupon = Coupon.get_by(coupon_code = coupon_code)
91
    discount = 0
92
    if coupon:
93
        args = eval(coupon.arguments) if coupon.arguments is not None else {}
94
 
6679 anupam.sin 95
        todate = datetime.datetime.now()
96
        if 'endOn' in args and todate > to_py_date(args['endOn']) :
97
            return {0:'This coupon has expired'}
6443 anupam.sin 98
 
6433 anupam.sin 99
        if 'minDiscountableVal' in args and total_amount < int(args['minDiscountableVal']):
8202 anupam.sin 100
            return {0:'This coupon is valid for purchases equal to or more than Rs.' + str((args['minDiscountableVal']))}
6433 anupam.sin 101
 
6680 anupam.sin 102
        if 'couponType' not in args or args['couponType'] not in ('recharge','both'):
6433 anupam.sin 103
            return {0:'Invalid Coupon'}
104
 
6730 anupam.sin 105
        isUserSpecific = False
106
 
6679 anupam.sin 107
        if args['emails'] != '*':
108
            user_client = UserClient().get_client()
109
            user = user_client.getUserById(user_id)
6730 anupam.sin 110
            isUserSpecific = True
6680 anupam.sin 111
            if user.email not in args['emails']:
6679 anupam.sin 112
                return {0:'Invalid coupon'}
113
 
114
        if 'startHour' in args and 'startMinute' in args and 'endHour' in args and 'endMinute' in args :
6433 anupam.sin 115
            startHour = int(args['startHour'])
116
            startMinute = int(args['startMinute'])
6679 anupam.sin 117
            endHour = int(args['endHour'])   
6433 anupam.sin 118
            endMinute = int(args['endMinute'])
6679 anupam.sin 119
            now = datetime.datetime.now()
120
            curtime = datetime.time(now.hour, now.minute, now.second)
121
            starttime = datetime.time(startHour, startMinute, 0)
122
            endtime = datetime.time(endHour, endMinute, 0)
123
            if (curtime < starttime or curtime > endtime):
124
                return {0:'Currently this coupon is unavailable'}
6433 anupam.sin 125
 
6679 anupam.sin 126
        if 'usage_limit_for_user' in args :
127
            userLimit = args['usage_limit_for_user']
6443 anupam.sin 128
        else :
6679 anupam.sin 129
            userLimit = 1
6443 anupam.sin 130
 
6433 anupam.sin 131
        count_coupon_usage_by_user = get_coupon_usage_count_by_user(coupon_code, user_id)
6443 anupam.sin 132
        if count_coupon_usage_by_user >= userLimit:
6758 anupam.sin 133
            return {0:'Invalid Coupon'}
6433 anupam.sin 134
 
6443 anupam.sin 135
        if 'globalLimit' in args :
136
            globalLimit = args['globalLimit']
6679 anupam.sin 137
            count_coupon_usage = get_coupon_usage_count(coupon_code)
138
            if count_coupon_usage >= globalLimit:
139
                return {0:'This promotion is over.'}
6443 anupam.sin 140
 
6679 anupam.sin 141
        if 'discountType' in args:
142
            discountType = args['discountType']
6688 anupam.sin 143
        else :
144
            discountType = 'absolute' #Default is absolute
145
 
146
        if discountType == 'percent' :
147
            discount = round(total_amount * (args['discount']/float(100)))
148
        elif discountType == 'absolute' :
149
            discount = min(args['discount'], total_amount)
150
        else :
151
            return {0 : 'Invalid coupon'}
6433 anupam.sin 152
 
153
        if 'maxDiscount' in args and discount > int(args['maxDiscount']):
154
            return {int(args['maxDiscount']):"Coupon Applied"}
155
 
6730 anupam.sin 156
        if isUserSpecific :
157
            return {discount:'login'}
158
 
6433 anupam.sin 159
        return {discount:'Coupon Applied'}
160
    else:
161
        return {0:'Invalid Coupon'}
162
 
1976 varun.gupt 163
def apply_coupon(coupon_code, cart_id):
164
    coupon = Coupon.get_by(coupon_code = coupon_code)
165
 
166
    if coupon:
6011 rajveer 167
        todate = datetime.datetime.now()
13247 amit.gupta 168
        if not coupon.promotion.start_on <=  todate:
169
            raise PromotionException(101, 'Invalid coupon')
170
        if not coupon.promotion.end_on >= todate:
6433 anupam.sin 171
            raise PromotionException(101, 'Promotion has expired')
13247 amit.gupta 172
 
6011 rajveer 173
 
1976 varun.gupt 174
        user_client = UserClient().get_client()
175
        cart = user_client.getCart(cart_id)
3554 varun.gupt 176
 
2389 varun.gupt 177
        coupon_module = coupon.promotion.rule_execution_src.strip()
178
 
179
        try:
3554 varun.gupt 180
            user_client.deleteDiscountsFromCart(cart_id)
2389 varun.gupt 181
            imported_coupon_module = __import__("shop2020.model.v1.user.promotionrules", globals(), locals(), [coupon_module])
182
            rule = eval("imported_coupon_module." + coupon_module)
2466 varun.gupt 183
 
8189 amit.gupta 184
            if coupon.promotion.id == 37:
185
                count = PromotionTracker.get_by(promotion_id = 37).count()
8190 amit.gupta 186
                if count >= 2013:
8189 amit.gupta 187
                    raise PromotionException(112, 'This promotion is over.')
188
 
2466 varun.gupt 189
            args = eval(coupon.arguments) if coupon.arguments is not None else {}
190
 
6736 amit.gupta 191
            '''
192
            Processing in case of EMI
193
            '''
194
            if coupon.promotion.type == 2:
195
                updated_cart = rule.execute(cart, coupon_code, args)
196
 
197
            else:
198
                updated_cart, discounts = rule.execute(cart, coupon_code, args)
199
                if discounts and len(discounts) > 0:    
200
                    user_client.saveDiscounts(discounts)
201
 
6922 anupam.sin 202
            user_client.applyCouponToCart(updated_cart, coupon_code)
3554 varun.gupt 203
 
2389 varun.gupt 204
            return updated_cart
205
 
206
        except ImportError as e:
207
            traceback.print_stack()
208
            #TODO: Better message
209
            raise PromotionException(100, 'Internal error occurred.')
1976 varun.gupt 210
    else:
211
        print 'Invalid Coupon Code'
212
        raise PromotionException(101, 'Invalid Coupon Code')
213
 
6736 amit.gupta 214
def get_emi_discount(cart_id):
215
    try:
216
        user_client = UserClient().get_client()
217
        cart = user_client.getCart(cart_id)
6738 amit.gupta 218
        if not (cart.couponCode is None or cart.couponCode == ""):
219
            coupon = Coupon.get_by(coupon_code = cart.couponCode)
220
            args = eval(coupon.arguments) if coupon.arguments is not None else {}
221
            if coupon.promotion.type != 2:
222
                return {}
223
            else:
224
                return rule_specific_emi_discount_on_specific_items.getEmiDiscounts(cart, coupon.coupon_code, args)
225
        else:
6736 amit.gupta 226
            return {}
227
 
228
    except ImportError as e:
229
        traceback.print_stack()
230
        return {}
231
 
13521 amit.gupta 232
def track_coupon_usage(coupon_code, transaction_id, user_id, amount, is_digital):
7987 amit.gupta 233
    coupon = Coupon.query.filter_by(coupon_code=coupon_code).one()
1976 varun.gupt 234
    promotion_tracker = PromotionTracker()
235
    promotion_tracker.coupon_code = coupon_code
236
    promotion_tracker.transaction_id = transaction_id
237
    promotion_tracker.user_id = user_id
7987 amit.gupta 238
    promotion_tracker.promotion_id = coupon.promotion.id
1976 varun.gupt 239
    promotion_tracker.applied_on = datetime.datetime.now()
13521 amit.gupta 240
    promotion_tracker.amount = amount
241
    promotion_tracker.is_digital = is_digital
1976 varun.gupt 242
    session.commit()
243
 
3386 varun.gupt 244
def get_active_coupons():
245
    return Coupon.query.all()
246
 
247
def get_successful_payment_count_for_coupon(coupon_code):
248
    return PromotionTracker.query.filter_by(coupon_code = coupon_code).count()
249
 
250
def get_rule_doc_string(rule_name):
251
    imported_coupon_module = __import__("shop2020.model.v1.user.promotionrules", globals(), locals(), [rule_name])
252
    rule = eval("imported_coupon_module." + rule_name)
253
    return rule.__doc__
4189 varun.gupt 254
 
1976 varun.gupt 255
def close_session():
256
    if session.is_active:
3376 rajveer 257
        session.close()
4189 varun.gupt 258
 
3376 rajveer 259
def is_alive():
260
    try:
261
        session.query(Promotion.id).limit(1).one()
262
        return True
263
    except:
4189 varun.gupt 264
        return False
265
 
4494 varun.gupt 266
def get_discounts_for_entity(entity_id):
267
    catalog_client = CatalogClient().get_client()
268
    items = catalog_client.getItemsByCatalogId(entity_id)
269
 
270
    discount_finder = ItemDiscountFinder()
271
    discounts = discount_finder.getCouponsAndDiscountsOnItem(items[0])
272
 
273
    if len(discounts) > 0:
274
        return {discounts[0][0]: discounts[0][1]}
275
    else:
276
        return {}
277
 
4189 varun.gupt 278
def get_item_discount_map(item_ids):
279
 
280
    discount_finder = ItemDiscountFinder()
281
    item_coupons_discounts = []
282
 
283
    catalog_client = CatalogClient().get_client()
284
 
285
    for item_id in item_ids:
286
        item = catalog_client.getItem(item_id)
287
 
288
        discounts = discount_finder.getCouponsAndDiscountsOnItem(item)
289
 
290
        for discount in discounts:
291
            item_coupons_discounts.append((item_id, discount[0], discount[1]))
292
            break
293
 
294
    return item_coupons_discounts
295
 
6497 amit.gupta 296
def get_active_gvs(promotion_id):
6570 amit.gupta 297
    all_coupons = session.query(Coupon).filter_by(promotion_id=promotion_id).filter(~exists().where(Coupon.coupon_code==PromotionTracker.coupon_code)).all()
6497 amit.gupta 298
    return [to_t_coupon(coupon) for coupon in all_coupons]
299
 
300
def delete_coupon(coupon_code):
301
    Coupon.query.filter_by(coupon_code = coupon_code).delete()
302
    session.commit()
303
 
7092 amit.gupta 304
def get_all_coupons_by_promotion_id(promotion_id):
305
    all_coupons = Coupon.query.filter_by(promotion_id = promotion_id).all()
306
    return [to_t_coupon(coupon) for coupon in all_coupons]
307
 
308
 
309
 
5469 rajveer 310
def add_voucher(t_voucher):
311
    voucher = RechargeVoucher()
312
    voucher.available = True
313
    voucher.amount = t_voucher.amount
314
    voucher.voucherCode = t_voucher.voucherCode
315
    voucher.voucherType = t_voucher.voucherType
316
    if t_voucher.issuedOn:
317
        voucher.issuedOn = to_py_date(t_voucher.issuedOn)
318
    if t_voucher.expiredOn:
319
        voucher.expiredOn = to_py_date(t_voucher.expiredOn)
320
    session.commit()
321
 
322
def assign_voucher(userId, userEmail, voucherType, amount):
323
    voucher = RechargeVoucher.query.filter_by(voucherType = voucherType, amount = amount, available = True).first()
324
    if not voucher:
325
        raise PromotionException(501, 'Voucher of this type is not available.')
326
    voucher.userId = userId
327
    voucher.available = False
328
    voucher.issuedOn = datetime.datetime.now()
329
    voucher.email = userEmail
330
    session.commit()
331
    return voucher
332
 
333
def mark_voucher_as_redeemed(voucherCode, redeemedOn):
334
    voucher = RechargeVoucher.query.filter_by(voucherCode = voucherCode).first()
335
    voucher.redeemedOn = to_py_date(redeemedOn)
336
    voucher.redeemed = True
337
    session.commit()
338
    return True
339
 
4189 varun.gupt 340
class ItemDiscountFinder:
341
 
342
    def __init__(self):
343
        self.coupon_modules = {}
344
        coupons = get_active_coupons()
345
 
346
        for coupon in coupons:
5996 amit.gupta 347
            if coupon.coupon_code not in ('SAHOLIC4RS', 'SAndroid', 'SAHOLIC4MJ', 'SAHOLIC4SS', 'SJunglee'):
4189 varun.gupt 348
                coupon_rule = coupon.promotion.rule_execution_src.strip()
349
 
350
                imported_coupon_module = __import__("shop2020.model.v1.user.promotionrules", globals(), locals(), [coupon_rule])
351
                self.coupon_modules[coupon.coupon_code] = eval("imported_coupon_module." + coupon_rule)
352
 
353
    def getCouponsAndDiscountsOnItem(self, item):
354
        discounts = []
355
 
356
        for coupon_code, coupon_rule_module in self.coupon_modules.iteritems():
357
 
358
            discount = coupon_rule_module.getDiscountOnItem(item)
359
 
360
            if discount is not None:
361
                discounts.append((coupon_code, discount))
362
 
363
        return discounts