# -*- 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 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 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']: return ChargingHaiNiaoDoubleWorkEvent(self.deviceAdapter, event_data) class ChargingHaiNiaoDoubleWorkEvent(WorkEvent): def support_playback(self): return self.event_data['cmdCode'] == '86' def do(self, **args): devNo = self.device['devNo'] logger.info('hainiaoDouble 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'] if reason == '': return 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 leftPrice = RMB(self.event_data['leftPrice']) leftTime = self.event_data['leftTime'] leftTimeStr = str(leftTime) actualNeedTime = usedTime + leftTime group = self.device.group consumeDict = {'reason': reason, 'leftTime': leftTimeStr, 'chargeIndex': port, 'duration': usedTime} # 如果是刷卡的,直接更新消费记录,然后发送通知消息,不支持退费 if lineInfo.has_key('cardNo'): card = Card.objects(cardNo = lineInfo['cardNo'], agentId = self.dealer.agentId).first() consumeDict.update({'balance': lineInfo['balance']}) ServiceProgress.update_progress_and_consume_rcd(self.device['ownerId'], {'open_id': lineInfo['openId'], 'port': int(port), '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) else: user = MyUser.objects(openId = lineInfo.get('openId', ''), groupId = self.device['groupId']).first() if not user: logger.warning('no user, devNo=%s' % devNo) return # 通知服务结束 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 needPrice = RMB(lineInfo['needPrice']) 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) finally: notify_event_to_north(self.dealer, self.device, level = Const.EVENT_NORMAL, desc = reason)