lang 3 жил өмнө
parent
commit
60ddfe097b

+ 10 - 4
AdminController/UserManageController.py

@@ -322,7 +322,7 @@ class UserManagement(View):
             elif operation == 'AddOrEditAccount':
                 return self.AddOrEditAccount(userID, request_dict, response)
             elif operation == 'doDelete':
-                return self.doDelete(userID, request_dict, response)
+                return self.doDelete(request_dict, response)
             elif operation == 'resetPassword':
                 return self.resetPassword(request_dict, response)
             elif operation == 'getFeedbackList':
@@ -447,10 +447,16 @@ class UserManagement(View):
             print(e)
             return response.json(500, repr(e))
 
-    def doDelete(self, userID, request_dict, response):
+    def doDelete(self, request_dict, response):
         userID = request_dict.get('userID', '')
-        Device_User.objects.filter(userID=userID).delete()
-        return response.json(0)
+        if not userID:
+            return response.json(444)
+        try:
+            Device_User.objects.filter(userID=userID).delete()
+            return response.json(0)
+        except Exception as e:
+            print(e)
+            return response.json(500, repr(e))
 
     def resetPassword(self, request_dict, response):
         userID = request_dict.get('userID', None)

+ 117 - 242
AdminController/VersionManagementController.py

@@ -1,32 +1,14 @@
 #!/usr/bin/env python3
 # -*- coding: utf-8 -*-
-import hashlib
-import json
 import os
-import time
-import urllib
-import uuid
-import boto3
-import threading
-import logging
-
-import xlwt
-from boto3.session import Session
-from django.http import JsonResponse, HttpResponseRedirect, HttpResponse, StreamingHttpResponse
+import hashlib
 from django.views.generic.base import View
 
-from Ansjer.config import BASE_DIR, SERVER_DOMAIN
-from Model.models import Device_Info, Role, MenuModel, VodBucketModel, CDKcontextModel, Store_Meal, Order_Model, \
-    UID_Bucket, ExperienceContextModel, Lang, Device_User, CloudLogModel, UidSetModel, Equipment_Version, \
-    EquipmentVersionLimitModel
-from Object.RedisObject import RedisObject
-from Object.ResponseObject import ResponseObject
+from Ansjer.config import BASE_DIR
+from Model.models import Equipment_Version
 from Object.TokenObject import TokenObject
-from Object.UidTokenObject import UidTokenObject
-from Object.UrlTokenObject import UrlTokenObject
+from Object.ResponseObject import ResponseObject
 from Service.CommonService import CommonService
-from django.db.models import Q, F
-from time import strftime
 
 
 class VersionManagement(View):
@@ -43,23 +25,24 @@ class VersionManagement(View):
     def validation(self, request_dict, request, operation):
         language = request_dict.get('language', 'en')
         response = ResponseObject(language, 'pc')
-        tko = TokenObject(
-            request.META.get('HTTP_AUTHORIZATION'),
-            returntpye='pc')
-        if tko.code != 0:
-            return response.json(tko.code)
-        response.lang = tko.lang
-        userID = tko.userID
-        if operation == 'getEquipmentVersionList':
-            return self.getEquipmentVersionList(request_dict, response)
-        elif operation == 'query':
-            return self.do_query(request_dict, response)
-        elif operation == 'update':
-            return self.do_update(request_dict, response, request)
-        elif operation == 'filter':
-            return self.do_filter(request_dict, response)
+        if operation == 'upLoadFile':
+            return self.upLoadFile(request, request_dict, response)
         else:
-            return response.json(404)
+            tko = TokenObject(
+                request.META.get('HTTP_AUTHORIZATION'),
+                returntpye='pc')
+            if tko.code != 0:
+                return response.json(tko.code)
+            response.lang = tko.lang
+            userID = tko.userID
+            if operation == 'getEquipmentVersionList':
+                return self.getEquipmentVersionList(request_dict, response)
+            elif operation == 'editVersionInformation':
+                return self.editVersionInformation(request_dict, response)
+            elif operation == 'deleteEquipmentVersion':
+                return self.deleteEquipmentVersion(request_dict, response)
+            else:
+                return response.json(404)
 
     def getEquipmentVersionList(self, request_dict, response):
         mci = request_dict.get('mci', None)
@@ -91,215 +74,107 @@ class VersionManagement(View):
             print(e)
             return response.json(500, repr(e))
 
