Subversion Repositories SmartDukaan

Rev

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