# -*- 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')