Переглянути джерело

后台订单新增序列号字段、插座新增离线复位、五兴新增兑换码订购套餐、修复标签查询消息列表数据错误问题

zhangdongming 2 роки тому
батько
коміт
c6ed9c3d7e

+ 11 - 15
AdminController/ServeManagementController.py

@@ -732,6 +732,7 @@ class serveManagement(View):
             order_ql = order_ql.order_by('-addTime')  # 根据CDK创建时间降序排序
             order_ql = order_ql[(page - 1) * line:page * line]
             for order in order_ql:
+                serialNumber = CommonService.query_serial_with_uid(order['UID'])
                 data = {
                     'orderID': order['orderID'],
                     'UID': order['UID'],
@@ -750,23 +751,24 @@ class serveManagement(View):
                     'rank__price': order['rank__price'],
                     'status': order['status'],
                     'order_type': order['order_type'],
-                    'payTime': order['payTime'] if order['payTime'] else 'N/A'
+                    'payTime': order['payTime'] if order['payTime'] else 'N/A',
+                    'serialNumber': 'N/A' if serialNumber == order['UID'] else serialNumber
                 }
                 #  订单显示(或不显示)停用/退款功能
-                if order['order_type'] == 0:  # 云存
+                if order['order_type'] == 0 or order['order_type'] == 1:  # 云存
                     uid_bucket = UID_Bucket.objects.filter(uid=order['UID']).values('use_status')
                     user_status = uid_bucket[0]['use_status'] if uid_bucket.exists() else ''
                     if user_status != '':
                         data['user_status'] = user_status
                     else:
                         data['user_status'] = 2
-                elif order['order_type'] == 1:  # ai
-                    ai_service_qs = AiService.objects.filter(
-                        Q(orders_id=order['orderID']) & ~Q(use_status=2))
-                    if ai_service_qs.exists():
-                        data['user_status'] = 1
-                    else:
-                        data['user_status'] = 2
+                # elif order['order_type'] == 1:  # ai
+                #     ai_service_qs = AiService.objects.filter(
+                #         Q(orders_id=order['orderID']) & ~Q(use_status=2))
+                #     if ai_service_qs.exists():
+                #         data['user_status'] = 1
+                #     else:
+                #         data['user_status'] = 2
                 elif order['order_type'] == 2:  # 联通4G
                     unicom_combor_order_qs = UnicomComboOrderInfo.objects.filter(
                         Q(order_id=order['orderID']) & ~Q(status=2))
@@ -774,12 +776,6 @@ class serveManagement(View):
                         data['user_status'] = 1
                     else:
                         data['user_status'] = 2
-                #  添加序列号
-                data['serial_number'] = 'N/A'
-                device_info_qs = Device_Info.objects.filter(UID=order['UID']).values('serial_number')
-                if device_info_qs.exists():
-                    data['serial_number'] = device_info_qs[0]['serial_number'] if device_info_qs[0][
-                        'serial_number'] else 'N/A'
                 #  添加PayPal交易号字段
                 data['trade_no'] = 'N/A'
                 if data['payType'] == 1:

+ 19 - 20
Controller/SensorGateway/SmartSocketController.py

@@ -10,7 +10,6 @@ import calendar
 import datetime
 import logging
 import time
-from decimal import Decimal
 
 import requests
 from dateutil.parser import parse
@@ -19,8 +18,7 @@ from django.db.models import Sum, Count
 from django.http import QueryDict
 from django.views import View
 
-from Model.models import SocketInfo, SocketSchedule, Device_Info, SocketPowerStatistics, SceneLog, FamilyRoomDevice, \
-    CountryModel
+from Model.models import SocketInfo, SocketSchedule, Device_Info, SocketPowerStatistics, SceneLog, FamilyRoomDevice
 from Object.ResponseObject import ResponseObject
 from Object.utils import LocalDateTimeUtil
 from Service.CommonService import CommonService
@@ -96,28 +94,31 @@ class SmartSocketView(View):
         try:
             with transaction.atomic():
                 serial_number = request_dict.get('serialNumber', None)
