1. 程式人生 > >DAY110 - 路飛學城(六)- 路飛學城之結算中心,支付中心

DAY110 - 路飛學城(六)- 路飛學城之結算中心,支付中心

一、路飛學城之結算中心

資料格式

# 使用者選中的課程以及優惠券
payment_使用者ID{
    '課程ID':{
        'default_coupon':選中的優惠券,
        'coupon':當前課程的優惠券
                {
                    '優惠券ID':{
                        "coupon_type":0,
                        "coupon_display":"立減券",
                        "money_equivalent_value":10
                    },
                    '優惠券ID':{
                        "coupon_type":1,
                        "coupon_display":"滿減券",
                        "money_equivalent_value":10,
                        "minimum_consume":100
                    },
                    '優惠券ID':{
                        "coupon_type":2,
                        "coupon_display":"折扣券",
                        "off_percent":90
                    },
                },
        'title':課程名,
        'img':課程圖片,
        'default_policy':選中價格策略,
        'policy':{
            當前課程的所有價格策略
            'policy的ID':{
                {
                   "period":課程週期(天),比如30,
                   "period_display":課程週期的簡寫,30天==1個月,
                   "price": 對應的價格
                }
            },
            ........
        }
    },
    .........
}


# 全站的優惠券
{
    'coupon':{
            '優惠券ID':{
                "coupon_type":0,
                "coupon_display":"立減券",
                "money_equivalent_value":10
            },
            '優惠券ID':{
                "coupon_type":1,
                "coupon_display":"滿減券",
                "money_equivalent_value":10,
                "minimum_consume":100
            },
            '優惠券ID':{
                "coupon_type":2,
                "coupon_display":"折扣券",
                "off_percent":90
            },
        },
}

新增到結算中心

# 從前端拿到了使用者想結算的課程資料,然後在後臺處理,返回帶優惠卷的課程資料和全站優惠卷
def post(self, request):
    '''
    業務邏輯:
    1 定義結算中心的字典,定義全域性優惠券的字典
    2 拿到購物車,迴圈取出傳入的課程id
    3 構造單個課程詳情的字典,把購物車中的當前課程,update到該字典中
    4 將該課程詳情,加入到結算中心
    5 一次性查出當前使用者的所有優惠券資訊(使用者為當前使用者,狀態為未使用,優惠券起始時間小於當前時間,優惠券結束時間大於當前時間)
    6 迴圈所有優惠券
    7 構造出單個優惠券的空字典,拿到優惠券型別(1立減 2 滿減 3折扣),拿到優惠券id,拿到該優惠券繫結的課程id(有可能為空)
    8 構造單個優惠券字典,將資料填充進去
    9 判斷是全站優惠券還是課程優惠券
    10 講結算中心字典和全域性優惠券字典,放入redis中
    :param request:
        {
            "course_list":[
                {
                    "course_id":"1",
                    "policy_id":"1"
                },
                {
                    "course_id":"2",
                    "policy_id":"2"
                },
                .......
            ]
        }
    :return:
    '''
    response = MyResponse()
    course_list = request.data.get('course_list')
    try:
        # 1 定義結算中心的字典,定義全域性優惠券的字典
        payment = {}
        global_coupon_dict = {
            'coupon': {},
            'dafault_coupon': '0',
        }

        # 2拿到購物車,獲得正確的課程詳情放入結算中心的字典中
        shoppingcart = self.conn.get('shoppingcart_%s' % request.user.pk)
        shoppingcart_dic = json.loads(shoppingcart) if shoppingcart else {}

        # 3 迴圈取出傳入的course_list的課程id,迴圈結束後,把結算中心payment中的課程詳情填滿(除了課程的優惠券)
        for course in course_list:
            course_id = course['course_id']
            # 判斷傳入的課程id是否在購物車中
            if course_id not in shoppingcart_dic:
                raise CommonException(101, '當前結算的課程不在購物車中')

            # 構造一個課程詳情的字典
            course_detail = {
                'coupon': {},
                'dafalut_coupon': 0,
            }
            # 把購物車中的當前課程,update到該字典中
            course_detail.update(shoppingcart_dic[course_id])

            # 以course_id為Key,對應的course_detail為value,將該課程詳情,加入到結算中心
            payment[course_id] = course_detail

        # 4一次性查出當前使用者的所有優惠券資訊(使用者為當前使用者,狀態為未使用,優惠券起始時間小於當前時間,優惠券結束時間大於當前時間)
        import datetime
        ctime = datetime.datetime.now()
        # 可使用的優惠券
        coupon_list = models.CouponRecord.objects.filter(user=request.user, status=0,
                                                         coupon__valid_begin_date__lte=ctime,
                                                         coupon__valid_end_date__gte=ctime)
        # 5迴圈所有優惠券
        for coupon in coupon_list:
            # 6構造出單個優惠券的空字典,拿到優惠券型別(1立減2滿減3折扣),拿到優惠券id,拿到該優惠券繫結的課程id(有可能為空)

            # 優惠券型別(0,1,2)
            coupon_type = coupon.coupon.coupon_type
            # 優惠券型別(立減,滿減,折扣)
            coupon_type_display = coupon.coupon.get_coupon_type_display()
            # 繫結的課程id
            object_id = coupon.coupon.object_id
            # 優惠券id
            coupon_id = str(coupon.pk)

            # 7構造單個優惠券字典,將資料填充進去
            coupon_detail = {
                "coupon_type": coupon_type,
                "coupon_display": coupon_type_display,
            }
            if coupon_type==0:# 立減
                coupon_detail['money_equivalent_value'] = coupon.coupon.money_equivalent_value
            elif coupon_type==1:# 滿減
                coupon_detail['money_equivalent_value'] = coupon.coupon.money_equivalent_value
                coupon_detail['minimum_consume'] = coupon.coupon.minimum_consume
            else:
                coupon_detail['off_percent'] = coupon.coupon.off_percent

            # 8.單個優惠券字典字典構造完成,判斷是全站優惠券還是課程優惠券
            # 全站優惠券
            if not object_id :
                global_coupon_dict['coupon'][coupon_id]=coupon_detail
            else:
                # 課程優惠券
                # 由於是在迴圈所有的優惠券,包括了沒選的課程的優惠券,所以要判斷當前優惠券的課程ID是否在結算中心的字典中
                if payment.get(str(object_id),None):
                    payment[str(object_id)]['coupon'][coupon_id]=coupon_detail

        # 9講結算中心字典和全域性優惠券字典,放入redis中
        self.conn.set('payment_%s' % request.user.pk,json.dumps(payment))
        self.conn.set('global_coupon_%s' % request.user.pk,json.dumps(global_coupon_dict))
        response.msg = '成功'
    except ObjectDoesNotExist as e:
        response.status = 101
        response.msg = '課程不存在'
    except CommonException as e:
        response.status = e.status
        response.msg = e.msg
    except Exception as e:
        response.status = 400
        response.msg = '未知錯誤'
        print(e)
    return Response(response.get_dic)

