123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- # -*- coding: utf-8 -*-
- # !/usr/bin/env python
- import datetime
- import logging
- from apilib.monetary import RMB, VirtualCoin
- from apilib.utils_datetime import to_datetime
- from apps.web.agent.models import Agent
- from apps.web.dealer.models import Dealer
- from apps.web.device.models import Group, Device
- from apps.web.eventer.base import WorkEvent
- from apps.web.eventer import EventBuilder
- from apps.web.eventer.errors import NoCommandHandlerAvailable
- from apps.web.user.models import ServiceProgress, UserVirtualCard, VCardConsumeRecord, MyUser
- from apps.web.user.transaction_deprecated import refund_money
- logger = logging.getLogger(__name__)
- service_id_generator = lambda dev_no, port, ts: '{}_{}_{}'.format(dev_no, port, ts)
- class builder(EventBuilder):
- def __getEvent__(self, device_event):
- event_data = self.deviceAdapter.analyze_event_data(device_event['data'])
- if event_data is None or 'cmdCode' not in event_data:
- return None
- if event_data['cmdCode'] in [0x09]:
- return ChargingNanjiguangWorkEvent(self.deviceAdapter, event_data)
- class ChargingNanjiguangWorkEvent(WorkEvent):
- def do(self, **args):
- devNo = self.device['devNo']
- logger.info('nanjiguang charging event detected, devNo=%s,curInfo=%s' % (devNo, self.event_data))
- cmdCode = self.event_data['cmdCode']
- #: 结束的命令
- if cmdCode in [0x09]:
- group = Group.get_group(self.device['groupId'])
- dealer = Dealer.objects(id = group['ownerId']).first()
- if not dealer:
- logger.error('dealer is not found, dealerId=%s' % group['ownerId'])
- return
- agent = Agent.objects(id = dealer.agentId).first()
- if not agent:
- logger.error('agent is not found, agentId=%s' % dealer.agentId)
- return
- ctrl_info = Device.get_dev_control_cache(self.device['devNo'])
- lineInfo = ctrl_info.get(str(self.event_data['port']))
- if 'ts' not in lineInfo or lineInfo['ts'] != self.event_data['ts']:
- service_progress = ServiceProgress.objects(
- id = service_id_generator(dev_no = devNo, port = self.event_data['port'],
- ts = self.event_data['ts'])).first()
- if not service_progress:
- logger.error(
- 'not find port status info. devNo = {}, port = {}'.format(devNo, self.event_data['port']))
- return
- lineInfo = {
- }
- vCardId = lineInfo.get('vCardId', None)
- coins = VirtualCoin(lineInfo['coins'])
- price = RMB(lineInfo.get('price', 0.0))
- spendTime = int(self.event_data['consumeTime'])
- spendElec = round(float(self.event_data['consumeElec']), 2)
- billingType = lineInfo.get('billingType')
- backCoins, backPrice = VirtualCoin(0.0), RMB(0.0)
- try:
- if billingType == 'autoClose': # 充满自停
- left_elec = lineInfo['needElec'] - spendElec
- if left_elec < 0:
- left_elec = 0
- else:
- backCoins = coins * (float(left_elec) / float(lineInfo['needElec']))
- backPrice = price * (float(left_elec) / float(lineInfo['needElec']))
- startTime = to_datetime(lineInfo['startTime'])
- nowTime = datetime.datetime.now()
- if startTime > nowTime:
- duration = 0
- else:
- duration = int(round(((nowTime - startTime).total_seconds() / 60.0)))
- else:
- leftTime = lineInfo['needTime'] - spendTime
- if leftTime < 0:
- leftTime = 0
- else:
- backCoins = coins * (float(leftTime) / float(lineInfo['needTime']))
- backPrice = price * (float(leftTime) / float(lineInfo['needTime']))
- duration = int(lineInfo['needTime'] / 60.0)
- is_auto_refund = self.device.is_auto_refund
- openId = lineInfo['openId']
- consumeDict = {
- 'chargeIndex': lineInfo['port'],
- 'duration': duration
- }
- if backCoins > VirtualCoin(0):
- consumeDict.update({'refundedMoney': str(backCoins)})
- ServiceProgress.update_progress_and_consume_rcd(
- self.device['ownerId'],
- {'open_id': openId, 'device_imei': self.device['devNo'],
- 'port': lineInfo['port'], 'isFinished': False}, consumeDict)
- if vCardId is None: # 扫码的方式
- if is_auto_refund:
- # 扫码退钱, 退到个人账号
- refund_money(self.device, backCoins, lineInfo['openId'])
- #: 使用的是虚拟卡
- elif vCardId is not None:
- try:
- consumeRcdId = lineInfo.get('consumeRcdId', None)
- if consumeRcdId:
- vCardConsumeRcd = VCardConsumeRecord.objects.get(id = consumeRcdId)
- vCard = UserVirtualCard.objects.get(id = vCardId)
- vCard.refund_quota(vCardConsumeRcd, duration, spendElec, backCoins.mongo_amount)
- except Exception as e:
- logger.exception(e)
- except Exception as e:
- logger.exception('deal with jingneng devNo=%s event e=%s' % (devNo, e))
- finally:
- Device.clear_port_control_cache(devNo, str(self.event_data['port']))
- title = u'充电结束,感谢您的使用!'
- if is_auto_refund and backCoins > 0:
- title = u'充电结束,感谢您的使用!退款金额已经返还到您的账号,请注意查收。'
- if billingType == 'autoClose':
- service_notify = u'自助充电\r\n' \
- u'设备编号:{logicalCode}\r\n' \
- u'充电端口:{port}\r\n' \
- u'预付金额:{money}币\r\n' \
- u'退款金额:{back}币\r\n' \
- u'设备地址:{address}\r\n' \
- u'充电状态:{status}'.format(
- logicalCode = self.device['logicalCode'], port = self.event_data['port'],
- money = coins, back = backCoins,
- address = group['address'],
- status = self.event_data['statusDesc'])
- else:
- service_notify = u'自助充电\r\n' \
- u'设备编号:{logicalCode}\r\n' \
- u'充电端口:{port}\r\n' \
- u'预付金额:{money}币\r\n' \
- u'退款金额:{back}币\r\n' \
- u'订购时间:{reverseTime}\r\n' \
- u'剩余时间:{leftTime}\r\n' \
- u'设备地址:{address}\r\n' \
- u'充电状态:{status}'.format(
- logicalCode = self.device['logicalCode'], port = self.event_data['port'],
- money = coins, back = backCoins,
- reverseTime = lineInfo['needTime'], leftTime = leftTime,
- address = group['address'],
- status = self.event_data['statusDesc'])
- user = MyUser.objects(openId = openId, groupId = self.device['groupId']).first()
- self.notify_user(
- user.managerialOpenId,
- 'service_complete',
- **{
- 'title': title,
- 'service': service_notify,
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- 'remark': u'谢谢您的支持'
- })
- else:
- raise NoCommandHandlerAvailable(
- '[nanjiguang] no command handler for cmd %s, curDevInfo=%s' % (cmdCode, self.event_data))
|