-                if not serial_number:
-                    return response.json(444)
+                status = request_dict.get('status', None)  # 设备当前状态0:关, 1:开, 2:离线
+                if not all([serial_number, status]):
+                    return response.json(444, {'error': 'serialNumber and status'})
                 socket_info_qs = SocketInfo.objects.filter(serial_number=serial_number, type_switch=0)
                 if not socket_info_qs.exists():
                     return response.json(173)
                 device_id = socket_info_qs.first().device_id
                 if socket_info_qs.first().status == 1:  # 设备电源开时 恢复为关闭状态
                     socket_info_qs.update(status=0, updated_time=int(time.time()))
-                # 删除插座倒计时
-                SocketInfo.objects.filter(device_id=device_id).delete()
                 # 删除插座电量统计
                 SocketPowerStatistics.objects.filter(device_id=device_id).delete()
                 # 删除插座排程
                 SocketSchedule.objects.filter(device_id=device_id).delete()
                 # 删除插座开关日志
                 SceneLog.objects.filter(device_id=serial_number).delete()
-                # 删除设备管理家庭接口
-                FamilyRoomDevice.objects.filter(device_id=device_id).delete()
-                # 删除设备
-                Device_Info.objects.filter(id=device_id).delete()
-                # alexa删除插座
-                cls.delete_alexa_socket(serial_number)
+                # 离线状态下只删除设备电量, 排程和开关日志
+                if int(status) != 2:
+                    # 删除插座倒计时
+                    SocketInfo.objects.filter(device_id=device_id).delete()
+                    # 删除设备管理家庭接口
+                    FamilyRoomDevice.objects.filter(device_id=device_id).delete()
+                    # 删除设备
+                    Device_Info.objects.filter(id=device_id).delete()
+                    # alexa删除插座
+                    cls.delete_alexa_socket(serial_number)
                 LOGGER.info('智能插座{}设备已复位'.format(serial_number))
                 return response.json(0)
         except Exception as e:
@@ -434,11 +435,9 @@ class SmartSocketView(View):
         # 确定是否会传值
         if not all([serial_number]):
             return response.json(444, {'error param': 'serialNumber'})
-        all_socket_power_qs = SocketPowerStatistics.objects.filter(serial_number=serial_number).values('electricity',
-                                                                                                       'accumulated_time',
-                                                                                                       'power',
-                                                                                                       'created_time'). \
-            order_by('-created_time')
+        all_socket_power_qs = SocketPowerStatistics.objects.\
+            filter(serial_number=serial_number).values('electricity', 'accumulated_time', 'power', 'created_time')\
+            .order_by('-created_time')
         if not all_socket_power_qs.exists():
             return response.json(0, {})
         try:
@@ -459,7 +458,7 @@ class SmartSocketView(View):
             electricity = all_socket_power_qs.filter(created_time__gte=startTime_now,
                                                      created_time__lt=endTime_now).aggregate(
                 total=Sum('electricity'))
-            if electricity['total'] != None:
+            if electricity['total'] is not None:
                 data['electricityMonth'] = round(electricity['total'], 1)
             else:
                 data['electricityMonth'] = 0
@@ -583,7 +582,7 @@ class SmartSocketView(View):
                 scene_log_qs = SceneLog.objects.filter(device_id=serial_number, created_time__gte=startTime,
                                                        created_time__lt=endTime).values('tasks', 'status',
                                                                                         'created_time').order_by(
-                    '-created_time','-id')[(page - 1) * size:page * size]
+                    '-created_time', '-id')[(page - 1) * size:page * size]
                 if not scene_log_qs.exists():
                     return response.json(0, [])
             log_list = []

+ 123 - 4
Controller/UnicomCombo/WXTechController.py

@@ -13,7 +13,8 @@ from django.views import View
 
 from Ansjer.config import LOGGER
 from Controller.UnicomCombo.UnicomComboController import UnicomComboView
-from Model.models import UnicomDeviceInfo, Order_Model, UnicomComboExperienceHistory, UnicomCombo
+from Model.models import UnicomDeviceInfo, Order_Model, UnicomComboExperienceHistory, UnicomCombo, ExchangeCode, \
+    LogModel
 from Object.Enums.WXOperatorEnum import WXOperatorEnum
 from Object.Enums.WXStartTypeEnum import WXStartTypeEnum
 from Object.ResponseObject import ResponseObject
