| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450 | 
							- # -*- encoding: utf-8 -*-
 
- """
 
- @File    : AgentDeviceController.py
 
- @Time    : 2024/3/8 13:55
 
- @Author  : stephen
 
- @Email   : zhangdongming@asj6.wecom.work
 
- @Software: PyCharm
 
- """
 
- import os
 
- import csv
 
- import time
 
- from datetime import datetime
 
- import calendar
 
- from dateutil.relativedelta import relativedelta
 
- from collections import defaultdict
 
- from decimal import Decimal
 
- import traceback
 
- import threading
 
- from django.db import transaction
 
- from django.db.models import Q
 
- from django.http import QueryDict
 
- from django.views import View
 
- from django.core.paginator import Paginator
 
- from AgentModel.models import AgentCustomerInfo, AgentDeviceOrder, AgentDevice, AgentCloudServicePackage, CustomUIDPool, \
 
-     DeviceCustomUID
 
- from Model.models import DeviceTypeModel
 
- from Object.ResponseObject import ResponseObject
 
- from Ansjer.config import LOGGER
 
- from Object.TokenObject import TokenObject
 
- class AgentDeviceView(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 delete(self, request, *args, **kwargs):
 
-         request.encoding = 'utf-8'
 
-         operation = kwargs.get('operation')
 
-         delete = QueryDict(request.body)
 
-         if not delete:
 
-             delete = request.GET
 
-         return self.validation(delete, request, operation)
 
-     def put(self, request, *args, **kwargs):
 
-         request.encoding = 'utf-8'
 
-         operation = kwargs.get('operation')
 
-         put = QueryDict(request.body)
 
-         return self.validation(put, request, operation)
 
-     def validation(self, request_dict, request, operation):
 
-         language = request_dict.get('language', 'en')
 
-         response = ResponseObject(language, 'pc')
 
-         # 订单结算界面
 
-         if operation == 'XXXXX':
 
-             pass
 
-         else:
 
-             tko = TokenObject(
 
-                 request.META.get('HTTP_AUTHORIZATION'),
 
-                 returntpye='pc')
 
-             if tko.code != 0:
 
-                 return response.json(tko.code)
 
-             response.lang = tko.lang
 
-             userID = tko.userID
 
-             if operation == 'getAgentDevice':
 
-                 return self.get_agent_device(userID, request_dict, response)
 
-             elif operation == 'getAgentDeviceOrder':
 
-                 return self.get_agent_device_order(userID, request_dict, response)
 
-             elif operation == 'batchBandDevice':
 
-                 return self.batch_band_device(userID, request, request_dict, response)
 
-             elif operation == 'customUidBind':
 
-                 return self.custom_uid_bindings(request_dict, response)
 
-             else:
 
-                 return response.json(444, 'operation')
 
-     def get_agent_device(self, userID, request_dict, response):
 
-         """
 
-         查询设备明细
 
-         @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:
 
-         """
 
-         device_name = request_dict.get('device_name', None)
 
-         status = request_dict.get('status', None)
 
-         serial_number = request_dict.get('serial_number', None)
 
-         page = int(request_dict.get('page', 1))  # 默认为第一页
 
-         page_size = int(request_dict.get('page_size', 10))  # 默认每页10条记录
 
-         try:
 
-             agent_customer_info = AgentCustomerInfo.objects.filter(user_id=userID).first()
 
-             if agent_customer_info is None:
 
-                 agent_device_qs = AgentDevice.objects.order_by('ac_id', '-created_time')
 
-             else:
 
-                 ac_id = agent_customer_info.id
 
-                 agent_device_qs = AgentDevice.objects.filter(ac_id=ac_id).order_by('ac_id', '-created_time')
 
-             if device_name:
 
-                 # 根据device_name查询对应的type值
 
-                 device_types = list(DeviceTypeModel.objects.filter(name=device_name).values_list('type', flat=True))
 
-                 agent_device_qs = agent_device_qs.filter(type__in=device_types)
 
-             if status:
 
-                 agent_device_qs = agent_device_qs.filter(status=status)
 
-             if serial_number:
 
-                 agent_device_qs = agent_device_qs.filter(serial_number=serial_number)
 
-             # 应用分页
 
-             paginator = Paginator(agent_device_qs, page_size)
 
-             current_page = paginator.get_page(page)
 
-             # 构造返回列表
 
-             device_list = []
 
-             for device in current_page:
 
-                 device_type = DeviceTypeModel.objects.filter(type=device.type).first()
 
-                 device_name = device_type.name if device_type else device.type
 
-                 agent_customer_info = AgentCustomerInfo.objects.filter(id=device.ac_id).first()
 
-                 company_name = agent_customer_info.company_name if agent_customer_info else device.ac_id
 
-                 device_list.append({
 
-                     'id': device.id,
 
-                     'ac_id': device.ac_id,
 
-                     'company_name': company_name,
 
-                     'status': device.status,
 
-                     'serial_number': device.serial_number,
 
-                     'device_name': device_name,
 
-                     'at_time': device.at_time,
 
-                 })
 
-             # 包含分页信息的响应
 
-             response_data = {
 
-                 'list': device_list,
 
-                 'total': paginator.count,
 
-                 'page': current_page.number,
 
-                 'page_size': page_size,
 
-                 'num_pages': paginator.num_pages,
 
-             }
 
-             return response.json(0, response_data)
 
-         except Exception as e:
 
-             print(e)
 
-             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,
 
-                                     end_time):
 
