# -*- coding: utf-8 -*- import datetime import logging from mongoengine import DoesNotExist, ValidationError from typing import TYPE_CHECKING from apps.web.constant import USER_RECHARGE_TYPE from apps.web.core.payment import WithdrawGateway from apps.web.device.models import Group from apps.web.report.ledger import Ledger from apps.web.user.models import Card, RechargeRecord if TYPE_CHECKING: from apps.web.device.models import DeviceDict logger = logging.getLogger(__name__) class CYConstant(object): FINISH_REASON_MAP = { '01': '充满电停止', '02': '超功率停止', '03': '时间用完停止', '04': '远程停止', '05': '预付卡的扣费金额用完', '06': '到达安全充电时间', '07': '正常结束充电', '09': '电量超限', '10': '设备充满停止充电' } NEED_REFUND = ["01", "04", "05", "06", "07", "10"] DEFAULT_DISCOUNT = "0" REFUND_PRODUCTION_TIME = 5 MAX_TEMPERATURE = 70 MIN_TEMPERATURE = -15 class FunCode(object): # 发送设备事件 GET_SETTING = "A0" SET_SETTING = "A1" GET_DEV_INFO = "A2" CLEAN_DEV_INFO = "A3" REFUND_RECORD = "A4" CHARGE_RECORD = "A5" CHECK_DEV_STATUS = "A6" WEIXIN_PAY_START = "A7" START_OR_STOP = "A9" CARD_RECHARGR = "AC" CARD_BALANCE = "AD" STOP_DEV = "AF" RESTART = "B0" class CmdCode(object): # 设备上报事件 CARD_REFUND = "B3" STOP_DEV = "A8" DEV_CONNECTED = "AE" CARD_PAY_START = "B1" HEART_BEAT = "B2" class CYCardMixin(object): if TYPE_CHECKING: @property def device(self): # type:()->DeviceDict return DeviceDict() def notify_dealer(self, templateName, **kwargs): pass def check_card_can_use(self, card): # type:(Card) -> bool """ 对于平台卡检验 的判定 返回结果是可用或者不可用 注意: 卡是否录入是以经销商录入为标准判定 规则是: 1.如果校验开关关闭 则都是可用的 2.如果校验开关打开 卡录入情况下可用 卡没有录入的情况下不可用 """ needBindCard = self.device.otherConf.get("needBindCard", True) if not needBindCard: return True # 剩下的是需要检验的情况 # 1. 没有绑定 if not card: return False # 2. 解除了绑定(经销商绑定的卡会通过检验 经销商绑定的卡是 匿名用户的openId) if not card.openId: return False # 3. 卡被冻结 if card.frozen: return False # 4. 地址不通用的情况 if not Group.is_currency_mode_group(card.groupId, self.device.groupId): return False return True def update_card_dealer_and_type(self, cardNo, cardType='IC', isHaveBalance=True, balance=None): """ 从数据库找卡 主要功能是为没有卡类型的卡添加上卡的类型 昌原的卡比较特别 如果是数据库的卡 一定会有dealerId """ from apps.web.agent.models import Agent dealer = self.device.owner agent = Agent.objects(id = dealer.agentId).first() # type: Agent if not agent: logger.error('agent is not found, agentId=%s' % dealer.agentId) return None try: card = Card.objects.get(cardNo=cardNo, agentId=str(agent.id)) # 存在卡的类型 说明已经在数据库中了 if card.cardType: return card card.devNo = card.devNo or self.device.devNo card.cardType = card.cardType or cardType card.isHaveBalance = isHaveBalance return card.save() except DoesNotExist: return None except Exception as e: logger.error("[CYCardMixin update_card_dealer_and_type] find card error = {}, dev = {}".format(e, self.device.devNo)) return None def notify_invalid_card_to_dealer(self, cardNo, card): logger.info('[CYCardMixin notify_invalid_card_to_dealer] Illegal card <{}>, charging is about to stop'.format(cardNo)) self.notify_dealer( 'device_fault', title=u'您当前的设备已被非法卡使用!', device=u'设备{}-{}'.format(self.device.logicalCode, self.device.groupNumber), location=u'地址{}-{}'.format(self.device.group.address, self.device.group.groupName), fault="启动卡号为:{} 卡联系人 {} 卡联系电话 {}".format( cardNo, card.nickName if card else "", card.phone if card else "" ), notifyTime=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') ) def do_ledger(self, rechargeRcdId): logger.info("[{} do_ledger] rechargeId = {}, devNo= {}".format(self.__class__.__name__, rechargeRcdId, self.device.devNo)) if not rechargeRcdId: return record = RechargeRecord.objects(id = rechargeRcdId).first() # type: RechargeRecord if not record: logger.error("dev <{}> don't get a recharge record by id <{}>".format(self.device.devNo, rechargeRcdId)) return if not record.is_success: logger.debug('{} state is {}.'.format(str(record), record.result)) raise ValueError(u'订单不能为未支付状态') try: if record.is_ledgered: logger.debug('{} has been ledgered.'.format(str(record))) return record ledgerTime = None if ( not WithdrawGateway.is_ledger(record.withdraw_source_key)) else datetime.datetime.now() ledger = Ledger(USER_RECHARGE_TYPE.RECHARGE, record, ledgerTime=ledgerTime) ledger.execute(stats=True) except DoesNotExist as de: logger.error("dev <{}> don't get a recharge record by id <{}>".format(self.device.devNo, rechargeRcdId)) return except ValidationError as ve: logger.error("dev <{}> bad a recharge record id <{}>".format(self.device.devNo, rechargeRcdId)) return except Exception as e: logger.exception(e) return # 执行分账成功的情况下 将充值订单返回 return record