-    def do_update(self, request_dict, response, request):
-        code = request_dict.get('code', None)
-        status = request_dict.get('status', None)
-        lang = request_dict.get('lang', None)
-        max_ver = request_dict.get('max_ver', None)
-        file_s = request.FILES.get('file', None)
-        paths = 'static/versions/image'
-        if not os.path.exists(paths):
-            os.makedirs(paths)  # makedirs 创建文件时如果路径不存在会创建这个路径
-            # print ('该文件不存在')
-        else:
-            print('该文件存在')
-        ev = Equipment_Version.objects.filter(code=code, lang=lang)
-        if file_s is None:
-            rv_path = 'static/versions/image/' + code + '.png'
-            img = SERVER_DOMAIN + 'sysfile/' + rv_path
-        else:
-            rv_path = 'static/versions/image/' + code + '.png'
-            try:
-                as_path = os.path.join(BASE_DIR, rv_path)
-                if os.path.exists(as_path):
-                    os.remove(as_path)
-                with open(as_path, 'wb+') as destination:
-                    for chunk in file_s.chunks():
-                        destination.write(chunk)
-            except Exception as e:
-                pass
-            else:
-                img = SERVER_DOMAIN + 'sysfile/' + rv_path
-        if code is not None:
+    def upLoadFile(self, request, request_dict, response):
+        file = request.FILES.get('file', None)
+        mci = request_dict.get('mci', '')
+        lang = request_dict.get('lang', '')
+        ESN = request_dict.get('ESN', '')
+        max_ver = request_dict.get('max_ver', '')
+        channel = request_dict.get('channel', '')
+        resolutionRatio = request_dict.get('resolutionRatio', '')
+        Description = request_dict.get('Description', '')
+        status = request_dict.get('status', 0)
+        fileSize = request_dict.get('fileSize', '')
+
+        if not all([file, mci, lang, ESN, max_ver, channel, resolutionRatio]):
+            return response.json(444)
 
-            if ev.exists():
-                try:
-                    update_time = time.timezone.localtime(time.timezone.now())
-                    update_dict = {
-                        'status': status,
-                        'img': img,
-                        'update_time': update_time
-                    }
-                    if max_ver:
-                        update_dict['max_ver'] = max_ver
-                    ev.update(**update_dict)
-                except Exception as e:
-                    return response.json(404, repr(e))
-                else:
-                    return response.json(0, {'update_time': str(update_time), 'img': img})
+        try:
+            channel = int(channel)
+            resolutionRatio = int(resolutionRatio)
+            status = int(status)
+            # 文件名为设备版本,最后一个'.'的前面为软件版本,后面为设备规格名称
+            # V2.2.4.16E201252CA,软件版本:2.2.4,设备规格名称:16E201252CA
+            file_name = str(file)                           # 文件名
+            version = file_name[:file_name.rindex('.')]     # 设备版本
+            rpoint = version.rindex('.')
+            softwareVersion = version[1:rpoint]             # 软件版本
+            code = version[rpoint+1:]                       # 设备规格名称
+            chipModelList2Code = code[:4]                   # 主芯片
+            type = code[-3:-1]                              # 设备机型
+            companyCode = code[-1:]                         # 公司代码
+            fileSize = fileSize
+            filePath = '/'.join(('static/otapack', mci, lang, file_name))
+            file_data = file.read()
+            fileMd5 = hashlib.md5(file_data).hexdigest()
+            data_dict = {'mci': mci, 'lang': lang, 'ESN': ESN, 'max_ver': max_ver,  'channel': channel,
+                         'resolutionRatio': resolutionRatio, 'Description': Description, 'status': status,
+                         'version': version, 'softwareVersion': softwareVersion, 'code': code,
+                         'chipModelList2Code': chipModelList2Code, 'type': type, 'companyCode': companyCode,
+                         'fileSize': fileSize, 'filePath': filePath, 'fileMd5': fileMd5}
+            # Equipment_Version表创建或更新数据
+            equipment_version_qs = Equipment_Version.objects.filter(code=code, lang=lang)
+            if not equipment_version_qs.exists():
+                Equipment_Version.objects.create(eid=CommonService.getUserID(getUser=False, setOTAID=True), **data_dict)
             else:
-                return response.json(173)
-        else:
-            return response.json(444, 'code')
-
-    def do_check_ver(self, request_dict, response):
-        code = request_dict.get('code', None)
-        ov = request_dict.get('ov', None)
-        uid = request_dict.get('uid', '')
-        if not code:
-            return response.json(444, 'code')
-        eqs = Equipment_Version.objects.filter(code=uid, status=1, lang='en').order_by('-data_joined')
-        if not eqs.exclude():
-            eqs = Equipment_Version.objects.filter(code=code, status=1, lang='en').order_by('-data_joined')
-        if not eqs.exists():
-            return response.json(900)
-        if ov is not None:
-            # 判断大小
-            if ov > eqs[0].softwareVersion:
-                return response.json(0, {'softwareVersion': ov})
-        file_path = eqs[0].filePath
-        if file_path.find('static/Upgrade/') != -1:
-            path = file_path.replace('static/Upgrade/', '').replace('\\', '/')
-            url = SERVER_DOMAIN + 'OTA/downloads/' + path + '?time=' + str(time.time())
-        elif file_path.find('static/otapack') != -1:
-            url = SERVER_DOMAIN + 'OTA/downloadsPack/' + file_path + '?time=' + str(time.time())
-            # url = SERVER_DOMAIN + 'dl/otaPack/' + file_path + '?time=' + str(time.time())
-        else:
-            return response.json(900, '2')
-        res = {
-            "url": url,
-            "fileSize": eqs[0].fileSize,
-            "Description": eqs[0].Description,
-            "softwareVersion": eqs[0].softwareVersion
-        }
-        return response.json(0, res)
-
-    # 修改加密的路径
-    def do_check_value(self, request_dict, response):
-        code = request_dict.get('code', None)
-        ov = request_dict.get('ov', None)
-        uid = request_dict.get('uid', '')
-        if not code:
-            return response.json(444, 'code')
-        eqs = Equipment_Version.objects.filter(code=uid, status=1, lang='en').order_by('-data_joined')
-
-        if not eqs.exclude():
-            eqs = Equipment_Version.objects.filter(code=code, status=1, lang='en').order_by('-data_joined')
-        if not eqs.exists():
-            return response.json(900)
-        if ov is not None:
-            # 判断大小
-            if ov > eqs[0].softwareVersion:
-                return response.json(0, {'softwareVersion': ov})
-        equipment = eqs[0]
-        redisObject = RedisObject()
-        key = 'limit_{eid}'.format(eid=equipment.eid)
+                equipment_version_qs.update(**data_dict)
+
+            # 上传文件到服务器
+            upload_path = '/'.join((BASE_DIR, 'static/otapack', mci, lang)).replace('\\', '/') + '/'
+            if not os.path.exists(upload_path):  # 上传目录不存在则创建
+                os.makedirs(upload_path)
+            # 文件上传
+            full_name = upload_path + file_name
+            if os.path.exists(full_name):   # 删除同名文件
+                os.remove(full_name)
+            with open(full_name, 'wb+') as write_file:
+                for chunk in file.chunks():
+                    write_file.write(chunk)
+            return response.json(0)
+        except Exception as e:
+            print(e)
+            return response.json(500, repr(e))
 
-        evl_qs = redisObject.get_data(key=key)
-        if evl_qs:
-            evl_qs = json.loads(evl_qs)
-        else:
-            evl_qs = EquipmentVersionLimitModel.objects.filter(equipment_version_id=equipment.eid,
-                                                               status=1).values()
-            if evl_qs.exists():
-                redisObject.set_data(key=key, val=json.dumps(list(evl_qs.values())), expire=600)
-        if evl_qs and len(evl_qs) > 0:
-            evl = evl_qs[0]
-            if evl['type'] == 1:  # uid限制
-                uids = json.loads(evl['content'])
-                if not uids.__contains__(uid):
-                    return response.json(902)
-        file_path = eqs[0].filePath
-        if file_path.find('static/Upgrade/') != -1:
-            path = file_path.replace('static/Upgrade/', '').replace('\\', '/')
-            # 创建url的token
-            tko = UrlTokenObject()
-            path = tko.generate(data={'Url': "ansjer/" + CommonService.RandomStr(6) + "/" + file_path})
+    def editVersionInformation(self, request_dict, response):
+        eid = request_dict.get('eid', None)
+        ESN = request_dict.get('ESN', '')
+        max_ver = request_dict.get('max_ver', '')
+        status = request_dict.get('status', '')
+        channel = request_dict.get('channel', '')
+        resolutionRatio = request_dict.get('resolutionRatio', '')
+        Description = request_dict.get('Description', '')
 
-            url = SERVER_DOMAIN + 'OTA/downloads/' + path
-        elif file_path.find('static/otapack') != -1:
-            file_path = file_path
-            # 创建url的token
-            tko = UrlTokenObject()
-            file_path = tko.generate(data={'Url': "ansjer/" + CommonService.RandomStr(6) + "/" + file_path})
+        if not eid:
+            return response.json(444)
+        status = 1 if status == 'true' else 0
+        try:
+            equipment_version_qs = Equipment_Version.objects.filter(eid=eid)
+            if not equipment_version_qs.exists():
+                return response.json(173)
+            data_dict = {'ESN': ESN, 'max_ver': max_ver, 'status': status, 'channel': channel,
+                         'resolutionRatio': resolutionRatio, 'Description': Description}
+            equipment_version_qs.update(**data_dict)
+            return response.json(0)
+        except Exception as e:
+            print(e)
+            return response.json(500, repr(e))
 
-            url = SERVER_DOMAIN + 'dlotapack/' + file_path
-        else:
-            return response.json(900, '2')
-        # http: // 192.168.136.39:8000 / EquipmentVersion / checkVer?code = 20D20410010
+    def deleteEquipmentVersion(self, request_dict, response):
+        eid = request_dict.get('eid', None)
 
