Bläddra i källkod

Merge branch 'test' of http://192.168.136.99:3000/servers/ASJServer

peng 3 år sedan
förälder
incheckning
9202cea2b4

+ 45 - 16
AdminController/DeviceManagementController.py

@@ -2,6 +2,7 @@
 # -*- coding: utf-8 -*-
 import json
 import time
+from bisect import bisect_left
 
 import oss2
 from django.db import transaction
@@ -12,7 +13,7 @@ from Ansjer.config import OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET, AWS_ACCESS_
     AWS_SES_ACCESS_REGION
 from Model.models import Device_Info, UidSetModel, LogModel, UID_Bucket, Unused_Uid_Meal, Order_Model, StsCrdModel, \
     VodHlsModel, ExperienceContextModel, DeviceTypeModel, Equipment_Info, UidUserModel, ExperienceAiModel, AiService, \
-    AppBundle, App_Info, AppDeviceType, DeviceNameLanguage
+    AppBundle, App_Info, AppDeviceType, DeviceNameLanguage, AppVersionNumber
 from Object.AWS.AmazonS3Util import AmazonS3Util
 from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
@@ -137,10 +138,10 @@ class DeviceManagement(View):
                         app_bundle_qs = AppBundle.objects.filter(id=app_id).values('id')
                         if not app_bundle_qs.exists():
                             AppBundle.objects.create(app_bundle_id=app_bundle_name, id=app_id)
-                #判断数据是否存在,是否上传
-                app_device_type_qs = AppDeviceType.objects.filter(type=type).values()
-                if app_device_type_qs.exists():
-                    return response.json(174)
+                # 判断数据是否存在,是否上传
+                # app_device_type_qs = AppDeviceType.objects.filter(type=type).values()
+                # if app_device_type_qs.exists():
+                #     return response.json(174)
                 # S3下文件夹路径+文件名 组成对象key
                 file_key = 'app/device_type_images/{}'.format(fileName)
                 s3 = AmazonS3Util(AWS_ACCESS_KEY_ID[1], AWS_SECRET_ACCESS_KEY[1], AWS_SES_ACCESS_REGION)
@@ -187,15 +188,15 @@ class DeviceManagement(View):
         try:
             if UID or serialNumber or NickName or username:  # 条件查询
                 if UID:
-                    device_info_qs = Device_Info.objects.filter(UID__contains=UID)
+                    device_info_qs = Device_Info.objects.filter(UID__icontains=UID)
                 if serialNumber:
-                    device_info_qs = Device_Info.objects.filter(serial_number__contains=serialNumber)
+                    device_info_qs = Device_Info.objects.filter(serial_number__icontains=serialNumber)
                 if NickName:
-                    device_info_qs = Device_Info.objects.filter(NickName__contains=NickName)
+                    device_info_qs = Device_Info.objects.filter(NickName__icontains=NickName)
                 if username:
-                    device_info_qs = Device_Info.objects.filter(Q(userID__username__contains=username) |
-                                                                Q(userID__userEmail__contains=username) |
-                                                                Q(userID__phone__contains=username))
+                    device_info_qs = Device_Info.objects.filter(Q(userID__username__icontains=username) |
+                                                                Q(userID__userEmail__icontains=username) |
+                                                                Q(userID__phone__icontains=username))
                 total = device_info_qs.count()
                 if not total:
                     return response.json(0, {'list': {}, 'total': 0})
@@ -450,16 +451,44 @@ class DeviceManagement(View):
     def get_device_icon(request_dict, response):
         lang = request_dict.get('lang', None)
         app_bundle_id = request_dict.get('appBundleId', None)
-
-        if not all([lang, app_bundle_id]):
+        version_number = request_dict.get('versionNumber', None)
+        if not all([lang, app_bundle_id, version_number]):
             return response.json(444)
+        version_number_qs = AppVersionNumber.objects.filter(app_bundle__app_bundle_id=app_bundle_id,
+                                                            version_number=version_number)
+        if not version_number_qs.exists():
+            version_number_qs = AppVersionNumber.objects.filter(app_bundle__app_bundle_id=app_bundle_id)
+            if not version_number_qs.exists():
+                return response.json(173)
+            version_qs = version_number_qs.values('version_number')
+            test_list = [item[key] for item in version_qs for key in item]
+            if (version_number > test_list[-1] or version_number < test_list[0]):
+                version_number_qs = version_number_qs.filter().values('id').order_by('id')
+                total_list = [item[key] for item in version_number_qs for key in item]
+                version_number_id = total_list[-1]
+            else:
+                pos = bisect_left(test_list, version_number)
+                if pos == 0:
+                    return test_list[0]
+                if pos == len(test_list):
+                    return test_list[-1]
+                before = test_list[pos - 1]
+                version_number_qs = AppVersionNumber.objects.filter(version_number=before).values('id')
+                version_number_id = version_number_qs[0]['id']
+        else:
+            version_number_qs = AppVersionNumber.objects.filter(version_number=version_number).values('id')
+            version_number_id = version_number_qs[0]['id']
         try:
             app_bundle_qs = AppBundle.objects.filter(app_bundle_id=app_bundle_id,
-                                                     app_device_type__devicenamelanguage__lang=lang).annotate(
+                                                     app_device_type__devicenamelanguage__lang=lang,
+                                                     app_device_type__app_version_number_id=version_number_id). \
+                annotate(
                 model=F('app_device_type__model'), type=F('app_device_type__type'), icon=F('app_device_type__icon'),
                 name=F('app_device_type__devicenamelanguage__name'),
-                sort=F('app_device_type__devicenamelanguage__sort')).order_by(
-                'app_device_type__devicenamelanguage__sort').values('model', 'type', 'icon', 'name', 'sort')
+                sort=F('app_device_type__devicenamelanguage__sort'),
+                app_version_number_id=F('app_device_type__app_version_number_id')).order_by(
+                'app_device_type__devicenamelanguage__sort').values('model', 'type', 'icon', 'name', 'sort',
+                                                                    'app_device_type__app_version_number_id')
             dvr_list = [app_bundle for app_bundle in app_bundle_qs if app_bundle['model'] == 1]
             ipc_list = [app_bundle for app_bundle in app_bundle_qs if app_bundle['model'] == 2]
             print(dvr_list, ipc_list)

+ 34 - 39
AdminController/ServeManagementController.py

@@ -843,31 +843,6 @@ class serveManagement(View):
             uid_bucket_qs = uid_bucket_qs.order_by('-addTime')[(page - 1) * line:page * line]
 
             for uid_bucket in uid_bucket_qs:
-                # 套餐到期时间累加未使用套餐
-                unused_qs = Unused_Uid_Meal.objects.filter(uid=uid_bucket.uid).values('num', 'expire')
-                if unused_qs.exists():
-                    addMonth = 0
-                    for unused in unused_qs:
-                        addMonth += unused['num'] * unused['expire']
-                    endTime = CommonService.calcMonthLater(addMonth, uid_bucket.endTime)
-                    endTime = time.strftime("%Y--%m--%d %H:%M:%S", time.localtime(endTime))
-                else:
-                    endTime = time.strftime("%Y--%m--%d %H:%M:%S", time.localtime(uid_bucket.endTime))
-
-                uid = uid_bucket.uid.upper()
-                data = {
-                    'id': uid_bucket.id,
-                    'uid': uid,
-                    'channel': uid_bucket.channel,
-                    'status': uid_bucket.status,
-                    'endTime': endTime,
-                    'addTime': time.strftime(
-                        "%Y--%m--%d %H:%M:%S",
-                        time.localtime(
-                            uid_bucket.addTime)),
-                    'use_status': uid_bucket.use_status,
-                    'has_unused': uid_bucket.has_unused}
-
                 for order in order_qs.filter(
                         uid_bucket_id=uid_bucket.id).values(
                         'uid_bucket_id',
@@ -880,22 +855,42 @@ class serveManagement(View):
                         'userID__phone',
                         'userID__userEmail',
                         'userID__data_joined'):
-                    data['desc'] = order['desc']
-                    data['payType'] = order['payType']
-                    data['price'] = order['price']
-                    data['username'] = order['userID__username']
-                    data['phone'] = order['userID__phone']
-                    data['userEmail'] = order['userID__userEmail']
-                    data['data_joined'] = order['userID__data_joined'].strftime(
-                        "%Y-%m-%d %H:%M:%S")
-                    data['playcount'] = cg_qs.filter(
-                        operation='cloudstorage/queryvodlist', uid=order['UID']).count()
+                    # 套餐到期时间累加未使用套餐
+                    unused_qs = Unused_Uid_Meal.objects.filter(uid=uid_bucket.uid).values('num', 'expire')
+                    if unused_qs.exists():
+                        addMonth = 0
+                        for unused in unused_qs:
+                            addMonth += unused['num'] * unused['expire']
+                        endTime = CommonService.calcMonthLater(addMonth, uid_bucket.endTime)
+                        endTime = time.strftime("%Y--%m--%d %H:%M:%S", time.localtime(endTime))
+                    else:
+                        endTime = time.strftime("%Y--%m--%d %H:%M:%S", time.localtime(uid_bucket.endTime))
+
+                    uid = uid_bucket.uid.upper()
+                    data = {
+                        'id': uid_bucket.id,
+                        'uid': uid,
+                        'channel': uid_bucket.channel,
+                        'status': uid_bucket.status,
+                        'endTime': endTime,
+                        'addTime': time.strftime("%Y--%m--%d %H:%M:%S", time.localtime(uid_bucket.addTime)),
+                        'use_status': uid_bucket.use_status,
+                        'has_unused': uid_bucket.has_unused,
+                        'desc': order['desc'],
+                        'payType': order['payType'],
+                        'price': order['price'],
+                        'username': order['userID__username'],
+                        'phone': order['userID__phone'],
+                        'userEmail': order['userID__userEmail'],
+                        'data_joined': order['userID__data_joined'].strftime("%Y-%m-%d %H:%M:%S"),
+                        'playcount': cg_qs.filter(operation='cloudstorage/queryvodlist', uid=order['UID']).count()
+                    }
 
-                if uid in uid_set_dict:
-                    data['ucode'] = uid_set_dict[uid]['ucode']
-                    data['version'] = uid_set_dict[uid]['version']
+                    if uid in uid_set_dict:
+                        data['ucode'] = uid_set_dict[uid]['ucode']
+                        data['version'] = uid_set_dict[uid]['version']
 
-                list_data.append(data)
+                    list_data.append(data)
             return response.json(
                 0, {'list': list_data, 'total': count})
         except Exception as e:

+ 314 - 163
AdminController/dataSystemManagement/DeviceDataController.py

@@ -14,7 +14,7 @@ from django.db.models import Count
 from django.views.generic.base import View
 
 from Ansjer.config import DEVICE_TYPE
-from Model.models import Device_Info, CountryModel, Order_Model
+from Model.models import Device_Info, CountryModel, Order_Model, VodHlsModel
 from Service.CommonService import CommonService
 
 
@@ -47,13 +47,17 @@ class DeviceDataView(View):
             return self.global_regional(request, request_dict, response)
         if operation == 'global/type':  # 全球设备类型
             return self.golbal_type(request, request_dict, response)
+        if operation == 'global/active':  # 全球设备活跃分布
+            return self.golbal_active(request, request_dict, response)
+        if operation == 'global/addDevice':  # 全球新增设备数据
+            return self.golbal_add_device(request, request_dict, response)
         else:
             return response.json(414)
 
     @classmethod