修改資料

# 更改某一門課的當前優惠卷
def put(self, request):
    # {"course_id": "1", "coupon_id": "1"}
    response = MyResponse()
    course_id = request.data.get('course_id')
    coupon_id = request.data.get('coupon_id')
    try:
        # 獲取redis中的payment資料
        payment_bytes = self.conn.get('payment_%s' % request.user.pk)
        payment_dic = json.loads(payment_bytes) if payment_bytes else {}

        # 判斷course_id是否合法
        if course_id not in payment_dic:
            raise CommonException(102, '課程不合法')

        # 判斷coupon_id是否合法
        if coupon_id not in payment_dic[course_id]['coupon']:
            raise CommonException(102, '優惠券不合法')

        payment_dic[course_id]['dafalut_coupon'] = coupon_id

        self.conn.set('payment_%s' % request.user.pk,json.dumps(payment_dic))

        response.msg = '成功'
    except ObjectDoesNotExist as e:
        response.status = 101
        response.msg = '課程不存在'
    except CommonException as e:
        response.status = e.status
        response.msg = e.msg
    except Exception as e:
        response.status = 400
        response.msg = '未知錯誤'
        print(e)
    return Response(response.get_dic)

顯示資料

def get(self, request):
    response = MyResponse()
    try:
        # 獲取redis中的payment資料
        payment_bytes = self.conn.get('payment_%s' % request.user.pk)
        payment_dic = json.loads(payment_bytes) if payment_bytes else {}

        global_coupon = self.conn.get('global_coupon_%s' % request.user.pk)
        global_coupon_dic = json.loads(global_coupon) if global_coupon else {}

        response.data={
            'global_coupon':global_coupon_dic,
            'payment':payment_dic,
        }
        response.msg = '成功'
    except ObjectDoesNotExist as e:
        response.status = 101
        response.msg = '課程不存在'
    except CommonException as e:
        response.status = e.status
        response.msg = e.msg
    except Exception as e:
        response.status = 400
        response.msg = '未知錯誤'
        print(e)
    return Response(response.get_dic)

