购物车:
-往后台传输数据(价格策略id,课程id) -{"course_id":"1","policy_id":"3"} -为什么要放到redis -存储数据方式:(key值为:shopping_card_userid) shopping_card_userid={ "1":{ "title":"Django从入门到放弃", "img":"django.png", "default_policy":"3", "policy":{ "1":{ "period":3, "period_display":"3天", "price":200 }, "3":{ "period":60, "period_display":"2个月", "price":1000 }, "4":{ "period":30, "period_display":"1个月", "price":500 } } }, "2":{ "title":"Git操作", "img":"git.png", "default_policy":"2", "policy":{ "2":{ "period":30, "period_display":"1个月", "price":60 }, "5":{ "period":1, "period_display":"1天", "price":0 }, "6":{ "period":90, "period_display":"3个月", "price":50 } } } } -校验规则: -校验课程是否存在 -校验价格策略是否合法 -把价格策略拼成一个字典,直接用id in 字典,判断价格策略是否合法 -取出原来购物车的商品,更新,或者新增 -传过来的id 在购物车字典中,只要修改默认价格策略即可 -传过来的id不在购物车字典中,直接新增 -存到redis -购物车整个逻辑: -(1)添加购物车 ----post:{"course_id":"1","policy_id":"1"} -1 校验课程是否存在 -2 获取所有价格策略 -3 从redis中取出当前登录用户的购物车 shoping_card_byte=self.conn.get(redis_str) shoping_card_dic=json.loads(shoping_card_byte) if shoping_card_byte else {} -4 循环价格策略组装成以下形式 { "period":3, "period_display":"3天", "price":200 } polic_dict[str(item.id)] = { "period": item.valid_period, "period_display": item.get_valid_period_display(), "price": item.price, } -5 校验价格策略是否是该课程的价格策略(判断传入的policy_id是否在上面的字典中) -6 价格策略合法,构造出购物车字典(如果购物车中有该课程,修改的是默认策略) shoping_card_dic[course_id] = { 'title': course.name, 'img': course.course_img, 'default_policy': policy_id, 'policy': polic_dict } -7 转成json,存入redis name值为:'shopping_%s' % (request.user.id,) -(2)修改购物车中某个课程价格策略---patch:{"course_id":"1","policy_id":"1"} -1 从redis中取出购物车 -2 判断价格策略是否合法(也就是是否在当前课程的policy字典中) -3 在的话,直接修改default_policy为传入的policy_id shopping_card[course_id]['default_policy'] = policy_id -4 把数据写回redis self.conn.set(redis_str, json.dumps(shopping_card)) -(3)删除购物车中课程---delete:{"course_id":"1"} -1 从redis中取出购物车 -2 从购物车中pop掉当前传入的course_id -3 把数据写会redis -(4)获取购物车---get -1 从redis中取出购物车 -2 把购物车放到res.data 中返回优惠券表介绍:结算中心:
-请求格式: {"course_list":[{"course_id":"1","policy_id":"1"},{"course_id":"2","policy_id":"2"}]} -存储格式(结算中心和全局优惠券格式): { "1":{ "coupon":{ "7":{ "coupon_type":0, "coupon_display":"立减券", "money_equivalent_value":10 }, "8":{ "coupon_type":1, "coupon_display":"满减券", "money_equivalent_value":10, "minimum_consume":100 }, "9":{ "coupon_type":2, "coupon_display":"折扣券", "off_percent":90 } }, "title":"Django从入门到放弃", "img":"django.png", "default_policy":"3", "policy":{ "1":{ "period":3, "period_display":"3天", "price":200 }, "3":{ "period":60, "period_display":"2个月", "price":1000 }, "4":{ "period":30, "period_display":"1个月", "price":500 } } }, "2":{ "coupon":{},
"title":"Git操作", "img":"git.png", "default_policy":"2", "policy":{ "2":{ "period":30, "period_display":"1个月", "price":60 }, "5":{ "period":1, "period_display":"1天", "price":0 }, "6":{ "period":90, "period_display":"3个月", "price":50 } } } } -全局优惠券格式: { "coupon":{ "4":{ "coupon_type":1, "coupon_display":"满减券", "money_equivalent_value":10, "minimum_consume":100 }, "5":{ "coupon_type":0, "coupon_display":"立减券", "money_equivalent_value":10 }, "6":{ "coupon_type":2, "coupon_display":"折扣券", "off_percent":80 } }, "default_coupon":0 } -结算中心逻辑分析: -(1)添加到结算中心--post---{"course_list":[{"course_id":"1","policy_id":"1"},{"course_id":"2","policy_id":"2"}]} -1 定义结算中心的字典,定义全局优惠券的字典 payment_dict_userid={} global_coupon_dict = { "coupon": {}, "default_coupon": 0 } -2 拿到购物车,循环取出传入的课程id,判断是否在购物车中,不在直接抛异常 -3 构造单个课程详情的字典,把购物车中的当前课程,update到该字典中 course_detail={ 'coupon':{} } course_detail.update(shopping_cart[course_id]) -4 将该课程详情,加入到结算中心(现在里面没有优惠券相关信息)(为了效率,不在for循环中查询数据库,查出优惠券) payment_dict_userid[course_id]=course_detail -5 一次性查出当前用户的所有优惠券信息(用户为当前用户,状态为未使用,优惠券起始时间小于当前时间,优惠券结束时间大于当前时间) ctime=datetime.datetime.today().strftime('%Y-%m-%d') print(ctime) coupon_list=models.CouponRecord.objects.filter( user=request.user, status=0, coupon__valid_begin_date__lte=ctime, coupon__valid_end_date__gte=ctime, ) -6 循环所有优惠券 -7 构造出单个优惠券的空字典,拿到优惠券类型(1立减 2 满减 3折扣),拿到优惠券id,拿到该优惠券绑定的课程id(有可能为空) coupon_detail = {} coupon_type = item.coupon.coupon_type coupon_id = item.id coupon_course_id = item.coupon.object_id -8 构造单个优惠券字典,将数据填充进去,格式如下: { "7":{"coupon_type":0,"coupon_display":"立减券","money_equivalent_value":10}, "8":{"coupon_type":1,"coupon_display":"满减券","money_equivalent_value":10,"minimum_consume":100}, "9":{"coupon_type":2,"coupon_display":"折扣券","off_percent":90} } coupon_detail['coupon_type'] = coupon_type coupon_detail['coupon_display'] = item.coupon.get_coupon_type_display() if coupon_type == 0: #立减券,构造出等值金额 coupon_detail['money_equivalent_value'] = item.coupon.money_equivalent_value elif coupon_type == 1:#满减券,构造出等值金额,和最低消费金额 coupon_detail['money_equivalent_value'] = item.coupon.money_equivalent_value coupon_detail['minimum_consume'] = item.coupon.minimum_consume else:#其他情况,构造出打折(如打八折,80) coupon_detail['off_percent'] = item.coupon.off_percent -9 判断是全站优惠券还是课程优惠券 if not coupon_course_id:#全站优惠券放到全站优惠券字典里 global_coupon_dict['coupon'][str(coupon_id)]=coupon_detail else: #其它情况,说明是绑定给课程的优惠券 coupon_course_id=str(coupon_course_id) if coupon_course_id not in payment_dict_userid:#当前课程优惠券对应的可能如果不在结算中心字典里,continue continue #在结算中心字典中的,对应放入到课程优惠券字段上 payment_dict_userid[str(coupon_course_id)]['coupon'][coupon_id]=coupon_detail payment_dict_userid[str(coupon_course_id)]['default_coupon'] = 0 -10 讲结算中心字典和全局优惠券字典,放入redis中 self.conn.set('payment_dict_%s'%request.user.id,json.dumps(payment_dict_userid)) self.conn.set('global_coupon_dict_%s'%request.user.id,json.dumps(global_coupon_dict)) -11 返回成功 -(2)修改结算中心某个课程的优惠券信息---patch--{"course_id":"1","coupon_id":"1"} -1 从reids中取出结算中心数据 -2 先校验coupon_id是否合法,也就是是否在结算中心的优惠券信息中 if coupon_id not in payment_dict_userid[course_id]['coupon']: raise Exception('该优惠不合法') -3 合法,直接修改,返回正确信息 payment_dict_userid[course_id]['default_coupon']=coupon_id -(3)获取结算中心数据----get -1 从redis中取出本人的结算中心数据 ('payment_dict_%s'%request.user.id)) -2 从redis中取出本人的全局优惠券数据 ('global_coupon_dict_%s'%request.user.id)) -3 构造数据返回前台 res.data={ 'payment':payment_dict_userid, 'global_coupon_dict':global_coupon_dict } -去支付: -前端传递数据格式: { "price":600 "bely":100 } -去支付逻辑: -从支付中心拿出字典,全局优惠券字典取出来 -payment_dic = self.conn.get('payment_dic_%s' % request.user.id) -循环结算中心字典,得到课程和课程id -for course_id,course_detail in payment_dic.items(): -取出默认价格策略,取出默认价格,取出默认优惠券id default_policy_id=course_detail['default_policy'] price=course_detail['policy'][str(default_policy_id)]['price'] default_coupon_id=course_detail['default_coupon'] -判断如果默认优惠券不为0,表示使用了优惠券:取出默认优惠券的字典,调用计算价格函数得到价格,把价格放到价格列表中(后面直接用sum函数计算总价格) if default_coupon_id!=0: coupon_dic=course_detail['coupon'][str(default_coupon_id)] price= self.account_price(price,coupon_dic) price_list.append(price) -取出全局默认优惠券id,根据默认优惠券id取出全局优惠券字典,调用计算价格函数得到实际支付价格 default_coupon_id=global_coupon['default_coupon'] global_coupon_dic=global_coupon['coupon'][str(default_coupon_id)] debate_price=self.account_price(sum(price_list),global_coupon_dic) -判断贝利数大于传入的贝利数,用实际价格减去贝利数,如果得到结果小于0,直接等于0,判断最终价格和传如的价格是否相等,不相等抛异常 if bely>request.user.bely: raise MyException('贝利数不合法') final_price=debate_price-bely/10 if final_price<0: final_price=0 if price!=final_price: raise MyException('传入的价格有问题') -如果实际支付价格大于0,生成支付宝url地址,返回给前端,让前端跳转 if final_price>0: # 拼凑支付宝url alipay = ali() # 生成支付的url query_params = alipay.direct_pay( subject="路飞学成课程", # 商品简单描述 out_trade_no="x2" + str(time.time()), # 商户订单号 total_amount=final_price, # 交易金额(单位: 元 保留俩位小数) ) pay_url = "https://openapi.alipaydev.com/gateway.do?{}".format(query_params) response.url=pay_url -计算价格方法: #传入价格和优惠券字典 def account_price(self,price,coupon_dic): #设置总价格为price total_price=price #取出优惠券类型 coupon_type=coupon_dic['coupon_type'] #优惠券类型是0,立减 if coupon_type==0: total_price=price-coupon_dic['money_equivalent_value'] ##优惠券类型是1,满减,必须大于最低消费金额 elif coupon_type==1: if price>=coupon_dic['minimum_consume']: total_price=price-coupon_dic['money_equivalent_value'] else: raise MyException('优惠券不满足最低使用金额') ##优惠券类型是2,直接打折 elif coupon_type==2: total_price=price*coupon_dic['off_percent']/100return total_price