UnicomComboTaskController.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. # -*- encoding: utf-8 -*-
  2. """
  3. @File : UnicomComboTaskController.py
  4. @Time : 2022/6/30 16:23
  5. @Author : stephen
  6. @Email : zhangdongming@asj6.wecom.work
  7. @Software: PyCharm
  8. """
  9. import datetime
  10. import logging
  11. import threading
  12. import time
  13. from decimal import Decimal
  14. from django.db import transaction
  15. from django.db.models import Q
  16. from django.views import View
  17. from Model.models import UnicomComboOrderInfo, UnicomCombo, Order_Model, UnicomDeviceInfo, UnicomFlowPush, SysMsgModel
  18. from Object.ResponseObject import ResponseObject
  19. from Object.UnicomObject import UnicomObjeect
  20. logger = logging.getLogger('info')
  21. class UnicomComboTaskView(View):
  22. def get(self, request, *args, **kwargs):
  23. request.encoding = 'utf-8'
  24. operation = kwargs.get('operation')
  25. return self.validation(request.GET, request, operation)
  26. def post(self, request, *args, **kwargs):
  27. request.encoding = 'utf-8'
  28. operation = kwargs.get('operation')
  29. return self.validation(request.POST, request, operation)
  30. def validation(self, request_dict, request, operation):
  31. response = ResponseObject()
  32. print(request)
  33. if operation == 'check-activate':
  34. return self.check_activate_combo(request_dict, response)
  35. elif operation == 'check-flow':
  36. return self.check_flow_usage(response)
  37. elif operation == 'check-flow-expire':
  38. return self.check_flow_expire(response)
  39. elif operation == 'check-expire':
  40. today = datetime.datetime.today()
  41. year = today.year
  42. month = today.month
  43. self.query_unused_combo_and_activate(request_dict.get('iccid'), year, month, '666')
  44. return response.json(0)
  45. @classmethod
  46. def check_activate_combo(cls, request_dict, response):
  47. """
  48. 定时检查是否有次月激活套餐
  49. @param request_dict:
  50. @param response:
  51. @return:
  52. """
  53. print(request_dict)
  54. logger.info('--->进入监控次月激活联通套餐')
  55. now_time = int(time.time())
  56. combo_order_info_qs = UnicomComboOrderInfo.objects.filter(status=0, next_month_activate=True,
  57. activation_time__lte=now_time,
  58. expire_time__gte=now_time, is_del=0).values()
  59. if not combo_order_info_qs.exists():
  60. return response.json(0)
  61. try:
  62. today = datetime.datetime.today()
  63. year = today.year
  64. month = today.month
  65. with transaction.atomic():
  66. unicom_api = UnicomObjeect()
  67. for item in combo_order_info_qs:
  68. if item['order_id']:
  69. order_id = item['order_id']
  70. order_qs = Order_Model.objects.filter(orderID=order_id, status=1)
  71. if not order_qs.exists():
  72. continue
  73. combo_order_qs = UnicomComboOrderInfo.objects.filter(status=1, iccid=item['iccid'])
  74. # 当前已有套餐正在使用则跳出当前循环
  75. if combo_order_qs.exists():
  76. continue
  77. combo_id = item['combo_id']
  78. combo_qs = UnicomCombo.objects.filter(id=combo_id).values()
  79. if not combo_qs.exists():
  80. continue
  81. # 查询当月用量情况
  82. flow_total_usage = unicom_api.get_flow_usage_total(item['iccid'])
  83. flow_total_usage = Decimal(flow_total_usage).quantize(
  84. Decimal('0.00')) if flow_total_usage > 0 else 0
  85. flow_total_usage = str(flow_total_usage)
  86. iccid = item['iccid']
  87. # 检查激活iccid
  88. unicom_api.change_device_to_activate(iccid)
  89. cls.query_unused_combo_and_activate(iccid, year, month, flow_total_usage)
  90. logger.info('激活成功,订单编号:{}'.format(order_id))
  91. return response.json(0)
  92. except Exception as e:
  93. logger.info('出错了~次月激活套餐异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  94. return response.json(177, repr(e))
  95. @classmethod
  96. def check_flow_usage(cls, response):
  97. """
  98. 检查流量使用情况
  99. @return:
  100. """
  101. logger.info('--->进入监控流量使用情况')
  102. try:
  103. unicom_api = UnicomObjeect()
  104. combo_order_qs = UnicomComboOrderInfo.objects.filter(status=1, is_del=False, combo__is_unlimited=0).values()
  105. if not combo_order_qs.exists():
  106. return response.json(0)
  107. today = datetime.datetime.today()
  108. year = today.year
  109. month = today.month
  110. now_time = int(time.time())
  111. for item in combo_order_qs:
  112. iccid = item['iccid']
  113. u_device_info_qs = UnicomDeviceInfo.objects.filter(iccid=iccid)
  114. if not u_device_info_qs.exists():
  115. continue
  116. u_device_info_qs = u_device_info_qs.first()
  117. activate_usage_flow = float(item['flow_total_usage']) if item['flow_total_usage'] else 0.0
  118. combo_id = item['combo_id']
  119. combo_qs = UnicomCombo.objects.filter(id=combo_id).values()
  120. if not combo_qs.exists():
  121. continue
  122. combo_qs = combo_qs.first()
  123. flow_total = combo_qs['flow_total']
  124. # 队列已使用总流量总量
  125. flow_total_usage = unicom_api.get_flow_usage_total(iccid)
  126. logger.info('--->iccid:{};套餐总值:{},激活时队列已用总流量:{},当前最新套餐队列已使用流量量:{}'
  127. .format(iccid, flow_total, activate_usage_flow, flow_total_usage))
  128. is_expire = False
  129. flow = activate_usage_flow + flow_total
  130. if flow_total_usage > 0:
  131. # 初始套餐已使用流量 + 套餐总流量
  132. if flow_total_usage >= flow:
  133. is_expire = True
  134. usage = (flow_total_usage - activate_usage_flow) if flow_total_usage > activate_usage_flow else 0
  135. cls.flow_warning_push(u_device_info_qs.user_id, u_device_info_qs.serial_no, item['id'], flow_total,
  136. usage)
  137. # 检查是否有当月未使用套餐 没有则停卡
  138. if is_expire:
  139. flow_exceed = flow_total_usage - flow
  140. UnicomComboOrderInfo.objects.filter(id=item['id']) \
  141. .update(status=2, updated_time=now_time, flow_exceed=flow_exceed)
  142. activate_status = cls.query_unused_combo_and_activate(iccid, year, month,
  143. flow_total_usage)
  144. if not activate_status:
  145. # 停用
  146. unicom_api.change_device_to_disable(iccid)
  147. return response.json(0)
  148. except Exception as e:
  149. logger.info('出错了~检测流量用量详情异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  150. return response.json(177, repr(e))
  151. @staticmethod
  152. def flow_warning_push(app_user_id, serial_no, combo_order_id, flow_total, flow_usage):
  153. """
  154. 监控流量使用大于85%and小于96%进行消息推送提醒
  155. @param app_user_id: app用户id
  156. @param serial_no: 序列号
  157. @param combo_order_id: 当前套餐订单id
  158. @param flow_total: 套餐流量总量
  159. @param flow_usage: 套餐已使用流量
  160. @return:
  161. """
  162. try:
  163. if not app_user_id:
  164. return False
  165. now_time = int(time.time())
  166. push_data = {'combo_order_id': str(combo_order_id), 'serial_no': serial_no,
  167. 'flow_total_usage': flow_usage, 'flow_total': flow_total, 'status': 0,
  168. 'updated_time': now_time,
  169. 'created_time': now_time, 'user_id': app_user_id}
  170. if 0 < flow_total and 0 < flow_usage < flow_total:
  171. res = flow_usage / flow_total * 100
  172. if 85 < res <= 95:
  173. flow_push = UnicomFlowPush.objects.filter(serial_no=serial_no, combo_order_id=combo_order_id)
  174. if not flow_push.exists():
  175. UnicomFlowPush.objects.create(**push_data)
  176. elif flow_usage >= flow_total:
  177. push_data['flow_total_usage'] = flow_total
  178. push_data['type'] = 1
  179. UnicomFlowPush.objects.create(**push_data)
  180. return True
  181. except Exception as e:
  182. logger.info('出错了~异常流量监控,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  183. @staticmethod
  184. def query_unused_combo_and_activate(iccid, year, month, usage_flow):
  185. """
  186. 查询未使用套餐并激活
  187. @param iccid:
  188. @param year:
  189. @param month:
  190. @param usage_flow:
  191. @return:
  192. """
  193. try:
  194. now_time = int(time.time())
  195. combo_order_qs = UnicomComboOrderInfo.objects \
  196. .filter(expire_time__gt=now_time, activation_time__lte=now_time, status=0, iccid=iccid) \
  197. .order_by('created_time')
  198. if not combo_order_qs.exists():
  199. return False
  200. combo_order = combo_order_qs.first()
  201. if not combo_order.order_id:
  202. return False
  203. order_qs = Order_Model.objects.filter(orderID=combo_order.order_id, status=1)
  204. if not order_qs.exists():
  205. return False
  206. upd_data = {
  207. 'status': 1,
  208. 'year': year,
  209. 'month': month,
  210. 'flow_total_usage': str(usage_flow),
  211. 'activation_time': now_time,
  212. 'updated_time': now_time,
  213. }
  214. UnicomComboOrderInfo.objects.filter(id=combo_order.id).update(**upd_data)
  215. ud_info_qs = UnicomDeviceInfo.objects.filter(iccid=iccid)
  216. if ud_info_qs.exists():
  217. ud_info = ud_info_qs.first()
  218. sys_msg_text = UnicomComboTaskView.get_sys_msg_text(ud_info.serial_no, combo_order.combo.combo_name, 2)
  219. asy = threading.Thread(target=UnicomComboTaskView.async_sys_msg_save,
  220. args=(ud_info.user_id, ud_info.serial_no, sys_msg_text))
  221. asy.start()
  222. return True
  223. except Exception as e:
  224. logger.info('出错了~激活套餐,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  225. return False
  226. @classmethod
  227. def check_flow_expire(cls, response):
  228. """
  229. 检查流量到期停卡操作
  230. @param response:
  231. @return:
  232. """
  233. logger.info('--->进入监控流量到期停卡或激活叠加包')
  234. now_time = int(time.time())
  235. combo_order_qs = UnicomComboOrderInfo.objects.filter(~Q(status=2), expire_time__lte=now_time,
  236. is_del=False).values()
  237. today = datetime.datetime.today()
  238. year = today.year
  239. month = today.month
  240. if not combo_order_qs.exists():
  241. return response.json(0)
  242. iccid_list = []
  243. with transaction.atomic():
  244. for item in combo_order_qs:
  245. try:
  246. icc_id = item['iccid']
  247. um_device_qs = UnicomDeviceInfo.objects.filter(iccid=icc_id)
  248. if not um_device_qs.exists():
  249. continue
  250. UnicomComboOrderInfo.objects.filter(id=item['id']).update(status=2, updated_time=now_time)
  251. iccid_list.append(icc_id)
  252. logger.info('--->当前流量套餐已过期,iccid:{}'.format(icc_id))
  253. except Exception as e:
  254. logger.info('出错了~监控流量到期异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  255. continue
  256. # set无序不重复元素集
  257. iccid_list = list(set(iccid_list))
  258. unicom_api = UnicomObjeect()
  259. for item in iccid_list:
  260. activate_combo_qs = UnicomComboOrderInfo.objects.filter(iccid=item, status=1, expire_time__gt=now_time,
  261. is_del=False).values()
  262. if activate_combo_qs.exists():
  263. continue
  264. usage_flow = unicom_api.get_flow_usage_total(item)
  265. result = cls.query_unused_combo_and_activate(item, year, month, usage_flow)
  266. if not result:
  267. # 停用设备
  268. unicom_api.change_device_to_disable(item)
  269. combo_order_info_qs = UnicomComboOrderInfo.objects.filter(iccid=item, status=2) \
  270. .values('combo__combo_name').order_by('-updated_time')
  271. ud_info_qs = UnicomDeviceInfo.objects.filter(iccid=item)
  272. combo_order = combo_order_info_qs.first()
  273. if ud_info_qs.exists():
  274. ud_info = ud_info_qs.first()
  275. sys_msg_text = UnicomComboTaskView.get_sys_msg_text(ud_info.serial_no,
  276. combo_order['combo__combo_name'], 1)
  277. asy = threading.Thread(target=UnicomComboTaskView.async_sys_msg_save,
  278. args=(ud_info.user_id, ud_info.serial_no, sys_msg_text))
  279. asy.start()
  280. else:
  281. unicom_api.change_device_to_activate(item)
  282. return response.json(0)
  283. @staticmethod
  284. def get_sys_msg_text(serial_no, combo_name, sys_type):
  285. """
  286. 获取系统消息文本
  287. @return:
  288. """
  289. if sys_type == 1:
  290. sys_msg_text = "温馨提示:尊敬的客户,您" + serial_no + "设备当前4G" + combo_name + "已到期"
  291. elif sys_type == 2:
  292. sys_msg_text = "温馨提示:尊敬的客户,您" + serial_no + "设备当前4G" + combo_name + "已激活"
  293. else:
  294. sys_msg_text = "温馨提示:尊敬的客户,您" + serial_no + "设备当前4G" + combo_name + "已用完"
  295. return sys_msg_text
  296. @staticmethod
  297. def async_sys_msg_save(user_id, serial_no, sys_msg_text):
  298. """
  299. 异步系统消息保存
  300. @param user_id: 用户id
  301. @param sys_msg_text: 系统消息文本
  302. @param serial_no: 序列号
  303. @return: None
  304. """
  305. now_time = int(time.time())
  306. try:
  307. data = {'addTime': now_time, 'updTime': now_time, 'userID_id': user_id, 'eventType': 0, 'msg': sys_msg_text,
  308. 'uid': serial_no}
  309. SysMsgModel.objects.create(**data)
  310. except Exception as e:
  311. print('出错了~异步保存配置信息错误,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))