@@ -53,6 +54,8 @@ class WXTechController(View):
         def validation(self, request_dict, request, operation):
             if operation == 'deleteCardPackage':
                 return self.delete_card_package(request_dict, ResponseObject('cn'))
+            elif operation == 'packageRefund':
+                return self.wx_package_refund(request_dict, ResponseObject('cn'))
             token_code, user_id, response = CommonService \
                 .verify_token_get_user_id(request_dict, request)
             if token_code != 0:
@@ -63,6 +66,38 @@ class WXTechController(View):
                 return self.get_experience_package(request_dict, response)
             elif operation == 'createOrder':
                 return self.create_order_package(request_dict, response)
+            elif operation == 'exchangePackage':
+                return self.wx_exchange_package(request_dict, response, request, user_id)
+
+        @classmethod
+        def wx_package_refund(cls, request_dict, response):
+            """
+            五兴套餐退订
+            """
+            try:
+                serial_number = request_dict.get('serialNumber', None)
+                if not serial_number:
+                    return response(444)
+                device_qs = UnicomDeviceInfo.objects.filter(serial_no=serial_number).values('iccid')
+                if not device_qs.exists():
+                    return response(173)
+                uid = CommonService.query_uid_with_serial(serial_number)
+                order_info_qs = Order_Model.objects.filter(UID=uid, order_type=3).values('trade_no') \
+                    .order_by('-payTime')
+                if not order_info_qs.exists():
+                    return response(173)
+                iccid = device_qs[0]['iccid']
+                trade_no = order_info_qs[0]['trade_no']
+                data = {'iccid': iccid, 'operator': 3, 'orderNumber': trade_no}
+                wx_tech = WXTechObject()
+                res = wx_tech.package_refund(**data)
+                if res['code'] == '0':
+                    return response.json(0)
+                return response.json(10059)
+            except Exception as e:
+                LOGGER.info('*****WXTechController.get_cards_info:errLine:{}, errMsg:{}'
+                            .format(e.__traceback__.tb_lineno, repr(e)))
+                return response.json(500, repr(e))
 
         @classmethod
         def get_cards_info(cls, request_dict, response):
@@ -157,12 +192,17 @@ class WXTechController(View):
                 return response.json(500, repr(e))
 
         @classmethod
-        def created_order(cls, serial_no, user_id, trade_no):
+        def created_order(cls, serial_no, user_id, trade_no, combo_id=None):
             """
             创建系统订单
             """
-            combo_info_qs = UnicomCombo.objects.filter(combo_type=1, status=0, is_del=False) \
-                .values('id', 'combo_name', 'price', 'virtual_price', 'remark').order_by('sort')
+            combo_info_qs = UnicomCombo.objects.filter(is_del=False)
+            if combo_id:
+                combo_info_qs = combo_info_qs.filter(id=int(combo_id))
+            else:
+                combo_info_qs = combo_info_qs.filter(combo_type=1, status=0)
+            combo_info_qs = combo_info_qs.values('id', 'combo_name', 'price', 'virtual_price', 'remark') \
+                .order_by('sort')
             if not combo_info_qs.exists():
                 return False
             combo_info_vo = combo_info_qs[0]
@@ -211,3 +251,82 @@ class WXTechController(View):
                 LOGGER.info('*****WXTechController.delete_card_package:errLine:{}, errMsg:{}'
                             .format(e.__traceback__.tb_lineno, repr(e)))
                 return response.json(500, repr(e))
