瀏覽代碼

获取代理客户公司列表、instaVision新增V2接口、设备版本接口返回分别率参数、后台订单制作方案优化

zhangdongming 1 周之前
父節點
當前提交
e486b40877

+ 16 - 0
AdminController/CloudServiceManage/AgentCustomerController.py

@@ -84,6 +84,8 @@ class AgentCustomerView(View):
             # 代理客户绑定套餐
             elif operation == 'getCustomerList':
                 return self.get_customer_list(request_dict, response)
+            elif operation == 'getCompanyNameList':#下拉框查询专用
+                return self.get_company_name_list(request_dict, response)
             elif operation == 'getCustomerPackageList':
                 return self.get_cumstomer_package_list(request_dict, response)
             elif operation == 'batchRebindCustomerPackage':
@@ -1062,3 +1064,17 @@ class AgentCustomerView(View):
         ApplyAgent.objects.create(name=name, phone=clean_phone, regin=regin, remark=remark)
 
         return response.json(0, '申请已提交')
+
+    def get_company_name_list(self, request_dict, response):
+        """下拉框用于查询代理公司信息,避免分页"""
+        try:
+            agent_infos_query = (AgentCustomerInfo.objects.filter(status=1)
+                                 .values("id", "company_name")
+                                 .order_by('-id'))
+            data = list(agent_infos_query)
+            return response.json(0, data)
+        except Exception as e:
+            error_msg: str = f'查询代理商数据异常: {str(e)}'
+            error_line: int = e.__traceback__.tb_lineno
+            LOGGER.error(f'{error_msg} 行号: {error_line}')
+            return response.json(500)

+ 32 - 13
AdminController/CloudServiceManage/AgentDeviceController.py

@@ -11,6 +11,8 @@ import csv
 import time
 from datetime import datetime
 import calendar
+from typing import Dict, Any, Tuple, List, Optional
+
 from dateutil.relativedelta import relativedelta
 from collections import defaultdict
 from decimal import Decimal
@@ -82,21 +84,35 @@ class AgentDeviceView(View):
             else:
                 return response.json(444, 'operation')
 
-    def get_agent_device(self, userID, request_dict, response):
+    def get_agent_device(self, userID: str, request_dict: Dict[str, Any],
+                         response: ResponseObject) -> Optional[Dict[str, Any]]:
         """
         查询设备明细
-        @param userID: userID
-        @param request_dict: 请求参数
-        @param request_dict ac_id: 代理商id
-        @param request_dict device_name: 设备名字
-        @param request_dict status: 设备类型
-        @param request_dict serial_number: 设备9位序列号
-        @param response: 响应对象
-        @return:
+
+        Args:
+            userID (str): 用户ID
+            request_dict (Dict[str, Any]): 请求参数,包含以下字段:
+                - ac_id (int): 代理商ID
+                - device_name (str): 设备名称
+                - status (str): 设备状态
+                - serial_number (str): 设备序列号
+            response (ResponseObject): 响应对象
+
+        Returns:
+            Optional[Dict[str, Any]]: 返回设备明细列表及分页信息,可能为None
+
+        Raises:
+            ValueError: 当参数无效时抛出
+            RuntimeError: 当操作失败时抛出
+
+        Example:
+            get_agent_device("user123", {"ac_id": 1, "device_name": "test"}, response)
+            {'list': [...], 'total': 10, 'page': 1, 'page_size': 10, 'num_pages': 1}
         """
         device_name = request_dict.get('device_name', None)
         status = request_dict.get('status', None)
         serial_number = request_dict.get('serial_number', None)
+        company_id = int(request_dict.get('ac_id', 0))  # 默认查询所有公司
 
         page = int(request_dict.get('page', 1))  # 默认为第一页
         page_size = int(request_dict.get('page_size', 10))  # 默认每页10条记录
@@ -108,7 +124,8 @@ class AgentDeviceView(View):
             else:
                 ac_id = agent_customer_info.id
                 agent_device_qs = AgentDevice.objects.filter(ac_id=ac_id).order_by('ac_id', '-created_time')
-
+            if company_id > 0:
+                agent_device_qs = agent_device_qs.filter(ac_id=company_id)
             if device_name:
                 # 根据device_name查询对应的type值
                 device_types = list(DeviceTypeModel.objects.filter(name=device_name).values_list('type', flat=True))
@@ -152,7 +169,9 @@ class AgentDeviceView(View):
 
             return response.json(0, response_data)
         except Exception as e:
-            print(e)
+            error_msg = f'查询设备明细 - 用户: {userID}, 错误: {str(e)}'
+            error_line = e.__traceback__.tb_lineno
+            LOGGER.error(f'{error_msg} 行号: {error_line}')
             return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
     def calculate_profit_or_revenue(self, agent_device_orders, package_details, time_unit, metric_type, start_time,
@@ -371,7 +390,7 @@ class AgentDeviceView(View):
                 device_info.update(status=0, updated_time=n_time)
         except Exception as e:
             LOGGER.error('*****AgentDeviceView.device_binding_or_unbinding:errLine:{}, errMsg:{}'
-                        .format(e.__traceback__.tb_lineno, repr(e)))
+                         .format(e.__traceback__.tb_lineno, repr(e)))
 
     @classmethod
     def custom_uid_bindings(cls, request_dict, response):
@@ -448,4 +467,4 @@ class AgentDeviceView(View):
 
         except Exception as e:
             print(e)
-            return response.json(500, f'error_line:{e.__traceback__.tb_lineno}, error_msg:{repr(e)}')
+            return response.json(500, f'error_line:{e.__traceback__.tb_lineno}, error_msg:{repr(e)}')

+ 17 - 1
AdminController/ProductsSchemeManageController.py

@@ -532,6 +532,8 @@ class ProductsSchemeManageView(View):
     def device_scheme_list(user_id, request_dict, response):
         """
         查询设备方案列表
+        支持通过 storageCode 或 orderNumber 查询 DeviceScheme 表数据
+        ProductsScheme 和 DeviceScheme 表通过 storage_code 字段关联
         @param request_dict: 请求参数
         @param response: 响应对象
         @return: 响应对象包含设备方案列表
@@ -542,6 +544,7 @@ class ProductsSchemeManageView(View):
             'storage_code': request_dict.get("storageCode"),
             'device_type': request_dict.get("deviceType"),
             'phone_model': request_dict.get("phoneModel"),
+            'order_number': request_dict.get("orderNumber"),
         }
         page = int(request_dict.get("page", 1))
         page_size = int(request_dict.get("pageSize", 20))
@@ -552,9 +555,22 @@ class ProductsSchemeManageView(View):
 
             # 应用过滤条件
             if filters['serial_number']:
-                queryset = queryset.filter(serial_number=filters['serial_number'])
+                queryset = queryset.filter(serial_number__icontains=filters['serial_number'])
             if filters['storage_code']:
                 queryset = queryset.filter(storage_code__icontains=filters['storage_code'])
+            elif filters['order_number']:
+                # 通过 orderNumber 查询 ProductsScheme 表获取对应的 storage_code
+                products_schemes = ProductsScheme.objects.filter(
+                    order_number__icontains=filters['order_number']
+                ).values_list('storage_code', flat=True)
+                if not products_schemes:
+                    return response.json(0, {
+                        'list': [],
+                        'total': 0,
+                        'currentPage': page,
+                        'totalPages': 0
+                    })
+                queryset = queryset.filter(storage_code__in=products_schemes)
             if filters['device_type']:
                 queryset = queryset.filter(device_type=filters['device_type'])
             if filters['phone_model']:

+ 86 - 2
Controller/SerialNumberController.py

@@ -82,6 +82,8 @@ class SerialNumberView(View):
             return self.get_baidu_big_model_license_url(request_dict, response)
         elif operation == 'getInstavision':
             return self.get_instavision(request_dict, response, request)
+        elif operation == 'getInstaVisionV2':
+            return self.get_insta_vision_v2(request_dict, response, request)
         else:
             return response.json(414)
 
@@ -121,6 +123,7 @@ class SerialNumberView(View):
         is_verify = request_dict.get('is_verify', None)
 
         if not all([serial_number, token, time_stamp]):
+            LOGGER.error(f'{serial_number}请求绑定uid参数缺失')
             return response.json(444)
 
         # 时间戳token校验
@@ -1189,9 +1192,10 @@ class SerialNumberView(View):
         if not mac:
             return response.json(444)
         try:
+            scheme_code = request_dict.get('scheme_code', 'INST01350WA')
             ip = CommonService.get_ip_address(request)
             # 查询mac是否已存在数据
-            instavision_qs = Instavision.objects.filter(mac=mac, use_status=1).values('device_id', 'access_key')
+            instavision_qs = Instavision.objects.filter(mac=mac, scheme_code=scheme_code, use_status=1).values('device_id', 'access_key')
             if instavision_qs.exists():
                 res = {
                     'device_id': instavision_qs[0]['device_id'],
@@ -1203,7 +1207,7 @@ class SerialNumberView(View):
                 # 使用事务和select_for_update来处理并发问题
                 with transaction.atomic():
                     # 使用select_for_update加锁,防止并发时多个请求获取到同一条记录
-                    instavision_qs = Instavision.objects.select_for_update().filter(use_status=0).first()
+                    instavision_qs = Instavision.objects.select_for_update().filter(use_status=0, scheme_code=scheme_code).first()
 
                     if not instavision_qs:
                         return response.json(444, '没有可用的即时视觉数据')
@@ -1226,3 +1230,83 @@ class SerialNumberView(View):
         except Exception as e:
             LOGGER.error('获取DID error:{},mac:{}'.format(repr(e), mac))
             return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+
+    @staticmethod
+    def get_insta_vision_v2(request_dict, response, request):
+        """
+        获取insta_vision数据
+        @param request_dict: 请求参数
+        @param response: 响应对象
+        @request_dict mac: 设备mac地址
+        @request_dict code: 设备code
+        @request_dict scheme_code: 设备scheme_code
+        @request_dict time_stamp: 时间戳
+        @request_dict token: token
+        @return: response
+        """
+        mac = request_dict.get('mac', None)
+        token = request_dict.get('token', None)
+        time_stamp = request_dict.get('time_stamp', None)
+        scheme_code = request_dict.get('scheme_code', None)
+        try:
+            if not all([mac, token, time_stamp, scheme_code]):
+                LOGGER.error(f'ins获取DID参数缺失,mac:{mac}')
+                return response.json(444)
+            # 时间戳token校验
+            if not CommonService.check_time_stamp_token(token, time_stamp):
+                LOGGER.error(f'ins获取DID{scheme_code}时间戳校验失败time:{time_stamp},token:{token}')
+                return response.json(13)
+            ip = CommonService.get_ip_address(request)
+            content = json.loads(json.dumps(request_dict))
+            # 查询mac是否已存在数据
+            ins_qs = (Instavision.objects.filter(mac=mac, scheme_code=scheme_code, use_status=1)
+                      .values('device_id', 'access_key'))
+            log = {
+                'ip': ip,
+                'user_id': 1,
+                'status': 200,
+                'time': int(time.time()),
+                'content': json.dumps(content),
+                'url': 'serialNumber/getInstaVisionV2',
+            }
+
+            if ins_qs.exists():
+                res = {
+                    'device_id': ins_qs[0]['device_id'],
+                    'access_key': ins_qs[0]['access_key'],
+                }
+                did = ins_qs[0]['device_id']
+                log['operation'] = f'MAC:{mac}获取uid: {did}'
+                LogModel.objects.create(**log)
+                return response.json(0, res)
+            else:
+                # 使用事务和select_for_update来处理并发问题
+                with (transaction.atomic()):
+                    # 使用select_for_update加锁,防止并发时多个请求获取到同一条记录
+                    ins_qs = Instavision.objects.select_for_update(
+                    ).filter(use_status=0, scheme_code=scheme_code).first()
+
+                    if not ins_qs:
+                        LOGGER.error(f'ins获取DID{mac}没有可用的即时视觉数据,code:{scheme_code}')
+                        return response.json(444, '没有可用的即时视觉数据')
+
+                    device_id = ins_qs.device_id
+                    access_key = ins_qs.access_key
+
+                    # 更新该条数据的mac、use_status和updated_time
+                    ins_qs.mac = mac
+                    ins_qs.use_status = 1  # 标记为已使用
+                    ins_qs.updated_time = int(time.time())
+                    ins_qs.save()
+
+                    res = {
+                        'device_id': device_id,
+                        'access_key': access_key,
+                    }
+                    log['operation'] = f'MAC:{mac}绑定uid: {device_id}'
+                    LogModel.objects.create(**log)
+            return response.json(0, res)
+        except Exception as e:
+            LOGGER.error('ins获取DID,error:{},mac:{}'.format(repr(e), mac))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+

+ 58 - 25
Controller/UserDevice/DeviceVersionInfoController.py

@@ -140,42 +140,28 @@ class DeviceVersionInfoView(View):
                 return response.json(0, json.loads(version_info))
 
             # 从数据库查询设备版本信息
-            device_version_qs = DeviceVersionInfo.objects.filter(d_code=d_code, software_ver=ver).values()
+            device_version_qs = DeviceVersionInfo.objects.filter(d_code=d_code, software_ver=ver)
             if not device_version_qs.exists():
                 LOGGER.info(f'获取设备版本配置信息失败 user: {user_id}, uid: {uid}, version: {version}, ip: {ip} ')
                 return response.json(173)  # 错误代码:未找到设备版本信息
 
             # 从QuerySet中获取设备信息
             device_info = device_version_qs.first()
+            device_dict = device_version_qs.values().first()
 
-            other_features_fields = [
-                'supports_lighting',
-                'is_support_multi_speed',
-                'supports_algorithm_switch',
-                'supports_playback_filtering'
-            ]
+            other_features = cls.build_other_features(device_dict, d_code)
+            device_dict["other_features"] = other_features
 
-            if not device_info.get("other_features"):
-                device_info["other_features"] = {field: -1 for field in other_features_fields}
-            else:
-                try:
-                    if isinstance(device_info["other_features"], str):
-                        device_info["other_features"] = json.loads(device_info["other_features"])
-
-                    for field in other_features_fields:
-                        if field not in device_info["other_features"] or device_info["other_features"][field] in (None,
-                                                                                                                  ''):
-                            device_info["other_features"][field] = -1
-                except json.JSONDecodeError:
-                    device_info["other_features"] = {field: -1 for field in other_features_fields}
-
-            # 将设备信息序列化为JSON
-            device_json = json.dumps(device_info)
+            if getattr(device_info, "other_features", {}) != other_features:
+                device_info.other_features = other_features
+                device_info.save(update_fields=['other_features'])
+                DeviceVersionInfo.objects.filter(d_code=d_code, software_ver=ver).update(other_features=other_features)#更新数据库
+                LOGGER.info(f'更新other_features成功 id={device_info.id}')
 
-            # 将数据写入Redis,以便后续使用
+            device_json = json.dumps(device_dict)
             redis.set_data(version_key, device_json, 60 * 60 * 24)  # 设置TTL为24小时
             # 返回设备信息
-            return response.json(0, device_info)
+            return response.json(0, device_dict)
 
         except Exception as e:
             LOGGER.error('uid:{}返回173,error_line:{}, error_msg:{}'.format(uid, e.__traceback__.tb_lineno, repr(e)))
@@ -207,6 +193,11 @@ class DeviceVersionInfoView(View):
         if not device_info:
             return None
 
+        other_features = cls.build_other_features(device_info, d_code)
+        device_info["other_features"] = other_features
+        DeviceVersionInfo.objects.filter(d_code=d_code, software_ver=ver).update(other_features=
+                                                                                 other_features)  # 更新数据库
+
         try:
             redis.set_data(version_key, json.dumps(device_info), 60 * 60 * 24)
         except Exception as e:
@@ -215,6 +206,48 @@ class DeviceVersionInfoView(View):
 
         return device_info
 
+    @staticmethod
+    def build_other_features(device_dict, d_code):
+        """根据设备信息构建完整的other_features"""
+        other_features_fields = [
+            'supports_lighting',
+            'is_support_multi_speed',
+            'supports_algorithm_switch',
+            'supports_playback_filtering',
+            'resolution_list'
+        ]
+
+        mp_resolution_map = {
+            '8': ["800", "50"],
+            '5': ["500", "50"],
+            '4': ["400", "50"],
+            '3': ["300", "50"],
+            '2': ["200", "50"],
+            '1': ["100", "50"],
+            'A': ["1000", "50"],
+            'B': ["1100", "50"],
+            'C': ["1200", "50"],
+        }
+        resolution_list = mp_resolution_map.get(d_code[-5], ["400", "50"])
+
+        other_features = {}
+        try:
+            raw = device_dict.get("other_features")
+            if raw:
+                other_features = json.loads(raw) if isinstance(raw, str) else raw.copy()
+        except Exception:
+            pass
+
+        # 填充默认值
+        for field in other_features_fields:
+            if field not in other_features or other_features[field] in (None, ''):
+                other_features[field] = resolution_list if field == 'resolution_list' else -1
+
+        if other_features.get('resolution_list') != resolution_list:
+            other_features['resolution_list'] = resolution_list
+
+        return other_features
+
     @classmethod
     def validateUserDevice(cls, user_id, request, request_dict, response):
         """

+ 1 - 0
Model/models.py

@@ -5615,6 +5615,7 @@ class Instavision(models.Model):
     mac = models.CharField(max_length=32, unique=True, null=True, blank=True, verbose_name='设备mac地址')
     device_id = models.CharField(default='', max_length=32, verbose_name='设备id')
     access_key = models.CharField(default='', max_length=32, verbose_name='访问密钥')
+    scheme_code = models.CharField(max_length=32, verbose_name='方案编码', default='')
     # 使用状态,0: 未使用, 1: 已使用
     use_status = models.PositiveSmallIntegerField(default=0, verbose_name='使用状态')
     created_time = models.IntegerField(default=0, verbose_name='创建时间')