-    def golbal_type(cls, request, request_dict, response):
+    def golbal_add_device(cls, request, request_dict, response):
         """
-        全球设备类型分布
+        全球新增设备数据
         @param request:请求
         @param request_dict:请求参数
         @param response: 响应对象
@@ -63,21 +67,170 @@ class DeviceDataView(View):
             headers = {
                 'Authorization': request.META.get('HTTP_AUTHORIZATION')
             }
+            device_list = []
+            device_count = 0
             type_list = []
             type_count = 0
+            region_list = []
+            region_count = 0
+            order_list = []
+            order_count = 0
             for url in url_list:
                 url = url + request.path.replace('global/', '')
                 res = requests.get(url=url, params=request_dict, headers=headers)
                 result = res.json()
                 if result['result_code'] == 0:
+                    for item in result['result']['addDevice']:
+                        flag = 0
+                        for each in device_list:
+                            if item['startTime'] == each['startTime'] and item['endTime'] == each['endTime']:
+                                each['count'] += item['count']
+                                device_count += item['count']
+                                flag = 1
+                                break
+                        if flag == 0:
+                            device_list.append(item)
+                            device_count += item['count']
+                    for item in device_list:
+                        item['rate'] = round(item['count'] / device_count * 100, 2)
                     for item in result['result']['region']:
+                        flag = 0
+                        for each in region_list:
+                            if item['countryName'] == each['countryName']:
+                                each['count'] += item['count']
+                                region_count += item['count']
+                                flag = 1
+                                break
+                        if flag == 0:
+                            region_list.append(item)
+                            region_count += item['count']
+                    for item in region_list:
+                        item['rate'] = round(item['count'] / region_count * 100, 2)
+                    for item in result['result']['type']:
                         flag = 0
                         for each in type_list:
+                            if item['type'] == each['type']:
+                                each['count'] += item['count']
+                                type_count += item['count']
+                                flag = 1
+                                break
+                        if flag == 0:
+                            type_list.append(item)
+                            type_count += item['count']
+                    for item in type_list:
+                        item['rate'] = round(item['count'] / type_count * 100, 2)
+                    for item in result['result']['version']:
+                        flag = 0
+                        for each in order_list:
+                            if item['type'] == each['type']:
+                                each['count'] += item['count']
+                                order_count += item['count']
+                                flag = 1
+                                break
+                        if flag == 0:
+                            order_list.append(item)
+                            order_count += item['count']
+                    for item in order_list:
+                        item['rate'] = round(item['count'] / order_count * 100, 2)
+                else:
+                    return response.json(result['result_code'])
+            res = {
+                'device': device_list,
+                'type': type_list,
+                'region': CommonService.list_sort(region_list),
+                'version': order_list
+            }
+            return response.json(0, res)
+        except Exception as e:
+            print(e)
+            return response.json(500, repr(e))
+
+    @classmethod
+    def golbal_active(cls, request, request_dict, response):
+        """
+        全球设备活跃分布
+        @param request:请求
+        @param request_dict:请求参数
+        @param response: 响应对象
+        """
+        url_list = CommonService.get_domain_name()
+        try:
+            headers = {
+                'Authorization': request.META.get('HTTP_AUTHORIZATION')
+            }
+            type_list = []
+            type_count = 0
+            region_list = []
+            region_count = 0
+            for url in url_list:
+                url = url + request.path.replace('global/', '')
+                res = requests.get(url=url, params=request_dict, headers=headers)
+                result = res.json()
+                if result['result_code'] == 0:
+                    for item in result['result']['vodHls']:
+                        flag = 0
+                        for each in type_list:
+                            if item['startTime'] == each['startTime'] and item['endTime'] == each['endTime']:
+                                each['count'] += item['count']
+                                type_count += item['count']
+                                flag = 1
+                                break
+                        if flag == 0:
+                            type_list.append(item)
+                            type_count += item['count']
+                    for item in type_list:
+                        item['rate'] = round(item['count'] / type_count * 100, 2)
+                    for item in result['result']['region']:
+                        flag = 0
+                        for each in region_list:
                             if item['countryName'] == each['countryName']:
+                                each['count'] += item['count']
+                                region_count += item['count']
+                                flag = 1
+                                break
+                        if flag == 0:
+                            region_list.append(item)
+                            region_count += item['count']
+                    for item in region_list:
+                        item['rate'] = round(item['count'] / region_count * 100, 2)
+                else:
+                    return response.json(result['result_code'])
+
+            res = {
+                'device': type_list,
+                'region': CommonService.list_sort(region_list)
+            }
+            return response.json(0, res)
+        except Exception as e:
+            print(e)
+            return response.json(500, repr(e))
+
+    @classmethod
+    def golbal_type(cls, request, request_dict, response):
+        """
+        全球设备类型分布
+        @param request:请求
+        @param request_dict:请求参数
+        @param response: 响应对象
+        """
+        url_list = CommonService.get_domain_name()
+        try:
+            headers = {
+                'Authorization': request.META.get('HTTP_AUTHORIZATION')
+            }
+            type_list = []
+            type_count = 0
+            for url in url_list:
+                url = url + request.path.replace('global/', '')
+                res = requests.get(url=url, params=request_dict, headers=headers)
+                result = res.json()
+                if result['result_code'] == 0:
+                    for item in result['result']['type']:
+                        flag = 0
+                        for each in type_list:
+                            if item['type'] == each['type']:
                                 each['count'] += item['count']
                                 type_count += item['count']
-                                each['countryType'] += item['countryType']
-                                type_count += item['countryType']
                                 flag = 1
                                 break
                         if flag == 0:
@@ -158,26 +311,60 @@ class DeviceDataView(View):
 
     @classmethod
     def device_active(cls, request_dict, response):
-        order_type = request_dict.get('orderType', None)
-        if not order_type:
-            return response.json(444)
-        order_type = int(order_type)
-        order_type_qs = Order_Model.objects.filter(order_type=order_type).values('UID').order_by('UID').distinct()
+        """
+        设备活跃数据
+        @param request_dict:请求参数
+        @request_dict starTime:开始时间
+        @request_dict endTime:结束时间
+        @param response:响应对象
+        """
+        start_time = request_dict.get('startTime', None)  # 时间戳
+        end_time = request_dict.get('endTime', None)
+        unit_time = request_dict.get('timeUnit', None)
+        if not all([start_time, end_time, unit_time]):
+            return response.json(444, {'error param': 'startTime or endTime or timeUnit'})
+        s_time = datetime.datetime.fromtimestamp(int(start_time))
+        e_time = datetime.datetime.fromtimestamp(int(end_time))
+        time_list = CommonService.cutting_time(s_time, e_time, unit_time)
         try:
-            order_type_list = []
-            for order in order_type_qs:
-                UID = order['UID']
-                device_info_qs = Device_Info.objects.filter(UID=UID).values('Type').order_by('Type').distinct()
-                if not device_info_qs.exists():
-                    continue
-                device_info_qs = device_info_qs[0]['Type']
-                order_type_list.append(device_info_qs)
-            type_list = []
-            for i in order_type_list:
-                if i not in type_list:
-                    type_list.append(i)
+            vod_hls_model_qs = VodHlsModel.objects.filter(time__range=(start_time, end_time))
+            if not vod_hls_model_qs.exists():
+                return response.json(173)
+            device_info = list(vod_hls_model_qs.values('uid').order_by('uid').distinct())
+            device_info_list = [item[key] for item in device_info for key in item]
+            count_all = len(device_info_list)
+            res = {}
+            vod_list = []
+            region_list = []
+            for item in time_list:
+                vod_hls_qs = vod_hls_model_qs.filter(time__range=(item[0], item[1]))
+                uid_qs = vod_hls_qs.values('uid').order_by('uid').distinct()
+                uid_list = [item[key] for item in uid_qs for key in item]
+                rate = round(uid_qs.count() / count_all * 100, 2)
+                vod_dict = {
+                    'count': uid_qs.count(),
+                    'rate': rate,
+                    'startTime': item[0],
+                    'endTime': item[1]
+                }
+                vod_list.append(vod_dict)
+                res['vodHls'] = vod_list
+                type_country_qs = Device_Info.objects.filter(UID__in=uid_list).values(
+                    'userID__region_country').annotate(count=Count('userID__region_country')).order_by('-count')
+                for item in type_country_qs:
+                    country_id = item['userID__region_country']
+                    country_name_qs = CountryModel.objects.filter(id=country_id).values('country_name')
+                    country_name = country_name_qs[0]['country_name'] if country_name_qs.exists() else '未知区域'
+                    rate = round(item['count'] / count_all * 100, 2)
+                    country_dict = {
+                        'countryName': country_name,
+                        'count': item['count'],
+                        'rate': rate
+                    }
+                    region_list.append(country_dict)
+                    res['region'] = region_list
 
-            return response.json(0, type_list)
+            return response.json(0, res)
         except Exception as e:
             print(e)
             return response.json(500)
@@ -193,7 +380,7 @@ class DeviceDataView(View):
         """
         start_time = request_dict.get('startTime', None)  # 时间戳
         end_time = request_dict.get('endTime', None)
-        unit_time = request_dict.get('unitTime', None)
+        unit_time = request_dict.get('timeUnit', None)
         order_type = request_dict.get('orderType', None)
         if not all([start_time, end_time, unit_time, order_type]):
             return response.json(444, {'error param': 'startTime or endTime or timeUnit or order_type'})
@@ -203,117 +390,114 @@ class DeviceDataView(View):
         time_list = CommonService.cutting_time(start_time, end_time, unit_time)
         try:
             device_info_qs = Device_Info.objects.filter(data_joined__range=(start_time, end_time))
-            device_count_qs = device_info_qs.count()
-            device_type_qs = device_info_qs.values('UID').order_by('UID').distinct()
+            device_test_qs = Device_Info.objects.filter(data_joined__lt=start_time)
+            device_test = list(device_test_qs.values('UID').order_by('UID').distinct())
+            device_info = list(device_info_qs.values('UID').order_by('UID').distinct())
+            test_list = [item[key] for item in device_test for key in item]
+            device_info_list = [item[key] for item in device_info for key in item]
+            part_only_list = list(set(device_info_list) - set(test_list))
+            count_all = len(part_only_list)
+            count_all = int(count_all)
+            # 统计该时间段的设备数量(已去重)
+            res = {
+                'addDevice': '',
+                'region': '',
+                'type': '',
+                'version': '',
+            }
             info_list = []
-            count_unique = device_type_qs.count()
-            # 统计该时间段的设备数量(去重)
+            region_list = []
+            type_list = []
+            version_list = []
             for item in time_list:
                 start_time = datetime.datetime.fromtimestamp(int(item[0]))
                 end_time = datetime.datetime.fromtimestamp(int(item[1]))
+                device_qs = device_info_qs.filter(data_joined__range=(start_time, end_time))
+                device_test_qs = Device_Info.objects.filter(data_joined__lt=start_time)
+                device_test = list(device_test_qs.values('UID').order_by('UID').distinct())
+                device_info = list(device_qs.values('UID').order_by('UID').distinct())
+                test_list = [item[key] for item in device_test for key in item]
+                device_info_list = [item[key] for item in device_info for key in item]
+                part_only_list = list(set(device_info_list) - set(test_list))
+                count_part = len(part_only_list)
+                rate = round(count_part / count_all * 100, 2)
                 info_dict = {
                     'startTime': item[0],
-                    'endTime': item[1]
+                    'endTime': item[1],
+                    'count': len(part_only_list),
+                    'rate': rate
                 }
