zoukankan      html  css  js  c++  java
  • 路飞学城结算中心实现

    路飞学城结算中心的优惠券表结构

    # ########################### 优惠券 ################################
    class Coupon(models.Model):
        """优惠券生成规则"""
        name = models.CharField(max_length=64, verbose_name="活动名称")
        brief = models.TextField(blank=True, null=True, verbose_name="优惠券介绍")
        coupon_type_choices = ((0, '立减券'), (1, '满减券'), (2, '折扣券'))
        coupon_type = models.SmallIntegerField(choices=coupon_type_choices, default=0, verbose_name="券类型")
    
        """
        通用:
            money_equivalent_value=100
            off_percent=null
            minimum_consume=0
        满减:
            money_equivalent_value=100
            off_percent=null
            minimum_consume=1000
        折扣:
            money_equivalent_value=0
            off_percent=79
            minimum_consume=0
        """
        money_equivalent_value = models.IntegerField(verbose_name="等值货币")
        off_percent = models.PositiveSmallIntegerField("折扣百分比", help_text="只针对折扣券,例7.9折,写79", blank=True, null=True)
        minimum_consume = models.PositiveIntegerField("最低消费", default=0, help_text="仅在满减券时填写此字段")
    
        content_type = models.ForeignKey(ContentType, blank=True, null=True)
        object_id = models.PositiveIntegerField("绑定课程", blank=True, null=True, help_text="可以把优惠券跟课程绑定")
        content_object = GenericForeignKey('content_type', 'object_id')
    
        quantity = models.PositiveIntegerField("数量(张)", default=1)
        open_date = models.DateField("优惠券领取开始时间")
        close_date = models.DateField("优惠券领取结束时间")
        valid_begin_date = models.DateField(verbose_name="有效期开始时间", blank=True, null=True)
        valid_end_date = models.DateField(verbose_name="有效结束时间", blank=True, null=True)
        coupon_valid_days = models.PositiveIntegerField(verbose_name="优惠券有效期(天)", blank=True, null=True,
                                                        help_text="自券被领时开始算起")
        date = models.DateTimeField(auto_now_add=True)
    
        class Meta:
            verbose_name_plural = "31. 优惠券生成记录"
    
        def __str__(self):
            return "%s(%s)" % (self.get_coupon_type_display(), self.name)
    
        def save(self, *args, **kwargs):
            if not self.coupon_valid_days or (self.valid_begin_date and self.valid_end_date):
                if self.valid_begin_date and self.valid_end_date:
                    if self.valid_end_date <= self.valid_begin_date:
                        raise ValueError("valid_end_date 有效期结束日期必须晚于 valid_begin_date ")
                if self.coupon_valid_days == 0:
                    raise ValueError("coupon_valid_days 有效期不能为0")
            if self.close_date < self.open_date:
                raise ValueError("close_date 优惠券领取结束时间必须晚于 open_date优惠券领取开始时间 ")
    
            super(Coupon, self).save(*args, **kwargs)
    
    
    class CouponRecord(models.Model):
        """优惠券发放、消费纪录"""
        coupon = models.ForeignKey("Coupon")
        number = models.CharField(max_length=64, unique=True)
        account = models.ForeignKey("Account", verbose_name="拥有者")
        status_choices = ((0, '未使用'), (1, '已使用'), (2, '已过期'))
        status = models.SmallIntegerField(choices=status_choices, default=0)
        get_time = models.DateTimeField(verbose_name="领取时间", help_text="用户领取时间")
        used_time = models.DateTimeField(blank=True, null=True, verbose_name="使用时间")
        # order = models.ForeignKey("Order", blank=True, null=True, verbose_name="关联订单")  # 一个订单可以有多个优惠券
    
        class Meta:
            verbose_name_plural = "32. 用户优惠券"
    
        def __str__(self):
            return '%s-%s-%s' % (self.account, self.number, self.status)
    优惠券表结构

     结算中心的实现思路及数据结构

     结算中心 
    		
    		1.购物车(可以选择价格策略)
    			{
    				luffy_shopping_car_6_11:{
    					'title':'21天入门到放弃',
    					'src':'xxx.png',
    					'policy':{
    						1:{id:'xx'.....},
    						2:{id:'xx'.....},
    						3:{id:'xx'.....},
    						4:{id:'xx'.....},
    					},
    					'default_policy':3
    				},
    				luffy_shopping_car_6_13:{
    					...
    				}
    			}
    
    			2.结算(可以选择优惠券)
    				a. POST请求,去结算
    				   请求体:
    						{
    							courseids:[1,2]
    						}
    					业务处理:
    						1. 检测课程ID是否已经加入到购物车
    						2. 获取指定价格策略信息
    						3. 获取优惠券信息
    						4. 构造结构放入redis
    						
    				b. GET请求,获取结算中心数据
    					业务处理:
    						1. 获取结算中心里的课程信息(绑定课程优惠券)
    						2. 获取全局优惠券
    						
    				c. PATCH请求,选择优惠券
    					请求体:
    						{
    							courseid:0
    							couponid:12
    						}
    					业务处理:
    						1. 校验结算中心是否存在该课程
    						2. 校验优惠券是否可用
    					
    				注意: 
    					1. 优惠券状态
    					2. 优惠券使用时间
    
    #结算中心
    {
        payment_1_2:{
                    'course_id':str(course_id),
                    'title':self.conn.hget(car_key, 'title').decode('utf-8'),
                    'img'  :self.conn.hget(car_key, 'img').decode('utf-8'),
                    'coupon':{
                        'coupon_id':coupon_id,
                        'coupon_type':coupon_type,
                        'coupon_type_display':item.coupon.get_coupon_type_display(),
                        'money_equivalent_value':item.coupon.money_equivalent_value,
                    },
                    'default_coupon':0,
        },
        payment_1_3:{
                    'course_id':str(course_id),
                    'title':self.conn.hget(car_key, 'title').decode('utf-8'),
                    'img'  :self.conn.hget(car_key, 'img').decode('utf-8'),
                    'coupon':{
                        'coupon_id':coupon_id,
                        'coupon_type':coupon_type,
                        'coupon_type_display':item.coupon.get_coupon_type_display(),
                        'money_equivalent_value':item.coupon.money_equivalent_value,
                    },
                    'default_coupon':0,
        },
    }
    
    payment_global_coupon_1={
        'coupon':{
            coupon_id:{ 
                'coupon_id':coupon_id,
                'coupon_type':coupon_type,
                'coupon_type_display':item.coupon.get_coupon_type_display(),
                'money_equivalent_value':item.coupon.money_equivalent_value,
                        },
        },
        'defalut_coupon':0
    }
    
    结算数据及目标:
    			payment_dict = {
    				'2': {
    					course_id:2,
    					'title': 'CRM客户关系管理系统实战开发-专题', 
    					'img': 'CRM.jpg', 'policy_id': '4', 
    					'coupon': {}, 
    					'default_coupon': 0, 
    					'period': 210, 'period_display': '12个月', 'price': 122.0}, 
    				'1': {
    					course_id:2,
    					'title': '爬虫开发-专题', 
    					'img': '爬虫开发-专题.jpg', 
    					'policy_id': '2', 
    					'coupon': {
    						4: {'coupon_type': 0, 'coupon_display': '立减券', 'money_equivalent_value': 40}, 
    						6: {'coupon_type': 1, 'coupon_display': '满减券', 'money_equivalent_value': 60, 'minimum_consume': 100}
    					}, 
    					'default_coupon': 0, 
    					'period': 60, 
    					'period_display': '2个月', 
    					'price': 599.0}
    			}
    
    			global_coupon_dict = {
    				'coupon': {
    					2: {'coupon_type': 1, 'coupon_display': '满减券', 'money_equivalent_value': 200, 'minimum_consume': 500}
    				}, 
    				'default_coupon': 0
    			}
    			========================================= redis ==============================================
    			redis = {
    				payment_1_2:{
    					course_id:2,
    					'title': 'CRM客户关系管理系统实战开发-专题', 
    					'img': 'CRM.jpg', 'policy_id': '4', 
    					'coupon': {}, 
    					'default_coupon': 0, 
    					'period': 210, 'period_display': '12个月', 'price': 122.0}, 
    				},
    				payment_1_1:{
    					course_id:1,
    					'title': '爬虫开发-专题', 
    					'img': '爬虫开发-专题.jpg', 
    					'policy_id': '2', 
    					'coupon': {
    						4: {'coupon_type': 0, 'coupon_display': '立减券', 'money_equivalent_value': 40}, 
    						6: {'coupon_type': 1, 'coupon_display': '满减券', 'money_equivalent_value': 60, 'minimum_consume': 100}
    					}, 
    					'default_coupon': 0, 
    					'period': 60, 
    					'period_display': '2个月', 
    					'price': 599.0}
    				},
    				payment_global_coupon_1:{
    					'coupon': {
    						2: {'coupon_type': 1, 'coupon_display': '满减券', 'money_equivalent_value': 200, 'minimum_consume': 500}
    					}, 
    					'default_coupon': 0
    				}
    			}
    			
    
    import   redis
    conn = redis.Redis(host='127.0.0.1',port=6379)
    conn.hset('k4','username','alex')
    conn.hset('k4','age','19')
    conn.hset('k3','k3key','k3value')
    for  i  in conn.scan_iter('k*'):
        data = conn.hgetall(i)
        for  k,v  in data.items():
            print(k,v)
    redis知识点

    settings.py

    SHOPPING_CAR_KEY = "luffy_shopping_car_%s_%s"
    PAYMENT_KEY = "luffy_payment_%s_%s"
    PAYMENT_COUPON_KEY = "luffy_payment_coupon_%s"
    settings.py
    url(r'^payment/$', payment.PaymentViewSet.as_view()),
    url.py
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from utils.auth import LuffyAuth
    from django.conf import settings
    from django_redis import get_redis_connection
    import json
    from utils.response import BaseResponse
    from api import models
    import datetime
    
    class PaymentViewSet(APIView):
    
        authentication_classes =  [LuffyAuth,]
        conn = get_redis_connection("default")
    
        def post(self,request,*args,**kwargs):
            ret = BaseResponse()
            try:
                # 清空当前用户结算中心的数据
                # luffy_payment_1_*
                # luffy_payment_coupon_1
                key_list = self.conn.keys( settings.PAYMENT_KEY %(request.auth.user_id,"*",) )
                key_list.append(settings.PAYMENT_COUPON_KEY %(request.auth.user_id,))
                self.conn.delete(*key_list)
    
                payment_dict = {}
    
                global_coupon_dict = {
                    "coupon":{},
                    "default_coupon":0
                }
    
                # 1. 获取用户要结算课程ID
                course_id_list = request.data.get('courseids')
                for course_id in course_id_list:
                    car_key = settings.SHOPPING_CAR_KEY %(request.auth.user_id,course_id,)
    
                    # 1.1 检测用户要结算的课程是否已经加入购物车
                    if not self.conn.exists(car_key):
                        ret.code = 1001
                        ret.error = "课程需要先加入购物车才能结算"
                    # 1.2 从购物车中获取信息,放入到结算中心。
                    # 获取标题和图片
                    policy = json.loads(self.conn.hget(car_key, 'policy').decode('utf-8'))
                    default_policy = self.conn.hget(car_key, 'default_policy').decode('utf-8')
                    policy_info = policy[default_policy]
    
                    payment_course_dict = {
                        "course_id":str(course_id),
                        "title":self.conn.hget(car_key, 'title').decode('utf-8'),
                        "img":self.conn.hget(car_key, 'img').decode('utf-8'),
                        "policy_id":default_policy,
                        "coupon":{},
                        "default_coupon":0
                    }
                    payment_course_dict.update(policy_info)
                    payment_dict[str(course_id)] = payment_course_dict
    
    
                # 2. 获取优惠券
                ctime = datetime.date.today()
    
                coupon_list = models.CouponRecord.objects.filter(
                    account=request.auth.user,
                    status=0,
                    coupon__valid_begin_date__lte=ctime,
                    coupon__valid_end_date__gte=ctime,
                )
    
    
                for item in coupon_list:
    
    
                    # 只处理绑定课程的优惠券
                    if not item.coupon.object_id:
                        # 优惠券ID
                        coupon_id = item.id
    
                        # 优惠券类型:满减、折扣、立减
                        coupon_type = item.coupon.coupon_type
    
                        info = {}
                        info['coupon_type'] = coupon_type
                        info['coupon_display'] = item.coupon.get_coupon_type_display()
                        if coupon_type == 0:  # 立减
                            info['money_equivalent_value'] = item.coupon.money_equivalent_value
                        elif coupon_type == 1:  # 满减券
                            info['money_equivalent_value'] = item.coupon.money_equivalent_value
                            info['minimum_consume'] = item.coupon.minimum_consume
                        else:  # 折扣
                            info['off_percent'] = item.coupon.off_percent
    
                        global_coupon_dict['coupon'][coupon_id] = info
    
                        continue
                    # 优惠券绑定课程的ID
                    coupon_course_id = str(item.coupon.object_id)
    
                    # 优惠券ID
                    coupon_id = item.id
    
                    # 优惠券类型:满减、折扣、立减
                    coupon_type = item.coupon.coupon_type
    
                    info = {}
                    info['coupon_type'] = coupon_type
                    info['coupon_display'] = item.coupon.get_coupon_type_display()
                    if coupon_type == 0: # 立减
                        info['money_equivalent_value'] = item.coupon.money_equivalent_value
                    elif coupon_type == 1: # 满减券
                        info['money_equivalent_value'] = item.coupon.money_equivalent_value
                        info['minimum_consume'] = item.coupon.minimum_consume
                    else: # 折扣
                        info['off_percent'] = item.coupon.off_percent
    
                    if coupon_course_id not in payment_dict:
                        # 获取到优惠券,但是没有购买此课程
                        continue
                    # 将优惠券设置到指定的课程字典中
                    payment_dict[coupon_course_id]['coupon'][coupon_id] = info
    
                # 可以获取绑定的优惠券
    
                # 3. 将绑定优惠券课程+全站优惠券 写入到redis中(结算中心)。
                # 3.1 绑定优惠券课程放入redis
                for cid,cinfo in payment_dict.items():
                    pay_key = settings.PAYMENT_KEY %(request.auth.user_id,cid,)
                    cinfo['coupon'] = json.dumps(cinfo['coupon'])
                    self.conn.hmset(pay_key,cinfo)
                # 3.2 将全站优惠券写入redis
                gcoupon_key = settings.PAYMENT_COUPON_KEY %(request.auth.user_id,)
                global_coupon_dict['coupon'] = json.dumps(global_coupon_dict['coupon'])
                self.conn.hmset(gcoupon_key,global_coupon_dict)
    
            except Exception as e:
                pass
    
            return Response(ret.dict)
    
        def patch(self,request,*args,**kwargs):
    
            ret = BaseResponse()
            try:
                # 1. 用户提交要修改的优惠券
                course = request.data.get('courseid')
                course_id = str(course) if course else course
    
                coupon_id = str(request.data.get('couponid'))
    
                # payment_global_coupon_1
                redis_global_coupon_key = settings.PAYMENT_COUPON_KEY %(request.auth.user_id,)
    
                # 修改全站优惠券
                if not course_id:
                    if coupon_id == "0":
                        # 不使用优惠券,请求数据:{"couponid":0}
                        self.conn.hset(redis_global_coupon_key,'default_coupon',coupon_id)
                        ret.data = "修改成功"
                        return Response(ret.dict)
                    # 使用优惠券,请求数据:{"couponid":2}
                    coupon_dict = json.loads(self.conn.hget(redis_global_coupon_key,'coupon').decode('utf-8'))
    
                    # 判断用户选择得优惠券是否合法
                    if coupon_id not in coupon_dict:
                        ret.code = 1001
                        ret.error = "全站优惠券不存在"
                        return Response(ret.dict)
    
                    # 选择的优惠券合法
                    self.conn.hset(redis_global_coupon_key, 'default_coupon', coupon_id)
                    ret.data = "修改成功"
                    return Response(ret.dict)
    
                # 修改课程优惠券
                # luffy_payment_1_1
                redis_payment_key = settings.PAYMENT_KEY % (request.auth.user_id, course_id,)
                # 不使用优惠券
                if coupon_id == "0":
                    self.conn.hset(redis_payment_key,'default_coupon',coupon_id)
                    ret.data = "修改成功"
                    return Response(ret.dict)
    
                # 使用优惠券
                coupon_dict = json.loads(self.conn.hget(redis_payment_key,'coupon').decode('utf-8'))
                if coupon_id not in coupon_dict:
                    ret.code = 1010
                    ret.error = "课程优惠券不存在"
                    return Response(ret.dict)
    
                self.conn.hset(redis_payment_key,'default_coupon',coupon_id)
    
            except Exception as e:
                ret.code = 1111
                ret.error = "修改失败"
    
            return Response(ret.dict)
    
        def get(self,request,*args,**kwargs):
    
            ret = BaseResponse()
    
            try:
                # luffy_payment_1_*
                redis_payment_key = settings.PAYMENT_KEY %(request.auth.user_id,"*",)
    
                # luffy_payment_coupon_1
                redis_global_coupon_key = settings.PAYMENT_COUPON_KEY %(request.auth.user_id,)
    
                # 1. 获取绑定课程信息
                course_list = []
                for key in self.conn.scan_iter(redis_payment_key): #  取到所有的与用户有关的key。。。。
                    info = {}
                    data = self.conn.hgetall(key)
                    for k,v in data.items():
                        kk = k.decode('utf-8')
                        if kk == "coupon":
                            info[kk] = json.loads(v.decode('utf-8'))
                        else:
                            info[kk] = v.decode('utf-8')
                    course_list.append(info)
    
                # 2.全站优惠券
                global_coupon_dict = {
                    'coupon':json.loads(self.conn.hget(redis_global_coupon_key,'coupon').decode('utf-8')),
                    'default_coupon':self.conn.hget(redis_global_coupon_key,'default_coupon').decode('utf-8')
                }
    
                ret.data = {
                    "course_list":course_list,
                    "global_coupon_dict":global_coupon_dict
                }
            except Exception as e:
                ret.code = 1001
                ret.error = "获取失败"
    
            return Response(ret.dict)
    payment.py

    I can feel you forgetting me。。 有一种默契叫做我不理你,你就不理我

  • 相关阅读:
    setup slack检查
    关于derive_pll_clock
    STA中的postmap和postfit
    sdc中对I/O口的约束set_input/output_delay
    hold slack的计算
    DDR I 和DDR II的简单比较
    ORA00600: 内部错误代码,参数: [kcratr1_lostwrt], [], [], [], [], [], [], []
    linux解压超过2G大文件
    linux 安装apache2.2.4
    plsql developer导出csv乱码问题
  • 原文地址:https://www.cnblogs.com/weidaijie/p/10510742.html
Copyright © 2011-2022 走看看