-         """
 
-         计算利润或者营业额
 
-         @param agent_device_orders: 代理设备订单
 
-         @param package_details: 代理套餐详情
 
-         @param time_unit: 时间单位
 
-         @param metric_type: 利润或者营业额
 
-         @param start_time: 开始时间
 
-         @param end_time: 结束时间
 
-         @return:
 
-         """
 
-         summary = defaultdict(lambda: {"云存": Decimal('0.00'), "4G": Decimal('0.00'), "all": Decimal('0.00')})
 
-         time_format = {
 
-             "month": "%Y-%m",
 
-             "year": "%Y",
 
-             "quarter": lambda x: f"{x.year}年{(x.month - 1) // 3 + 1}季度"
 
-         }
 
-         for order in agent_device_orders:
 
-             package = package_details.get(order.csp_id)
 
-             if not package:
 
-                 continue
 
-             # 根据利润类型计算利润或者直接使用营业额
 
-             if metric_type == 1:  # 利润
 
-                 profit = order.profit
 
-             else:  # 营业额
 
-                 profit = order.profit_amount
 
-             # 区分云服务 + 4G套餐并加入 summary
 
-             service_type = "云存" if package.type == 1 else "4G"
 
-             time_key = datetime.fromtimestamp(order.created_time).strftime(
 
-                 time_format[time_unit]) if time_unit != "quarter" else time_format[time_unit](
 
-                 datetime.fromtimestamp(order.created_time))
 
-             summary[time_key][service_type] += profit
 
-             summary[time_key]["all"] += profit
 
-         # 补全时间段内所有可能的时间单位
 
-         current_time = start_time
 
-         while current_time < end_time:
 
-             time_key = current_time.strftime(time_format[time_unit]) if time_unit != "quarter" else time_format[
 
-                 time_unit](current_time)
 
-             if time_key not in summary:
 
-                 summary[time_key] = {"云存": Decimal('0.00'), "4G": Decimal('0.00'), "all": Decimal('0.00')}
 
-             current_time += relativedelta(months=1) if time_unit == "month" else relativedelta(
 
-                 years=1) if time_unit == "year" else relativedelta(months=3)
 
-         return [{"time": time, **data} for time, data in sorted(summary.items())]
 
-     def get_agent_device_order(self, userID, request_dict, response):
 
-         """
 
-         查询设备订单明细
 
-         @param userID: userID
 
-         @param request_dict: 请求参数
 
-         @param request_dict startTime: 开始时间
 
-         @param request_dict endTime: 结束时间
 
-         @param request_dict timeUnit: 时间单位
 
-         @param request_dict metric_type: 利润或者营业额
 
-         @param response: 响应对象
 
-         @return:
 
-         """
 
-         try:
 
-             startTime = int(request_dict.get('startTime', 1704038400))
 
-             endTime = int(request_dict.get('endTime', 1732982400))
 
-             timeUnit = request_dict.get('timeUnit', 'month')
 
-             metric_type = int(request_dict.get('metric_type', 0))
 
-             # endTime变成每个月最后一天
 
-             end_datetime = datetime.fromtimestamp(endTime)
 
-             month_str = end_datetime.strftime('%Y-%m')
 
-             year, month = int(month_str.split('-')[0]), int(month_str.split('-')[1])
 
-             end = calendar.monthrange(year, month)[1]
 