-                count = 0
-                for device_type in device_type_qs:
-                    uid = device_type['UID']
-                    device_test_qs = Device_Info.objects.filter(data_joined__lt=start_time, UID=uid).values()
-                    if device_test_qs.exists():
-                        continue
-                    else:
-                        count += 1
-                        device_only_qs = device_info_qs.filter(UID=uid).values()
-                        device_only = device_only_qs[0]
-                        # res = {
-                        #     'country': '',
-                        #     'count': ''
-                        # }
-                        #
-                        # for country in device_only:
-
-
-                info_dict['count'] = count
                 info_list.append(info_dict)
-
-
-
-
-        #         info_list.append(info_dict)
-        #     # 统计地区设备数量
-        #     device_info_country_qs = device_info_qs.values('userID__region_country').annotate(
-        #         count=Count('userID__region_country')).order_by('-count')
-        #     region_list = []
-        #     for item in device_info_country_qs:
-        #         country_id = item['userID__region_country']
-        #         country_qs = CountryModel.objects.filter(id=country_id).values('country_name', 'id')
-        #         country_name = country_qs[0]['country_name'] if country_qs.exists() else '未知区域'
-        #         count = device_info_qs.filter(userID__region_country=item['userID__region_country']).values(
-        #             'UID').annotate(count=Count('UID', distinct=True)).order_by('-count').count()
-        #         rate = round(count / count_unique * 100, 2)
-        #         country_dict = {
-        #             'countryName': country_name,
-        #             'count': count,
-        #             'rate': rate
-        #         }
-        #         region_list.append(country_dict)
-        #     # 统计设备类型数量
-        #     device_info_type_qs = device_info_qs.values('Type').annotate(
-        #         count=Count('Type', distinct=True)).order_by('-count')
-        #     count = device_info_type_qs.count()
-        #     # count_list = []
-        #     # for device_info_country in device_info_type_qs:
-        #     #     type = device_info_country['Type']
-        #     #     count_list.append(type)
-        #     device_info_type_qs = device_info_type_qs.values('Type').distinct()
-        #     type_list = []
-        #     for device_type in device_info_type_qs:
-        #         type = device_type['Type']
-        #         name = DEVICE_TYPE.get(type, '未知类型')
-        #         name = name if name != 'UNKOWN' else '未知类型'
-        #         total = device_info_qs.filter(Type=device_type['Type']).values('UID').annotate(
-        #             count=Count('UID', distinct=True)).order_by('-count').count()
-        #         rate = round(total / count_unique * 100, 2)  # count_unique 有误,跟device_info_type_qs 总数合不上 (可以看151行)
-        #         type_dict = {
-        #             'type': name,
-        #             'count': total,
-        #             'rate': rate
-        #         }
-        #         type_list.append(type_dict)
-        #     # 统计设备版本数量
-        #     device_info_type_qs = device_info_qs.values('UID').annotate(
-        #         count=Count('UID', distinct=True)).order_by('-count')
-        #     count = device_info_type_qs.count()
-        #     uid_list = []
-        #     for device_clound in device_info_type_qs:
-        #         uid = device_clound['UID']
-        #         uid_list.append(uid)
-        #     order_model_qs = Order_Model.objects.filter(UID__in=uid_list).values('UID').annotate(
-        #         count=Count('UID', distinct=True)).values('order_type').order_by('order_type')
-        #     count = order_model_qs.count()
-        #     order_type_list = []
-        #     for order_model in order_model_qs:
-        #         orderType = order_model['order_type']
-        #         order_type_list.append(orderType)
-        #     version_list = []
-        #     res = {}
-        #     if order_type == 0:
-        #         res['name'] = '云存'
-        #     elif order_type == 1:
-        #         res['name'] = 'AI'
-        #     elif order_type == 2:
-        #         res['name'] = '联通4G'
-        #     res['total'] = order_type_list.count(order_type)
-        #     version_list.append(res)
-        #
-        #     res = {
-        #         'info': info_list,
-        #         'region': region_list,
-        #         'type': type_list,
-        #         'version': version_list
-        #     }
-            return response.json(0, info_list)
+                res['addDevice'] = info_list
+                # 统计地区设备数量
+                device_info_country_qs = device_info_qs.filter(UID__in=part_only_list).values(
+                    'userID__region_country').annotate(
+                    count=Count('userID__region_country')).order_by('-count')
+                for item in device_info_country_qs:
+                    country_id = item['userID__region_country']
+                    country_qs = CountryModel.objects.filter(id=country_id).values('country_name', 'id')
+                    country_name = country_qs[0]['country_name'] if country_qs.exists() else '未知区域'
+                    country_qs = device_info_qs.filter(UID__in=part_only_list).values('UID').order_by(
+                        'UID').distinct().values(
+                        'userID__region_country')
+                    total_list = [item[key] for item in country_qs for key in item]
+                    country_count = total_list.count(country_id)
+                    rate = round(country_count / count_part * 100, 2)
+                    country_dict = {
+                        'countryName': country_name,
+                        'count': country_count,
+                        'rate': rate
+                    }
+                    region_list.append(country_dict)
+                    res['region'] = CommonService.list_sort(region_list)
+                # 统计设备类型数量
+                device_info_type_qs = device_info_qs.filter(UID__in=part_only_list).values('Type').annotate(
+                    count=Count('Type', distinct=True)).order_by('-count').distinct()
+                count = device_info_type_qs.count()
+                for device_type in device_info_type_qs:
+                    type = device_type['Type']
+                    name = DEVICE_TYPE.get(type, '未知类型')
+                    name = name if name != 'UNKOWN' else '未知类型'
+                    type_qs = device_info_qs.filter(UID__in=part_only_list).values('UID').order_by(
+                        'UID').distinct().values(
+                        'Type')
+                    test_list = [item[key] for item in type_qs for key in item]
+                    type_count = test_list.count(type)
+                    rate = round(type_count / count_part * 100, 2)
+                    type_dict = {
+                        'type': name,
+                        'count': type_count,
+                        'rate': rate
+                    }
+                    type_list.append(type_dict)
+                    res['type'] = CommonService.list_sort(type_list)
+                # 统计设备版本数量
+                order_model_qs = Order_Model.objects.filter(UID__in=part_only_list).values('UID').annotate(
+                    count=Count('UID', distinct=True))
+                order_model_qs = order_model_qs.filter(order_type=order_type).values('order_type', 'UID').order_by(
+                    'UID')
+                order_type_list = []
+                for order_model in order_model_qs:
+                    orderType = order_model['UID']
+                    order_type_list.append(orderType)
+                res_part = {}
+                device_info_type_qs = device_info_qs.filter(UID__in=order_type_list).values('Type').annotate(
+                    count=Count('Type', distinct=True)).order_by('-count').distinct()
+                for device_type in device_info_type_qs:
+                    type = device_type['Type']
+                    name = DEVICE_TYPE.get(type, '未知类型')
+                    res_part['type'] = name if name != 'UNKOWN' else '未知类型'
+                    type_qs = device_info_qs.filter(UID__in=order_type_list).values('UID').order_by(
+                        'UID').distinct().values(
+                        'Type')
+                    test_list = [item[key] for item in type_qs for key in item]
+                    res_part['count'] = test_list.count(type)
+                    res_part['rate'] = round(res_part['count'] / count_part * 100, 2)
+                    version_list.append(res_part)
+                    res['version'] = version_list
+            return response.json(0, res)
         except Exception as e:
+            print(e)
             return response.json(500, repr(e))
 
     @classmethod
@@ -325,7 +509,7 @@ class DeviceDataView(View):
         device_country_qs = Device_Info.objects.all().values('userID__region_country').annotate(
             count=Count('userID__region_country')).order_by('-count')
         device_info_qs = Device_Info.objects.values('UID').order_by('UID').distinct()
-        count = device_info_qs.count()
+        count_all = device_info_qs.count()
         if not device_country_qs.exists():
             return response.json(444)
         res = {}
@@ -360,9 +544,9 @@ class DeviceDataView(View):
                             'count': count
                         })
             for item in continent_list:
-                item['rate'] = round(item['count'] / count * 100, 2)
-            res['countries'] = device_country_list
-            res['continent'] = continent_list
+                item['rate'] = round(item['count'] / count_all * 100, 2)
+            res['countries'] = CommonService.list_sort(device_country_list)
+            res['continent'] = CommonService.list_sort(continent_list)
             return response.json(0, res)
         except Exception as e:
             print(e)
@@ -391,40 +575,7 @@ class DeviceDataView(View):
                     'type': name,
                     'count': count
                 })
-
-            device_country_qs = Device_Info.objects.all().values('userID__region_country').annotate(
-                count=Count('userID__region_country')).order_by('-count')
-            device_country_list = []
-            for device_country in device_country_qs:
-                country_id = device_country['userID__region_country']
-                country_qs = CountryModel.objects.filter(id=country_id).values('country_name', 'region__name')
-                if not country_qs.exists():
-                    country_name = '未知地区'
-                else:
-                    country_name = country_qs[0]['country_name']
-                device_type_qs = Device_Info.objects.filter(userID__region_country=country_id).values('Type').annotate(count=Count('Type', distinct=True)).order_by('-count')
-                country_type_list = []
-                for device_type in device_type_qs:
-                    type = device_type['Type']
-                    name = DEVICE_TYPE.get(type, '未知类型')
-                    name = name if name != 'UNKOWN' else '未知类型'
-                    count = device_type_qs.filter(Type=device_type['Type']).values('UID').annotate(
-                        count=Count('UID', distinct=True)).order_by('-count').count()
-                    country_type_list.append({
-                        'type': name,
-                        'count': count
-                    })
-                count = Device_Info.objects.filter(
-                    userID__region_country=device_country['userID__region_country']).values('UID').annotate(
-                    count=Count('UID', distinct=True)).order_by('-count').count()
-
-                device_country_list.append({
-                    'countryName': country_name,
-                    'count': count,
-                    'countryType': country_type_list
-                })
             res['type'] = device_info_list
-            res['region'] = device_country_list
             return response.json(0, res)
         except Exception as e:
             print(e)

+ 73 - 5
AdminController/dataSystemManagement/HomeDataController.py

@@ -10,12 +10,12 @@ import datetime
 import openpyxl
 import requests
 
-from django.db.models import Sum
+from django.db.models import Sum, Count
 from django.http import HttpResponse
 from django.utils.encoding import escape_uri_path
 from django.views.generic.base import View
 
-from Model.models import VideoPlaybackTimeModel, Device_User, Device_Info, Order_Model
+from Model.models import VideoPlaybackTimeModel, Device_User, Device_Info, Order_Model, CountryModel
 from Service.CommonService import CommonService
 
 
@@ -61,9 +61,21 @@ class HomeDataView(View):
         end_time_stamp = CommonService.str_to_timestamp(end_time.strftime('%Y-%m-%d %H:%M:%S'))
         start_time_stamp = CommonService.str_to_timestamp(start_time.strftime('%Y-%m-%d %H:%M:%S'))
         try:
-            user_increase_count = Device_User.objects.filter(data_joined__range=(start_time, end_time)).count()
+            user_increase_qs = Device_User.objects.filter(data_joined__range=(start_time, end_time))
+            user_increase_list = user_increase_qs.values('region_country').annotate(
+                count=Count('region_country')).order_by('-count')
+            for item in user_increase_list:
+                country_qs = CountryModel.objects.filter(id=item['region_country']).values('country_name')
+                item['countryName'] = country_qs[0]['country_name'] if country_qs.exists() else '未知区域'
+            user_increase_count = user_increase_qs.count()
             user_active_count = Device_User.objects.filter(last_login__range=(start_time, end_time)).count()
