# -*- coding: utf-8 -*- # !/usr/bin/env python import logging from mongoengine import DoesNotExist from apilib.monetary import RMB 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 import EventBuilder from apps.web.eventer.base import WorkEvent 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 ChargingHaiNiaoNewWorkEvent(self.deviceAdapter, event_data) return None class ChargingHaiNiaoNewWorkEvent(WorkEvent): def support_playback(self): return self.event_data['cmdCode'] == '86' def do(self, **args): devNo = self.device['devNo'] logger.info('hainiao new 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'] leftTime = self.event_data['leftTime'] if reason == u'成功!': return try: lineInfo = Device.clear_port_control_cache(self.device['devNo'], str(port)) recvTime = to_datetime(self.recvTime) 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']) if startTime > recvTime: # 如果web服务器时间和事件监控服务器时间不一致,导致开始时间比事件时间还大 usedTime = 0 else: usedTime = int(round(((recvTime - startTime).total_seconds() / 60.0))) needTime = lineInfo['needTime'] if usedTime > needTime: usedTime = needTime elec = self.event_data['elec'] group = Group.get_group(self.device['groupId']) consumeDict = {'reason': reason, 'chargeIndex': port, 'duration': usedTime, 'elec': elec} # 如果是刷卡的,直接更新消费记录,然后发送通知消息,不支持退费 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'): coins = RMB(lineInfo['coins']) backCoins = coins * (float(leftTime) / float(needTime)) 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['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 coins = RMB(lineInfo['coins']) backCoins = coins * (float(leftTime) / float(needTime)) # 直接退现金 if RMB(0) < backCoins <= coins: self.refund_net_pay(user, lineInfo, backCoins, backCoins, 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)