Subversion Repositories SmartDukaan

Rev

Rev 8202 | Rev 8859 | 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 == '':
65
            coupon_code = uuid.uuid4().hex[:10] if prefix is None else prefix + uuid.uuid4().hex[:10]
66
        else:
67
            coupon_code = couponCode
6250 amit.gupta 68
        coupon = Coupon.get_by(coupon_code = coupon_code)
69
        while coupon is not None:
6561 amit.gupta 70
            coupon_code = uuid.uuid4().hex[:10] if prefix is None else prefix + uuid.uuid4().hex[:10]
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'):
75
            coupon_code = coupon_code +'#'+ 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()
168
        if not (coupon.promotion.start_on <=  todate and coupon.promotion.end_on >= todate):
6433 anupam.sin 169
            raise PromotionException(101, 'Promotion has expired')
6011 rajveer 170
 
1976 varun.gupt 171
        user_client = UserClient().get_client()
172
        cart = user_client.getCart(cart_id)
3554 varun.gupt 173
 
2389 varun.gupt 174
        coupon_module = coupon.promotion.rule_execution_src.strip()
175
 
176
        try:
3554 varun.gupt 177
            user_client.deleteDiscountsFromCart(cart_id)
2389 varun.gupt 178
            imported_coupon_module = __import__("shop2020.model.v1.user.promotionrules", globals(), locals(), [coupon_module])
179
            rule = eval("imported_coupon_module." + coupon_module)
2466 varun.gupt 180
 
8189 amit.gupta 181
            if coupon.promotion.id == 37:
182
                count = PromotionTracker.get_by(promotion_id = 37).count()
8190 amit.gupta 183
                if count >= 2013:
8189 amit.gupta 184
                    raise PromotionException(112, 'This promotion is over.')
185
 
2466 varun.gupt 186
            args = eval(coupon.arguments) if coupon.arguments is not None else {}
187
 
6736 amit.gupta 188
            '''
189
            Processing in case of EMI
190
            '''
191
            if coupon.promotion.type == 2:
192
                updated_cart = rule.execute(cart, coupon_code, args)
193
 
194
            else:
195
                updated_cart, discounts = rule.execute(cart, coupon_code, args)
196
                if discounts and len(discounts) > 0:    
197
                    user_client.saveDiscounts(discounts)
198
 
6922 anupam.sin 199
            user_client.applyCouponToCart(updated_cart, coupon_code)
3554 varun.gupt 200
 
2389 varun.gupt 201
            return updated_cart
202
 
203
        except ImportError as e:
204
            traceback.print_stack()
205
            #TODO: Better message
206
            raise PromotionException(100, 'Internal error occurred.')
1976 varun.gupt 207
    else:
208
        print 'Invalid Coupon Code'
209
        raise PromotionException(101, 'Invalid Coupon Code')
210
 
6736 amit.gupta 211
def get_emi_discount(cart_id):
212
    try:
213
        user_client = UserClient().get_client()
214
        cart = user_client.getCart(cart_id)
6738 amit.gupta 215
        if not (cart.couponCode is None or cart.couponCode == ""):
216
            coupon = Coupon.get_by(coupon_code = cart.couponCode)
217
            args = eval(coupon.arguments) if coupon.arguments is not None else {}
218
            if coupon.promotion.type != 2:
219
                return {}
220
            else:
221
                return rule_specific_emi_discount_on_specific_items.getEmiDiscounts(cart, coupon.coupon_code, args)
222
        else:
6736 amit.gupta 223
            return {}
224
 
225
    except ImportError as e:
226
        traceback.print_stack()
227
        return {}
228
 
1976 varun.gupt 229
def track_coupon_usage(coupon_code, transaction_id, user_id):
7987 amit.gupta 230
    coupon = Coupon.query.filter_by(coupon_code=coupon_code).one()
1976 varun.gupt 231
    promotion_tracker = PromotionTracker()
232
    promotion_tracker.coupon_code = coupon_code
233
    promotion_tracker.transaction_id = transaction_id
234
    promotion_tracker.user_id = user_id
7987 amit.gupta 235
    promotion_tracker.promotion_id = coupon.promotion.id
1976 varun.gupt 236
    promotion_tracker.applied_on = datetime.datetime.now()
237
    session.commit()
238
 
3386 varun.gupt 239
def get_active_coupons():
240
    return Coupon.query.all()
241
 
242
def get_successful_payment_count_for_coupon(coupon_code):
243
    return PromotionTracker.query.filter_by(coupon_code = coupon_code).count()
244
 
245
def get_rule_doc_string(rule_name):
246
    imported_coupon_module = __import__("shop2020.model.v1.user.promotionrules", globals(), locals(), [rule_name])
247
    rule = eval("imported_coupon_module." + rule_name)
248
    return rule.__doc__
4189 varun.gupt 249
 