-            user_all_count = Device_User.objects.filter(data_joined__lte=end_time).count()
+            user_all_qs = Device_User.objects.filter(data_joined__lte=end_time)
+            user_all_list = user_all_qs.values('region_country').annotate(
+                count=Count('region_country')).order_by('-count')
+            for item in user_all_list:
+                country_qs = CountryModel.objects.filter(id=item['region_country']).values('country_name')
+                item['countryName'] = country_qs[0]['country_name'] if country_qs.exists() else '未知区域'
+            user_all_count = user_all_qs.count()
             device_increase_count = Device_Info.objects.filter(data_joined__range=(start_time, end_time)).values(
                 'UID').distinct().count()
             device_active_count = VideoPlaybackTimeModel.objects.filter(
@@ -94,6 +106,8 @@ class HomeDataView(View):
                 'vodOrderAllTotal': round(vod_order_all_total, 2) if vod_order_all_total else 0,
                 'aiOrderAllTotal': round(ai_order_all_total, 2) if ai_order_all_total else 0,
                 'unicomOrderAllTotal': round(unicom_order_all_total, 2) if unicom_order_all_total else 0,
+                'userIncreaseRegion': list(user_increase_list),
+                'userAllRegion': list(user_all_list)
             }
             return response.json(0, res)
         except Exception as e:
@@ -161,6 +175,12 @@ class HomeDataView(View):
             vod_order_all_total = 0
             ai_order_all_total = 0
             unicom_order_all_total = 0
+            user_increase_temp_list = []
+            user_increase_list = []
+            user_increase_other_dict = {'count': 0, 'countryName': '其他', 'rate': 0}
+            user_all_temp_list = []
+            user_all_list = []
+            user_all_other_dict = {'count': 0, 'countryName': '其他', 'rate': 0}
             for url in url_list:
                 url = url + request.path.replace('global/', '')
                 res = requests.get(url=url, params=request_dict, headers=headers)
@@ -179,6 +199,53 @@ class HomeDataView(View):
                 vod_order_all_total += result['result']['vodOrderAllTotal']
                 ai_order_all_total += result['result']['aiOrderAllTotal']
                 unicom_order_all_total += result['result']['unicomOrderAllTotal']
+                for item in result['result']['userIncreaseRegion']:
+                    flag = 0
+                    for each in user_increase_temp_list:
+                        if item['countryName'] == each['countryName']:
+                            each['count'] += item['count']
+                            flag = 1
+                            break
+                    if flag == 0:
+                        user_increase_temp_list.append(item)
+
+                for item in result['result']['userAllRegion']:
+                    flag = 0
+                    for each in user_all_temp_list:
+                        if item['countryName'] == each['countryName']:
+                            each['count'] += item['count']
+                            flag = 1
+                            break
+                    if flag == 0:
+                        user_all_temp_list.append(item)
+            if user_increase_temp_list:
+                for item in user_increase_temp_list:
+                    if user_increase_count:
+                        rate = round(item['count'] / user_increase_count * 100, 2)
+                    else:
+                        rate = 0
+                    if rate >= 10:
+                        item['rate'] = rate
+                        user_increase_list.append(item)
+                    else:
+                        user_increase_other_dict['count'] += item['count']
+                if user_increase_count:
+                    user_increase_other_dict['rate'] = round(user_increase_other_dict['count'] / user_increase_count * 100, 2)
+                user_increase_list.append(user_increase_other_dict)
+            if user_all_temp_list:
+                for item in user_all_temp_list:
+                    if user_all_count:
+                        rate = round(item['count'] / user_all_count * 100, 2)
+                    else:
+                        rate = 0
+                    if rate >= 10:
+                        item['rate'] = rate
+                        user_all_list.append(item)
+                    else:
+                        user_all_other_dict['count'] += item['count']
+                if user_all_count:
+                    user_all_other_dict['rate'] = round(user_all_other_dict['count'] / user_all_count * 100, 2)
+                user_all_list.append(user_all_other_dict)
             res = {
                 'userIncreaseCount': user_increase_count,
                 'userActiveCount': user_active_count,
@@ -194,6 +261,8 @@ class HomeDataView(View):
                 'vodOrderAllTotal': vod_order_all_total,
                 'aiOrderAllTotal': ai_order_all_total,
                 'unicomOrderAllTotal': unicom_order_all_total,
+                'userIncreaseRegion': user_increase_list,
+                'userAllRegion': user_all_list
             }
             return response.json(0, res)
         except Exception as e:
@@ -230,7 +299,6 @@ class HomeDataView(View):
         except Exception as e:
             return response.json(500, repr(e))
 
