123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348 |
- # -*- coding: utf-8 -*-
- # !/usr/bin/env python
- import datetime
- import logging
- from apilib.monetary import RMB, VirtualCoin
- from apps import serviceCache
- from apps.web.constant import Const, DEALER_CONSUMPTION_AGG_KIND
- from apps.web.core.device_define.water_despenser import CMD_CODE
- from apps.web.dealer.models import Dealer
- 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, MyUser
- from taskmanager.mediator import task_caller
- 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 event_data['cmdCode'] == CMD_CODE.WATER_DISPENSE_ALERT_EVENT_CODE:
- return WaterDispenserAlertEvent(self.deviceAdapter, event_data)
- if event_data['cmdCode'] in [
- CMD_CODE.WATER_DISPENSE_SETTING_EVENT_CODE,
- CMD_CODE.WATER_DISPENSE_WORK_STATUS_EVENT_CODE,
- CMD_CODE.WATER_DISPENSE_FINISH_EVENT_CODE
- ]:
- return WaterDispenserWorkEvent(self.deviceAdapter, event_data)
- class WaterDispenserAlertEvent(WorkEvent):
- def do(self, **args):
- def _send_alert_message_to_dealer(dealer, group, fault):
- notifyData = {
- 'title': '设备故障',
- 'device': u'{gNum}组-{lc}'.format(gNum=self.device['groupNumber'], lc=self.device['logicalCode']),
- 'location': u'{address}-{groupName}'.format(address=group['address'], groupName=group['groupName']),
- 'fault': fault,
- 'notifyTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
- }
- task_caller(
- func_name='report_to_dealer_via_wechat',
- openId=dealer.managerialOpenId,
- dealerId=str(dealer.id),
- templateName='device_fault',
- **notifyData
- )
- devNo = self.device['devNo']
- logger.info('water dispenser event detected, devNo=%s, curInfo=%s' % (devNo, self.event_data))
- if self.event_data['eventKey'] != '00':
- pass
- else:
- if self.event_data['isError'] is True:
- group = Group.objects(id=self.device['groupId']).first()
- dealer = Dealer.objects(id=self.device['ownerId']).first()
- portStatus = {}
- temp = []
- if self.event_data['noWater'] is True:
- temp.append('noWater')
- if self.event_data['moreWater'] is True:
- temp.append('moreWater')
- if self.event_data['port1Leak'] is True:
- temp.append('port1Leak')
- if self.event_data['port2Leak'] is True:
- temp.append('port2Leak')
- if self.event_data['port1Error'] is True:
- temp.append('port1Error')
- if self.event_data['port2Error'] is True:
- temp.append('port2Error')
- cache_key = ''
- fault = u''
- statusErrorInfo1 = u''
- statusErrorInfo2 = u''
- # 遍历temp, 然后更新数据
- for _ in temp:
- cache_key += _
- portStatus = {
- '1': {'status': Const.DEV_WORK_STATUS_IDLE, 'statusErrorInfo': u'无'},
- '2': {'status': Const.DEV_WORK_STATUS_IDLE, 'statusErrorInfo': u'无'}
- }
- if 'noWater' == _:
- statusErrorInfo1 += u'水箱缺液'
- statusErrorInfo2 += u'水箱缺液'
- portStatus['1'].update({'statusErrorInfo': statusErrorInfo1})
- portStatus['2'].update({'statusErrorInfo': statusErrorInfo2})
- fault = u'水箱缺液!'
- if 'moreWater' == _:
- statusErrorInfo1 = statusErrorInfo1 + u' ' + u'水箱溢流'
- statusErrorInfo2 = statusErrorInfo2 + u' ' + u'水箱溢流'
- portStatus['1'].update({'statusErrorInfo': statusErrorInfo1})
- portStatus['2'].update({'statusErrorInfo': statusErrorInfo2})
- fault = fault + u' ' + u'水箱溢流!'
- if 'port1Leak' == _:
- statusErrorInfo1 = statusErrorInfo1 + u' ' + u'漏水'
- portStatus['1'].update({'statusErrorInfo': statusErrorInfo1})
- fault = fault + u' ' + u'通道1漏水!'
- if 'port2Leak' == _:
- statusErrorInfo2 = statusErrorInfo2 + u' ' + u'漏水'
- portStatus['2'].update({'statusErrorInfo': statusErrorInfo2})
- fault = fault + u' ' + u'通道2漏水!'
- if 'port1Error' == _:
- statusErrorInfo1 = statusErrorInfo1 + u' ' + u'电磁阀故障'
- portStatus['1'].update({'statusErrorInfo': statusErrorInfo1})
- portStatus['1'].update({'status': Const.DEV_WORK_STATUS_FAULT})
- fault = fault + u' ' + u'通道1电磁阀故障!'
- if 'port2Error' == _:
- statusErrorInfo2 = statusErrorInfo2 + u' ' + u'电磁阀故障'
- portStatus['2'].update({'statusErrorInfo': statusErrorInfo2})
- portStatus['2'].update({'status': Const.DEV_WORK_STATUS_FAULT})
- fault = fault + u' ' + u'通道2电磁阀故障!'
- jsjCache = serviceCache.get(dealer.username + '_jsj', 0)
- jsjData = dealer.username + '_' + cache_key
- if jsjCache == 0:
- _send_alert_message_to_dealer(dealer, group, fault)
- serviceCache.set(dealer.username + '_jsj', jsjData, 60 * 60)
- else:
- if jsjCache == jsjData:
- pass
- else:
- _send_alert_message_to_dealer(dealer, group, fault)
- serviceCache.set(dealer.username + '_jsj', jsjData, 60 * 60)
- Device.update_dev_control_cache(devNo, {'deviceId': self.event_data['deviceId']})
- Device.update_dev_control_cache(devNo, portStatus)
- else:
- portStatus = {
- '1': {'status': Const.DEV_WORK_STATUS_IDLE, 'statusErrorInfo': u'无'},
- '2': {'status': Const.DEV_WORK_STATUS_IDLE, 'statusErrorInfo': u'无'}
- }
- ctrlInfo = Device.get_dev_control_cache(devNo)
- if ctrlInfo.get('1', None) is not None and ctrlInfo.get('2', None) is not None:
- if ctrlInfo['1'].get('status', '') == 3:
- portStatus.update({'1': {'status': Const.DEV_WORK_STATUS_FORBIDDEN, 'statusErrorInfo': u'无'}})
- if ctrlInfo['2'].get('status', '') == 3:
- portStatus.update({'2': {'status': Const.DEV_WORK_STATUS_FORBIDDEN, 'statusErrorInfo': u'无'}})
- Device.update_dev_control_cache(devNo, {'deviceId': self.event_data['deviceId']})
- Device.update_dev_control_cache(devNo, portStatus)
- class WaterDispenserWorkEvent(WorkEvent):
- def calc_backCoins(self, reason, need, left, coins):
- device = Device.objects(logicalCode=self.device['logicalCode']).first()
- minConsumeRatio = device.otherConf.get('minConsumeRatio', 5)
- minConsumeTime = int(need * (float(minConsumeRatio) / 100))
- staticMinConsumeTime = int(need * 0.95)
- if left > need:
- backCoins = RMB('0.0')
- else:
- if reason in ['01', '05']:
- if (float(left) / float(need)) > (float(staticMinConsumeTime) / float(need)):
- backCoins = coins
- else:
- if (need - left) > minConsumeTime:
- backCoins = coins * (float(left) / float(need))
- else:
- backCoins = coins * (1 - float(minConsumeRatio) / 100)
- elif reason == '04':
- if (need - left) > minConsumeTime:
- backCoins = coins * (float(left) / float(need))
- else:
- backCoins= coins * (1-float(minConsumeRatio) / 100)
- elif reason == '06':
- if (float(left) / float(need)) > (float(staticMinConsumeTime) / float(need)):
- backCoins = coins
- else:
- backCoins = coins * (float(left) / float(need))
- elif reason in ['03']:
- backCoins = coins
- elif reason in ['02', '08', '09']:
- backCoins = coins * (float(left) / float(need))
- elif reason in ['07']:
- backCoins = RMB('0.0')
- else:
- backCoins = RMB('0.0')
- return backCoins
- def do(self, **args):
- devNo = self.device['devNo']
- logger.info('WaterDispenser event detected, devNo=%s, curInfo=%s' % (devNo, self.event_data))
- if self.event_data['cmdCode'] == CMD_CODE.WATER_DISPENSE_SETTING_EVENT_CODE:
- boardSoftVer = self.event_data['boardSoftVer']
- return self.deviceAdapter.init_dev_settings(boardSoftVer)
- if self.event_data['cmdCode'] == CMD_CODE.WATER_DISPENSE_WORK_STATUS_EVENT_CODE:
- Device.update_dev_control_cache(devNo, {str(self.event_data['port']): {'isPause': False if self.event_data['isPause'] == '02' else True}})
- return
- if self.event_data['cmdCode'] == CMD_CODE.WATER_DISPENSE_FINISH_EVENT_CODE:
- port = self.event_data['port']
- reason = self.event_data['reason']
- try:
- ctrInfo = Device.get_dev_control_cache(self.device['devNo'])
- lineInfo = ctrInfo.get(port)
- coins = lineInfo['coins']
- refundedMoney = RMB('0.0')
- refundCoins = VirtualCoin('0.0')
- consumeDict = {}
- reasonDesc = self.event_data['desc']
- reasonCode = self.event_data['reason']
- agentId = Dealer.objects(id=self.device['ownerId']).first().agentId
- users = MyUser.objects(openId=lineInfo['openId'], agentId=agentId)
- for _ in users:
- breakRuleTimes = _.blacklistConfig.get('breakRuleTimes', 0)
- if reasonCode in ['08', '09']:
- breakRuleTimes += 1
- if breakRuleTimes > 3:
- breakRuleTimes = 3
- else:
- breakRuleTimes -= 1
- if breakRuleTimes < 0:
- breakRuleTimes = 0
- _.blacklistConfig['breakRuleTimes'] = breakRuleTimes
- _.save()
- # 计时
- if lineInfo['consumeMode'] == '1':
- usedTime = self.event_data['duration']
- needTime = lineInfo['needTime']
- leftTime = needTime - usedTime
- consumeDict = {'reason': reasonDesc, 'desc': reasonDesc, 'chargeIndex': port, 'duration': usedTime}
- group = Group.get_group(self.device['groupId'])
- user = MyUser.objects(openId=lineInfo['openId'], groupId=self.device['groupId']).first()
- # 通知服务结束
- self.notify_user(user.managerialOpenId if user else '', 'service_complete',
- **{
- 'title': u'%s' % reasonDesc,
- 'service': u'设备服务(设备编号:%s, 端口:%s,地址:%s)' % (
- self.device['logicalCode'], port, group['address']),
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- 'remark': u'谢谢您的支持'
- })
- ServiceProgress.update_progress_and_consume_rcd(self.device['ownerId'],
- {'open_id': lineInfo['openId'],
- 'port': int(port),
- 'device_imei': self.device['devNo'],
- 'isFinished': False}, consumeDict)
- backCoins = self.calc_backCoins(reason, needTime, leftTime, RMB(lineInfo['coins']))
- refundedMoney = backCoins
- refundCoins = backCoins
- consumeDict.update({'refundedMoney': refundedMoney})
- isRefund = True
- # 计量
- elif lineInfo['consumeMode'] == '2':
- usedLitre = self.event_data['spendLitre']
- needLitre = lineInfo['needLitre']
- leftLitre = needLitre - usedLitre
- consumeDict = {'reason': reasonDesc, 'desc': reasonDesc, 'chargeIndex': port,
- 'usedLitre': usedLitre}
- group = Group.get_group(self.device['groupId'])
- user = MyUser.objects(openId=lineInfo['openId'], groupId=self.device['groupId']).first()
- # 通知服务结束
- self.notify_user(user.managerialOpenId if user else '', 'service_complete',
- **{
- 'title': u'%s' % reasonDesc,
- 'service': u'设备服务(设备编号:%s, 端口:%s,地址:%s)' % (
- self.device['logicalCode'], port, group['address']),
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- 'remark': u'谢谢您的支持'
- })
- ServiceProgress.update_progress_and_consume_rcd(self.device['ownerId'],
- {'open_id': lineInfo['openId'],
- 'port': int(port),
- 'device_imei': self.device['devNo'],
- 'isFinished': False}, consumeDict)
- backCoins = self.calc_backCoins(reason, needLitre, leftLitre, RMB(lineInfo['coins']))
- refundedMoney = backCoins
- refundCoins = backCoins
- consumeDict.update({'refundedMoney': refundedMoney})
- isRefund = True
- else:
- user = None
- group = None
- isRefund = False
- if self.device.is_auto_refund is True and isRefund is True:
- is_cash = False
- if 'refundRMB_device_event' in self.device.owner.features and refundedMoney > RMB(0):
- is_cash = True
- consumeDict.update({DEALER_CONSUMPTION_AGG_KIND.COIN: VirtualCoin(coins).mongo_amount})
- if refundedMoney > RMB(0) or refundCoins > VirtualCoin(0):
- consumeDict.update(
- {DEALER_CONSUMPTION_AGG_KIND.COIN: (VirtualCoin(coins) - refundCoins).mongo_amount})
- self.refund_net_pay(user, lineInfo, refundedMoney, refundCoins, consumeDict, is_cash)
- ServiceProgress.update_progress_and_consume_rcd(self.device['ownerId'],
- {'open_id': lineInfo['openId'], 'port': int(port),
- 'device_imei': self.device['devNo'],
- 'isFinished': False}, consumeDict)
- extra = []
- price = RMB(lineInfo['price'])
- coins = VirtualCoin(coins)
- if DEALER_CONSUMPTION_AGG_KIND.REFUNDED_CASH in consumeDict:
- real_refund = RMB(consumeDict[DEALER_CONSUMPTION_AGG_KIND.REFUNDED_CASH])
- if real_refund > RMB(0):
- extra.append({u'消费金额': '{}(元)'.format(RMB(price) - real_refund)})
- extra.append({u'退款金额': '{}(元)'.format(real_refund)})
- else:
- extra.append({u'消费金额': '{}(元)'.format(price)})
- elif DEALER_CONSUMPTION_AGG_KIND.REFUNDED_COINS in consumeDict:
- real_refund = VirtualCoin(consumeDict[DEALER_CONSUMPTION_AGG_KIND.REFUNDED_COINS])
- if real_refund > VirtualCoin(0):
- extra.append({u'消费金额': '{}(金币)'.format(VirtualCoin(coins) - real_refund)})
- extra.append({u'退款金额': '{}(金币)'.format(real_refund)})
- else:
- extra.append({u'消费金额': '{}(金币)'.format(VirtualCoin(coins))})
- else:
- extra.append({u'消费金额': '{}(金币)'.format(VirtualCoin(coins))})
- self.notify_user_service_complete(
- service_name='服务完成',
- openid=user.managerialOpenId if user else '',
- port=port,
- address=group['address'],
- reason=reasonDesc,
- finished_time=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- extra=extra)
- finally:
- Device.clear_port_control_cache(devNo, str(port))
- notify_event_to_north(self.dealer, self.device, level=Const.EVENT_NORMAL, desc=reason)
|