-        res = {
-            "url": url,
-            "fileSize": eqs[0].fileSize,
-            "Description": eqs[0].Description,
-            "softwareVersion": eqs[0].softwareVersion
-        }
-        print(url)
-        return response.json(0, res)
- 
-    def do_query(self, request_dict, response):
-        mci = request_dict.get('mci', None)
-        page = request_dict.get('page', None)
-        line = request_dict.get('line', None)
-        code = request_dict.get('code', None)
-        if not page or not line:
-            return response.json(444, 'page,line')
-        else:
-            page = int(page)
-            line = int(line)
-        cv_qs = Equipment_Version.objects
-        if mci is not None:
-            cv_qs = cv_qs.filter(mci=mci)
-        if code is not None:
-            cv_qs = cv_qs.filter(code__contains=code)
-        cv_qs = cv_qs.order_by('code').values_list('code', flat=True).distinct()
-        print(cv_qs)
-        count = cv_qs.count()
-        cv_qs = list(cv_qs[(page - 1) * line:page * line])
-        # return response.json(0, cv_qs)
-        ev_qs = Equipment_Version.objects.filter(code__in=list(cv_qs)).values()
-        ev_list = CommonService.qs_to_list(ev_qs)
-        datas = {}
-        # 组装数据
-        for ev in ev_list:
-            for code in cv_qs:
-                if code not in datas.keys():
-                    datas[code] = []
-                if code == ev['code']:
-                    datas[code].append(ev)
-        res = {
-            'datas': datas,
-            'count': count
-        }
-        return response.json(0, res)
+        if not eid:
+            return response.json(444)
 
-    def do_filter(self, request_dict, response):
-        mci = request_dict.get('mci', None)
-        page = request_dict.get('page', None)
-        line = request_dict.get('line', None)
-        code = request_dict.get('code', None)
-        lang = request_dict.get('lang', None)
-        if not page or not line:
-            return response.json(444, 'page,line')
-        else:
-            page = int(page)
-            line = int(line)
-        ev_qs = Equipment_Version.objects
-        if mci:
-            ev_qs = ev_qs.filter(mci=mci)
-        if code:
-            ev_qs = ev_qs.filter(code__contains=code)
-        if lang:
-            if lang == 'cn' or lang == 'zh-Hans':
-                ev_qs = ev_qs.filter(Q(lang='cn') | Q(lang='zh-Hans'))
-            else:
-                ev_qs = ev_qs.filter(lang=lang)
+        try:
+            equipment_version_qs = Equipment_Version.objects.filter(eid=eid)
+            filePath = equipment_version_qs.values('filePath')[0]['filePath']
+            equipment_version_qs.delete()
+            # 删除文件
+            full_name = '/'.join((BASE_DIR, filePath)).replace('\\', '/')
+            if os.path.exists(full_name):
+                os.remove(full_name)
+            return response.json(0)
+        except Exception as e:
+            print(e)
+            return response.json(500, repr(e))
 
-        count = ev_qs.count()
-        ev_qs = ev_qs[(page - 1) * line:page * line].values()
-        ev_ls = CommonService.qs_to_list(ev_qs)
-        res = {
-            'datas': ev_ls,
-            'count': count
-        }
-        return response.json(0, res)

+ 82 - 20
Controller/CloudStorage.py

@@ -40,7 +40,7 @@ from Ansjer.config import OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET, OSS_ROLE_AR
 from Controller.CheckUserData import DataValid
 from Model.models import Device_Info, Order_Model, Store_Meal, VodHlsModel, OssCrdModel, UID_Bucket, StsCrdModel, \
     ExperienceContextModel, Pay_Type, CDKcontextModel, Device_User, SysMassModel, SysMsgModel, UidPushModel, \
-    Unused_Uid_Meal, UIDMainUser, UserModel
+    Unused_Uid_Meal, UIDMainUser, UserModel, PromotionRuleModel
 from Object.AWS.S3Email import S3Email
 from Object.AliPayObject import AliPayObject
 from Object.AliSmsObject import AliSmsObject
@@ -52,7 +52,7 @@ from Service.CommonService import CommonService
 from Object.m3u8generate import PlaylistGenerator
 from Object.WechatPayObject import WechatPayObject
 from django.db.models import Q, F, Count
-
+from Ansjer.config import SERVER_TYPE
 from Service.ModelService import ModelService
 
 # SERVER_DOMAIN = 'http://test.dvema.com/'
@@ -232,13 +232,19 @@ class CloudStorageView(View):
 
                 res_c = {'area': area, 'items': items_list}
                 res.append(res_c)
+            #是否促销
+            nowTime = int(time.time())
+            promotion = PromotionRuleModel.objects.filter(status=1, startTime__lte=nowTime,
+                                                          endTime__gte=nowTime).values('id','ruleConfig')
+            is_promotion = 1 if promotion.exists() else 0
             result = {
                 'meals': res,
                 'extra':
                     {
                         'cloud_banner': SERVER_DOMAIN+'web/images/cloud_cn_banner.png',
                         'cloud_en_baner': SERVER_DOMAIN_SSL+'web/images/cloud_en_banner.png'
-                    }
+                    },
+                'is_promotion':is_promotion
             }
             return response.json(0, result)
         else:
@@ -723,12 +729,17 @@ class CloudStorageView(View):
             data.pop('sign')
             orderID = data['out_trade_no']
 
-            order_qs = Order_Model.objects.filter(orderID=orderID, status=0)
+            # redis加锁,防止订单重复
+            redisObj = RedisObject()
+            isLock = redisObj.CONN.setnx(orderID + 'do_notify', 1)
+            redisObj.CONN.expire(orderID + 'do_notify', 60)
+            if not isLock:
+                return response.json(5)
 
+            order_qs = Order_Model.objects.filter(orderID=orderID, status=0)
             aliPayObj = AliPayObject()
             alipay = aliPayObj.conf()
             success = alipay.verify(data, signature)
-
             if success and data["trade_status"] in ("TRADE_SUCCESS", "TRADE_FINISHED"):
                 print("trade succeed")
 
@@ -751,6 +762,14 @@ class CloudStorageView(View):
                 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')
+                promotion_rule_id = ''
+                if promotion.exists():
+                    promotion_rule_id = promotion[0]['id']
+                    expire = expire * 2
                 with transaction.atomic():
                     if ubqs.exists():
                         ubq = ubqs[0]
@@ -762,6 +781,8 @@ class CloudStorageView(View):
                         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:
@@ -792,18 +813,20 @@ class CloudStorageView(View):
                     #     }
                     #     UIDMainUser.objects.create(**uid_main_dict)
 
-                    order_qs.update(status=1, updTime=nowTime, uid_bucket_id=uid_bucket_id)
+                    order_qs.update(status=1, updTime=nowTime, uid_bucket_id=uid_bucket_id, promotion_rule_id=promotion_rule_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())]
                     self.do_vod_msg_Notice(UID, channel, userid, lang, sys_msg_text_list, 'SMS_219738485')
                     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)
+                    redisObj.del_data(key=orderID + 'do_notify')
                     return HttpResponseRedirect(red_url)
             return response.json(0, signature)
         except Exception as e:
             if order_qs:
-                order_qs.update(status=10)
+                order_qs.update(status=10, promotion_rule_id=promotion_rule_id)
+            redisObj.del_data(key=orderID + 'do_notify')
             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)
@@ -814,6 +837,12 @@ class CloudStorageView(View):
         PayerID = request_dict.get('PayerID', None)
         orderID = request_dict.get('orderID', None)
         lang = request_dict.get('lang', 'en')
+        # redis加锁,防止订单重复
+        redisObj = RedisObject()
+        isLock = redisObj.CONN.setnx(orderID + 'do_notify', 1)
+        redisObj.CONN.expire(orderID + 'do_notify', 60)
+        if not isLock:
+            return response.json(5)
         try:
             order_qs = Order_Model.objects.filter(orderID=orderID, status=0)
 
@@ -834,6 +863,7 @@ class CloudStorageView(View):
                 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)
+                redisObj.del_data(key=orderID + 'do_notify')
                 return HttpResponseRedirect(red_url)
             print("Payment execute successfully")
 
@@ -858,6 +888,14 @@ class CloudStorageView(View):
 
             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')
+            promotion_rule_id = ''
+            if promotion.exists():
+                promotion_rule_id = promotion[0]['id']
+                expire = expire * 2
             with transaction.atomic():
                 if ubqs.exists():
                     ubq = ubqs[0]
@@ -869,6 +907,8 @@ class CloudStorageView(View):
                     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:
@@ -899,7 +939,7 @@ class CloudStorageView(View):
                 #     }
                 #     UIDMainUser.objects.create(**uid_main_dict)
 
-                order_qs.update(status=1, updTime=nowTime, uid_bucket_id=uid_bucket_id)
+                order_qs.update(status=1, updTime=nowTime, uid_bucket_id=uid_bucket_id, promotion_rule_id=promotion_rule_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(
@@ -911,20 +951,21 @@ class CloudStorageView(View):
                 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)
-
+                redisObj.del_data(key=orderID + 'do_notify')
                 return HttpResponseRedirect(red_url)
         except Exception as e:
             print(repr(e))
             if order_qs:
-                order_qs.update(status=10)
+                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)
+            redisObj.del_data(key=orderID + 'do_notify')
             return HttpResponseRedirect(red_url)
 
     def do_pay_by_wechat_callback(self, request, response):  # 微信支付回调
 
-        logger = logging.getLogger('log')
+        logger = logging.getLogger('info')
         try:
             pay = WechatPayObject()
             data = pay.weixinpay_call_back(request.body)
@@ -935,17 +976,25 @@ class CloudStorageView(View):
             out_trade_no = data['out_trade_no']  # 商户订单号
             order_qs = Order_Model.objects.filter(orderID=out_trade_no, status=0)
             if trade_status == "SUCCESS":
-                logger.info('微信回调返回值 进来了。')
                 check_sign = pay.get_notifypay(data)
                 if not check_sign:
                     return HttpResponse(pay.xml_to_dict({'return_code': 'FAIL', 'return_msg': '签名失败'}))
