123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- # -*- coding: utf-8 -*-
- # !/usr/bin/env python
- import datetime
- import logging
- from mongoengine import DoesNotExist
- from apilib.monetary import RMB
- from apilib.utils_datetime import to_datetime
- from apps.web.constant import Const
- from apps.web.device.models import Group, Device
- from apps.web.eventer.base import WorkEvent
- from apps.web.eventer import EventBuilder
- from apps.web.south_intf.platform import notify_event_to_north
- from apps.web.user.models import ServiceProgress, UserVirtualCard, VCardConsumeRecord, Card, MyUser, CardRechargeOrder
- 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 'elec' in device_event:
- event_data.update({'elec': device_event['elec']})
- if event_data['cmdCode'] in ['02', '03', '04', '20']:
- return ChargingMOXIAOZHI2WorkEvent(self.deviceAdapter, event_data)
- return None
- class ChargingMOXIAOZHI2WorkEvent(WorkEvent):
- def do(self, **args):
- devNo = self.device['devNo']
- logger.info('moxiaozhi2 charging event detected, devNo=%s' % (devNo,))
- smartBox = self.deviceAdapter
- if self.event_data['cmdCode'] == '02': # 刷卡,用于查询余额.如果发现有充值订单,马上下发充值
- cardNo = self.event_data['cardNo']
- card = self.update_card_dealer_and_type(cardNo, 'ID') # type: Card
- card_recharge_order = CardRechargeOrder.get_last_to_do_one(str(card.id)) # type: CardRechargeOrder
- result = self.recharge_id_card(card = card,
- rechargeType = 'append',
- order = card_recharge_order)
- card.reload()
- # 如果卡挂失,直接余额为0
- if card.frozen:
- balance = RMB(0)
- else:
- balance = result['balance']
- try:
- smartBox.response_card_balance(cardNo, balance)
- except Exception, e:
- logger.error('response card balance error=%s' % e)
- return
- elif self.event_data['cmdCode'] == '03': # 刷卡,开始结束充电。刷卡是后扣费,移动支付是先扣费,后退费
- group = Group.get_group(self.device['groupId'])
- portInfo = Device.update_port_control_cache(self.device['devNo'], self.event_data, 'overwrite')
- port = portInfo['port']
- card = self.update_card_dealer_and_type(portInfo['cardNo'], 'ID')
- portInfo['openId'] = card.openId
- portInfo['cardId'] = str(card.id)
- portInfo['startTime'] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
- self.event_data.update({'isStart': True, 'status': Const.DEV_WORK_STATUS_WORKING})
- Device.update_port_control_cache(self.device['devNo'], portInfo)
- # 如果是开始报文,最重要的是刷新内存计费相关数据,前面代码已经完成.刷卡不预扣费,等待结束后,直接扣费
- if portInfo['isStart']: # 如果是刷卡启动的,禁用的端口不允许充电
- isNormal = True
- otherConf = Device.objects.get(devNo = self.device['devNo']).otherConf
- if otherConf.has_key(str(port)) and otherConf[str(port)] == Const.DEV_WORK_STATUS_FORBIDDEN:
- logger.info('this port is forbidden port=%s' % (port,))
- isNormal = False
- # 刷卡启动,需要等级正在服务的progress
- ServiceProgress.register_card_service(self.device, port, card)
- try:
- smartBox.response_card_charging(isNormal)
- except Exception, e:
- logger.exception('response card=%s e=%s' % (portInfo['cardNo'], e))
- else:
- #: 结束,就需要扣费咯.先支持按时间扣费,后续再支持按电量扣费 ------------比较奇怪,从来没有收到这个协议
- #: 回复设备
- try:
- smartBox.response_card_charging(True)
- except Exception, e:
- logger.exception('response devNo=%s card charging e=%s' % (self.device['devNo'], e))
- if self.event_data.has_key('duration') and self.event_data['duration'] > 0:
- duration = self.event_data['duration']
- else:
- duration = (to_datetime(portInfo['endTime']) - to_datetime(
- portInfo['startTime'])).total_seconds() / 60.0
- if duration < 0:
- duration = 0
- if self.event_data.has_key('elec'):
- consumeElec = round(self.event_data['elec'] / 3600.0, 4)
- else:
- consumeElec = 0.03 * duration / 0.9 # 这里做个特殊的保护,只有模块出现异常的时候,但是需要计费
- if consumeElec < 0:
- consumeElec = 0
- consumeMoney, desc = smartBox.calc_consume_money(duration, consumeElec)
- card = self.update_card_dealer_and_type(portInfo['cardNo'], 'ID')
- self.consume_money_for_card(card, consumeMoney)
- self.record_consume_for_card(card, consumeMoney, desc = u'充电时间:%s分钟,充电电量%s度' % (duration, consumeElec))
- desc = u'您本次充电约:%s分钟,收费标准为:%s,共计花费:%s元' % (duration, desc, consumeMoney)
- self.notify_balance_has_consume_for_card(card, consumeMoney)
- self.notify_user(card.managerialOpenId if card else '', 'service_complete',
- **{
- 'title': desc,
- '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 self.event_data['cmdCode'] in ['04', '20']: # 收到的结束事件
- portInfo = Device.update_port_control_cache(self.device['devNo'], self.event_data)
- port = self.event_data['port']
- try:
- # 回复设备,04号报文是设备主动停止的,所以需要我们回复一条消息过去
- if self.event_data['cmdCode'] == '04':
- try:
- smartBox.response_finished_back(True)
- except Exception, e:
- logger.error('response devNo=%s card charging e=%s' % (self.device['devNo'], e))
- # 如果是开始报文,最重要的是刷新内存计费相关数据,前面代码已经完成.刷卡不预扣费,等待结束后,直接扣费
- if self.event_data['isStart']:
- pass
- else: # 结束,就需要扣费咯.支持按时间扣费,也支持按电量扣费
- if self.event_data.has_key('duration') and self.event_data['duration'] > 0:
- duration = self.event_data['duration']
- else:
- duration = (datetime.datetime.now() - to_datetime(portInfo['startTime'])).total_seconds() / 60.0
- if duration < 0:
- duration = 0
- if self.event_data.has_key('elec'):
- consumeElec = round(self.event_data['elec'] / 3600.0, 4)
- else:
- consumeElec = 0.03 * duration / 0.9 # 这里做个特殊的保护,只有模块出现异常的时候,但是需要计费
- if consumeElec < 0:
- consumeElec = 0
- if (not portInfo.has_key('cardNo')) and portInfo.has_key('openId') and (
- not portInfo.has_key('consumeRcdId')): # 非刷卡的是退费,刷卡的结束扣费。两种方式不一样
- consumeMoney, descFee = smartBox.calc_consume_money(duration, consumeElec)
- backMoney = RMB(portInfo['coins']) - consumeMoney
- if backMoney > RMB(0):
- refund_money(self.device, backMoney, portInfo['openId'])
- else:
- backMoney = RMB(0)
- desc = u'您本次充电使用%s号端口,共计:%s分钟,收费标准为:%s,共计花费:%s元,您预支了:%s元,退回:%s元到您的个人中心中。' % \
- (port, duration, descFee, consumeMoney, portInfo['coins'], backMoney)
- consumeDict = {'reason': self.event_data['reason'], 'duration': duration,
- 'feeType': descFee, 'refundedMoney': str(backMoney),
- 'spendMoney': str(consumeMoney), 'chargeIndex': port}
- ServiceProgress.update_progress_and_consume_rcd(self.device['ownerId'],
- {'open_id': portInfo['openId'], 'port': port,
- 'device_imei': self.device['devNo'],
- 'isFinished': False},
- consumeDict)
- user = MyUser.objects(openId = portInfo['openId'], groupId = self.device['groupId']).first()
- self.notify_user(user.managerialOpenId if user else '', 'refund_coins',
- **{
- 'title': '%s%s' % (self.event_data['reason'], desc),
- 'backCount': u'金币:%s' % backMoney,
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
- })
- self.notify_charging_finished(user.managerialOpenId if user else '')
- elif portInfo.has_key('consumeRcdId'):
- consumeMoney, descFee = smartBox.calc_consume_money(duration, consumeElec)
- backMoney = RMB(portInfo['coins']) - consumeMoney
- if backMoney < RMB(0):
- backMoney = RMB(0)
- desc = u'您本次充电使用%s号端口,共计:%s分钟,收费标准为:%s,共计花费:%s元,您预支了:%s元,退回:%s元到您的个人中心中。' % \
- (port, duration, descFee, consumeMoney, portInfo['coins'], backMoney)
- consumeDict = {'reason': self.event_data['reason'], 'duration': duration,
- 'feeType': descFee, 'chargeIndex': port}
- ServiceProgress.update_progress_and_consume_rcd(self.device['ownerId'],
- {'open_id': portInfo['openId'], 'port': port,
- 'device_imei': self.device['devNo'],
- 'isFinished': False},
- consumeDict)
- # 退额度
- try:
- vCardId = portInfo['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(portInfo['openId']) if vCard else '',
- 'refund_coins',
- **{
- 'title': '%s%s' % (self.event_data['reason'], desc),
- 'backCount': u'金币:%s' % backMoney,
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
- })
- consumeRcdId = portInfo.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, duration, consumeElec, backMoney.mongo_amount)
- elif portInfo.has_key('cardNo'):
- card = self.update_card_dealer_and_type(portInfo['cardNo'], 'ID')
- consumeMoney, descFee = smartBox.calc_consume_money(duration, consumeElec)
- self.consume_money_for_card(card, consumeMoney)
- desc = u'您本次充电使用%s号端口,共计:%s分钟,收费标准为:%s,共计花费:%s元' % \
- (port, duration, descFee, consumeMoney)
- consumeDict = {'reason': self.event_data['reason'], 'duration': duration,
- 'feeType': descFee, 'spendMoney': str(consumeMoney),
- 'chargeIndex': port}
- self.record_consume_for_card(card, consumeMoney,
- desc = u'充电时间:%s分钟' % duration,
- servicedInfo = consumeDict)
- ServiceProgress.update_progress_and_consume_rcd(self.device['ownerId'],
- {'cardId': str(card.id), 'port': port,
- 'device_imei': self.device['devNo'],
- 'isFinished': False},
- consumeDict, False)
- self.notify_balance_has_consume_for_card(card, consumeMoney, desc)
- self.notify_charging_finished(card.managerialOpenId)
- finally:
- Device.clear_port_control_cache(self.device['devNo'], str(port))
- notify_event_to_north(self.dealer, self.device, level = Const.EVENT_NORMAL,
- desc = self.event_data['reason'])
|