123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- # -*- coding: utf-8 -*-
- # !/usr/bin/env python
- import datetime
- import logging
- from mongoengine import DoesNotExist
- from apilib.monetary import RMB, VirtualCoin
- from apilib.utils_datetime import to_datetime
- from apps.web.constant import Const, DEALER_CONSUMPTION_AGG_KIND
- from apps.web.device.models import Group, Device
- from apps.web.eventer.base import WorkEvent, FaultEvent
- from apps.web.eventer import EventBuilder
- from apps.web.user.models import ServiceProgress, MyUser, CardRechargeOrder, UserVirtualCard, \
- VCardConsumeRecord, Card
- from apps.web.user.transaction_deprecated import refund_money
- logger = logging.getLogger(__name__)
- 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 'duration' in device_event:
- event_data.update({'duration': device_event['duration']})
- if event_data['cmdCode'] in ['05', '04', '12']:
- return ChargingXUZHOUWorkEvent(self.deviceAdapter, event_data)
- if event_data['cmdCode'] == '0D':
- return FaultEvent(self.deviceAdapter, event_data)
- class ChargingXUZHOUWorkEvent(WorkEvent):
- def do(self, **args):
- devNo = self.device['devNo']
- logger.info('xuzhoudianzi charging event detected, devNo=%s' % (devNo,))
- if self.event_data['cmdCode'] == '05':
- port = str(self.event_data['port'])
- try:
- ctrInfo = Device.get_dev_control_cache(self.device['devNo'])
- lineInfo = ctrInfo.get(port)
- if 'duration' in self.event_data and self.event_data['duration'] > 0:
- usedTime = self.event_data['duration']
- else:
- if (not lineInfo) or (not lineInfo.has_key('startTime')):
- return
- startTime = to_datetime(lineInfo['startTime'])
- nowTime = datetime.datetime.now()
- if startTime > nowTime: # 如果web服务器时间和事件监控服务器时间不一致,导致开始时间比事件时间还大
- usedTime = 0
- else:
- usedTime = int(round(((nowTime - startTime).total_seconds() / 60.0)))
- group = Group.get_group(self.device['groupId'])
- consumeDict = {'reason': self.event_data['reason'], 'chargeIndex': port, 'duration': usedTime}
- isBackCoins = self.device.is_auto_refund
- backCoins = self.event_data['leftMoney']
- if isBackCoins:
- consumeDict.update({
- DEALER_CONSUMPTION_AGG_KIND.REFUNDED_COINS: VirtualCoin(backCoins).mongo_amount,
- })
- # 如果是刷卡的,直接更新消费记录,然后发送通知消息,不支持退费
- if lineInfo.has_key('cardNo'):
- card = Card.objects(cardNo = lineInfo['cardNo'], agentId = self.dealer.agentId).first()
- consumeDict.update({'balance': lineInfo['balance']})
- ServiceProgress.update_progress_and_consume_rcd(self.device['ownerId'],
- {'open_id': lineInfo['openId'], 'port': int(port),
- 'device_imei': self.device['devNo'],
- 'isFinished': False}, consumeDict)
- # 通知服务结束
- self.notify_user(card.managerialOpenId if card else '', 'service_complete',
- **{
- 'title': u'%s 卡号:%s,剩余时间:%s分钟' % (
- self.event_data['reason'],
- lineInfo['cardNo'],
- usedTime,
- 0),
- 'service': u'充电服务(设备编号:%s, 端口:%s,地址:%s)' % (
- self.device['logicalCode'], port, group['address']),
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- 'remark': u'谢谢您的支持'
- })
- elif lineInfo.has_key('consumeRcdId'):
- # 退额度
- try:
- vCardId = lineInfo['vCardId']
- vCard = UserVirtualCard.objects.get(id = vCardId)
- except DoesNotExist, e:
- logger.info('can not find the vCard id = %s' % vCardId)
- return
- # 通知服务结束
- self.notify_user(self.get_managerialOpenId_by_openId(lineInfo['openId']) if vCard else '',
- 'service_complete',
- **{
- 'title': u'%s,退费:%s元' % (
- self.event_data['reason'], backCoins) if not isBackCoins else self.event_data[
- 'reason'],
- 'service': u'充电服务(设备编号:%s, 端口:%s,地址:%s)' % (
- self.device['logicalCode'], port, group['address']),
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- 'remark': u'谢谢您的支持'
- })
- ServiceProgress.update_progress_and_consume_rcd(self.device['ownerId'],
- {'open_id': lineInfo['openId'], 'port': int(port),
- 'device_imei': self.device['devNo'],
- 'isFinished': False}, consumeDict)
- consumeRcdId = lineInfo.get('consumeRcdId', None)
- if consumeRcdId is None:
- logger.info('can not find consume rcd id')
- return
- try:
- vCardConsumeRcd = VCardConsumeRecord.objects.get(id = consumeRcdId)
- except DoesNotExist, e:
- logger.info('can not find the consume rcd id = %s' % consumeRcdId)
- return
- vCard.refund_quota(vCardConsumeRcd, usedTime, 0.0, backCoins)
- else:
- if not lineInfo.has_key('openId'):
- return
- user = MyUser.objects(openId = lineInfo['openId'], groupId = self.device['groupId']).first()
- # 通知服务结束
- self.notify_user(user.managerialOpenId if user else '', 'service_complete',
- **{
- 'title': u'%s,退费:%s元' % (
- self.event_data['reason'], backCoins) if isBackCoins else self.event_data[
- 'reason'],
- 'service': u'充电服务(设备编号:%s, 端口:%s,地址:%s)' % (
- self.device['logicalCode'], port, group['address']),
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- 'remark': u'谢谢您的支持'
- })
- # 如果需要退款,计算退款数据.
- if not isBackCoins:
- ServiceProgress.update_progress_and_consume_rcd(
- self.device['ownerId'],
- {'open_id': lineInfo['openId'], 'port': int(port),
- 'device_imei': self.device['devNo'], 'isFinished': False}, consumeDict)
- else:
- refund_money(self.device, backCoins, lineInfo['openId'])
- ServiceProgress.update_progress_and_consume_rcd(self.device['ownerId'],
- {'open_id': lineInfo['openId'], 'port': int(port),
- 'device_imei': self.device['devNo'],
- 'isFinished': False}, consumeDict)
- self.notify_user(user.managerialOpenId if user else '', 'refund_coins', **{
- 'title': u'%s 退金币:%s元,您下次可以接着使用哦' % (
- self.event_data['reason'], backCoins),
- 'backCount': u'金币:%s' % backCoins,
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
- })
- finally:
- Device.clear_port_control_cache(devNo, str(port))
- elif self.event_data['cmdCode'] == '04':
- cardNo = self.event_data['cardNo']
- card = self.update_card_dealer_and_type(cardNo, 'IC')
- if not card:
- return
- lineInfo = Device.update_port_control_cache(self.device['devNo'], self.event_data)
- lineInfo['openId'] = card.openId
- lineInfo = Device.update_port_control_cache(self.device['devNo'], lineInfo)
- balance = RMB(self.event_data['balance'])
- consumeMoney = RMB(self.event_data['coins'])
- if self.event_data['status'] == '01': # 扣款成功,表示马上需要使用卡了,需要登记
- desc = u'正在刷卡使用,卡号:%s,卡名称:%s,端口号:%s,扣费:%s,余额:%s' % (
- card.cardNo, card.cardName,
- self.event_data['port'],
- self.event_data['coins'], balance)
- orderNo, cardOrderNo = \
- self.record_consume_for_card(card = card,
- money = consumeMoney,
- desc = desc,
- servicedInfo = {
- 'balance': self.event_data['balance'],
- 'coin': self.event_data['coins'],
- 'port': self.event_data['port']})
- # 记录当前服务的progress.没有上报端口号,所以先用-1标记,表示端口未知。端口等消费的时候会报上来
- ServiceProgress.register_card_service(self.device, self.event_data['port'], card,
- {'orderNo': orderNo, 'coin': self.event_data['coins'],
- 'cardOrderNo': cardOrderNo})
- self.notify_balance_has_consume_for_card(card, consumeMoney, desc)
- # 更新下balance,便于刷卡记录中,更新到数据库中
- lineInfo['balance'] = str(balance)
- lineInfo['cardId'] = str(card.id)
- lineInfo['startTime'] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
- lineInfo['isStart'] = True
- lineInfo['status'] = Const.DEV_WORK_STATUS_WORKING
- Device.update_port_control_cache(self.device['devNo'], lineInfo)
- # 如果卡挂失掉了,立马把端口关闭掉
- if card.frozen:
- logger.debug('{} has been frozen.'.format(repr(card)))
- self.deviceAdapter.stop_charging_port(lineInfo['port'])
- elif self.event_data['status'] == '02': # 扣款失败,余额不足
- pass
- elif self.event_data['status'] == '03': # 返现
- balance = balance + consumeMoney
- self.update_card_balance(card, balance)
- elif self.event_data['cmdCode'] == '12': # 电川的板子充值是覆写方式,需要把上次的余额一起累加进来
- cardNo = self.event_data['cardNo']
- card = self.update_card_dealer_and_type(cardNo, 'IC') # type: Card
- if card.frozen:
- logger.debug('{} has been frozen.'.format(repr(card)))
- return
- preBalance = RMB(self.event_data['balance'])
- card_recharge_order = CardRechargeOrder.get_last_to_do_one(str(card.id)) # type: CardRechargeOrder
- self.recharge_ic_card(card = card,
- preBalance = preBalance,
- rechargeType = 'overwrite',
- order = card_recharge_order,
- need_verify = False)
|