Subversion Repositories SmartDukaan

Rev

Rev 6679 | Rev 6688 | 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']
120
            if discountType == 'percent' :
6680 anupam.sin 121
                discount = round(total_amount * (args['discount']/float(100)))
122
            elif discountType == 'absolute' :
6679 anupam.sin 123
                discount = min(args['discount'], total_amount)
124
            else :
125
                return {0 : 'Invalid coupon'}
6433 anupam.sin 126
 
127
        if 'maxDiscount' in args and discount > int(args['maxDiscount']):
128
            return {int(args['maxDiscount']):"Coupon Applied"}
129
 
130
        return {discount:'Coupon Applied'}
131
    else:
132
        return {0:'Invalid Coupon'}
133
 
1976 varun.gupt 134
def apply_coupon(coupon_code, cart_id):
135
    coupon = Coupon.get_by(coupon_code = coupon_code)
136
 
137
    if coupon:
6011 rajveer 138
        todate = datetime.datetime.now()
139
        if not (coupon.promotion.start_on <=  todate and coupon.promotion.end_on >= todate):
6433 anupam.sin 140
            raise PromotionException(101, 'Promotion has expired')
6011 rajveer 141
 
1976 varun.gupt 142
        user_client = UserClient().get_client()
143
        cart = user_client.getCart(cart_id)
3554 varun.gupt 144
 
2389 varun.gupt 145
        coupon_module = coupon.promotion.rule_execution_src.strip()
146
 
147
        try:
3554 varun.gupt 148
            user_client.deleteDiscountsFromCart(cart_id)
2389 varun.gupt 149
            imported_coupon_module = __import__("shop2020.model.v1.user.promotionrules", globals(), locals(), [coupon_module])
150
            rule = eval("imported_coupon_module." + coupon_module)
2466 varun.gupt 151
 
152
            args = eval(coupon.arguments) if coupon.arguments is not None else {}
153
 
3554 varun.gupt 154
            updated_cart, discounts = rule.execute(cart, coupon_code, args)
155
 
156
            if discounts and len(discounts) > 0:    user_client.saveDiscounts(discounts)
157
 
2389 varun.gupt 158
            user_client.applyCouponToCart(cart_id, coupon_code, updated_cart.totalPrice, updated_cart.discountedPrice)
3554 varun.gupt 159
 
2389 varun.gupt 160
            return updated_cart
161
 
162
        except ImportError as e:
163
            traceback.print_stack()
164
            #TODO: Better message
165
            raise PromotionException(100, 'Internal error occurred.')
1976 varun.gupt 166
    else:
167
        print 'Invalid Coupon Code'
168
        raise PromotionException(101, 'Invalid Coupon Code')
169
 
170
def track_coupon_usage(coupon_code, transaction_id, user_id):
171
    promotion_tracker = PromotionTracker()
172
    promotion_tracker.coupon_code = coupon_code
173
    promotion_tracker.transaction_id = transaction_id
174
    promotion_tracker.user_id = user_id
175
    promotion_tracker.applied_on = datetime.datetime.now()
176
    session.commit()
177
 
3386 varun.gupt 178
def get_active_coupons():
179
    return Coupon.query.all()
180
 
181
def get_successful_payment_count_for_coupon(coupon_code):
182
    return PromotionTracker.query.filter_by(coupon_code = coupon_code).count()
183
 
184
def get_rule_doc_string(rule_name):
185
    imported_coupon_module = __import__("shop2020.model.v1.user.promotionrules", globals(), locals(), [rule_name])
186
    rule = eval("imported_coupon_module." + rule_name)
187
    return rule.__doc__
4189 varun.gupt 188
 
1976 varun.gupt 189
def close_session():
190
    if session.is_active:
3376 rajveer 191
        session.close()
4189 varun.gupt 192
 
3376 rajveer 193
def is_alive():
194
    try:
195
        session.query(Promotion.id).limit(1).one()
196
        return True
197
    except:
4189 varun.gupt 198
        return False
199
 
4494 varun.gupt 200
def get_discounts_for_entity(entity_id):
201
    catalog_client = CatalogClient().get_client()