-
     @classmethod
     def export_data(cls, request_dict, response):
         """

+ 100 - 25
AdminController/dataSystemManagement/ServiceDataController.py

@@ -100,7 +100,10 @@ class ServiceDataView(View):
                 country_id = item['userID__region_country']
                 country_qs = CountryModel.objects.filter(id=country_id).values('country_name')
                 country_name = country_qs[0]['country_name'] if country_qs.exists() else '未知区域'
-                rate = round(item['count'] / count * 100, 2)
+                if count:
+                    rate = round(item['count'] / count * 100, 2)
+                else:
+                    rate = 0
                 region_dict = {
                     'countryName': country_name,
                     'count': item['count'],
@@ -126,9 +129,15 @@ class ServiceDataView(View):
                 type_name = DEVICE_TYPE.get(k, '未知类型')
                 type_name = type_name if type_name != 'UNKOWN' else '未知类型'
                 device_count = order_qs.filter(UID__in=v).count()
-                type_rate = round(device_count / count * 100, 2)
+                if count:
+                    type_rate = round(device_count / count * 100, 2)
+                else:
+                    type_rate = 0
                 temp_total = order_qs.filter(UID__in=v).aggregate(total=Sum('price'))['total']
-                total_rate = round(temp_total / total * 100, 2)
+                if total:
+                    total_rate = round(temp_total / total * 100, 2)
+                else:
+                    total_rate = 0
                 device_temp_qs = {
                     'typeName': type_name,
                     'count': device_count,
@@ -167,7 +176,10 @@ class ServiceDataView(View):
                         'combo_name')
                     store_meal_name = store_meal_content_qs[0][
                         'combo_name'] if store_meal_content_qs.exists() else '未知套餐'
-                rate = round(item['count'] / count * 100, 2)
+                if count:
+                    rate = round(item['count'] / count * 100, 2)
+                else:
+                    rate = 0
                 store_meal_dict = {
                     'storeMealId': store_meal_id,
                     'count': item['count'],
@@ -221,7 +233,10 @@ class ServiceDataView(View):
             else:
                 uidset_count = uidset_qs.filter(mobile_4g=1).count()
             order_device_count = order_qs.values('UID').distinct().order_by('UID').count()
-            inversion_rate = round(order_device_count / uidset_count * 100, 2)
+            if uidset_count:
+                inversion_rate = round(order_device_count / uidset_count * 100, 2)
+            else:
+                inversion_rate = 0
             # 订单数量统计
             order_list = []
             for item in time_list:
@@ -240,7 +255,10 @@ class ServiceDataView(View):
                 country_id = item['userID__region_country']
                 country_qs = CountryModel.objects.filter(id=country_id).values('country_name')
                 country_name = country_qs[0]['country_name'] if country_qs.exists() else '未知区域'
-                rate = round(item['count'] / count * 100, 2)
+                if count:
+                    rate = round(item['count'] / count * 100, 2)
+                else:
+                    rate = 0
                 region_dict = {
                     'countryName': country_name,
                     'count': item['count'],
@@ -263,7 +281,10 @@ class ServiceDataView(View):
                 type_name = DEVICE_TYPE.get(k, '未知类型')
                 type_name = type_name if type_name != 'UNKOWN' else '未知类型'
                 device_count = order_qs.filter(UID__in=v).count()
-                type_rate = round(device_count / count * 100, 2)
+                if count:
+                    type_rate = round(device_count / count * 100, 2)
+                else:
+                    type_rate = 0
                 device_temp_qs = {
                     'typeName': type_name,
                     'count': device_count,
@@ -335,7 +356,10 @@ class ServiceDataView(View):
                 country_id = item['userID__region_country']
                 country_qs = CountryModel.objects.filter(id=country_id).values('country_name')
                 country_name = country_qs[0]['country_name'] if country_qs.exists() else '未知区域'
-                rate = round(item['count'] / count * 100, 2)
+                if count:
+                    rate = round(item['count'] / count * 100, 2)
+                else:
+                    rate = 0
                 region_dict = {
                     'countryName': country_name,
                     'count': item['count'],
@@ -357,7 +381,10 @@ class ServiceDataView(View):
                 type_name = DEVICE_TYPE.get(k, '未知类型')
                 type_name = type_name if type_name != 'UNKOWN' else '未知类型'
                 device_count = order_qs.filter(UID__in=v).count()
-                type_rate = round(device_count / count * 100, 2)
+                if count:
+                    type_rate = round(device_count / count * 100, 2)
+                else:
+                    type_rate = 0
                 device_temp_qs = {
                     'typeName': type_name,
                     'count': device_count,
@@ -402,11 +429,14 @@ class ServiceDataView(View):
             order_qs = Order_Model.objects.filter(order_type=store_meal_type, status=1,
                                                   addTime__range=(start_time, end_time)).filter(
                 ~Q(price='0.00'), ~Q(price='0'), Q(UID__in=uid_list))
-            total = order_qs.count()
+            total = order_gte_start_time_qs.count()
 
             # 订单复购率
             count = order_qs.count()
-            repeat_rate = round(count / total * 100, 2)
+            if total:
+                repeat_rate = round(count / total * 100, 2)
+            else:
+                repeat_rate = 0
 
             start_time = datetime.datetime.fromtimestamp(int(start_time))
             end_time = datetime.datetime.fromtimestamp(int(end_time))
@@ -429,7 +459,10 @@ class ServiceDataView(View):
                 country_id = item['userID__region_country']
                 country_qs = CountryModel.objects.filter(id=country_id).values('country_name')
                 country_name = country_qs[0]['country_name'] if country_qs.exists() else '未知区域'
-                rate = round(item['count'] / count * 100, 2)
+                if count:
+                    rate = round(item['count'] / count * 100, 2)
+                else:
+                    rate = 0
                 region_dict = {
                     'countryName': country_name,
                     'count': item['count'],
@@ -451,7 +484,13 @@ class ServiceDataView(View):
                 type_name = DEVICE_TYPE.get(k, '未知类型')
                 type_name = type_name if type_name != 'UNKOWN' else '未知类型'
                 device_count = order_qs.filter(UID__in=v).count()
-                type_rate = round(device_count / count * 100, 2)
+                if count:
+                    if count:
+                        type_rate = round(device_count / count * 100, 2)
+                    else:
+                        type_rate = 0
+                else:
+                    type_rate = 0
                 device_temp_qs = {
                     'typeName': type_name,
                     'count': device_count,
@@ -521,7 +560,10 @@ class ServiceDataView(View):
                             region_list.append(item)
                             region_count += int(item['count'])
                     for item in region_list:
-                        rate = round(item['count'] / region_count * 100, 2)
+                        if region_count:
+                            rate = round(item['count'] / region_count * 100, 2)
+                        else:
+                            rate = 0
                         item['rate'] = rate
                     # 处理设备类型
                     for item in result['result']['deviceType']:
@@ -539,8 +581,14 @@ class ServiceDataView(View):
                             device_type_count += int(item['count'])
                             device_type_total += item['totalMoney']
                     for item in device_type_list:
-                        type_rate = round(item['count'] / device_type_count * 100, 2)
-                        total_rate = round(item['totalMoney'] / device_type_total * 100, 2)
+                        if device_type_count:
+                            type_rate = round(item['count'] / device_type_count * 100, 2)
+                        else:
+                            type_rate = 0
+                        if device_type_total:
+                            total_rate = round(item['totalMoney'] / device_type_total * 100, 2)
+                        else:
+                            total_rate = 0
                         item['typeRate'] = type_rate
                         item['totalRate'] = total_rate
                     # 处理套餐
@@ -556,7 +604,10 @@ class ServiceDataView(View):
                             store_meal_list.append(item)
                             store_meal_count += int(item['count'])
                     for item in store_meal_list:
-                        rate = round(item['count'] / store_meal_count * 100, 2)
+                        if store_meal_count:
+                            rate = round(item['count'] / store_meal_count * 100, 2)
+                        else:
+                            rate = 0
                         item['rate'] = rate
                 else:
                     return response.json(result['result_code'])
@@ -619,7 +670,10 @@ class ServiceDataView(View):
                             region_list.append(item)
                             region_count += int(item['count'])
                     for item in region_list:
-                        rate = round(item['count'] / region_count * 100, 2)
+                        if region_count:
+                            rate = round(item['count'] / region_count * 100, 2)
+                        else:
+                            rate = 0
                         item['rate'] = rate
                     # 处理设备类型
                     for item in result['result']['deviceType']:
@@ -634,14 +688,20 @@ class ServiceDataView(View):
                             device_type_list.append(item)
                             device_type_count += int(item['count'])
                     for item in device_type_list:
-                        type_rate = round(item['count'] / device_type_count * 100, 2)
+                        if device_type_count:
+                            type_rate = round(item['count'] / device_type_count * 100, 2)
+                        else:
+                            type_rate = 0
                         item['typeRate'] = type_rate
                     # 处理转化率
                     new_device_count += int(result['result']['newDeviceCount'])
                     order_device_count += int(result['result']['orderDeviceCount'])
                 else:
                     return response.json(result['result_code'])
-            inversion_rate = round(order_device_count / new_device_count * 100, 2)
+            if new_device_count:
+                inversion_rate = round(order_device_count / new_device_count * 100, 2)
+            else:
+                inversion_rate = 0
             res = {
                 'orders': order_list,
                 'regions': CommonService.list_sort(region_list),
@@ -701,7 +761,10 @@ class ServiceDataView(View):
                             region_list.append(item)
                             region_count += int(item['count'])
                     for item in region_list:
-                        rate = round(item['count'] / region_count * 100, 2)
+                        if region_count:
+                            rate = round(item['count'] / region_count * 100, 2)
+                        else:
+                            rate = 0
                         item['rate'] = rate
                     # 处理设备类型
                     for item in result['result']['deviceType']:
@@ -716,7 +779,10 @@ class ServiceDataView(View):
                             device_type_list.append(item)
                             device_type_count += int(item['count'])
                     for item in device_type_list:
-                        type_rate = round(item['count'] / device_type_count * 100, 2)
+                        if device_type_count:
+                            type_rate = round(item['count'] / device_type_count * 100, 2)
+                        else:
+                            type_rate = 0
                         item['typeRate'] = type_rate
                 else:
                     return response.json(result['result_code'])
@@ -778,7 +844,10 @@ class ServiceDataView(View):
                             region_list.append(item)
                             region_count += int(item['count'])
                     for item in region_list:
-                        rate = round(item['count'] / region_count * 100, 2)
+                        if region_count:
+                            rate = round(item['count'] / region_count * 100, 2)
+                        else:
+                            rate = 0
                         item['rate'] = rate
                     # 处理设备类型
                     for item in result['result']['deviceType']:
@@ -793,14 +862,20 @@ class ServiceDataView(View):
                             device_type_list.append(item)
                             device_type_count += int(item['count'])
                     for item in device_type_list:
-                        type_rate = round(item['count'] / device_type_count * 100, 2)
+                        if device_type_count:
+                            type_rate = round(item['count'] / device_type_count * 100, 2)
+                        else:
+                            type_rate = 0
                         item['typeRate'] = type_rate
                     # 处理订单复购率
                     repeat_count += result['result']['repeatCount']
                     order_count += result['result']['orderCount']
                 else:
                     return response.json(result['result_code'])
-            repeat_rate = round(repeat_count / order_count * 100, 2)
+            if order_count:
+                repeat_rate = round(repeat_count / order_count * 100, 2)
+            else:
+                repeat_rate = 0
             res = {
                 'orders': order_list,
                 'regions': CommonService.list_sort(region_list),

+ 48 - 13
AdminController/dataSystemManagement/UserDataController.py

@@ -75,7 +75,10 @@ class UserDataView(View):
                 s_time = datetime.datetime.fromtimestamp(int(item[0]))
                 e_time = datetime.datetime.fromtimestamp(int(item[1]))
                 user_date_qs = user_qs.filter(last_login__range=(s_time, e_time))
-                rate = round(user_date_qs.count() / count * 100, 2)
+                if count:
+                    rate = round(user_date_qs.count() / count * 100, 2)
+                else:
+                    rate = 0
                 user_dict = {
                     'count': user_date_qs.count(),
                     'rate': rate,
@@ -90,7 +93,10 @@ class UserDataView(View):
                 country_id = item['region_country']
                 country_qs = CountryModel.objects.filter(id=country_id).values('country_name')
                 country_name = country_qs[0]['country_name'] if country_qs.exists() else '未知区域'
-                rate = round(item['count'] / count * 100, 2)
+                if count:
+                    rate = round(item['count'] / count * 100, 2)
+                else:
+                    rate = 0
                 country_dict = {
                     'countryName': country_name,
                     'count': item['count'],
@@ -132,7 +138,10 @@ class UserDataView(View):
                 s_time = datetime.datetime.fromtimestamp(int(item[0]))
                 e_time = datetime.datetime.fromtimestamp(int(item[1]))
                 user_date_qs = user_qs.filter(last_login__range=(s_time, e_time))
-                rate = round(user_date_qs.count() / count * 100, 2)
+                if count:
+                    rate = round(user_date_qs.count() / count * 100, 2)
+                else:
+                    rate = 0
                 user_dict = {
                     'count': user_date_qs.count(),
                     'rate': rate,
@@ -147,7 +156,10 @@ class UserDataView(View):
                 country_id = item['region_country']
                 country_qs = CountryModel.objects.filter(id=country_id).values('country_name')
                 country_name = country_qs[0]['country_name'] if country_qs.exists() else '未知区域'
-                rate = round(item['count'] / count * 100, 2)
+                if count:
+                    rate = round(item['count'] / count * 100, 2)
+                else:
+                    rate = 0
                 country_dict = {
                     'countryName': country_name,
                     'count': item['count'],
@@ -181,7 +193,10 @@ class UserDataView(View):
                 country_id = item['region_country']
                 country_qs = CountryModel.objects.filter(id=country_id).values('country_name', 'region__name')
                 item['countryName'] = country_qs[0]['country_name'] if country_qs.exists() else '未知区域'
-                item['rate'] = round(item['count'] / count * 100, 2)
+                if count:
+                    item['rate'] = round(item['count'] / count * 100, 2)
+                else:
+                    item['rate'] = 0
                 if country_qs.exists():
                     flag = 0
                     for each in continent_list:
@@ -195,7 +210,10 @@ class UserDataView(View):
                             'count': item['count']
                         })
             for item in continent_list:
-                item['rate'] = round(item['count'] / count * 100, 2)
+                if count:
+                    item['rate'] = round(item['count'] / count * 100, 2)
+                else:
+                    item['rate'] = 0
             res['countries'] = list(user_qs)
             res['continent'] = continent_list
             return response.json(0, res)
@@ -237,7 +255,10 @@ class UserDataView(View):
                             user_list.append(item)
                             user_count += item['count']
                     for item in user_list:
-                        item['rate'] = round(item['count'] / user_count * 100, 2)
+                        if user_count:
+                            item['rate'] = round(item['count'] / user_count * 100, 2)
+                        else:
+                            item['rate'] = 0
                     for item in result['result']['region']:
                         flag = 0
                         for each in region_list:
@@ -250,7 +271,10 @@ class UserDataView(View):
                             region_list.append(item)
                             region_count += item['count']
                     for item in region_list:
-                        item['rate'] = round(item['count'] / region_count * 100, 2)
+                        if region_count:
+                            item['rate'] = round(item['count'] / region_count * 100, 2)
+                        else:
+                            item['rate'] = 0
                 else:
                     return response.json(result['result_code'])
             res = {
@@ -296,7 +320,10 @@ class UserDataView(View):
                             user_list.append(item)
                             user_count += item['count']
                     for item in user_list:
-                        item['rate'] = round(item['count'] / user_count * 100, 2)
+                        if user_count:
+                            item['rate'] = round(item['count'] / user_count * 100, 2)
+                        else:
+                            item['rate'] = 0
                     for item in result['result']['region']:
                         flag = 0
                         for each in region_list:
@@ -309,7 +336,10 @@ class UserDataView(View):
                             region_list.append(item)
                             region_count += item['count']
                     for item in region_list:
-                        item['rate'] = round(item['count'] / region_count * 100, 2)
+                        if region_count:
+                            item['rate'] = round(item['count'] / region_count * 100, 2)
+                        else:
+                            item['rate'] = 0
                 else:
                     return response.json(result['result_code'])
             res = {
@@ -354,8 +384,10 @@ class UserDataView(View):
                             user_list.append(item)
                             user_count += int(item['count'])
                     for item in user_list:
-                        rate = round(item['count'] / user_count * 100, 2)
-                        item['rate'] = rate
+                        if user_count:
+                            item['rate'] = round(item['count'] / user_count * 100, 2)
+                        else:
+                            item['rate'] = 0
                     for item in result['result']['continent']:
                         flag = 0
                         for each in region_list:
@@ -366,7 +398,10 @@ class UserDataView(View):
                         if flag == 0:
                             region_list.append(item)
                     for item in region_list:
-                        item['rate'] = round(item['count'] / user_count * 100, 2)
+                        if user_count:
+                            item['rate'] = round(item['count'] / user_count * 100, 2)
+                        else:
+                            item['rate'] = 0
                 else:
                     return response.json(result['result_code'])
             res = {

+ 10 - 10
Ansjer/cn_config/formal_settings.py

@@ -74,17 +74,17 @@ TEMPLATES = [
 
 WSGI_APPLICATION = 'Ansjer.cn_config.formal_wsgi.application'
 
+# 业务数据库
+DATABASE_DATA = 'ansjer_server_cn'
+SERVER_HOST = 'server-cn.cvp7gfpnmziz.rds.cn-northwest-1.amazonaws.com.cn'
+DATABASES_USER = 'aws_rds'
+DATABASES_PASS = 'H84NQ8NARr9e39tn6aW5'
 
-# 服务器类型
-DATABASE_DATA = 'Ansjer81'
-SERVER_HOST = 'business-server.cvp7gfpnmziz.rds.cn-northwest-1.amazonaws.com.cn'
-DATABASES_USER = 'azrds'
-DATABASES_PASS = 'UKv78ezQhiGMmSef5U5s'
-
-DATABASE_DATA2 = 'Ansjer81'
-SERVER_HOST2 = 'ansjerpush.cvp7gfpnmziz.rds.cn-northwest-1.amazonaws.com.cn'
-DATABASES_USER2 = 'azrds'
-DATABASES_PASS2 = 'azrds.x.x'
+# 推送数据库
+DATABASE_DATA2 = 'ansjer_push_cn'
+SERVER_HOST2 = 'push-cn.cvp7gfpnmziz.rds.cn-northwest-1.amazonaws.com.cn'
+DATABASES_USER2 = 'aws_rds'
+DATABASES_PASS2 = 'Dil02uKDyd5Mxv7fhhHJ'
 
 DATABASES = {
     'default': {

+ 9 - 11
Ansjer/cn_config/test_settings.py

@@ -75,19 +75,17 @@ TEMPLATES = [
 
 WSGI_APPLICATION = 'Ansjer.cn_config.test_wsgi.application'
 
-
-# 服务器类型
-#国内宁夏测试业务数据库
-DATABASE_DATA = 'AnsjerTest'
-SERVER_HOST = 'business-server.cvp7gfpnmziz.rds.cn-northwest-1.amazonaws.com.cn'
-DATABASES_USER = 'azrds'
-DATABASES_PASS = 'UKv78ezQhiGMmSef5U5s'
+# 业务数据库
+DATABASE_DATA = 'ansjer_server_test'
+SERVER_HOST = 'server-test.cvp7gfpnmziz.rds.cn-northwest-1.amazonaws.com.cn'
+DATABASES_USER = 'aws_rds'
+DATABASES_PASS = 'tIPV7Dhvi8LDageBIrsI'
 
 # 推送数据库
-DATABASE_DATA2 = 'AnsjerTest'
-SERVER_HOST2 = 'ansjerpush.cvp7gfpnmziz.rds.cn-northwest-1.amazonaws.com.cn'
-DATABASES_USER2 = 'azrds'
-DATABASES_PASS2 = 'azrds.x.x'
+DATABASE_DATA2 = 'ansjer_push_test'
+SERVER_HOST2 = 'push-test.cvp7gfpnmziz.rds.cn-northwest-1.amazonaws.com.cn'
+DATABASES_USER2 = 'aws_rds'
+DATABASES_PASS2 = 'p7XolzlQoOJ2YqvBqogr'
 
 DATABASES = {
     'default': {

+ 7 - 11
Ansjer/eur_config/config_formal.py

@@ -16,17 +16,13 @@ import os
 # 配置信息
 CONFIG_INFO = 'eur'
 
-NGINX_RTMP_STAT = 'http://www.dvema.com/stat'
-SERVER_DOMAIN_SSL = 'https://www.dvema.com/'
-SERVER_DOMAIN = 'http://www.dvema.com/'
-DOMAIN_HOST = 'www.dvema.com'
+NGINX_RTMP_STAT = 'http://www.zositeche.com/stat'
+SERVER_DOMAIN_SSL = 'https://www.zositeche.com/'
+SERVER_DOMAIN = 'http://www.zositeche.com/'
+DOMAIN_HOST = 'www.zositeche.com'
 SERVER_HOST = 'server-redis.av1kep.ng.0001.euw1.cache.amazonaws.com'
 PUSH_REDIS_ADDRESS = 'push-redis.av1kep.ng.0001.euw1.cache.amazonaws.com'
-# PAYPAL_CRD = {
-#     "mode": "live",  # sandbox or live
-#     "client_id": "AdSRd6WBn-qLl9OiQHQuNYTDFSx0ZX0RUttqa58au8bPzoGYQUrt8bc6591RmH8_pEAIPijdvVYSVXyI",
-#     "client_secret": "ENT-J08N3Fw0B0uAokg4RukljAwO9hFHPf8whE6-Dwd8oBWJO8AWMgpdTKpfB1pOy89t4bsFEzMWDowm"
-# }
+
 PAYPAL_CRD = {
     "mode": "sandbox",  # sandbox or live
     "client_id": "AVLoQVq3xHZ6FrF4mxHwlCPgVBAw4Fw5RtMkuxmYd23SkUTIY643n2g3KdK-Al8wV05I28lza5uoQbAA",
@@ -36,8 +32,8 @@ PAYPAL_WEB_HOOK_ID = '3YH86681TH784461T'
 PAYPAL_WEB_HOOK_ID_TWO = '7TN87895N70389928'
 
 
-DETECT_PUSH_DOMAIN = 'http://push.dvema.com/'
-DETECT_PUSH_DOMAINS = 'https://push.dvema.com/'
+DETECT_PUSH_DOMAIN = 'http://push.zositeche.com/'
+DETECT_PUSH_DOMAINS = 'https://push.zositeche.com/'
 DETECT_PUSH_DOMAIN_JIUAN = 'http://jiuan.push.dvema.com/'
 DETECT_PUSH_DOMAINS_JIUAN = 'https://jiuan.push.dvema.com/'
 # 数据库dyanamo品牌日志数据库

+ 15 - 0
Ansjer/server_urls/algorithm_shop_url.py

@@ -0,0 +1,15 @@
+# -*- encoding: utf-8 -*-
+"""
+@File    : algorithm_shop_url.py
+@Time    : 2022/8/26 14:38
+@Author  : stephen
+@Email   : zhangdongming@asj6.wecom.work
+@Software: PyCharm
+"""
+from django.urls import re_path
+
+from Controller.AlgorithmShop import AlgorithmShopController
+
+urlpatterns = [
+    re_path(r'^api/(?P<operation>.*)$', AlgorithmShopController.AlgorithmShopView.as_view()),
+]

+ 3 - 0
Ansjer/urls.py

@@ -43,6 +43,7 @@ urlpatterns = [
     url(r'^account/email-re-pwd$', UserController.EmailResetPwdView.as_view()),
     url(r'^account/refreshTk$', UserController.refreshTokenView.as_view()),
     url(r'^v3/account/refreshTk$', UserController.refreshTokenViewV3.as_view()),
+    url(r'^v3/account/deleteUser$', UserController.DeleteUser.as_view()),
     url(r'^favicon.ico$', UserManger.success, name=u'favicon.ico'),
     url(r'^account/showUserMore$', UserManger.showUserMoreView.as_view()),
     url(r'^account/perfectUserInfo$', UserManger.perfectUserInfoView.as_view()),
@@ -353,6 +354,8 @@ urlpatterns = [
     url(r'^loocam/', include("Ansjer.server_urls.loocam_url")),
     # 联通4G套餐模块
     url(r'^unicom/', include("Ansjer.server_urls.unicom_url")),
+    # 算法小店
+    url(r'^algorithm-shop/', include("Ansjer.server_urls.algorithm_shop_url")),
 
     # 传感器网关
     re_path('sensorGateway/(?P<operation>.*)', SensorGatewayController.SensorGateway.as_view()),

+ 185 - 0
Controller/AlgorithmShop/AlgorithmShopController.py

@@ -0,0 +1,185 @@
+# -*- encoding: utf-8 -*-
+"""
+@File    : AlgorithmShopController.py
+@Time    : 2022/8/24 20:02
+@Author  : stephen
+@Email   : zhangdongming@asj6.wecom.work
+@Software: PyCharm
+"""
+import logging
+import time
+
+from django.views.generic.base import View
+
+from Model.models import DeviceAlgorithmExplain, DeviceAlgorithmBanner, DeviceUidAlgorithmType
+from Object.ResponseObject import ResponseObject
+from Object.TokenObject import TokenObject
+
+logger = logging.getLogger('info')
+
+
+class AlgorithmShopView(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):
+        token = TokenObject(request.META.get('HTTP_AUTHORIZATION'))
+        lang = request_dict.get('lang', token.lang)
+        response = ResponseObject(lang)
+        if token.code != 0:
+            return response.json(token.code)
+        if operation == 'list':
+            return self.algorithm_list(request_dict, response)
+        elif operation == 'banner-list':
+            return self.get_algorithm_banner(response)
+        elif operation == 'uid-details':
+            return self.get_algorithm_details(request_dict, response)
+        elif operation == 'save':
+            return self.algorithm_setting_save(request_dict, response)
+
+    @classmethod
+    def get_algorithm_banner(cls, response):
+        """
+        获取算法小店banner
+        """
+        banner_qs = DeviceAlgorithmBanner.objects.all()
+        banner_vs = banner_qs.order_by('sort') \
+            .values('algorithm_type__type', 'algorithm_type__id', 'image_url')
+        banner_list = []
+        if not banner_vs.exists():
+            return response.json(0, banner_list)
+        for item in banner_vs:
+            banner_list.append({
+                'typeId': item['algorithm_type__id'],
+                'type': item['algorithm_type__type'],
+                'imageUrl': item['image_url'],
+            })
+        return response.json(0, banner_list)
+
+    @classmethod
+    def algorithm_list(cls, request_dict, response):
+        """
+        获取算法小店列表
+        """
+        try:
+            lang = request_dict.get('lang', 'en')
+            uid = request_dict.get('uid', None)
+            algorithm_qs = DeviceAlgorithmExplain.objects.filter(lang=lang).order_by('algorithm_type__sort') \
+                .values('algorithm_type__id', 'algorithm_type__type',
+                        'algorithm_type__icon_url',
+                        'title', 'subtitle', 'algorithm_type__image_url',
+                        'algorithm_type__basic_function')
+            algorithm_list = []
+            if not algorithm_qs.exists():
+                return response.json(0, algorithm_list)
+            for item in algorithm_qs:
+                setting = ''
+                if uid:
+                    setting = cls.get_uid_algorithm_info(item['algorithm_type__id'], uid)
+                    setting = setting if setting else {'status': 0, 'function': {}}
+                algorithm_list.append({
+                    'typeId': item['algorithm_type__id'],
+                    'type': item['algorithm_type__type'],
+                    'iconUrl': item['algorithm_type__icon_url'],
+                    'imageUrl': item['algorithm_type__image_url'],
+                    'title': item['title'],
+                    'subtitle': item['subtitle'],
+                    'setting': setting,
+                    'basicFunction': item['algorithm_type__basic_function']
+                })
+            return response.json(0, algorithm_list)
+        except Exception as e:
+            print('查询算法小店列表异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+            return response.json(177, repr(e))
+
+    @classmethod
+    def get_algorithm_details(cls, request_dict, response):
+        """
+        获取算法小店类型详情
+        """
+        try:
+            lang = request_dict.get('lang', 'en')
+            type_id = request_dict.get('typeId', None)
+            if not type_id:
+                return response.json(444, 'typeId not null')
+            type_id = int(type_id)
+            uid = request_dict.get('uid', None)
+            explain_qs = DeviceAlgorithmExplain.objects.filter(lang=lang).filter(algorithm_type__id=type_id) \
+                .values('algorithm_type__id', 'algorithm_type__type',
+                        'algorithm_type__down_count',
+                        'algorithm_type__details_img_url',
+                        'algorithm_type__icon_url',
+                        'title', 'subtitle', 'introduction',
+                        'install_explain', 'risk_warning',
+                        'algorithm_type__basic_function')
+            if not explain_qs.exists():
+                return response.json(0, {})
+            item = explain_qs.first()
+            algorithm_dict = {
+                'typeId': item['algorithm_type__id'],
+                'type': item['algorithm_type__type'],
+                'downCount': item['algorithm_type__down_count'],
+                'detailsImgUrl': item['algorithm_type__details_img_url'],
+                'iconUrl': item['algorithm_type__icon_url'],
+                'title': item['title'],
+                'subtitle': item['subtitle'],
+                'introduction': item['introduction'],
+                'installExplain': item['install_explain'],
+                'riskWarning': item['risk_warning'],
+                'basicFunction': item['algorithm_type__basic_function'],
+            }
+            if uid:
+                setting = cls.get_uid_algorithm_info(item['algorithm_type__id'], uid)
+                algorithm_dict['setting'] = setting if setting else {'status': 0, 'function': {}}
+            return response.json(0, algorithm_dict)
+        except Exception as e:
+            print('查询算法详情异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+            return response.json(177, repr(e))
+
+    @staticmethod
+    def get_uid_algorithm_info(type_id, uid):
+        """
+        获取当前设备使用算法状态信息
+        @param type_id: 算法类型ID
+        @param uid: 设备唯一标识
+        @return: dict
+        """
+        uid_algorithm_qs = DeviceUidAlgorithmType.objects.filter(algorithm_type_id=type_id, device_uid=uid) \
+            .values('status', 'function')
+        if not uid_algorithm_qs.exists():
+            return None
+        return uid_algorithm_qs.first()
+
+    @classmethod
+    def algorithm_setting_save(cls, request_dict, response):
+        """
+        算法设置保存
+        """
+        try:
+            type_id = request_dict.get('typeId', None)
+            uid = request_dict.get('uid', None)
+            status = request_dict.get('status', None)
+            setting_json = request_dict.get('function')
+            if not all([type_id, uid, status, setting_json]):
+                return response.json(444)
+            status = int(status)
+            type_id = int(type_id)
+            now_time = int(time.time())
+            uid_algorithm_qs = DeviceUidAlgorithmType.objects.filter(algorithm_type_id=type_id, device_uid=uid)
+            if not uid_algorithm_qs.exists():
+                param = {'algorithm_type_id': int(type_id), 'uid': uid, 'function': setting_json,
+                         'status': status, 'updated_time': now_time, 'created_time': now_time}
+                DeviceUidAlgorithmType.objects.create(**param)
+                return response.json(0)
+            uid_algorithm_qs.update(status=status, function=setting_json, updated_time=now_time)
+            return response.json(0)
+        except Exception as e:
+            print('保存算法设置异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+            return response.json(177, repr(e))

+ 40 - 9
Controller/CloudTransfer.py

@@ -5,6 +5,7 @@
 @File :CloudTransfer.py
 @IDE :PyCharm
 """
