hainiaoSingleNew.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. # -*- coding: utf-8 -*-
  2. # !/usr/bin/env python
  3. import logging
  4. from mongoengine import DoesNotExist
  5. from apilib.monetary import RMB, VirtualCoin
  6. from apilib.utils_datetime import to_datetime
  7. from apps.web.constant import Const, DEALER_CONSUMPTION_AGG_KIND
  8. from apps.web.device.models import Device, Group
  9. from apps.web.eventer.base import WorkEvent
  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, UserVirtualCard, VCardConsumeRecord, Card, MyUser, CardRechargeOrder
  13. logger = logging.getLogger(__name__)
  14. class builder(EventBuilder):
  15. def __getEvent__(self, device_event):
  16. event_data = self.deviceAdapter.analyze_event_data(device_event['data'])
  17. if not event_data or 'cmdCode' not in event_data:
  18. return None
  19. if 'duration' in device_event:
  20. event_data.update({'duration': device_event['duration']})
  21. if event_data['cmdCode'] in ['86', '8B', '8C', '8D']:
  22. return ChargingHaiNiaoSingleNewWorkEvent(self.deviceAdapter, event_data)
  23. class ChargingHaiNiaoSingleNewWorkEvent(WorkEvent):
  24. def support_playback(self):
  25. return self.event_data['cmdCode'] == '86'
  26. def do(self, **args):
  27. devNo = self.device['devNo']
  28. logger.info('hainiaoSingle charging event detected, devNo=%s, curInfo=%s' % (devNo, self.event_data))
  29. if self.event_data['cmdCode'] == '86':
  30. port = self.event_data['port']
  31. reason = self.event_data['reason']
  32. cardNo = self.event_data['cardNo']
  33. try:
  34. lineInfo = Device.clear_port_control_cache(self.device['devNo'], str(port))
  35. recvTime = to_datetime(self.recvTime)
  36. # 为-1的时候就是没有
  37. deviceDuration = self.event_data.get('duration', -1)
  38. if lineInfo is not None and 'startTime' in lineInfo:
  39. startTime = to_datetime(lineInfo['startTime'])
  40. if startTime > recvTime:
  41. serverDuration = 0
  42. else:
  43. serverDuration = int(round(((recvTime - startTime).total_seconds() / 60.0)))
  44. # 为-1的时候就是没有
  45. else:
  46. serverDuration = -1
  47. if deviceDuration > 0:
  48. usedTime = deviceDuration
  49. else:
  50. usedTime = serverDuration
  51. needPrice = RMB(lineInfo['needPrice'])
  52. leftPrice = RMB(self.event_data['leftPrice'])
  53. leftTime = self.event_data['leftTime']
  54. leftTimeStr = str(leftTime)
  55. actualNeedTime = usedTime + leftTime
  56. group = Group.get_group(self.device['groupId'])
  57. consumeDict = {'reason': reason, 'leftTime': leftTimeStr,
  58. 'chargeIndex': port, 'duration': usedTime}
  59. # 如果是刷卡的,直接更新消费记录,然后发送通知消息,不支持退费
  60. if cardNo:
  61. card = Card.objects(cardNo = cardNo, agentId = self.dealer.agentId).first()
  62. if not self.device.is_auto_refund:
  63. ServiceProgress.update_progress_and_consume_rcd(self.device['ownerId'],
  64. {'open_id': lineInfo['openId'], 'port': 1,
  65. 'device_imei': self.device['devNo'],
  66. 'isFinished': False}, consumeDict)
  67. return
  68. backCoins = leftPrice
  69. if backCoins > needPrice:
  70. backCoins = needPrice
  71. self.refund_money_for_card(backCoins, str(card.id))
  72. consumeDict.update(
  73. {DEALER_CONSUMPTION_AGG_KIND.REFUND_CARD: backCoins.mongo_amount})
  74. ServiceProgress.update_progress_and_consume_rcd(self.device['ownerId'],
  75. {'open_id': lineInfo['openId'], 'port': 1,
  76. 'device_imei': self.device['devNo'],
  77. 'isFinished': False}, consumeDict)
  78. elif lineInfo.has_key('consumeRcdId'):
  79. backCoins = leftPrice
  80. vCardId = ''
  81. try:
  82. vCardId = lineInfo['vCardId']
  83. vCard = UserVirtualCard.objects.get(id = vCardId)
  84. except DoesNotExist, e:
  85. logger.info('can not find the vCard id = %s' % vCardId)
  86. return
  87. ServiceProgress.update_progress_and_consume_rcd(self.device['ownerId'],
  88. {'open_id': lineInfo['openId'], 'port': int(port),
  89. 'device_imei': self.device['devNo'],
  90. 'isFinished': False}, consumeDict)
  91. consumeRcdId = lineInfo.get('consumeRcdId', None)
  92. if consumeRcdId is None:
  93. logger.info('can not find consume rcd id')
  94. return
  95. try:
  96. vCardConsumeRcd = VCardConsumeRecord.objects.get(id = consumeRcdId)
  97. except DoesNotExist, e:
  98. logger.info('can not find the consume rcd id = %s' % consumeRcdId)
  99. return
  100. vCard.refund_quota(vCardConsumeRcd, usedTime, 0.0, backCoins.mongo_amount)
  101. elif 'openId' in lineInfo and lineInfo['openId']:
  102. user = MyUser.objects(openId = lineInfo.get('openId', ''), groupId = self.device['groupId']).first()
  103. # 通知服务结束
  104. self.notify_user(user.managerialOpenId if user else '', 'service_complete',
  105. **{
  106. 'title': u'%s' % reason,
  107. 'service': u'充电服务(设备编号:%s, 端口:%s,地址:%s)' % (
  108. self.device['logicalCode'], port, group['address']),
  109. 'finishTime': recvTime.strftime('%Y-%m-%d %H:%M:%S'),
  110. 'remark': u'谢谢您的支持'
  111. })
  112. # 如果需要退款,计算退款数据.
  113. if not self.device.is_auto_refund:
  114. ServiceProgress.update_progress_and_consume_rcd(self.device['ownerId'],
  115. {'open_id': lineInfo['openId'],
  116. 'port': int(port),
  117. 'device_imei': self.device['devNo'],
  118. 'isFinished': False}, consumeDict)
  119. return
  120. minConsumptionLimit = self.device.my_obj.otherConf.get('minConsumptionLimit', 0)
  121. tempMoneyNum = float(needPrice) - float(minConsumptionLimit)
  122. if tempMoneyNum < 0:
  123. tempMoneyNum = 0
  124. backCoins = leftPrice
  125. if backCoins > needPrice:
  126. backCoins = needPrice
  127. if float(backCoins) >= tempMoneyNum:
  128. backCoins = RMB(tempMoneyNum)
  129. # 直接退现金
  130. if RMB(0) < backCoins <= needPrice:
  131. self.refund_net_pay(user, lineInfo, backCoins, VirtualCoin(0), consumeDict, True)
  132. refund = RMB(consumeDict.get(DEALER_CONSUMPTION_AGG_KIND.REFUNDED_CASH, '0.00'))
  133. if refund > RMB(0):
  134. self.notify_user(user.managerialOpenId if user else '', 'refund_coins', **{
  135. 'title': reason,
  136. 'backCount': u'%s元' % refund,
  137. 'finishTime': recvTime.strftime('%Y-%m-%d %H:%M:%S')
  138. })
  139. ServiceProgress.update_progress_and_consume_rcd(self.device['ownerId'],
  140. {'open_id': lineInfo['openId'], 'port': int(port),
  141. 'device_imei': self.device['devNo'],
  142. 'isFinished': False}, consumeDict)
  143. else:
  144. logger.debug('other start device mode.')
  145. finally:
  146. notify_event_to_north(self.dealer, self.device, level = Const.EVENT_NORMAL, desc = reason)
  147. if self.event_data['cmdCode'] == '8B':
  148. cardNo = self.event_data['cardNo']
  149. card = self.update_card_dealer_and_type(cardNo)
  150. if not card:
  151. self.deviceAdapter.ack_query_card_balance(cardNo, 0)
  152. return
  153. card_recharge_order = CardRechargeOrder.get_last_to_do_one(str(card.id))
  154. self.recharge_id_card(card=card, rechargeType='append', order=card_recharge_order)
  155. card.reload()
  156. self.deviceAdapter.ack_query_card_balance(cardNo, card.balance)
  157. Device.update_dev_control_cache(self.device.devNo, {'1': {'wait8CCardNo': cardNo}})
  158. if self.event_data['cmdCode'] == '8C':
  159. cardNo = self.event_data['cardNo']
  160. operFee = RMB(self.event_data['operFee'])
  161. wait8C = Device.get_dev_control_cache(self.device['devNo']).get('1', {})
  162. if wait8C.get('wait8CCardNo', '') != cardNo:
  163. self.deviceAdapter.ack_consume_card(cardNo, 0, '00')
  164. return
  165. Device.update_dev_control_cache(self.device.devNo, {'1': {'wait8CCardNo': ''}})
  166. card = self.update_card_dealer_and_type(cardNo)
  167. if not card:
  168. self.deviceAdapter.ack_consume_card(cardNo, 0, '00')
  169. return
  170. if card.openId == '' or card.frozen:
  171. self.deviceAdapter.ack_consume_card(cardNo, card.balance, '01')
  172. return
  173. if card.balance < operFee:
  174. self.deviceAdapter.ack_consume_card(cardNo, card.balance, '02')
  175. return
  176. orderNo, cardOrderNo = self.record_consume_for_card(card, operFee)
  177. ServiceProgress.register_card_service(self.device, 1, card,
  178. {
  179. 'orderNo': orderNo,
  180. 'money': self.event_data['operFee'],
  181. 'coin': self.event_data['operFee'], 'needTime': 0,
  182. 'cardOrderNo': cardOrderNo
  183. })
  184. self.consume_money_for_card(card, operFee)
  185. self.deviceAdapter.ack_consume_card(cardNo, card.balance, '55')
  186. Device.update_dev_control_cache(self.device.devNo, {'1': {'needPrice': operFee, 'consumeType': 'card', 'cardNo': cardNo}})
  187. if self.event_data['cmdCode'] == '8D':
  188. hexUrl = self.event_data['hexUrl']
  189. self.deviceAdapter.init_device_QR_code(hexUrl)