-                logger.info('签名成功')
                 orderID = out_trade_no
-                print("进来了,微信支付成功回调")
+
+                #redis加锁,防止订单重复
+                redisObj = RedisObject()
+                isLock = redisObj.CONN.setnx(orderID + 'do_notify', 1)
+                redisObj.CONN.expire(orderID + 'do_notify', 60)
+                if not isLock:
+                    return response.json(5)
 
                 nowTime = int(time.time())
                 order_list = order_qs.values("UID", "channel", "commodity_code", "rank", "isSelectDiscounts",
-                                             "userID__userID", "userID__username")
+                                             "userID__userID", "userID__username","status")
+
+                logger.info(order_list[0]['UID'])
+                logger.info(orderID)
+
                 userid = order_list[0]['userID__userID']
                 username = order_list[0]['userID__username']
                 UID = order_list[0]['UID']
@@ -962,6 +1011,13 @@ class CloudStorageView(View):
                 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')
+                promotion_rule_id = ''
+                if promotion.exists():
+                    promotion_rule_id = promotion[0]['id']
+                    expire = expire * 2
                 with transaction.atomic():
                     if ubqs.exists():
                         ubq = ubqs[0]
@@ -973,6 +1029,8 @@ class CloudStorageView(View):
                         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:
@@ -1003,20 +1061,24 @@ class CloudStorageView(View):
                     #     }
                     #     UIDMainUser.objects.create(**uid_main_dict)
 
-                    order_qs.update(status=1, updTime=nowTime, uid_bucket_id=uid_bucket_id)
+                    order_qs.update(status=1, updTime=nowTime, uid_bucket_id=uid_bucket_id, promotion_rule_id=promotion_rule_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())]
-
                     self.do_vod_msg_Notice(UID, channel, userid, lang, sys_msg_text_list, 'SMS_219738485')
-                    return HttpResponse(pay.xml_to_dict({'return_code': 'SUCCESS', 'return_msg': 'OK'}))
+                    redisObj.del_data(key=orderID + 'do_notify')
+                    return HttpResponse("<xml>\
+                      <return_code><![CDATA[SUCCESS]]></return_code>\
+                      <return_msg><![CDATA[OK]]></return_msg>\
+                    </xml>")
             else:
-                order_qs.update(status=10)
+                order_qs.update(status=10, promotion_rule_id=promotion_rule_id)
             return HttpResponse(pay.xml_to_dict({'return_code': 'FAIL', 'return_msg': '参数格式校验错误'}))
         except Exception as e:
             if order_qs:
-                order_qs.update(status=10)
+                order_qs.update(status=10, promotion_rule_id=promotion_rule_id)
+            redisObj.del_data(key=orderID + 'do_notify')
             return HttpResponse(pay.xml_to_dict({'return_code': 'FAIL', 'return_msg': repr(e)}))
 
     def do_create_pay_order(self, request_dict, userID, ip, response):  # 创建支付订单

+ 206 - 0
Controller/EquipmentManagerV3.py

@@ -50,6 +50,8 @@ class EquipmentManagerV3(View):
         # 手机端添加设备,查询,修改
         if operation == 'add':
             return self.do_add(userID, request_dict, response, request)
+        if operation == 'batchAdd':
+            return self.do_batch_add(userID, request_dict, response, request)
         elif operation == 'query':
             return self.do_query(userID, request_dict, response)
         elif operation == 'modify':
@@ -257,6 +259,210 @@ class EquipmentManagerV3(View):
                 }
             return response.json(0, res)
 