-             end_timestamp = datetime(year, month, end, 23, 59, 59).timestamp()
 
-             endTime = int(end_timestamp)
 
-             agent_customer_info = AgentCustomerInfo.objects.filter(user_id=userID).first()
 
-             if not agent_customer_info:
 
-                 return response.json(104, 'Agent customer not found')
 
-             agent_device_orders = AgentDeviceOrder.objects.filter(
 
-                 ac_id=agent_customer_info.id, created_time__gte=startTime, created_time__lte=endTime, status__in=[1, 2]
 
-             )
 
-             # 获取代理套餐包id
 
-             package_ids = agent_device_orders.values_list('csp_id', flat=True).distinct()
 
-             package_details = {pkg.id: pkg for pkg in AgentCloudServicePackage.objects.filter(id__in=package_ids)}
 
-             start_time = datetime.fromtimestamp(startTime)
 
-             end_time = datetime.fromtimestamp(endTime)
 
-             result = self.calculate_profit_or_revenue(agent_device_orders, package_details, timeUnit, metric_type,
 
-                                                       start_time, end_time)
 
-             total_4G = Decimal('0.00')
 
-             total_cloud = Decimal('0.00')
 
-             # 遍历result列表来累加4G和云存的值
 
-             for item in result:
 
-                 total_4G = item['4G'] + total_4G
 
-                 total_cloud = item['云存'] + total_cloud
 
-             response_data = {
 
-                 "list": result,
 
-                 "total_4G": total_4G,  # 4G的总和
 
-                 "total_云存": total_cloud,  # 云存的总和
 
-             }
 
-             return response.json(0, response_data)
 
-         except Exception as e:
 
-             error_msg = f"error_line:{traceback.format_exc()}, error_msg:{str(e)}"
 
-             return response.json(500, error_msg)
 
-     def agent_devices_from_csv(self, ac_id, device_type, userID, file_path):
 
-         """
 
-         异步批量绑定设备
 
-         """
 
-         try:
 
-             with open(file_path, 'r') as file:
 
-                 reader = csv.DictReader(file)
 
-                 devices_to_create = []
 
-                 # 先收集所有CSV中的序列号
 
-                 csv_serial_numbers = [row.get('serial_number') for row in reader]
 
-                 # 去重
 
-                 unique_serial_numbers = set(csv_serial_numbers)
 
-                 existing = set(AgentDevice.objects.filter(
 
-                     serial_number__in=unique_serial_numbers
 
-                 ).values_list('serial_number', flat=True))
 
-                 for row in unique_serial_numbers:
 
-                     serial_number = row.get('serial_number')
 
-                     if serial_number not in existing:
 
-                         device = AgentDevice(
 
-                             ac_id=ac_id,
 
-                             serial_number=serial_number,
 
-                             type=device_type,
 
-                             status=0,
 
-                             created_time=int(time.time()),
 
-                             created_by=userID,
 
-                             updated_time=int(time.time()),
 
-                             updated_by=userID
 
-                         )
 
-                         devices_to_create.append(device)
 
-                 # 使用Django的bulk_create来批量创建对象
 
-                 if devices_to_create:
 
-                     with transaction.atomic():
 
-                         AgentDevice.objects.bulk_create(devices_to_create, batch_size=200)
 
-             # 删除文件
 
-             os.remove(file_path)
 
-         except Exception as e:
 
