Subversion Repositories SmartDukaan

Rev

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