xueying.py 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. # -*- coding: utf-8 -*-
  2. # !/usr/bin/env python
  3. import datetime
  4. import logging
  5. from mongoengine import DoesNotExist
  6. from apilib.monetary import RMB
  7. from apps.web.constant import Const
  8. from apps.web.device.models import Group, Device
  9. from apps.web.eventer.base import WorkEvent, FaultEvent
  10. from apps.web.eventer import EventBuilder
  11. from apps.web.south_intf.platform import notify_event_to_north
  12. from apps.web.user.models import ServiceProgress, MyUser, CardConsumeRecord, CardRechargeOrder, UserVirtualCard, \
  13. VCardConsumeRecord
  14. from apps.web.user.transaction_deprecated import refund_money
  15. logger = logging.getLogger(__name__)
  16. class builder(EventBuilder):
  17. def __getEvent__(self, device_event):
  18. event_data = self.deviceAdapter.analyze_event_data(device_event['data'])
  19. if event_data is None or 'cmdCode' not in event_data:
  20. return None
  21. if event_data['cmdCode'] in ['A8', 'B6', 'C8', 'C9']:
  22. return ChargingXUEYINGWorkEvent(self.deviceAdapter, event_data)
  23. if event_data['cmdCode'] == 'C4':
  24. if event_data['status'] == Const.DEV_WORK_STATUS_FAULT:
  25. return FaultEvent(self.deviceAdapter, event_data)
  26. else:
  27. return ChargingXUEYINGWorkEvent(self.deviceAdapter, event_data)
  28. class ChargingXUEYINGWorkEvent(WorkEvent):
  29. def do(self, **args):
  30. devNo = self.device['devNo']
  31. logger.info('xueying charging event detected, devNo=%s' % (devNo,))
  32. if self.event_data['cmdCode'] == 'B6': # 使用IC卡充电结束
  33. card = self.update_card_dealer_and_type(self.event_data['cardNo'], 'IC')
  34. sid = str(self.event_data['finishedTime']) + str(self.event_data['orderNo'])
  35. # 如果记录过,就表示处理过,不重复处理
  36. count = CardConsumeRecord.objects.filter(cardId = str(card.id), sid = sid).count()
  37. if count > 0:
  38. return
  39. self.update_card_balance(card, RMB(self.event_data['balance'] / 100.0))
  40. # 如果没有响应过,就需要记录下卡的消费数据
  41. self.record_consume_for_card(card, RMB(self.event_data['coins'] / 100.0), desc = '',
  42. servicedInfo = {'duration': self.event_data['duration'] / 60.0})
  43. elif self.event_data['cmdCode'] == 'A8': # 刷卡,或者网络卡的余额
  44. card = self.update_card_dealer_and_type(self.event_data['cardNo'], 'ID')
  45. card_recharge_order = CardRechargeOrder.get_last_to_do_one(str(card.id))
  46. result = self.recharge_id_card(card = card,
  47. rechargeType = 'append',
  48. order = card_recharge_order)
  49. card.reload()
  50. logger.info(
  51. 'cardNo=%s,openId=%s,result=%s,curinfo=%s' % (card.cardNo, card.openId, result, self.event_data))
  52. # 扣费
  53. if not card.openId:
  54. res = '02'
  55. balance = 0
  56. elif card.frozen:
  57. res = '04'
  58. balance = 0
  59. elif float(result['balance']) < self.event_data['coins'] / 100.0:
  60. res = '05'
  61. balance = 0
  62. else:
  63. res = '01'
  64. balance = int(result['balance'] * 100) - self.event_data['coins']
  65. self.deviceAdapter.reply_card_balance(res, self.event_data['orderNo'], balance)
  66. elif self.event_data['cmdCode'] == 'C8': # ID卡,充电结束,需要刷新数据
  67. card = self.update_card_dealer_and_type(self.event_data['cardNo'], 'ID')
  68. sid = str(self.event_data['finishedTime']) + str(self.event_data['orderNo'])
  69. # 如果记录过,就表示处理过,不重复处理
  70. count = CardConsumeRecord.objects.filter(cardId = str(card.id), sid = sid).count()
  71. if count > 0:
  72. return
  73. self.consume_money_for_card(card, RMB(self.event_data['coins'] / 100.0))
  74. # 如果没有响应过,就需要记录下卡的消费数据
  75. self.record_consume_for_card(card, RMB(self.event_data['coins'] / 100.0), desc = '',
  76. servicedInfo = {'duration': self.event_data['duration']})
  77. elif self.event_data['cmdCode'] == 'C9': # 扫码,充电结束,需要刷新数据
  78. try:
  79. port = str(self.event_data['port'])
  80. ctrInfo = Device.get_dev_control_cache(self.device['devNo'])
  81. lineInfo = ctrInfo.get(port, None)
  82. if lineInfo is None or (not lineInfo.has_key('openId')) or (lineInfo.has_key('dealing')):
  83. return
  84. ctrInfo[port]['dealing'] = True
  85. Device.update_dev_control_cache(devNo, ctrInfo)
  86. usedTime = self.event_data['duration']
  87. group = Group.get_group(self.device['groupId'])
  88. consumeDict = {'reason': u'充电结束', 'chargeIndex': port, 'duration': usedTime}
  89. group = Group.get_group(self.device['groupId'])
  90. user = MyUser.objects(openId = lineInfo['openId'], groupId = self.device['groupId']).first()
  91. # 如果不需要退款,更新完毕,直接结束.
  92. if not self.device.is_auto_refund:
  93. ServiceProgress.update_progress_and_consume_rcd(
  94. self.device['ownerId'],
  95. {'open_id': lineInfo['openId'], 'port': int(port),
  96. 'device_imei': self.device['devNo'], 'isFinished': False}, consumeDict)
  97. self.notify_user(user.managerialOpenId if user else '', 'service_complete',
  98. **{
  99. 'title': u'充电结束。一共使用时间:%s分钟' % (usedTime),
  100. 'service': u'充电服务(设备编号:%s, 端口:%s,地址:%s)' % (
  101. self.device['logicalCode'], port, group['address']),
  102. 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
  103. 'remark': u'谢谢您的支持'
  104. })
  105. return
  106. backCoins = lineInfo['coins'] - self.event_data['coins'] / 100.0
  107. if backCoins < 0:
  108. backCoins = 0
  109. # 通知服务结束
  110. consumeDict.update({'refundedMoney': str(backCoins)})
  111. if lineInfo.has_key('consumeRcdId'): # 如果用的是虚拟卡,直接把配额返回到虚拟卡
  112. try:
  113. vCardId = lineInfo['vCardId']
  114. vCard = UserVirtualCard.objects.get(id = vCardId)
  115. except DoesNotExist, e:
  116. logger.info('can not find the vCard id = %s' % vCardId)
  117. return
  118. consumeRcdId = lineInfo.get('consumeRcdId', None)
  119. if consumeRcdId is None:
  120. logger.info('can not find consume rcd id')
  121. return
  122. try:
  123. vCardConsumeRcd = VCardConsumeRecord.objects.get(id = consumeRcdId)
  124. except DoesNotExist, e:
  125. logger.info('can not find the consume rcd id = %s' % consumeRcdId)
  126. return
  127. vCard.refund_quota(vCardConsumeRcd, usedTime, 0.0, backCoins)
  128. else:
  129. refund_money(self.device, backCoins, lineInfo['openId'])
  130. ServiceProgress.update_progress_and_consume_rcd(self.device['ownerId'],
  131. {'open_id': lineInfo['openId'], 'port': int(port),
  132. 'device_imei': self.device['devNo'],
  133. 'isFinished': False}, consumeDict)
  134. if lineInfo.has_key('consumeRcdId'):
  135. self.notify_user(user.managerialOpenId if user else '', 'refund_coins', **{
  136. 'title': u'充电结束。您使用的是虚拟卡。预付%s元,订购充电时间%s分钟,使用了%s分钟,花费了%s元。给您退还成相应的虚拟卡额度,您下次可以接着使用哦' % (
  137. lineInfo['coins'], lineInfo['needTime'], usedTime, self.event_data['coins'] / 100.0),
  138. 'backCount': u'金币:%s' % backCoins,
  139. 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
  140. })
  141. else:
  142. self.notify_user(user.managerialOpenId if user else '', 'refund_coins', **{
  143. 'title': u'充电结束。您预付%s元,订购充电时间%s分钟,使用了%s分钟,花费了%s元。给您退还成相应的金币:%s元,您下次可以接着使用哦' % (
  144. lineInfo['coins'], lineInfo['needTime'], usedTime, self.event_data['coins'] / 100.0,
  145. backCoins),
  146. 'backCount': u'金币:%s' % backCoins,
  147. 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
  148. })
  149. finally:
  150. Device.clear_port_control_cache(devNo, str(port))
  151. notify_event_to_north(self.dealer, self.device, level = Const.EVENT_NORMAL, desc = u'充电结束')
  152. elif self.event_data['cmdCode'] == 'C4': # 直接更新端口以及设备状态
  153. port = str(self.event_data['port'])
  154. if port == 0:
  155. return
  156. ctrInfo = Device.get_dev_control_cache(self.device['devNo'])
  157. ctrInfo[port].update({'status': self.event_data['status']})
  158. Device.update_dev_control_cache(devNo, ctrInfo)