购物车:
	-往后台传输数据(价格策略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‘]/100
return total_price
原文:https://www.cnblogs.com/zhouhai007/p/10486309.html