+    def do_batch_add(self, userID, request_dict, response, request):
+        # 批量添加设备
+        uidContent = request_dict.get('uidContent', None)
+
+        if not uidContent:
+            return response.json(444, {'param': 'uidContent'})
+
+        try:
+            add_success_flag = False    # 添加成功标识
+            exception_flag = False      # 异常标识
+            exists_flag = False         # 已存在标识
+            uid_content_list = eval(uidContent)
+            print('uidContent: ', uid_content_list)
+            re_uid = re.compile(r'^[A-Za-z0-9]{14,20}$')
+            for uid_content in uid_content_list:
+                exception_flag = False  # 重置异常标识
+                exists_flag = False     # 已存在标识
+                UID = uid_content['uid']
+                NickName = uid_content['nickName']
+                Type = uid_content['type']
+                ChannelIndex = uid_content['channelIndex']
+                version = uid_content['version']
+                isCheckMainUser = uid_content['isCheckMainUser']
+                View_Account = uid_content['viewAccount']
+                encryptPassword = uid_content['encryptPassword']
+                View_Password = self.decode_pwd(encryptPassword)
+                if not all([UID, NickName, View_Account, Type, ChannelIndex]):  # Type和ChannelIndex可能为0
+                    return response.json(444, {'param': 'UID, NickName, View_Account, Type, ChannelIndex'})
+
+                if not re_uid.match(UID):   # 检查uid长度
+                    return response.json(444, {'error uid length': UID})
+
+                device_info_qs = Device_Info.objects.filter(UID=UID, userID_id=userID)
+                if device_info_qs:
+                    # 判断设备是否已存在
+                    if device_info_qs[0].isExist == 1:
+                        exists_res = {UID: 'device already exists!'}
+                        exists_flag = True
+                        continue
+                    else:
+                        device_info_qs.delete()
+
+                id = CommonService.getUserID(getUser=False)
+                userName = Device_User.objects.get(userID=userID).username
+                main_exist = Device_Info.objects.filter(UID=UID)
+                main_exist = main_exist.filter(~Q(vodPrimaryUserID='')).values('vodPrimaryUserID', 'vodPrimaryMaster')
+
+                vodPrimaryUserID = userID
+                vodPrimaryMaster = userName
+                primaryUserID = ''
+                primaryMaster = ''
+                isShare = False
+
+                is_bind = Device_Info.objects.filter(UID=UID, isShare=False).values('userID__userID', 'primaryUserID', 'primaryMaster')
+
+                if main_exist.exists():
+                    vodPrimaryUserID = main_exist[0]['vodPrimaryUserID']
+                    vodPrimaryMaster = main_exist[0]['vodPrimaryMaster']
+
+                if is_bind.exists():
+                    primaryUserID = is_bind[0]['primaryUserID']
+                    primaryMaster = is_bind[0]['primaryMaster']
+                    isShare = True
+
+                isusermain = False
+                if (vodPrimaryUserID != userID and vodPrimaryUserID != '') or (primaryUserID != userID and primaryUserID != ''):
+                    isusermain = True
+
+                # 判断是否有已绑定用户
+                if isCheckMainUser == 1 and isusermain:
+                    res = {
+                        'id': id,
+                        'userID': userID,
+                        'NickName': NickName,
+                        'UID': UID,
+                        'View_Account': View_Account,
+                        'View_Password': View_Password,
+                        'ChannelIndex': ChannelIndex,
+                        'Type': Type,
+                        'isShare': isShare,
+                        'primaryUserID': primaryUserID,
+                        'primaryMaster': primaryMaster,
+                        'vodPrimaryUserID': vodPrimaryUserID,
+                        'vodPrimaryMaster': vodPrimaryMaster,
+                        'data_joined': '',
+                        'version': version,
+                        'isVod': 0,
+                        'isExist': 1,
+                        'userID__userEmail': ''
+                    }
+                    res['vod'] = [
+                        {
+                            "status": 1,
+                            "channel": ChannelIndex,
+                            "endTime": '',
+                            "bucket__content": '',
+                            "uid": UID
+                        }
+                    ]
+                    res['isMainUserExists'] = 1
+                    continue
+
+                # 判断是否有用户绑定
+                nowTime = int(time.time())
+                us_qs = UidSetModel.objects.filter(uid=UID)
+                if us_qs.exists():
+                    us_qs.update(nickname=NickName)
+                    UidSet_id = us_qs.first().id
+                else:
+                    ip = CommonService.get_ip_address(request)
+                    region_id = Device_Region().get_device_region(ip)
+                    region_alexa = 'CN' if region_id == 1 else 'ALL'
+                    uid_set_create_dict = {
+                        'uid': UID,
+                        'addTime': nowTime,
+                        'updTime': nowTime,
+                        'ip': CommonService.get_ip_address(request_dict),
+                        'channel': ChannelIndex,
+                        'nickname': NickName,
+                        'version': version,
+                        'region_alexa': region_alexa,
+                    }
+                    UidSet = UidSetModel.objects.create(**uid_set_create_dict)
+                    UidSet_id = UidSet.id
+
+                # 查询uid_channel表有无该uid的数据
+                uid_channel_set = UidChannelSetModel.objects.filter(uid_id=UidSet_id)
+                if not uid_channel_set.exists():
+                    # 多通道设备设置通道名
+                    multi_channel_list = [1, 2, 3, 4, 10001]
+                    if Type in multi_channel_list:
+                        UidChannelSet_bulk = []
+                        for i in range(1, ChannelIndex+1):
+                            channel_name = 'channel'+str(i)  # channel1,channel2...
+                            UidChannelSet = UidChannelSetModel(uid_id=UidSet_id, channel=i, channel_name=channel_name)
+                            UidChannelSet_bulk.append(UidChannelSet)
+                        UidChannelSetModel.objects.bulk_create(UidChannelSet_bulk)
+
+                userDevice = Device_Info(id=id, userID_id=userID, UID=UID, NickName=NickName, View_Account=View_Account,
+                                         View_Password=View_Password, Type=Type, ChannelIndex=ChannelIndex, version=version,
+                                         vodPrimaryUserID=vodPrimaryUserID, vodPrimaryMaster=vodPrimaryMaster)
+                userDevice.save()
+                uid_serial_qs = UIDCompanySerialModel.objects.filter(uid__uid=UID)
+                if uid_serial_qs.exists():
+                    uid_serial = uid_serial_qs[0]
+                    Device_Info.objects.filter(UID=UID).update(vodPrimaryUserID=vodPrimaryUserID,
+                                                               vodPrimaryMaster=vodPrimaryMaster,
+                                                               serial_number=uid_serial.company_serial.serial_number + uid_serial.company_serial.company.mark)
+                else:
+                    Device_Info.objects.filter(UID=UID).update(vodPrimaryUserID=vodPrimaryUserID,
+                                                               vodPrimaryMaster=vodPrimaryMaster)
+
+                if not us_qs.exists():
+                    us_qs = UidSetModel.objects.filter(uid=UID)
+
+                if us_qs.exists() and us_qs[0].is_alexa == 1:
+                    if us_qs[0].channel > 1:
+                        data_list = []
+                        uid_channel_set_qs = UidChannelSetModel.objects.filter(uid_id=us_qs[0].id).\
+                            values('channel', 'channel_name')
+                        if uid_channel_set_qs.exists():
+                            # 多通道设备名为 UidChannelSetModel 的 channel_name
+                            for uid_channel_set in uid_channel_set_qs:
+                                data_list.append({'userID': userID, 'UID': UID, 'uid_nick': uid_channel_set['channel_name'],
+                                                  'channel': uid_channel_set['channel'], 'password': encryptPassword})
+                    else:
+                        data_list = [{'userID': userID, 'UID': UID, 'uid_nick': NickName, 'password': encryptPassword}]
+
+                    # 请求Alexa服务器更新事件网关
+                    data_list = json.dumps(data_list)
+                    data = {'data_list': data_list}
+                    url = 'https://www.zositech.xyz/deviceStatus/addOrUpdateV2'
+                    requests.post(url, data=data, timeout=2)
+                dvqs = Device_Info.objects.filter(id=id).values('id', 'userID', 'NickName', 'UID',
+                                                                'View_Account',
+                                                                'View_Password', 'ChannelIndex', 'Type',
+                                                                'isShare',
+                                                                'primaryUserID', 'primaryMaster',
+                                                                'vodPrimaryUserID', 'vodPrimaryMaster',
+                                                                'userID__userEmail',
+                                                                'data_joined', 'version',
+                                                                'isVod', 'isExist', 'isCameraOpenCloud', 'serial_number')
+                dvql = CommonService.qs_to_list(dvqs)
+                ubqs = UID_Bucket.objects.filter(uid=UID). \
+                    values('bucket__content', 'status', 'channel', 'endTime', 'uid')
+                success_res = dvql[0]
+                success_res['vod'] = list(ubqs)
+                iotqs = iotdeviceInfoModel.objects.filter(serial_number=dvql[0]['serial_number'])
+                if iotqs.exists():
+                    success_res['iot'] = {'endpoint': iotqs[0].endpoint, 'token_iot_number': iotqs[0].endpoint}
+                add_success_flag = True
+        except Exception as e:
+            print(e)
+            error_res = repr(e)
+            exception_flag = True
+            pass
+        finally:
+            if add_success_flag:    # 有一台添加成功则返回成功
+                return response.json(0, success_res)
+            if exists_flag:         # 全部设备已存在
+                return response.json(174, exists_res)
+            if exception_flag:
+                return response.json(500, error_res)
+            return response.json(0, res)
 
     def do_modify(self, userID, request_dict, response, request):
         token = request_dict.get('token', None)