202
    items = catalog_client.getItemsByCatalogId(entity_id)
203
 
204
    discount_finder = ItemDiscountFinder()
205
    discounts = discount_finder.getCouponsAndDiscountsOnItem(items[0])
206
 
207
    if len(discounts) > 0:
208
        return {discounts[0][0]: discounts[0][1]}
209
    else:
210
        return {}
211
 
4189 varun.gupt 212
def get_item_discount_map(item_ids):
213
 
214
    discount_finder = ItemDiscountFinder()
215
    item_coupons_discounts = []
216
 
217
    catalog_client = CatalogClient().get_client()
218
 
219
    for item_id in item_ids:
220
        item = catalog_client.getItem(item_id)
221
 
222
        discounts = discount_finder.getCouponsAndDiscountsOnItem(item)
223
 
224
        for discount in discounts:
225
            item_coupons_discounts.append((item_id, discount[0], discount[1]))
226
            break
227
 
228
    return item_coupons_discounts
229
 
6497 amit.gupta 230
def get_active_gvs(promotion_id):
6570 amit.gupta 231
    all_coupons = session.query(Coupon).filter_by(promotion_id=promotion_id).filter(~exists().where(Coupon.coupon_code==PromotionTracker.coupon_code)).all()
6497 amit.gupta 232
    return [to_t_coupon(coupon) for coupon in all_coupons]
233
 
234
def delete_coupon(coupon_code):
235
    Coupon.query.filter_by(coupon_code = coupon_code).delete()
236
    session.commit()
237
 
5469 rajveer 238
def add_voucher(t_voucher):
239
    voucher = RechargeVoucher()
240
    voucher.available = True
241
    voucher.amount = t_voucher.amount
242
    voucher.voucherCode = t_voucher.voucherCode
243
    voucher.voucherType = t_voucher.voucherType
244
    if t_voucher.issuedOn:
245
        voucher.issuedOn = to_py_date(t_voucher.issuedOn)
246
    if t_voucher.expiredOn:
247
        voucher.expiredOn = to_py_date(t_voucher.expiredOn)
248
    session.commit()
249
 
250
def assign_voucher(userId, userEmail, voucherType, amount):
251
    voucher = RechargeVoucher.query.filter_by(voucherType = voucherType, amount = amount, available = True).first()
252
    if not voucher:
253
        raise PromotionException(501, 'Voucher of this type is not available.')
254
    voucher.userId = userId
255
    voucher.available = False
256
    voucher.issuedOn = datetime.datetime.now()
257
    voucher.email = userEmail
258
    session.commit()
259
    return voucher
260
 
261
def mark_voucher_as_redeemed(voucherCode, redeemedOn):
262
    voucher = RechargeVoucher.query.filter_by(voucherCode = voucherCode).first()
263
    voucher.redeemedOn = to_py_date(redeemedOn)
264
    voucher.redeemed = True
265
    session.commit()
266
    return True
267
 
4189 varun.gupt 268
class ItemDiscountFinder:
269
 
270
    def __init__(self):
271
        self.coupon_modules = {}
272
        coupons = get_active_coupons()
273
 
274
        for coupon in coupons:
5996 amit.gupta 275
            if coupon.coupon_code not in ('SAHOLIC4RS', 'SAndroid', 'SAHOLIC4MJ', 'SAHOLIC4SS', 'SJunglee'):
4189 varun.gupt 276
                coupon_rule = coupon.promotion.rule_execution_src.strip()
277
 
278
                imported_coupon_module = __import__("shop2020.model.v1.user.promotionrules", globals(), locals(), [coupon_rule])
279
                self.coupon_modules[coupon.coupon_code] = eval("imported_coupon_module." + coupon_rule)
280
 
281
    def getCouponsAndDiscountsOnItem(self, item):
282
        discounts = []
283
 
284
        for coupon_code, coupon_rule_module in self.coupon_modules.iteritems():
285
 
286
            discount = coupon_rule_module.getDiscountOnItem(item)
287
 
288
            if discount is not None:
289
                discounts.append((coupon_code, discount))
290
 
291
        return discounts