1976 varun.gupt 250
def close_session():
251
    if session.is_active:
3376 rajveer 252
        session.close()
4189 varun.gupt 253
 
3376 rajveer 254
def is_alive():
255
    try:
256
        session.query(Promotion.id).limit(1).one()
257
        return True
258
    except:
4189 varun.gupt 259
        return False
260
 
4494 varun.gupt 261
def get_discounts_for_entity(entity_id):
262
    catalog_client = CatalogClient().get_client()
263
    items = catalog_client.getItemsByCatalogId(entity_id)
264
 
265
    discount_finder = ItemDiscountFinder()
266
    discounts = discount_finder.getCouponsAndDiscountsOnItem(items[0])
267
 
268
    if len(discounts) > 0:
269
        return {discounts[0][0]: discounts[0][1]}
270
    else:
271
        return {}
272
 
4189 varun.gupt 273
def get_item_discount_map(item_ids):
274
 
275
    discount_finder = ItemDiscountFinder()
276
    item_coupons_discounts = []
277
 
278
    catalog_client = CatalogClient().get_client()
279
 
280
    for item_id in item_ids:
281
        item = catalog_client.getItem(item_id)
282
 
283
        discounts = discount_finder.getCouponsAndDiscountsOnItem(item)
284
 
285
        for discount in discounts:
286
            item_coupons_discounts.append((item_id, discount[0], discount[1]))
287
            break
288
 
289
    return item_coupons_discounts
290
 
6497 amit.gupta 291
def get_active_gvs(promotion_id):
6570 amit.gupta 292
    all_coupons = session.query(Coupon).filter_by(promotion_id=promotion_id).filter(~exists().where(Coupon.coupon_code==PromotionTracker.coupon_code)).all()
6497 amit.gupta 293
    return [to_t_coupon(coupon) for coupon in all_coupons]
294
 
295
def delete_coupon(coupon_code):
296
    Coupon.query.filter_by(coupon_code = coupon_code).delete()
297
    session.commit()
298
 
7092 amit.gupta 299
def get_all_coupons_by_promotion_id(promotion_id):
300
    all_coupons = Coupon.query.filter_by(promotion_id = promotion_id).all()
301
    return [to_t_coupon(coupon) for coupon in all_coupons]
302
 
303
 
304
 
5469 rajveer 305
def add_voucher(t_voucher):
306
    voucher = RechargeVoucher()
307
    voucher.available = True
308
    voucher.amount = t_voucher.amount
309
    voucher.voucherCode = t_voucher.voucherCode
310
    voucher.voucherType = t_voucher.voucherType
311
    if t_voucher.issuedOn:
312
        voucher.issuedOn = to_py_date(t_voucher.issuedOn)
313
    if t_voucher.expiredOn:
314
        voucher.expiredOn = to_py_date(t_voucher.expiredOn)
315
    session.commit()
316
 
317
def assign_voucher(userId, userEmail, voucherType, amount):
318
    voucher = RechargeVoucher.query.filter_by(voucherType = voucherType, amount = amount, available = True).first()
319
    if not voucher:
320
        raise PromotionException(501, 'Voucher of this type is not available.')
321
    voucher.userId = userId
322
    voucher.available = False
323
    voucher.issuedOn = datetime.datetime.now()
324
    voucher.email = userEmail
325
    session.commit()
326
    return voucher
327
 
328
def mark_voucher_as_redeemed(voucherCode, redeemedOn):
329
    voucher = RechargeVoucher.query.filter_by(voucherCode = voucherCode).first()
330
    voucher.redeemedOn = to_py_date(redeemedOn)
331
    voucher.redeemed = True
332
    session.commit()
333
    return True
334
 
4189 varun.gupt 335
class ItemDiscountFinder:
336
 
337
    def __init__(self):
338
        self.coupon_modules = {}
339
        coupons = get_active_coupons()
340
 
341
        for coupon in coupons:
5996 amit.gupta 342
            if coupon.coupon_code not in ('SAHOLIC4RS', 'SAndroid', 'SAHOLIC4MJ', 'SAHOLIC4SS', 'SJunglee'):
4189 varun.gupt 343
                coupon_rule = coupon.promotion.rule_execution_src.strip()
344
 
345
                imported_coupon_module = __import__("shop2020.model.v1.user.promotionrules", globals(), locals(), [coupon_rule])
346
                self.coupon_modules[coupon.coupon_code] = eval("imported_coupon_module." + coupon_rule)
347
 
348
    def getCouponsAndDiscountsOnItem(self, item):
349
        discounts = []
350
 
351
        for coupon_code, coupon_rule_module in self.coupon_modules.iteritems():
352
 
353
            discount = coupon_rule_module.getDiscountOnItem(item)
354
 
355
            if discount is not None:
356
                discounts.append((coupon_code, discount))
357
 
358
        return discounts