-             LOGGER.info('errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
-     def batch_band_device(self, userID, request, request_dict, response):
 
-         """
 
-         批量绑定设备
 
-         @param ac_id: ac_id 代理商id
 
-         @param userID: userID
 
-         @param csv_file_path: 文件路径
 
-         @param response: 响应对象
 
-         @return:
 
-         """
 
-         ac_id = request_dict.get('ac_id', None)
 
-         device_name = request_dict.get('device_name', None)
 
-         csv_file = request.FILES['file']
 
-         upload_dir = os.path.join('static', 'uploaded_files')
 
-         if not all([ac_id, device_name]):
 
-             return response.json(444)
 
-         try:
 
-             device_type_dict = DeviceTypeModel.objects.filter(name=device_name).values('type').first()
 
-             device_type = device_type_dict['type']
 
-             if not os.path.exists(upload_dir):
 
-                 os.makedirs(upload_dir)
 
-             file_path = os.path.join(upload_dir, csv_file.name)
 
-             with open(file_path, 'wb+') as destination:
 
-                 for chunk in csv_file.chunks():
 
-                     destination.write(chunk)
 
-             # 创建并启动线程来异步执行任务
 
-             thread = threading.Thread(target=self.agent_devices_from_csv, args=(ac_id, device_type, userID, file_path))
 
-             thread.start()
 
-             return response.json(0)
 
-         except Exception as e:
 
-             print(e)
 
-             return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
-     @classmethod
 
-     def device_binding_or_unbinding(cls, serial_number, bind_type):
 
-         """
 
-         设备绑定或解绑
 
-         @param serial_number: 设备序列号
 
-         @param bind_type: 绑定类型 1:绑定 2:解绑
 
-         @return: 无返回值
 
-         """
 
-         try:
 
-             # 获取设备信息
 
-             device_info = AgentDevice.objects.filter(serial_number=serial_number)
 
-             if not device_info.exists():
 
-                 return
 
-             n_time = int(time.time())
 
-             if bind_type == 1:
 
-                 # 绑定设备
 
-                 device_info.update(status=1, updated_time=n_time)
 
-             elif bind_type == 2:
 
-                 # 解绑设备
 
-                 device_info.update(status=0, updated_time=n_time)
 
-         except Exception as e:
 
-             LOGGER.info('*****AgentDeviceView.device_binding_or_unbinding:errLine:{}, errMsg:{}'
 
-                         .format(e.__traceback__.tb_lineno, repr(e)))
 
-     @classmethod
 
-     def custom_uid_bindings(cls, request_dict, response):
 
-         try:
 
-             uid = request_dict.get('uid', None)
 
-             customer_name = request_dict.get('customer_name', None)
 
-             status = request_dict.get('status', None)
 
-             device_mac = request_dict.get('device_mac', None)
 
-             page = int(request_dict.get('page', 1))
 
-             page_size = int(request_dict.get('pageSize', 20))
 
-             filters = Q()
 
-             if uid:
 
-                 filters &= Q(uid__icontains=uid)
 
-             if customer_name:
 
-                 filters &= Q(customer_name__icontains=customer_name)
 
-             if status is not None:
 
-                 filters &= Q(status=status)
 
-             if device_mac:
 
-                 bound_uids = DeviceCustomUID.objects.filter(
 
-                     device_mac__icontains=device_mac
 
-                 ).values_list('uid', flat=True)
 
-                 filters &= Q(uid__in=list(bound_uids))
 
-             custom_uid_pool_qs = CustomUIDPool.objects.filter(filters).order_by('-updated_time')
 
-             paginator = Paginator(custom_uid_pool_qs, page_size)
 
-             page_obj = paginator.page(page)
 
-             uid_list = [obj.uid for obj in page_obj]
 
-             bindings = DeviceCustomUID.objects.filter(uid__in=uid_list)
 
-             # 构建 uid -> 多条绑定记录 map
 
-             binding_map = {}
 
-             for b in bindings:
 
-                 binding_map.setdefault(b.uid, []).append(b)
 
-             # 构建结果列表
 
-             result_list = []
 
-             for obj in page_obj:
 
-                 uid_bindings = binding_map.get(obj.uid, [])
 
-                 if uid_bindings:
 
-                     for bind in uid_bindings:
 
-                         result_list.append({
 
-                             'id': obj.id,
 
-                             'uid': obj.uid,
 
-                             'type': obj.type,
 
-                             'customer_name': obj.customer_name,
 
-                             'uid_status': obj.status,
 
-                             'created_time': obj.created_time,
 
-                             'updated_time': obj.updated_time,
 
-                             'device_mac': bind.device_mac,
 
-                             'device_status': bind.status,
 
-                             'bind_time': bind.created_time,
 
-                         })
 
-                 else:
 
-                     result_list.append({
 
-                         'id': obj.id,
 
-                         'uid': obj.uid,
 
-                         'type': obj.type,
 
-                         'customer_name': obj.customer_name,
 
-                         'uid_status': obj.status,
 
-                         'created_time': obj.created_time,
 
-                         'updated_time': obj.updated_time,
 
-                         'device_mac': '',
 
-                         'device_status': None,
 
-                         'bind_time': None,
 
-                     })
 
-             return response.json(0, {
 
-                 'list': result_list,
 
-                 'total': paginator.count
 
-             })
 
-         except Exception as e:
 
-             print(e)
 
-             return response.json(500, f'error_line:{e.__traceback__.tb_lineno}, error_msg:{repr(e)}')
 
 
  |