# -*- coding: utf-8 -*- # !/usr/bin/env python import logging from mongoengine import DoesNotExist from apilib.monetary import RMB, VirtualCoin from apilib.utils_datetime import to_datetime from apps.web.constant import Const, DEALER_CONSUMPTION_AGG_KIND from apps.web.device.models import Device, Group from apps.web.eventer.base import WorkEvent from apps.web.eventer import EventBuilder from apps.web.south_intf.platform import notify_event_to_north from apps.web.user.models import ServiceProgress, UserVirtualCard, VCardConsumeRecord, Card, MyUser, CardRechargeOrder logger = logging.getLogger(__name__) class builder(EventBuilder): def __getEvent__(self, device_event): event_data = self.deviceAdapter.analyze_event_data(device_event['data']) if not event_data 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 ['86', '8B', '8C', '8D']: return ChargingHaiNiaoSingleNewWorkEvent(self.deviceAdapter, event_data) class ChargingHaiNiaoSingleNewWorkEvent(WorkEvent): def support_playback(self): return self.event_data['cmdCode'] == '86' def do(self, **args): devNo = self.device['devNo'] logger.info('hainiaoSingle charging event detected, devNo=%s, curInfo=%s' % (devNo, self.event_data)) if self.event_data['cmdCode'] == '86': port = self.event_data['port'] reason = self.event_data['reason'] cardNo = self.event_data['cardNo'] try: lineInfo = Device.clear_port_control_cache(self.device['devNo'], str(port)) recvTime = to_datetime(self.recvTime) # 为-1的时候就是没有 deviceDuration = self.event_data.get('duration', -1) if lineInfo is not None and 'startTime' in lineInfo: startTime = to_datetime(lineInfo['startTime']) if startTime > recvTime: serverDuration = 0 else: serverDuration = int(round(((recvTime - startTime).total_seconds() / 60.0))) # 为-1的时候就是没有 else: serverDuration = -1 if deviceDuration > 0: usedTime = deviceDuration else: usedTime = serverDuration needPrice = RMB(lineInfo['needPrice']) leftPrice = RMB(self.event_data['leftPrice']) leftTime = self.event_data['leftTime'] leftTimeStr = str(leftTime) actualNeedTime = usedTime + leftTime group = Group.get_group(self.device['groupId']) consumeDict = {'reason': reason, 'leftTime': leftTimeStr, 'chargeIndex': port, 'duration': usedTime} # 如果是刷卡的,直接更新消费记录,然后发送通知消息,不支持退费 if cardNo: card = Card.objects(cardNo = cardNo, agentId = self.dealer.agentId).first() if not self.device.is_auto_refund: ServiceProgress.update_progress_and_consume_rcd(self.device['ownerId'], {'open_id': lineInfo['openId'], 'port': 1, 'device_imei': self.device['devNo'], 'isFinished': False}, consumeDict) return backCoins = leftPrice if backCoins > needPrice: backCoins = needPrice self.refund_money_for_card(backCoins, str(card.id)) consumeDict.update( {DEALER_CONSUMPTION_AGG_KIND.REFUND_CARD: backCoins.mongo_amount}) ServiceProgress.update_progress_and_consume_rcd(self.device['ownerId'], {'open_id': lineInfo['openId'], 'port': 1, 'device_imei': self.device['devNo'], 'isFinished': False}, consumeDict) elif lineInfo.has_key('consumeRcdId'): backCoins = leftPrice vCardId = '' try: vCardId = lineInfo['vCardId'] vCard = UserVirtualCard.objects.get(id = vCardId) except DoesNotExist, e: logger.info('can not find the vCard id = %s' % vCardId) return ServiceProgress.update_progress_and_consume_rcd(self.device['ownerId'], {'open_id': lineInfo['openId'], 'port': int(port), 'device_imei': self.device['devNo'], '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) return vCard.refund_quota(vCardConsumeRcd, usedTime, 0.0, backCoins.mongo_amount) elif 'openId' in lineInfo and lineInfo['openId']: user = MyUser.objects(openId = lineInfo.get('openId', ''), groupId = self.device['groupId']).first() # 通知服务结束 self.notify_user(user.managerialOpenId if user else '', 'service_complete', **{ 'title': u'%s' % reason, 'service': u'充电服务(设备编号:%s, 端口:%s,地址:%s)' % ( self.device['logicalCode'], port, group['address']), 'finishTime': recvTime.strftime('%Y-%m-%d %H:%M:%S'), 'remark': u'谢谢您的支持' }) # 如果需要退款,计算退款数据. if not self.device.is_auto_refund: ServiceProgress.update_progress_and_consume_rcd(self.device['ownerId'], {'open_id': lineInfo['openId'], 'port': int(port), 'device_imei': self.device['devNo'], 'isFinished': False}, consumeDict) return minConsumptionLimit = self.device.my_obj.otherConf.get('minConsumptionLimit', 0) tempMoneyNum = float(needPrice) - float(minConsumptionLimit) if tempMoneyNum < 0: tempMoneyNum = 0 backCoins = leftPrice if backCoins > needPrice: backCoins = needPrice if float(backCoins) >= tempMoneyNum: backCoins = RMB(tempMoneyNum) # 直接退现金 if RMB(0) < backCoins <= needPrice: self.refund_net_pay(user, lineInfo, backCoins, VirtualCoin(0), consumeDict, True) refund = RMB(consumeDict.get(DEALER_CONSUMPTION_AGG_KIND.REFUNDED_CASH, '0.00')) if refund > RMB(0): self.notify_user(user.managerialOpenId if user else '', 'refund_coins', **{ 'title': reason, 'backCount': u'%s元' % refund, 'finishTime': recvTime.strftime('%Y-%m-%d %H:%M:%S') }) ServiceProgress.update_progress_and_consume_rcd(self.device['ownerId'], {'open_id': lineInfo['openId'], 'port': int(port), 'device_imei': self.device['devNo'], 'isFinished': False}, consumeDict) else: logger.debug('other start device mode.') finally: notify_event_to_north(self.dealer, self.device, level = Const.EVENT_NORMAL, desc = reason) if self.event_data['cmdCode'] == '8B': cardNo = self.event_data['cardNo'] card = self.update_card_dealer_and_type(cardNo) if not card: self.deviceAdapter.ack_query_card_balance(cardNo, 0) return 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() self.deviceAdapter.ack_query_card_balance(cardNo, card.balance) Device.update_dev_control_cache(self.device.devNo, {'1': {'wait8CCardNo': cardNo}}) if self.event_data['cmdCode'] == '8C': cardNo = self.event_data['cardNo'] operFee = RMB(self.event_data['operFee']) wait8C = Device.get_dev_control_cache(self.device['devNo']).get('1', {}) if wait8C.get('wait8CCardNo', '') != cardNo: self.deviceAdapter.ack_consume_card(cardNo, 0, '00') return Device.update_dev_control_cache(self.device.devNo, {'1': {'wait8CCardNo': ''}}) card = self.update_card_dealer_and_type(cardNo) if not card: self.deviceAdapter.ack_consume_card(cardNo, 0, '00') return if card.openId == '' or card.frozen: self.deviceAdapter.ack_consume_card(cardNo, card.balance, '01') return if card.balance < operFee: self.deviceAdapter.ack_consume_card(cardNo, card.balance, '02') return orderNo, cardOrderNo = self.record_consume_for_card(card, operFee) ServiceProgress.register_card_service(self.device, 1, card, { 'orderNo': orderNo, 'money': self.event_data['operFee'], 'coin': self.event_data['operFee'], 'needTime': 0, 'cardOrderNo': cardOrderNo }) self.consume_money_for_card(card, operFee) self.deviceAdapter.ack_consume_card(cardNo, card.balance, '55') Device.update_dev_control_cache(self.device.devNo, {'1': {'needPrice': operFee, 'consumeType': 'card', 'cardNo': cardNo}}) if self.event_data['cmdCode'] == '8D': hexUrl = self.event_data['hexUrl'] self.deviceAdapter.init_device_QR_code(hexUrl)