Subversion Repositories SmartDukaan

Rev

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