Эх сурвалжийг харах

Merge remote-tracking branch 'origin/test'

locky 3 жил өмнө
parent
commit
a5cb1c8bfc

+ 83 - 5
AdminController/TestServeController.py

@@ -19,6 +19,9 @@ from Object.UidTokenObject import UidTokenObject
 from Service.CommonService import CommonService
 from Service.CommonService import CommonService
 from django.db.models import Q, F
 from django.db.models import Q, F
 from time import strftime
 from time import strftime
+from Ansjer.config import BASE_DIR
+from Object import MergePic
+import os
 
 
 
 
 class TestServeView(View):
 class TestServeView(View):
@@ -56,10 +59,41 @@ class TestServeView(View):
 
 
     def AItest(self, userID, request, request_dict, response):
     def AItest(self, userID, request, request_dict, response):
         file = request.FILES.get('file', None)
         file = request.FILES.get('file', None)
-        if not file:
-            return response.json(444)
-        maxLabels = int(request_dict.get('maxLabels', 5))
-        minConfidence = float(request_dict.get('minConfidence', 55))
+        file2 = request.FILES.get('file_one', None)
+        file3 = request.FILES.get('file_two', None)
+        file4 = request.FILES.get('file_three', None)
+
+        post_file_list = [file, file2, file3, file4]
+        file_list = []
+        for index in range(len(post_file_list)):
+            if post_file_list[index]:
+                file_list.append(post_file_list[index])
+
+        del post_file_list
+        if len(file_list) > 1:
+            merge = []
+            now_time = int(time.time())
+            dir_path = os.path.join(BASE_DIR, 'static/', str(now_time))
+            if not os.path.exists(dir_path):
+                os.makedirs(dir_path)
+            for item in file_list:
+                if hasattr(item, 'name'):
+                    file_path = os.path.join(dir_path, item.name)
+                    with open(file_path, 'wb') as f:
+                        for c in item.chunks():
+                            f.write(c)
+                            merge.append(file_path)
+
+            image_size = 500  # 每张小图片的大小
+            image_colnum = 2  # 合并成一张图后,一行有几个小图
+            MergePic.merge_images(dir_path, image_size, image_colnum)
+            # return HttpResponse(dir_path + '.jpg')
+            photo = open(dir_path + '.jpg', 'rb')
+        else:
+            photo = file_list[0]
+
+        maxLabels = int(request_dict.get('maxLabels', 10))
+        minConfidence = float(request_dict.get('minConfidence', 30))
 
 
         try:
         try:
             client = boto3.client(
             client = boto3.client(
@@ -71,7 +105,7 @@ class TestServeView(View):
             # https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/rekognition.html#Rekognition.Client.detect_labels
             # https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/rekognition.html#Rekognition.Client.detect_labels
             rekognition_res = client.detect_labels(
             rekognition_res = client.detect_labels(
                 Image={
                 Image={
-                    'Bytes': file.read()},
+                    'Bytes': photo.read()},
                 MaxLabels=maxLabels,
                 MaxLabels=maxLabels,
                 MinConfidence=minConfidence)
                 MinConfidence=minConfidence)
             print('rekognition_res: ', rekognition_res)
             print('rekognition_res: ', rekognition_res)
@@ -79,3 +113,47 @@ class TestServeView(View):
         except Exception as e:
         except Exception as e:
             print(e)
             print(e)
             return response.json(500, repr(e))
             return response.json(500, repr(e))
+
+
+
+
+
+
+        files1 = request.FILES.get('image1')
+        files2 = request.FILES.get('image2')
+        files3 = request.FILES.get('image3')
+        files4 = request.FILES.get('image4')
+        file_list = [files1,files2,files3,files4]
+        merge = []
+        now_time = int(time.time())
+        dir_path = os.path.join(BASE_DIR,'static/', str(now_time))
+        if not os.path.exists(dir_path):
+            os.makedirs(dir_path)
+        for item in file_list:
+            if hasattr(item,'name'):
+                file_path = os.path.join(dir_path,item.name)
+                with open(file_path, 'wb') as f:
+                    for c in item.chunks():
+                        f.write(c)
+                        merge.append(file_path)
+
+        image_size = 500  # 每张小图片的大小
+        image_colnum = 2  # 合并成一张图后,一行有几个小图
+        MergePic.merge_images(dir_path, image_size, image_colnum)
+        files = open(dir_path+'.jpg','rb')
+        # return HttpResponse(files.read())
+
+
+        labels = int(request_dict.get('labels',5))
+        minConfidence = int(request_dict.get('minConfidence',99))
+        if not files:
+            return HttpResponse('请上传图片!!!!')
+        client = boto3.client('rekognition', aws_access_key_id='AKIA2E67UIMD6JD6TN3J',aws_secret_access_key='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',region_name='us-east-1')
+        # image = open('E:/photo/a615fa40b8c476bab0f6eeb332e62a5a-1000.jpg', "rb")
+        response = client.detect_labels(Image={'Bytes':files.read()},MaxLabels=labels,MinConfidence=minConfidence)
+        # for obj in response['Labels']:
+        #     exit(obj)
+        #     if obj['Name'] == 'Person':
+        #         jsonstr = json.dumps(obj)
+        return HttpResponse(json.dumps(response, ensure_ascii=False),
+                            content_type="application/json,charset=utf-8")

+ 1 - 1
Ansjer/urls.py

@@ -18,7 +18,7 @@ from Controller import FeedBack, EquipmentOTA, EquipmentInfo, AdminManage, AppIn
     VerifyCodeController, FileController, UIDController, LogController, SalesController, \
     VerifyCodeController, FileController, UIDController, LogController, SalesController, \
     OrderTaskController, HistoryUIDController, UIDManageUserController, SerialNumberController, CompanyController, \
     OrderTaskController, HistoryUIDController, UIDManageUserController, SerialNumberController, CompanyController, \
     RegionController, VPGController, LanguageController, TestController, DeviceConfirmRegion, S3GetStsController, \
     RegionController, VPGController, LanguageController, TestController, DeviceConfirmRegion, S3GetStsController, \
-    DetectControllerV2, ShadowController, TestDetectController, PcInfo, PctestController, DeviceDebug, \
+    DetectControllerV2, ShadowController, TestDetectController, PcInfo, PctestController, DeviceDebug, PaymentCycle, \
     DeviceLogController
     DeviceLogController
 from AdminController import UserManageController, RoleController, MenuController, TestServeController, \
 from AdminController import UserManageController, RoleController, MenuController, TestServeController, \
     ServeManagementController, LogManagementController, DeviceManagementController, VersionManagementController
     ServeManagementController, LogManagementController, DeviceManagementController, VersionManagementController

+ 19 - 3
Controller/CloudStorage.py

@@ -52,6 +52,7 @@ from Service.CommonService import CommonService
 from Object.m3u8generate import PlaylistGenerator
 from Object.m3u8generate import PlaylistGenerator
 from Object.WechatPayObject import WechatPayObject
 from Object.WechatPayObject import WechatPayObject
 from django.db.models import Q, F, Count
 from django.db.models import Q, F, Count
+from Controller.PaymentCycle import Paypal
 from Ansjer.config import SERVER_TYPE
 from Ansjer.config import SERVER_TYPE
 from Service.ModelService import ModelService
 from Service.ModelService import ModelService
 
 
@@ -216,7 +217,7 @@ class CloudStorageView(View):
         qs = qs.values("id", "title", "content", "price", "day", "currency", "bucket__storeDay",
         qs = qs.values("id", "title", "content", "price", "day", "currency", "bucket__storeDay",
                        "bucket__bucket", "bucket__area", "commodity_code",
                        "bucket__bucket", "bucket__area", "commodity_code",
                        "commodity_type", "is_discounts", "virtual_price", "expire",
                        "commodity_type", "is_discounts", "virtual_price", "expire",
-                       "discount_price", "discount_content", "symbol")
+                       "discount_price", "discount_content", "symbol","cycle_config_id")
 
 
         if qs.exists():
         if qs.exists():
             ql = list(qs)
             ql = list(qs)
@@ -229,7 +230,8 @@ class CloudStorageView(View):
                 for key, val in enumerate(items_list):
                 for key, val in enumerate(items_list):
                     pay_types = Pay_Type.objects.filter(store_meal=items_list[key]['id']).values("id", "payment")
                     pay_types = Pay_Type.objects.filter(store_meal=items_list[key]['id']).values("id", "payment")
                     items_list[key]['pay_type'] = list(pay_types)
                     items_list[key]['pay_type'] = list(pay_types)
-
+                    items_list[key]['is_pay_cycle'] = 1 if items_list[key]['cycle_config_id'] else 0
+                    del items_list[key]['cycle_config_id']
                 res_c = {'area': area, 'items': items_list}
                 res_c = {'area': area, 'items': items_list}
                 res.append(res_c)
                 res.append(res_c)
             #是否促销
             #是否促销
@@ -1130,7 +1132,7 @@ class CloudStorageView(View):
         smqs = Store_Meal.objects.filter(id=rank, pay_type=pay_type, lang__lang=lang, is_show=0). \
         smqs = Store_Meal.objects.filter(id=rank, pay_type=pay_type, lang__lang=lang, is_show=0). \
             values('currency', 'price', 'lang__content', 'day',
             values('currency', 'price', 'lang__content', 'day',
                    'commodity_type', 'lang__title',
                    'commodity_type', 'lang__title',
-                   'expire', 'commodity_code', 'discount_price', 'bucket__mold')
+                   'expire', 'commodity_code', 'discount_price', 'bucket__mold', 'cycle_config_id')
         if not smqs.exists():
         if not smqs.exists():
             return response.json(173)
             return response.json(173)
         currency = smqs[0]['currency']
         currency = smqs[0]['currency']
@@ -1157,6 +1159,20 @@ class CloudStorageView(View):
 
 
         orderID = CommonService.createOrderID()
         orderID = CommonService.createOrderID()
         if pay_type == 1:
         if pay_type == 1:
+            # 订阅周期扣款
+            if(smqs[0]['cycle_config_id']):
+                subInfo = Paypal.subscriptions(store_info=smqs[0],lang=lang,orderID=orderID)
+                if not subInfo:
+                    return response.json(10048)
+                Order_Model.objects.create(orderID=orderID, UID=uid, channel=channel, userID_id=userID,
+                                           desc=content, payType=pay_type, payTime=nowTime,
+                                           price=price, currency=currency, addTime=nowTime, updTime=nowTime,
+                                           pay_url=subInfo['url'], isSelectDiscounts=is_select_discount,
+                                           commodity_code=commodity_code, commodity_type=commodity_type,
+                                           rank_id=rank, plan_id=subInfo['plan_id'])
+                return response.json(0, {"redirectUrl": subInfo['url'], "orderID": orderID})
+
+            #正常扣款
             cal_url = "{SERVER_DOMAIN_SSL}web/paid2/fail.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
             cal_url = "{SERVER_DOMAIN_SSL}web/paid2/fail.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
             if lang != 'cn':
             if lang != 'cn':
                 cal_url = "{SERVER_DOMAIN_SSL}web/paid2/en_fail.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
                 cal_url = "{SERVER_DOMAIN_SSL}web/paid2/en_fail.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)

+ 249 - 0
Controller/PaymentCycle.py

@@ -0,0 +1,249 @@
+from Ansjer.config import PAYPAL_CRD,SERVER_DOMAIN,SERVER_DOMAIN_SSL
+from Model.models import PayCycleConfigModel,Order_Model, Store_Meal, UID_Bucket, PromotionRuleModel, Unused_Uid_Meal,Device_Info
+from Service.CommonService import CommonService
+from django.http import JsonResponse, HttpResponseRedirect, HttpResponse
+import requests
+import time
+from Object.ResponseObject import ResponseObject
+import paypalrestsdk
+from paypalrestsdk import BillingAgreement
+from django.views.generic.base import View
+from django.db import transaction
+from Controller import CloudStorage
+from django.db.models import Q, F, Count
+
+#周期扣款相关
+class Paypal:
+    def subscriptions(store_info,lang,orderID):
+        cycle_config = PayCycleConfigModel.objects.filter(id=store_info['cycle_config_id']).values()
+        if not cycle_config:
+            return False
+        cal_url = "{SERVER_DOMAIN_SSL}web/paid2/fail.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
+        if lang != 'cn':
+            cal_url = "{SERVER_DOMAIN_SSL}web/paid2/en_fail.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
+        return_url = "{SERVER_DOMAIN_SSL}payCycle/paypalCycleReturn?lang={lang}". \
+            format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL, lang=lang)
+        # call_sub_url = "http://binbin.uicp.vip/cloudstorage/dopaypalcallback?orderID={orderID}".format(
+        # SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL, orderID=orderID)
+        BillingPlan = {
+            "description": orderID,
+            "merchant_preferences": {
+                "auto_bill_amount": "YES",
+                "cancel_url": cal_url,  # 取消协议url
+                "initial_fail_amount_action": "CANCEL",
+                "max_fail_attempts": "1",  # 允许的最大失败付款尝试次数
+                "return_url": return_url,  # 客户批准协议的url
+                # "notify_url": "http://www.notify.com",  #通知客户协议已创建的 URL。只读并保留供将来使用。
+                "setup_fee": {
+                    "currency": store_info['currency'],
+                    "value": store_info['price'],
+                }
+            },
+            "name": store_info['lang__content'],
+            "payment_definitions": [
+                {
+                    "amount": {
+                        "currency": store_info['currency'],
+                        "value": store_info['price']
+                    },
+                    # "charge_models": [
+                    #     {
+                    #         "amount": {
+                    #             "currency": "USD",
+                    #             "value": "20"
+                    #         },
+                    #         "type": "TAX"   #税金
+                    #     }
+                    # ],
+                    "cycles": cycle_config[0]['cycles'],
+                    "frequency": cycle_config[0]['frequency'],
+                    "frequency_interval": cycle_config[0]['frequencyInterval'],
+                    "name": store_info['lang__title'],
+                    "type": "REGULAR"
+                },
+            ],
+            "type": "INFINITE",
+        }
+        paypalrestsdk.configure(PAYPAL_CRD)
+        billing_plan = paypalrestsdk.BillingPlan(BillingPlan)
+        if billing_plan.create():
+            billing_plan.activate()  # 激活
+            plan_id = billing_plan.id
+        else:
+            print(billing_plan.error)
+            return False
+
+        now_time = int(time.time())
+        start_date_timestamp = CommonService.calcMonthLater(1, now_time) - (5 * 86400) #下次扣款为下个月提前5天扣款
+        start_date_str = CommonService.timestamp_to_str(start_date_timestamp, "%Y-%m-%dT%H:%M:%SZ")
+        #订阅
+        billingAgreement = {
+            "name": store_info['lang__content'],
+            "description": orderID,
+            "start_date": start_date_str,
+            "plan": {
+                "id": plan_id
+            },
+            "payer": {
+                "payment_method": "paypal"
+            },
+        }
+        billing_agreement = paypalrestsdk.BillingAgreement(billingAgreement)
+        # print(billing_agreement.create())
+        if billing_agreement.create():
+            for link in billing_agreement.links:
+                if link.rel == "approval_url":
+                    return {"plan_id": plan_id, "url": link.href}
+        else:
+            print(billing_agreement.error)
+            return False
+
+class PaypalCycleNotify(View):
+    def get(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        operation = kwargs.get('operation')
+        return self.validation(request.GET, request, operation)
+
+    def post(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        operation = kwargs.get('operation')
+        return self.validation(request.POST, request, operation)
+
+    def validation(self, request_dict, request, operation):
+        response = ResponseObject()
+        if operation is None:
+            return response.json(444, 'error path')
+        elif operation == 'paypalCycleReturn':  # paypal成功订阅回调
+            return self.do_paypal_cycle_return(request_dict, response)
+        elif operation == 'paypalCycleNotify':  # paypal 周期付款回调
+            return self.do_paypal_webhook_notify(request_dict, response)
+    def do_paypal_cycle_return(self, request_dict, response):
+        lang = request_dict.get('lang', 'en')
+        token = request_dict.get('token',None)
+        paypalrestsdk.configure(PAYPAL_CRD)
+        billing_agreement = paypalrestsdk.BillingAgreement()
+        billing_agreement_response = billing_agreement.execute(token)
+        if billing_agreement_response.error:
+            print(billing_agreement_response.error)
+            red_url = "{SERVER_DOMAIN_SSL}web/paid2/fail.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
+            if lang != 'cn':
+                red_url = "{SERVER_DOMAIN_SSL}web/paid2/en_fail.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
+            return HttpResponseRedirect(red_url)
+
+        orderID = billing_agreement_response.description
+        agreement_id = billing_agreement_response.id
+        promotion_rule_id = ''
+        try:
+            order_qs = Order_Model.objects.filter(orderID=orderID, status=0)
+
+            if not orderID:
+                print("not orderID")
+                red_url = "{SERVER_DOMAIN_SSL}web/paid2/fail.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
+                if lang != 'cn':
+                    red_url = "{SERVER_DOMAIN_SSL}web/paid2/en_fail.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
+                return HttpResponseRedirect(red_url)
+
+            order_list = order_qs.values("UID", "channel", "commodity_code", "rank", "isSelectDiscounts",
+                                         "userID__userID",
+                                         "userID__username")
+            userid = order_list[0]['userID__userID']
+            username = order_list[0]['userID__username']
+            UID = order_list[0]['UID']
+            channel = order_list[0]['channel']
+            rank = order_list[0]['rank']
+            smqs = Store_Meal.objects.filter(id=rank). \
+                values("day", "bucket_id", "bucket__storeDay", "expire")
+            bucketId = smqs[0]['bucket_id']
+            if not smqs.exists():
+                print("not smqs")
+                red_url = "{SERVER_DOMAIN_SSL}web/paid2/fail.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
+                if lang != 'cn':
+                    red_url = "{SERVER_DOMAIN_SSL}web/paid2/en_fail.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
+                return HttpResponseRedirect(red_url)
+            # ##
+            ubqs = UID_Bucket.objects.filter(uid=UID).values("id", "bucket_id", "bucket__storeDay", "bucket__region",
+                                                             "endTime", "use_status")
+            expire = smqs[0]['expire']
+
+            if order_list[0]['isSelectDiscounts'] == 1:
+                expire = smqs[0]['expire'] * 2
+            # 是否有促销
+            nowTime = int(time.time())
+            promotion = PromotionRuleModel.objects.filter(status=1, startTime__lte=nowTime,
+                                                          endTime__gte=nowTime).values('id','ruleConfig')
+            if promotion.exists():
+                promotion_rule_id = promotion[0]['id']
+                expire = expire * 2
+            with transaction.atomic():
+                if ubqs.exists():
+                    ubq = ubqs[0]
+                    if ubq['use_status'] == 1 and ubq['bucket_id'] == bucketId:  #套餐使用中并且相同套餐叠加过期时间
+                        endTime = CommonService.calcMonthLater(expire, ubq['endTime'])
+                        UID_Bucket.objects.filter(id=ubq['id']).update \
+                            (uid=UID, channel=channel, bucket_id=bucketId,
+                             endTime=endTime, updateTime=nowTime)
+                    else:     #已过期或者不相同的套餐加入未使用的关联套餐表
+                        has_unused = Unused_Uid_Meal.objects.filter(uid=UID, bucket_id=bucketId).values("id")
+                        nums = 2 if order_list[0]['isSelectDiscounts'] == 1 else 1
+                        if promotion.exists():
+                            nums = nums + 1
+                        if has_unused.exists():
+                            Unused_Uid_Meal.objects.filter(id=has_unused[0]['id']).update(num=F('num') + nums)
+                        else:
+                            Unused_Uid_Meal.objects.create(uid=UID,channel=channel,addTime=nowTime,num=nums,
+                                                           expire=smqs[0]['expire'],bucket_id=bucketId)
+                        UID_Bucket.objects.filter(id=ubq['id']).update(has_unused=1)
+                    uid_bucket_id = ubq['id']
+                else:
+                    endTime = CommonService.calcMonthLater(expire)
+                    ub_cqs = UID_Bucket.objects.create \
+                        (uid=UID, channel=channel, bucket_id=bucketId, endTime=endTime, addTime=nowTime,
+                         updateTime=nowTime,use_status=1)
+                    uid_bucket_id = ub_cqs.id
+
+                dvq = Device_Info.objects.filter(UID=UID, vodPrimaryUserID='', vodPrimaryMaster='')
+                if dvq.exists():
+                    dvq_set_update_dict = {
+                        'vodPrimaryUserID': userid,
+                        'vodPrimaryMaster': username
+                    }
+                    dvq.update(**dvq_set_update_dict)
+
+                # uid_main_exist = UIDMainUser.objects.filter(UID=UID)
+                # if not uid_main_exist.exists():
+                #     uid_main_dict = {
+                #         'UID': UID,
+                #         'user_id': userid
+                #     }
+                #     UIDMainUser.objects.create(**uid_main_dict)
+
+                order_qs.update(status=1, updTime=nowTime, uid_bucket_id=uid_bucket_id,
+                                promotion_rule_id=promotion_rule_id,agreement_id=agreement_id)
+                datetime = time.strftime("%Y-%m-%d", time.localtime())
+                sys_msg_text_list = ['温馨提示:尊敬的客户,您的' + UID + '设备在' + datetime + '已成功订阅云存套餐',
+                                     'Dear customer,you already subscribed the cloud storage package successfully for device ' + UID + ' on ' + time.strftime(
+                                         "%b %dth,%Y", time.localtime())]
+
+                CloudStorage.CloudStorageView.do_vod_msg_Notice(self, UID, channel, userid, lang, sys_msg_text_list, 'SMS_219738485')
+
+                # return response.json(0)
+                red_url = "{SERVER_DOMAIN_SSL}web/paid2/success.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
+                if lang != 'cn':
+                    red_url = "{SERVER_DOMAIN_SSL}web/paid2/en_success.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
+                return HttpResponseRedirect(red_url)
+        except Exception as e:
+            print(repr(e))
+            if order_qs:
+                order_qs.update(status=10, promotion_rule_id=promotion_rule_id)
+            red_url = "{SERVER_DOMAIN_SSL}web/paid2/fail.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
+            if lang != 'cn':
+                red_url = "{SERVER_DOMAIN_SSL}web/paid2/en_fail.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
+            return HttpResponseRedirect(red_url)
+
+
+    def do_paypal_webhook_notify(self, request_dict, response):
+        paymentId = request_dict.get('paymentId', None)
+        PayerID = request_dict.get('PayerID', None)
+        lang = request_dict.get('lang', 'en')
+        token = request_dict.get('token',None)
+        paypalrestsdk.configure(PAYPAL_CRD)

+ 8 - 24
Controller/UidSetController.py

@@ -160,30 +160,14 @@ class UidSetView(View):
                     else:
                     else:
                         val = val + 1
                         val = val + 1
                         print('UID_Preview表没有数据')
                         print('UID_Preview表没有数据')
-                if 'UID_Bucket' in id_list:
-                    del_uid = UID_Bucket.objects.filter(uid__in=uid)
-                    if del_uid.exists():
-                        del_uid.delete()
-                        # print ('删除UID_Bucket')
-                    else:
-                        val = val + 1
-                        print('UID_Bucket表没有数据')
-                if 'VodHlsModel' in id_list:
-                    del_uid = VodHlsModel.objects.filter(uid__in=uid)
-                    if del_uid.exists():
-                        # del_uid.delete()
-                        print ('删除VodHlsModel')
-                    else:
-                        val = val + 1
-                        print('VodHlsModel表没有数据')
-                if 'Order_Model' in id_list:
-                    del_uid = Order_Model.objects.filter(UID__in=uid)
-                    if del_uid.exists():
-                        del_uid.delete()
-                        # print ('删除Order_Model')
-                    else:
-                        val = val + 1
-                        print('Order_Model表没有数据')
+                if 'Reset_Vod' in id_list:  # 重置设备云存
+                    UID_Bucket.objects.filter(uid__in=uid).delete()
+                    Unused_Uid_Meal.objects.filter(uid__in=uid).delete()
+                    Order_Model.objects.filter(UID__in=uid).delete()
+                    StsCrdModel.objects.filter(uid__in=uid).delete()
+                    VodHlsModel.objects.filter(uid__in=uid).delete()
+                    ExperienceContextModel.objects.filter(uid__in=uid).delete()
+                    Device_Info.objects.filter(UID__in=uid).update(vodPrimaryUserID='', vodPrimaryMaster='')
                 if 'Device_Info' in id_list:
                 if 'Device_Info' in id_list:
                     del_uid = Device_Info.objects.filter(UID__in=uid)
                     del_uid = Device_Info.objects.filter(UID__in=uid)
                     if del_uid.exists():
                     if del_uid.exists():

+ 21 - 5
Model/models.py

@@ -472,9 +472,8 @@ class Store_Meal(models.Model):
     is_show = models.SmallIntegerField(default=0, verbose_name=u'该套餐是否隐藏 [0=否,1是]')
     is_show = models.SmallIntegerField(default=0, verbose_name=u'该套餐是否隐藏 [0=否,1是]')
     # lang = models.CharField(default='', max_length=20, verbose_name='语言/国家')
     # lang = models.CharField(default='', max_length=20, verbose_name='语言/国家')
     lang = models.ManyToManyField(to='Lang', verbose_name='套餐语言', db_table='store_meal_lang')
     lang = models.ManyToManyField(to='Lang', verbose_name='套餐语言', db_table='store_meal_lang')
-
+    cycle_config_id = models.IntegerField(null=True, verbose_name='周期付款配置表id')
     # 备用字段
     # 备用字段
-    spare_1 = models.CharField(default='', blank=True, max_length=64, verbose_name=u'备用字段1')
     spare_2 = models.CharField(default='', blank=True, max_length=64, verbose_name=u'备用字段2')
     spare_2 = models.CharField(default='', blank=True, max_length=64, verbose_name=u'备用字段2')
     spare_3 = models.CharField(default='', blank=True, max_length=64, db_index=True, verbose_name=u'备用字段3')
     spare_3 = models.CharField(default='', blank=True, max_length=64, db_index=True, verbose_name=u'备用字段3')
     spare_4 = models.CharField(default='', blank=True, max_length=64, db_index=True, verbose_name=u'备用字段4')
     spare_4 = models.CharField(default='', blank=True, max_length=64, db_index=True, verbose_name=u'备用字段4')
@@ -623,12 +622,12 @@ class Order_Model(models.Model):
     pay_url = models.CharField(max_length=2000, default='', verbose_name='支付url')
     pay_url = models.CharField(max_length=2000, default='', verbose_name='支付url')
     paypal = models.CharField(max_length=500, null=True, blank=True, verbose_name='支付批准url')
     paypal = models.CharField(max_length=500, null=True, blank=True, verbose_name='支付批准url')
     promotion_rule_id = models.CharField(blank=True, max_length=64, default='', verbose_name='促销id')
     promotion_rule_id = models.CharField(blank=True, max_length=64, default='', verbose_name='促销id')
+    plan_id = models.CharField(default='', blank=True, max_length=64, verbose_name=u'paypal计划id')
+    agreement_id = models.CharField(default='', blank=True, max_length=64, verbose_name=u'paypal协议id')
 
 
     # 备用字段
     # 备用字段
-    spare_1 = models.CharField(default='', blank=True, max_length=64, verbose_name=u'备用字段1')
-    spare_2 = models.CharField(default='', blank=True, max_length=64, verbose_name=u'备用字段2')
-    spare_3 = models.CharField(default='', blank=True, max_length=64, db_index=True, verbose_name=u'备用字段3')
     spare_4 = models.CharField(default='', blank=True, max_length=64, db_index=True, verbose_name=u'备用字段4')
     spare_4 = models.CharField(default='', blank=True, max_length=64, db_index=True, verbose_name=u'备用字段4')
+    spare_2 = models.CharField(default='', blank=True, max_length=64, verbose_name=u'备用字段2')
 
 
     def __str__(self):
     def __str__(self):
         return self.orderID
         return self.orderID
@@ -639,6 +638,23 @@ class Order_Model(models.Model):
         verbose_name_plural = verbose_name
         verbose_name_plural = verbose_name
         ordering = ('-orderID',)
         ordering = ('-orderID',)
 
 
+class PayCycleConfigModel(models.Model):
+    id = models.AutoField(primary_key=True, verbose_name='主键')
+    # name = models.CharField(default='',max_length=200, verbose_name='计划名字')
+    # tax = models.CharField(max_length=2000, default='', verbose_name='税金')
+    cycles = models.IntegerField(verbose_name='周期:0代表无限期', default=0)
+    frequency = models.CharField(max_length=50,verbose_name='频率,MONTH,WEEK,YEAR', default=0)
+    frequencyInterval = models.IntegerField(default=0, verbose_name='频率周期')
+    remark = models.CharField(max_length=1000, default='', verbose_name='备注')
+
+    def __str__(self):
+        return self.id
+
+    class Meta:
+        db_table = 'pay_cycle_config'
+        verbose_name = u'周期付款计划'
+        verbose_name_plural = verbose_name
+
 class PromotionRuleModel(models.Model):
 class PromotionRuleModel(models.Model):
     id = models.AutoField(primary_key=True, verbose_name='主键')
     id = models.AutoField(primary_key=True, verbose_name='主键')
     ruleName = models.TextField(default='', verbose_name='规则名字')                     #json格式, 例: {"cn":"黑色星期五","en":"Black Friday"}
     ruleName = models.TextField(default='', verbose_name='规则名字')                     #json格式, 例: {"cn":"黑色星期五","en":"Black Friday"}

+ 94 - 0
Object/MergePic.py

@@ -0,0 +1,94 @@
+import os
+
+import PIL.Image as Image
+
+
+def resize_by_width(infile, image_size):
+    """按照宽度进行所需比例缩放"""
+    im = Image.open(infile)
+    (x, y) = im.size
+    lv = round(x / image_size, 2) + 0.01
+    x_s = int(x // lv)
+    y_s = int(y // lv)
+    print("x_s", x_s, y_s)
+    out = im.resize((x_s, y_s), Image.ANTIALIAS)
+    return out
+
+
+def get_new_img_xy(infile, image_size):
+    """返回一个图片的宽、高像素"""
+    im = Image.open(infile)
+    (x, y) = im.size
+    lv = round(x / image_size, 2) + 0.01
+    x_s = x // lv
+    y_s = y // lv
+    # print("x_s", x_s, y_s)
+    # out = im.resize((x_s, y_s), Image.ANTIALIAS)
+    return x_s, y_s
+
+
+# 定义图像拼接函数
+def image_compose(image_colnum, image_size, image_rownum, image_names, image_save_path, x_new, y_new):
+    to_image = Image.new('RGB', (image_colnum * x_new, image_rownum * y_new))  # 创建一个新图
+    # 循环遍历,把每张图片按顺序粘贴到对应位置上
+    total_num = 0
+    for y in range(1, image_rownum + 1):
+        for x in range(1, image_colnum + 1):
+            from_image = resize_by_width(image_names[image_colnum * (y - 1) + x - 1], image_size)
+            # from_image = Image.open(image_names[image_colnum * (y - 1) + x - 1]).resize((image_size,image_size ), Image.ANTIALIAS)
+            to_image.paste(from_image, ((x - 1) * x_new, (y - 1) * y_new))
+            total_num += 1
+            if total_num == len(image_names):
+                break
+    return to_image.save(image_save_path)  # 保存新图
+
+
+def get_image_list_fullpath(dir_path):
+    file_name_list = os.listdir(dir_path)
+    image_fullpath_list = []
+    for file_name_one in file_name_list:
+        file_one_path = os.path.join(dir_path, file_name_one)
+        if os.path.isfile(file_one_path):
+            image_fullpath_list.append(file_one_path)
+        else:
+            img_path_list = get_image_list_fullpath(file_one_path)
+            image_fullpath_list.extend(img_path_list)
+    return image_fullpath_list
+
+
+def merge_images(image_dir_path,image_size,image_colnum):
+    # 获取图片集地址下的所有图片名称
+    image_fullpath_list = get_image_list_fullpath(image_dir_path)
+    print("image_fullpath_list", len(image_fullpath_list), image_fullpath_list)
+
+    image_save_path = r'{}.jpg'.format(image_dir_path)  # 图片转换后的地址
+    print(image_save_path);
+    # image_rownum = 4  # 图片间隔,也就是合并成一张图后,一共有几行
+    image_rownum_yu = len(image_fullpath_list) % image_colnum
+    if image_rownum_yu == 0:
+        image_rownum = len(image_fullpath_list) // image_colnum
+    else:
+        image_rownum = len(image_fullpath_list) // image_colnum + 1
+
+    x_list = []
+    y_list = []
+    for img_file in image_fullpath_list:
+        img_x, img_y = get_new_img_xy(img_file, image_size)
+        x_list.append(img_x)
+        y_list.append(img_y)
+
+    print("x_list", sorted(x_list))
+    print("y_list", sorted(y_list))
+    x_new = int(x_list[len(x_list) // 5 * 4])
+    y_new = int(y_list[len(y_list) // 5 * 4])
+    print(" x_new, y_new", x_new, y_new)
+    image_compose(image_colnum, image_size, image_rownum, image_fullpath_list, image_save_path, x_new, y_new)  # 调用函数
+    # for img_file in image_fullpath_list:
+    #     resize_by_width(img_file,image_size)
+
+if __name__ == '__main__':
+
+    image_dir_path = r'E:\photo\test'  # 图片集地址
+    image_size = 500  # 每张小图片的大小
+    image_colnum = 2  # 合并成一张图后,一行有几个小图
+    merge_images(image_dir_path, image_size, image_colnum)

+ 2 - 0
Object/ResponseObject.py

@@ -104,6 +104,7 @@ class ResponseObject(object):
             10045: 'Already the latest version',
             10045: 'Already the latest version',
             10046: 'Sorry, users who have activated cloud storage packages do not support logout at the moment, please contact customer service',
             10046: 'Sorry, users who have activated cloud storage packages do not support logout at the moment, please contact customer service',
             10047: 'Please delete all devices under your account first',
             10047: 'Please delete all devices under your account first',
+            10048: 'Subscribe to the failure',
         }
         }
         data_cn = {
         data_cn = {
             0: '成功',
             0: '成功',
@@ -201,6 +202,7 @@ class ResponseObject(object):
             10045: '当前为最新版本',
             10045: '当前为最新版本',
             10046: '已开通云存的用户,暂不支持注销,请联系客服',
             10046: '已开通云存的用户,暂不支持注销,请联系客服',
             10047: '请先删除您当前帐户下的所有设备',
             10047: '请先删除您当前帐户下的所有设备',
+            10048: '订阅失败',
         }
         }
         if self.lang == 'cn':
         if self.lang == 'cn':
             msg = data_cn
             msg = data_cn