1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021 |
- # -*- coding: utf-8 -*-
- # !/usr/bin/env python
- import datetime
- import time
- import simplejson as json
- import logging
- from typing import TYPE_CHECKING
- from apilib.monetary import RMB, VirtualCoin
- from apilib.utils_datetime import to_datetime
- from apps.web.common.models import TempValues
- from apps.web.constant import Const, DEALER_CONSUMPTION_AGG_KIND
- from apps.web.core.accounting import Accounting
- from apps.web.device.models import Group, Device
- from apps.web.eventer.base import WorkEvent, FaultEvent
- from apps.web.eventer import EventBuilder
- from apps.web.report.utils import record_consumption_stats
- from apps.web.user.transaction_deprecated import refund_money
- from apps.web.user.models import ServiceProgress, CardRechargeOrder, MyUser, Card, \
- ConsumeRecord
- if TYPE_CHECKING:
- from apps.web.device.models import GroupDict
- logger = logging.getLogger(__name__)
- class builder(EventBuilder):
- def __getEvent__(self, device_event):
- if "ack_event_id" in device_event:
- self.deviceAdapter.ack_05_event(device_event.get("ack_event_id"))
- event_data = self.deviceAdapter.analyze_event_data(device_event)
- if "FaultCode" in event_data:
- return LVZHIFaultEvent(self.deviceAdapter, event_data)
- elif event_data.get('cmd') == '99':
- return LVZHIOnline(self.deviceAdapter, event_data)
- else:
- return ChargingLVZHIWorkEvent(self.deviceAdapter, event_data)
- class ChargingLVZHIWorkEvent(WorkEvent):
- def __parse_device_finished_data(self, event_data):
- duration = event_data.get("duration", -1)
- if duration != -1:
- if "v" in event_data:
- duration = ((duration + 59) / 60)
- elec = event_data.get("elec", -1)
- if elec != -1:
- if "v" in event_data:
- elec = round(elec / (10000.0 * 3600.0), 3)
- else:
- elec = round(elec / 3600.0, 3)
- logger.debug("lz_device duration is {}, device elec is {}".format(duration, elec))
- return duration, elec
- def do(self, **args):
- logger.info("lz_charging event to do devNo=%s,info=%s" % (
- self.device.devNo, json.dumps(self.event_data, ensure_ascii=False)))
- cmd = self.event_data.get("cmd")
- if cmd == "03":
- coins = self.event_data.get("coins")
- port = self.event_data.get("port")
- port_control_cache = Device.get_dev_control_cache(self.device.devNo)
- lineInfo = port_control_cache.get(port, {})
- offlineCoin = float(coins) - float(lineInfo.get("coins", 0))
- if offlineCoin:
- Accounting.recordOfflineCoin(self.device,
- int(time.time()),
- int(offlineCoin))
- else:
- Accounting.recordOfflineCoin(self.device,
- int(time.time()),
- int(float(coins)))
- consumeDict = {
- "totalCount": offlineCoin,
- "chargeIndex": port
- }
- orderNo = self.record_consume_for_coin(RMB(coins), servicedInfo=consumeDict)
- # 更新端口缓存
- billingType = self.event_data.get("billingType")
- portInfo = {
- "port": port,
- "status": Const.DEV_WORK_STATUS_WORKING,
- "coins": coins,
- "billingType": billingType,
- "startTime": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
- "consumeType": "coin",
- "orderNo": orderNo,
- }
- deviceConfigs = self.device['otherConf'].get('deviceConfigs', {})
- if not deviceConfigs:
- deviceConfigs = self.deviceAdapter.get_consumption_rules()
- if billingType == "time":
- coinTime = deviceConfigs.get("coinTime", 240)
- needTime = int(float(coinTime) * float(coins))
- portInfo.update({"needTime": needTime})
- elif billingType == 'billAsService':
- coinElec = deviceConfigs.get("coinElec", 0.6)
- serviceCharge = self.device.bill_as_service_feature.service_charge
- elecCharge = self.device.bill_as_service_feature.elec_charge
- if float(coinElec) == 0.0:
- coinElec = elecCharge
- unitFee = float(serviceCharge) + float(coinElec)
- needElec = round(float(coins) / unitFee, 2)
- portInfo.update({"needElec": needElec})
- else:
- coinElec = deviceConfigs.get("coinElec", 0.6)
- needElec = round(float(coinElec) * float(coins), 2)
- portInfo.update({"needElec": needElec})
- if lineInfo.get("startTime"):
- lastOrder = lineInfo.get("orderNo")
- historicalOrders = lastOrder
- portInfo["startTime"] = lineInfo.get("startTime")
- portInfo["coins"] = coins
- portInfo["historicalOrders"] = historicalOrders
- try:
- order = ConsumeRecord.objects.filter(orderNo=historicalOrders).first()
- order.finishedTime = datetime.datetime.now()
- order.status = "finished"
- order.servicedInfo.update({"reason": "再次投币使用,当前订单金额({})累计到下一单(消费订单号:{})".format(order.coin, orderNo),
- "duration": ((order.finishedTime - order.dateTimeAdded).total_seconds() + 59) / 60,
- })
- order.coin = VirtualCoin(0).mongo_amount
- order.money = RMB(0).mongo_amount
- order.save()
- ServiceProgress.objects(device_imei=self.device.devNo,
- port=int(port), isFinished=False).update_one(upsert=False,
- consumeOrder={
- "orderNo": orderNo,
- "coins": portInfo[
- "coins"]})
- except Exception:
- pass
- Device.update_port_control_cache(self.device.devNo, portInfo)
- # 如果是投币,直接把端口状态刷新下
- try:
- self.deviceAdapter.get_all_port_status()
- except Exception, e:
- logger.info("lz_some err=%s" % e)
- elif cmd == "04": # 只有离线卡 离线卡记录数据更新
- cardNo = self.event_data["cardNo"]
- fee = RMB(self.event_data["fee"])
- cardType = self.event_data["cardType"]
- cardBalance = RMB(self.event_data["cardBalance"])
- port = self.event_data["port"]
- eventCode = self.event_data["eventCode"]
- card = self.update_card_dealer_and_type(cardNo, cardType=cardType, balance=cardBalance)
- if not card:
- card = Card(cardNo=cardNo, remarks="中山智能离线卡", agentId=self.dealer.agentId,
- openId=Const.DEFAULT_CARD_OPENID, dealerId=str(self.dealer.id), cardType=cardType, isHaveBalance=False,
- devNo=self.device.devNo, balance=cardBalance)
- card.save()
- if cardType == "IC":
- if eventCode == "01": # 刷卡上报事件 01 代表扣费 02 代表退费
- billingType = self.event_data.get("billingType")
- port_control_cache = Device.get_dev_control_cache(self.device.devNo)
- portInfo = {
- "port": port,
- "status": Const.DEV_WORK_STATUS_WORKING,
- "cardType": cardType,
- "cardNo": cardNo,
- "coins": str(fee),
- "billingType": billingType,
- "startTime": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
- "consumeType": "card",
- }
- # 如果是绑定了卡的
- if card.cardNo != card.openId:
- portInfo.update({"openId": card.openId})
- deviceConfigs = self.device['otherConf'].get('deviceConfigs', {})
- if not deviceConfigs:
- deviceConfigs = self.deviceAdapter.get_consumption_rules()
- if billingType == "time":
- cardTime = deviceConfigs.get("cardTime", 240)
- needTime = int(float(cardTime) * float(fee))
- portInfo.update({"needTime": needTime})
- elif billingType == 'billAsService':
- cardElec = deviceConfigs.get("cardElec", 0.6)
- serviceCharge = self.device.bill_as_service_feature.service_charge
- elecCharge = self.device.bill_as_service_feature.elec_charge
- if float(cardElec) == 0.0:
- cardElec = elecCharge
- unitFee = float(serviceCharge) + float(cardElec)
- needElec = round(float(fee) / unitFee, 2)
- portInfo.update({"needElec": needElec})
- else:
- cardElec = deviceConfigs.get("cardElec", 0.6)
- needElec = round(float(cardElec) * float(fee), 2)
- portInfo.update({"needElec": needElec})
- servicedInfo = {"卡号": cardNo, "chargeIndex": port}
- # 记录卡消费记录以及消费记录
- orderNo, cardOrderNo = self.record_consume_for_card(card, fee, servicedInfo=servicedInfo)
- portInfo.update({"orderNo": orderNo})
- lineInfo = port_control_cache.get(port, {})
- if lineInfo.get("startTime"):
- lastOrder = lineInfo.get("orderNo")
- historicalOrders = lastOrder
- portInfo["startTime"] = lineInfo.get("startTime")
- portInfo["coins"] = str(fee)
- portInfo["historicalOrders"] = historicalOrders
- try:
- order = ConsumeRecord.objects.filter(orderNo=historicalOrders).first()
- order.finishedTime = datetime.datetime.now()
- order.status = "finished"
- order.servicedInfo.update(
- {"reason": "再次刷卡使用,当前订单金额({})累计到下一单(消费订单号:{})".format(order.coin, orderNo),
- "duration": ((order.finishedTime - order.dateTimeAdded).total_seconds() + 59) / 60,
- })
- order.coin = VirtualCoin(0).mongo_amount
- order.money = RMB(0).mongo_amount
- order.save()
- ServiceProgress.objects(device_imei=self.device.devNo,
- port=int(port), isFinished=False).update_one(upsert=False,
- consumeOrder={
- "orderNo": orderNo,
- "coins": portInfo[
- "coins"]})
- except Exception:
- pass
- else:
- # 记录当前服务的progress.没有上报端口号,所以先用-1标记,表示端口未知。端口等消费的时候会报上来
- ServiceProgress.register_card_service(self.device, int(port), card,
- {"orderNo": orderNo,
- "money": self.event_data["fee"],
- "coin": self.event_data["fee"],
- "needTime": 0,
- "cardOrderNo": cardOrderNo})
- Device.update_port_control_cache(self.device.devNo, portInfo)
- # 卡号与openId相同,则为未绑定卡不用发送
- if card.cardNo == card.openId:
- return
- # 通知微信,已经扣费
- self.notify_balance_has_consume_for_card(card, fee)
- # 离线卡退费事件 更新卡余额
- else:
- self.update_card_dealer_and_type(cardNo, balance=cardBalance)
- elif cmd == "05":
- devNo = self.device.devNo
- port = self.event_data["port"]
- try:
- # 获取充电的模式
- ctrInfo = Device.get_dev_control_cache(devNo)
- lineInfo = ctrInfo.get(port)
- if not lineInfo:
- logger.debug("lz_get null control cache from {}".format(repr(self.device)))
- return
- billingType = self.event_data.get("billingType")
- if billingType == "elec":
- return self.do_elec_finish(devNo, port, lineInfo, self.event_data)
- elif billingType == "billAsService":
- return self.do_billAsService_finish(devNo, port, lineInfo, self.event_data)
- else:
- return self.do_time_finish(devNo, port, lineInfo, self.event_data)
- finally:
- Device.clear_port_control_cache(devNo, str(port))
- elif cmd == "1D":
- cardNo = self.event_data["cardNo"]
- cardType = self.event_data["cardType"]
- cardBalance = self.event_data["cardBalance"]
- if cardType == "ID":
- logger.info("lz_cardType is IdCard return!!!")
- card = self.update_card_dealer_and_type(cardNo, cardType, balance=RMB(cardBalance)) # type: Card
- if not card:
- card = Card(cardNo=cardNo, remarks="中山智能离线卡", agentId=self.dealer.agentId,
- openId=Const.DEFAULT_CARD_OPENID, dealerId=str(self.dealer.id), cardType=cardType, isHaveBalance=False,
- devNo=self.device.devNo, balance=RMB(cardBalance))
- card.save()
- logger.info("lz_ no such card now create!! cardNo:%s" % cardNo)
- money, coins, orderNos, cardOrderNos = CardRechargeOrder.get_to_do_list(str(card.id))
- if not orderNos:
- logger.info("lz_not card recharge record!, card is <{}>".format(cardNo))
- # 缓存里面更新低余额卡号
- card.reload()
- self.deviceAdapter.updata_no_balance_list(self.device.devNo, card)
- return
- orderNos = [str(item) for item in orderNos]
- CardRechargeInfo = {
- "rechargeRecord": orderNos,
- "cardRechargeOrder": cardOrderNos,
- "asyncMoney": str(coins),
- "cardBalance": str(cardBalance)
- }
- tempKey = "%s-%s" % (self.device["devNo"], cardNo)
- TempValues.set(key=tempKey, value=json.dumps(CardRechargeInfo))
- if card.frozen:
- asyncMoney = 0
- else:
- asyncMoney = str(coins)
- try:
- CardRechargeOrder.objects.filter(orderNo__in=cardOrderNos).update(status="finished")
- except Exception as e:
- logger.debug("lz_%s" % e)
- else:
- self.deviceAdapter.recharge_ic_card(cardNo, asyncMoney)
- logger.info("send recharge cmd is done,wait 1F return cardNo:%s asyncMoney:%s tempKey:%s" % (
- cardNo, asyncMoney, tempKey))
- elif cmd == "1F":
- cardNo = str(self.event_data["cardNo"])
- cardType = self.event_data["cardType"]
- ayscMoney = RMB(self.event_data["ayscMoney"])
- nowBalance = RMB(self.event_data["cardBalance"])
- status = self.event_data["status"]
- card = self.update_card_dealer_and_type(cardNo, cardType) # type: Card
- if not card:
- return
- if card.frozen:
- logger.debug("lz_{} has been frozen.".format(repr(card)))
- return
- # 明确接收到了主板同步失败的情况下,将订单的状态回传
- if status != "01":
- CardRechargeInfoKey = "%s-%s" % (self.device["devNo"], cardNo)
- CardRechargeInfo = TempValues.get(CardRechargeInfoKey)
- cardRechargeOrders = CardRechargeInfo.get("cardRechargeOrder")
- logger.info("lz_card recharge receive fail status from device, card is <{}>".format(cardNo))
- try:
- CardRechargeOrder.objects.filter(orderNo__in=cardRechargeOrders).update(status="finishedPay")
- except Exception as e:
- logger.debug("lz_%s" % e)
- return
- else:
- self.update_card_dealer_and_type(cardNo, cardType=cardType, balance=nowBalance)
- logger.info("IcCard recharge completed cardNo:%s asyncMoney:%s nowBalance%s" % (
- cardNo, str(ayscMoney), str(nowBalance)))
- elif cmd == "F1":
- self.deviceAdapter.send_F1_heartbeat()
- def do_elec_finish(self, devNo, port, lineInfo, msgDict=None):
- leftElec = float(self.event_data.get("leftElec", 0))
- reasonStr = self.event_data.get("reason")
- cardNo = self.event_data.get("cardNo")
- startTime = lineInfo.get("startTime")
- startTime = to_datetime(startTime)
- nowTime = datetime.datetime.now()
- coins = VirtualCoin(lineInfo.get("coins"))
- needElec = lineInfo.get("needElec")
- if leftElec == 65535:
- leftElec = needElec
- elif leftElec > needElec:
- logger.error("lz_left elec is bigger than need elec. something is wrong")
- leftElec = 0
- spendElec = needElec - leftElec
- if startTime > nowTime:
- usedTime = 0
- else:
- usedTime = int(round(((nowTime - startTime).total_seconds() / 60.0)))
- # 获取组信息
- group = Group.get_group(self.device["groupId"])
- consumeTypeCode = self.event_data["consumeTypeCode"]
- if consumeTypeCode == "01": # 投币结束上报 记录到表中
- CoinConsumeRcd = ConsumeRecord.objects.get(orderNo=lineInfo["orderNo"])
- CoinConsumeRcd.finishedTime = datetime.datetime.now()
- consumeDict = {
- "chargeIndex": port,
- "reason": reasonStr,
- "leftElec": leftElec,
- "leftMoney": self.event_data["backMoney"],
- DEALER_CONSUMPTION_AGG_KIND.DURATION: usedTime,
- DEALER_CONSUMPTION_AGG_KIND.ELEC: spendElec,
- }
- servicedInfo = CoinConsumeRcd.servicedInfo
- servicedInfo.update(consumeDict)
- servicedInfo["rechargeCode"] = self.event_data["rechargeCode"]
- CoinConsumeRcd.servicedInfo = servicedInfo
- CoinConsumeRcd.save()
- valueDict = {
- DEALER_CONSUMPTION_AGG_KIND.TOTAL_COUNT: servicedInfo.get("totalCount"),
- DEALER_CONSUMPTION_AGG_KIND.DURATION: servicedInfo.get("duration")
- }
- status = CoinConsumeRcd.update_agg_info(valueDict)
- if status:
- record_consumption_stats(CoinConsumeRcd)
- ServiceProgress.objects(device_imei=self.device.devNo, port=int(port), isFinished=False).update_one(
- upsert=False, isFinished=True, expireAt = datetime.datetime.now())
- elif consumeTypeCode == "04": # 扫码的结束
- refundCoins = VirtualCoin(0)
- consumeDict = {
- "reason": reasonStr,
- "chargeIndex": port,
- "duration": usedTime,
- "leftElec": leftElec,
- DEALER_CONSUMPTION_AGG_KIND.COIN: coins.mongo_amount,
- DEALER_CONSUMPTION_AGG_KIND.SPEND_MONEY: coins.mongo_amount,
- DEALER_CONSUMPTION_AGG_KIND.ELEC: spendElec,
- }
- refundSwitch = self.device.is_auto_refund
- refundProtection = int(lineInfo.get("refundProtection", 0))
- refundProtectionTime = int(lineInfo.get("refundProtectionTime", 5))
- if refundSwitch:
- refundCoins = VirtualCoin(self.event_data["backMoney"])
- if (refundProtection == 1 and usedTime < refundProtectionTime) and refundCoins != VirtualCoin(0):
- refundCoins = coins
- if refundCoins > coins:
- refundCoins = coins
- if "openId" in lineInfo:
- # 扫码使用金币启动
- openId = lineInfo["openId"]
- extra = []
- extra.append({u"消费金额": "{}(金币)".format(coins)})
- try:
- if refundCoins > VirtualCoin(0):
- consumeDict.update({
- DEALER_CONSUMPTION_AGG_KIND.REFUNDED_COINS: refundCoins.mongo_amount,
- DEALER_CONSUMPTION_AGG_KIND.SPEND_MONEY: (coins - refundCoins).mongo_amount
- })
- refund_money(self.device, refundCoins, openId)
- extra.append({u"退款金额": "{}(金币)".format(refundCoins)})
- ServiceProgress.update_progress_and_consume_rcd(
- self.device.ownerId,
- {
- "open_id": lineInfo["openId"],
- "port": int(port),
- "device_imei": self.device.devNo,
- "isFinished": False
- },
- consumeDict
- )
- finally:
- user = MyUser.objects(openId=lineInfo["openId"],
- groupId=self.device.groupId).first()
- self.notify_user_service_complete(
- service_name="充电",
- openid=user.managerialOpenId if user else "",
- port=port,
- address=group["address"],
- reason=self.event_data["reason"],
- finished_time=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
- extra=extra
- )
- else:
- logger.error("lz_not net pay rather user virtual card pay. something is wrong.")
- # 离线卡结束 直接结束服务进程
- elif consumeTypeCode == "02": # 离线卡结束
- consumeDict = {
- "chargeIndex": port,
- "reason": self.event_data["reason"],
- "leftElec": leftElec,
- "duration": usedTime,
- # "finishedTime": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
- "cardNo": cardNo,
- DEALER_CONSUMPTION_AGG_KIND.CONSUME_CARD: coins.mongo_amount,
- DEALER_CONSUMPTION_AGG_KIND.SPEND_MONEY: coins.mongo_amount,
- DEALER_CONSUMPTION_AGG_KIND.ELEC: spendElec,
- }
- backMoney = VirtualCoin(self.event_data.get("backMoney", 0))
- if backMoney > VirtualCoin(0):
- consumeDict.update({
- DEALER_CONSUMPTION_AGG_KIND.REFUND_CARD: backMoney.mongo_amount,
- DEALER_CONSUMPTION_AGG_KIND.SPEND_MONEY: (coins - backMoney).mongo_amount,
- })
- card = self.update_card_dealer_and_type(cardNo)
- if not card:
- logger.info("end charge but no cardNo!!! cardNo=%s" % cardNo)
- openId = lineInfo.get("openId", cardNo)
- ServiceProgress.update_progress_and_consume_rcd(
- self.device.ownerId,
- {
- "open_id": openId,
- "port": int(port),
- "device_imei": self.device.devNo,
- "isFinished": False,
- },
- consumeDict
- )
- # 未绑定用户的离线卡
- if card.cardNo == card.openId:
- return
- extra = [{u"实体卡号": cardNo}]
- if backMoney > VirtualCoin(0):
- extra.append({
- u"等待靠卡返回金额": u"{}(金币)".format(backMoney.mongo_amount)
- })
- else:
- extra.append({
- u"消耗金额": u"{}(金币)".format(lineInfo.get("coins",0))
- })
- self.notify_user_service_complete(
- service_name=u"充电",
- openid=self.get_managerialOpenId_by_openId(lineInfo.get("openId")),
- port=port,
- address=group["address"],
- reason=self.event_data["reason"],
- finished_time=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
- extra=extra
- )
- def do_time_finish(self, devNo, port, lineInfo, msgDict=None):
- try:
- refundProtection = lineInfo.get("refundProtection", 0)
- refundProtectionTime = int(lineInfo.get("refundProtectionTime", 5))
- startTime = to_datetime(lineInfo["startTime"])
- nowTime = datetime.datetime.now()
- if startTime > nowTime:
- logger.error("lz_start time is bigger than now time,devNo={}".format(devNo))
- usedTime = 0
- else:
- usedTime = (((nowTime - startTime).total_seconds() + 59) / 60)
- leftTime = int(self.event_data["leftTime"])
- actualNeedTime = usedTime + leftTime
- group = self.device.group # type: GroupDict
- coins = VirtualCoin(lineInfo.get("coins"))
- consumeTypeCode = self.event_data["consumeTypeCode"]
- if consumeTypeCode == "01": # 投币结束上报 记录到表中
- CoinConsumeRcd = ConsumeRecord.objects.get(orderNo=lineInfo["orderNo"])
- CoinConsumeRcd.finishedTime = datetime.datetime.now()
- consumeDict = {
- "reason": self.event_data["reason"],
- "leftTime": leftTime,
- "duration": usedTime,
- # "finishedTime": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
- "leftMoney": self.event_data["backMoney"],
- }
- servicedInfo = CoinConsumeRcd.servicedInfo
- servicedInfo.update(consumeDict)
- servicedInfo["rechargeCode"] = self.event_data["rechargeCode"]
- CoinConsumeRcd.servicedInfo = servicedInfo
- CoinConsumeRcd.save()
- valueDict = {
- DEALER_CONSUMPTION_AGG_KIND.TOTAL_COUNT: servicedInfo.get("totalCount"),
- DEALER_CONSUMPTION_AGG_KIND.DURATION: servicedInfo.get("duration")
- }
- status = CoinConsumeRcd.update_agg_info(valueDict)
- if status:
- record_consumption_stats(CoinConsumeRcd)
- ServiceProgress.objects(device_imei=self.device.devNo, port=int(port), isFinished=False).update_one(
- upsert=False, isFinished=True)
- elif consumeTypeCode == "02": # 离线卡
- # 服务消息
- consumeDict = {
- "reason": self.event_data["reason"],
- "leftTime": leftTime,
- "chargeIndex": port,
- "duration": usedTime,
- "cardNo": self.event_data["cardNo"],
- DEALER_CONSUMPTION_AGG_KIND.CONSUME_CARD: lineInfo['coins'],
- DEALER_CONSUMPTION_AGG_KIND.SPEND_MONEY: lineInfo['coins'],
- }
- card = Card.objects.filter(cardNo=lineInfo["cardNo"], agentId=self.dealer.agentId).first()
- if not card:
- logger.error("lz_not exist this card no.")
- return
- openId = lineInfo.get("openId", card.cardNo)
- backMoney = VirtualCoin(self.event_data.get("backMoney"))
- if backMoney > VirtualCoin(0):
- consumeDict.update({
- DEALER_CONSUMPTION_AGG_KIND.REFUND_CARD: VirtualCoin(self.event_data["backMoney"]).mongo_amount,
- DEALER_CONSUMPTION_AGG_KIND.SPEND_MONEY: (coins-backMoney).mongo_amount
- })
- ServiceProgress.update_progress_and_consume_rcd(self.device.ownerId,
- {"open_id": openId, "port": int(port),
- "device_imei": self.device.devNo,
- "isFinished": False}, consumeDict)
- # 判断是否绑卡 绑卡就推送,不绑卡就不推送
- if card.cardNo == card.openId:
- return
- extra = [{
- u"实体卡号": lineInfo["cardNo"]
- }]
- if VirtualCoin(self.event_data["backMoney"]) > VirtualCoin(0):
- extra.append({
- u"等待靠卡返回金额": u"{}(金币)".format(self.event_data["backMoney"])
- })
- self.notify_user_service_complete(
- service_name="充电",
- openid=card.managerialOpenId if card else "",
- port=port,
- address=group["address"],
- reason=self.event_data["reason"],
- finished_time=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
- extra=extra)
- elif consumeTypeCode == "04": # 扫码支付
- extra = []
- consumeDict = {
- "reason": self.event_data["reason"],
- "leftTime": leftTime,
- "chargeIndex": port,
- "duration": usedTime,
- DEALER_CONSUMPTION_AGG_KIND.COIN: coins.mongo_amount,
- DEALER_CONSUMPTION_AGG_KIND.SPEND_MONEY: coins.mongo_amount,
- }
- coins = VirtualCoin(lineInfo["coins"])
- backCoins = VirtualCoin(0)
- if self.device.is_auto_refund:
- backCoins = VirtualCoin(self.event_data.get("backMoney", 0))
- if (refundProtection == 1 and usedTime < refundProtectionTime) and backCoins != VirtualCoin(0):
- backCoins = coins
- if backCoins > coins:
- backCoins = coins
- logger.debug(
- "lz_lefttime = {}, usedTime = {}, need time = {}, back coins = {}".format(leftTime, usedTime,
- actualNeedTime,
- backCoins))
- if "openId" in lineInfo:
- try:
- if backCoins > VirtualCoin(0):
- consumeDict.update({
- DEALER_CONSUMPTION_AGG_KIND.REFUNDED_COINS: backCoins.mongo_amount,
- DEALER_CONSUMPTION_AGG_KIND.SPEND_MONEY: (coins- backCoins).mongo_amount
- })
- refund_money(self.device, backCoins, lineInfo["openId"])
- extra.append({u"消费金额": "{}(金币)".format(coins)})
- extra.append({u"退款金额": "{}(金币)".format(backCoins)})
- else:
- extra.append({u"消费金额": "{}(金币)".format(coins)})
- ServiceProgress.update_progress_and_consume_rcd(self.device.ownerId,
- {"open_id": lineInfo["openId"],
- "port": int(port),
- "device_imei": self.device.devNo,
- "isFinished": False}, consumeDict)
- user = MyUser.objects(openId=lineInfo["openId"],
- groupId=self.device.groupId).first()
- self.notify_user_service_complete(
- service_name="充电",
- openid=user.managerialOpenId if user else "",
- port=port,
- address=group["address"],
- reason=self.event_data["reason"],
- finished_time=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
- extra=extra
- )
- except Exception as e:
- logger.info(e)
- else: # 后续在线卡或是其他
- pass
- except Exception as e:
- logger.exception(e)
- def do_billAsService_finish(self,devNo, port, lineInfo, msgDict=None):
- serviceFee = float(self.event_data.get("serviceFee", 0))
- reasonStr = self.event_data.get("reason")
- cardNo = self.event_data.get("cardNo")
- startTime = lineInfo.get("startTime")
- startTime = to_datetime(startTime)
- nowTime = datetime.datetime.now()
- coins = VirtualCoin(lineInfo.get("coins"))
- if serviceFee == 65535:
- serviceFee = 0
- usedElec = 0
- usedElecFee = 0
- else:
- usedElec = float(serviceFee) / float(self.device.devTypeFeatures.get("billAsService").get("serviceCharge"))
- usedElecFee = float(str(coins)) - float(self.event_data.get("backMoney")) - serviceFee
- if startTime > nowTime:
- usedTime = 0
- else:
- usedTime = int(round(((nowTime - startTime).total_seconds() / 60.0)))
- # 获取组信息
- group = Group.get_group(self.device["groupId"])
- consumeTypeCode = self.event_data["consumeTypeCode"]
- if consumeTypeCode == "01": # 投币结束上报 记录到表中
- CoinConsumeRcd = ConsumeRecord.objects.get(orderNo=lineInfo["orderNo"])
- CoinConsumeRcd.finishedTime = datetime.datetime.now()
- consumeDict = {
- "chargeIndex": port,
- "reason": reasonStr,
- "leftMoney": self.event_data["backMoney"],
- DEALER_CONSUMPTION_AGG_KIND.DURATION: usedTime,
- }
- servicedInfo = CoinConsumeRcd.servicedInfo
- servicedInfo.update(consumeDict)
- servicedInfo["rechargeCode"] = self.event_data["rechargeCode"]
- CoinConsumeRcd.servicedInfo = servicedInfo
- CoinConsumeRcd.save()
- valueDict = {
- DEALER_CONSUMPTION_AGG_KIND.TOTAL_COUNT: servicedInfo.get("totalCount"),
- DEALER_CONSUMPTION_AGG_KIND.DURATION: servicedInfo.get("duration"),
- DEALER_CONSUMPTION_AGG_KIND.ELECFEE: usedElecFee,
- DEALER_CONSUMPTION_AGG_KIND.SERVICEFEE: serviceFee,
- }
- status = CoinConsumeRcd.update_agg_info(valueDict)
- if status:
- record_consumption_stats(CoinConsumeRcd)
- ServiceProgress.objects(device_imei=self.device.devNo, port=int(port), isFinished=False).update_one(
- upsert=False, isFinished=True, expireAt = datetime.datetime.now())
- elif consumeTypeCode == "02": # 离线卡结束
- consumeDict = {
- "chargeIndex": port,
- "reason": self.event_data["reason"],
- "duration": usedTime,
- "cardNo": cardNo,
- DEALER_CONSUMPTION_AGG_KIND.CONSUME_CARD: VirtualCoin(coins).mongo_amount,
- DEALER_CONSUMPTION_AGG_KIND.SPEND_MONEY: VirtualCoin(coins).mongo_amount,
- DEALER_CONSUMPTION_AGG_KIND.SERVICEFEE: serviceFee,
- DEALER_CONSUMPTION_AGG_KIND.ELECFEE: usedElecFee,
- }
- backMoney = VirtualCoin(self.event_data.get("backMoney", 0))
- if backMoney > VirtualCoin(0):
- consumeDict.update({
- DEALER_CONSUMPTION_AGG_KIND.REFUND_CARD: backMoney.mongo_amount,
- DEALER_CONSUMPTION_AGG_KIND.SPEND_MONEY: (coins - backMoney).mongo_amount,
- })
- card = self.update_card_dealer_and_type(cardNo)
- if not card:
- logger.info("end charge but no cardNo!!! cardNo=%s" % cardNo)
- openId = lineInfo.get("openId", cardNo)
- ServiceProgress.update_progress_and_consume_rcd(
- self.device.ownerId,
- {
- "open_id": openId,
- "port": int(port),
- "device_imei": self.device.devNo,
- "isFinished": False,
- },
- consumeDict
- )
- # 未绑定用户的离线卡
- if card.cardNo == card.openId:
- return
- extra = [{u"实体卡号": cardNo}]
- if backMoney > VirtualCoin(0):
- extra.append({
- u"等待靠卡返回金额": u"{}(金币)".format(backMoney.mongo_amount)
- })
- else:
- extra.append({
- u"消耗金额": u"{}(金币)".format(lineInfo.get("coins",0)),
- u"服务费金额": "{}(金币)".format(serviceFee),
- u"电费金额": "{}(金币)".format(float(lineInfo.get("coins",0)) - serviceFee)
- })
- self.notify_user_service_complete(
- service_name=u"充电",
- openid=self.get_managerialOpenId_by_openId(lineInfo.get("openId")),
- port=port,
- address=group["address"],
- reason=self.event_data["reason"],
- finished_time=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
- extra=extra
- )
- elif consumeTypeCode == "03":
- pass
- elif consumeTypeCode == "04": # 扫码的结束
- refundCoins = VirtualCoin(0)
- consumeDict = {
- "reason": reasonStr,
- "chargeIndex": port,
- "duration": usedTime,
- DEALER_CONSUMPTION_AGG_KIND.COIN: coins.mongo_amount,
- DEALER_CONSUMPTION_AGG_KIND.ELEC: usedElec,
- DEALER_CONSUMPTION_AGG_KIND.ELECFEE: usedElecFee,
- DEALER_CONSUMPTION_AGG_KIND.SERVICEFEE: serviceFee
- }
- refundSwitch = self.device.is_auto_refund
- refundProtection = int(lineInfo.get("refundProtection", 0))
- refundProtectionTime = int(lineInfo.get("refundProtectionTime", 5))
- if refundSwitch:
- refundCoins = VirtualCoin(self.event_data["backMoney"])
- if (refundProtection == 1 and usedTime < refundProtectionTime) and refundCoins != VirtualCoin(0):
- refundCoins = coins
- if refundCoins > coins:
- refundCoins = coins
- if "openId" in lineInfo:
- # 扫码使用金币启动
- openId = lineInfo["openId"]
- extra = []
- extra.append({u"消费金额": "{}(金币)".format(coins)})
- extra.append({u"服务费金额": "{}(金币)".format(serviceFee)})
- extra.append({u"电费金额": "{}(金币)".format(usedElecFee)})
- try:
- if refundCoins > VirtualCoin(0):
- consumeDict.update({
- DEALER_CONSUMPTION_AGG_KIND.REFUNDED_COINS: refundCoins.mongo_amount,
- DEALER_CONSUMPTION_AGG_KIND.SPEND_MONEY: (coins - refundCoins).mongo_amount
- })
- refund_money(self.device, refundCoins, openId)
- extra.append({u"退款金额": "{}(金币)".format(refundCoins)})
- ServiceProgress.update_progress_and_consume_rcd(
- self.device.ownerId,
- {
- "open_id": lineInfo["openId"],
- "port": int(port),
- "device_imei": self.device.devNo,
- "isFinished": False
- },
- consumeDict
- )
- finally:
- user = MyUser.objects(openId=lineInfo["openId"],
- groupId=self.device.groupId).first()
- self.notify_user_service_complete(
- service_name="充电",
- openid=user.managerialOpenId if user else "",
- port=port,
- address=group["address"],
- reason=self.event_data["reason"],
- finished_time=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
- extra=extra
- )
- else:
- logger.error("lz_not net pay rather user virtual card pay. something is wrong.")
- # 离线卡结束 直接结束服务进程
- class LVZHIFaultEvent(FaultEvent):
- def do(self, **args):
- group = Group.get_group(self.device["groupId"])
- port = self.event_data.get("port")
- faultContent = self.event_data.get("statusInfo")
- if port:
- if self.event_data.get("FaultCode") == "01":
- faultContent = "当前设备第%s号端口警告:发生非法充电" % (port)
- else:
- faultContent = "当前设备第%s号端口发生故障: %s" % (port, faultContent)
- if self.event_data.get("FaultCode") == "04":
- self.notify_dealer(
- templateName="device_fault",
- title="注意!设备火警预告!",
- device=u"{groupNumber}组-{logicalCode}".format(groupNumber=self.device["groupNumber"],
- logicalCode=self.device["logicalCode"]),
- location=u"{address}-{groupName}".format(address=group["address"], groupName=group["groupName"]),
- fault=faultContent,
- notifyTime=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- )
- self.record(
- faultCode=self.event_data.get("FaultCode"),
- description=faultContent,
- title="注意!设备火警预告!",
- # detail=self.event_data.get("statusInfo"),
- )
- elif self.event_data.get("FaultCode") == "01":
- self.notify_dealer(
- templateName="device_fault",
- title="注意!非法充电警告!",
- device=u"{groupNumber}组-{logicalCode}".format(groupNumber=self.device["groupNumber"],
- logicalCode=self.device["logicalCode"]),
- location=u"{address}-{groupName}".format(address=group["address"], groupName=group["groupName"]),
- fault=faultContent,
- notifyTime=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- )
- self.record(
- faultCode=self.event_data.get("FaultCode"),
- description=faultContent,
- title="注意!非法充电警告!",
- )
- # 端口管理页面需要看到非法充电端口的端口状态,所以需要在非法充电信息报上来的时候将状态记录到缓存中
- if port:
- portInfo = {
- "port": str(int(port)),
- "billingType": "faultCharge",
- "startTime" : datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
- "statusErrorInfo": "非法充电"
- }
- Device.update_port_control_cache(self.device.devNo,portInfo)
- else:
- self.notify_dealer(
- templateName="device_fault",
- title="注意!您的设备当前发生故障!",
- device=u"{groupNumber}组-{logicalCode}".format(groupNumber=self.device["groupNumber"],
- logicalCode=self.device["logicalCode"]),
- location=u"{address}-{groupName}".format(address=group["address"], groupName=group["groupName"]),
- fault=faultContent,
- notifyTime=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- )
- self.record(
- faultCode=self.event_data.get("FaultCode"),
- description=faultContent,
- title="注意!您的设备当前发生故障!",
- # detail=self.event_data.get("statusInfo"),
- )
- class LVZHIOnline(WorkEvent):
- def do(self, **args):
- ctrInfo = Device.get_dev_control_cache(self.device.devNo)
- if ctrInfo:
- for k , v in ctrInfo.items():
- if isinstance(v,dict):
- if 'statusErrorInfo' in v:
- if v['statusErrorInfo'] == "非法充电":
- Device.clear_port_control_cache(self.device.devNo, str(k))
|