#!/usr/bin/env python3 # -*- coding: utf-8 -*- import json import logging import time import requests from bulk_update.helper import bulk_update from django.db import transaction from django.db.models import Count from django.views import View from Model.models import SerialNumberModel, UserModel, UserSerialNumberModel, CompanySerialModel, \ MacModel, LogModel, CompanyModel from Object.RedisObject import RedisObject from Object.ResponseObject import ResponseObject from Object.TokenObject import TokenObject from Service.AlgorithmService import AlgorithmBaseOn35 from Service.CommonService import CommonService class SerialNumberView(View): def get(self, request, *args, **kwargs): request.encoding = 'utf-8' request_dict = request.GET operation = kwargs.get('operation') return self.validate(request_dict, operation, request) def post(self, request, *args, **kwargs): request.encoding = 'utf-8' request_dict = request.POST operation = kwargs.get('operation') return self.validate(request_dict, operation, request) def validate(self, request_dict, operation, request): response = ResponseObject() if operation == 'create': return self.do_create(request_dict, response) elif operation == 'getSerial': return self.do_get_serial_number(request_dict, request, response) token = request_dict.get('token', None) token = TokenObject(token) if token.code != 0: return response.json(token.code) if operation == 'quantity': # 查询当前可用的UID的数量 return self.do_quantity(token.userID, response) elif operation == 'allot': return self.do_allot(request_dict, response) elif operation == 'createSerial': # 生成序列号 return self.create_serial(request_dict, response, request) elif operation == 'serialCompany': # 将序列号分匹配到指定企业 return self.do_serial_company(request_dict, response, request) elif operation == 'revise/state': # 修改序列号状态 return self.revise_state(request_dict, response, request) else: return response.json(309) def revise_state(self, request_dict, response, request): """ 修改序列号状态 @param request_dict:请求参数 @param response: 响应对象 """ use_status = request_dict.get('useStatus', None) # 序列号表的状态 status = request_dict.get('status', None) # 关联企业序列号表的状态 if not all([use_status, status]): return response.json(444) serial_number_qs = SerialNumberModel.objects.filter(use_status=use_status).values('serial_number') if not serial_number_qs.exists(): return response.json(173) serial_list = [item[key] for item in serial_number_qs for key in item] try: country_serial_qs = CompanySerialModel.objects.filter(serial_number__in=serial_list).values('status') country_serial_qs.filter(status=status).update(status=2) return response.json(0) except Exception as e: print(e) return response.json(500) def do_serial_company(self, request_dict, response, request): """ 将序列号分匹配到指定企业 :param request_dict: 请求参数 :param response: 响应对象 :param request: 请求 :return: """ id = request_dict.get('id', None) quantity = request_dict.get('quantity', None) if not all([id, quantity]): return response.json(444) company_qs = CompanyModel.objects.filter(id=id) if not company_qs.exists(): return response.json(444) sum_Serial = SerialNumberModel.objects.filter().count() sum_Serial_company = CompanySerialModel.objects.filter().count() sum_bind = sum_Serial - sum_Serial_company # 剩余可绑定的序列号 if int(quantity) > int(sum_bind): return response.json(10041) try: company = company_qs[0] start_1 = sum_Serial_company end_1 = int(start_1) + int(quantity) serial_qs = SerialNumberModel.objects.filter()[start_1:end_1] if not serial_qs.exists(): return response.json(173) company_serial_bulk = [] now_time = int(time.time()) for item in serial_qs: # 更新状态为已分配但未使用 company_serial_bulk.append(CompanySerialModel( status=3, add_time=now_time, update_time=now_time, company_id=company.id, serial_number=item.serial_number, )) SerialNumberModel.objects.filter(serial_number=item.serial_number).update( use_status=3, add_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': now_time, 'url': 'serialNumber/serialCompany', 'content': json.dumps(content), 'operation': '{}生成{}个Company Serial{}: {}'.format(company.name, quantity, '成功', '同步更新成功'), } with transaction.atomic(): CompanySerialModel.objects.bulk_create(company_serial_bulk) company.quantity = CompanySerialModel.objects.filter(company_id=id).count() company.save() Log = LogModel.objects.create(**log) # 同步更新业务服务器和uid管理系统的企业序列号表 url1 = 'http://test.zositechc.cn/company/createSerial' url2 = 'https://www.zositechc.cn/company/createSerial' url3 = 'http://www.dvema.com/company/createSerial' # url4 = 'http://www.zositeche.com/company/createSerial' requests_data = {'id': id, 'quantity': quantity} res1 = requests.post(url=url1, data=requests_data, timeout=2 * 60) if res1.status_code != 200: fail_reason = '请求测试服务器生成Company Serial响应状态码异常' return self.failResponse(company.name, quantity, fail_reason, Log, response) res1 = res1.json() if res1['result_code'] != 0: fail_reason = '测试服务器生成Company Serial发生异常' return self.failResponse(company.name, quantity, fail_reason, Log, response) res2 = requests.post(url=url2, data=requests_data, timeout=2 * 60) if res2.status_code != 200: fail_reason = '请求国内服务器生成Company Serial响应状态码异常' return self.failResponse(company.name, quantity, fail_reason, Log, response) res2 = res2.json() if res2['result_code'] != 0: fail_reason = '国内服务器生成Company Serial发生异常' return self.failResponse(company.name, quantity, fail_reason, Log, response) res3 = requests.post(url=url3, data=requests_data, timeout=2 * 60) if res3.status_code != 200: fail_reason = '请求美国服务器生成Company Serial响应状态码异常' return self.failResponse(company.name, quantity, fail_reason, Log, response) res3 = res3.json() if res3['result_code'] != 0: fail_reason = '美国服务器生成Company Serial发生异常' return self.failResponse(company.name, quantity, fail_reason, Log, response) # res4 = requests.post(url=url4, data=requests_data, timeout=2 * 60) # if res4.status_code != 200: # fail_reason = '请求欧洲服务器生成Company Serial响应状态码异常' # return self.failResponse(company.name, quantity, fail_reason, Log, response) # res4 = res4.json() # if res4['code'] != 0: # fail_reason = '欧洲服务器生成Company Serial发生异常' # return self.failResponse(company.name, quantity, fail_reason, Log, response) return response.json(0) except Exception as e: djangoLogger = logging.getLogger('django') djangoLogger.exception(repr(e)) return response.json(176) def failResponse(self, company_name, quantity, fail_reason, Log, response): operation = '{}生成{}个Company Serial{}: {}'.format(company_name, quantity, '失败', fail_reason) Log.operation = operation Log.save() return response.json(177) def create_serial(self, request_dict, response, request): """ 生成序列号 :param request_dict: 请求参数 :param response: 响应对象 :param request: 请求 :return: """ quantity = int(request_dict.get('quantity', 0)) if not quantity: return response.json(444) try: try: sum = SerialNumberModel.objects.last().id except: sum = 0 serial_number_bulk = [] now_time = int(time.time()) algorithm = AlgorithmBaseOn35() for i in range(quantity): serial_number = algorithm.getLetter(sum) sum += 1 # sum每次递增1 # 前面补0至六位 serial_number = (6 - len(serial_number)) * '0' + serial_number serial_number_bulk.append(SerialNumberModel(serial_number=serial_number, add_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': now_time, 'url': 'serialNumber/createSerial', 'content': json.dumps(content), 'operation': '生成{}个Serial Number{}: {}'.format(quantity, '成功', '同步更新成功'), } # 开启事务写入 with transaction.atomic(): SerialNumberModel.objects.bulk_create(serial_number_bulk) Log = LogModel.objects.create(**log) # 同步更新业务服务器和uid管理系统的序列号表 url1 = 'http://test.zositechc.cn/serialNumber/create' url2 = 'https://www.zositechc.cn/serialNumber/create' url3 = 'http://www.dvema.com/serialNumber/create' # url4 = 'http://www.zositeche.com/company/createSerial' requests_data = {'quantity': quantity} res1 = requests.post(url=url1, data=requests_data, timeout=2 * 60) if res1.status_code != 200: fail_reason = '请求测试服务器生成Serial Number响应状态码异常' return self.generateFail(quantity, fail_reason, Log, response) res1 = res1.json() if res1['result_code'] != 0: fail_reason = '测试服务器生成Serial Number发生异常' return self.generateFail(quantity, fail_reason, Log, response) res2 = requests.post(url=url2, data=requests_data, timeout=2 * 60) if res2.status_code != 200: fail_reason = '请求国内服务器生成Serial Number响应状态码异常' return self.generateFail(quantity, fail_reason, Log, response) res2 = res2.json() if res2['result_code'] != 0: fail_reason = '国内服务器生成Serial Number发生异常' return self.generateFail(quantity, fail_reason, Log, response) res3 = requests.post(url=url3, data=requests_data, timeout=2 * 60) if res3.status_code != 200: fail_reason = '请求美国服务器生成Serial Number响应状态码异常' return self.generateFail(quantity, fail_reason, Log, response) res3 = res3.json() if res3['result_code'] != 0: fail_reason = '美国服务器生成Serial Number发生异常' return self.generateFail(quantity, fail_reason, Log, response) # res4 = requests.post(url=url4, data=requests_data, timeout=2 * 60) # if res4.status_code != 200: # fail_reason = '请求欧洲服务器生成Company Serial响应状态码异常' # return self.generateFail(quantity, fail_reason, Log, response) # res4 = res4.json() # if res4['code'] != 0: # fail_reason = '欧洲服务器生成Company Serial发生异常' # return self.generateFail(quantity, fail_reason, Log, response) return response.json(0) except Exception as e: djangoLogger = logging.getLogger('django') djangoLogger.exception(repr(e)) return response.json(176) def generateFail(self, quantity, fail_reason, Log, response): operation = '生成{}个Serial Number{}: {}'.format(quantity, '失败', fail_reason) Log.operation = operation Log.save() return response.json(177) def do_quantity(self, userID, response): """ 查询当前可用的UID的数量 :param userID: 响应对象 :param response: 请求 :return: """ user_qs = UserModel.objects.filter(id=userID) if not user_qs.exists(): return response.json(9) unused_serial_number_count = SerialNumberModel.objects.filter(use_status=0).count() remain_qs = CompanySerialModel.objects.filter(status=1).count() company_qs = CompanyModel.objects.values('id', 'name') try: company_serial_list = [] # 剩余已分配未使用的序列号数量 company_not_used_list = [] # 已使用的序列号数量 for company in company_qs: id = company['id'] name = company['name'] not_used_qs = CompanySerialModel.objects.filter(status=3, company_id=id).count() res = { 'name': name, 'number': not_used_qs } company_not_used_list.append(res) for company in company_qs: id = company['id'] name = company['name'] company_serial_qs = CompanySerialModel.objects.filter(status=1, company_id=id).values( 'serial_number').order_by('serial_number') company_used_qs = company_serial_qs.count() serial_list = [item[key] for item in company_serial_qs for key in item] last_serial = serial_list[-1] if company_serial_qs.exists() else '' res = { 'name': name, 'numbers': company_used_qs, 'lastSerial': last_serial } company_serial_list.append(res) res_data = {'code': 0, 'companyRemainCount': company_not_used_list, 'companyRemain': company_serial_list, 'unused_serial_number_count': unused_serial_number_count, 'unused_all_count': remain_qs} return response.json(0, {'data': res_data}) except Exception as e: print(e) return response.json(500) def do_create(self, request_dict, response): quantity = int(request_dict.get('quantity', 0)) if not quantity: return response.json(444) try: try: sum = SerialNumberModel.objects.last().id except: sum = 0 serial_number_bulk = [] now_time = int(time.time()) algorithm = AlgorithmBaseOn35() for i in range(quantity): serial_number = algorithm.getLetter(sum) sum += 1 # sum每次递增1 # 前面补0至六位 serial_number = (6 - len(serial_number)) * '0' + serial_number serial_number_bulk.append(SerialNumberModel(serial_number=serial_number, add_time=now_time)) # 开启事务写入 with transaction.atomic(): SerialNumberModel.objects.bulk_create(serial_number_bulk) return response.json(0) except Exception as e: print(e) return response.json(500, repr(e)) # 分配序列号 @transaction.atomic def do_allot(self, request_dict, response): username = request_dict.get('username', None) quantity = int(request_dict.get('quantity', None)) token = request_dict.get('token', None) token = TokenObject(token) if token.code != 0: return response.json(token.code) user = UserModel.objects.get(id=token.userID) if not user or '0' not in user.permission: return response.json(404) # 要分配的对象 allot_user_qs = UserModel.objects.filter(username=username) if not allot_user_qs.exists(): return response.json(444, 'username') # 取出对应区域可用的UID分配给allot_user sn_qs = SerialNumberModel.objects.filter(use_status=3)[0:quantity] sns = [] for sn in sn_qs: sns.append(sn.serial_number) cs_qs = CompanySerialModel.objects.filter(serial_number__in=sns, status=3) sns = [] for cs in cs_qs: sns.append(cs.serial_number) sn_qs = SerialNumberModel.objects.filter(serial_number__in=sns) count = sn_qs.count() if count < quantity: return response.json(444, '序列号不足') try: updates = [] datas = [] count = 0 if sn_qs.exists(): sn_qs = sn_qs[0:quantity] now_time = int(time.time()) for i in range(len(sn_qs)): item = sn_qs[i] serialNumberModel = SerialNumberModel( id=item.id, serial_number=item.serial_number, status=item.status, use_status=1, add_time=item.add_time ) CompanySerialModel.objects.filter(serial_number=item.serial_number).update(status=1) user_serial_number = UserSerialNumberModel() user_serial_number.serial_number = serialNumberModel user_serial_number.user = allot_user_qs[0] user_serial_number.add_time = now_time user_serial_number.update_time = now_time datas.append(user_serial_number) updates.append(serialNumberModel) if len(updates) % 5000 == 0: bulk_update(updates) UserSerialNumberModel.objects.bulk_create(datas) if len(updates) > 0: bulk_update(updates) UserSerialNumberModel.objects.bulk_create(datas) del datas del updates return response.json(0) else: return response.json(444) except Exception as e: print(e) return response.json(500) # 提供给pc端获取序列号 def do_get_serial_number(self, request_dict, request, response): quantity = 1 # 只能取一个 company_id = request_dict.get('company_id', None) token = request_dict.get('token', None) time_stamp = request_dict.get('time_stamp', None) mac = request_dict.get('mac', None) if not all([token, time_stamp, company_id]): return response.json(444) token = int(CommonService.decode_data(token)) time_stamp = int(time_stamp) now_time = int(time.time()) distance = now_time - time_stamp if token != time_stamp or distance > 60000 or distance < -60000: # 为了全球化时间控制在一天内 return response.json(404) redisObj = RedisObject() # redis加锁,防止同时进行其他操作 serial_operate_lock_key = 'serial_operate_lock' isLock = redisObj.CONN.setnx(serial_operate_lock_key, 1) if not isLock: return response.json(5) redisObj.CONN.expire(serial_operate_lock_key, 60) user_qs = UserModel.objects.filter(id=3) if not user_qs.exists(): redisObj.del_data(key=serial_operate_lock_key) # redis解锁 return response.json(9) user = user_qs[0] result = UserSerialNumberModel.objects.filter(user__id=user.id, serial_number__use_status=1). \ aggregate(num=Count('serial_number__use_status')) us_qs = UserSerialNumberModel.objects.filter(user__id=user.id, serial_number__use_status=1). \ values('serial_number__serial_number') sns = [] for us in us_qs: sns.append(us['serial_number__serial_number']) cs_qs = CompanySerialModel.objects.filter(serial_number__in=sns, status=1, company__secret=company_id).values( 'serial_number', 'company__mark') sns = [] mark = "" if cs_qs.exists(): for cs in cs_qs: sns.append(cs['serial_number']) mark = cs_qs[0]['company__mark'] # 判断是否还有可用的序列号 count = result['num'] sn_qs = SerialNumberModel.objects.filter(serial_number__in=sns) if not sn_qs.exists() or count < quantity: redisObj.del_data(key=serial_operate_lock_key) # redis解锁 return response.json(444, '序列号不足') try: with transaction.atomic(): # 开启事务 sn_qs = sn_qs[0: quantity] serial_number = sn_qs[0].serial_number # 防止重复获取序列号 is_lock = redisObj.CONN.setnx(serial_number + 'serial_number_lock', 1) redisObj.CONN.expire(serial_number + 'serial_number_lock', 60) if not is_lock: return response.json(5) if not mac: # 不传入则分配mac mac_qs = MacModel.objects.filter().values('id', 'value', 'is_active')[0] if not mac_qs['is_active']: return response.json(175) mac = mac_qs['value'] # 绑定mac地址成功后更新mac表 next_mac = CommonService.updateMac(mac) # mac地址值+1;后3个字节为FF时返回None if next_mac: MacModel.objects.filter().update(value=next_mac, update_time=now_time) # 更新mac表的mac地址值 else: MacModel.objects.filter().update(is_active=False, update_time=now_time) # 更新序列号表数据 serialNumberModel = SerialNumberModel( id=sn_qs[0].id, serial_number=serial_number, status=sn_qs[0].status, use_status=2, add_time=now_time ) updates = [] updates.append(serialNumberModel) bulk_update(updates) # 更新企业关联序列号状态 CompanySerialModel.objects.filter(serial_number=serial_number).update(status=2, update_time=now_time) # 记录操作日志 ip = CommonService.get_ip_address(request) content = json.loads(json.dumps(request.POST)) operation = '获取序列号:{}'.format(serial_number) log = { 'status': 200, 'content': json.dumps(content), 'ip': ip, 'time': now_time, 'url': 'serialNumber/getSerial', 'operation': operation, 'user': user_qs[0] } LogModel.objects.create(**log) redisObj.del_data(key=serial_operate_lock_key) # redis解锁 return response.json(0, {'serial_number': serial_number + mark, 'mac': mac}) except Exception as e: redisObj.del_data(key=serial_operate_lock_key) # redis解锁 return response.json(500, repr(e))