刪除課程

def delete(self, request):
    # {"course_id": "1"}
    response = MyResponse()
    course_id = request.data.get('course_id')
    try:
        # 獲取redis中的payment資料
        payment_bytes = self.conn.get('payment_%s' % request.user.pk)
        payment_dic = json.loads(payment_bytes) if payment_bytes else {}

        # 判斷course_id是否合法
        if course_id not in payment_dic:
            raise CommonException(102, '課程不合法')

        payment_dic.pop(course_id,None)

        self.conn.set('payment_%s' % request.user.pk,json.dumps(payment_dic))

        response.msg = '刪除成功'
    except ObjectDoesNotExist as e:
        response.status = 101
        response.msg = '課程不存在'
    except CommonException as e:
        response.status = e.status
        response.msg = e.msg
    except Exception as e:
        response.status = 400
        response.msg = '未知錯誤'
        print(e)
    return Response(response.get_dic)

二、路飛學城之支付中心

# 支付成功後,並且支付寶回撥,才去對購物車和結算中心清空
class Account(APIView):
    authentication_classes = [Login_token]
    conn = get_redis_connection()

    def post(self, request):
        response = MyResponse()
        price_in = request.data.get('price')
        bely = request.data.get('bely')
        try:
            payment_bytes = self.conn.get('payment_%s' % request.user.pk)
            payment_dic = json.loads(payment_bytes) if payment_bytes else {}
            global_coupon = self.conn.get('global_coupon_%s' % request.user.pk)
            global_coupon_dic = json.loads(global_coupon) if global_coupon else {}

            list_price = []
            # 迴圈所有課程是為了計算每個課程優惠券優惠後的價格
            for course_id, course_detail in payment_dic.items():
                # 取出預設價格策略,取出預設價格,取出預設優惠券id
                default_policy = course_detail['default_policy']
                default_price = course_detail['policy'][str(default_policy)]['price']
                default_coupon_id = course_detail['default_coupon']

                # !=0說明是選擇了優惠券的
                if default_coupon_id !='0':
                    # 預設優惠券對應詳情
                    default_coupon_detail = course_detail['coupon'][str(default_coupon_id)]
                    default_price = self.account(default_coupon_id, default_price, default_coupon_detail)
                # 課程優惠後的價格:default_price
                # 所有課程價格列表:list_price
                list_price.append(default_price)


            # 預設全站優惠券ID
            global_coupon_id = global_coupon_dic['dafault_coupon']
            global_coupon_price = sum(list_price)
            if global_coupon_id!='0':
                # 預設全站優惠券詳情
                global_coupon_detail = global_coupon_dic['coupon'][str(global_coupon_id)]
                # 全站優惠後的價格
                global_coupon_price = self.account(global_coupon_id, sum(list_price), global_coupon_detail)



            # 貝利可以抵一部分錢

            if int(bely) > request.user.bely:
                raise CommonException(102,'貝利數超出使用者本身所有,不合法')
            # 最後的價格:final_price
            final_price = global_coupon_price - int(bely) / 10
            # 把剩餘的貝利存入資料庫
            request.user.bely = request.user.bely - int(bely)
            request.user.save()

            if not final_price==float(price_in):
                raise CommonException(103,'傳入的價格與計算不一致')
            if final_price<=0:
                final_price=0
            # 為了測試資料,所以沒有用支付寶介面
            # 構造支付寶連結
            # 拼湊支付寶url
            # alipay = ali()
            # import time
            # # 生成支付的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)
            pay_url = "https://openapi.alipaydev.com/gateway.do?"
            response.url = pay_url
            response.msg = '成功'
        except ObjectDoesNotExist as e:
            response.status = 101
            response.msg = '課程不存在'
        except CommonException as e:
            response.status = e.status
            response.msg = e.msg
        except Exception as e:
            response.status = 400
            response.msg = '未知錯誤'
            print(e)
        return Response(response.get_dic)

    # 把優惠券的計算單獨封裝
    def account(self,default_coupon_id,default_price,default_coupon_detail):
        if default_coupon_id == '1':  # 立減
            default_price = default_price - default_coupon_detail['money_equivalent_value']
        elif default_coupon_id == '2':  # 滿減
            if default_price >= 100:
                default_price = default_price - default_coupon_detail['money_equivalent_value']
            else:
                raise CommonException(102, '不滿足最低消費金額')
        else:
            default_price = default_price * default_coupon_detail['off_percent'] / 100
        return default_price