+
+        @classmethod
+        def wx_exchange_package(cls, request_dict, response, request, user_id):
+            """
+            使用兑换码订购五兴五年流量套餐包
+            """
+            ip = CommonService.get_ip_address(request)
+            try:
+                code = request_dict.get('code')
+                serial_number = request_dict.get('serialNumber')
+                LOGGER.info('*****WXTechController.wx_exchange_package:params,{}'.format(request_dict))
+                if not all([code, serial_number]):
+                    return response.json(444)  # 参数缺失
+                # 校验兑换码格式是否正确
+                if not (code.isalnum() and len(code) == 10):
+                    return response.json(10040)  # 兑换码格式错误
+                card_type = 1
+                device_info_qs = UnicomDeviceInfo.objects.filter(serial_no=serial_number, card_type=card_type) \
+                    .values('iccid')
+                if not device_info_qs.exists():
+                    return response.json(173)  # 设备信息不存在
+                #  查询兑换码信息
+                exchange_code_qs = ExchangeCode.objects.filter(code=code, status=False, package_type=card_type) \
+                    .values('package_id', 'expire_time')
+                if not exchange_code_qs.exists():
+                    return response.json(10040)  # 兑换码无效
+                combo_id = exchange_code_qs[0]['package_id']
+                # 获取五兴套餐套餐编码
+                package_info_qs = UnicomCombo.objects.filter(id=combo_id, is_del=False) \
+                    .values('package_id')
+                if not package_info_qs.exists():
+                    return response.json(173)
+                package_code = package_info_qs[0]['package_id']
+                iccid = device_info_qs[0]['iccid']
+                # 五兴订购流量包请求参数
+                data = {'iccid': iccid, 'operator': WXOperatorEnum.TELECOM.value,
+                        'startType': str(WXStartTypeEnum.EFFECTIVE_IMMEDIATELY.value), 'packageCode': package_code}
+                wx_tech = WXTechObject()
+                # 请求五兴API订购套餐接口
+                res = wx_tech.create_order_package(**data)
+                LOGGER.info('*****五兴订购年卡套餐结果:{}'.format(res))
+                if res['code'] == '0':
+                    trade_no = res['data']['orderNumber']
+                    cls.created_order(serial_number, user_id, trade_no, combo_id)
+                    exchange_code_qs.update(status=True, updated_time=int(time.time()))
+                    cls.save_log(ip, 200, '兑换成功{},{}'.format(serial_number, code))
+                    return response.json(0)
+                cls.save_log(ip, 10040, '兑换失败{},{}'.format(serial_number, code))
+                return response.json(10040)
+            except Exception as e:
+                LOGGER.info('*****WXTechController.wx_exchange_package:errLine:{}, errMsg:{}'
+                            .format(e.__traceback__.tb_lineno, repr(e)))
+                cls.save_log(ip, 500, '兑换内部错误')
+                return response.json(500, repr(e))
+
+        @staticmethod
+        def save_log(ip, code, operation):
+            """
+            保存操作日志
+            @param ip: ip地址
+            @param code: 状态码
+            @param operation: 操作说明
+            @return: 保存结果
+            """
+            try:
+                log = {
+                    'ip': ip,
+                    'user_id': 1,
+                    'status': code,
+                    'time': int(time.time()),
+                    'operation': operation,
+                    'url': 'unicom/open/wxtech/exchangePackage',
+                }
+                LogModel.objects.create(**log)
+                return True
+            except Exception as e:
+                LOGGER.info('*****WXTechController.save_log:errLine:{}, errMsg:{}'
+                            .format(e.__traceback__.tb_lineno, repr(e)))
+                return False

+ 22 - 3
Model/models.py

@@ -2881,10 +2881,10 @@ class SceneLog(models.Model):
 
 class UnicomCombo(models.Model):
     id = models.AutoField(primary_key=True, verbose_name=u'自增标记Id')
-    package_id = models.CharField(default='', max_length=32, verbose_name=u'联通套餐id')
+    package_id = models.CharField(default='', max_length=128, verbose_name=u'第三方套餐包id')
     combo_name = models.CharField(default='', max_length=32, verbose_name=u'套餐名称')
     status = models.SmallIntegerField(default=0, verbose_name='状态{0:开启,1:停用}')
-    # 套餐类型 0:商用,1:初始化赠送,2:赠送套餐
+    # 套餐类型 0:联通商用,1:联通初始化赠送,2:联通赠送套餐,3:五兴电信
     combo_type = models.SmallIntegerField(default=0, verbose_name='套餐类型')
     flow_total = models.IntegerField(default=0, blank=True, verbose_name=u'流量总量值 单位(MB)')
     expiration_days = models.IntegerField(default=0, blank=True, verbose_name=u'有效期天数')
