123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700 |
- # -*- coding: utf-8 -*-
- # !/usr/bin/env python
- import datetime
- import logging
- import time
- from decimal import Decimal
- from mongoengine import DoesNotExist
- from apilib.monetary import RMB
- from apilib.utils_datetime import to_datetime
- from apps.web.agent.models import Agent
- from apps.web.constant import Const, DEALER_CONSUMPTION_AGG_KIND
- from apps.web.core.device_define.jndz import CMD_CODE, SWIPE_CARD_PARAM_OP, SWIPE_CARD_RES
- from apps.web.core.accounting import Accounting
- from apps.web.core.exceptions import ServiceException
- from apps.web.device.models import Device, Group
- from apps.web.eventer.base import WorkEvent, FaultEvent
- from apps.web.eventer import EventBuilder
- from apps.web.report.utils import record_consumption_stats
- from apps.web.south_intf.platform import notify_event_to_north
- from apps.web.south_intf.zhejiang_fire import send_event_to_zhejiang
- from apps.web.user.models import VCardConsumeRecord, ServiceProgress, CardRechargeOrder, MyUser, UserVirtualCard, Card, \
- ConsumeRecord
- from apps.web.eventer.errors import EventerError, InvalidOption, NoCommandHandlerAvailable
- 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)
- if event_data is None or 'cmdCode' not in event_data:
- return
- if 'duration' in device_event:
- event_data.update({'duration': device_event['duration']})
- if event_data['cmdCode'] in [CMD_CODE.SWIPE_CARD_10,
- CMD_CODE.DEVICE_SUBMIT_CHARGE_FINISHED_06,
- CMD_CODE.DEVICE_SUBMIT_CHARGE_FINISHED_v2_16,
- CMD_CODE.DEVICE_SUBMIT_OFFLINE_COINS_20]:
- return ChargingGUANGFAWorkEvent(self.deviceAdapter, event_data)
- if event_data['cmdCode'] == CMD_CODE.DEVICE_SUBMIT_DEVICE_FAULT_0A:
- return FaultEvent(self.deviceAdapter, event_data)
- class JNDZEventerFailure(EventerError):
- pass
- class ChargingGUANGFAWorkEvent(WorkEvent):
- def find_busy_ports(self, card):
- result = []
- ctrInfo = Device.get_dev_control_cache(self.device['devNo'])
- for port, value in ctrInfo.items():
- if not str(port).isdigit():
- continue
- if value.get('cardId', '') == str(card.id) and value.get('status', '') == Const.DEV_WORK_STATUS_WORKING:
- result.append(port)
- return result
- def stop_ports(self, ports):
- for port in ports:
- self.deviceAdapter.stop_charging_port(port)
- def do(self, **args):
- devNo = self.device['devNo']
- logger.info('guangfa charging event detected, devNo=%s,curInfo=%s' % (devNo, self.event_data))
- cmdCode = self.event_data['cmdCode']
- #: 刷卡消费的,分为扣费和退费两种
- if cmdCode == CMD_CODE.SWIPE_CARD_10:
- cardNo = self.event_data['cardNo']
- preFee = RMB(self.event_data['preFee'])
- #: 操作符,是充值还是减少 <- (00, 01)
- oper = self.event_data['oper']
- card = self.update_card_dealer_and_type(cardNo)
- #: 经销商限制ID卡, 如果满足直接return
- if not card:
- return
- self.event_data['openId'] = card.openId
- self.event_data['cardId'] = str(card.id)
- self.event_data['startTime'] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
- Device.update_dev_control_cache(devNo, self.event_data)
- #: 首先检查订单,并进行充值
- #: 用户首先在手机客户端充值,需要这个时刻刷卡上报事件将充值的订单同步上来
- card_recharge_order = CardRechargeOrder.get_last_to_do_one(str(card.id))
- result = self.recharge_id_card(card = card,
- rechargeType = 'append',
- order = card_recharge_order)
- card.reload()
- logger.info('guangfa cmdNo(10) - cardNo=%s, openId=%s, result=%s, preFee=%s, curinfo=%s' % (
- cardNo, card.openId, result, preFee, self.event_data))
- virtual_card = card.bound_virtual_card
- # 如果虚拟卡已经绑定,需要检查下今天是否可用,如果可用,有限使用虚拟卡
- vCardCanUse = False
- package = {'coins': float(preFee), 'unit': u'分钟', 'time': 180}
- if virtual_card is not None and card.openId is not None:
- devObj = Device.objects.get(devNo = devNo)
- cardMin = devObj.otherConf.get('cardMin', None)
- if cardMin is not None:
- package = {'coins': float(preFee), 'unit': u'分钟', 'time': int(cardMin)}
- vCardCanUse = virtual_card.can_use_today(package)
- #: 扣费
- if oper == SWIPE_CARD_PARAM_OP.DECR_00:
- # #光法的特殊需求,如果开始是通过刷卡启动设备的,这时再次刷卡,直接把刷卡启动的端口关闭掉,然后不回复任何数据
- # ports = self.find_busy_ports(card)
- # if ports:
- # self.stop_ports(ports)
- # return
- if card.openId == '' or card.frozen:
- res = SWIPE_CARD_RES.INVALID_CARD_02
- leftBalance = RMB(0)
- return self.response_use_card(res, leftBalance)
- # 如果虚拟卡可用,卡的费用不要扣掉,仅仅做记录,但是虚拟卡的额度需要扣掉
- elif vCardCanUse:
- # 记录卡消费记录以及消费记录
- orderNo, cardOrderNo = self.record_consume_for_card(card, money = RMB(0.0), desc = u'使用绑定的虚拟卡')
- # 记录当前服务的progress.没有上报端口号,所以先用-1标记,表示端口未知。端口等消费的时候会报上来
- ServiceProgress.register_card_service(self.device, -1, card,
- {
- 'orderNo': orderNo,
- 'money': self.event_data['preFee'],
- 'coin': self.event_data['preFee'], 'needTime': 0,
- 'cardOrderNo': cardOrderNo
- })
- self.consume_money_for_card(card, money = RMB(0.0))
- group = Group.get_group(self.device['groupId'])
- consumeRcd = virtual_card.consume(openId = card.openId, group = group, dev = self.device,
- package = package,
- attachParas = {}, nickname = card.cardName)
- if consumeRcd is None: # 如果额度没有扣除成功,就用卡
- pass
- else:
- self.response_use_card(SWIPE_CARD_RES.SUCCESS_00, leftBalance = 0)
- # 通知微信,已经扣费
- self.notify_balance_has_consume_for_card(card, preFee, desc = u'使用绑定的虚拟卡')
- return
- elif result['balance'] < preFee:
- res = SWIPE_CARD_RES.BALANCE_NOT_ENOUGH_01
- leftBalance = result['balance']
- return self.response_use_card(res, leftBalance)
- else:
- # 记录卡消费记录以及消费记录
- orderNo, cardOrderNo = self.record_consume_for_card(card, preFee)
- # 记录当前服务的progress.没有上报端口号,所以先用-1标记,表示端口未知。端口等消费的时候会报上来
- ServiceProgress.register_card_service(self.device, -1, card,
- {
- 'orderNo': orderNo,
- 'money': self.event_data['preFee'],
- 'coin': self.event_data['preFee'], 'needTime': 0,
- 'cardOrderNo': cardOrderNo
- })
- res = SWIPE_CARD_RES.SUCCESS_00
- leftBalance = result['balance']
- self.consume_money_for_card(card, preFee)
- leftBalance -= preFee
- self.response_use_card(res, leftBalance)
- # 通知微信,已经扣费
- self.notify_balance_has_consume_for_card(card, preFee)
- # 退费.卡的退费比较特殊:如果需要按照电量进行扣费退费,需要在设备管理后台,设置成按电量方式计费。然后把卡的余额回收关闭掉。
- # 充电结束后,上报事件,然后把钱退到卡里。如果是按照时间计费(霍柏的特殊),完全由设备决定,设备告诉我退费,我就退。针对霍柏
- # 绑定虚拟卡的情况下,按照时间退费,需要直接取消掉余额回收,靠结束事件触发结束
- elif oper == SWIPE_CARD_PARAM_OP.INCR_01:
- if virtual_card is not None:
- pass
- else:
- res = SWIPE_CARD_RES.SUCCESS_00
- self.response_use_card(res, card.balance + preFee)
- self.refund_money_for_card(preFee, str(card.id))
- # 通知微信,已经退费
- self.notify_user(card.managerialOpenId, 'refund_coins', **{
- 'title': u'退币完成!您的卡号是%s,卡别名:%s' % (card.cardNo, card.nickName),
- 'backCount': u'金币:%s' % preFee,
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
- })
- # 还需要把最近刷卡使用的消费记录中,补充退费的金额,便于报表汇总数据
- self.update_consume_record_refund_money_for_card(preFee, card)
- else:
- raise InvalidOption('oper has be to 00 or 01, %s was given' % (oper,))
- #: 结束的命令
- elif cmdCode in [CMD_CODE.DEVICE_SUBMIT_CHARGE_FINISHED_06, CMD_CODE.DEVICE_SUBMIT_CHARGE_FINISHED_v2_16]:
- lineInfo = Device.update_port_control_cache(devNo, self.event_data)
- group = Group.get_group(self.device['groupId'])
- if 'coins' not in lineInfo:
- return
- if 'duration' in self.event_data and self.event_data['duration'] > 0:
- usedTime = self.event_data['duration']
- else:
- if (not lineInfo) or ('startTime' not in lineInfo):
- 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)))
- cardId = lineInfo.get('cardId', '')
- vCardId = lineInfo.get('vCardId', None)
- money = RMB(lineInfo['coins'])
- price = lineInfo.get('price', 0.0)
- leftTime = self.event_data['leftTime']
- billingType = lineInfo.get('billingType', 'time')
- consumeType = lineInfo.get('consumeType', '')
- backCoins, backPrice = RMB(0.0), RMB(0.0)
- try:
- #: 刷卡或者万一缓存重启了,出现needElec为空的,作为1000度电吧,就会一定使用设备上报的电量
- if lineInfo.get('elec', 0.0) < lineInfo.get('needElec', 0.0):
- spendElec = round(lineInfo['needElec'] - lineInfo['elec'], 2)
- else:
- spendElec = 0.0
- if leftTime == 65535:
- actualNeedTime = 0
- backCoins = money
- backPrice = price
- usedTime = 0
- spendElec = 0.0
- else:
- actualNeedTime = usedTime + leftTime
- leftTimeStr = leftTime
- if billingType == 'time':
- needTime = lineInfo['needTime']
- backCoins = money * (float(leftTime) / float(actualNeedTime))
- else:
- needElec, elec = Decimal(lineInfo.get('needElec', 1000)), Decimal(str(lineInfo.get('elec')))
- ratio = (needElec - elec) / needElec
- backCoins = RMB(money.amount - money.amount * ratio)
- refundProtectionTime = int(self.device.get_other_conf_item('refundProtectionTime', 5))
- if (usedTime < refundProtectionTime) and backCoins != 0:
- backCoins = money
- if backCoins > money:
- backCoins = money
- backPrice = round(price * float(backCoins) / float(money), 2)
- #: 扫码的方式
- if cardId == '' and vCardId is None and consumeType != 'coin':
- openId = lineInfo['openId']
- billingType = lineInfo.get('billingType', 'time')
- if billingType == 'time':
- leftTimeStr = leftTime if leftTime != 65535 else lineInfo['needTime']
- title = u'%s 按动态功率计算总时间为:%s分钟,剩余时间:%s分钟' % (
- self.event_data['reason'],
- actualNeedTime,
- leftTimeStr)
- else:
- title = u'%s %s元购买%s度电量,实际使用电量为:%s度' % (
- self.event_data['reason'],
- money, lineInfo.get('needElec', 1000),
- spendElec
- )
- # 通知充电完成
- user = MyUser.objects(openId = openId, groupId = self.device['groupId']).first()
- self.notify_user(user.managerialOpenId, 'service_complete',
- **{
- 'title': title,
- 'service': u'充电服务(设备编号:%s,端口:%s,地址:%s)' % (
- self.device['logicalCode'], self.event_data['port'], group['address']),
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- 'remark': u'谢谢您的支持'
- })
- consumeDict = {'chargeIndex': lineInfo['port'],
- 'reason': lineInfo['reason'],
- 'elec': spendElec, # 记录以及花费的电量
- 'actualNeedTime': u'动态功率计算为%s分钟' % actualNeedTime,
- 'duration': usedTime,
- 'elecFee': self.calc_elec_fee(spendElec)}
- if billingType == 'time':
- leftTimeStr = leftTime if leftTime != 65535 else lineInfo['needTime']
- consumeDict.update({'leftTime': leftTimeStr, 'needTime': u'扫码订购%s分钟' % lineInfo['needTime']})
- else:
- consumeDict.update({'needElec': lineInfo['needElec']})
- # 如果需要退款,计算退款数据.
- if not self.device.is_auto_refund:
- ServiceProgress.update_progress_and_consume_rcd(
- self.device['ownerId'],
- {'open_id': openId, 'device_imei': self.device['devNo'],
- 'port': lineInfo['port'], 'isFinished': False}, consumeDict
- )
- else:
- # 扫码退钱, 退到个人账号
- refund_money(self.device, backCoins, lineInfo['openId'])
- 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 billingType == 'time':
- leftTimeStr = leftTime if leftTime != 65535 else lineInfo['needTime']
- desc = u'您使用的%s号端口充电,共付款:%s元,充电预定时间为:%s分钟,剩余时间:%s分钟,给您退款:%s元' % (
- lineInfo['port'], money, lineInfo['needTime'], leftTimeStr, backCoins)
- else:
- desc = u'您使用的%s号端口充电,共付款:%s元,充电预定电量为:%s度,使用:%s度,给您退款:%s元' % (
- lineInfo['port'], money, lineInfo.get('needElec', 1), spendElec, backCoins)
- self.notify_user(user.managerialOpenId if user else '', 'refund_coins', **{
- 'title': desc,
- 'backCount': u'金币:%s' % backCoins,
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
- })
- #: 使用的是虚拟卡
- elif vCardId is not None:
- billingType = lineInfo.get('billingType', 'time')
- if billingType == 'time':
- leftTimeStr = leftTime if leftTime != 65535 else lineInfo['needTime']
- title = u'%s 按动态功率计算总时间为:%s分钟,剩余时间:%s分钟' % (
- self.event_data['reason'],
- actualNeedTime,
- leftTimeStr)
- else:
- title = u'%s %s元购买%s度电量,实际使用电量为:%s度' % (
- self.event_data['reason'],
- money, lineInfo.get('needElec', 1000),
- spendElec
- )
- # 通知充电完成
- try:
- vCard = UserVirtualCard.objects.get(id = vCardId)
- except DoesNotExist:
- logger.info('can not find the vCard id = %s' % vCardId)
- return
- self.notify_user(self.get_managerialOpenId_by_openId(lineInfo['openId']), 'service_complete',
- **{
- 'title': title,
- 'service': u'充电服务(设备编号:%s,端口:%s,地址:%s)' % (
- self.device['logicalCode'], self.event_data['port'], group['address']),
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- 'remark': u'谢谢您的支持'
- })
- consumeDict = {'chargeIndex': lineInfo['port'],
- 'reason': lineInfo['reason'],
- 'elec': spendElec, # 记录以及花费的电量
- 'actualNeedTime': u'动态功率计算为%s分钟' % actualNeedTime,
- 'duration': usedTime,
- 'elecFee': self.calc_elec_fee(spendElec)}
- ServiceProgress.update_progress_and_consume_rcd(
- self.device['ownerId'],
- {'open_id': lineInfo['openId'], 'device_imei': self.device['devNo'],
- 'port': lineInfo['port'], '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, spendElec, backCoins.mongo_amount)
- #: 刷的实体卡
- elif cardId != '':
- card = Card.objects.get(id = cardId)
- agent = Agent.objects.get(id = card.agentId)
- virtual_card = card.bound_virtual_card
- consumeDict = {'chargeIndex': lineInfo['port'],
- 'reason': lineInfo['reason'],
- 'actualNeedTime': u'动态功率计算为%s分钟' % actualNeedTime,
- 'duration': usedTime}
- if billingType == 'time': # 刷卡,如果按照时间的,不予退费(霍柏家的特殊,需要退费)
- self.notify_user(card.managerialOpenId if card else '', 'service_complete',
- **{
- 'title': u'%s 卡号:%s(%s),按动态功率计算总时间为:%s分钟,剩余时间:%s分钟' % (
- self.event_data['reason'],
- card.cardNo,
- card.cardName,
- actualNeedTime,
- leftTimeStr),
- 'service': u'充电服务(设备编号:%s,端口:%s 地址:%s)' % (
- self.device['logicalCode'], self.event_data['port'],
- group['address']),
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- 'remark': u'谢谢您的支持'
- })
- if 'huopo_card_time_refund' in agent.features and virtual_card is None:
- ServiceProgress.update_progress_and_consume_rcd(
- self.device['ownerId'],
- {'cardId': cardId, 'device_imei': self.device['devNo'],
- 'port': lineInfo['port'], 'isFinished': False},
- {'chargeIndex': lineInfo['port'], 'leftTime': leftTimeStr,
- 'needTime': u'刷卡订购%s分钟' % needTime if virtual_card is None else u'绑定虚拟卡订购%s分钟' % needTime,
- 'reason': lineInfo['reason'],
- 'elec': spendElec, 'duration': usedTime,
- 'actualNeedTime': u'动态功率计算为%s分钟' % actualNeedTime,
- 'elecFee': self.calc_elec_fee(spendElec),
- 'refundedMoney': str(backCoins)
- }
- )
- else:
- ServiceProgress.update_progress_and_consume_rcd(
- self.device['ownerId'],
- {'cardId': cardId, 'device_imei': self.device['devNo'],
- 'port': lineInfo['port'], 'isFinished': False},
- {'chargeIndex': lineInfo['port'], 'leftTime': leftTimeStr,
- 'needTime': u'刷卡订购%s分钟' % needTime if virtual_card is None else u'绑定虚拟卡订购%s分钟' % needTime,
- 'reason': lineInfo['reason'],
- 'elec': spendElec, 'duration': usedTime,
- 'actualNeedTime': u'动态功率计算为%s分钟' % actualNeedTime,
- 'elecFee': self.calc_elec_fee(spendElec)})
- if 'huopo_card_time_refund' in agent.features:
- if virtual_card is None:
- self.refund_money_for_card(backCoins, str(card.id))
- else:
- consumeRcdId = lineInfo.get('consumeRcdId', None)
- if consumeRcdId is None:
- logger.info('can not find consume rcd id')
- return
- try:
- vCardConsumeRcd = VCardConsumeRecord.objects.filter(
- cardId = str(virtual_card.id)).first()
- except DoesNotExist, e:
- logger.info('can not find the consume rcd id = %s' % consumeRcdId)
- return
- virtual_card.refund_quota(vCardConsumeRcd, usedTime, spendElec, backCoins.mongo_amount)
- desc = u'您使用的%s号端口充电,共付款:%s元,充电预定时间为:%s分钟,使用:%s分钟,给您退款:%s元' % (
- lineInfo['port'], money, needTime, usedTime, backCoins)
- self.notify_user(card.managerialOpenId if card else '', 'refund_coins', **{
- 'title': desc,
- 'backCount': u'金币:%s' % backCoins,
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
- })
- return
- self.notify_user(card.managerialOpenId if card else '', 'service_complete',
- **{
- 'title': u'%s 卡号:%s(%s),%s元购买%s度电量,实际使用电量为:%s度' % (
- self.event_data['reason'],
- card.cardNo,
- card.cardName,
- money,
- lineInfo['needElec'],
- spendElec),
- 'service': u'充电服务(设备编号:%s,端口:%s 地址:%s)' % (
- self.device['logicalCode'], self.event_data['port'],
- group['address']),
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- 'remark': u'谢谢您的支持'
- })
- consumeDict = {'chargeIndex': lineInfo['port'], 'leftTime': leftTimeStr,
- 'reason': lineInfo['reason'],
- 'elec': spendElec, 'duration': usedTime, 'needElec': lineInfo['needElec'],
- 'elecFee': self.calc_elec_fee(spendElec)}
- # 如果需要退款,计算退款数据.
- if not self.device.is_auto_refund:
- ServiceProgress.update_progress_and_consume_rcd(
- self.device['ownerId'],
- {'cardId': cardId, 'device_imei': self.device['devNo'],
- 'port': lineInfo['port'], 'isFinished': False}, consumeDict
- )
- return
- # 按照电量的退费,由结束事件来搞定
- if virtual_card is None:
- self.refund_money_for_card(backCoins, str(card.id))
- consumeDict.update({'refundedMoney': str(backCoins)})
- else:
- consumeRcdId = lineInfo.get('consumeRcdId', None)
- if consumeRcdId is None:
- logger.info('can not find consume rcd id')
- return
- try:
- vCardConsumeRcd = VCardConsumeRecord.objects.filter(cardId = str(virtual_card.id)).first()
- except DoesNotExist, e:
- logger.info('can not find the consume rcd id = %s' % consumeRcdId)
- return
- virtual_card.refund_quota(vCardConsumeRcd, usedTime, spendElec, backCoins.mongo_amount)
- ServiceProgress.update_progress_and_consume_rcd(
- self.device['ownerId'],
- {'open_id': lineInfo['openId'], 'device_imei': self.device['devNo'],
- 'port': lineInfo['port'], 'isFinished': False}, consumeDict)
- desc = u'您使用的%s号端口充电,共付款:%s元,充电预定电量为:%s度,使用:%s度,给您退款:%s元' % (
- lineInfo['port'], money, lineInfo.get('needElec', 0.0), spendElec, backCoins)
- self.notify_user(card.managerialOpenId if card else '', 'refund_coins', **{
- 'title': desc,
- 'backCount': u'金币:%s' % backCoins,
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
- })
- #: 消费类型为金币,则
- elif consumeType == 'coin':
- CoinConsumeRcd = ConsumeRecord.objects.get(orderNo = lineInfo['consumeOrderNo']) # type: ConsumeRecord
- CoinConsumeRcd.servicedInfo['elec'] = spendElec
- CoinConsumeRcd.servicedInfo['actualNeedTime'] = u'动态功率计算为%s分钟' % actualNeedTime
- CoinConsumeRcd.servicedInfo['needTime'] = u'投币订购%s分钟' % needTime
- CoinConsumeRcd.servicedInfo['reason'] = lineInfo['reason']
- CoinConsumeRcd.servicedInfo['chargeIndex'] = lineInfo['port']
- CoinConsumeRcd.finishedTime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
- CoinConsumeRcd.save()
- valueDict = {
- DEALER_CONSUMPTION_AGG_KIND.ELEC: spendElec,
- DEALER_CONSUMPTION_AGG_KIND.ELECFEE: self.calc_elec_fee(spendElec)
- }
- status = CoinConsumeRcd.update_agg_info(valueDict)
- if status:
- record_consumption_stats(CoinConsumeRcd)
- else:
- logger.error(
- '[update_progress_and_consume_rcd] failed to update_agg_info record=%r' % (CoinConsumeRcd,))
- 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']))
- dataDict = {'backMoney': backPrice, 'backCoins': str(backCoins.mongo_amount)}
- if lineInfo.has_key('orderNo'):
- dataDict.update({'orderNo': lineInfo['orderNo']})
- notify_event_to_north(self.dealer, self.device, level = Const.EVENT_NORMAL,
- desc = self.event_data['reason'], dataDict = dataDict)
- send_event_to_zhejiang(self.dealer, self.device, self.event_data)
- #: 启动了端口,主要记录下投币数据
- elif cmdCode == CMD_CODE.DEVICE_SUBMIT_OFFLINE_COINS_20:
- consumeType = self.event_data['consumeType']
- port = self.event_data['port']
- ctrInfo = Device.get_dev_control_cache(self.device['devNo'])
- lastPortInfo = ctrInfo.get(str(port), None)
- if consumeType == 'coin':
- self.event_data.update({'startTime': datetime.datetime.now().strftime(Const.DATETIME_FMT)})
- # 记录该端口累计需要的时间和钱,cardId
- if lastPortInfo is None:
- Accounting.recordOfflineCoin(self.device,
- int(time.time()),
- int(self.event_data['coins']))
- self.event_data.update({'needElec': self.event_data['elec']})
- self.event_data.update(
- {'consumeOrderNo': self.record_consume_for_coin(RMB(self.event_data['coins']))})
- Device.update_port_control_cache(self.device['devNo'], self.event_data)
- else:
- if lastPortInfo.has_key('needElec'):
- lastPortInfo['needElec'] += self.event_data['elec']
- else:
- lastPortInfo['needElec'] = self.event_data['elec']
- orderNo = self.record_consume_for_coin(RMB(self.event_data['coins']))
- lastPortInfo['consumeOrderNo'] = orderNo
- Device.update_port_control_cache(self.device['devNo'], lastPortInfo)
- elif consumeType == 'card':
- port = self.event_data['port']
- consumeDict = {'chargeIndex': port, 'elec': self.event_data['elec'],
- 'money': self.event_data['coins'], 'needTime': u'刷卡订购%s分钟' % self.event_data['needTime']}
- queryDict = {'device_imei': self.device['devNo'],
- 'port': -1, 'isFinished': False,
- 'cardId': {'$ne': ''}, 'start_time': {'$gte': int(time.time()) - 3600}}
- progressDict = {'port': port}
- ServiceProgress.update_progress_and_consume_rcd(ownerId = self.device['ownerId'], queryDict = queryDict,
- consumeDict = consumeDict, updateConsume = True,
- progressDict = progressDict)
- # 找出对应的卡的ID记录到端口内存数据
- queryDict.update(progressDict)
- rcds = ServiceProgress.get_collection().find(queryDict, {'cardId': 1, 'open_id': 1},
- sort = [('start_time', 1)])
- if rcds.count() == 0:
- return
- rcd = rcds[0]
- dev = Device.objects.get(devNo = self.device['devNo'])
- billingType = dev.otherConf.get('billingType', 'time')
- self.event_data.update({'billingType': billingType})
- self.event_data.update({'cardId': rcd['cardId']})
- self.event_data.update({'openId': rcd['open_id']})
- cInfo = Device.get_dev_control_cache(devNo)
- lastPortInfo = cInfo.get(str(port), {})
- # 钱需要累计
- lastCoins = lastPortInfo.get('coins', 0.0)
- self.event_data.update({'coins': self.event_data['coins'] + lastCoins})
- # 电量需要累加
- lastNeedElec = lastPortInfo.get('needElec', 0.0)
- self.event_data.update({'needElec': self.event_data['elec'] + lastNeedElec})
- # 时间需要累加
- lastNeedTime = lastPortInfo.get('needTime', 0.0)
- self.event_data.update({'needTime': self.event_data['needTime'] + lastNeedTime})
- self.event_data.update({'startTime': datetime.datetime.now().strftime(Const.DATETIME_FMT)})
- self.event_data.update({'isStart': True, 'status': Const.DEV_WORK_STATUS_WORKING})
- #: 记录该端口累计需要的时间和钱,cardId
- Device.update_port_control_cache(self.device['devNo'], self.event_data)
- elif consumeType == 'server':
- port = self.event_data['port']
- #: 记录该端口累计需要的时间和钱
- Device.update_port_control_cache(self.device['devNo'], self.event_data)
- consumeDict = {'chargeIndex': self.event_data['port'], 'elec': self.event_data['elec'],
- 'needTime': u'订购%s分钟' % self.event_data['needTime']}
- queryDict = {'device_imei': self.device['devNo'],
- 'port': port, 'isFinished': False,
- 'start_time': {'$gte': int(time.time()) - 3600}}
- progressDict = {'port': self.event_data['port']}
- ServiceProgress.update_progress_and_consume_rcd(ownerId = self.device['ownerId'],
- queryDict = queryDict, consumeDict = consumeDict,
- updateConsume = True, progressDict = progressDict)
- else:
- raise NoCommandHandlerAvailable(
- '[JNDZ]] no command handler for cmd %s, curDevInfo=%s' % (cmdCode, self.event_data))
- def response_use_card(self, res, leftBalance):
- # 启动失败需要把金币还回去
- try:
- self.deviceAdapter.response_use_card(res, leftBalance)
- except ServiceException as e:
- logger.exception(e)
- raise JNDZEventerFailure('failed to connect to device')
|