#!/usr/bin/env python3 # -*- coding: utf-8 -*- import json import logging import random import time 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, UserUIDModel, CompanySerialModel, \ MacModel, LogModel 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 from Service.ModelService import ModelService 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': return self.do_quantity(request_dict,token.userID, response) elif operation == 'allot': return self.do_allot(request_dict, response) else: return response.json(309) # 查询当前可用的UID的数量 def do_quantity(self, request_dict, userID, response): user_qs = UserModel.objects.filter(id=userID) if not user_qs.exists(): 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')) chenyundev = result['num'] unused_serial_number_count = SerialNumberModel.objects.filter(use_status=0).count() chenyun = SerialNumberModel.objects.filter(use_status=1).count() res_data = {'code': 0, 'chenyun': chenyun, 'unused_serial_number_count': unused_serial_number_count, 'chenyundev': chenyundev} return response.json(0, {'data': res_data}) 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=0)[0:quantity] sns = [] for sn in sn_qs: sns.append(sn.serial_number) cs_qs = CompanySerialModel.objects.filter(serial_number__in=sns, status=1) 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, '序列号不足') 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 ) 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) # 提供给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) key = 'serial_lock' value = redisObj.lpop(key) count = 0 while value is False and count < 5: time.sleep(1) value = redisObj.lpop(key) count += 1 if count == 5 and value is False: # 暂时注释 return response.json(5) userid = '3' user_qs = UserModel.objects.filter(id=userid) if not user_qs.exists(): redisObj.rpush(key, value) 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'] sn_qs = SerialNumberModel.objects.filter(serial_number__in=sns) if not sn_qs.exists(): return response.json(444, '序列号不足') count = result['num'] if count < quantity: redisObj.rpush(key, value) 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) # 记录操作日志 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解锁 redisObj.rpush(key, value) return response.json(0, {'serial_number': serial_number + mark, 'mac': mac}) except Exception as e: return response.json(500, repr(e))