@@ -2942,7 +2942,7 @@ class UnicomDeviceInfo(models.Model):
     serial_no = models.CharField(default='', max_length=32, verbose_name=u'设备序列号')
     user_id = models.CharField(blank=True, max_length=32, verbose_name=u'用户id')
     card_type = models.SmallIntegerField(default=0, verbose_name=u'状态{0:联通,1:电信,2:移动}')
-    main_card = models.SmallIntegerField(default=0, verbose_name=u'状态{0:主卡,1:拔插卡}')
+    main_card = models.SmallIntegerField(default=0, verbose_name=u'SIM卡类型{0:拔插卡,1:贴片卡}')
     updated_time = models.IntegerField(default=0, verbose_name='更新时间')
     created_time = models.IntegerField(default=0, verbose_name='创建时间')
 
@@ -3529,3 +3529,22 @@ class SocketSchedule(models.Model):
         db_table = 's_socket_schedule'
         verbose_name = '插座排程'
         verbose_name_plural = verbose_name
+
+
+class ExchangeCode(models.Model):
+    id = models.AutoField(primary_key=True)
+    code = models.CharField(max_length=32, unique=True, verbose_name='兑换码')
+    status = models.BooleanField(default=False, verbose_name='状态(0-未使用,1-已使用)')
+    is_down = models.BooleanField(default=0, verbose_name='是否已下载 0-未下载,1-已下载')
+    package_type = models.SmallIntegerField(default=0, verbose_name='套餐包类型 0-联通,1-五兴,2-其它')
+    package_id = models.BigIntegerField(default=0, verbose_name='套餐包id')
+    expire_time = models.IntegerField(default=0, verbose_name='过期时间')
+    # 备用字段
+    spare_1 = models.CharField(default='', blank=True, max_length=64, verbose_name=u'备用字段1')
+    created_time = models.IntegerField(default=0, verbose_name='创建时间')
+    updated_time = models.IntegerField(default=0, verbose_name='创建时间')
+
+    class Meta:
+        db_table = 'exchange_code'
+        verbose_name = '套餐包兑换码'
+        verbose_name_plural = verbose_name

+ 9 - 0
Object/WXTechObject.py

@@ -79,6 +79,15 @@ class WXTechObject:
         url = WX_TECH_URL + '/api/v2/package/orderPackage'
         return self.wx_service_api(url, **params)
 
+    def package_refund(self, **params):
+        """
+        根据套餐订购记录ID,退订套餐(不退款)
+        @param params: operator、iccid、orderNumber
+        @return:
+        """
+        url = WX_TECH_URL + '/api/v2/outputApi/packageRefund'
+        return self.wx_service_api(url, **params)
+
     def delete_card_package(self, **params):
         """
         清空卡片的所有套餐订购记录

+ 7 - 2
Service/EquipmentInfoService.py

@@ -172,7 +172,10 @@ class EquipmentInfoService:
             # eventTypeList += cls.get_combo_type_bins(event_type)
             eventTypeList = list(set(eventTypeList))
             tags = cls.get_event_tag(event_type)
-            qs = qs.filter(Q(event_type__in=eventTypeList) | Q(event_tag__regex=tags))
+            if eventTypeList:
+                qs = qs.filter(Q(event_type__in=eventTypeList) | Q(event_tag__regex=tags))
+            elif tags:
+                qs = qs.filter(event_tag__regex=tags)
         if start_time and end_time:
             qs = qs.filter(event_time__range=(start_time, end_time))
         else:
@@ -240,11 +243,13 @@ class EquipmentInfoService:
             event_type_list = [int(event_type)]
         ai_event_type_list = []
         normal_event_type_list = []
+        a_type = [60, 61, 62, 63, 64, 65, 66]
         for val in event_type_list:
             if val <= 4:  # 分离出ai类型,以便后续组合ai标签,目前只存在4个ai类型1,2,3,4
                 ai_event_type_list.append(val)
             else:
-                normal_event_type_list.append(val)
+                if val not in a_type:
+                    normal_event_type_list.append(val)
         if len(ai_event_type_list) < 1:
             return normal_event_type_list
         ai_event_type_list.sort()