+ 19 - 0
Model/models.py

@@ -622,6 +622,7 @@ class Order_Model(models.Model):
     commodity_code = models.CharField(default='', max_length=32, verbose_name='套餐规格码')
     pay_url = models.CharField(max_length=2000, default='', 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')
 
     # 备用字段
     spare_1 = models.CharField(default='', blank=True, max_length=64, verbose_name=u'备用字段1')
@@ -638,6 +639,24 @@ class Order_Model(models.Model):
         verbose_name_plural = verbose_name
         ordering = ('-orderID',)
 
+class PromotionRuleModel(models.Model):
+    id = models.AutoField(primary_key=True, verbose_name='主键')
+    ruleName = models.CharField(max_length=50, default='', verbose_name='规则名字')
+    ruleConfig = models.CharField(max_length=2000, default='', verbose_name='规则配置')
+    startTime = models.IntegerField(verbose_name='促销活动开始时间', default=0)
+    endTime = models.IntegerField(verbose_name='促销活动结束时间', default=0)
+    status = models.SmallIntegerField(default=0, verbose_name='活动状态:0未进行;1进行中')
+
+    def __str__(self):
+        return self.id
+
+    class Meta:
+        db_table = 'promotion_rule'
+        verbose_name = u'促销规则表'
+        verbose_name_plural = verbose_name
+        ordering = ('-id',)
+
+
 
 class VodHlsModel(models.Model):
     id = models.AutoField(primary_key=True, verbose_name='回放列表主键')