anxin.py 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640
  1. # -*- coding: utf-8 -*-
  2. # !/usr/bin/env python
  3. import datetime
  4. import logging
  5. import time
  6. from decimal import Decimal
  7. from mongoengine import DoesNotExist
  8. from apilib.monetary import RMB
  9. from apilib.utils_datetime import to_datetime
  10. from apps.web.constant import Const, DEALER_CONSUMPTION_AGG_KIND
  11. from apps.web.core.accounting import Accounting
  12. from apps.web.device.models import Device, Group
  13. from apps.web.eventer.base import FaultEvent, WorkEvent
  14. from apps.web.eventer import EventBuilder
  15. from apps.web.report.utils import record_consumption_stats
  16. from apps.web.south_intf.platform import notify_event_to_north, notify_event_to_north_v2
  17. from apps.web.user.models import ServiceProgress, UserVirtualCard, VCardConsumeRecord, CardRechargeOrder, Card, MyUser, \
  18. ConsumeRecord
  19. from apps.web.user.transaction_deprecated import refund_money
  20. logger = logging.getLogger(__name__)
  21. class builder(EventBuilder):
  22. def __getEvent__(self, device_event):
  23. event_data = self.deviceAdapter.analyze_event_data(device_event['data'])
  24. if event_data is None or 'cmdCode' not in event_data:
  25. return None
  26. if 'duration' in device_event:
  27. event_data.update({'duration': device_event['duration']})
  28. fun_code = event_data['cmdCode']
  29. if fun_code in ['06', '10', '20', '16', '11', '12']:
  30. return ChargingAnxinWorkEvent(self.deviceAdapter, event_data)
  31. if fun_code == '0A':
  32. return FaultEvent(self.deviceAdapter, event_data)
  33. return None
  34. class ChargingAnxinWorkEvent(WorkEvent):
  35. def do(self, **args):
  36. devNo = self.device['devNo']
  37. logger.info('anxin charging event detected, devNo=%s,info=%s' % (devNo, self.event_data))
  38. if self.event_data['cmdCode'] == '10': # 刷卡消费的,分为扣费和退费两种
  39. cardNo = self.event_data['cardNo']
  40. preFee = RMB(self.event_data['preFee'])
  41. oper = self.event_data['oper']
  42. card = self.update_card_dealer_and_type(cardNo)
  43. # 首先检查订单,并进行充值
  44. card_recharge_order = CardRechargeOrder.get_last_to_do_one(str(card.id)) # type: CardRechargeOrder
  45. result = self.recharge_id_card(card = card,
  46. rechargeType = 'append',
  47. order = card_recharge_order)
  48. # 暂时保留. 按照流程应该不需要在重新加载
  49. card.reload()
  50. logger.info('cardNo=%s,openId=%s,result=%s,preFee=%s,curinfo=%s' % (
  51. cardNo, card.openId, result, preFee, self.event_data))
  52. try:
  53. # 扣费
  54. if oper == '00':
  55. leftBalance = result['balance']
  56. res = '00'
  57. if card.openId == '' or card.frozen:
  58. res = '02'
  59. leftBalance = RMB(0)
  60. elif result['balance'] < preFee:
  61. res = '01'
  62. if res == '00':
  63. self.consume_money_for_card(card, preFee)
  64. # 记录卡消费记录以及消费记录
  65. orderNo, cardOrderNo = self.record_consume_for_card(card, preFee)
  66. # 记录当前服务的progress.没有上报端口号,所以先用-1标记,表示端口未知。端口等消费的时候会报上来
  67. ServiceProgress.register_card_service(self.device, -1, card,
  68. {'orderNo': orderNo, 'money': self.event_data['preFee'],
  69. 'coin': self.event_data['preFee'], 'needTime': 0,
  70. 'cardOrderNo': cardOrderNo})
  71. leftBalance -= preFee
  72. try:
  73. self.deviceAdapter.response_use_card(res, leftBalance)
  74. except Exception, e: # 启动失败需要把金币还回去
  75. logger.info('resp back error=%s' % e)
  76. return
  77. if res in ['01', '02']:
  78. return
  79. self.event_data['openId'] = card.openId
  80. self.event_data['cardId'] = str(card.id)
  81. self.event_data['startTime'] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
  82. Device.update_dev_control_cache(devNo, self.event_data)
  83. # 通知微信,已经扣费
  84. self.notify_balance_has_consume_for_card(card, preFee)
  85. # 退费.卡的退费完全由设备决定,设备告诉我退费,我就退。刷卡充电结束后,不要去退费。
  86. elif oper == '01':
  87. try:
  88. res = '00'
  89. self.deviceAdapter.response_use_card(res, card.balance + preFee)
  90. except Exception, e: # 启动失败需要把金币还回去
  91. logger.info('resp back error=%s' % e)
  92. return
  93. self.refund_money_for_card(preFee, str(card.id))
  94. # 通知微信,已经退费
  95. self.notify_user(card.managerialOpenId, 'refund_coins', **{
  96. 'title': u'退币完成!您的卡号是%s,卡别名:%s' % (card.cardNo, card.nickName),
  97. 'backCount': u'金币:%s' % preFee,
  98. 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
  99. })
  100. except Exception, e:
  101. logger.error('use card=%s catche exception=%s' % (cardNo, e))
  102. elif self.event_data['cmdCode'] in ['06', '16']: # 结束的命令
  103. lineInfo = Device.update_port_control_cache(devNo, self.event_data)
  104. try:
  105. group = Group.get_group(self.device['groupId'])
  106. if not lineInfo.has_key('coins'):
  107. return
  108. if 'duration' in self.event_data and self.event_data['duration'] > 0:
  109. usedTime = self.event_data['duration']
  110. else:
  111. if (not lineInfo) or (not lineInfo.has_key('startTime')):
  112. return
  113. startTime = to_datetime(lineInfo['startTime'])
  114. nowTime = datetime.datetime.now()
  115. # 如果web服务器时间和事件监控服务器时间不一致,导致开始时间比事件时间还大
  116. if startTime > nowTime:
  117. usedTime = 0
  118. else:
  119. usedTime = int(round(((nowTime - startTime).total_seconds() / 60.0)))
  120. cardId = lineInfo.get('cardId', '')
  121. vCardId = lineInfo.get('vCardId', None)
  122. money = RMB(lineInfo['coins'])
  123. price = lineInfo.get('price', 0.0)
  124. leftTime = self.event_data['leftTime']
  125. billingType = lineInfo.get('billingType', 'time')
  126. consumeType = lineInfo.get('consumeType', '')
  127. backCoins, backPrice = 0.0, 0.0
  128. # 刷卡或者万一缓存重启了,出现needElec为空的,作为1000度电吧,就会一定使用设备上报的电量
  129. if lineInfo.has_key('elec') and lineInfo.has_key('needElec'):
  130. spendElec = round(lineInfo['needElec'] - lineInfo['elec'], 2) if lineInfo.get(
  131. 'elec') < lineInfo.get('needElec') else 0.0
  132. else:
  133. spendElec = 0.0
  134. if leftTime == 65535:
  135. actualNeedTime = 0
  136. backCoins = money
  137. backPrice = price
  138. usedTime = 0
  139. spendElec = 0.0
  140. else:
  141. actualNeedTime = usedTime + leftTime
  142. leftTimeStr = leftTime
  143. if billingType == 'time':
  144. needTime = lineInfo['needTime']
  145. backCoins = money * (float(leftTime) / float(actualNeedTime))
  146. else:
  147. backCoins = RMB(money.amount - money.amount * (
  148. Decimal(lineInfo.get('needElec', 1000)) - Decimal(
  149. str(lineInfo.get('elec')))) / Decimal(lineInfo.get('needElec', 1000)))
  150. if backCoins > money:
  151. backCoins = money
  152. backPrice = round(price * float(backCoins) / float(money), 2)
  153. if vCardId is None and cardId == '': # 扫码的方式
  154. openId = lineInfo['openId']
  155. billingType = lineInfo.get('billingType', 'time')
  156. if billingType == 'time':
  157. leftTimeStr = leftTime if leftTime != 65535 else lineInfo['needTime']
  158. title = u'%s 按动态功率计算总时间为:%s分钟,剩余时间:%s分钟' % (
  159. self.event_data['reason'],
  160. actualNeedTime,
  161. leftTimeStr)
  162. else:
  163. title = u'%s %s元购买%s度电量,实际使用电量为:%s度' % (
  164. self.event_data['reason'],
  165. money, lineInfo.get('needElec', 1000),
  166. spendElec
  167. )
  168. # 通知充电完成
  169. user = MyUser.objects(openId = openId, groupId = self.device['groupId']).first()
  170. self.notify_user(user.managerialOpenId, 'service_complete',
  171. **{
  172. 'title': title,
  173. 'service': u'充电服务(设备编号:%s,端口:%s,地址:%s)' % (
  174. self.device['logicalCode'], self.event_data['port'], group['address']),
  175. 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
  176. 'remark': u'谢谢您的支持'
  177. })
  178. consumeDict = {'chargeIndex': lineInfo['port'],
  179. 'reason': lineInfo['reason'],
  180. 'elec': spendElec, 'actualNeedTime': u'动态功率计算为%s分钟' % actualNeedTime,
  181. 'duration': usedTime, 'elecFee': self.calc_elec_fee(spendElec)}
  182. if billingType == 'time':
  183. leftTimeStr = leftTime if leftTime != 65535 else lineInfo['needTime']
  184. consumeDict.update({'leftTime': leftTimeStr, 'needTime': u'扫码订购%s分钟' % lineInfo['needTime']})
  185. else:
  186. consumeDict.update({'needElec': lineInfo['needElec']})
  187. # 如果需要退款,计算退款数据.
  188. if not self.device.is_auto_refund:
  189. consumeDict.update({DEALER_CONSUMPTION_AGG_KIND.COIN: money.mongo_amount})
  190. ServiceProgress.update_progress_and_consume_rcd(
  191. self.device['ownerId'],
  192. {'open_id': openId, 'device_imei': self.device['devNo'],
  193. 'port': lineInfo['port'], 'isFinished': False}, consumeDict
  194. )
  195. else:
  196. # 扫码退钱, 退到个人账号
  197. refund_money(self.device, backCoins, lineInfo['openId'])
  198. consumeDict.update({
  199. DEALER_CONSUMPTION_AGG_KIND.REFUNDED_COINS: backCoins.mongo_amount,
  200. DEALER_CONSUMPTION_AGG_KIND.COIN: (money - backCoins).mongo_amount
  201. })
  202. ServiceProgress.update_progress_and_consume_rcd(
  203. self.device['ownerId'],
  204. {'open_id': openId, 'device_imei': self.device['devNo'],
  205. 'port': lineInfo['port'], 'isFinished': False}, consumeDict)
  206. if billingType == 'time':
  207. leftTimeStr = leftTime if leftTime != 65535 else lineInfo['needTime']
  208. desc = u'您使用的%s号端口充电,共付款:%s元,充电预定时间为:%s分钟,剩余时间:%s分钟,给您退款:%s元' % (
  209. lineInfo['port'], money, lineInfo['needTime'], leftTimeStr, backCoins)
  210. else:
  211. desc = u'您使用的%s号端口充电,共付款:%s元,充电预定电量为:%s度,使用:%s度,给您退款:%s元' % (
  212. lineInfo['port'], money, lineInfo.get('needElec', 1), spendElec, backCoins)
  213. self.notify_user(user.managerialOpenId if user else '', 'refund_coins', **{
  214. 'title': desc,
  215. 'backCount': u'金币:%s' % backCoins,
  216. 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
  217. })
  218. elif vCardId is not None: # 使用的是虚拟卡
  219. billingType = lineInfo.get('billingType', 'time')
  220. if billingType == 'time':
  221. leftTimeStr = leftTime if leftTime != 65535 else lineInfo['needTime']
  222. title = u'%s 按动态功率计算总时间为:%s分钟,剩余时间:%s分钟' % (
  223. self.event_data['reason'],
  224. actualNeedTime,
  225. leftTimeStr)
  226. else:
  227. title = u'%s %s元购买%s度电量,实际使用电量为:%s度' % (
  228. self.event_data['reason'],
  229. money, lineInfo.get('needElec', 1000),
  230. spendElec
  231. )
  232. # 通知充电完成
  233. try:
  234. vCard = UserVirtualCard.objects.get(id = vCardId)
  235. except DoesNotExist, e:
  236. logger.info('can not find the vCard id = %s' % vCardId)
  237. return
  238. self.notify_user(self.get_managerialOpenId_by_openId(lineInfo['openId']), 'service_complete',
  239. **{
  240. 'title': title,
  241. 'service': u'充电服务(设备编号:%s,端口:%s,地址:%s)' % (
  242. self.device['logicalCode'], self.event_data['port'], group['address']),
  243. 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
  244. 'remark': u'谢谢您的支持'
  245. })
  246. consumeDict = {'chargeIndex': lineInfo['port'],
  247. 'reason': lineInfo['reason'],
  248. 'elec': spendElec, 'actualNeedTime': u'动态功率计算为%s分钟' % actualNeedTime,
  249. 'duration': usedTime,
  250. 'elecFee': self.calc_elec_fee(spendElec)}
  251. ServiceProgress.update_progress_and_consume_rcd(
  252. self.device['ownerId'],
  253. {'open_id': lineInfo['openId'], 'device_imei': self.device['devNo'],
  254. 'port': lineInfo['port'], 'isFinished': False}, consumeDict
  255. )
  256. consumeRcdId = lineInfo.get('consumeRcdId', None)
  257. if consumeRcdId is None:
  258. logger.info('can not find consume rcd id')
  259. return
  260. try:
  261. vCardConsumeRcd = VCardConsumeRecord.objects.get(id = consumeRcdId)
  262. except DoesNotExist, e:
  263. logger.info('can not find the consume rcd id = %s' % consumeRcdId)
  264. return
  265. vCard.refund_quota(vCardConsumeRcd, usedTime, spendElec, backCoins.mongo_amount)
  266. elif cardId != '': # 刷卡的方式,分ID卡和IC卡两种
  267. card = Card.objects.get(id = cardId)
  268. if card.cardType == 'ID':
  269. consumeDict = {'chargeIndex': lineInfo['port'], 'leftTime': leftTimeStr,
  270. 'reason': lineInfo['reason'], 'actualNeedTime': u'动态功率计算为%s分钟' % actualNeedTime,
  271. 'elec': spendElec, 'duration': usedTime, 'needElec': lineInfo['needElec'],
  272. 'elecFee': self.calc_elec_fee(spendElec)}
  273. if billingType == 'time':
  274. self.notify_user(card.managerialOpenId if card else '', 'service_complete',
  275. **{
  276. 'title': u'%s 卡号:%s(%s),按动态功率计算总时间为:%s分钟,剩余时间:%s分钟' % (
  277. self.event_data['reason'],
  278. card.cardNo,
  279. card.cardName,
  280. actualNeedTime,
  281. leftTimeStr),
  282. 'service': u'充电服务(设备编号:%s,端口:%s 地址:%s)' % (
  283. self.device['logicalCode'], self.event_data['port'],
  284. group['address']),
  285. 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
  286. 'remark': u'谢谢您的支持'
  287. })
  288. ServiceProgress.update_progress_and_consume_rcd(
  289. self.device['ownerId'],
  290. {'cardId': cardId, 'device_imei': self.device['devNo'],
  291. 'port': lineInfo['port'], 'isFinished': False},
  292. {'chargeIndex': lineInfo['port'], 'leftTime': leftTimeStr,
  293. 'needTime': u'刷卡订购%s分钟' % needTime, 'reason': lineInfo['reason'],
  294. 'elec': spendElec, 'duration': usedTime,
  295. 'actualNeedTime': u'动态功率计算为%s分钟' % actualNeedTime,
  296. 'elecFee': self.calc_elec_fee(spendElec)})
  297. if not self.device.is_auto_refund:
  298. consumeDict.update({
  299. DEALER_CONSUMPTION_AGG_KIND.CONSUME_CARD: money.mongo_amount
  300. })
  301. ServiceProgress.update_progress_and_consume_rcd(
  302. self.device['ownerId'],
  303. {'cardId': cardId, 'device_imei': self.device['devNo'],
  304. 'port': lineInfo['port'], 'isFinished': False}, consumeDict
  305. )
  306. return
  307. else:
  308. consumeDict.update({
  309. DEALER_CONSUMPTION_AGG_KIND.REFUND_CARD: backCoins.mongo_amount,
  310. DEALER_CONSUMPTION_AGG_KIND.CONSUME_CARD: (money - backCoins).mongo_amount
  311. })
  312. self.refund_money_for_card(backCoins, str(card.id))
  313. ServiceProgress.update_progress_and_consume_rcd(
  314. self.device['ownerId'],
  315. {'open_id': lineInfo['openId'], 'device_imei': self.device['devNo'],
  316. 'port': lineInfo['port'], 'isFinished': False}, consumeDict)
  317. leftTimeStr = leftTime if leftTime != 65535 else lineInfo['needTime']
  318. desc = u'您使用的%s号端口充电,共付款:%s元,充电预定时间为:%s分钟,剩余时间:%s分钟,给您退款:%s元' % (
  319. lineInfo['port'], money, lineInfo['needTime'], leftTimeStr, backCoins)
  320. self.notify_user(card.managerialOpenId if card else '', 'refund_coins', **{
  321. 'title': desc,
  322. 'backCount': u'金币:%s' % backCoins,
  323. 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
  324. })
  325. return
  326. else:
  327. self.notify_user(card.managerialOpenId if card else '', 'service_complete',
  328. **{
  329. 'title': u'%s 卡号:%s(%s),%s元购买%s度电量,实际使用电量为:%s度' % (
  330. self.event_data['reason'],
  331. card.cardNo,
  332. card.cardName,
  333. money,
  334. lineInfo['needElec'],
  335. spendElec),
  336. 'service': u'充电服务(设备编号:%s,端口:%s 地址:%s)' % (
  337. self.device['logicalCode'], self.event_data['port'],
  338. group['address']),
  339. 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
  340. 'remark': u'谢谢您的支持'
  341. })
  342. consumeDict = {'chargeIndex': lineInfo['port'], 'leftTime': leftTimeStr,
  343. 'reason': lineInfo['reason'],
  344. 'elec': spendElec, 'duration': usedTime, 'needElec': lineInfo['needElec'],
  345. 'elecFee': self.calc_elec_fee(spendElec)}
  346. if not self.device.is_auto_refund:
  347. consumeDict.update({
  348. DEALER_CONSUMPTION_AGG_KIND.CONSUME_CARD: money.mongo_amount
  349. })
  350. ServiceProgress.update_progress_and_consume_rcd(
  351. self.device['ownerId'],
  352. {'cardId': cardId, 'device_imei': self.device['devNo'],
  353. 'port': lineInfo['port'], 'isFinished': False}, consumeDict
  354. )
  355. else:
  356. consumeDict.update({
  357. DEALER_CONSUMPTION_AGG_KIND.REFUND_CARD: backCoins.mongo_amount,
  358. DEALER_CONSUMPTION_AGG_KIND.CONSUME_CARD: (money - backCoins).mongo_amount
  359. })
  360. self.refund_money_for_card(backCoins, str(card.id))
  361. ServiceProgress.update_progress_and_consume_rcd(
  362. self.device['ownerId'],
  363. {'open_id': lineInfo['openId'], 'device_imei': self.device['devNo'],
  364. 'port': lineInfo['port'], 'isFinished': False}, consumeDict)
  365. desc = u'您使用的%s号端口充电,共付款:%s元,充电预定电量为:%s度,使用:%s度,给您退款:%s元' % (
  366. lineInfo['port'], money, lineInfo.get('needElec', 0.0), spendElec, backCoins)
  367. self.notify_user(card.managerialOpenId if card else '', 'refund_coins', **{
  368. 'title': desc,
  369. 'backCount': u'金币:%s' % backCoins,
  370. 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
  371. })
  372. else: # IC卡
  373. self.notify_user(card.managerialOpenId if card else '', 'service_complete',
  374. **{
  375. 'title': u'%s 卡号:%s(%s),总时间为:%s分钟' % (
  376. self.event_data['reason'],
  377. card.cardNo,
  378. card.cardName,
  379. usedTime),
  380. 'service': u'充电服务(设备编号:%s,端口:%s 地址:%s)' % (
  381. self.device['logicalCode'], self.event_data['port'], group['address']),
  382. 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
  383. 'remark': u'谢谢您的支持'
  384. })
  385. ServiceProgress.update_progress_and_consume_rcd(
  386. self.device['ownerId'],
  387. {'cardId': cardId, 'device_imei': self.device['devNo'],
  388. 'port': lineInfo['port'], 'isFinished': False},
  389. {'chargeIndex': lineInfo['port'], 'leftTime': leftTimeStr,
  390. 'needTime': u'刷卡订购%s分钟' % needTime, 'reason': lineInfo['reason'],
  391. 'elec': spendElec, 'duration': usedTime,
  392. 'actualNeedTime': u'动态功率计算为%s分钟' % actualNeedTime,
  393. 'elecFee': self.calc_elec_fee(spendElec)})
  394. return
  395. elif consumeType == 'coin':
  396. CoinConsumeRcd = ConsumeRecord.objects.get(
  397. orderNo = lineInfo['consumeOrderNo']) # type: ConsumeRecord
  398. CoinConsumeRcd.servicedInfo['elec'] = spendElec
  399. CoinConsumeRcd.servicedInfo['actualNeedTime'] = u'动态功率计算为%s分钟' % actualNeedTime
  400. CoinConsumeRcd.servicedInfo['needTime'] = u'投币订购%s分钟' % needTime
  401. CoinConsumeRcd.servicedInfo['reason'] = lineInfo['reason']
  402. CoinConsumeRcd.servicedInfo['chargeIndex'] = lineInfo['port']
  403. CoinConsumeRcd.finishedTime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
  404. CoinConsumeRcd.save()
  405. valueDict = {
  406. DEALER_CONSUMPTION_AGG_KIND.ELEC: spendElec,
  407. DEALER_CONSUMPTION_AGG_KIND.ELECFEE: self.calc_elec_fee(spendElec)
  408. }
  409. status = CoinConsumeRcd.update_agg_info(valueDict)
  410. if status:
  411. record_consumption_stats(CoinConsumeRcd)
  412. else:
  413. logger.error(
  414. '[update_progress_and_consume_rcd] failed to update_agg_info record=%r' % (CoinConsumeRcd,))
  415. except Exception, e:
  416. logger.exception('deal with jingneng devNo=%s event e=%s' % (devNo, e))
  417. finally:
  418. Device.clear_port_control_cache(devNo, str(self.event_data['port']))
  419. try:
  420. dataDict = {'backMoney': backPrice, 'backCoins': backCoins.mongo_amount}
  421. if lineInfo.has_key('orderNo'):
  422. dataDict.update({'orderNo': lineInfo['orderNo']})
  423. notify_event_to_north_v2(self.device["devNo"], self.event_data)
  424. notify_event_to_north(self.dealer, self.device, level = Const.EVENT_NORMAL,
  425. desc = self.event_data['reason'], dataDict = dataDict)
  426. except Exception:
  427. pass
  428. elif self.event_data['cmdCode'] == '20': # 启动了端口,主要记录下投币数据
  429. consumeType = self.event_data['consumeType']
  430. if consumeType == 'coin':
  431. self.event_data.update({'startTime': datetime.datetime.now().strftime(Const.DATETIME_FMT)})
  432. Device.update_port_control_cache(self.device['devNo'], self.event_data) # 记录该端口累计需要的时间和钱,cardId
  433. Accounting.recordOfflineCoin(self.device,
  434. int(time.time()),
  435. int(self.event_data['coins']),
  436. port = self.event_data.get('port', None))
  437. self.event_data.update({'needElec': self.event_data['elec']})
  438. self.event_data.update({'consumeOrderNo': self.record_consume_for_coin(RMB(self.event_data['coins']))})
  439. Device.update_port_control_cache(self.device['devNo'], self.event_data)
  440. elif consumeType == 'card':
  441. port = self.event_data['port']
  442. consumeDict = {'chargeIndex': port, 'elec': self.event_data['elec'],
  443. 'money': self.event_data['coins'], 'needTime': u'刷卡订购%s分钟' % self.event_data['needTime']}
  444. queryDict = {'device_imei': self.device['devNo'],
  445. 'port': -1, 'isFinished': False,
  446. 'cardId': {'$ne': ''}, 'start_time': {'$gte': int(time.time()) - 3600}}
  447. progressDict = {'port': port}
  448. ServiceProgress.update_progress_and_consume_rcd(ownerId = self.device['ownerId'], queryDict = queryDict,
  449. consumeDict = consumeDict, updateConsume = True,
  450. progressDict = progressDict)
  451. # 找出对应的卡的ID记录到端口内存数据
  452. queryDict.update(progressDict)
  453. rcds = ServiceProgress.get_collection().find(queryDict, {'cardId': 1, 'open_id': 1},
  454. sort = [('start_time', -1)])
  455. if rcds.count() == 0:
  456. return
  457. rcd = rcds[0]
  458. dev = Device.objects.get(devNo = self.device['devNo'])
  459. billingType = dev.otherConf.get('billingType', 'time')
  460. self.event_data.update({'billingType': billingType})
  461. self.event_data.update({'cardId': rcd['cardId']})
  462. self.event_data.update({'openId': rcd['open_id']})
  463. self.event_data.update({'coins': self.event_data['coins']})
  464. self.event_data.update({'needElec': self.event_data['elec']})
  465. self.event_data.update({'needTime': self.event_data['needTime']})
  466. self.event_data.update({'startTime': datetime.datetime.now().strftime(Const.DATETIME_FMT)})
  467. self.event_data.update({'isStart': True, 'status': Const.DEV_WORK_STATUS_WORKING})
  468. Device.update_port_control_cache(self.device['devNo'], self.event_data)
  469. elif consumeType == 'server':
  470. port = self.event_data['port']
  471. # 强制更新信息, 避免代码进入错误流程
  472. Device.update_port_control_cache(self.device['devNo'], self.event_data) # 记录该端口累计需要的时间和钱
  473. consumeDict = {'chargeIndex': self.event_data['port'], 'elec': self.event_data['elec'],
  474. 'needTime': u'订购%s分钟' % self.event_data['needTime']}
  475. queryDict = {'device_imei': self.device['devNo'],
  476. 'port': port, 'isFinished': False,
  477. 'start_time': {'$gte': int(time.time()) - 3600}}
  478. progressDict = {'port': self.event_data['port']}
  479. ServiceProgress.update_progress_and_consume_rcd(ownerId = self.device['ownerId'],
  480. queryDict = queryDict, consumeDict = consumeDict,
  481. updateConsume = True, progressDict = progressDict)
  482. elif self.event_data['cmdCode'] == '11' and self.event_data['oper'] == '01': # IC卡扣费
  483. cardType = self.event_data['cardType']
  484. card = self.update_card_dealer_and_type(self.event_data['cardNo'], cardType)
  485. fee = RMB(self.event_data['preFee'])
  486. card.balance = RMB(self.event_data['balance']) - fee
  487. try:
  488. card.save()
  489. except Exception, e:
  490. logger.exception(e)
  491. orderNo, cardOrderNo = self.record_consume_for_card(card, fee)
  492. # 记录当前服务的progress.没有上报端口号,所以先用-1标记,表示端口未知。端口等消费的时候会报上来
  493. ServiceProgress.register_card_service(self.device, self.event_data['port'], card,
  494. {'orderNo': orderNo, 'money': self.event_data['preFee'],
  495. 'coin': self.event_data['preFee'], 'cardOrderNo': cardOrderNo})
  496. # 通知微信,已经扣费
  497. self.notify_balance_has_consume_for_card(card, fee)
  498. self.event_data.update({'cardId': str(card.id)})
  499. self.event_data.update({'openId': card.openId})
  500. self.event_data.update({'coins': self.event_data['preFee']})
  501. self.event_data.update({'startTime': datetime.datetime.now().strftime(Const.DATETIME_FMT)})
  502. self.event_data.update({'isStart': True, 'status': Const.DEV_WORK_STATUS_WORKING})
  503. Device.update_port_control_cache(self.device['devNo'], self.event_data) # 记录该端口累计需要的时间和钱,cardId
  504. elif self.event_data['cmdCode'] == '11' and self.event_data['oper'] == '03': # IC卡退费
  505. card = self.update_card_dealer_and_type(self.event_data['cardNo'], 'IC')
  506. self.refund_money_for_card(RMB(self.event_data['preFee']), card.id)
  507. elif self.event_data['cmdCode'] == '12':
  508. cardNo = self.event_data['cardNo']
  509. card = self.update_card_dealer_and_type(cardNo, 'IC') # type: Card
  510. if card.frozen:
  511. logger.debug('{} has been frozen.'.format(repr(card)))
  512. return
  513. preBalance = RMB(self.event_data['balance'])
  514. order = CardRechargeOrder.get_last_to_do_one(str(card.id)) # type: CardRechargeOrder
  515. # 为了测试,测试OK删除
  516. if order.money == RMB(0.0):
  517. try:
  518. cardData = self.deviceAdapter.recharge_card(cardNo, RMB(0.0))
  519. Card.objects(id = card.id).update_one(set__balance = cardData['balance'])
  520. except Exception as e:
  521. logger.exception('recharge card error=%s' % e)
  522. else:
  523. self.recharge_ic_card(card = card,
  524. preBalance = preBalance,
  525. rechargeType = 'append',
  526. order = order,
  527. need_verify = False)