123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295 |
- # -*- coding: utf-8 -*-
- # !/usr/bin/env python
- import datetime
- import json
- import random
- from typing import TYPE_CHECKING
- from apilib.monetary import RMB, VirtualCoin
- from apilib.utils_datetime import to_datetime
- from apps.web.device.models import Device
- from apps.web.eventer.base import WorkEvent, logger
- from apps.web.eventer import EventBuilder
- from apps.web.user.transaction_deprecated import refund_money
- from apps.web.user.models import Card, UserVirtualCard, ServiceProgress, VCardConsumeRecord, MyUser
- if TYPE_CHECKING:
- from apps.web.device.models import GroupDict
- class builder(EventBuilder):
- def __getEvent__(self, device_event):
- event_data = self.deviceAdapter.analyze_event_data(device_event.get("data"))
- logger.info("lz_reve event eventData:{}".format(json.dumps(event_data, ensure_ascii=False)))
- return CFJWorkEvent(self.deviceAdapter, event_data)
- class CFJWorkEvent(WorkEvent):
- def _parse_device_finished_data(self, event_data):
- duration = event_data.get('duration', -1)
- if duration != -1:
- if 'v' in event_data:
- duration = ((duration + 59) / 60)
- elec = event_data.get('elec', -1)
- if elec != -1:
- if 'v' in event_data:
- elec = round(elec / (10000.0 * 3600.0), 3)
- else:
- elec = round(elec / 3600.0, 3)
- logger.debug('device duration is {}, device elec is {}'.format(duration, elec))
- return duration, elec
- def do(self, **args):
- cmd = self.event_data.get("cmd", "E")
- if cmd == "E":
- logger.info("cfj_no this event!!!! event_data: {}".format(json.dumps(self.event_data, ensure_ascii=False)))
- return
- elif cmd == "05":
- logger.info("cfj_is finished event event_data: {}".format(json.dumps(self.event_data, ensure_ascii=False)))
- devNo = self.device.devNo
- port = str(self.event_data.get('port','1'),)
- try:
- ctrInfo = Device.get_dev_control_cache(devNo)
- lineInfo = ctrInfo.get(port)
- if not lineInfo:
- logger.debug('cfj_get null control cache from {}'.format(repr(self.device)))
- return
- billingType = lineInfo.get("billingType", "time")
- if billingType == "time":
- self._do_time_finish(devNo, port, lineInfo, self.event_data)
- except Exception as e:
- logger.error("cfj_do finished event is error!!! e={} event_data: {}".format(e,
- json.dumps(self.event_data, ensure_ascii=False)))
- finally:
- Device.clear_port_control_cache(devNo, str(port))
- def _do_time_finish(self, devNo, port, lineInfo, msgDict):
- refundProtectionTime = lineInfo.get('refundProtectionTime', 0)
- deviceDuration, deviceElec = self._parse_device_finished_data(self.event_data)
- if lineInfo is not None and 'startTime' in lineInfo:
- startTime = to_datetime(lineInfo['startTime'])
- nowTime = datetime.datetime.now()
- if startTime > nowTime:
- logger.error('start time is bigger than now time,devNo={}'.format(devNo))
- serverDuration = -1
- else:
- serverDuration = int(round((((nowTime - startTime).total_seconds() + 59) / 60.0)))
- else:
- logger.info('lineinfo has not startTime,devNo=%s' % devNo)
- serverDuration = -1
- if deviceDuration > 0:
- usedTime = deviceDuration
- elif serverDuration >= 0:
- usedTime = serverDuration
- else:
- usedTime = -1
- leftTime = int(self.event_data['leftTime'])
- if leftTime != 65535:
- leftTimeStr = leftTime
- if usedTime == -1:
- actualNeedTime = -1
- else:
- actualNeedTime = usedTime + leftTime
- else:
- leftTimeStr = u'端口未使用'
- actualNeedTime = 0
- group = self.device.group # type: GroupDict
- if actualNeedTime == -1:
- if 'cardNo' in self.event_data and self.event_data['cardNo']:
- card = Card.objects(cardNo=str(self.event_data['cardNo']), agentId=self.dealer.agentId).first()
- if card:
- self.notify_user_service_complete(
- service_name=u'使用吹风机',
- openid=card.managerialOpenId if card else '',
- port=port,
- address=group['address'],
- reason=self.event_data['reason'],
- finished_time=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- extra=[{
- u'实体卡号': self.event_data['cardNo']
- }]
- )
- logger.debug('has no actual need time. ignore this event.')
- return
- consumeDict = {
- 'reason': self.event_data['reason'],
- 'leftTime': leftTimeStr,
- 'chargeIndex': port,
- 'actualNeedTime': u'动态计算时间为%s分钟' % actualNeedTime,
- 'duration': usedTime,
- # 'deviceDuration': deviceDuration,
- # 'serverDuration': serverDuration
- }
- if deviceElec != -1:
- consumeDict.update({'elec': deviceElec})
- else:
- deviceObj = Device.objects(devNo=self.device.devNo).first()
- if deviceObj.otherConf.get('zhuxing', None) is not None:
- spendElec = round((float(random.randint(15, 19)) / 100) * (float(usedTime) / 60), 3)
- consumeDict.update({'elec': spendElec})
- consumeDict.update({'elecFee': self.deviceAdapter.calc_elec_fee(spendElec)})
- else:
- spendElec = 0.0
- consumeDict.update({'elec': 0.0})
- consumeDict.update({'elecFee': RMB(0.0).mongo_amount})
- if 'cardNo' in lineInfo and lineInfo['cardNo']:
- # 如果是刷卡的,直接更新消费记录,发通知消息,支持ID卡的退费。
- # IC卡的退费, 如果结束原因是刷卡退费(05), 则会把退费信息返回;
- # 否则不会把退费信息传过来,会通过11号命令返回
- card = Card.objects(cardNo=lineInfo['cardNo'], agentId=self.dealer.agentId).first()
- if not card:
- logger.error('not exist this card no.')
- return
- if self.event_data['cardType'] == 'ID':
- consumeDict.update({'balance': str(card.balance + VirtualCoin(self.event_data['backMoney']))})
- if self.event_data.has_key('backMoney') and self.event_data['backMoney'] > 0:
- self.refund_money_for_card(VirtualCoin(self.event_data['backMoney']), card.id)
- # 通知微信,已经退费
- self.notify_user(card.managerialOpenId, 'refund_coins', **{
- 'title': u'退币完成!您的卡号是%s,卡别名:%s' % (card.cardNo, card.nickName),
- 'backCount': u'金币:%s' % VirtualCoin(self.event_data['backMoney']),
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
- })
- else:
- # IC 并且结束code是05 表示卡贴上去了
- if self.event_data['endType'] == '05': # 刷卡退费结束的时候,才能够刷新IC卡的余额
- self.refund_money_for_card(VirtualCoin(self.event_data['backMoney']), card.id)
- consumeDict.update({'balance': str(card.balance + VirtualCoin(self.event_data['backMoney']))})
- else:
- consumeDict.update({'balance': str(card.balance)}) # IC卡必须下次刷卡的时候回收上来
- ServiceProgress.update_progress_and_consume_rcd(self.device.ownerId,
- {'open_id': lineInfo['openId'], 'port': int(port),
- 'device_imei': self.device.devNo,
- 'isFinished': False}, consumeDict)
- extra = [{
- u'实体卡号': lineInfo['cardNo']
- }]
- if VirtualCoin(self.event_data['backMoney']) > VirtualCoin(0):
- extra.append({
- u'退费金额': u'{}(金币)'.format(self.event_data['backMoney'])
- })
- self.notify_user_service_complete(
- service_name=u'充电',
- openid=card.managerialOpenId if card else '',
- port=port,
- address=group['address'],
- reason=self.event_data['reason'],
- finished_time=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- extra=extra)
- else:
- # 计算退费信息
- coins = VirtualCoin(lineInfo['coins'])
- backCoins = VirtualCoin(0)
- if self.device.is_auto_refund:
- if leftTime != 65535:
- backCoins = coins * (float(leftTime) / float(actualNeedTime))
- else:
- backCoins = coins
- # if (refundProtection == 1 and usedTime < refundProtectionTime) and backCoins != VirtualCoin(0):
- if usedTime < refundProtectionTime and backCoins != VirtualCoin(0):
- backCoins = coins
- if backCoins > coins:
- backCoins = coins
- logger.debug(
- 'lefttime = {}, usedTime = {}, need time = {}, back coins = {}'.format(leftTime, usedTime,
- actualNeedTime,
- backCoins))
- if 'consumeRcdId' in lineInfo and lineInfo['consumeRcdId']:
- vCardId = lineInfo['vCardId']
- vCard = UserVirtualCard.objects(id=vCardId).first() # type: UserVirtualCard
- if not vCard:
- logger.info('can not find the vCard id = %s' % vCardId)
- return
- try:
- ServiceProgress.update_progress_and_consume_rcd(self.device.ownerId,
- {'open_id': lineInfo['openId'],
- 'port': int(port),
- 'device_imei': self.device.devNo,
- 'isFinished': False}, consumeDict)
- if backCoins > VirtualCoin(0):
- vCardConsumeRcd = VCardConsumeRecord.objects.get(id=lineInfo['consumeRcdId'])
- vCard.refund_quota(vCardConsumeRcd, usedTime, 0.0, backCoins.mongo_amount)
- finally:
- user = MyUser.objects(openId=lineInfo['openId'],
- groupId=self.device.groupId).first()
- self.notify_user_service_complete(
- service_name=u'充电',
- openid=user.managerialOpenId if user else '',
- port=port,
- address=group['address'],
- reason=self.event_data['reason'],
- finished_time=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- extra=[
- {u'虚拟卡号': vCard.cardNo}
- ]
- )
- elif 'openId' in lineInfo and lineInfo['openId']:
- try:
- if backCoins > VirtualCoin(0):
- consumeDict.update({'refundedMoney': str(backCoins)})
- 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)
- finally:
- extra = []
- if backCoins > VirtualCoin(0):
- extra.append({u'消费金额': '{}(金币)'.format(coins - backCoins)})
- extra.append({u'退款金额': '{}(金币)'.format(backCoins)})
- else:
- extra.append({u'消费金额': '{}(金币)'.format(coins)})
- user = MyUser.objects(openId=lineInfo['openId'],
- groupId=self.device.groupId).first()
- self.notify_user_service_complete(
- service_name=u'充电',
- openid=user.managerialOpenId if user else '',
- port=port,
- address=group['address'],
- reason=self.event_data['reason'],
- finished_time=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- extra=extra
- )
- else:
- logger.error('not net pay rather user virtual card pay. something is wrong.')
|