1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503 |
- # -*- coding: utf-8 -*-
- # !/usr/bin/env python
- import datetime
- import json
- import logging
- import time
- from arrow import Arrow
- from django.conf import settings
- from mongoengine import DoesNotExist
- from apilib.monetary import RMB, VirtualCoin, Ratio
- from apilib.systypes import StrEnum
- from apilib.utils_datetime import to_datetime
- from apilib.utils_string import make_title_from_dict
- from apps.web.agent.models import Agent
- from apps.web.constant import Const, DEALER_CONSUMPTION_AGG_KIND, APP_TYPE, DeviceCmdCode
- from apps.web.core.accounting import Accounting
- from apps.web.core.adapter.base import SmartBox
- from apps.web.core.adapter.hedong import ChargingHDBox
- from apps.web.core.device_define.jndz import CMD_CODE, SWIPE_CARD_PARAM_OP, SWIPE_CARD_RES
- from apps.web.core.exceptions import ServiceException
- from apps.web.core.networking import MessageSender
- from apps.web.dealer.models import Dealer
- from apps.web.device.models import Group, Device, DeviceDict, GroupDict
- from apps.web.eventer import EventBuilder
- from apps.web.eventer.base import FaultEvent, WorkEvent, ComNetPayAckEvent, AckEventProcessorIntf, \
- IcStartAckEvent, IcRechargeAckEvent, CardRefundAckEvent, IdStartAckEvent, VirtualCardStartAckEvent
- from apps.web.eventer.errors import InvalidOption, NoCommandHandlerAvailable
- from apps.web.helpers import get_wechat_auth_bridge
- 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.south_intf.zhongtian import report_zhongtian_service_complete, report_zhongtian_refund
- from apps.web.user.models import VCardConsumeRecord, ServiceProgress, CardRechargeOrder, MyUser, \
- UserVirtualCard, Card, ConsumeRecord, RechargeRecord
- from apps.web.api.models import APIStartDeviceRecord
- from apps.web.user.utils import freeze_user_balance
- logger = logging.getLogger(__name__)
- class Cmd:
- # 刷卡类
- SUCCESS_00 = 0
- BALANCE_NOT_ENOUGH_01 = 1
- INVALID_CARD_02 = 2
- class CARD_TYPE(StrEnum):
- OFFLINE_CARD = "00"
- ONLINE_CARD = "01"
- MONTHLY_CARD = "02"
- FULL_CARD = "04"
- def is_server_refund(billingType, dev, dealer, agent):
- # type:(str, DeviceDict, Dealer, Agent)->bool
- if billingType != 'time':
- if 'jhCardElecRefund' in dealer.features:
- return False
- if dev.is_auto_refund:
- return True
- else:
- return False
- else:
- if 'huopo_card_time_refund' in agent.features:
- return True
- else:
- support_server_refund = dev.devType.get('features', {}).get(
- 'support_server_refund', False)
- if not support_server_refund:
- return False
- if dev.is_auto_refund:
- return True
- else:
- return False
- class builder(EventBuilder):
- def __getEvent__(self, device_event):
- if 'order_id' in device_event:
- if device_event['order_type'] == 'com_start':
- return MyComNetPayAckEvent(self.deviceAdapter, device_event)
- elif device_event['order_type'] == 'ic_recharge':
- return MyIcRechargeAckEvent(self.deviceAdapter, device_event)
- elif device_event['order_type'] == 'ic_start':
- return MyIcStartAckEvent(self.deviceAdapter, device_event)
- elif device_event['order_type'] == 'id_start':
- return MyIdStartAckEvent(self.deviceAdapter, device_event)
- elif device_event['order_type'] == 'vir_start':
- return MyVirtualCardStartAckEvent(self.deviceAdapter, device_event)
- elif device_event['order_type'] == 'card_refund':
- return MyCardRefundAckEvent(self.deviceAdapter, device_event)
- else:
- pass
- elif 'event_type' in device_event:
- if device_event['event_type'] == 'card':
- return CardEvent(self.deviceAdapter, device_event)
- else:
- return None
- event_data = self.deviceAdapter.analyze_event_data(device_event['data'])
- if event_data is None or 'cmdCode' not in event_data:
- return None
- if 'duration' in device_event:
- event_data.update({'duration': device_event['duration']})
- if event_data['cmdCode'] in ['06', '16', '20', '2D', '2C']:
- return ChargingJNDZWorkEvent(self.deviceAdapter, event_data)
- if event_data['cmdCode'] in [
- CMD_CODE.DEVICE_SUBMIT_DEVICE_FAULT_0A,
- CMD_CODE.DEVICE_FAULT_TEMPERATURE,
- CMD_CODE.DEVICE_FAULT_POWER,
- CMD_CODE.DEVICE_FAULT_SMOKE,
- CMD_CODE.DEVICE_ELEC,
- CMD_CODE.DEVICE_FAULT_ALTER
- ]:
- return JNDZEventerFailure(self.deviceAdapter, event_data)
- #if event_data['cmdCode'] == '21':
- # return ChargingJNDZReportEvent(self.deviceAdapter, event_data)
- class CardEvent(WorkEvent):
- def do(self):
- if not self.deviceAdapter.get_device_configs(): # type:ChargingHDBox.get_device_configs()
- self.deviceAdapter.get_dev_setting()
- if self.event_data['funCode'] == '10':
- self._do_get_balance()
- def _do_get_balance(self):
- cardNo = str(int(self.event_data["cardNo"], 16))
- logger.info('[_do_get_balance] receive cardNo = {}'.format(cardNo))
- card = self.update_card_dealer_and_type(cardNo)
- if not card or not card.openId or card.frozen:
- logger.info('[_do_get_balance] receive cardNo = {}, card invalid!'.format(cardNo))
- data = {
- 'funCode': '10',
- 'cardNo': self.event_data.get('cardNo'),
- 'result': Cmd.INVALID_CARD_02,
- 'balance': 0,
- }
- else:
- # 是否存在没有到账的余额 进行充值
- card_recharge_order = CardRechargeOrder.get_last_to_do_one(str(card.id))
- self.recharge_id_card(
- card=card,
- rechargeType='append',
- order=card_recharge_order
- )
- card.reload()
- device_configs = self.deviceAdapter.get_device_configs()
- cst = RMB(device_configs.get('cst', 30) / 10.0)
- if card.balance >= RMB(0.1):
- pay = int(min(cst, card.balance) * 10) * 0.1 # 采用向下取整
- rule = self.get_account_rule(pay) # 下发对应的额度
- data = {
- 'funCode': '10',
- 'cardNo': self.event_data.get('cardNo'),
- 'result': Cmd.SUCCESS_00,
- 'balance': int(card.balance * 10.0),
- }
- data.update(rule)
- else:
- data = {
- 'funCode': '10',
- 'cardNo': self.event_data.get('cardNo'),
- 'result': Cmd.BALANCE_NOT_ENOUGH_01,
- 'balance': 0,
- }
- self.send_mqtt(data=data)
- def send_mqtt(self, data=None, cmd=DeviceCmdCode.OPERATE_DEV_SYNC, otherData=None):
- '''
- 发送mqtt 指令默认210 返回data
- '''
- result = MessageSender.send(self.device, cmd,
- data)
- if 'rst' in result and result['rst'] != 0:
- if result['rst'] == -1:
- raise ServiceException(
- {'result': 2, 'description': u'该设备正在玩命找网络,请您稍候再试', 'rst': -1})
- elif result['rst'] == 1:
- raise ServiceException(
- {'result': 2, 'description': u'该设备忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能', 'rst': 1})
- else:
- if cmd in [DeviceCmdCode.OPERATE_DEV_NO_RESPONSE, DeviceCmdCode.PASSTHROUGH_OPERATE_DEV_NO_RESPONSE]:
- return
- return result.get('data', 'ok')
- def get_account_rule(self, coins):
- device_configs = self.deviceAdapter.get_device_configs()
- cardMin = device_configs.get('cardMin', 240)
- cardElec = device_configs.get('cardElec', 10)
- # 秒
- timeMax = int(coins * 60 * cardMin)
- # 度 > 瓦
- elecMax = int(coins * 0.1 * 3600000 * cardElec)
- powerMax1 = device_configs.get('powerMax1', 200)
- power1Ti = device_configs.get('power1Ti', 100)
- powerMax2 = device_configs.get('powerMax2', 300)
- power2Ti = device_configs.get('power2Ti', 75)
- powerMax3 = device_configs.get('powerMax3', 400)
- power3Ti = device_configs.get('power3Ti', 50)
- powerMax4 = device_configs.get('powerMax4', 500)
- power4Ti = device_configs.get('power4Ti', 25)
- return {
- 'timeMax': timeMax,
- 'elecMax': elecMax,
- 'accountRule': {
- 'powerStep': [
- {'max': powerMax1,
- 'ratio': power1Ti},
- {'max': powerMax2,
- 'ratio': power2Ti},
- {'max': powerMax3,
- 'ratio': power3Ti},
- {'max': powerMax4,
- 'ratio': power4Ti},
- ]
- }
- }
- class JNDZEventerFailure(FaultEvent):
- def do(self, **args):
- cmdCode = self.event_data.get('cmdCode')
- faultType = self.event_data.get(u'fault')
- desc = self.event_data.get('desc', '')
- # 保证原有的故障处理逻辑不变
- if cmdCode == CMD_CODE.DEVICE_SUBMIT_DEVICE_FAULT_0A:
- if self.event_data.get('FaultCode') == 1: # 不准确的继电器粘连上报
- pass
- else:
- super(JNDZEventerFailure, self).do()
- group = Group.get_group(self.device.groupId)
- titleList = [
- {u'告警名称': faultType},
- {u'地址名称': group['groupName']}
- ]
- title = make_title_from_dict(titleList)
- # 接下来的都是整机告警,这个地方需要通知到经销商
- # TODO zjl 需要知道 这个告警标志位是否有具体含义
- self.notify_dealer(
- 'device_fault',
- title = title,
- device = u' 号设备'.format(self.device.logicalCode),
- faultType = faultType,
- notifyTime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- fault = ''
- )
- # 记录错误故障
- self.record(
- faultCode = cmdCode,
- description = desc,
- title = faultType,
- detail ={'faultType':faultType}
- )
- class ChargingJNDZWorkEvent(WorkEvent):
- def do(self, **args):
- devNo = self.device['devNo']
- logger.info('JingNengDianZi charging event detected, devNo=%s,curInfo=%s' % (devNo, self.event_data))
- cmdCode = self.event_data['cmdCode']
- #: 刷卡消费的,分为扣费和退费两种
- if cmdCode == CMD_CODE.SWIPE_CARD_10:
- if self.device.support_reliable:
- return self.do_id_response_support_reliable(**args)
- 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:
- self.response_use_card(SWIPE_CARD_RES.INVALID_CARD_02, 0)
- 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('JingNengDianZi cmdNo(10) - cardNo=%s, openId=%s, result=%s, preFee=%s, curinfo=%s' % (
- cardNo, card.openId, result, preFee, self.event_data))
- # TODO 这个地方为了同时满足劲能电子和霍珀的需求 先使用特性 vCardNeedBind 后续需要统一规则
- try:
- dealer = Dealer.get_dealer(card.dealerId)
- agent = Agent.objects.get(id = dealer.get('agentId'))
- features = agent.features
- except Exception as e:
- features = list()
- if 'vCardNeedBind' in features:
- virtual_card = card.bound_virtual_card
- else:
- virtual_card = card.related_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:
- 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'使用绑定的虚拟卡')
- 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)
- # 记录当前服务的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,
- 'consumeRcdId': str(consumeRcd.id)
- })
- self.consume_money_for_card(card, money = RMB(0.0))
- 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:
- logger.debug('virtual card is not do device refund.')
- return
- dev = Device.objects.get(devNo = self.device['devNo'])
- dealer = self.device.owner
- if not dealer:
- logger.error('dealer is not found, dealerId=%s' % self.device.ownerId)
- return
- agent = Agent.objects(id = dealer.agentId).first()
- if not agent:
- logger.error('agent is not found, agentId=%s' % dealer.agentId)
- return
- res = SWIPE_CARD_RES.SUCCESS_00
- device_refund = False
- billingType = dev.otherConf.get('billingType', 'time')
- if is_server_refund(billingType, self.device, dealer, agent):
- logger.debug('{} in {} has card refund by server refund.'.format(repr(card), repr(self.device)))
- return
- logger.debug('{} card refund by {}.'.format(repr(card), repr(self.device)))
- 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')
- })
- 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'])
- dealer = Dealer.objects(id = group['ownerId']).first()
- if not dealer:
- logger.error('dealer is not found, dealerId=%s' % group['ownerId'])
- return
- agent = Agent.objects(id = dealer.agentId).first()
- if not agent:
- logger.error('agent is not found, agentId=%s' % dealer.agentId)
- return
- if not lineInfo.has_key('coins'):
- logger.debug('port cache has no coins. no order in port {}'.format(lineInfo.get('port')))
- return
- if 'duration' in self.event_data and self.event_data['duration'] > 0:
- usedTime = self.event_data['duration']
- else:
- if (not lineInfo) or (not lineInfo.has_key('startTime')):
- 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 = VirtualCoin(lineInfo['coins'])
- backCoins = VirtualCoin(0.0)
- price = RMB(lineInfo.get('price', 0.0))
- refundRMB = RMB('0.0')
- leftTime = self.event_data['leftTime']
- billingType = lineInfo.get('billingType', 'time')
- consumeType = lineInfo.get('consumeType', '')
- refundProtectionTime = lineInfo.get('refundProtectionTime', 5)
- isTempPackage = lineInfo.get('isTempPackage', False)
- needTime = 0
- leftTimeStr = ''
- try:
- #: 刷卡或者万一缓存重启了,出现needElec为空的,作为1000度电吧,就会一定使用设备上报的电量
- if lineInfo.get('elec', 0.0) < lineInfo.get('needElec', 0.0):
- spendElec = round(lineInfo['needElec'] - lineInfo['elec'], 2)
- backCoins_by_elec = round(self.event_data.get('elec',0) / lineInfo['needElec'] * float(money), 2)
- else:
- spendElec = 0.0
- backCoins_by_elec = money
- if leftTime == 65535:
- actualNeedTime = 0
- backCoins = money
- refundRMB = price
- usedTime = 0
- spendElec = 0.0
- else:
- actualNeedTime = usedTime + leftTime
- leftTimeStr = leftTime
- if 'alt_tech_refund_mode' in agent.features and billingType == 'time':
- needTime = lineInfo['needTime']
- # 剩余时间不满 60 按照 0 算, 不满 120 按照 60 算...
- calcleftTime = (int(leftTime) // 60) * 60
- backCoins = money * (float(calcleftTime) / float(actualNeedTime))
- else:
- # TODO 整改退费 哪个时间电量取小的
- needTime = lineInfo['needTime']
- backCoins = money * (float(leftTime) / float(actualNeedTime))
- # elif 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 = VirtualCoin(money.amount - money.amount * ratio)
- backCoins = VirtualCoin(min(float(backCoins), float(backCoins_by_elec)))
- isRefundProtection = False
- if usedTime < refundProtectionTime:
- backCoins = money
- isRefundProtection = True
- if backCoins > money:
- backCoins = money
- refundRMB = price * (float(backCoins) / float(money))
- logger.debug(
- 'refund money is: {}; refund rmb is: {}'.format(str(backCoins.amount), str(refundRMB.amount)))
- #: 扫码的方式
- if cardId == '' and vCardId is None and consumeType != 'coin':
- logger.info('finished with netPay')
- #: 这里需要考虑API调用的和普通使用场景
- if 'extOrderNo' in lineInfo:
- record = APIStartDeviceRecord.get_api_record(self.device['logicalCode'], lineInfo['extOrderNo'])
- if not record:
- logger.debug('cannot find api start device record')
- return
- if record.postActionTriggered:
- logger.debug('api({}) post action has done.'.format(lineInfo['extOrderNo']))
- return
- # 中天的结束状态匹配
- reasonCode = self.event_data['reasonCode']
- if reasonCode == '0B':
- reasonCode = '03'
- elif reasonCode == '03':
- reasonCode = '04'
- else:
- pass
- # 中天空载需要这样写
- if leftTime == 65535:
- leftTime = lineInfo['needTime']
- report_zhongtian_service_complete(
- event_code = '16',
- record = record,
- orderNo = lineInfo['extOrderNo'],
- deviceCode = self.device['logicalCode'],
- groupName = group['groupName'],
- address = group['address'],
- actualNeedTime = lineInfo['needTime'],
- leftTime = leftTime,
- finishedState = reasonCode
- )
- record.update(servicedInfo = {'spendElec': str(spendElec), 'backCoins': '0'})
- if self.device.is_auto_refund:
- coins = VirtualCoin(lineInfo['coins'])
- money = RMB(lineInfo['price'])
- backCoins = self.get_backCoins(coins = coins, leftTime = leftTime,
- actualNeedTime = lineInfo['needTime'])
- backMoney = self.get_backMoney(money = money, leftTime = leftTime,
- actualNeedTime = lineInfo['needTime'])
- report_zhongtian_refund(
- eventCode = '16',
- record = record,
- orderNo = lineInfo['extOrderNo'],
- deviceCode = self.device['logicalCode'],
- groupName = group['groupName'],
- address = group['address'],
- backMoney = str(backMoney),
- backCoins = str(backCoins),
- actualNeedTime = lineInfo['needTime'],
- leftTime = leftTime,
- finishedState = reasonCode
- )
- record.update(servicedInfo = {'spendElec': str(spendElec), 'backCoins': str(backCoins)})
- else:
- openId = lineInfo['openId']
- user = MyUser.objects(openId = openId, groupId = self.device['groupId']).first()
- leftTimeStr = leftTime if leftTime != 65535 else u'空载'
- # todo 生成模板所需要的所有参数, 后续有客户自定义的话, 直接在这个字典里面添加, 不需要删掉之前的.
- # todo 这个变量仅仅用于下面generate_service_complete_title_by_devType()函数的参. 做成配置项更好, 下次不用改代码.
- templateMap = {
- 'reason': self.event_data['reason'],
- 'logicalCode': self.device['logicalCode'],
- 'port': self.event_data['port'],
- 'address': group['address'],
- 'actualNeedTime': actualNeedTime,
- 'leftTimeStr': leftTimeStr
- }
- # 先去获取devType上面的模板, 如果没有就走正常的流程
- title = self.generate_service_complete_title_by_devType(self.device['devType']['id'], templateMap)
- if title == '':
- billingType = lineInfo.get('billingType', 'time')
- if billingType == 'time':
- title = u'\\n\\n结束原因:\\t\\t{reason}\\n\\n设备编号:\\t\\t{logicalCode}-{port}\\n\\n设备地址:\\t\\t{address}\\n\\n消费时间:\\t\\t动态功率计算{actualNeedTime}分钟\\n\\n剩余时间:\\t\\t{leftTimeStr}分钟'.format(
- reason = self.event_data['reason'],
- logicalCode = self.device['logicalCode'],
- port = self.event_data['port'],
- address = group['address'],
- actualNeedTime = actualNeedTime,
- leftTimeStr = leftTimeStr
- )
- else:
- title = u'\\n\\n结束原因:\\t\\t{reason}\\n\\n设备编号:\\t\\t{logicalCode}-{port}\\n\\n设备地址:\\t\\t{address}\\n\\n购买电量:\\t\\t{needElec}\\n\\n消耗电量:\\t\\t{spendElec}'.format(
- reason = self.event_data['reason'],
- logicalCode = self.device['logicalCode'],
- port = self.event_data['port'],
- address = group['address'],
- needElec = lineInfo.get('needElec', 1000),
- spendElec = spendElec)
- self.notify_user(
- managerialOpenId = user.managerialOpenId if user else '',
- templateName = 'service_complete',
- title = title,
- service = u'充电服务',
- finishTime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- remark = u'谢谢您的支持')
- consumeDict = {
- 'chargeIndex': lineInfo['port'],
- 'reason': lineInfo['reason'],
- 'actualNeedTime': u'动态功率计算为%s分钟' % actualNeedTime,
- 'duration': usedTime
- }
- if billingType == 'time':
- leftTimeStr = leftTime if leftTime != 65535 else lineInfo['needTime']
- consumeDict.update(
- {'leftTime': leftTimeStr, 'needTime': u'扫码订购%s分钟' % lineInfo['needTime']})
- consumeDict.update({'elec': spendElec})
- else:
- consumeDict.update({'needElec': lineInfo['needElec']})
- consumeDict.update({'elec': spendElec})
- consumeDict.update({'elecFee': self.calc_elec_fee(spendElec)})
- need_refund = False
- if not group.get('isFree', False):
- if isTempPackage is True:
- if isRefundProtection is True:
- need_refund = True
- else:
- pass
- elif self.device.is_auto_refund:
- need_refund = True
- elif isRefundProtection is True:
- need_refund = True
- else:
- pass
- if self.event_data['elec'] == 0 or self.event_data['leftTime'] == 0:
- need_refund = False
- else:
- pass
- if not need_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:
- if isTempPackage:
- self.refund_net_pay(user, lineInfo, refundRMB, VirtualCoin(0), consumeDict, True)
- else:
- self.refund_net_pay(user, lineInfo, refundRMB, backCoins, consumeDict,
- ('refundRMB_device_event' in dealer.features))
- ServiceProgress.update_progress_and_consume_rcd(
- self.device['ownerId'],
- {
- 'open_id': openId, 'device_imei': self.device['devNo'],
- 'port': lineInfo['port'], 'isFinished': False
- },
- consumeDict)
- if DEALER_CONSUMPTION_AGG_KIND.REFUNDED_COINS in consumeDict:
- self.notify_user(user.managerialOpenId if user else '', 'refund_coins', **{
- 'title': u'充电已经完成',
- 'backCount': u'%s(金币)' % str(consumeDict[DEALER_CONSUMPTION_AGG_KIND.REFUNDED_COINS]),
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
- })
- elif DEALER_CONSUMPTION_AGG_KIND.REFUNDED_CASH in consumeDict:
- self.notify_user(user.managerialOpenId if user else '', 'refund_coins', **{
- 'title': u'充电已经完成',
- 'backCount': u'%s(元)' % str(consumeDict[DEALER_CONSUMPTION_AGG_KIND.REFUNDED_CASH]),
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
- })
- elif vCardId is not None:
- # 使用的是虚拟卡
- logger.info('finished with vCard!')
- billingType = lineInfo.get('billingType', 'time')
- if billingType == 'time':
- leftTimeStr = leftTime if leftTime != 65535 else lineInfo['needTime']
- title = u'\\n\\n结束原因:\\t\\t{reason}\\n\\n设备编号:\\t\\t{logicalCode}-{port}\\n\\n设备地址:\\t\\t{address}\\n\\n消费时间:\\t\\t动态功率计算{actualNeedTime}分钟\\n\\n剩余时间:\\t\\t{leftTimeStr}分钟'.format(
- reason = self.event_data['reason'],
- logicalCode = self.device['logicalCode'],
- port = self.event_data['port'],
- address = group['address'],
- actualNeedTime = actualNeedTime,
- leftTimeStr = leftTimeStr
- )
- else:
- title = u'\\n\\n结束原因:\\t\\t{reason}\\n\\n设备编号:\\t\\t{logicalCode}-{port}\\n\\n设备地址:\\t\\t{address}\\n\\n购买电量:\\t\\t{needElec}\\n\\n消耗电量:\\t\\t{spendElec}'.format(
- reason = self.event_data['reason'],
- logicalCode = self.device['logicalCode'],
- port = self.event_data['port'],
- address = group['address'],
- needElec = lineInfo.get('needElec', 1000),
- spendElec = spendElec
- )
- # 通知充电完成
- try:
- vCard = UserVirtualCard.objects.get(id = vCardId)
- except DoesNotExist:
- logger.info('can not find the vCard id = %s' % vCardId)
- return
- self.notify_user(
- managerialOpenId = self.get_managerialOpenId_by_openId(lineInfo['openId']),
- templateName = 'service_complete',
- title = title,
- service = u'充电服务',
- finishTime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- remark = u'谢谢您的支持'
- )
- consumeDict = {'chargeIndex': lineInfo['port'],
- 'reason': lineInfo['reason'],
- 'actualNeedTime': u'动态功率计算为%s分钟' % actualNeedTime,
- 'duration': usedTime}
- consumeDict.update({'elec': spendElec})
- if billingType != 'time':
- consumeDict.update({'elec': spendElec})
- consumeDict.update({'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)
- else:
- vCard.refund_quota(vCardConsumeRcd, usedTime, spendElec, backCoins.mongo_amount)
- elif cardId != '':
- # 刷的实体卡
- logger.info('finished with card')
- card = Card.objects.get(id = cardId)
- virtual_card = card.bound_virtual_card # type: UserVirtualCard
- if billingType == 'time':
- logger.info('billingType is time.')
- self.notify_user(
- managerialOpenId = card.managerialOpenId,
- templateName = 'service_complete',
- title = u'\\n\\n结束原因:\\t\\t{reason}\\n\\n设备编号:\\t\\t{logicalCode}-{port}\\n\\n设备地址:\\t\\t{address}\\n\\n消费卡号:\\t\\t{cardNo}\\n\\n持卡姓名:\\t\\t{cardName}\\n\\n消费时间:\\t\\t动态功率计算{actualNeedTime}分钟\\n\\n剩余时间:\\t\\t{leftTimeStr}分钟'.format(
- reason = self.event_data['reason'],
- logicalCode = self.device['logicalCode'],
- port = self.event_data['port'],
- address = group['address'],
- cardNo = card.cardNo,
- cardName = card.cardName,
- actualNeedTime = actualNeedTime,
- leftTimeStr = leftTimeStr
- ),
- service = u'充电服务',
- finishTime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- remark = u'谢谢您的支持')
- consumeDict = {
- 'chargeIndex': lineInfo['port'],
- 'leftTime': leftTimeStr,
- 'needTime': u'刷卡订购%s分钟' % needTime if virtual_card is None else u'绑定虚拟卡订购%s分钟' % needTime,
- 'reason': lineInfo['reason'],
- 'duration': usedTime,
- 'actualNeedTime': u'动态功率计算为%s分钟' % actualNeedTime,
- 'elec': spendElec,
- 'elecFee': self.calc_elec_fee(spendElec)
- }
- if virtual_card:
- self.refund_virtual_card(backCoins, cardId, consumeDict, lineInfo, spendElec, usedTime,
- virtual_card)
- elif is_server_refund(billingType, self.device, dealer, agent):
- logger.info(
- 'ready to server refund money <{}> for user card <{}> in device<{}>'.format(
- backCoins,
- str(card.id),
- self.device.devNo))
- consumeDict.update({DEALER_CONSUMPTION_AGG_KIND.REFUND_CARD: backCoins.mongo_amount})
- ServiceProgress.update_progress_and_consume_rcd(
- self.device['ownerId'],
- {
- 'cardId': cardId,
- 'device_imei': self.device['devNo'],
- 'port': lineInfo['port'],
- 'isFinished': False
- },
- consumeDict)
- self.refund_money_for_card(backCoins, str(card.id))
- desc = u'您使用的%s号端口充电,共付款:%s元,充电预定时间为:%s分钟,使用:%s分钟,给您退款:%s元' % (
- lineInfo['port'], money, actualNeedTime, 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')})
- else:
- ServiceProgress.update_progress_and_consume_rcd(
- self.device['ownerId'],
- {
- 'cardId': cardId,
- 'device_imei': self.device['devNo'],
- 'port': lineInfo['port'],
- 'isFinished': False
- },
- consumeDict)
- else:
- logger.info('billingType is elec')
- self.notify_user(
- managerialOpenId = card.managerialOpenId,
- templateName = 'service_complete',
- title = u'\\n\\n结束原因:\\t\\t{reason}\\n\\n设备编号:\\t\\t{logicalCode}-{port}\\n\\n设备地址:\\t\\t{address}\\n\\n消费卡号:\\t\\t{cardNo}\\n\\n持卡姓名:\\t\\t{cardName}\\n\\n购买电量:\\t\\t{needElec}\\n\\n消耗电量:\\t\\t{spendElec}'.format(
- reason = self.event_data['reason'],
- logicalCode = self.device['logicalCode'],
- port = self.event_data['port'],
- address = group['address'],
- cardNo = card.cardNo,
- cardName = card.cardName,
- needElec = lineInfo.get('needElec'),
- spendElec = spendElec
- ),
- service = u'充电服务',
- finishTime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- remark = u'谢谢您的支持')
- consumeDict = {
- 'chargeIndex': lineInfo['port'],
- 'leftTime': leftTimeStr,
- 'reason': lineInfo['reason'],
- 'elec': spendElec,
- 'elecFee': self.calc_elec_fee(spendElec),
- 'duration': usedTime,
- 'needElec': lineInfo['needElec']
- }
- if virtual_card:
- self.refund_virtual_card(backCoins, cardId, consumeDict, lineInfo, spendElec, usedTime,
- virtual_card)
- elif is_server_refund(billingType, self.device, dealer, agent):
- logger.info(
- 'ready to server refund money <{}> for user card <{}> in device<{}>'.format(
- backCoins,
- str(card.id),
- self.device.devNo))
- self.refund_money_for_card(backCoins, str(card.id))
- consumeDict.update({DEALER_CONSUMPTION_AGG_KIND.REFUND_CARD: backCoins.mongo_amount})
- 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')
- })
- else:
- logger.info('device not open refund switch')
- ServiceProgress.update_progress_and_consume_rcd(
- self.device['ownerId'],
- {'cardId': cardId, 'device_imei': self.device['devNo'],
- 'port': lineInfo['port'], 'isFinished': False}, consumeDict
- )
- elif consumeType == 'coin': #: 消费类型为金币,则
- logger.info('finished with 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 = {'duration': usedTime}
- 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': str(refundRMB.mongo_amount), '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']
- if consumeType == 'coin':
- self.event_data.update({'startTime': datetime.datetime.now().strftime(Const.DATETIME_FMT)})
- # 记录该端口累计需要的时间和钱,cardId
- Device.update_port_control_cache(self.device['devNo'], self.event_data)
- 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)
- 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, 'consumeOrder': 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')
- # 刷卡虚拟卡启动的时候,将consumeRcd 写入到缓存 退费的时候使用
- consumeRcdId = rcd.get('consumeOrder', dict()).get('consumeRcdId')
- if consumeRcdId:
- self.event_data.update({'consumeRcdId': consumeRcdId})
- 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)
- # todo 功率过低告警还没做完
- # openId = self.curDevInfo['openId']
- # if openId is not None:
- # user = MyUser.objects(openId=openId, groupId = self.device['groupId']).first()
- #
- # report_to_user_low_power_wechat.delay(self.notify_low_power_to_user(user, 1, 20), 15)
- elif cmdCode == '2D':
- self._do_charge_consume()
- elif cmdCode == '2C':
- self._do_coin_finished()
- else:
- raise NoCommandHandlerAvailable(
- '[JNDZ]] no command handler for cmd %s, curDevInfo=%s' % (cmdCode, self.event_data))
- def _do_charge_consume(self):
- if self.event_data.get("result", '00') == '00':
- logger.info("receive failure card charge data <{}>".format(self.event_data.get("sourceData", '')))
- return
- # 回复主板是正常的2D指令
- sessionId = self.event_data.get("sessionId")
- self.deviceAdapter._response_to_2D("{:0>10}".format(sessionId))
- # 判断是否这个 sessionId 是否已经被执行 判断方式是该端口中是否有这个 sessionId
- portStr = self.event_data.get("portStr")
- if not portStr:
- logger.info("receive card charge data <{}> without port !".format(self.event_data.get("sourceData", '')))
- return
- portCache = Device.get_dev_control_cache(self.device.devNo).get(portStr, dict())
- if portCache.get("status", Const.DEV_WORK_STATUS_WORKING) == Const.DEV_WORK_STATUS_WORKING and portCache.get(
- "sessionId") == sessionId:
- logger.info(
- "receive card charge data <{}> has been handle, <{}>!".format(self.event_data.get("sourceData", ''),
- sessionId))
- return
- # 接下来判断上传成功启动的类别 由硬币/卡类型决定
- chargeType = self.event_data.get("chargeType")
- if chargeType == "00":
- self._charge_with_coin()
- elif chargeType == "01":
- self._charge_with_card()
- elif chargeType == "02":
- self._charge_with_remote()
- else:
- logger.info("card recharge type <{}> undefined! <{}>".format(chargeType, self.event_data.get("sourceData")))
- def refund_virtual_card(self, backCoins, cardId, consumeDict, lineInfo, spendElec, usedTime, virtual_card):
- logger.debug('server refund for virtual card<{}> in device<{}>'.format(
- str(virtual_card.id),
- self.device.devNo))
- ServiceProgress.update_progress_and_consume_rcd(
- self.device['ownerId'],
- {
- 'cardId': cardId,
- 'device_imei': self.device['devNo'],
- 'port': lineInfo['port'],
- 'isFinished': False
- },
- consumeDict)
- consumeRcdId = lineInfo.get('consumeRcdId', None)
- # 不是虚拟卡启动的直接结束掉
- if consumeRcdId:
- # 尝试进行虚拟卡退费
- try:
- vCardConsumeRcd = VCardConsumeRecord.objects.get(id = consumeRcdId)
- except DoesNotExist, e:
- logger.info('can not find the consume rcd id = %s' % consumeRcdId)
- else:
- virtual_card.refund_quota(vCardConsumeRcd, usedTime, spendElec,
- backCoins.mongo_amount)
- else:
- logger.info('can not find consume rcd id')
- def response_use_card(self, res, leftBalance):
- # 启动失败需要把金币还回去
- try:
- self.deviceAdapter.response_use_card(res, leftBalance)
- except ServiceException as e:
- logger.exception(e)
- def do_id_response_support_reliable(self, **args):
- # TODO 预扣请求和余额回收,此处进行验证,通过则下发可以开启设备
- cardNo = self.event_data['cardNo']
- cardHex = self.event_data['sourceData'][8:16]
- fee = self.event_data['preFee']
- oper = self.event_data['oper']
- logger.info('Check card can be used cardNo={} ,cardHex={} fee={} oper={}'.format(cardNo, cardHex, fee, oper))
- # 进来的时候检查过卡是否存在这里校验卡的合法型
- card = self.update_card_dealer_and_type(cardNo)
- if not card or not card.openId or card.frozen:
- self.deviceAdapter.response_card(2, 0, fee, oper, cardHex)
- return
- # 2.检查卡片充值订单是否存在
- 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('JingNengDianZi cmdNo(10) - cardNo=%s, openId=%s, result=%s, preFee=%s, curinfo=%s' % (
- cardNo, card.openId, result, fee, self.event_data))
- virtual_card = self._get_virtual_card_by_card(card)
- # 3.检查当前操作为是否为扣费还是余额回收(00:扣费,01:充值)
- if oper == SWIPE_CARD_PARAM_OP.DECR_00:
- # 先检查虚拟卡是否能使用
- leftCount = self._check_virtual_card_can_use_today(virtual_card, fee)
- if leftCount:
- return self.deviceAdapter.response_card(0, leftCount, fee, oper, cardHex, isVir=True , virtual_card_id=str(virtual_card.id))
- # 校验实体卡能否使用
- elif self._check_card_balance_can_use_today(card, fee):
- return self.deviceAdapter.response_card(0, card.balance, fee, oper, cardHex)
- else:
- return self.deviceAdapter.response_card(1, card.balance, fee, oper, cardHex)
- elif oper == SWIPE_CARD_PARAM_OP.INCR_01:
- if virtual_card:
- logger.debug('virtual card is not do device refund...')
- return
- dev = Device.objects.get(devNo=self.device['devNo'])
- dealer = self.device.owner
- if not dealer:
- logger.error('dealer is not found, dealerId=%s' % self.device.ownerId)
- return
- agent = Agent.objects(id=dealer.agentId).first()
- if not agent:
- logger.error('agent is not found, agentId=%s' % dealer.agentId)
- return
- res = SWIPE_CARD_RES.SUCCESS_00
- billingType = dev.otherConf.get('billingType', 'time')
- if is_server_refund(billingType, self.device, dealer, agent):
- logger.debug('{} in {} has card refund by server refund.'.format(repr(card), repr(self.device)))
- return
- logger.debug('{} card refund by {}.'.format(repr(card), repr(self.device)))
- self.response_use_card(res, card.balance.mongo_amount + fee)
- self.refund_money_for_card(fee, str(card.id))
- self.notify_user(card.managerialOpenId, 'refund_coins', **{
- 'title': u'退币完成!!!您的卡号是%s,卡别名:%s' % (card.cardNo, card.nickName),
- 'backCount': u'金币:%s' % fee,
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
- })
- def _get_virtual_card_by_card(self, card):
- if not card.openId or float(card.balance) != 0:
- return
- try:
- dealer = self.device.owner
- agent = Agent.objects.get(id=dealer.agentId)
- features = agent.features
- except Exception as e:
- features = []
- return card.bound_virtual_card if 'vCardNeedBind' in features else card.related_virtual_card
- def _check_virtual_card_can_use_today(self, virtual_card, fee):
- # 如果虚拟卡已经绑定,需要检查下今天是否可用,如果可用,有限使用虚拟卡
- if virtual_card:
- unit = self.device['washConfig'].get('1', {}).get('unit','分钟')
- if unit == '分钟':
- cardMin = self.device['otherConf'].get('cardMin', 180)
- package = {'coins': float(fee), 'unit': unit, 'time': int(cardMin)}
- elif unit == '度':
- cardMin = self.device['otherConf'].get('cardMin', 180)
- package = {'coins': float(fee), 'unit': unit, 'time': int(cardMin)}
- else:
- return 0
- if virtual_card.can_use_today(package):
- dayKey = datetime.datetime.now().strftime('%Y-%m-%d')
- leftDayQuota = virtual_card.calc_left_day_quota(dayKey)
- left_count = virtual_card.find_match_unit_and_can_use_count(leftDayQuota, package)
- return left_count
- def _check_card_balance_can_use_today(self, card, fee):
- if float(card.balance) >= fee:
- return True
- else:
- return False
- def _charge_with_card(self):
- """
- 充值卡 的充值
- :return:
- """
- cardType = self.event_data.get("cardType")
- if cardType == CARD_TYPE.OFFLINE_CARD:
- self._charge_with_offline_card()
- elif cardType == CARD_TYPE.ONLINE_CARD:
- self._charge_with_online_card()
- elif cardType == CARD_TYPE.MONTHLY_CARD:
- self._charge_with_monthly_card()
- elif cardType == CARD_TYPE.FULL_CARD:
- self._charge_with_full_card()
- else:
- logger.info(
- "card recharge card type <{}> undefined! <{}>".format(cardType, self.event_data.get("sourceData")))
- def _charge_with_coin(self):
- """
- 投币的上报
- :return:
- """
- port = self.event_data.get('portStr')
- ctrInfo = Device.get_dev_control_cache(self.device.devNo)
- lineInfo = ctrInfo.get(port, {})
- if lineInfo.get('status', 0) == Const.DEV_WORK_STATUS_WORKING and lineInfo.get('consumeType') == 'coin': #续充
- lineInfo['coins'] += self.event_data.get('coins', 0)
- lineInfo['needTime'] += self.event_data.get('time', 0)
- lineInfo['needElec'] += self.event_data.get('elec', 0)
- if 'sub_orderNo' in lineInfo:
- lineInfo['sub_orderNo'].append( self.record_consume_for_coin(RMB(self.event_data['coins'])))
- else:
- lineInfo['sub_orderNo'] = [self.record_consume_for_coin(RMB(self.event_data['coins'])),]
- else:
- lineInfo = {
- 'startTime': datetime.datetime.now().strftime(Const.DATETIME_FMT),
- 'port': port,
- 'coins': self.event_data.get('coins', 0),
- 'needTime': self.event_data.get('time', 0),
- 'needElec': self.event_data.get('elec', 0),
- 'consumeOrderNo': self.record_consume_for_coin(RMB(self.event_data['coins'])),
- 'consumeType': 'coin',
- 'isStart': True,
- 'status': Const.DEV_WORK_STATUS_WORKING,
- 'sessionId': self.event_data.get('sessionId'),
- }
- # 记录该端口累计需要的时间和钱,cardId
- Device.update_port_control_cache(self.device['devNo'], lineInfo)
- Accounting.recordOfflineCoin(self.device,
- int(time.time()),
- int(self.event_data.get('coins', 0)))
- def _charge_with_remote(self):
- logger.info("not supper charge type! {}".format(self.event_data))
- def _charge_with_online_card(self):
- """
- 在线卡启动充值
- :return:
- """
- portStr = self.event_data.get("portStr")
- needElec = self.event_data.get("elec", 0)
- cardNo = self.event_data.get("cardNo")
- cardCst = self.event_data.get("cardCst")
- card = self.update_card_dealer_and_type(cardNo)
- if not card or not card.openId or card.frozen:
- logger.warning("error card, cardNo is {}".format(cardNo))
- return
- res, cardBalance = self.consume_money_for_card(card, RMB(cardCst))
- if res != 1:
- logger.warning("consume error!!!, cardNo is {}".format(cardNo))
- return
- consumeDict = {
- "chargeIndex": portStr,
- "needElec": needElec
- }
- orderNo, cardOrderNo = self.record_consume_for_card(card, RMB(cardCst), servicedInfo=consumeDict)
- portCache = {
- "isStart": True,
- "status": Const.DEV_WORK_STATUS_WORKING,
- "openId": card.openId,
- "price": cardCst,
- "coins": cardCst,
- "needElec": needElec,
- "startTime": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
- "startTimeStamp": int(time.time()),
- "consumeType": "card",
- }
- Device.update_dev_control_cache(self.device.devNo, {portStr: portCache})
- ServiceProgress.register_card_service(
- self.device,
- int(portStr),
- card,
- consumeOrder={
- "orderNo": orderNo,
- "cardOrderNo": cardOrderNo,
- }
- )
- def _charge_with_offline_card(self):
- """
- 离线卡启动充值
- :return:
- """
- pass
- def _charge_with_monthly_card(self):
- """
- 包月在线卡启动
- :return:
- """
- logger.info("not supper card charge type! {}".format(self.event_data))
- def _charge_with_full_card(self):
- """
- 充满自停卡
- :return:
- """
- logger.info("not supper card charge type! {}".format(self.event_data))
- def _do_coin_finished(self):
- port = str(self.event_data.get('port'))
- ctrInfo = Device.get_dev_control_cache(self.device.devNo)
- lineInfo = ctrInfo.get(port, {})
- now = datetime.datetime.now()
- if lineInfo and lineInfo.get('consumeType') == 'coin': # 只处理投币结束
- if 'consumeOrderNo' in lineInfo:
- order = ConsumeRecord.objects.filter(orderNo=lineInfo['consumeOrderNo']).first()
- if 'duration' in self.event_data and self.event_data['duration'] > 0:
- usedTime = self.event_data['duration']
- else:
- 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)))
- actualNeedTime = usedTime + self.event_data.get('leftTime', 0)
- consumeDict = {
- 'chargeIndex': port,
- 'reason': self.event_data.get('reasonDesc', ''),
- 'totalCount': lineInfo.get('coins', 0),
- 'needTime': lineInfo.get('needTime', 0),
- 'leftTime': self.event_data.get('leftTime', 0),
- 'leftElec': self.event_data.get('leftElec', 0),
- 'actualNeedTime': actualNeedTime,
- }
- order.update_service_info(consumeDict)
- ConsumeRecord.objects.filter(orderNo=lineInfo['consumeOrderNo']).update(status='finished',
- finishedTime=now)
- if 'sub_orderNo' in lineInfo:
- subConsumeDict = {
- 'desc': '关联主单号:{}'.format(order.orderNo)
- }
- ConsumeRecord.objects.filter(orderNo__in=lineInfo['sub_orderNo']).update(status='finished', finishedTime=now,
- servicedInfo=subConsumeDict)
- Device.clear_port_control_cache(self.device.devNo, port)
- class ChargingJNDZReportEvent(WorkEvent):
- def do(self, **args):
- # if not self.device.get('otherConf', {}).get('need_save_upload_data', None):
- # logger.info('No need to record!!!')
- # return
- portNum = self.event_data.get('portNum')
- portInfo = self.event_data.get('portInfo')
- ctrInfo = Device.get_dev_control_cache(self.device.devNo)
- now = datetime.datetime.now()
- for port, one_info in portInfo.items():
- if one_info.get('portStatus') == '02':
- lineInfo = ctrInfo.get(port, {})
- orderNo = lineInfo.get('orderNo')
- if not orderNo:
- continue
- try:
- order = ConsumeRecord.objects.filter(orderNo=orderNo).first()
- if hasattr(order, 'upload_data'):
- upload_data = order.upload_data
- else:
- upload_data = []
- one_info['upload_time'] = now.strftime('%Y-%m-%d %H:%M:%S')
- if not upload_data:
- one_info['duration'] = round((now - order.startTime).total_seconds() / 60.0, 1)
- one_info['total_time'] = one_info['duration']
- else:
- one_info['duration'] = round((now - to_datetime(upload_data[-1]['upload_time'])).total_seconds() / 60.0, 1)
- one_info['total_time'] = round((now - order.startTime).total_seconds() / 60.0, 1)
- upload_data.append(one_info)
- order.upload_data = upload_data
- order.save()
- except Exception as e:
- logger.error(e)
- pass
- class StartAckEventPreProcessor(AckEventProcessorIntf):
- def analysis_reason(self, reason):
- FINISHED_CHARGE_REASON_MAP = {
- '00': u'为了防止过度充电,您的充电已超过最大设定充电时长。',
- '01': u'充电满了或者用户手动停止(拔插头,或是按了停止按钮)',
- '02': u'充电满了,自动停止',
- '03': u'超功率自停',
- '04': u'远程断电',
- '05': u'刷卡断电',
- '0B': u'设备或是端口出现问题,被迫停止',
- # 服务器定义的停止事件
- '90': u'用户手动点击结束按钮结束充电',
- '91': u'检测到设备未在充电工作状态,结束本次充电',
- -2: u'检测到设备未在充电工作状态,结束本次充电',
- }
- return FINISHED_CHARGE_REASON_MAP.get(reason)
- def pre_processing(self, device, event_data):
- # type:(DeviceDict, dict)->dict
- source = json.dumps(event_data)
- event_data['source'] = source
- if 'duration' in event_data and event_data['duration'] != 0:
- duration = event_data.get('duration')
- event_data['duration'] = ((duration + 59) / 60)
- elif 'fts' in event_data and 'sts' in event_data:
- duration = event_data['fts'] - event_data['sts']
- event_data['duration'] = ((duration + 59) / 60)
- else:
- event_data['duration'] = 0
- if 'elec' in event_data:
- event_data['elec'] = round(event_data.pop('elec') / 3600000.0, 3)
- else:
- event_data['elec'] = 0
-
- # 初始化分档时间
- if 'time' in event_data:
- event_data['time'] = event_data['time'] / 60.0
- else:
- event_data['time'] = 0.0
- if 'timeMax' in event_data:
- event_data['needTime'] = event_data.pop('timeMax') / 60.0
- if 'elecMax' in event_data:
- event_data['needElec'] = round(event_data.pop('elecMax') / 3600000.0, 3)
- if 'port' in event_data:
- pass
- if 'sub' in event_data:
- subs = event_data.get('sub', [])
- for item in subs:
- if 'card_cst' in item:
- item['fee'] = RMB(item['card_cst']) * Ratio('0.1')
- # event_data['fee'] += item['fee']
- if 'balance' in item:
- item['balance'] = RMB(item['balance']) * Ratio('0.1')
- if 'timeMax' in event_data:
- event_data['needTime'] = event_data.pop('timeMax')
- if 'elecMax' in event_data:
- event_data['needElec'] = event_data.pop('elecMax')
- if event_data['order_type'] != 'com_start':
- package = {'coins': float(event_data['fee']), 'unit': 'time', 'time': 999}
- event_data['package'] = package
- if event_data['status'] == 'finished':
- if 'reason' in event_data: # 正常结束
- event_data['reasonDesc'] = self.analysis_reason(event_data['reason'])
- else:
- event_data['reasonDesc'] = self.analysis_reason('91') # 由轮询订单出来的结果
- if 'time' in event_data and 'needTime' in event_data:
- if event_data['time'] >= event_data['needTime']:
- event_data['time'] = event_data['needTime']
- event_data['reasonDesc'] = '购买的充电时间用完,功率超过额定值时间会相应缩短。'
- if 'elec' in event_data and 'needElec' in event_data:
- if event_data['elec'] >= event_data['needElec']:
- event_data['elec'] = event_data['needElec']
- event_data['reasonDesc'] = '根据您的动态功率计算, 您订购的电量已用完, 当前充电服务已结束, 谢谢您的使用!!'
- if 'cardType' in event_data:
- pass
- if 'cardNo' in event_data:
- event_data['cardNoHex'] = str(event_data.pop('cardNo'))
- event_data['cardNo'] = str(int(event_data['cardNoHex'], 16))
- event_data['cardType'] = 'ID'
- if 'balance' in event_data:
- if event_data['order_type'] == 'com_start':
- event_data['fee'] = RMB(event_data.pop('balance')) * Ratio('0.1')
- elif event_data['order_type'] == 'id_start':
- cst = float(device['otherConf'].get("deviceConfigs", {}).get('cst', 30.0)) * 0.1
- event_data['fee'] = RMB(cst)
- event_data['fee'] = min(RMB(cst), RMB(event_data.pop('balance')) * Ratio('0.1'))
- else:
- event_data['fee'] = RMB(0)
- if event_data['needTime'] == 0:
- event_data['timeFee'] = RMB(0)
- else:
- event_data['timeFee'] = event_data['fee'] * round(event_data['time'] / event_data['needTime'], 2)
- if event_data['needElec'] == 0:
- event_data['elecFee'] = RMB(0)
- else:
- event_data['elecFee'] = event_data['fee'] * round(event_data['elec'] / event_data['needElec'], 2)
- # if event_data.get('reason') in ['00']:
- # event_data['timeFee'] = event_data['fee']
- # event_data['elecFee'] = event_data['fee']
- if event_data['order_type'] != 'com_start':
- package = {'coins': float(event_data['fee']), 'unit': 'time', 'time': 999}
- event_data['package'] = package
- return event_data
- class MyComNetPayAckEvent(ComNetPayAckEvent):
- def __init__(self, smartBox, event_data):
- super(MyComNetPayAckEvent, self).__init__(smartBox, event_data, StartAckEventPreProcessor())
- def post_after_start(self, order = None):
- pass
- def post_after_finish(self, order = None):
- # TODO 订单结束处理后付费
- self.pay_order(order)
- def merge_order(self, master_order, sub_orders):
- # type:(ConsumeRecord, list)->dict
- if self.is_postpaid:
- # TODO 显示费用调整 portDict
- start_time = Arrow.fromdatetime(master_order.startTime, tzinfo=settings.TIME_ZONE)
- portDict = {'billingType': 'time'}
- portDict['coins'] = 0
- portDict['needKind'] = 'needTime'
- portDict['needValue'] = 999
- portDict['unit'] = u'分钟'
- portDict['estimatedTs'] = int(start_time.timestamp + 720 * 60 * 60)
- return portDict
- else:
- needTime, needElec= self.deviceAdapter._check_package(master_order.package)
- start_time = Arrow.fromdatetime(master_order.startTime, tzinfo = settings.TIME_ZONE)
- portDict = {
- }
- if master_order.paymentInfo['via'] == 'virtualCard':
- portDict.update({
- 'vCardId': master_order.virtual_card_id
- })
- all_coins = master_order.package['coins']
- all_price = master_order.package['price']
- all_consume_time_value = needTime
- all_consume_elec_value = needElec
- for sub_order in sub_orders:
- all_coins += sub_order.package['coins']
- all_price += sub_order.package['price']
- sub_needTime, sub_needElec = self.deviceAdapter._check_package(sub_order.package)
- all_consume_time_value += sub_needTime
- all_consume_elec_value += sub_needElec
- portDict['coins'] = str(all_coins)
- portDict['price'] = str(all_price)
- portDict['all_consume_time_value'] = str(all_consume_time_value)
- portDict['all_consume_elec_value'] = str(all_consume_elec_value)
- portDict['needKind'] = 'needTime'
- portDict['needValue'] = 999 #显示充满自停
- portDict['unit'] = u'分钟'
- portDict['estimatedTs'] = int(start_time.timestamp + 720 * 60)
- portDict['consumeType'] = 'mobile'
- return portDict
- def do_finished_event(self, master_order, sub_orders, merge_order_info):
- # type: (ConsumeRecord, [ConsumeRecord], dict)->None
- self._do_finished(master_order, sub_orders, merge_order_info)
- # billing_type = merge_order_info['billingType']
- # if billing_type == 'time':
- # if self.is_postpaid:
- # self.do_postpaid_time_finished(master_order, sub_orders, merge_order_info)
- # else:
- # self.do_time_finished(master_order, sub_orders, merge_order_info)
- # else:
- # self.do_elec_finished(master_order, sub_orders, merge_order_info)
- @SmartBox.check_device_features(device_features=['Postpaid'])
- def pay_order(self, order):
- order.status = 'running'
- order.save()
- order.s_to_e()
- @property
- @SmartBox.check_device_features(device_features=['Postpaid'])
- def is_postpaid(self):
- return True
- def do_postpaid_time_finished(self, master_order, sub_orders=None, merge_order_info=None):
- user = MyUser.objects(openId=master_order.openId,
- groupId=master_order.groupId).first() # type: MyUser
- if not user:
- logger.error(
- 'user is not exist. openId = {}, groupId = {}'.format(master_order.openId, master_order.groupId))
- return
- left = self.event_data.get('leftTime', 0)
- duration = self.event_data.get('duration', 0)
- elec = self.event_data.get('elec', 0)
- consumeDict = {
- 'reason': self.event_data.get('reasonDesc'),
- 'leftTime': str(left),
- 'chargeIndex': str(master_order.used_port),
- 'duration': duration,
- 'elec': elec,
- 'elecFee': self.deviceAdapter.calc_elec_fee(elec)
- }
- logger.debug(
- 'orderNo = {}, orderType = isPostpaid, usedTime = {}, needPayMoney = {}'.format(master_order.orderNo,
- duration,
- master_order.coin))
- extra = []
- desc = r'(已使用账户余额自动结算此次消费)' if master_order.is_finished() else r'(您的账户余额已不足以抵扣此次消费,请前往账单中心进行支付)'
- self.event_data['reasonDesc'] += desc
- extra.append({u'消费金额': '{}(金币)'.format(master_order.money)} if master_order.is_finished() else {
- u'消费金额': '{}(元)'.format(master_order.money)})
- master_order.update_service_info(consumeDict)
- auth_bridge = get_wechat_auth_bridge(source=self.device,
- app_type=APP_TYPE.WECHAT_USER_MANAGER)
- self.notify_user_service_complete(
- service_name='充电',
- openid=user.get_bound_pay_openid(auth_bridge.bound_openid_key),
- port=str(master_order.used_port),
- address=master_order.address,
- reason=self.event_data.get('reasonDesc'),
- finished_time=master_order.finishedTime.strftime('%Y-%m-%d %H:%M:%S'),
- extra=extra)
- def insert_vCard_consume_record(self, vCard, order, success, consumeTotal,consumeDay):
- try:
- if success and consumeDay['count'] > 0:
- record = VCardConsumeRecord(
- orderNo=VCardConsumeRecord.make_no(order.logicalCode),
- openId=order.openId,
- nickname=order.nickname,
- cardId=str(vCard.id),
- dealerId=vCard.dealerId,
- devNo=order.devNo,
- devTypeCode = order.devTypeCode,
- devTypeName = order.dev_type_name,
- logicalCode=order.logicalCode,
- groupId=order.groupId,
- address=order.address,
- groupNumber=order.groupNumber,
- groupName=order.groupName,
- attachParas=order.attachParas,
- consumeData=consumeTotal,
- consumeDayData=consumeDay
- )
- record.save()
- except Exception, e:
- logger.exception(e)
- def _do_finished(self, order, sub_orders, merge_order_info):
- # type: (ConsumeRecord, list, dict)->None
- duration, elec = self.event_data.get('duration',0), self.event_data.get('elec',0)
- coins = VirtualCoin(merge_order_info['coins'])
- timeFee = VirtualCoin(self.event_data.get('timeFee', 0.0))
- elecFee = VirtualCoin(self.event_data.get('elecFee', 0.0))
- usedFee = max(timeFee, elecFee)
- auto_refund = self.device.is_auto_refund
- refundProtectionTime = self.device.get('otherConf', {}).get('refundProtectionTime', 5)
- user = MyUser.objects(openId=order.openId,
- groupId=order.groupId).first() # type: MyUser
- backCoins = VirtualCoin(0)
- if duration < refundProtectionTime:
- backCoins = coins
- usedFee = VirtualCoin(0)
- else:
- if auto_refund:
- backCoins = coins - usedFee
- else:
- usedFee = coins
- logger.debug('{} auto refund enable switch is {}, refund protect time = {} backMoney={}'.format(
- repr(self.device), str(auto_refund), refundProtectionTime, backCoins))
- extra = []
- extra.append({u'本次使用时长':u'{}(分钟)'.format(duration)})
- if order.paymentInfo['via'] == 'free':
- extra.append({u'消费金额': u'当前设备免费使用'})
- elif order.paymentInfo['via'] in ['netPay', 'coins', 'cash', 'coin']:
- all_money = RMB(0)
- all_refund_money = RMB(0)
- orders = [order] + sub_orders
- refundCash = 'refundRMB_device_event' in self.device.owner.features
- for _order in orders[::-1]:
- consumeDict = {
- 'reason': self.event_data.get('reasonDesc', None),
- 'chargeIndex': str(order.used_port),
- 'source': self.event_data.get('source', None)
- }
- need_back_coins, need_consume_coins, backCoins = self._calc_refund_info(backCoins, _order.coin)
- rechargeRcdId = _order.attachParas.get('linkedRechargeRecordId', '')
- if rechargeRcdId != '':
- rechargeRcd = RechargeRecord.objects.filter(id=rechargeRcdId, isQuickPay=True).first()
- else:
- rechargeRcd = None
- if refundCash and rechargeRcd: # 退现金特征 + 有充值订单
- # 退现金部分
- user.clear_frozen_balance(str(_order.id), _order.paymentInfo['deduct'],
- back_coins=VirtualCoin(0),
- consume_coins=VirtualCoin(_order.coin))
- refundRMB = rechargeRcd.money * (float(need_back_coins) / float(_order.coin))
- self.refund_net_pay(user, {'rechargeRcdId': rechargeRcdId, 'openId': user.openId},
- refundRMB, VirtualCoin(0), consumeDict, True)
- all_money += RMB(rechargeRcd.money)
- all_refund_money += RMB(refundRMB)
- else:
- user.clear_frozen_balance(str(_order.id), _order.paymentInfo['deduct'], back_coins=need_back_coins,
- consume_coins=need_consume_coins)
- consumeDict.update({
- DEALER_CONSUMPTION_AGG_KIND.COIN: _order.coin.mongo_amount,
- DEALER_CONSUMPTION_AGG_KIND.SPEND_MONEY: need_consume_coins.mongo_amount,
- DEALER_CONSUMPTION_AGG_KIND.REFUNDED_COINS: need_back_coins.mongo_amount})
- if _order.orderNo == order.orderNo:
- consumeDict.update({
- DEALER_CONSUMPTION_AGG_KIND.DURATION: duration,
- DEALER_CONSUMPTION_AGG_KIND.ELEC: elec,
- DEALER_CONSUMPTION_AGG_KIND.ELECFEE: self.deviceAdapter.calc_elec_fee(elec),
- })
- _order.update_service_info(consumeDict)
- if refundCash:
- extra.append({u'消费金额': '{}元'.format(all_money - all_refund_money)})
- if all_refund_money > RMB(0):
- extra.append({u'退款金额': '{}元'.format(all_refund_money)})
- else:
- extra.append({u'消费金额': '{}金币'.format(usedFee)})
- if backCoins > VirtualCoin(0):
- extra.append({u'退款金额': '{}金币(当充电金币数量大于或等于扫码充电金额时可抵现金,金币不可提现)'.format(backCoins)})
- else:
- logger.error('not net pay rather user virtual card pay. something is wrong.')
- return
- auth_bridge = get_wechat_auth_bridge(source=self.device,
- app_type=APP_TYPE.WECHAT_USER_MANAGER)
- self.notify_user_service_complete(
- service_name='充电',
- openid=user.get_bound_pay_openid(auth_bridge.bound_openid_key),
- port=str(order.used_port),
- address=order.address,
- reason=self.event_data.get('reasonDesc'),
- finished_time=order.finishedTime.strftime('%Y-%m-%d %H:%M:%S'),
- extra=extra)
- def _calc_refund_info(self, backCoins, orderCoin):
- if backCoins >= orderCoin:
- need_back_coins = orderCoin
- need_consume_coins = VirtualCoin(0)
- backCoins -= orderCoin
- else:
- need_back_coins = backCoins
- need_consume_coins = orderCoin - need_back_coins
- backCoins = VirtualCoin(0)
- return need_back_coins, need_consume_coins, backCoins
- class MyIcStartAckEvent(IcStartAckEvent):
- def __init__(self, smartBox, event_data):
- super(MyIcStartAckEvent, self).__init__(smartBox, event_data, StartAckEventPreProcessor())
- def post_after_start(self, order = None):
- pass
- def post_after_finish(self, order = None):
- pass
- def merge_order(self, master_order, sub_orders):
- # type:(ConsumeRecord, list)->dict
- consumeModule = self.device.get('otherConf', dict()).get('consumeModule', 0)
- # 按时间计费
- if consumeModule == 0:
- billingType = 'time'
- else:
- billingType = 'elec'
- start_time = Arrow.fromdatetime(master_order.startTime, tzinfo = settings.TIME_ZONE)
- portDict = {
- 'billingType': billingType
- }
- if master_order.paymentInfo['via'] == 'virtualCard':
- portDict.update({
- 'vCardId': master_order.paymentInfo['itemId']
- })
- all_coins = master_order.coin
- all_money = master_order.money
- for sub_order in sub_orders:
- all_coins += sub_order.coin
- all_money += sub_order.money
- portDict['coins'] = str(all_coins)
- portDict['money'] = str(all_money)
- portDict['estimatedTs'] = int(start_time.timestamp + 12 * 60 * 60)
- return portDict
- def do_time_finished(self, card, order, merge_order_info):
- # type: (Card, ConsumeRecord, dict)->None
- duration, elec = self.event_data['duration'], self.event_data['elec']
- coins = VirtualCoin(merge_order_info['coins'])
- left = self.event_data['left']
- consumeDict = {
- 'reason': self.event_data['reason'],
- 'chargeIndex': str(order.used_port),
- 'duration': duration,
- 'elec': elec,
- 'elecFee': self.deviceAdapter.calc_elec_fee(elec)
- }
- # backMoney = VirtualCoin(self.event_data['backMoney'])
- group = self.device.group # type: GroupDict
- extra = [{
- u'实体卡号': self.event_data['cardNo']
- }]
- consumeDict.update({'balance': str(card.balance)})
- order.update_service_info(consumeDict)
- self.notify_user_service_complete(
- service_name = '充电',
- openid = card.managerialOpenId if card else '',
- port = order.used_port,
- address = group.address,
- reason = self.event_data['reason'],
- finished_time = order.finishedTime.strftime('%Y-%m-%d %H:%M:%S'),
- extra = extra)
- def do_elec_finished(self, card, order, merge_order_info):
- # type:(Card, ConsumeRecord, dict)->None
- '''
- 电川的板子 按电量退费
- :return:
- '''
- leftElec = self.event_data.get('left', 0) / 100.0
- duration, elec = self.event_data['duration'], self.event_data['elec']
- try:
- consumeDict = {
- 'reason': self.event_data['reasonDesc'],
- 'chargeIndex': order.used_port,
- 'duration': duration,
- 'elec': elec,
- 'elecFee': self.deviceAdapter.calc_elec_fee(elec)
- }
- # backMoney = self.event_data.get('backMoney')
- extra = [{u'实体卡号': self.event_data['cardNo']}]
- # if self.event_data['cardType'] == 'ID':
- # if backMoney > 0:
- # self.refund_money_for_card(RMB(backMoney), card.id)
- # extra.append({
- # u'退款金额': u'{}(金币)'.format(backMoney)
- # })
- #
- # consumeDict.update({'balance': str(card.balance + VirtualCoin(self.event_data['backMoney']))})
- # else:
- consumeDict.update({'balance': str(card.balance)})
- order.update_service_info(consumeDict)
- self.notify_user_service_complete(
- service_name = '充电',
- openid = self.get_managerialOpenId_by_openId(order.openId),
- port = order.used_port,
- address = self.device.group.address,
- reason = self.event_data['reason'],
- finished_time = order.finishedTime.strftime('%Y-%m-%d %H:%M:%S'),
- extra = extra)
- except Exception as e:
- logger.exception(e)
- def do_finished_event(self, card, order, merge_order_info):
- # type:(Card, ConsumeRecord, dict)->None
- if 'backMoney' in self.event_data and self.event_data['backMoney'] > RMB(0):
- refund_order = RechargeRecord.objects(orderNo = self.event_data['order_id']).first()
- if not refund_order:
- self.refund_money_for_card(RMB(self.event_data['backMoney']), card.id, self.event_data['order_id'])
- billing_type = merge_order_info['billingType']
- if billing_type == 'time':
- self.do_time_finished(card, order, merge_order_info)
- else:
- self.do_elec_finished(card, order, merge_order_info)
- class MyIcRechargeAckEvent(IcRechargeAckEvent):
- def __init__(self, smartBox, event_data):
- super(MyIcRechargeAckEvent, self).__init__(smartBox, event_data, StartAckEventPreProcessor())
- class MyCardRefundAckEvent(CardRefundAckEvent):
- def __init__(self, smartBox, event_data):
- super(MyCardRefundAckEvent, self).__init__(smartBox, event_data, CardRefundAckEventPreProcessor())
- class CardRefundAckEventPreProcessor(AckEventProcessorIntf):
- def pre_processing(self, device, event_data):
- # type:(DeviceDict, dict)->dict
- if 'cardType' in event_data:
- if event_data['cardType'] == 'AA33':
- event_data['cardType'] = 'ID'
- else:
- event_data['cardType'] = 'IC'
- if 'cardNo' in event_data:
- event_data['cardNo'] = str(event_data['cardNo'])
- event_data['backMoney'] = (int(event_data['backMoney']) / 10.0)
- return event_data
- class MyIdStartAckEvent(IdStartAckEvent):
- def __init__(self, smartBox, event_data):
- super(MyIdStartAckEvent, self).__init__(smartBox, event_data, StartAckEventPreProcessor())
- def post_after_start(self, order=None):
- pass
- def post_after_finish(self, order=None):
- pass
- def merge_order(self, master_order, sub_orders):
- # type:(ConsumeRecord, list)->dict
- billingType = self.device.get('otherConf', dict()).get('billingType', 'time')
- start_time = Arrow.fromdatetime(master_order.startTime, tzinfo = settings.TIME_ZONE)
- portDict = {
- 'billingType': billingType
- }
- all_coins = master_order.coin
- all_money = master_order.money
- all_consume_time = self.event_data.get('needTime', 0)
- all_consume_elec = self.event_data.get('needElec', 0)
- for sub_order in sub_orders:
- all_coins += sub_order.coin
- all_money += sub_order.money
- if self.event_data.get('sub', []):
- for _ in self.event_data['sub']:
- all_consume_time += _.get('needTime', 0)
- all_consume_elec += _.get('needElec', 0)
- portDict['coins'] = str(all_coins)
- portDict['money'] = str(all_money)
- portDict['all_consume_time_value'] = all_consume_time
- portDict['all_consume_elec_value'] = all_consume_elec
- # 直接显示充满自停
- portDict['needValue'] = 999
- portDict['needKind'] = 'needTime'
- portDict['unit'] = u'分钟'
- portDict['estimatedTs'] = int(start_time.timestamp + portDict['needValue'] * 60)
- return portDict
- def _do_finished(self, order, merge_order_info):
- # type: (ConsumeRecord, dict)->None
-
- duration, elec = self.event_data.get('duration', 0), self.event_data.get('elec', 0)
- coins = VirtualCoin(merge_order_info['coins'])
- timeFee = VirtualCoin(self.event_data.get('timeFee', 0.0))
- elecFee = VirtualCoin(self.event_data.get('elecFee', 0.0))
- usedFee = max(timeFee, elecFee)
-
- consumeDict = {
- 'reason': self.event_data.get('reasonDesc', None),
- 'chargeIndex': str(order.used_port),
- 'duration': duration,
- 'elec': elec,
- 'cardNo': self.event_data['cardNo'],
- 'elecFee': self.deviceAdapter.calc_elec_fee(elec),
- DEALER_CONSUMPTION_AGG_KIND.CONSUME_CARD: coins.mongo_amount,
- 'source': self.event_data.get('source', None)
- }
-
- refundProtectionTime = int(self.device.get('otherConf', {}).get('refundProtectionTime', 5))
- logger.info('[HDV3]{} refund protect time = {} duration={} coins={} usedFee={}'.format(
- repr(self.device), refundProtectionTime, duration, coins, usedFee))
- if duration <= refundProtectionTime:
- backMoney = coins
- usedFee = VirtualCoin(0)
- else:
- backMoney = coins - usedFee
- logger.info('{} refund protect time = {} backMoney={}'.format(
- repr(self.device), refundProtectionTime, backMoney))
- self.card.clear_frozen_balance(str(order.id), backMoney)
- self.card.reload()
- extra = []
- extra.append({u'实体卡': '{}--No:{}'.format(self.card.cardName, self.card.cardNo)})
- extra.append({u'本次使用时长': '{}(分钟)'.format(duration)})
- extra.append({u'本次消费金额': '{}(金币)'.format(usedFee)})
- extra.append({u'卡片当前余额': '{}(金币)'.format(self.card.balance.mongo_amount)})
-
- if backMoney > VirtualCoin(0):
- self.record_refund_money_for_card(backMoney, str(self.card.id), orderNo=order.orderNo)
- consumeDict.update({
- DEALER_CONSUMPTION_AGG_KIND.CONSUME_CARD: usedFee.mongo_amount,
- DEALER_CONSUMPTION_AGG_KIND.REFUNDED_COINS: backMoney.mongo_amount
- })
- order.update_service_info(consumeDict)
- self.notify_user_service_complete(
- service_name='充电',
- openid=self.card.managerialOpenId,
- port=str(order.used_port),
- address=order.address,
- reason=self.event_data.get('reasonDesc'),
- finished_time=order.finishedTime.strftime('%Y-%m-%d %H:%M:%S'),
- extra=extra)
- def do_finished_event(self, order, merge_order_info):
- # type:(ConsumeRecord, dict)->None
- self._do_finished(order, merge_order_info)
- def checkout_order(self, order):
- fee = VirtualCoin(order.coin)
- self.card.freeze_balance(transaction_id=str(order.id), fee=fee)
- class MyVirtualCardStartAckEvent(VirtualCardStartAckEvent):
- def __init__(self, smartBox, event_data):
- super(MyVirtualCardStartAckEvent, self).__init__(smartBox, event_data, StartAckEventPreProcessor())
- def post_after_start(self, order = None, card = None):
- pass
- def post_after_finish(self, order = None):
- pass
- def checkout_order(self, order):
- group = Group.get_group(self.device.groupId) # type:GroupDict
- freeze_user_balance(self.device, group, order, self.virtualCard)
- def merge_order(self, master_order, sub_orders):
- # type:(ConsumeRecord, list)->dict
- billingType = self.device.get('otherConf', dict()).get('billingType', 'time')
- start_time = Arrow.fromdatetime(master_order.startTime, tzinfo = settings.TIME_ZONE)
- portDict = {
- 'billingType': billingType
- }
- all_coins = master_order.coin
- all_money = master_order.money
- all_consume_time = self.event_data.get('needTime', 0)
- all_consume_elec = self.event_data.get('needElec', 0)
- if self.event_data.get('sub', []):
- for _ in self.event_data['sub']:
- all_consume_time += _.get('needTime', 0)
- all_consume_elec += _.get('needElec', 0)
- portDict['coins'] = str(all_coins)
- portDict['money'] = str(all_money)
- if billingType == 'time':
- portDict['needKind'] = 'needTime'
- portDict['needValue'] = all_consume_time
- portDict['unit'] = u'分钟'
- portDict['estimatedTs'] = int(start_time.timestamp + all_consume_time * 60)
- elif billingType == 'elec':
- portDict['needKind'] = 'needElec'
- portDict['needValue'] = round(all_consume_elec / 100.0, 2)
- portDict['unit'] = u'度'
- portDict['estimatedTs'] = int(start_time.timestamp + 12 * 60 * 60)
- else:
- pass
- return portDict
- def do_time_finished(self, card, order, sub_orders, merge_order_info):
- # type: (Card, ConsumeRecord, list, dict)->None
- duration, elec = self.event_data['duration'], self.event_data['elec']
- consumeDict = {
- 'reason': self.event_data['reasonDesc'],
- 'chargeIndex': str(order.used_port),
- 'duration': duration,
- 'elec': elec,
- 'cardNo': self.event_data['cardNo'],
- 'elecFee': self.deviceAdapter.calc_elec_fee(elec)
- }
- auto_refund = self.device.is_auto_refund
- refundProtection = self.device.get('otherConf', {}).get('refundProtection', 0)
- refundProtectionTime = self.device.get('otherConf', {}).get('refundProtectionTime', 5)
- logger.debug('{} auto refund enable switch is {}. refund protect = {}, refund protect time = {}'.format(
- repr(self.device), str(auto_refund), refundProtection, refundProtectionTime))
- if auto_refund:
- order_need_time = order.package.get('time')
- if order_need_time >= duration:
- usedTime = duration
- duration = 0
- else:
- usedTime = order_need_time
- duration -= order_need_time
- success, consumeTotal, consumeDay = self.virtualCard.clear_frozen_quota(transaction_id=str(order.id),
- usedTime=usedTime, spendElec=0,
- backCoins=VirtualCoin(0).mongo_amount)
- self.insert_vCard_consume_record(self.virtualCard, order, success, consumeTotal, consumeDay)
- for sub_order in sub_orders:
- order_need_time = sub_order.package.get('time')
- if order_need_time >= duration:
- usedTime = duration
- duration = 0
- else:
- usedTime = order_need_time
- duration -= order_need_time
- success, consumeTotal, consumeDay = self.virtualCard.clear_frozen_quota(transaction_id=str(sub_order.id),
- usedTime=usedTime, spendElec=0,
- backCoins=VirtualCoin(0).mongo_amount)
- self.insert_vCard_consume_record(self.virtualCard, sub_order, success, consumeTotal, consumeDay)
- else:
- order_need_time = order.package.get('time')
- success, consumeTotal, consumeDay = self.virtualCard.clear_frozen_quota(transaction_id=str(order.id),
- usedTime=order_need_time, spendElec=0,
- backCoins=VirtualCoin(
- 0).mongo_amount)
- self.insert_vCard_consume_record(self.virtualCard, order, success, consumeTotal, consumeDay)
- for sub_order in sub_orders:
- order_need_time = sub_order.package.get('time')
- success, consumeTotal, consumeDay = self.virtualCard.clear_frozen_quota(
- transaction_id=str(sub_order.id),
- usedTime=order_need_time, spendElec=0,
- backCoins=VirtualCoin(0).mongo_amount)
- self.insert_vCard_consume_record(self.virtualCard, sub_order, success, consumeTotal, consumeDay)
- group = self.device.group # type: GroupDict
- extra = [{
- u'虚拟卡号': self.virtualCard.cardNo
- }]
- order.update_service_info(consumeDict)
- self.notify_user_service_complete(
- service_name = '充电',
- openid = card.managerialOpenId if card else '',
- port = order.used_port,
- address = group.address,
- reason = self.event_data['reasonDesc'],
- finished_time = order.finishedTime.strftime('%Y-%m-%d %H:%M:%S'),
- extra = extra)
- def do_elec_finished(self, card, order, sub_orders, merge_order_info):
- # type:(Card, ConsumeRecord, list, dict)->None
- duration, elec = self.event_data['duration'], self.event_data['elec']
- consumeDict = {
- 'reason': self.event_data['reasonDesc'],
- 'chargeIndex': str(order.used_port),
- 'duration': duration,
- 'elec': elec,
- 'cardNo': self.event_data['cardNo'],
- 'elecFee': self.deviceAdapter.calc_elec_fee(elec),
- }
- auto_refund = self.device.is_auto_refund
- refundProtection = self.device.get('otherConf', {}).get('refundProtection', 0)
- refundProtectionTime = self.device.get('otherConf', {}).get('refundProtectionTime', 5)
- logger.debug('{} auto refund enable switch is {}. refund protect = {}, refund protect time = {}'.format(
- repr(self.device), str(auto_refund), refundProtection, refundProtectionTime))
- if auto_refund:
- order_need_time = order.package.get('time')
- if order_need_time >= elec:
- usedTime = duration
- duration = 0
- else:
- usedTime = order_need_time
- elec -= order_need_time
- success, consumeTotal, consumeDay = self.virtualCard.clear_frozen_quota(transaction_id=str(order.id),
- usedTime=usedTime, spendElec=0,
- backCoins=VirtualCoin(
- 0).mongo_amount)
- self.insert_vCard_consume_record(self.virtualCard, order, success, consumeTotal, consumeDay)
- for sub_order in sub_orders:
- order_need_time = order.package.get('time')
- if order_need_time >= duration:
- usedTime = duration
- duration = 0
- else:
- usedTime = order_need_time
- duration -= order_need_time
- success, consumeTotal, consumeDay = self.virtualCard.clear_frozen_quota(
- transaction_id=str(sub_order.id),
- usedTime=usedTime, spendElec=0,
- backCoins=VirtualCoin(0).mongo_amount)
- self.insert_vCard_consume_record(self.virtualCard, sub_order, success, consumeTotal, consumeDay)
- else:
- order_need_time = order.package.get('time')
- success, consumeTotal, consumeDay = self.virtualCard.clear_frozen_quota(
- transaction_id=str(order.id),
- usedTime=order_need_time, spendElec=0,
- backCoins=VirtualCoin(
- 0).mongo_amount)
- self.insert_vCard_consume_record(self.virtualCard, order, success, consumeTotal, consumeDay)
- for sub_order in sub_orders:
- order_need_time = sub_order.package.get('time')
- success, consumeTotal, consumeDay = self.virtualCard.clear_frozen_quota(
- transaction_id=str(sub_order.id),
- usedTime=order_need_time, spendElec=0,
- backCoins=VirtualCoin(0).mongo_amount)
- self.insert_vCard_consume_record(self.virtualCard, sub_order, success, consumeTotal, consumeDay)
- extra = [{
- u'虚拟卡号': self.virtualCard.cardNo
- }]
- order.update_service_info(consumeDict)
- self.notify_user_service_complete(
- service_name = '充电',
- openid = self.get_managerialOpenId_by_openId(order.openId),
- port = order.used_port,
- address = self.device.group.address,
- reason = self.event_data['reason'],
- finished_time = order.finishedTime.strftime('%Y-%m-%d %H:%M:%S'),
- extra = extra)
- def do_finished_event(self, card, order, sub_orders, merge_order_info):
- # type:(Card, ConsumeRecord, list, dict)->None
- billing_type = merge_order_info['billingType']
- if billing_type == 'time':
- self.do_time_finished(card, order, sub_orders,merge_order_info)
- else:
- self.do_elec_finished(card, order, sub_orders,merge_order_info)
- def insert_vCard_consume_record(self, vCard, order, success, consumeTotal, consumeDay):
- try:
- if success and consumeDay['count'] > 0:
- record = VCardConsumeRecord(
- orderNo=VCardConsumeRecord.make_no(order.logicalCode),
- openId=order.openId,
- nickname=order.nickname,
- cardId=str(vCard.id),
- dealerId=vCard.dealerId,
- devNo=order.devNo,
- devTypeCode = order.devTypeCode,
- devTypeName = order.dev_type_name,
- logicalCode=order.logicalCode,
- groupId=order.groupId,
- address=order.address,
- groupNumber=order.groupNumber,
- groupName=order.groupName,
- attachParas=order.attachParas,
- consumeData=consumeTotal,
- consumeDayData=consumeDay
- )
- record.save()
- except Exception, e:
- logger.exception(e)
|