Subversion Repositories SmartDukaan

Rev

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