# -*- coding: utf-8 -*- # !/usr/bin/env python import json import logging from copy import deepcopy import datetime import time from typing import TYPE_CHECKING, Tuple, Optional from apilib.monetary import RMB, VirtualCoin, Ratio from apilib.utils_string import make_title_from_dict from apilib.utils_sys import memcache_lock from apps.web.constant import Const, FAULT_LEVEL, DEALER_CONSUMPTION_AGG_KIND from apps.web.device.models import DeviceUploadInfo, Group, DeviceDict from apps.web.eventer import EventBuilder from apps.web.eventer.base import WorkEvent, FaultEvent from apps.web.eventer.weifuleCommon import WeiFuLeStatusEvent from apps.web.user.models import ConsumeRecord, CardConsumeRecord, RefundMoneyRecord from apps.web.user.models import ServiceProgress, RechargeRecord, MyUser, CardRechargeOrder from apps.web.utils import concat_user_login_entry_url if TYPE_CHECKING: from apps.web.user.models import Card logger = logging.getLogger(__name__) def log_obj(obj): obj = deepcopy(obj) if isinstance(obj, dict): for k, v in obj.items(): if isinstance(v, object): obj[k] = str(v) if isinstance(obj, list) or isinstance(obj, tuple) or isinstance(obj, set): obj = map(lambda x: str(x) if isinstance(x, object) else x, obj) if isinstance(obj, unicode): obj = str(obj) # print('\33[33m' + json.dumps(obj,ensure_ascii=True,encoding='utf-8') + '\33[0m') return '\33[33m' + json.dumps(obj, ensure_ascii=False, encoding='utf-8') + '\33[0m' card_is_normal = 1 card_not_in_db = 2 card_is_forzen = 3 card_has_not_order = 4 # IC卡适用 CREATED = 'created' RUNNING = 'running' WAITING = 'wait' FINISHED = 'finished' END = 'end' TIMEOUT = 'timeout' FAILURE = 'failure' class builder(EventBuilder): def __getEvent__(self, device_event): logger.info('reve event, event_data:{}'.format(log_obj(device_event))) event_data = device_event.get('data') fun_code = event_data.get('fun_code') if not event_data: return if fun_code in [44]: # 44状态变更 return ChargingWeiFuLeCarStatusEvent(self.deviceAdapter, device_event) if fun_code in [40, 41, 42, 43]: # 40温度告警/41电流超限/42电压超限/43功率过载 return ChargingWeiFuLeCarFaultEvent(self.deviceAdapter, event_data) else: return ChargingWeiFuLeCarWorkEvent(self.deviceAdapter, event_data) class ChargingWeiFuLeCarStatusEvent(WeiFuLeStatusEvent): def parse_status(self, data): return {'1': data.get('result')} class ChargingWeiFuLeCarWorkEvent(WorkEvent): def do(self, **args): fun_code = self.event_data.get('fun_code') order_id = self.event_data.get('order', {}).get('id') key = '{}.{}.event'.format(self.device.devNo, order_id) if fun_code == 37: # 处理卡充值 self.deal_with_ic_charge_event() elif fun_code == 45: # 上传要链接 self.response_the_link() else: with memcache_lock(key = key, value = '1', expire = 15) as acquired: if acquired: if fun_code == 32 or fun_code == 34 or fun_code == 33: self._do_order_change_event_32_33_34() self._do_ack_order_32_or_remove_order_from_device_34() else: logger.debug('fun_code<{}> is doing. cache_key:{}'.format(repr(fun_code), key)) return def deal_with_ic_charge_event(self): cardNo = self.event_data.get('card_no') card = self.update_card_dealer_and_type(cardNo, cardType='IC') logger.info(log_obj('Start card recharge operation')) if not card: logger.info(log_obj('Start card recharge operation --> no such card !!! ')) return self.deviceAdapter.send_mqtt({ 'fun_code': 37, 'card_no': cardNo, 'result': card_not_in_db, }) elif card.frozen: logger.info(log_obj('Start card recharge operation --> card is frozen !!! ')) return self.deviceAdapter.send_mqtt({ 'fun_code': 37, 'card_no': cardNo, 'result': card_is_forzen, }) rechargeOrder = CardRechargeOrder.get_last_to_do_one(str(card.id)) if rechargeOrder: preBalance = RMB(self.event_data.get('balance', 0) / 100.0) logger.info(log_obj('Start card recharge operation --> to recharg rechargeAmount:{}'.format(preBalance))) self.recharge_ic_card(card=card, preBalance=preBalance, rechargeType='append', order=rechargeOrder, need_verify=False) else: logger.info(log_obj('Start card recharge operation --> no rechargeOrder !! ')) self.deviceAdapter.send_mqtt({ 'card_no': cardNo, 'fun_code': 37, 'result': card_has_not_order, }) def _do_order_change_event_32_33_34(self): order_info = self.event_data.get('order') if not order_info: logger.info(log_obj('no order info,do over!!')) else: order_processing = OrderProcessing(self) order_type = order_info.get('order_type') self.save_upload_log() if hasattr(order_processing, order_type): event = getattr(order_processing, order_type) try: event() except Exception: import traceback logger.info(traceback.format_exc()) else: logger.info(log_obj('no this order_type')) def _do_ack_order_32_or_remove_order_from_device_34(self): order_info = self.event_data.get('order') order_id = order_info.get('id') fun_code = self.event_data.get('fun_code') if (time.time() - order_info.get('create_time', 0)) < 300 and order_info.get('order_type') == 'apps_start': order = ConsumeRecord.objects.filter(orderNo=order_id).first() if order: # 正常流程 第一次上报先不处理, 否则则为发mqtt命令测试直接回复 return if fun_code == 32: self.deviceAdapter.do_ack_order_32(order_id) elif fun_code == 34: self.deviceAdapter.do_ack_remove_order_from_device_34(order_id) else: pass def save_upload_log(self): order_info = self.event_data.get('order') order_info = deepcopy(order_info) order_info['order_id'] = order_info.pop('id') DeviceUploadInfo(**order_info).save() def response_the_link(self): qr_code_url = concat_user_login_entry_url(l=self.device['logicalCode']) data = { 'fun_code': 45, 'qrcode': qr_code_url } self.deviceAdapter.send_mqtt(data) def record_consume_for_card(self, card, money, desc=u'', servicedInfo=None, sid=None, attachParas=None): # type: (Card, RMB, unicode, Optional[dict], Optional[str], Optional[dict])->Tuple[str, str] servicedInfo = {} if servicedInfo is None else servicedInfo attachParas = {} if attachParas is None else attachParas group = Group.get_group(self.device['groupId']) address = group['address'] group_number = self.device['groupNumber'] now = datetime.datetime.now() orderNo = attachParas.get('orderNo') new_record = { 'orderNo': orderNo, 'time': now.strftime('%Y-%m-%d %H:%M:%S'), 'dateTimeAdded': now, 'openId': card.openId, 'ownerId': self.device['ownerId'], 'coin': money.mongo_amount, 'money': money.mongo_amount, 'devNo': self.device['devNo'], 'logicalCode': self.device['logicalCode'], 'groupId': self.device['groupId'], 'address': address, 'groupNumber': group_number, 'groupName': group['groupName'], 'devTypeCode': self.device.devTypeCode, 'devTypeName': self.device.devTypeName, 'isNormal': True, 'remarks': u'刷卡消费', 'errorDesc': '', 'sequanceNo': '', 'desc': desc, 'attachParas': attachParas, 'servicedInfo': servicedInfo } ConsumeRecord.get_collection().insert_one(new_record) # 刷卡消费也记录一条数据 new_card_record = { 'orderNo': orderNo, 'openId': card.openId, 'cardId': str(card.id), 'money': money.mongo_amount, 'balance': card.balance.mongo_amount, 'devNo': self.device['devNo'], 'devType': self.device['devType']['name'], 'logicalCode': self.device['logicalCode'], 'groupId': self.device['groupId'], 'address': address, 'groupNumber': group_number, 'groupName': group['groupName'], 'result': 'success', 'remarks': u'刷卡消费', 'sequanceNo': '', 'dateTimeAdded': datetime.datetime.now(), 'desc': desc, 'servicedInfo': servicedInfo, 'linkedConsumeRcdOrderNo': str(new_record['orderNo']) } if sid is not None: new_card_record.update({'sid': sid}) CardConsumeRecord.get_collection().insert(new_card_record) return new_record['orderNo'], new_card_record['orderNo'] class ChargingWeiFuLeCarFaultEvent(FaultEvent): def do(self, **args): # 40温度告警/41电流超限/42电压超限/43功率过载 group = Group.get_group(self.device['groupId']) fun_code = self.event_data.get('fun_code') if fun_code == 40: item = self.event_data.get('temp') faultName = r'设备火灾预警' desc = r'主板上报设备过热,设备温度超限(设备温度:{} 度)'.format(item) title = r'告警名称:\t\t{}\n\n地址名称:\t\t{}-{}\n'.format(faultName, group['address'], group['groupName']) elif fun_code == 41: item = self.event_data.get('ampr') faultName = r'设备电流超过最大限制' desc = r'主板上报电流超限,设备电流超限(设备电流:{} 安)'.format(item) title = r'告警名称:\t\t{}\n\n地址名称:\t\t{}-{}\n'.format(faultName, group['address'], group['groupName']) elif fun_code == 42: item = self.event_data.get('volt') faultName = r'设备电压超过最限制' desc = r'主板上报电压超限,设备电压超限(设备电压:{} 伏)'.format(item) title = r'告警名称:\t\t{}\n\n地址名称:\t\t{}-{}\n'.format(faultName, group['address'], group['groupName']) elif fun_code == 43: item = self.event_data.get('watt') faultName = r'设备功率超过最限制' desc = r'主板上报功率超限,设备功率超限(设备电压:{} 瓦)'.format(item) title = r'告警名称:\t\t{}\n\n地址名称:\t\t{}-{}\n'.format(faultName, group['address'], group['groupName']) else: return self.notify_dealer( templateName='device_fault', title=title, device=r'{}号设备({})\n'.format(self.device['groupNumber'], self.device['logicalCode']), location=r'设备告警\n', notifyTime=desc + r'\n', fault=r'%s\n' % datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') ) self.record( faultCode=self.event_data.get('FaultCode'), description=desc, title=faultName, level=self.event_data.get('level', FAULT_LEVEL.NORMAL), # detail=self.event_data.get('statusInfo'), ) class OrderProcessing: desc_map = { 0: '订购已用完', 1: '管理员停止', 2: '设备故障', 3: '充电枪拔除', 4: '紧急停止按钮', 5: '计量故障', 6: '功率过载', 7: '电压过载', 8: '电流过载', 9: '超过单次充电最大时长', 10: '设备启动失败', 11: '继电器故障', 12: '刷卡停止', 13: '用户远程停止', 14: '经销商远程停止' } def __init__(self, base): self.devNo = base.device.devNo self.fun_code = base.event_data.get('fun_code') self.order_info = base.event_data.get('order') self.dev = base.device # type: DeviceDict self.adapter = base.deviceAdapter self.base = base self.PORT = '1' def _exec_order_33(self): start_time = self.order_info.get('exec_time') start_time = datetime.datetime.fromtimestamp(start_time) order_id = self.order_info.get('id') consumeOrder = ConsumeRecord.objects.filter(orderNo=order_id, status__ne=ConsumeRecord.Status.FINISHED).first() if not consumeOrder: logger.info(log_obj('no this order')) return consumeOrder.update(startTime=start_time) def apps_start(self): """ 'order_type' : 'apps_start', 'money' : 1.2388653318201, 'id' : '86743505437857520201225084915001', 'left_money' : 98.76113466818, 'last_clock' : 607.31, 'create_time' : 1608857355, 'time' : 475.525, 'amount' : 100, 'elec' : 12388.653318201, 'exec_time' : 1608857355, 'status' : 'running', 'last_ecnt' : 16777128 """ dev_stat = self.order_info.get('status') order = ConsumeRecord.objects.filter(orderNo=self.order_info['id']).first() if not order: logger.info('no this order') return if dev_stat == 'running': self._apps_start_do_record_running(dev_stat, order) elif dev_stat == 'waiting': self._apps_start_do_record_waiting(dev_stat, order) elif dev_stat == 'finished': self._apps_start_do_record_finished(dev_stat, order) def _apps_start_do_record_running(self, dev_stat, order): rechargeRcdId = order.rechargeRcdId or '' if order.status == CREATED: # 让adapter处理 if 'adapter' in self.order_info: # 服务器过来直接处理 order.update(status=RUNNING) else: if (time.time() - self.order_info.get('create_time', 0)) > 300: ConsumeRecord.objects.filter(id=order.id, status=CREATED).update(status=RUNNING, isNormal=True) elif order.status == RUNNING: # 设备上报 start_time = self.order_info.get('exec_time') start_time = datetime.datetime.fromtimestamp(start_time) order.update( status=RUNNING, startTime=start_time ) elif order.status == WAITING: # 33 上来的wait单变running start_time = self.order_info.get('exec_time') start_time = datetime.datetime.fromtimestamp(start_time) order.update( status=RUNNING, startTime=start_time, ) elif order.status in [TIMEOUT, FAILURE]: # 此时已经退费,标记为后支付,不做处理 start_time = self.order_info.get('exec_time') or self.order_info.get('create_time') start_time = datetime.datetime.fromtimestamp(start_time) order.update( status=RUNNING, coin=VirtualCoin(0), money=RMB(0), startTime=start_time, attachParas__payAfterUse=True, rechargeRcdId='', attachParas__last_refund_rechargeRcdId=rechargeRcdId, isNormal=True, errorDesc='设备启动已退费, 此单标记为后支付'.format(dev_stat), ) consumeOrder = { 'orderNo': order.orderNo, 'coin': 0, 'consumeType': 'postpaid', } self.adapter.register_service_progress(order.openId, order.orderNo, consumeOrder, order.attachParas) title = make_title_from_dict([ {u'设备地址': u'{}'.format(self.dev.group.address)}, {u'设备编号': u'{}'.format(self.dev['logicalCode'])}, ]) self.base.notify_user( order.user.managerialOpenId, 'dev_start', **{ 'title': title, 'things': u'您的汽车充电服务已启动', 'remark': u'感谢您的支持!', 'time': start_time.strftime(Const.DATETIME_FMT) } ) elif order.status in [FINISHED, END]: pass else: logger.info('error order status devStat=<{}>, order=<{}>'.format(dev_stat, order.orderNo)) def _apps_start_do_record_waiting(self, dev_stat, order): # 兼容系统 全改为running单 rechargeRcdId = order.rechargeRcdId or '' if order.status == CREATED: # 启动过程服务器中断停留在 if (time.time() - self.order_info.get('create_time', 0)) > 300: ConsumeRecord.objects.filter(id=order.id, status=CREATED).update(status=RUNNING, isNormal=True) elif order.status == RUNNING: # 服务器成功启动置为running order.update( status=RUNNING ) elif order.status == WAITING: # 重复 pass elif order.status in [TIMEOUT, FAILURE]: # 此时已经退费,标记为后支付,不做处理 order.update( status=RUNNING, coin=VirtualCoin(0), money=RMB(0), attachParas__payAfterUse=True, rechargeRcdId='', attachParas__last_refund_rechargeRcdId=rechargeRcdId, isNormal=True, errorDesc='设备启动已退费, 此单标记为后支付'.format(dev_stat), ) consumeOrder = { 'orderNo': order.orderNo, 'coin': 0, 'consumeType': 'postpaid', } self.adapter.register_service_progress(order.openId, order.orderNo, consumeOrder, order.attachParas) elif order.status in [FINISHED, END]: pass def _apps_start_do_record_finished(self, dev_stat, order): if order.status == CREATED: # 启动过程中服务器出错 ConsumeRecord.objects.filter(id=order.id, status=CREATED).update(status=RUNNING, isNormal=True) order.reload() self.pre_pay(order) elif order.status in [RUNNING, WAITING]: # 正常状态的 或者修正状态的单 payAfterUse = order.attachParas.get('payAfterUse') if payAfterUse: self.after_pay(order) else: self.pre_pay(order) elif order.status == TIMEOUT: # 设备启动后,100事件先上(该状态为running),210回复改为timeout,后付费处理 order.update( status=RUNNING, coin=VirtualCoin(0), money=RMB(0), attachParas__payAfterUse=True, rechargeRcdId='', attachParas__last_refund_rechargeRcdId=order.rechargeRcdId, isNormal=True, errorDesc='设备启动已退费, 此单标记为后支付'.format(dev_stat), ) order.reload() self.after_pay(order) elif order.status == FAILURE: # 状态位置不处理 pass elif order.status in [FINISHED, END]: logger.info( log_obj('do apps finished --> no order found or repeated submit orderNo:{}'.format(order.orderNo))) return logger.info(log_obj('apps start event orderNo:{} is over'.format(order))) def pre_pay(self, order): openId = order.openId # leftMoney = RMB.fen_to_yuan(self.order_info.get('left_money', 0)) # 传过来的这个值有问题 amount = RMB.fen_to_yuan(self.order_info.get('amount', 0)) usedMoney = RMB.fen_to_yuan(self.order_info.get('money')) leftMoney = amount - usedMoney used_time = round(self.order_info.get('time') / 60.0, 2) used_elec = self.order_info.get('elec') / 10.0 ** 6 reason = self.desc_map.get(self.order_info.get('cause')) execTimeStamp = self.order_info.get('exec_time') finishedTimeStamp = self.order_info.get('over_time') finishedTime = datetime.datetime.fromtimestamp(finishedTimeStamp) if not execTimeStamp: startTime = finishedTime else: startTime = datetime.datetime.fromtimestamp(execTimeStamp) status = self.order_info.get('status') consumeDict = { DEALER_CONSUMPTION_AGG_KIND.DURATION: '%d' % used_time, DEALER_CONSUMPTION_AGG_KIND.ELEC: '%.2f' % used_elec, DEALER_CONSUMPTION_AGG_KIND.COIN: amount.mongo_amount, 'reason': reason } order.status = status order.startTime = startTime order.finishedTime = finishedTime order.save() user = MyUser.objects(openId=order.openId, groupId=self.dev.groupId).first() group = Group.get_group(self.dev['groupId']) extra = [ # {u'订单号': '{}'.format(order.orderNo)}, {u'本次使用时长': '{}(分钟)'.format(used_time)}, ] self.base.notify_user_service_complete( service_name='充电', openid=user.managerialOpenId if user else '', port=self.PORT, address=group['address'], reason=reason, finished_time=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), extra=extra ) if self.dev.is_auto_refund: recharge_record = None if order.rechargeRcdId: recharge_record = RechargeRecord.objects( id=order.rechargeRcdId, isQuickPay=True).first() # type: RechargeRecord if recharge_record: refundMoneyRecord = RefundMoneyRecord.objects.filter(openId=openId, rechargeObjId=recharge_record.id).first() if not refundMoneyRecord: self.__do_refund_money(recharge_record, order, leftMoney, consumeDict) else: self.__do_refund_coin(order, leftMoney, consumeDict) order.update_service_info(consumeDict) ServiceProgress.objects.filter(device_imei=self.devNo, weifuleOrderNo=order.orderNo).update( isFinished=True, finished_time=int(time.time()) ) def after_pay(self, order): """ 只针对设备下发之后,没有回复的故障单为后付费 :return: """ used_money = RMB.fen_to_yuan(self.order_info.get('money', 0)) amount = RMB.fen_to_yuan(self.order_info.get('amount', 0)) used_time = round(self.order_info.get('time') / 60.0, 2) used_elec = self.order_info.get('elec') / 10.0 ** 6 reason = self.desc_map.get(self.order_info.get('cause')) execTimeStamp = self.order_info.get('exec_time') finishedTimeStamp = self.order_info.get('over_time') finishedTime = datetime.datetime.fromtimestamp(finishedTimeStamp) if not execTimeStamp: startTime = finishedTime else: startTime = datetime.datetime.fromtimestamp(execTimeStamp) consumeDict = { DEALER_CONSUMPTION_AGG_KIND.DURATION: '%d' % used_time, DEALER_CONSUMPTION_AGG_KIND.ELEC: '%.2f' % used_elec, 'reason': reason, } order.startTime = startTime order.finishedTime = finishedTime coins = VirtualCoin(order.package.get('coins', 0)) price = RMB(order.package.get('price')) ratio = Ratio(float(used_money) / float(amount)) order.coin = coins * ratio order.money = price * ratio if order.money == RMB(0): order.coin = VirtualCoin(0) order.save() extra = [ # {u'订单号': '{}'.format(order.orderNo)}, {u'本次使用时长': '{}(分钟)'.format(used_time)}, ] if order.money > RMB(0): self._pay_by_coins(order) else: order.update(status=FINISHED) order.reload() if order.status == FINISHED: extra.append({u'本单消费金额': '{}金币(已使用账户余额自动结算本次消费)'.format(order.coin.mongo_amount)}) consumeDict.update({DEALER_CONSUMPTION_AGG_KIND.COIN: order.coin.mongo_amount}) else: extra.append({u'本单消费金额': '{}元((您的账户余额已不足以抵扣本次消费,请前往账单中心进行支付))'.format(order.money.mongo_amount)}) consumeDict.update({DEALER_CONSUMPTION_AGG_KIND.SPEND_MONEY: order.money.mongo_amount}) self.base.notify_user_service_complete( service_name='充电结束', openid=order.user.managerialOpenId, port=self.PORT, address=self.dev.group['address'], reason=reason, finished_time=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), extra=extra ) order.update_service_info(consumeDict) ServiceProgress.objects.filter(device_imei=self.devNo, weifuleOrderNo=order.orderNo).update( isFinished=True, finished_time=int(time.time()) ) def _pay_by_coins(self, order): try: order.s_to_e() except Exception: return False def __do_refund_money(self, recharge_record, consumeOrder, leftMoney, consumeDict): logger.info(log_obj('now do refund money!')) coins = consumeOrder.coin openId = consumeOrder.openId price = recharge_record.money user = MyUser.objects.filter(openId=openId, groupId=self.dev['groupId']).first() refundMoney = RMB(price) * Ratio(float(leftMoney) / float(coins)) if refundMoney > RMB(price): refundMoney = RMB(price) if refundMoney > RMB(0): self.base.refund_net_pay(user, {'rechargeRcdId': str(recharge_record.id), 'openId': user.openId}, refundMoney, VirtualCoin(0), consumeDict, True) title = make_title_from_dict([ {u'设备地址': u'{}'.format(self.dev.group.address)}, {u'设备编号': u'{}'.format(self.dev['logicalCode'])}, ]) self.base.notify_user(self.base.get_managerialOpenId_by_openId(openId), 'refund_coins', **{ 'title': title, 'backCount': u'金额:%s' % refundMoney, 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}) logger.info(log_obj('refund cash is successful refundMoney:{}'.format(refundMoney))) def __do_refund_coin(self, consumeOrder, leftMoney, consumeDict): logger.info(log_obj('now do refund coin !')) coins = consumeOrder.coin openId = consumeOrder.openId user = MyUser.objects.filter(openId=openId, groupId=self.dev['groupId']).first() backCoins = VirtualCoin(coins) * Ratio(float(leftMoney) / float(coins)) if backCoins > VirtualCoin(coins): backCoins = VirtualCoin(coins) if backCoins > RMB(0): self.base.refund_net_pay(user, {'openId': openId}, RMB(0), backCoins, consumeDict, False) title = make_title_from_dict([ {u'设备地址': u'{}'.format(self.dev.group.address)}, {u'设备编号': u'{}'.format(self.dev['logicalCode'])}, ]) self.base.notify_user(self.base.get_managerialOpenId_by_openId(openId), 'refund_coins', **{ 'title': title, 'backCount': u'金币:%s' % backCoins, 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}) # ---------------------刷卡处理------------------------- def card_start(self): status = self.order_info.get('status') if self.fun_code == 32: self._card_start_do_record_running_32() elif self.fun_code == 34: if status == 'finished': self._card_start_do_record_finished_34() else: pass elif self.fun_code == 33: self._exec_order_33() def card_refund(self): """ 离线卡:上报退费 做一次卡余额同步 """ status = self.order_info.get('status') if self.fun_code == 32: if status == 'finished': self._card_refund_do_record_finished() else: pass elif self.fun_code == 34: if status == 'finished': pass # self._card_refund_do_record_finished() else: pass def _card_start_do_record_running_32(self): self._charge_by_card() def _card_start_do_record_finished_34(self): used_time = round(self.order_info.get('time') / 60.0, 2) finishedTimeStamp = self.order_info.get('over_time') finishedTime = datetime.datetime.fromtimestamp(finishedTimeStamp) execTimeStamp = self.order_info.get('exec_time') if not execTimeStamp: startTime = finishedTime else: startTime = datetime.datetime.fromtimestamp(execTimeStamp) reason = self.desc_map.get(self.order_info.get('cause')) card_no = self.order_info.get('card_no') used_elec = self.order_info.get('elec') / 10 ** 6 card_balance = RMB.fen_to_yuan(self.order_info.get('balance')) amount = RMB.fen_to_yuan(self.order_info.get('amount')) order_id = self.order_info.get('id') # left_money = RMB.fen_to_yuan(self.order_info.get('left_money')) #这个值有问题 used_money = RMB.fen_to_yuan(self.order_info.get('money')) left_money = amount - used_money consumeOrder = ConsumeRecord.objects.filter(devNo=self.devNo, orderNo=order_id, status__ne=ConsumeRecord.Status.FINISHED).first() if not consumeOrder: logger.info( log_obj('do card finished --> no order found or repeated submit orderNo:{}'.format(order_id))) return openId = consumeOrder.openId consumeOrder.servicedInfo.update({ DEALER_CONSUMPTION_AGG_KIND.REFUND_CARD: left_money.mongo_amount, DEALER_CONSUMPTION_AGG_KIND.CONSUME_CARD: amount.mongo_amount, DEALER_CONSUMPTION_AGG_KIND.SPEND_MONEY: (amount - left_money).mongo_amount, DEALER_CONSUMPTION_AGG_KIND.DURATION: '%d' % used_time, DEALER_CONSUMPTION_AGG_KIND.ELEC: '%.2f' % used_elec, 'cardBalance': card_balance.mongo_amount, 'reason': reason, 'cardNo': card_no }) consumeOrder.startTime = startTime consumeOrder.finishedTime = finishedTime consumeOrder.save() ServiceProgress.update_progress_and_consume_rcd( self.dev['ownerId'], { 'open_id': openId, 'device_imei': self.devNo, 'isFinished': False, 'weifuleOrderNo': order_id, }, consumeOrder.servicedInfo, progressDict={'isFinished': True, 'finished_time': finishedTimeStamp} ) user = MyUser.objects(openId=consumeOrder.openId, groupId=self.dev.groupId).first() group = Group.get_group(self.dev['groupId']) extra = [ # {u'订单号': '{}'.format(consumeOrder.orderNo)}, {u'本次使用时长': '{}(分钟)'.format(used_time)}, ] self.base.notify_user_service_complete( service_name=u'刷卡充电', openid=user.managerialOpenId if user else '', port=self.PORT, address=group['address'], reason=reason, finished_time=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), extra=extra ) logger.info(log_obj('card start event orderNo:{} is over'.format(order_id))) def _register_card_service_progress(self, card, consumeOrder, weifuleOrderNo=None, attachParas=None): return ServiceProgress.objects.create( open_id=card.openId, device_imei=self.devNo, devTypeCode='100257', port=1, cardId=str(card.id), attachParas=attachParas if attachParas else {}, start_time=int(time.time()), finished_time=int(time.time() + 24 * 60 * 60), consumeOrder=consumeOrder if consumeOrder else {}, weifuleOrderNo=weifuleOrderNo, ).id def _charge_by_card(self): # used_money = RMB.fen_to_yuan(self.order_info.get('money', 0)) # left_money = RMB.fen_to_yuan(self.order_info.get('left_money')) amount = RMB.fen_to_yuan(self.order_info.get('amount', 0)) card_balance = RMB.fen_to_yuan(self.order_info.get('balance')) start_time_stamp = self.order_info.get('create_time') start_time = datetime.datetime.fromtimestamp(start_time_stamp) # used_time = self.order_info.get('time') / 60 # used_elec = self.order_info.get('elec') / 10 ** 6 # status = self.order_info.get('status') order_id = self.order_info.get('id') card_no = self.order_info.get('card_no') card = self.base.update_card_dealer_and_type(card_no, cardType='IC', balance=card_balance) if not card: logger.info(log_obj('no this card cardNo:{}'.format(card_no))) return servicedInfo = { 'cardNo': card_no, 'cardBalance': card_balance.mongo_amount } attachParas = { 'orderNo': order_id } # 记录卡消费记录以及消费记录 orderNo, cardOrderNo = self.base.record_consume_for_card(card, amount, servicedInfo=servicedInfo, attachParas=attachParas) consumeOrder = { 'orderNo': orderNo, 'cardOrderNo': cardOrderNo, 'coin': str(amount), 'consumeType': 'card', } self._register_card_service_progress(card, consumeOrder, order_id) title = make_title_from_dict([ {u'设备地址': u'{}'.format(self.dev.group.address)}, {u'设备编号': u'{}'.format(self.dev['logicalCode'])}, {u'实体卡': u'{}--No:{}'.format(card.cardName or card.nickName, card.cardNo)}, {u'本次消费': u'{} 元'.format(amount)}, {u'卡余额': u'{} 元'.format(card_balance)}, ]) self.base.notify_user( card.managerialOpenId, 'dev_start', **{ 'title': title, 'things': u'刷卡消费', 'remark': u'感谢您的支持!', 'time': start_time.strftime(Const.DATETIME_FMT) } ) def _card_refund_do_record_finished(self): card_no = self.order_info.get('card_no') card_balance = RMB.fen_to_yuan(self.order_info.get('balance')) refundMoney = RMB.fen_to_yuan(self.order_info.get('refund')) finishedTime = self.order_info.get('over_time') finishedTime = datetime.datetime.fromtimestamp(finishedTime).strftime('%Y-%m-%d %H:%M:%S') card = self.base.update_card_dealer_and_type(card_no, cardType='IC', balance=card_balance) if card: logger.info(log_obj( 'Card balance sync completed, cardNo:{} , refundMoney:{} ,finishedTime:{}'.format( card_no, refundMoney.mongo_amount, finishedTime))) title = make_title_from_dict([ {u'设备地址': u'{}'.format(self.dev.group.address)}, {u'设备编号': u'{}'.format(self.dev['logicalCode'])}, {u'实体卡': u'{}--No:{}'.format(card.cardName, card.cardNo)}, {u'卡余额': u'{} 元'.format(card_balance)}, ]) self.base.notify_user( card.managerialOpenId, 'refund_coins', **{ 'title': title, 'backCount': u'%s 元' % refundMoney, 'finishTime': finishedTime } ) else: logger.info(log_obj( 'Card balance sync failed, cardNo:{} , refundMoney:{} ,finishedTime:{}'.format( card_no, refundMoney.mongo_amount, finishedTime)))