+import json
 import time
 
 from django.db import transaction
@@ -12,7 +13,7 @@ from django.db.models import Q
 from django.views.generic.base import View
 
 from Model.models import Device_User, Device_Info, Order_Model, UID_Bucket, StsCrdModel, VodHlsModel, Unused_Uid_Meal, \
-    VodBucketModel, UnicomDeviceInfo
+    VodBucketModel, UnicomDeviceInfo, LogModel
 from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
 from Service.CommonService import CommonService
@@ -44,13 +45,13 @@ class cloudTestView(View):
                 return response.json(tko.code)
             userID = tko.userID
             if operation == 'deviceTransfer':
-                return self.deviceTransfer(request_dict, response)
+                return self.deviceTransfer(request, request_dict, response)
             elif operation == 'mealTransfer':
-                return self.mealTransfer(request_dict, response, userID)
+                return self.mealTransfer(request, request_dict, response, userID)
             elif operation == 'expireMeal':
                 return self.expireMeal(request_dict, response)
 
-    def deviceTransfer(self, request_dict, response):
+    def deviceTransfer(self, request, request_dict, response):
         # 设备转移,一个用户下的设备转移到另一个用户
         oldUserID = request_dict.get("oldUserID", None)
         username = request_dict.get("username", None)
@@ -61,10 +62,10 @@ class cloudTestView(View):
         try:
             # 查询该userID下是否存在此设备
             old_deviceInfo_qs = Device_Info.objects.filter(userID_id=oldUserID, UID=uid, isExist=1) \
