1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012 |
- # -*- coding: utf-8 -*-
- # !/usr/bin/env python
- import datetime
- import json
- import logging
- from mongoengine import DoesNotExist
- from apilib.monetary import RMB, VirtualCoin
- from apilib.utils_string import make_title_from_dict
- from apilib.utils_sys import memcache_lock
- from apps.web.constant import Const, ErrorCode, DEALER_CONSUMPTION_AGG_KIND
- from apps.web.device.models import Group, Device
- from apps.web.eventer import EventBuilder
- from apps.web.eventer.base import WorkEvent
- from apps.web.eventer.weifuleCommon import WeiFuLeStatusEvent, WeiFuLeCommonEvent
- from apps.web.user.models import ServiceProgress, UserVirtualCard, VCardConsumeRecord, \
- ConsumeRecord, Card, CardConsumeRecord, CardRechargeOrder, MyUser, CardRechargeRecord, RechargeRecord, \
- MonthlyPackage
- logger = logging.getLogger(__name__)
- created_order_32 = 32
- exec_order_33 = 33
- finished_order_34 = 34
- id_card_request_35 = 35
- card_recharge_order_36 = 36
- status_change_event_44 = 44
- ic_consume_event_48 = 48 # ic卡花钱的时候,会上报此事件
- part_sn_event = 49 # 组件上报相关信息
- card_is_normal = 1
- card_not_in_db = 2
- card_is_forzen = 3
- card_has_not_order = 4 # IC卡适用
- card_less_balance = 5 # ID卡适用
- card_type_is_ic = 6 # IC卡不允许当做ID卡使用
- no_load_code = 7
- class builder(EventBuilder):
- def __getEvent__(self, device_event):
- event_data = self.deviceAdapter.analyze_event_data(device_event['data'])
- if event_data is None:
- return None
- if event_data['fun_code'] in [created_order_32, exec_order_33, finished_order_34, id_card_request_35,
- card_recharge_order_36]:
- return ChargingSocketWorkEvent(self.deviceAdapter, event_data)
- if event_data['fun_code'] in [status_change_event_44]:
- return WeiFuLeStatusEvent(self.deviceAdapter, device_event)
- class ChargingSocketWorkEvent(WorkEvent, WeiFuLeCommonEvent):
- def analyse_need_from_package(self, order):
- needKind, needValue, unit = 'needElec', 0, u'度'
- if order['chrmt'] == 'TIME':
- needKind = 'needTime'
- needValue = order['amount_time'] / 60
- unit = u'分钟'
- else:
- needValue = order['amount_elec'] / 1000000.0
- return needKind, needValue, unit
- def create_progress_for_socket_order(self, consumeRcd, order):
- try:
- port = int(order['port'])
- progress = ServiceProgress.objects.filter(device_imei=self.device.devNo, port=port).first()
- if not progress:
- progress = ServiceProgress(device_imei=self.device.devNo, port=port)
- progress.start_time = order['create_time']
- progress.finished_time = order['create_time'] + order.get('amount_time', 60 * 60 * 12)
- progress.isFinished = False
- else:
- if order['id'] in progress.consumes:
- return
- if progress.isFinished == False:
- progress.finished_time = progress.finished_time + order.get('amount_time', 60 * 60 * 12)
- else:
- progress.consumes = []
- progress.start_time = order['create_time']
- progress.finished_time = order['create_time'] + order.get('amount_time', 60 * 60 * 12)
- progress.isFinished = False
- progress.open_id = consumeRcd.openId
- progress.consumes.append(order['id'])
- progress.status = 'running'
- progress.save()
- except Exception as e:
- logger.exception(e)
- def do(self, **args):
- devNo = self.device['devNo']
- funCode = self.event_data.get('fun_code')
- order = self.event_data.get('order', {})
- logger.info('weifule charging event detected, devNo=%s' % (devNo,))
- with memcache_lock(key='%s-%s-%s-finished' % (devNo, order.get('id'), funCode), value='1',
- expire=120) as acquired:
- if acquired:
- self._do_ack_order(order)
- try:
- if funCode == created_order_32:
- self._do_created_order_32(order)
- elif funCode == exec_order_33:
- self._do_exec_order_33(order)
- elif funCode == finished_order_34 and order['order_type'] != 'card_charge':
- self._do_finished_order_34(order)
- elif funCode == finished_order_34 and order['order_type'] == 'card_charge':
- self.update_card_recharge_for_success_event(order['id'], RMB(order['balance'] / 100.0))
- elif funCode == id_card_request_35:
- self.response_id_card()
- elif funCode == card_recharge_order_36: # 如果是卡充值,直接回复订单
- self.deal_with_ic_charge_event()
- except Exception:
- import traceback
- logger.warn(traceback.format_exc())
- logger.info('deal order is finished < funCode: {} order: {} >'.format(funCode, order.get('id')))
- else:
- logger.info('weifule charging event is doing !!!, devNo=%s' % (devNo,))
- def update_balance_for_IC_card(self, card, balance):
- card.balance = balance
- try:
- card.save()
- except Exception, e:
- pass
- def __translate_reason(self, cause, chrmt):
- if cause == 1:
- if chrmt == 'TIME':
- return u'订购时间已经用完。'
- else:
- return u'订购电量已经用完。'
- elif cause == 2:
- return u'用户远程停止。'
- elif cause == 3:
- return u'管理员操作停止。'
- elif cause == 4:
- return u'经销商远程停止。'
- elif cause == 5:
- return u'用户拔掉充电器,或者插座脱落。'
- elif cause == 6:
- return u'端口功率过载,系统为了安全,关闭此充电端口。'
- elif cause == 7:
- return u'整机电压过载,系统为了安全,关闭所有充电端口。'
- elif cause == 8:
- return u'端口电流过载,系统为了安全,关闭此充电端口。'
- elif cause == 9:
- return u'整机功率超限,系统为了安全,关闭所有充电端口。'
- elif cause == 10:
- return u'检测到温度超限,系统为了安全,关闭所有充电端口。'
- elif cause == 11:
- return u'充满自停'
- elif cause == 20:
- return u'端口功率过小。可能是电池已经充满,也可能是所接负载功率太小'
- return u'充电结束。'
- def record_consume_for_card(self, card, money, orderNo):
- group = Group.get_group(self.device['groupId'])
- address = group['address']
- group_number = self.device['groupNumber']
- now = datetime.datetime.now()
- new_record = {
- 'orderNo': orderNo,
- 'time': now.strftime('%Y-%m-%d %H:%M:%S'),
- 'dateTimeAdded': now,
- 'openId': card.openId,
- 'nickname': card.nickName,
- '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': '',
- 'attachParas': {},
- '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': '',
- 'servicedInfo': {},
- 'linkedConsumeRcdOrderNo': str(new_record['orderNo'])
- }
- CardConsumeRecord.get_collection().insert(new_card_record)
- return new_record['orderNo'], new_card_record['orderNo']
- def record_consume_for_monthly_package(self, card, info):
- # type: (Card, dict)-> (ConsumeRecord, CardConsumeRecord)
- monthlyPackage = card.monthlyPackage
- group = Group.get_group(self.device['groupId'])
- address = group['address']
- group_number = self.device['groupNumber']
- now = datetime.datetime.now()
- new_record = {
- 'orderNo': info['id'],
- 'time': now.strftime('%Y-%m-%d %H:%M:%S'),
- 'dateTimeAdded': now,
- 'openId': card.openId,
- 'nickname': card.nickName,
- 'ownerId': self.device['ownerId'],
- 'coin': VirtualCoin(0).mongo_amount,
- 'money': RMB(0).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': '',
- 'attachParas': {'monthlyPackageId': str(monthlyPackage.id)},
- 'servicedInfo': {'chargeIndex': info['port'], 'cardNo': info['card_no']}
- }
- consumeRcd = ConsumeRecord.objects.create(**new_record)
- # 刷卡消费也记录一条数据
- new_card_record = {
- 'orderNo': info['id'],
- 'openId': card.openId,
- 'cardId': str(card.id),
- 'money': RMB(0).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': '',
- 'servicedInfo': {'chargeIndex': info['port'], 'cardNo': info['card_no']},
- 'linkedConsumeRcdOrderNo': str(new_record['orderNo'])
- }
- CardConsumeRecord.objects.create(**new_card_record)
- return consumeRcd
- def _do_ack_order(self, order):
- funCode = self.event_data['fun_code']
- if funCode in [created_order_32, finished_order_34]:
- try:
- self.deviceAdapter.ack_event(order['id'], funCode)
- except Exception, e:
- logger.info('ack event devNo=%s err=%s' % (self.device.devNo, e))
- pass
- def _do_created_order_32(self, order):
- if order['order_type'] == 'apps_start': # 扫码
- self.pay_apps_start_by_32(order)
- consumeRcd = ConsumeRecord.objects.filter(orderNo=order['id']).first()
- if consumeRcd is None: #远程上分的时候,没有consumeRcd
- return None
- self.create_progress_for_socket_order(consumeRcd, order)
- elif order['order_type'] == 'card_start':
- cardNo = order['card_no']
- # 登记下卡相关信息
- if order['card_type'] == 'IC':
- card = self.update_card_dealer_and_type(cardNo, 'IC')
- if card:
- self.update_balance_for_IC_card(card, RMB(order['balance'] / 100.0))
- else:
- return
- # 如果卡冻结了,马上把端口关闭
- if card.frozen:
- logger.info('this card=%s is frozen,so shut down the port which opened by the card' % cardNo)
- self.deviceAdapter.stop_charging_port(order['port'])
- else:
- card = self.update_card_dealer_and_type(cardNo, 'ID')
- if card.monthlyPackage:
- return self.start_by_monthly_package(card, order)
- balance = card.balance - RMB(order['amount'] / 100.0)
- card.balance = balance
- # 卡的显示余额同步下
- card.showBalance = balance
- card.save()
- fee = RMB(order['amount'] / 100.0)
- # 记录卡消费记录以及消费记录
- orderNo, cardOrderNo = self.record_consume_for_card(card, fee, order['id'])
- consumeRcd = ConsumeRecord.objects.filter(orderNo=orderNo).first()
- if consumeRcd is None:
- return
- self.create_progress_for_socket_order(consumeRcd, order)
- # 通知用户,已经扣费
- title = make_title_from_dict([
- {u'设备地址': u'{}'.format(self.device.group.address)},
- {u'设备编号': u'{}'.format(self.device['logicalCode'])},
- {u'实体卡': u'{}--No:{}'.format(card.cardName or card.nickName, card.cardNo)},
- {u'本次消费': u'{} 元'.format(fee)},
- {u'卡余额': u'{} 元'.format(RMB(order['balance'] / 100.0))},
- ])
- start_time_stamp = order.get('create_time')
- start_time = datetime.datetime.fromtimestamp(start_time_stamp)
- self.notify_user(
- card.managerialOpenId,
- 'dev_start',
- **{
- 'title': title,
- 'things': u'刷卡消费',
- 'remark': u'感谢您的支持!',
- 'time': start_time.strftime(Const.DATETIME_FMT)
- }
- )
- # 缓存切换
- ctrInfo = Device.get_dev_control_cache(self.device.devNo)
- lineInfo = ctrInfo.get(str(order['port']), {})
- if not lineInfo or lineInfo.get('status') == Const.DEV_WORK_STATUS_IDLE:
- lineInfo = {
- 'port': str(order['port']),
- 'status': Const.DEV_WORK_STATUS_WORKING,
- 'order_type': 'card_start',
- 'startTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- 'orderNo': orderNo,
- }
- Device.update_port_control_cache(self.device.devNo, lineInfo)
- else:
- pass
- def _do_exec_order_33(self, order):
- now = datetime.datetime.fromtimestamp(order['exec_time'])
- consumeRcd = ConsumeRecord.objects.filter(orderNo=order['id']).first()
- if not consumeRcd:
- logger.info('no this order <{}> '.format(order['id']))
- return
- consumeRcd.startTime = now
- consumeRcd.save()
- ctrInfo = Device.get_dev_control_cache(self.device.devNo)
- lineInfo = ctrInfo.get(str(order['port']), {})
- if lineInfo.get('status') == Const.DEV_WORK_STATUS_WORKING and lineInfo.get('orderNo') == order['id']:
- lineInfo.update({'chrmt': order['chrmt']})
- if 'card_no' in order:
- lineInfo.update({'cardType': order.get('card_type'), 'cardNo': order.get('card_no')})
- Device.update_port_control_cache(self.device.devNo, lineInfo)
- logger.info('now to exec order <{}>'.format(lineInfo.get('orderNo')))
- return
- consumeRcd = ConsumeRecord.objects.filter(orderNo=order['id']).first()
- if consumeRcd is None:
- return
- lineInfo = {
- 'port': str(order['port']),
- 'status': Const.DEV_WORK_STATUS_WORKING,
- 'order_type': order['order_type'],
- 'startTime': now.strftime('%Y-%m-%d %H:%M:%S'),
- 'orderNo': consumeRcd.orderNo,
- 'chrmt': order['chrmt']
- }
- if 'card_no' in order:
- lineInfo.update({'cardType': order.get('card_type'), 'cardNo': order.get('card_no')})
- Device.update_port_control_cache(self.device.devNo, lineInfo)
- logger.info('now to exec next order <{}>'.format(lineInfo.get('orderNo')))
- def _do_finished_order_34(self, order):
- # 如果是离线卡的余额回收,修改下余额,然后直接返回即可
- if order['order_type'] == 'card_refund':
- return self.end_for_card_refund(order)
- self.consumeRcd = self.common_verify_order(order) # type: ConsumeRecord
- if not self.consumeRcd:
- return
- try:
- self._init_common_info(order)
- if self.is_postpaid:
- return self.end_of_auto_stop(order)
- elif self.consumeRcd.monthlyPackageId:
- return self.end_for_monthly_package(order)
- else:
- self._analyze_order_info(order)
- self._analyze_notify_info(order)
- self._analyze_refund_info(order)
- self._calc_refund_coins(order)
- self.refundDict.update({'backCount': u'金币:%s' % self.backCoins})
- # 虚拟卡
- if u'虚拟卡' in self.consumeRcd.remarks:
- self.end_for_vCard_start(order)
- # 刷卡的方式
- elif order['order_type'] == 'card_start' and order['card_no']:
- self.end_for_card_start(order)
- # 扫码的
- else:
- self.end_for_app_start(order)
- self.consumeRcd.update_service_info(self.consumeDict)
- except Exception as e:
- logger.exception('some exception happed,devNo=%s,e=%s' % (self.device.devNo, e))
- finally:
- ctrInfo = Device.get_dev_control_cache(self.device.devNo)
- lineInfo = ctrInfo.get(str(order['port']), {})
- # 如果缓存中要结束的端口是本单的 就清空缓存 否则不处
- if order['id'] == lineInfo.get('orderNo'):
- Device.clear_port_control_cache(self.device.devNo, order['port'])
- # 这里采用更新端口 不操作缓存
- self.deviceAdapter.get_port_status_from_dev()
- def common_verify_order(self, order):
- consumeRcd = ConsumeRecord.objects.filter(orderNo=order['id'],
- status__ne='finished').first() # type:ConsumeRecord
- if not consumeRcd:
- logger.info('Repeat processing!! orderNo<{}>'.format(order['id']))
- return
- else:
- consumeRcd.status = 'finished'
- consumeRcd.finishedTime = datetime.datetime.now()
- consumeRcd.servicedInfo['source'] = json.dumps(order)
- consumeRcd.save()
- progress = ServiceProgress.objects.filter(device_imei=self.device.devNo, port=int(order['port']),
- consumes__contains=order['id']).first()
- if progress is None:
- pass
- else:
- progress.consumes.remove(order['id'])
- if len(progress.consumes) > 0: # 还有其他的单未处理完成
- progress.save()
- else:
- progress.status = 'finished' # 此时为本次服务的最后一单
- progress.isFinished = True
- progress.save()
- return consumeRcd
- def end_for_card_refund(self, order):
- return self.update_card_dealer_and_type(cardNo=order['card_no'], cardType='IC',
- balance=RMB(order['balance'] / 100.0))
- def deal_with_ic_charge_event(self):
- cardNo = self.event_data['card_no']
- card = self.update_card_dealer_and_type(cardNo, 'IC')
- if not card:
- return self.deviceAdapter.response_card_charge_result(self.event_data['card_no'], card_not_in_db)
- elif card.frozen:
- return self.deviceAdapter.response_card_charge_result(self.event_data['card_no'], card_is_forzen)
- preBalance = card.balance
- rechargeOrder = CardRechargeOrder.get_last_to_do_one(str(card.id))
- if rechargeOrder:
- self.recharge_ic_card(card=card,
- preBalance=preBalance,
- rechargeType='append',
- order=rechargeOrder,
- need_verify=False)
- else:
- return self.deviceAdapter.response_card_charge_result(self.event_data['card_no'], card_has_not_order)
- def recharge_ic_card(self, card, preBalance, rechargeType, order, need_verify=True):
- # type:(Card, RMB, str, CardRechargeOrder, bool)->bool
- """
- # rechargeType有两种,一种是用直接覆写overwrite的方式,一种是append追加钱的方式。
- # 不同的的设备,充值的方式还不一样.注意:money是实际用户付的钱,coins是给用户充值的钱,比如付10块(money),充15(coins)。
- :param card:
- :param preBalance:
- :param rechargeType:
- :param order:
- :return:
- """
- if not order or order.coins == RMB(0):
- return False
- status = Card.get_card_status(str(card.id))
- if status == 'busy':
- return False
- Card.set_card_status(str(card.id), 'busy')
- try:
- # IC卡需要下发到设备,设备写卡,把余额打入卡中
- if rechargeType == 'overwrite':
- sendMoney = preBalance + order.coins
- else:
- sendMoney = order.coins
- # 先判断order最近一次充值是否OK. 满足三个条件才认为上次充值成功:
- # 1、操作时间已经超过三天
- # 2、操作结果是串口超时, 即result == 1
- # 3、当前余额大于最后一次充值操作的充值前余额
- if need_verify and len(order.operationLog) > 0:
- log = order.operationLog[-1]
- result = log['result']
- time_delta = (datetime.datetime.now() - log['time']).total_seconds()
- last_pre_balance = RMB(log['preBalance'])
- if (result == ErrorCode.DEVICE_CONN_FAIL or result == ErrorCode.BOARD_UART_TIMEOUT) \
- and (time_delta > 3 * 24 * 3600 or preBalance > last_pre_balance):
- logger.debug('{} recharge verify result is finished.'.format(repr(card)))
- order.update_after_recharge_ic_card(device=self.device,
- sendMoney=sendMoney,
- preBalance=preBalance,
- result=ErrorCode.SUCCESS,
- description=u'充值校验结束')
- CardRechargeRecord.add_record(
- card=card,
- group=Group.get_group(order.groupId),
- order=order,
- device=self.device)
- return False
- try:
- operation_result, balance = self.deviceAdapter.recharge_card(card.cardNo, sendMoney,
- orderNo=str(order.id))
- order.update_after_recharge_ic_card(device=self.device,
- sendMoney=sendMoney,
- preBalance=preBalance,
- syncBalance=balance,
- result=operation_result['result'],
- description=operation_result['description'])
- if operation_result['result'] != ErrorCode.SUCCESS:
- return False
- if not balance:
- balance = preBalance + order.coins
- CardRechargeRecord.add_record(
- card=card,
- group=Group.get_group(order.groupId),
- order=order,
- device=self.device)
- # 刷新卡里面的余额
- card.balance = balance
- card.lastMaxBalance = balance
- card.save()
- return True
- except Exception as e:
- order.update_after_recharge_ic_card(device=self.device,
- sendMoney=sendMoney,
- preBalance=preBalance,
- syncBalance=balance,
- result=ErrorCode.EXCEPTION,
- description=e.message)
- return False
- except Exception as e:
- logger.exception(e)
- return False
- finally:
- Card.set_card_status(str(card.id), 'idle')
- def response_id_card(self):
- cardNo = self.event_data['card_no']
- Card.record_dev_card_no(self.device['devNo'], cardNo)
- card = Card.objects.filter(cardNo=cardNo, agentId=self.device.owner.agentId).first()
- # 如果没有卡,直接返回
- if card is None:
- return self.deviceAdapter.response_card_balance(cardNo=cardNo, balance=0, result=card_not_in_db, amount=0)
- if card.cardType == '':
- card.update(cardType='ID')
- elif card.cardType != 'ID': # 如果以前是离线卡,只能用于离线卡,需要提醒用户
- return self.deviceAdapter.response_card_balance(cardNo=cardNo, balance=0, result=card_type_is_ic, amount=0)
- if card.frozen:
- return self.deviceAdapter.response_card_balance(cardNo=cardNo, balance=0, result=card_is_forzen, amount=0)
- card_recharge_order = CardRechargeOrder.get_last_to_do_one(str(card.id))
- if card_recharge_order:
- result = self.recharge_id_card(card=card,
- rechargeType='append',
- order=card_recharge_order)
- card.reload()
- oper = self.event_data.get('reduce')
- fee = RMB(self.device['otherConf'].get('id_card_oncefee', 1))
- if card.monthlyPackage:
- dayLeft = card.monthlyPackage.to_dict().get('dayLeft')
- if dayLeft > 0:
- result = card_is_normal
- if oper:
- balance = fee * dayLeft - fee
- else:
- balance = fee * dayLeft
- return self.deviceAdapter.response_card_balance(cardNo, fee, balance, result)
- if oper:
- if card.balance >= fee:
- result = card_is_normal
- balance = card.balance - fee
- # balance = card.showBalance * 100
- else:
- result = card_less_balance
- # balance = card.showBalance * 100
- balance = card.balance
- self.deviceAdapter.response_card_balance(cardNo, fee, balance, result) # 返回的cardNo为16进制
- else:
- self.deviceAdapter.response_card_balance(cardNo, fee, card.balance, card_is_normal)
- def _init_common_info(self, order):
- """
- 初始化结束要用到的数据
- """
- order['reason'] = self.__translate_reason(order['cause'], order['chrmt'])
- self.consumeDict = {
- 'reason': order['reason'],
- 'chargeIndex': order['port'],
- 'duration': round(order['time'] / 60.0, 1),
- 'elec': round(order['elec'] / 1000000.0, 2)
- }
- self.notifyDict = {
- 'title': make_title_from_dict([
- {u'设备编号': self.device['logicalCode']},
- {u'端口': order['port']},
- {u'地址': self.device.group['address']},
- {u'结束原因': order['reason']},
- {u'充电时间': u'%s分钟' % self.consumeDict['duration']},
- ]),
- 'service': u'充电服务完成',
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- 'remark': u'谢谢您的支持'
- }
- self.refundDict = {
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
- }
- self.refundProtection = self.device['otherConf'].get('refundProtection', 5)
- def _calc_refund_coins(self, order):
- coins = self.consumeRcd.coin
- self.backCoins = RMB(0)
- usedTime = round(order['time'] / 60.0, 1)
- if usedTime <= self.refundProtection:
- self.backCoins = coins
- else:
- if self.device.is_auto_refund:
- self.backCoins = coins * (float(order['left_money']) / float(order['amount']))
- logger.info(
- 'REFUND STATUS orderNo=<{}>, refundSwitch={}, refundProtectionTime=<{}>, backCoins=<{}>'.format(
- self.consumeRcd.orderNo, self.device.is_auto_refund, self.refundProtection, self.backCoins.mongo_amount
- ))
- def _analyze_elec_params(self, order):
- needElec = round(order['amount_elec'] / 1000000.0, 2)
- usedTime = round(order['time'] / 60.0, 1)
- usedElec = round(order['elec'] / 1000000.0, 2)
- leftElec = round(needElec - usedElec if needElec > usedElec else 0.0, 2)
- return leftElec, needElec, usedElec, usedTime
- def _analyze_time_params(self, order):
- needTime = round(order['amount_time'] / 60.0, 1)
- usedTime = round(order['time'] / 60.0, 1)
- leftTime = round(order['left_time'] / 60 if order['left_time'] > 0 else 0, 1)
- actualNeedTime = round(usedTime + leftTime, 1)
- return actualNeedTime, leftTime, needTime, usedTime
- def _analyze_order_info(self, order):
- if order['chrmt'] == 'TIME':
- actualNeedTime, leftTime, needTime, usedTime = self._analyze_time_params(order)
- self.consumeDict.update({
- 'needTime': needTime,
- 'leftTime': leftTime,
- 'actualNeedTime': u'动态功率计算为%s分钟' % actualNeedTime,
- })
- else:
- leftElec, needElec, usedElec, usedTime = self._analyze_elec_params(order)
- self.consumeDict.update({
- 'needElec': needElec,
- 'leftElec': leftElec,
- })
- def _analyze_notify_info(self, order):
- if order['chrmt'] == 'TIME':
- actualNeedTime, leftTime, needTime, usedTime = self._analyze_time_params(order)
- self.notifyDict.update({'title': make_title_from_dict([
- {u'设备编号': self.device['logicalCode']},
- {u'端口': order['port']},
- {u'地址': self.device.group['address']},
- {u'结束原因': order['reason']},
- {u'订购时间': u'%s分钟' % needTime},
- {u'应充时间': u'%s分钟' % actualNeedTime},
- {u'充电时间': u'%s分钟' % usedTime},
- {u'剩余时间': u'%s分钟' % leftTime}
- ])})
- else:
- leftElec, needElec, usedElec, usedTime = self._analyze_elec_params(order)
- self.notifyDict.update({'title': make_title_from_dict([
- {u'设备编号': self.device['logicalCode']},
- {u'端口': order['port']},
- {u'结束原因': order['reason']},
- {u'充电时间': u'%s分钟' % usedTime},
- {u'订购电量': u'%s度' % needElec},
- {u'消耗电量': u'%s度' % usedElec},
- {u'剩余电量': u'%s度' % leftElec},
- ])})
- def _analyze_refund_info(self, order):
- if order['chrmt'] == 'TIME':
- actualNeedTime, leftTime, needTime, usedTime = self._analyze_time_params(order)
- refundTitleDictList = [
- {u'设备编号': self.device['logicalCode']},
- {u'端口': order['port']},
- {u'结束原因': order['reason']},
- {u'预定时间': u'%s分钟' % needTime},
- {u'应充时间': u'%s分钟' % actualNeedTime},
- {u'充电时间': u'%s分钟' % usedTime},
- {u'剩余时间': u'%s分钟' % leftTime},
- ]
- else:
- leftElec, needElec, usedElec, usedTime = self._analyze_elec_params(order)
- refundTitleDictList = [
- {u'设备编号': self.device['logicalCode']},
- {u'端口': order['port']},
- {u'结束原因': order['reason']},
- {u'充电时间': u'%s分钟' % usedTime},
- {u'订购电量': u'%s度' % needElec},
- {u'消耗电量': u'%s度' % usedElec},
- {u'剩余电量': u'%s度' % leftElec},
- ]
- self.refundDict.update({'title': make_title_from_dict(refundTitleDictList), })
- def end_for_monthly_package(self, order):
- """
- 包月卡的流程 单独走
- """
- self._init_common_info(order)
- usedTime = round(order['time'] / 60.0, 1)
- if usedTime <= self.refundProtection:
- monthlyPackage = MonthlyPackage.objects.filter(id=self.consumeRcd.monthlyPackageId).first()
- if not monthlyPackage:
- return
- monthlyPackage.rollback(self.consumeRcd)
- else:
- pass
- # 通知服务结束
- self.consumeRcd.update_service_info(self.consumeDict)
- notifyOpenId = self.consumeRcd.user.managerialOpenId
- self.notify_user(notifyOpenId, 'service_complete', **self.notifyDict)
- def end_of_auto_stop(self, order):
- self._init_common_info(order)
- usedFee = VirtualCoin(order['money'] * 0.01)
- usedTime = order['time'] / 60
- if usedTime <= self.refundProtection:
- usedFee = VirtualCoin(0)
- self.consumeDict.update({
- DEALER_CONSUMPTION_AGG_KIND.SPEND_MONEY: usedFee.mongo_amount
- })
- user = MyUser.objects(openId=self.consumeRcd.openId, groupId=self.device['groupId']).first()
- if not user:
- return
- try:
- user.pay(usedFee)
- self.consumeRcd.update(coin=usedFee.mongo_amount, status='finished')
- except Exception:
- pass
- self.notifyDict.update(
- {'title': make_title_from_dict([
- {u'设备编号': self.device['logicalCode']},
- {u'端口': order['port']},
- {u'地址': self.device.group['address']},
- {u'结束原因': order['reason']},
- {u'充电时间': u'%s分钟' % round(usedTime, 1)},
- {u'本次服务费用': u'%s币' % usedFee},
- ])})
- # 通知服务结束
- notifyOpenId = user.managerialOpenId if user else ''
- self.notify_user(notifyOpenId, 'service_complete', **self.notifyDict)
- self.consumeRcd.update_service_info(self.consumeDict)
- logger.info('orderNo<{}> finished!!'.format(self.consumeRcd.orderNo))
- def end_for_vCard_start(self, order):
- try:
- vRcd = VCardConsumeRecord.objects.get(orderNo=order['id'])
- vCard = UserVirtualCard.objects.get(id=vRcd.cardId)
- except DoesNotExist, e:
- logger.info('can not find the vCard id = %s' % vRcd.cardId)
- return
- # 通知服务结束
- notifyOpenId = self.get_managerialOpenId_by_openId(vRcd.openId)
- self.notify_user(notifyOpenId, 'service_complete', **self.notifyDict)
- # 不需要退款,直接返回,不通知
- if self.device.is_auto_refund:
- if order['chrmt'] == 'TIME':
- vCard.refund_quota(vRcd, self.consumeDict['duration'], 0.0, 0.0)
- else:
- vCard.refund_quota(vRcd, 0.0, self.consumeDict['usedElec'], 0.0)
- def end_for_card_start(self, order):
- card = Card.objects.filter(agentId=self.device.owner.agentId, cardNo=order['card_no']).first()
- if card is None: # 离线卡没有绑定或者在线卡被解绑了
- return
- if self.consumeRcd.monthlyPackageId:
- return self.end_for_monthly_package(order)
- # 先通知
- notifyOpenId = card.managerialOpenId if card else ''
- self.notify_user(notifyOpenId, 'service_complete', **self.notifyDict)
- # 不需要退款,直接返回.在线卡需要退费,离线卡只登记使用记录就OK
- if self.backCoins > RMB(0) and card.cardType == 'ID':
- card = self.refund_money_for_card(self.backCoins, card.id)
- card.showBalance = card.balance
- card.save()
- self.consumeDict.update({'refundedMoney': self.backCoins.mongo_amount})
- self.notify_user(notifyOpenId, 'refund_coins', **self.refundDict)
- def end_for_app_start(self, order):
- self.notify_user(self.consumeRcd.user.managerialOpenId, 'service_complete', **self.notifyDict)
- # 如果需要退款,计算退款数据.
- if self.backCoins > RMB(0):
- openId = self.consumeRcd.user.openId
- lineInfo = {'openId': openId}
- refundRMB = RMB(0)
- refundCash = 'refundRMB_device_event' in self.device.owner.features
- if refundCash and self.consumeRcd.recharge_record_id:
- rechargeRcd = RechargeRecord.objects.filter(id=self.consumeRcd.recharge_record_id,
- openId=openId,
- devNo=self.device.devNo,
- isQuickPay=True,
- groupId=self.device.groupId).first()
- refundRMB = rechargeRcd.money * (self.backCoins.amount / self.consumeRcd.coin.amount)
- lineInfo.update({'rechargeRcdId': self.consumeRcd.recharge_record_id})
- self.refundDict.update({'backCount': u'金额:%s' % refundRMB})
- self.refund_net_pay(self.consumeRcd.user, lineInfo,
- refundRMB, self.backCoins, self.consumeDict, refundCash)
- self.notify_user(self.consumeRcd.user.managerialOpenId, 'refund_coins', **self.refundDict)
- @property
- def is_postpaid(self):
- return self.consumeRcd.package.get('name') == '充满自停' and self.consumeRcd.package.get('coins') == 0 and self.consumeRcd.package.get('price') == 0
- def start_by_monthly_package(self, card, order):
- monthlyPackage = card.monthlyPackage
- consumeRcd = self.record_consume_for_monthly_package(card, order)
- monthlyPackage.deduct(consumeRcd)
- self.create_progress_for_socket_order(consumeRcd, order)
- # 通知用户,已经扣费
- title = make_title_from_dict([
- {u'设备地址': u'{}'.format(self.device.group.address)},
- {u'设备编号': u'{}'.format(self.device['logicalCode'])},
- {u'实体卡': u'{}--No:{}'.format(card.cardName or card.nickName, card.cardNo)},
- {u'本次消费': u'包月卡抵扣'.format(0)},
- ])
- start_time_stamp = order.get('create_time')
- start_time = datetime.datetime.fromtimestamp(start_time_stamp)
- self.notify_user(
- card.managerialOpenId,
- 'dev_start',
- **{
- 'title': title,
- 'things': u'刷卡消费',
- 'remark': u'感谢您的支持!',
- 'time': start_time.strftime(Const.DATETIME_FMT)
- }
- )
- # 缓存切换
- ctrInfo = Device.get_dev_control_cache(self.device.devNo)
- lineInfo = ctrInfo.get(str(order['port']), {})
- if not lineInfo or lineInfo.get('status') == Const.DEV_WORK_STATUS_IDLE:
- lineInfo = {
- 'port': str(order['port']),
- 'status': Const.DEV_WORK_STATUS_WORKING,
- 'order_type': 'card_start',
- 'startTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- 'orderNo': consumeRcd.orderNo,
- }
- Device.update_port_control_cache(self.device.devNo, lineInfo)
|