Subversion Repositories SmartDukaan

Rev

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