-                .values('isShare', 'vodPrimaryUserID', 'serial_number')
+                .values('isShare', 'vodPrimaryUserID', 'serial_number', 'userID__username')
             if not old_deviceInfo_qs.exists():
                 return response.json(10008)
-
+            old_user_name = old_deviceInfo_qs[0]['userID__username']
             newUserID = ModelService.get_userID_byname(username)  # 根据username获取userID
             if newUserID is None:  # 没有此用户
                 return response.json(104)
@@ -116,6 +117,19 @@ class cloudTestView(View):
                 if u_dev_info_qs.exists():
                     now_time = int(time.time())
                     u_dev_info_qs.update(user_id=newUserID, updated_time=now_time)
+                # 记录设备转移日志
+                ip = CommonService.get_ip_address(request)
+                content = json.loads(json.dumps(request_dict))
+                log = {
+                    'ip': ip,
+                    'user_id': 1,
+                    'status': 200,
+                    'time': int(time.time()),
+                    'url': 'cloudTransfer/deviceTransfer',
+                    'content': json.dumps(content),
+                    'operation': '用户{}的设备{}转移给了用户{}'.format(old_user_name, uid, newUserName),
+                }
+                LogModel.objects.create(**log)
                 # UIDMainUser.objects.filter(UID=uid).delete()
                 # uid_main_dict = {
                 #     'UID': uid,
@@ -129,7 +143,7 @@ class cloudTestView(View):
         else:
             return response.json(0)
 
-    def mealTransfer(self, request_dict, response, userID):
+    def mealTransfer(self, request, request_dict, response, userID):
         # 云存套餐转移,同一用户下不同设备间的云存套餐转移
         old_uid = request_dict.get("old_uid", None)
         new_uid = request_dict.get("new_uid", None)
@@ -138,7 +152,8 @@ class cloudTestView(View):
         try:
             # 查询两个UID是否在同一账号下
             old_deviceInfo_qs = Device_Info.objects.filter(userID_id=userID, UID=old_uid).values('isExist',
-                                                                                                 'vodPrimaryUserID')
+                                                                                                 'vodPrimaryUserID',
+                                                                                                 'userID__username')
             new_deviceInfo_qs = Device_Info.objects.filter(userID_id=userID, UID=new_uid).values('isExist')
             if not (old_deviceInfo_qs.exists() and new_deviceInfo_qs.exists()):
                 return response.json(10010)
@@ -157,7 +172,8 @@ class cloudTestView(View):
             # 查询转出设备正在使用的套餐
             old_using_uid_bucket = UID_Bucket.objects.filter(uid=old_uid, endTime__gte=nowTime).values('id',
                                                                                                        'bucket_id',
-                                                                                                       'has_unused').order_by(
+                                                                                                       'has_unused',
+                                                                                                       'bucket__content').order_by(
                 'addTime')
             if not old_using_uid_bucket.exists():
                 return response.json(10013)
@@ -205,6 +221,21 @@ class cloudTestView(View):
                 UID_Bucket.objects.filter(id=old_using_uid_bucket_id).update(uid=new_uid, has_unused=0)
                 StsCrdModel.objects.filter(uid=old_uid).delete()  # 删除转出设备stscrd表关联数据
 
+                # 记录套餐转移日志
+                ip = CommonService.get_ip_address(request)
+                content = json.loads(json.dumps(request_dict))
+                log = {
+                    'ip': ip,
+                    'user_id': 1,
+                    'status': 200,
+                    'time': int(time.time()),
+                    'url': 'cloudTransfer/mealTransfer',
+                    'content': json.dumps(content),
+                    'operation': '用户{}的设备{}的套餐{}转移给设备{}'.format(old_deviceInfo_qs[0]['userID__username'], old_uid,
+                                                                old_using_uid_bucket[0]['bucket__content'], new_uid),
+                }
+                LogModel.objects.create(**log)
+
         except Exception as e:
             # print(e)
             return response.json(500, repr(e))

+ 8 - 34
Controller/EquipmentManagerV3.py

@@ -1,9 +1,9 @@
+import base64
 import json
 import re
 import threading
 import time
 
-import base64
 import oss2
 import requests
 from django.db.models import Q
@@ -605,10 +605,14 @@ class EquipmentManagerV3(View):
         dvqs = Device_Info.objects.filter(userID_id=userID)
         # # 过滤已重置的设备
         dvqs = dvqs.filter(~Q(isExist=2))
+        if NickName:
+            dvqs = dvqs.filter(NickName=NickName)
+        if uid:
+            dvqs = dvqs.filter(UID=uid)
         dvql = dvqs.values('id', 'userID', 'NickName', 'UID', 'View_Account', 'View_Password', 'ChannelIndex',
                            'Type', 'isShare', 'primaryUserID', 'primaryMaster', 'data_joined', 'vodPrimaryUserID',
                            'vodPrimaryMaster', 'userID__userEmail', 'version', 'isVod', 'isExist', 'NotificationMode',
-                           'isCameraOpenCloud', 'serial_number')
+                           'isCameraOpenCloud', 'serial_number')[(page - 1) * line:page * line]
         dvls = CommonService.qs_to_list(dvql)
         uid_list = []
         for dvl in dvls:
@@ -776,40 +780,10 @@ class EquipmentManagerV3(View):
                 # 设备版本号
                 p['uid_version'] = ''
                 p['ucode'] = ''
+            p['View_Password'] = self.encrypt_pwd(p['View_Password'])
             data.append(p)
         result = data
-
-        if NickName:
-            # print('NickName搜索缓存')
-            data = []
-            for index, item in enumerate(result):
-                if NickName == item['NickName']:
-                    # 加密
-                    item['View_Password'] = self.encrypt_pwd(item['View_Password'])
-                    data.append(item)
-                    return response.json(0, data)
-        if uid:
-            # print('uid搜索缓存')
-            data = []
-            for index, item in enumerate(result):
-                if uid != item['UID']:
-                    continue
-                else:
-                    item['View_Password'] = self.encrypt_pwd(item['View_Password'])  # 加密
-                    data.append(item)
-                    return response.json(0, data)
-                return response.json(0, data)
-        items = []
-        # print('缓存分页')
-        for index, item in enumerate(result):
-            if (page - 1) * line <= index:
-                if index < page * line:
-                    # 加密
-                    item['View_Password'] = self.encrypt_pwd(item['View_Password'])
-                    print(item)
-                    items.append(item)
-        print(items)
-        return response.json(0, items)
+        return response.json(0, result)
 
     def do_fuzzy_query(self, userID, request_dict, response):
         fuzzy = request_dict.get('fuzzy', None)

+ 5 - 4
Controller/SensorGateway/SmartSceneController.py

@@ -111,14 +111,15 @@ class SmartSceneView(View):
 
                 if device_type != SENSOR_TYPE['smart_button']:  # 非智能按钮只返回网关
                     res = [cls.get_gateway_data(device_id)]
-                else:
+                else:   # 智能按钮返回网关,门磁和人体传感器(如果存在)
                     gateway_data = cls.get_gateway_data(device_id)
                     sub_device_qs = GatewaySubDevice.objects.filter(
                         Q(device_id=device_id) & Q(device_type=SENSOR_TYPE['door_magnet']) | Q(
                             device_type=SENSOR_TYPE['body_sensor'])).values('id', 'nickname', 'status', 'device_type')
-                    if not sub_device_qs.exists():
-                        return response.json(173)
-                    res = cls.get_sub_device_room_name(sub_device_qs, gateway_data)
+                    if sub_device_qs.exists():
+                        res = cls.get_sub_device_room_name(sub_device_qs, gateway_data)
+                    else:
+                        res = [gateway_data]
 
             return response.json(0, res)
         except Exception as e:

+ 37 - 7
Controller/UserController.py

@@ -15,7 +15,6 @@ import base64
 import datetime
 import logging
 import random
