# -*- coding: utf-8 -*- # !/usr/bin/env python import datetime import logging from typing import TYPE_CHECKING from apilib.monetary import VirtualCoin from apps.web.constant import ErrorCode, Const, DeviceErrorCodeDesc from apps.web.device.models import Group, Device from apps.web.eventer import EventBuilder from apps.web.eventer.base import AckEvent from apps.web.user.models import ConsumeRecord from apps.web.user.utils import freeze_user_balance, clear_frozen_user_balance, recover_user_frozen_balance if TYPE_CHECKING: pass logger = logging.getLogger(__name__) class builder(EventBuilder): def __getEvent__(self, device_event): # type:(dict)->PulseAckEvent if 'order_id' not in device_event or 'order_type' not in device_event: logger.error('order info is not complete.') return None if device_event['order_type'] != 'pulse_start': logger.error('order type<{}> is not match.'.format(device_event['order_type'])) return None return PulseAckEvent(self.deviceAdapter, device_event) class PulseAckEvent(AckEvent): """ 脉冲设备订单状态只可能是created, timeout, finished """ def do_impl(self, **args): order_id = self.event_data['order_id'] order = ConsumeRecord.objects(ownerId = self.device.ownerId, orderNo = order_id).first() # type: ConsumeRecord if not order: logger.debug('order is not exist.'.format(self.event_data['order_id'])) return if order.status == 'finished': logger.debug('order<{}> has been fished.'.format(repr(order))) return if order.used_port != self.event_data['port']: logger.error('port is not equal. {} != {}'.format(self.event_data['port'], order.used_port)) return if self.event_data['rst'] == ErrorCode.DEVICE_SUCCESS: consume_dict = order.my_package.initial_consume_dict consume_dict.update({'refundedMoney': 0}) if order.status == 'timeout': freeze_user_balance(self.device, Group.get_group(order.groupId), order) # 补充扣款 err_desc = u'事件上报成功,补充扣款' else: err_desc = 'success' clear_frozen_user_balance(self.device, order, consume_dict['duration'], 0, VirtualCoin(0)) start_ts = self.event_data['sts'] finished_ts = start_ts + consume_dict['duration'] * 60 # 设置订单执行完成 order.status = 'finished' order.isNormal = True order.errorDesc = err_desc order.startTime = datetime.datetime.fromtimestamp(start_ts) order.finishedTime = datetime.datetime.fromtimestamp(finished_ts) order.save() # 处理缓存 try: control_cache = Device.get_dev_control_cache(self.device.devNo) if not control_cache or 'startTime' not in control_cache or control_cache[ 'startTime'] < order.startTime.strftime(Const.DATETIME_FMT): Device.update_dev_control_cache(self.device.devNo, { 'status': Const.DEV_WORK_STATUS_WORKING, 'startTime': order.startTime.strftime(Const.DATETIME_FMT), 'finishedTime': finished_ts }) except Exception as e: logger.exception('error = %s' % e) # 增加统计 order.update_service_info(consume_dict) else: logger.error('order<{}> failure.'.format(repr(order))) recover_user_frozen_balance(self.device, Group.get_group(order.groupId), order) order.status = 'finished' order.isNormal = False order.finishedTime = datetime.datetime.now() order.errorDesc = DeviceErrorCodeDesc.get(self.event_data['rst']) order.save() consume_dict = { 'duration': 0, 'refundedMoney': VirtualCoin(order.coin).mongo_amount } order.update_service_info(consume_dict)