123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972 |
- # -*- 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='设备启动已退费, 此单标记为后支付<dev_stat:{}>'.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='设备启动已退费, 此单标记为后支付<dev_stat:{}>'.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='设备启动已退费, 此单标记为后支付<dev_stat:{}>'.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)))
|