Subversion Repositories SmartDukaan

Rev

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