SerialNumberController.py 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  1. import json
  2. import logging
  3. import time
  4. import requests
  5. from bulk_update.helper import bulk_update
  6. from django.db import transaction
  7. from django.views import View
  8. from Model.models import SerialNumberModel, UserModel, UserSerialNumberModel, CompanySerialModel, \
  9. MacModel, LogModel, CompanyModel
  10. from Object.RedisObject import RedisObject
  11. from Object.ResponseObject import ResponseObject
  12. from Object.S3Email import S3Email
  13. from Object.TokenObject import TokenObject
  14. from Service.AlgorithmService import AlgorithmBaseOn35
  15. from Service.CommonService import CommonService
  16. class SerialNumberView(View):
  17. def get(self, request, *args, **kwargs):
  18. request.encoding = 'utf-8'
  19. request_dict = request.GET
  20. operation = kwargs.get('operation')
  21. return self.validate(request_dict, operation, request)
  22. def post(self, request, *args, **kwargs):
  23. request.encoding = 'utf-8'
  24. request_dict = request.POST
  25. operation = kwargs.get('operation')
  26. return self.validate(request_dict, operation, request)
  27. def validate(self, request_dict, operation, request):
  28. response = ResponseObject()
  29. if operation == 'getSerial': # 获取序列号
  30. return self.get_serial(request_dict, response)
  31. elif operation == 'create': # 生成序列号
  32. return self.do_create(request_dict, response)
  33. elif operation == 'mac': # 生成mac
  34. return self.generate_mac(request_dict, response)
  35. elif operation == 'checkSerial': # 序列号库存数量少于2000,发送邮件通知
  36. return self.check_serial_number(response)
  37. token = request_dict.get('token', None)
  38. token = TokenObject(token)
  39. if token.code != 0:
  40. return response.json(token.code)
  41. if operation == 'quantity': # 查询当前可用的UID的数量
  42. return self.do_quantity(token.userID, response)
  43. elif operation == 'allot': # 分配序列号
  44. return self.do_allot(request_dict, response)
  45. elif operation == 'createSerial': # 生成序列号
  46. return self.create_serial(request_dict, response, request, token.userID)
  47. elif operation == 'serialCompany': # 将序列号分匹配到指定企业
  48. return self.do_serial_company(request_dict, response, request, token.userID)
  49. elif operation == 'revise/state': # 修改序列号状态
  50. return self.revise_state(request_dict, response, request)
  51. else:
  52. return response.json(309)
  53. def revise_state(self, request_dict, response, request):
  54. """
  55. 修改序列号状态
  56. @param request_dict:请求参数
  57. @param response: 响应对象
  58. """
  59. use_status = request_dict.get('useStatus', None) # 序列号表的状态
  60. status = request_dict.get('status', None) # 关联企业序列号表的状态
  61. if not all([use_status, status]):
  62. return response.json(444)
  63. serial_number_qs = SerialNumberModel.objects.filter(use_status=use_status).values('serial_number')
  64. if not serial_number_qs.exists():
  65. return response.json(173)
  66. serial_list = [item[key] for item in serial_number_qs for key in item]
  67. try:
  68. country_serial_qs = CompanySerialModel.objects.filter(serial_number__in=serial_list).values('status')
  69. country_serial_qs.filter(status=status).update(status=2)
  70. return response.json(0)
  71. except Exception as e:
  72. print(e)
  73. return response.json(500)
  74. def do_serial_company(self, request_dict, response, request, user_id):
  75. """
  76. 将序列号分匹配到指定企业
  77. :param request_dict: 请求参数
  78. :param response: 响应对象
  79. :param request: 请求
  80. :param user_id: 用户id
  81. :return:
  82. """
  83. id = request_dict.get('id', None)
  84. quantity = request_dict.get('quantity', None)
  85. if not all([id, quantity]):
  86. return response.json(444)
  87. company_qs = CompanyModel.objects.filter(id=id)
  88. if not company_qs.exists():
  89. return response.json(444)
  90. sum_Serial = SerialNumberModel.objects.filter().count()
  91. sum_Serial_company = CompanySerialModel.objects.filter().count()
  92. sum_bind = sum_Serial - sum_Serial_company # 剩余可绑定的序列号
  93. if int(quantity) > int(sum_bind):
  94. return response.json(10041)
  95. try:
  96. company = company_qs[0]
  97. start_1 = sum_Serial_company
  98. end_1 = int(start_1) + int(quantity)
  99. serial_qs = SerialNumberModel.objects.filter()[start_1:end_1]
  100. if not serial_qs.exists():
  101. return response.json(173)
  102. company_serial_bulk = []
  103. now_time = int(time.time())
  104. for item in serial_qs: # 更新状态为已分配但未使用
  105. company_serial_bulk.append(CompanySerialModel(
  106. status=3,
  107. add_time=now_time,
  108. update_time=now_time,
  109. company_id=company.id,
  110. serial_number=item.serial_number,
  111. ))
  112. SerialNumberModel.objects.filter(serial_number=item.serial_number).update(
  113. use_status=3,
  114. add_time=now_time
  115. )
  116. # 记录操作日志
  117. ip = CommonService.get_ip_address(request)
  118. content = json.loads(json.dumps(request_dict))
  119. log = {
  120. 'ip': ip,
  121. 'user_id': user_id,
  122. 'status': 200,
  123. 'time': now_time,
  124. 'url': 'serialNumber/serialCompany',
  125. 'content': json.dumps(content),
  126. 'operation': '{}生成{}个序列号{}: {}'.format(company.name, quantity, '成功', '同步更新成功'),
  127. }
  128. with transaction.atomic():
  129. CompanySerialModel.objects.bulk_create(company_serial_bulk)
  130. company.quantity = CompanySerialModel.objects.filter(company_id=id).count()
  131. company.save()
  132. Log = LogModel.objects.create(**log)
  133. # 同步更新业务服务器和uid管理系统的企业序列号表
  134. url1 = 'http://test.zositechc.cn/company/createSerial'
  135. url2 = 'https://www.zositechc.cn/company/createSerial'
  136. url3 = 'http://www.dvema.com/company/createSerial'
  137. # url4 = 'http://www.zositeche.com/company/createSerial'
  138. requests_data = {'id': id, 'quantity': quantity}
  139. res1 = requests.post(url=url1, data=requests_data, timeout=2 * 60)
  140. if res1.status_code != 200:
  141. fail_reason = '请求测试服务器生成序列号响应状态码异常'
  142. return self.failResponse(company.name, quantity, fail_reason, Log, response)
  143. res1 = res1.json()
  144. if res1['result_code'] != 0:
  145. fail_reason = '测试服务器生成序列号发生异常'
  146. return self.failResponse(company.name, quantity, fail_reason, Log, response)
  147. res2 = requests.post(url=url2, data=requests_data, timeout=2 * 60)
  148. if res2.status_code != 200:
  149. fail_reason = '请求国内服务器生成序列号响应状态码异常'
  150. return self.failResponse(company.name, quantity, fail_reason, Log, response)
  151. res2 = res2.json()
  152. if res2['result_code'] != 0:
  153. fail_reason = '国内服务器生成序列号发生异常'
  154. return self.failResponse(company.name, quantity, fail_reason, Log, response)
  155. res3 = requests.post(url=url3, data=requests_data, timeout=2 * 60)
  156. if res3.status_code != 200:
  157. fail_reason = '请求美国服务器生成序列号响应状态码异常'
  158. return self.failResponse(company.name, quantity, fail_reason, Log, response)
  159. res3 = res3.json()
  160. if res3['result_code'] != 0:
  161. fail_reason = '美国服务器生成序列号发生异常'
  162. return self.failResponse(company.name, quantity, fail_reason, Log, response)
  163. # res4 = requests.post(url=url4, data=requests_data, timeout=2 * 60)
  164. # if res4.status_code != 200:
  165. # fail_reason = '请求欧洲服务器生成序列号响应状态码异常'
  166. # return self.failResponse(company.name, quantity, fail_reason, Log, response)
  167. # res4 = res4.json()
  168. # if res4['code'] != 0:
  169. # fail_reason = '欧洲服务器生成序列号发生异常'
  170. # return self.failResponse(company.name, quantity, fail_reason, Log, response)
  171. return response.json(0)
  172. except Exception as e:
  173. djangoLogger = logging.getLogger('django')
  174. djangoLogger.exception(repr(e))
  175. return response.json(176)
  176. def failResponse(self, company_name, quantity, fail_reason, Log, response):
  177. operation = '{}生成{}个序列号{}: {}'.format(company_name, quantity, '失败', fail_reason)
  178. Log.operation = operation
  179. Log.save()
  180. return response.json(177)
  181. def create_serial(self, request_dict, response, request, user_id):
  182. """
  183. 生成序列号
  184. :param request_dict: 请求参数
  185. :param response: 响应对象
  186. :param request: 请求
  187. :param user_id: 用户id
  188. :return:
  189. """
  190. quantity = int(request_dict.get('quantity', 0))
  191. if not quantity:
  192. return response.json(444)
  193. try:
  194. try:
  195. sum = SerialNumberModel.objects.last().id
  196. except:
  197. sum = 0
  198. serial_number_bulk = []
  199. now_time = int(time.time())
  200. algorithm = AlgorithmBaseOn35()
  201. for i in range(quantity):
  202. serial_number = algorithm.getLetter(sum)
  203. sum += 1 # sum每次递增1
  204. # 前面补0至六位
  205. serial_number = (6 - len(serial_number)) * '0' + serial_number
  206. serial_number_bulk.append(SerialNumberModel(serial_number=serial_number, add_time=now_time))
  207. # 记录操作日志
  208. ip = CommonService.get_ip_address(request)
  209. content = json.loads(json.dumps(request_dict))
  210. log = {
  211. 'ip': ip,
  212. 'user_id': user_id,
  213. 'status': 200,
  214. 'time': now_time,
  215. 'url': 'serialNumber/createSerial',
  216. 'content': json.dumps(content),
  217. 'operation': '生成{}个序列号{}: {}'.format(quantity, '成功', '同步更新成功'),
  218. }
  219. # 开启事务写入
  220. with transaction.atomic():
  221. SerialNumberModel.objects.bulk_create(serial_number_bulk)
  222. Log = LogModel.objects.create(**log)
  223. # 同步更新业务服务器和uid管理系统的序列号表
  224. url1 = 'http://test.zositechc.cn/serialNumber/create'
  225. url2 = 'https://www.zositechc.cn/serialNumber/create'
  226. url3 = 'http://www.dvema.com/serialNumber/create'
  227. # url4 = 'http://www.zositeche.com/company/createSerial'
  228. requests_data = {'quantity': quantity}
  229. res1 = requests.post(url=url1, data=requests_data, timeout=2 * 60)
  230. if res1.status_code != 200:
  231. fail_reason = '请求测试服务器生成序列号响应状态码异常'
  232. return self.generateFail(quantity, fail_reason, Log, response)
  233. res1 = res1.json()
  234. if res1['result_code'] != 0:
  235. fail_reason = '测试服务器生成序列号发生异常'
  236. return self.generateFail(quantity, fail_reason, Log, response)
  237. res2 = requests.post(url=url2, data=requests_data, timeout=2 * 60)
  238. if res2.status_code != 200:
  239. fail_reason = '请求国内服务器生成序列号响应状态码异常'
  240. return self.generateFail(quantity, fail_reason, Log, response)
  241. res2 = res2.json()
  242. if res2['result_code'] != 0:
  243. fail_reason = '国内服务器生成序列号发生异常'
  244. return self.generateFail(quantity, fail_reason, Log, response)
  245. res3 = requests.post(url=url3, data=requests_data, timeout=2 * 60)
  246. if res3.status_code != 200:
  247. fail_reason = '请求美国服务器生成序列号响应状态码异常'
  248. return self.generateFail(quantity, fail_reason, Log, response)
  249. res3 = res3.json()
  250. if res3['result_code'] != 0:
  251. fail_reason = '美国服务器生成序列号发生异常'
  252. return self.generateFail(quantity, fail_reason, Log, response)
  253. # res4 = requests.post(url=url4, data=requests_data, timeout=2 * 60)
  254. # if res4.status_code != 200:
  255. # fail_reason = '请求欧洲服务器生成序列号响应状态码异常'
  256. # return self.generateFail(quantity, fail_reason, Log, response)
  257. # res4 = res4.json()
  258. # if res4['code'] != 0:
  259. # fail_reason = '欧洲服务器生成序列号发生异常'
  260. # return self.generateFail(quantity, fail_reason, Log, response)
  261. return response.json(0)
  262. except Exception as e:
  263. djangoLogger = logging.getLogger('django')
  264. djangoLogger.exception(repr(e))
  265. return response.json(176)
  266. def generateFail(self, quantity, fail_reason, Log, response):
  267. operation = '生成{}个序列号{}: {}'.format(quantity, '失败', fail_reason)
  268. Log.operation = operation
  269. Log.save()
  270. return response.json(177)
  271. def do_quantity(self, userID, response):
  272. """
  273. 查询当前可用的UID的数量
  274. :param userID: 响应对象
  275. :param response: 请求
  276. :return:
  277. """
  278. user_qs = UserModel.objects.filter(id=userID)
  279. if not user_qs.exists():
  280. return response.json(9)
  281. unused_serial_number_count = SerialNumberModel.objects.filter(use_status=0).count()
  282. remain_qs = CompanySerialModel.objects.filter(status=1).count()
  283. company_qs = CompanyModel.objects.values('id', 'name')
  284. try:
  285. company_serial_list = [] # 剩余已分配未使用的序列号数量
  286. company_not_used_list = [] # 已使用的序列号数量
  287. for company in company_qs:
  288. id = company['id']
  289. name = company['name']
  290. not_used_qs = CompanySerialModel.objects.filter(status=3, company_id=id).count()
  291. res = {
  292. 'name': name,
  293. 'number': not_used_qs
  294. }
  295. company_not_used_list.append(res)
  296. for company in company_qs:
  297. id = company['id']
  298. name = company['name']
  299. count = CompanySerialModel.objects.filter(status=1, company_id=id).count()
  300. # 获取最后一个序列号
  301. if count == 0:
  302. last_serial = ''
  303. else:
  304. last_serial = CompanySerialModel.objects.filter(status=1, company_id=id).order_by('-id').values(
  305. 'serial_number')[:1][0]['serial_number']
  306. res = {
  307. 'name': name,
  308. 'numbers': count,
  309. 'lastSerial': last_serial
  310. }
  311. company_serial_list.append(res)
  312. res_data = {'code': 0, 'companyRemainCount': company_not_used_list, 'companyRemain': company_serial_list,
  313. 'unused_serial_number_count': unused_serial_number_count,
  314. 'unused_all_count': remain_qs}
  315. return response.json(0, {'data': res_data})
  316. except Exception as e:
  317. print(e)
  318. return response.json(500)
  319. def do_create(self, request_dict, response):
  320. quantity = int(request_dict.get('quantity', 0))
  321. if not quantity:
  322. return response.json(444)
  323. try:
  324. try:
  325. sum = SerialNumberModel.objects.last().id
  326. except:
  327. sum = 0
  328. serial_number_bulk = []
  329. now_time = int(time.time())
  330. algorithm = AlgorithmBaseOn35()
  331. for i in range(quantity):
  332. serial_number = algorithm.getLetter(sum)
  333. sum += 1 # sum每次递增1
  334. # 前面补0至六位
  335. serial_number = (6 - len(serial_number)) * '0' + serial_number
  336. serial_number_bulk.append(SerialNumberModel(serial_number=serial_number, add_time=now_time))
  337. # 开启事务写入
  338. with transaction.atomic():
  339. SerialNumberModel.objects.bulk_create(serial_number_bulk)
  340. return response.json(0)
  341. except Exception as e:
  342. print(e)
  343. return response.json(500, repr(e))
  344. @transaction.atomic
  345. def do_allot(self, request_dict, response):
  346. username = request_dict.get('username', None)
  347. quantity = int(request_dict.get('quantity', None))
  348. token = request_dict.get('token', None)
  349. token = TokenObject(token)
  350. if token.code != 0:
  351. return response.json(token.code)
  352. user = UserModel.objects.get(id=token.userID)
  353. if not user or '0' not in user.permission:
  354. return response.json(404)
  355. # 要分配的对象
  356. allot_user_qs = UserModel.objects.filter(username=username)
  357. if not allot_user_qs.exists():
  358. return response.json(444, 'username')
  359. # 取出对应区域可用的UID分配给allot_user
  360. sn_qs = SerialNumberModel.objects.filter(use_status=3)[0:quantity]
  361. sns = []
  362. for sn in sn_qs:
  363. sns.append(sn.serial_number)
  364. cs_qs = CompanySerialModel.objects.filter(serial_number__in=sns, status=3)
  365. sns = []
  366. for cs in cs_qs:
  367. sns.append(cs.serial_number)
  368. sn_qs = SerialNumberModel.objects.filter(serial_number__in=sns)
  369. count = sn_qs.count()
  370. if count < quantity:
  371. return response.json(444, '序列号不足')
  372. try:
  373. updates = []
  374. datas = []
  375. if not sn_qs.exists():
  376. return response.json(444)
  377. sn_qs = sn_qs[0:quantity]
  378. now_time = int(time.time())
  379. for i in range(len(sn_qs)):
  380. item = sn_qs[i]
  381. serialNumberModel = SerialNumberModel(
  382. id=item.id,
  383. serial_number=item.serial_number,
  384. status=item.status,
  385. use_status=1,
  386. add_time=item.add_time
  387. )
  388. CompanySerialModel.objects.filter(serial_number=item.serial_number).update(status=1)
  389. user_serial_number = UserSerialNumberModel()
  390. user_serial_number.serial_number = serialNumberModel
  391. user_serial_number.user = allot_user_qs[0]
  392. user_serial_number.add_time = now_time
  393. user_serial_number.update_time = now_time
  394. datas.append(user_serial_number)
  395. updates.append(serialNumberModel)
  396. if len(updates) > 0:
  397. bulk_update(updates)
  398. UserSerialNumberModel.objects.bulk_create(datas)
  399. return response.json(0)
  400. except Exception as e:
  401. print(e)
  402. return response.json(500)
  403. @staticmethod
  404. def get_serial(request_dict, response):
  405. """
  406. 获取序列号
  407. @param request_dict: 请求数据
  408. @param response: 响应
  409. @return: response
  410. """
  411. token = request_dict.get('token', None)
  412. time_stamp = request_dict.get('time_stamp', None)
  413. company_secret = request_dict.get('company_id', None)
  414. if not all([token, time_stamp, company_secret]):
  415. return response.json(444)
  416. # 时间戳token校验
  417. if not CommonService.check_time_stamp_token(token, time_stamp):
  418. return response.json(13)
  419. redis_obj = RedisObject()
  420. # redis加锁,防止同时进行其他操作
  421. serial_operate_lock_key = 'serial_operate_lock'
  422. serial_operate_lock = redis_obj.CONN.setnx(serial_operate_lock_key, 1)
  423. if not serial_operate_lock:
  424. return response.json(5)
  425. redis_obj.CONN.expire(serial_operate_lock_key, 60)
  426. # 查询可用的序列号
  427. company_serial_qs = CompanySerialModel.objects.filter(company__secret=company_secret, status=1).first()
  428. if company_serial_qs is None:
  429. redis_obj.del_data(key=serial_operate_lock_key) # redis解锁
  430. return response.json(14)
  431. serial_number = company_serial_qs.serial_number
  432. company_mark = company_serial_qs.company.mark
  433. user_serial_number_qs = UserSerialNumberModel.objects.filter(user__id=3,
  434. serial_number__serial_number=serial_number,
  435. serial_number__use_status=1)
  436. if not user_serial_number_qs.exists():
  437. redis_obj.del_data(key=serial_operate_lock_key) # redis解锁
  438. return response.json(14)
  439. # 防止重复获取序列号
  440. serial_number_lock = redis_obj.CONN.setnx(serial_number + 'serial_number_lock', 1)
  441. redis_obj.CONN.expire(serial_number + 'serial_number_lock', 60)
  442. if not serial_number_lock:
  443. return response.json(5)
  444. # 获取mac
  445. mac_qs = MacModel.objects.filter(is_active=True).values('value')
  446. if not mac_qs.exists():
  447. return response.json(175)
  448. mac = mac_qs[0]['value']
  449. # 绑定mac地址成功后更新mac表
  450. next_mac = CommonService.updateMac(mac)
  451. now_time = int(time.time())
  452. mac_data = {
  453. 'update_time': now_time
  454. }
  455. if next_mac:
  456. mac_data['value'] = next_mac
  457. else:
  458. mac_data['is_active'] = False
  459. # 操作日志数据
  460. operation = '获取序列号:{}'.format(serial_number)
  461. log = {
  462. 'user_id': 3,
  463. 'time': now_time,
  464. 'operation': operation,
  465. 'url': 'serialNumber/getSerial',
  466. }
  467. try:
  468. with transaction.atomic():
  469. # 更新和创建数据
  470. mac_qs.update(**mac_data)
  471. SerialNumberModel.objects.filter(serial_number=serial_number).update(use_status=2, add_time=now_time)
  472. CompanySerialModel.objects.filter(serial_number=serial_number).update(status=2, update_time=now_time)
  473. LogModel.objects.create(**log)
  474. redis_obj.del_data(key=serial_operate_lock_key) # redis解锁
  475. return response.json(0, {'serial_number': serial_number + company_mark, 'mac': mac})
  476. except Exception as e:
  477. redis_obj.del_data(key=serial_operate_lock_key) # redis解锁
  478. return response.json(500, repr(e))
  479. @staticmethod
  480. def generate_mac(request_dict, response):
  481. """
  482. 生成mac到mac.txt文件
  483. :param request_dict: 请求
  484. :param response: 响应
  485. :return: response
  486. """
  487. quantity = int(request_dict.get('quantity', 0))
  488. if quantity == 0:
  489. return response.json(444)
  490. mac_qs = MacModel.objects.filter(is_active=True).values('value')
  491. if not mac_qs.exists():
  492. return response.json(175)
  493. mac = mac_qs[0]['value']
  494. now_time = int(time.time())
  495. with open('mac.txt', 'w') as f:
  496. f.write(mac + '\n')
  497. for i in range(quantity-1):
  498. next_mac = CommonService.updateMac(mac)
  499. mac = next_mac
  500. f.write(next_mac+'\n')
  501. # 保存下个mac
  502. next_mac = CommonService.updateMac(mac)
  503. mac_qs.update(value=next_mac, update_time=now_time)
  504. return response.json(0)
  505. @staticmethod
  506. def check_serial_number(response):
  507. """
  508. 定时查询序列号库存数量,不足2000发送邮件通知
  509. :param response: 响应
  510. :return: response
  511. """
  512. company_qs = CompanyModel.objects.values('id')
  513. try:
  514. for company in company_qs:
  515. company_id = company['id']
  516. company_serial_count = CompanySerialModel.objects.filter(status=1, company_id=company_id).count()
  517. if company_serial_count < 2000:
  518. sys_msg_text = '序列号库存数量少于2000,请及时处理'
  519. S3Email().faEmail(sys_msg_text, 'servers@ansjer.com')
  520. break
  521. return response.json(0)
  522. except Exception as e:
  523. return response.json(500)