-import threading
 import time
 import traceback
 from io import BytesIO
@@ -38,7 +37,7 @@ from jwt.algorithms import RSAAlgorithm
 from ratelimit.decorators import ratelimit
 
 from Ansjer.config import AuthCode_Expire, SERVER_DOMAIN, APNS_CONFIG, JPUSH_CONFIG, FCM_CONFIG, TUTK_PUSH_DOMAIN
-from Ansjer.config import BASE_DIR
+from Ansjer.config import BASE_DIR, CONFIG_US, CONFIG_EUR, CONFIG_INFO, SERVER_DOMAIN_US, SERVER_DOMAIN_EUR
 from Controller.CheckUserData import DataValid, date_handler, RandomStr
 from Model.models import Device_User, Role, UidPushModel, UserOauth2Model, UserExModel, Device_Info, UidSetModel, \
     UserAppFrequencyModel, CountryIPModel, CountryModel, UidChannelSetModel, Order_Model, UID_Bucket, Unused_Uid_Meal, \
@@ -708,6 +707,14 @@ class refreshTokenViewV3(TemplateView):
             userID = tko.userID
             tko.lang = lang
 
+            # 删除不同区域相同用户
+            headers = {'Authorization': token}
+            if CONFIG_INFO == CONFIG_US:
+                url = SERVER_DOMAIN_EUR + 'v3/account/deleteUser'
+                # requests.get(url=url, headers=headers)
+            elif CONFIG_INFO == CONFIG_EUR:
+                url = SERVER_DOMAIN_US + 'v3/account/deleteUser'
+                # requests.get(url=url, headers=headers)
             if password:  # 检验密码
                 password = password.strip()
                 # 解密
@@ -2209,9 +2216,7 @@ class InitInfoView(View):
                     return response.json(904)
             else:
                 return response.json(444, 'push_type')
-            asy = threading.Thread(target=self.save_push_config,
-                                   args=(userID, appBundleId, push_type, token_val, m_code, lang, tz))
-            asy.start()
+            self.save_push_config(userID, appBundleId, push_type, token_val, m_code, lang, tz)
             if m_code:
                 # 获取设备推送状态
                 update_dict = {
@@ -2272,14 +2277,14 @@ class InitInfoView(View):
             app_type = 1 if push_type == 0 else 2
             gateway_push_qs = GatewayPush.objects.filter(user_id=user_id, m_code=m_code)
             if gateway_push_qs.exists():
-                gateway_push_qs.update(token_val=token_val, logout=False)
+                if gateway_push_qs.first().token_val != token_val:
+                    gateway_push_qs.update(token_val=token_val, logout=False)
             else:
                 GatewayPush.objects.create(user_id=user_id, app_bundle_id=app_bundle_id, app_type=app_type,
                                            push_type=push_type, token_val=token_val, m_code=m_code, lang=lang, tz=tz)
         except Exception as e:
             print('出错了~异步保存配置信息错误,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
-
     def update_country(self, request_dict, response, request):
         username = request_dict.get('unique', None)
         appBundleId = request_dict.get('appBundleId', None)
@@ -4230,3 +4235,28 @@ class InitUserInformationView(View):
             return response.json(0)
         else:
             return response.json(444)
+
+
+class DeleteUser(View):
+
+    def get(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        request_dict = request.GET
+        return self.validate(request, request_dict)
+
+    def post(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        request_dict = request.POST
+        return self.validate(request, request_dict)
+
+    def validate(self, request, request_dict):
+        token_code, user_id, response = CommonService.verify_token_get_user_id(request_dict, request)
+
+        if token_code != 0:
+            return response.json(token_code)
+        user_qs = Device_User.objects.filter(userID=user_id)
+        if user_qs.exists():
+            user_qs.delete()
+        return response.json(0)
+
+

+ 88 - 4
Model/models.py

@@ -1184,7 +1184,7 @@ class UidSetModel(models.Model):
     is_human = models.IntegerField(default=0, verbose_name='是否支持人形追踪。0:不支持,1:支持')
     is_custom_voice = models.IntegerField(default=0, verbose_name='是否支持自定义语音。0:不支持,1:支持')
     double_wifi = models.IntegerField(default=0, verbose_name='是否支持双频wifi。0:不支持,1:支持')
-    isSupportFourPoint = models.SmallIntegerField(default=0, verbose_name='是否支持预置点')    # 0:不支持, 1:支持
+    isSupportFourPoint = models.SmallIntegerField(default=0, verbose_name='是否支持预置点')  # 0:不支持, 1:支持
     mobile_4g = models.IntegerField(default=0, verbose_name='是否支持4g。0:不支持,1:支持')
     is_ptz = models.IntegerField(default=0, verbose_name='是否支持云台。0:不支持,1:支持')
     is_vod = models.IntegerField(default=0, verbose_name='是否支持云存储。0:不支持,1:支持')
@@ -1223,12 +1223,12 @@ class UidPushModel(models.Model):
 
 class GatewayPush(models.Model):
     id = models.AutoField(primary_key=True, verbose_name='自增id')
-    user_id = models.CharField(default='', max_length=32, verbose_name=u'用户id')
+    user_id = models.CharField(default='', max_length=32, db_index=True, verbose_name=u'用户id')
     app_bundle_id = models.CharField(default='', max_length=32, verbose_name=u'app包id')
     app_type = models.IntegerField(default=0, verbose_name=u'app类型')  # 1: ios, 2: 安卓
     push_type = models.IntegerField(default=0, verbose_name=u'推送类型')  # 0: apns, 1: 安卓gcm, 2: 极光
     token_val = models.CharField(default='', max_length=500, verbose_name=u'设备验证令牌')
-    m_code = models.CharField(default='', max_length=64, verbose_name='手机唯一标识')
+    m_code = models.CharField(default='', max_length=64, db_index=True, verbose_name='手机唯一标识')
     lang = models.CharField(default='en', max_length=8, verbose_name='推送语言')
     tz = models.CharField(default='0', max_length=8, verbose_name='时区')
     logout = models.BooleanField(default=False, verbose_name=u'退出登录')
@@ -1714,11 +1714,25 @@ class AppBundle(models.Model):
         verbose_name_plural = verbose_name
 
 
+class AppVersionNumber(models.Model):
+    id = models.AutoField(primary_key=True)
+    app_bundle = models.ForeignKey(AppBundle, to_field='id', default='', on_delete=models.DO_NOTHING,
+                                   verbose_name='关联APP版本表')
+    version_number = models.CharField(max_length=32, verbose_name='版本号', default='')
+
+    class Meta:
+        db_table = 'app_version_number'
+        verbose_name = 'APP版本号表'
+        verbose_name_plural = verbose_name
+
+
 class AppDeviceType(models.Model):
     id = models.AutoField(primary_key=True)
-    model = models.SmallIntegerField(default=0, verbose_name='设备类型')  # 1:DVR, 2:IPC
+    # 1:DVR, 2:IPC
+    model = models.SmallIntegerField(default=0, verbose_name='设备类型')
     type = models.IntegerField(default=0, verbose_name='设备型号')
     icon = models.CharField(default='', max_length=200, verbose_name='图标文件路径')
+    app_version_number_id = models.CharField(default='', max_length=32, verbose_name='关联APP版本号表id')
 
     class Meta:
         db_table = 'app_device_type'
@@ -2803,3 +2817,73 @@ class UnicomFlowPush(models.Model):
         verbose_name = '联通流量用量推送'
         verbose_name_plural = verbose_name
         app_label = "PushModel"
+
+
+class DeviceAlgorithmType(models.Model):
+    id = models.AutoField(primary_key=True)
+    # 0:移动侦测,1:人形检测,2:挥手识别,3:人脸检测,4:异声感知,5:车辆检测,6:宠物检测,7:绊线入侵,8:离岗检测,9:徘徊检测
+    type = models.SmallIntegerField(default=0, verbose_name='算法类型')
+    memory = models.CharField(max_length=32, default='', verbose_name='所需内存')
+    down_count = models.IntegerField(default=0, verbose_name='下载次数')
+    sort = models.IntegerField(default=0, verbose_name=u'排序,越小越靠前')
+    basic_function = models.TextField(blank=True, default='', verbose_name=u'基础功能(json格式)')
+    image_url = models.CharField(max_length=255, default='', verbose_name='图片地址')
+    details_img_url = models.CharField(max_length=255, default='', verbose_name='详情图')
+    icon_url = models.CharField(max_length=255, default='', verbose_name='图标地址')
+    created_time = models.IntegerField(default=0, verbose_name='创建时间')
+
+    class Meta:
+        db_table = 'device_algorithm_type'
+        verbose_name = '设备算法类型'
+        verbose_name_plural = verbose_name
+
+
+class DeviceAlgorithmBanner(models.Model):
+    id = models.AutoField(primary_key=True)
+    algorithm_type = models.ForeignKey(DeviceAlgorithmType, to_field='id', default='', on_delete=models.CASCADE,
+                                       verbose_name=u'关联算法类型')
+    image_url = models.CharField(max_length=255, default='', verbose_name='横幅图')
+    sort = models.IntegerField(default=0, verbose_name=u'排序,越小越靠前')
+    updated_time = models.IntegerField(default=0, verbose_name='更新时间')
+    created_time = models.IntegerField(default=0, verbose_name='创建时间')
+
+    class Meta:
+        db_table = 'device_algorithm_banner'
+        verbose_name = '设备算法横幅广告'
+        verbose_name_plural = verbose_name
+
+
+class DeviceAlgorithmExplain(models.Model):
+    id = models.AutoField(primary_key=True)
+    algorithm_type = models.ForeignKey(DeviceAlgorithmType, to_field='id', default='', on_delete=models.CASCADE,
+                                       verbose_name=u'关联算法类型')
+    title = models.CharField(max_length=32, default='', verbose_name='标题')
+    subtitle = models.CharField(max_length=100, default='', verbose_name='副标题')
+    introduction = models.TextField(blank=True, default='', verbose_name='功能介绍')
+    install_explain = models.TextField(blank=True, default='', verbose_name=u'安装说明')
+    risk_warning = models.TextField(blank=True, default='', verbose_name=u'风险提示')
+    lang = models.CharField(default='', max_length=20, db_index=True, verbose_name='语言/国家')
+    updated_time = models.IntegerField(default=0, verbose_name='更新时间')
+    created_time = models.IntegerField(default=0, verbose_name='创建时间')
+
+    class Meta:
+        db_table = 'device_algorithm_explain'
+        verbose_name = '设备算法详情'
+        verbose_name_plural = verbose_name
+
+
+class DeviceUidAlgorithmType(models.Model):
+    id = models.AutoField(primary_key=True)
+    status = models.SmallIntegerField(default=0, verbose_name=u'状态{0:关闭,1:开启}')
+    memory = models.CharField(max_length=32, default='', verbose_name='设备内存')
+    function = models.TextField(blank=True, default='', verbose_name='功能设置')
+    device_uid = models.CharField(max_length=32, db_index=True, default='', verbose_name='设备uid')
+    algorithm_type = models.ForeignKey(DeviceAlgorithmType, to_field='id', default='', on_delete=models.CASCADE,
+                                       verbose_name=u'关联算法类型')
+    updated_time = models.IntegerField(default=0, verbose_name='更新时间')
+    created_time = models.IntegerField(default=0, verbose_name='创建时间')
+
+    class Meta:
+        db_table = 'device_uid_algorithm_type'
+        verbose_name = '设备uid关联算法类型'
+        verbose_name_plural = verbose_name