Subversion Repositories SmartDukaan

Rev

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