Subversion Repositories SmartDukaan

Rev

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