Subversion Repositories SmartDukaan

Rev

Rev 13521 | 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():
35718 amit 256
    session.remove()
4189 varun.gupt 257
 
3376 rajveer 258
def is_alive():
259
    try:
260
        session.query(Promotion.id).limit(1).one()
261
        return True
262
    except:
4189 varun.gupt 263
        return False
264
 
4494 varun.gupt 265
def get_discounts_for_entity(entity_id):
266
    catalog_client = CatalogClient().get_client()
267
    items = catalog_client.getItemsByCatalogId(entity_id)
268
 
269
    discount_finder = ItemDiscountFinder()
270
    discounts = discount_finder.getCouponsAndDiscountsOnItem(items[0])
271
 
272
    if len(discounts) > 0:
273
        return {discounts[0][0]: discounts[0][1]}
274
    else:
275
        return {}
276
 
4189 varun.gupt 277
def get_item_discount_map(item_ids):
278
 
279
    discount_finder = ItemDiscountFinder()
280
    item_coupons_discounts = []
281
 
282
    catalog_client = CatalogClient().get_client()
283
 
284
    for item_id in item_ids:
285
        item = catalog_client.getItem(item_id)
286
 
287
        discounts = discount_finder.getCouponsAndDiscountsOnItem(item)
288
 
289
        for discount in discounts:
290
            item_coupons_discounts.append((item_id, discount[0], discount[1]))
291
            break
292
 
293
    return item_coupons_discounts
294
 
6497 amit.gupta 295
def get_active_gvs(promotion_id):
6570 amit.gupta 296
    all_coupons = session.query(Coupon).filter_by(promotion_id=promotion_id).filter(~exists().where(Coupon.coupon_code==PromotionTracker.coupon_code)).all()
6497 amit.gupta 297
    return [to_t_coupon(coupon) for coupon in all_coupons]
298
 
299
def delete_coupon(coupon_code):
300
    Coupon.query.filter_by(coupon_code = coupon_code).delete()
301
    session.commit()
302
 
7092 amit.gupta 303
def get_all_coupons_by_promotion_id(promotion_id):
304
    all_coupons = Coupon.query.filter_by(promotion_id = promotion_id).all()
305
    return [to_t_coupon(coupon) for coupon in all_coupons]
306
 
307
 
308
 
5469 rajveer 309
def add_voucher(t_voucher):
310
    voucher = RechargeVoucher()
311
    voucher.available = True
312
    voucher.amount = t_voucher.amount
313
    voucher.voucherCode = t_voucher.voucherCode
314
    voucher.voucherType = t_voucher.voucherType
315
    if t_voucher.issuedOn:
316
        voucher.issuedOn = to_py_date(t_voucher.issuedOn)
317
    if t_voucher.expiredOn:
318
        voucher.expiredOn = to_py_date(t_voucher.expiredOn)
319
    session.commit()
320
 
321
def assign_voucher(userId, userEmail, voucherType, amount):
322
    voucher = RechargeVoucher.query.filter_by(voucherType = voucherType, amount = amount, available = True).first()
323
    if not voucher:
324
        raise PromotionException(501, 'Voucher of this type is not available.')
325
    voucher.userId = userId
326
    voucher.available = False
327
    voucher.issuedOn = datetime.datetime.now()
328
    voucher.email = userEmail
329
    session.commit()
330
    return voucher
331
 
332
def mark_voucher_as_redeemed(voucherCode, redeemedOn):
333
    voucher = RechargeVoucher.query.filter_by(voucherCode = voucherCode).first()
334
    voucher.redeemedOn = to_py_date(redeemedOn)
335
    voucher.redeemed = True
336
    session.commit()
337
    return True
338
 
4189 varun.gupt 339
class ItemDiscountFinder:
340
 
341
    def __init__(self):
342
        self.coupon_modules = {}
343
        coupons = get_active_coupons()
344
 
345
        for coupon in coupons:
5996 amit.gupta 346
            if coupon.coupon_code not in ('SAHOLIC4RS', 'SAndroid', 'SAHOLIC4MJ', 'SAHOLIC4SS', 'SJunglee'):
4189 varun.gupt 347
                coupon_rule = coupon.promotion.rule_execution_src.strip()
348
 
349
                imported_coupon_module = __import__("shop2020.model.v1.user.promotionrules", globals(), locals(), [coupon_rule])
350
                self.coupon_modules[coupon.coupon_code] = eval("imported_coupon_module." + coupon_rule)
351
 
352
    def getCouponsAndDiscountsOnItem(self, item):
353
        discounts = []
354
 
355
        for coupon_code, coupon_rule_module in self.coupon_modules.iteritems():
356
 
357
            discount = coupon_rule_module.getDiscountOnItem(item)
358
 
359
            if discount is not None:
360
                discounts.append((coupon_code, discount))
361
 
362
        return discounts