Subversion Repositories SmartDukaan

Rev

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