|
@@ -12,6 +12,7 @@ import threading
|
|
|
import time
|
|
|
import uuid
|
|
|
from decimal import Decimal
|
|
|
+from math import ceil
|
|
|
|
|
|
import openpyxl
|
|
|
import requests
|
|
@@ -36,6 +37,8 @@ from Object.WXTechObject import WXTechObject
|
|
|
from Service.CommonService import CommonService
|
|
|
from Service.TelecomService import TelecomService
|
|
|
|
|
|
+UNICOM_MANAGE_LOCK = 'BASIC:UNICOM:MANAGE:OPERATION:LOCK'
|
|
|
+
|
|
|
|
|
|
class UnicomManageControllerView(View):
|
|
|
|
|
@@ -51,6 +54,7 @@ class UnicomManageControllerView(View):
|
|
|
|
|
|
def validation(self, request_dict, request, operation):
|
|
|
response = ResponseObject()
|
|
|
+
|
|
|
# 获取支付类型
|
|
|
if operation == 'get/pay':
|
|
|
return self.get_pay_type(response)
|
|
@@ -105,7 +109,7 @@ class UnicomManageControllerView(View):
|
|
|
elif operation == 'downloadCDK': # 下载兑换码
|
|
|
return self.package_cdk_export_excel(response)
|
|
|
elif operation == 'uploadSerialNumberFile': # 上传序列号文件绑定4G套餐
|
|
|
- return self.upload_file(userID, tko.user, request, request_dict, response)
|
|
|
+ return self.serial_number_bind_package_bulk(userID, tko.user, request, request_dict, response)
|
|
|
elif operation == 'iccidBatchReset': # 批量重置流量
|
|
|
return self.iccid_batch_reset(tko.user, request, request_dict, response)
|
|
|
elif operation == 'orderFlowPackage': # 订购流量套餐包
|
|
@@ -116,6 +120,10 @@ class UnicomManageControllerView(View):
|
|
|
return self.serial_number_package_update(request_dict, response, tko.user)
|
|
|
elif operation == 'transferDevicePackage': # 转移设备套餐
|
|
|
return self.transfer_device_package(request_dict, response, tko.user)
|
|
|
+ elif operation == 'updateExpirationDate': # 修改套餐过期时间
|
|
|
+ return self.update_expiration_date(request_dict, response)
|
|
|
+ if operation == 'verifyPackageExport':
|
|
|
+ return self.verify_package_export_excel(request, request_dict, response)
|
|
|
else:
|
|
|
return response.json(404)
|
|
|
|
|
@@ -828,7 +836,7 @@ class UnicomManageControllerView(View):
|
|
|
card_type = ud_qs[0]['card_type']
|
|
|
if card_type == 0 or card_type == 3:
|
|
|
o_qs = UnicomComboOrderInfo.objects.filter(iccid=iccid) \
|
|
|
- .values('status', 'flow_total_usage', 'flow_exceed', 'activation_time', 'expire_time',
|
|
|
+ .values('id', 'status', 'flow_total_usage', 'flow_exceed', 'activation_time', 'expire_time',
|
|
|
'combo__combo_name', 'combo__flow_total', 'updated_time') \
|
|
|
.order_by('created_time')
|
|
|
if not o_qs:
|
|
@@ -865,6 +873,7 @@ class UnicomManageControllerView(View):
|
|
|
status_dict = {0: "待使用", 1: "使用中", 2: "已失效"}
|
|
|
status = status_dict.get(item['status'])
|
|
|
package_list.append({
|
|
|
+ 'id': item['id'],
|
|
|
'packageName': item['combo__combo_name'],
|
|
|
'status': status,
|
|
|
'flowTotal': flow_total,
|
|
@@ -1066,7 +1075,7 @@ class UnicomManageControllerView(View):
|
|
|
return response.json(0, flow_combo_list)
|
|
|
|
|
|
@classmethod
|
|
|
- def upload_file(cls, user_id, user, request, request_dict, response):
|
|
|
+ def serial_number_bind_package_bulk(cls, user_id, user, request, request_dict, response):
|
|
|
"""
|
|
|
上传序列号文件绑定套餐id
|
|
|
@param user_id: user_id
|
|
@@ -1076,46 +1085,68 @@ class UnicomManageControllerView(View):
|
|
|
@param response: 响应对象
|
|
|
@return: 成功数以及异常序列号列表
|
|
|
"""
|
|
|
- package_id = request_dict.get('packageId', None)
|
|
|
- file = request.FILES['file']
|
|
|
- serial_list = []
|
|
|
- error_list = []
|
|
|
- if not package_id:
|
|
|
- return response.json(444)
|
|
|
- n_time = int(time.time())
|
|
|
- package_id = int(package_id)
|
|
|
- sn_list = []
|
|
|
-
|
|
|
- uc_qs = UnicomCombo.objects.filter(id=package_id)
|
|
|
- if not uc_qs.exists():
|
|
|
- return response.json(173)
|
|
|
+ redis_obj = RedisObject(5)
|
|
|
+ try:
|
|
|
+ lock = redis_obj.try_lock(UNICOM_MANAGE_LOCK, 'iccid', 15, 60)
|
|
|
+ if not lock:
|
|
|
+ return response.json(10074)
|
|
|
|
|
|
- for line in file:
|
|
|
- serial_number = line.decode().strip()[0:9]
|
|
|
- try:
|
|
|
- sn_qs = SerialNumberPackage.objects.filter(serial_number=serial_number)
|
|
|
- if sn_qs:
|
|
|
- error_list.append({'serialNumber': serial_number, 'msg': '此序列号已绑定套餐'})
|
|
|
- continue
|
|
|
- if serial_number in serial_list:
|
|
|
- error_list.append({'serialNumber': serial_number, 'msg': 'txt存在重复序列号'})
|
|
|
- continue
|
|
|
- data = {'status': 1, 'serial_number': serial_number, 'package_id': package_id,
|
|
|
- 'created_time': n_time, 'updated_time': n_time, 'created_by': user, 'updated_by': user}
|
|
|
- serial_number_p = SerialNumberPackage(**data)
|
|
|
- serial_list.append(serial_number)
|
|
|
- sn_list.append(serial_number_p)
|
|
|
- except Exception as e:
|
|
|
- error_list.append({'serialNumber': serial_number, 'msg': repr(e)})
|
|
|
- if sn_list:
|
|
|
- SerialNumberPackage.objects.bulk_create(sn_list)
|
|
|
+ package_id = request_dict.get('packageId', None)
|
|
|
+ file = request.FILES['file']
|
|
|
+ serial_list = []
|
|
|
+ error_list = []
|
|
|
+ if not package_id:
|
|
|
+ return response.json(444)
|
|
|
+ n_time = int(time.time())
|
|
|
+ package_id = int(package_id)
|
|
|
+ sn_list = []
|
|
|
|
|
|
- # 终身免流量时只保留一个有效套餐并自动激活
|
|
|
- if uc_qs.first().remark == 'LIFETIME_FREE':
|
|
|
- asy = threading.Thread(target=cls.activate_4G_lifetime_free, args=(sn_list, user_id))
|
|
|
- asy.start()
|
|
|
+ uc_qs = UnicomCombo.objects.filter(id=package_id)
|
|
|
+ if not uc_qs.exists():
|
|
|
+ return response.json(173)
|
|
|
|
|
|
- return response.json(0, {'total': len(serial_list), 'errData': error_list})
|
|
|
+ for line in file:
|
|
|
+ serial_number = line.decode().strip()[0:9]
|
|
|
+ try:
|
|
|
+ sn_qs = SerialNumberPackage.objects.filter(serial_number=serial_number)
|
|
|
+ if sn_qs:
|
|
|
+ error_list.append({'serialNumber': serial_number, 'msg': '此序列号已绑定套餐'})
|
|
|
+ continue
|
|
|
+ if serial_number in serial_list:
|
|
|
+ error_list.append({'serialNumber': serial_number, 'msg': 'txt存在重复序列号'})
|
|
|
+ continue
|
|
|
+ data = {'status': 1, 'serial_number': serial_number, 'package_id': package_id,
|
|
|
+ 'created_time': n_time, 'updated_time': n_time, 'created_by': user, 'updated_by': user}
|
|
|
+ serial_number_p = SerialNumberPackage(**data)
|
|
|
+ serial_list.append(serial_number)
|
|
|
+ sn_list.append(serial_number_p)
|
|
|
+ except Exception as e:
|
|
|
+ error_list.append({'serialNumber': serial_number, 'msg': repr(e)})
|
|
|
+
|
|
|
+ if sn_list:
|
|
|
+ # 计算总数量和页数,仅计算一次
|
|
|
+ total_count = len(sn_list)
|
|
|
+ pages = ceil(total_count / 100)
|
|
|
+
|
|
|
+ # 遍历每一页,使用列表切片处理批次
|
|
|
+ for page in range(pages):
|
|
|
+ # 计算本次循环实际处理的结束索引,考虑最后一页可能不足100的情况
|
|
|
+ end = min((page + 1) * 100, total_count)
|
|
|
+ # 切片获取当前批次的sn_list
|
|
|
+ batch_sn_list = sn_list[page * 100:end]
|
|
|
+
|
|
|
+ # 执行批量创建
|
|
|
+ SerialNumberPackage.objects.bulk_create(batch_sn_list)
|
|
|
+
|
|
|
+ # 终身免流量时只保留一个有效套餐并自动激活
|
|
|
+ if uc_qs.first().remark == 'LIFETIME_FREE':
|
|
|
+ asy = threading.Thread(target=cls.activate_4G_lifetime_free, args=(sn_list, user_id))
|
|
|
+ asy.start()
|
|
|
+ # 释放锁
|
|
|
+ redis_obj.release_lock(UNICOM_MANAGE_LOCK, 'iccid')
|
|
|
+ return response.json(0, {'total': len(serial_list), 'errData': error_list})
|
|
|
+ except Exception as e:
|
|
|
+ LOGGER.info('批量绑定异常详情,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
|
|
|
|
|
|
@classmethod
|
|
|
def activate_4G_lifetime_free(cls, sn_list, user_id):
|
|
@@ -1154,6 +1185,10 @@ class UnicomManageControllerView(View):
|
|
|
"""
|
|
|
iccid批量重置流量
|
|
|
"""
|
|
|
+ redis_obj = RedisObject(5)
|
|
|
+ lock = redis_obj.try_lock(UNICOM_MANAGE_LOCK, 'iccid', 15, 60)
|
|
|
+ if not lock:
|
|
|
+ return response.json(10074)
|
|
|
file = request.FILES['file']
|
|
|
binding_type = int(request_dict.get('type', 0))
|
|
|
if not file:
|
|
@@ -1167,6 +1202,9 @@ class UnicomManageControllerView(View):
|
|
|
@staticmethod
|
|
|
def async_bulk_reset_flow_package(file, user, ip, binding_type):
|
|
|
err_data = []
|
|
|
+ date_str = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
|
|
+
|
|
|
+ num = 0
|
|
|
for line in file:
|
|
|
serial_number = line.decode().strip()[0:9]
|
|
|
try:
|
|
@@ -1193,6 +1231,7 @@ class UnicomManageControllerView(View):
|
|
|
res = wx_tech.delete_card_package(**data)
|
|
|
if res['code'] == '0':
|
|
|
UnicomComboExperienceHistory.objects.filter(iccid=iccid).delete()
|
|
|
+ num += 1
|
|
|
continue
|
|
|
err_data.append({'serialNumber': serial_number, 'msg': '电信重置流量异常:{}'.format(res['code'])})
|
|
|
continue
|
|
@@ -1217,6 +1256,7 @@ class UnicomManageControllerView(View):
|
|
|
result = UnicomComboView().activate_test_flow_package(serial_number) # 订购新的100M测试流量
|
|
|
describe = '批量重置4G流量序列号{},iccid:{},{}'.format(serial_number, iccid, result)
|
|
|
|
|
|
+ num += 1
|
|
|
# 当前缓存是客户首次扫序列号,激活赠送测试流量生成的,重置流量所以要清除
|
|
|
key = f'ASJ:UNICOM:CARD:ACTIVATE:{serial_number}'
|
|
|
redis = RedisObject()
|
|
@@ -1231,6 +1271,15 @@ class UnicomManageControllerView(View):
|
|
|
describe = json.loads(json.dumps(err_data))
|
|
|
UnicomManageControllerView().create_operation_log('unicom/manage/iccidBatchReset', ip, binding_type,
|
|
|
describe)
|
|
|
+ try:
|
|
|
+ redis_obj = RedisObject(5)
|
|
|
+ lock = redis_obj.release_lock(UNICOM_MANAGE_LOCK, 'iccid')
|
|
|
+ describe = f'{date_str}批量重置流量释放锁{lock},数量:{num}'
|
|
|
+ UnicomManageControllerView().create_operation_log('unicom/manage/iccidBatchReset', ip, binding_type,
|
|
|
+ describe)
|
|
|
+ except Exception as e:
|
|
|
+ LOGGER.info('释放锁异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
|
|
|
+
|
|
|
LOGGER.info(f'批量重置流量type={binding_type},err_data={err_data}')
|
|
|
|
|
|
@classmethod
|
|
@@ -1394,3 +1443,111 @@ class UnicomManageControllerView(View):
|
|
|
}
|
|
|
package_list.append(new_package)
|
|
|
return package_list
|
|
|
+
|
|
|
+ @classmethod
|
|
|
+ def update_expiration_date(cls, request_dict, response):
|
|
|
+ """
|
|
|
+ 更改套餐过期时间
|
|
|
+ @param request_dict: 请求参数
|
|
|
+ @request_dict id: 套餐id
|
|
|
+ @request_dict expireTime: 过期时间
|
|
|
+ @request_dict serialNumber: 序列号
|
|
|
+ @param response: 响应对象
|
|
|
+ @return:
|
|
|
+ """
|
|
|
+ id = request_dict.get("id", None)
|
|
|
+ expire_time = request_dict.get("expireTime", None)
|
|
|
+ serial_number = request_dict.get("serialNumber", None)
|
|
|
+
|
|
|
+ if not all([id, serial_number, expire_time]):
|
|
|
+ return response.json(444)
|
|
|
+ try:
|
|
|
+ ud_qs = UnicomDeviceInfo.objects.filter(serial_no=serial_number).values('iccid', 'card_type')
|
|
|
+ package_list = []
|
|
|
+ if not ud_qs.exists():
|
|
|
+ return response.json(0, {'packageList': package_list})
|
|
|
+
|
|
|
+ card_type = ud_qs[0]['card_type']
|
|
|
+ if card_type == 0 or card_type == 3:
|
|
|
+ UnicomComboOrderInfo.objects.filter(pk=id).update(expire_time=expire_time)
|
|
|
+ return response.json(0)
|
|
|
+ else:
|
|
|
+ return response.json(177, "这个类型的卡不能更改过期时间")
|
|
|
+
|
|
|
+ except Exception as e:
|
|
|
+ LOGGER.info('UnicomManageControllerView.update_expiration_date, errLine:{}, errMsg:{}'.format(
|
|
|
+ e.__traceback__.tb_lineno, repr(e)))
|
|
|
+ return response.json(500)
|
|
|
+
|
|
|
+ @classmethod
|
|
|
+ def verify_package_export_excel(cls, request, request_dict, response):
|
|
|
+ """
|
|
|
+ 验证套餐导出excel
|
|
|
+ @param request_dict:
|
|
|
+ @param request:
|
|
|
+ @param response: 响应对象
|
|
|
+ @return:
|
|
|
+ """
|
|
|
+ try:
|
|
|
+ serial_list = []
|
|
|
+ file = request.FILES['serialFile']
|
|
|
+ for line in file:
|
|
|
+ serial_number = line.decode().strip()[0:9]
|
|
|
+ serial_list.append(serial_number)
|
|
|
+ total_count = len(serial_list)
|
|
|
+ pages = ceil(total_count / 100)
|
|
|
+
|
|
|
+ package_list = []
|
|
|
+ # 遍历每一页,使用列表切片处理批次
|
|
|
+ for page in range(pages):
|
|
|
+ start = page * 100
|
|
|
+ end = (page + 1) * 100
|
|
|
+ serial_list_batch = serial_list[start:end]
|
|
|
+ # 获取设备信息
|
|
|
+ pck_qs = SerialNumberPackage.objects.filter(serial_number__in=serial_list_batch) \
|
|
|
+ .values('serial_number', 'package_id')
|
|
|
+ if not pck_qs.exists():
|
|
|
+ return response.json(0)
|
|
|
+ for item in pck_qs:
|
|
|
+ package_list.append(item)
|
|
|
+
|
|
|
+ combo_list = list(UnicomCombo.objects.filter(is_del=False).values('id', 'combo_name'))
|
|
|
+
|
|
|
+ # 创建一个新的excel文档
|
|
|
+ wb = openpyxl.Workbook()
|
|
|
+ # 获取默认的工作表
|
|
|
+ sheet = wb.active
|
|
|
+ sheet.title = '套餐核对'
|
|
|
+ sheet.column_dimensions['A'].width = 20
|
|
|
+ sheet.column_dimensions['B'].width = 20
|
|
|
+ sheet.column_dimensions['C'].width = 20
|
|
|
+ sheet.column_dimensions['D'].width = 20
|
|
|
+
|
|
|
+ for i, item in enumerate(package_list):
|
|
|
+ combo_name = next((combo['combo_name'] for combo in combo_list if combo['id'] == item['package_id']),
|
|
|
+ None)
|
|
|
+ u_device_qs = UnicomDeviceInfo.objects.filter(serial_no=item['serial_number']).values('card_type',
|
|
|
+ 'iccid')
|
|
|
+ sheet.cell(row=i + 1, column=1, value=item['serial_number'])
|
|
|
+ if u_device_qs.exists():
|
|
|
+ card_name = ''
|
|
|
+ if u_device_qs[0]['card_type'] == 0:
|
|
|
+ card_name = '珠海联通'
|
|
|
+ elif u_device_qs[0]['card_type'] == 1:
|
|
|
+ card_name = '五兴电信'
|
|
|
+ sheet.cell(row=i + 1, column=2, value=card_name)
|
|
|
+ sheet.cell(row=i + 1, column=3, value=u_device_qs[0]['iccid'])
|
|
|
+ sheet.cell(row=i + 1, column=4, value=combo_name)
|
|
|
+
|
|
|
+ filename = '序列号流量套餐核对-{}.xlsx'.format(len(package_list))
|
|
|
+ # 创建一个http响应
|
|
|
+ res = HttpResponse(content_type='application/vnd.ms-excel')
|
|
|
+ # 设置响应头,告诉浏览器文件要下载而不是直接打开
|
|
|
+ res['Content-Disposition'] = 'attachment; filename={}'.format(filename)
|
|
|
+ # 将excel文档保存到http响应中
|
|
|
+ wb.save(res)
|
|
|
+ return res
|
|
|
+ except Exception as e:
|
|
|
+ LOGGER.info('*****UnicomManageController.package_cdk_export_excel:errLine:{}, errMsg:{}'
|
|
|
+ .format(e.__traceback__.tb_lineno, repr(e)))
|
|
|
+ return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
|