# -*- coding: utf-8 -*- # !/usr/bin/env python import base64 import datetime import logging import random import re import time import urlparse import uuid from collections import Counter, defaultdict from decimal import Decimal from itertools import groupby from operator import itemgetter import arrow import cytoolz import simplejson as json from bson import Regex from bson.objectid import ObjectId from dateutil.relativedelta import relativedelta from django.conf import settings from django.contrib import auth from django.contrib.auth.hashers import make_password from django.core.cache import caches from django.core.handlers.wsgi import WSGIRequest from django.http import HttpResponse from django.views.decorators.http import require_POST, require_GET from mongoengine import Q from mongoengine.errors import DoesNotExist, NotUniqueError from typing import TYPE_CHECKING, Optional, cast, Union, Dict, Mapping from voluptuous import MultipleInvalid from apilib import utils_datetime from apilib.monetary import RMB, VirtualCoin, sum_rmb from apilib.quantity import Quantity from apilib.utils import natural_sort, is_number, round_2_digits from apilib.utils_datetime import to_datetime, defaultTodayDate, dt_to_timestamp, get_zero_time, \ get_tomorrow_zero_time from apilib.utils_datetime import today_datetime_range from apilib.utils_json import JsonResponse, json_dumps from apilib.utils_mongo import format_dot_key from apilib.utils_string import cn from apilib.utils_url import add_query from apps import serviceCache, reportCache from apps.common.utils import get_start_and_end_by_month, get_start_and_end_by_year, get_date_range from apps.thirdparties.aliyun import AliyunSlider from apps.web.agent.models import Agent from apps.web.api.models import APIStartDeviceRecord from apps.web.common.models import District, DEFAULT_DEALER_FEATURES, WithdrawRecord, OperatorLog, \ MonthlyPackageTemp, WithdrawBankCard from apps.web.common.proxy import ClientRechargeModelProxy, ClientConsumeModelProxy, DealerDailyStatsModelProxy, \ GroupDailyStatsModelProxy, DeviceDailyStatsModelProxy, ClientDealerIncomeModelProxy, DealerReportModelProxy from apps.web.common.transaction import WithdrawStatus, WITHDRAW_PAY_TYPE, translate_withdraw_state from apps.web.common.transaction.pay import OrderCacheMgr, PayManager from apps.web.common.transaction.refund import RefundManager from apps.web.common.validation import NAME_RE, PHONE_NUMBER_RE from apps.web.constant import ( Const, DEALER_CONSUMPTION_AGG_KIND_TRANSLATION, DEALER_CONSUMPTION_AGG_KIND, DEALER_CONSUMPTION_AGG_KIND_UNIT, MONTH_DATE_KEY, FAULT_RECORD_STATUS, APP_TYPE, PollRecordDefine, TYPE_ADJUST_USER_VIRTUAL_CARD, DeviceCmdCode, ErrorCode, RECHARGE_CARD_TYPE, RECHARGE_RECORD_VIA_TRANSLATION, skip_package_unit_verify_list, skip_package_range_verify_list, skip_package_params_verify_list, USER_RECHARGE_TYPE, CONSUMETYPE, support_policy_weifule, support_policy_device) from apps.web.constant import RechargeRecordVia from apps.web.core import PayAppType, ROLE from apps.web.core.accounting import Accounting, devCoinTmpl from apps.web.core.auth.wechat import WechatAuthBridge from apps.web.core.bridge import WechatClientProxy from apps.web.core.db import paginate, prepare_query, search_query from apps.web.core.device_define.huopo import HuopoCacheMgr from apps.web.core.exceptions import ServiceException, InvalidParameter, ParameterError, InvalidFileSize, \ InvalidFileName, RentDeviceError from apps.web.core.file import AliOssFileUploader, SwapGroupPicFileUploader from apps.web.core.helpers import ActionDeviceBuilder from apps.web.core.messages.sms import ( dealerAutoWithdrawSMSProvider, dealerRegisterSMSProvider, dealerWithdrawSMSProvider, dealerBindWechatSMSProvider, dealerBindWalletWechatSMSProvider, dealerEditMonitorSMSProvider, dealerMonitorWithdrawSMSProvider) from apps.web.core.models import OfflineTask, WechatPayApp from apps.web.core.networking import MessageSender from apps.web.core.payment import WithdrawGateway, PaymentGateway from apps.web.core.payment.wechat import WechatPaymentGateway from apps.web.core.sysparas import SysParas from apps.web.core.utils import DefaultJsonErrorResponse, JsonErrorResponse, JsonOkResponse, parse_json_payload from apps.web.dealer import OfflineTaskType from apps.web.dealer.define import DEALER_INCOME_SOURCE, DEALER_INCOME_SOURCE_TRANSLATION, DEALER_INCOME_TYPE, \ PAY_NOTIFY_URL, DEALER_BIND_WECHAT_URL, DEALER_BIND_WALLET_WECHAT_URL from apps.web.dealer.models import ( Dealer, UpscoreRecord, DealerRechargeRecord, OnSale, OnSaleRecord, VirtualCard, ElecPriceTemplate, ItemType, SubAccount, DealerMessage, Complaint, AdjustUserVirtualCardRecord, ExchangeOrder, DealerAddr, UpCardScoreRecord, PermissionRole, PermissionRule, TodoMessage, ApiAppInfo, RefundDealerRechargeRecord) from apps.web.dealer.proxy import DealerIncomeProxy from apps.web.dealer.transaction import post_pay from apps.web.dealer.transaction_deprecated import refund_post_pay from apps.web.dealer.utils import gen_login_response, gen_home_response, gen_subaccount_login_response, \ VirtualCardBuilder, create_dealer_sim_charge_order, DealerSessionBuilder, MyToken, \ create_dealer_charge_order_for_api, create_dealer_charge_order_for_disable_ad from apps.web.dealer.validation import dealerSchema from apps.web.dealer.validator import UserListValidator from apps.web.dealer.withdraw import DealerWithdrawService from apps.web.device.define import DeviceChannelType from apps.web.device.models import Device, Group, FeedBack, DeviceType, StockRecord, Cell, FaultRecord, Part, Battery, \ GroupDict, DeviceRentOrder, GroupCacheMgr from apps.web.device.models import DeviceDict, RequestBodyDict, SwapGroup, DiscountPriceCharging, PriceCharging, \ ChargeTag, Picture from apps.web.device.timescale import SignalManager from apps.web.device.utils import device_control_cache_key from apps.web.exceptions import UserServerException from apps.web.helpers import get_wx_config, current_platform, get_app, \ get_wechat_auth_bridge, \ get_wechat_user_manager_mp_proxy, \ remove_some_desc_for_consume, get_inhourse_wechat_env_pay_gateway from apps.web.management.models import Manager from apps.web.report.models import ( DevReport, GroupReport, DealerReport, GroupDailyStat, DealerMonthlyStat, DealerDailyStat, DeviceDailyStat ) from apps.web.report.utils import ( consumption_unit_precision, to_quantity, translate_income, translate_consumption) from apps.web.south_intf.swap_carcharger import SwapContract from apps.web.south_intf.zhejiang_fire import Company from apps.web.south_intf.zhejiang_fire import handler_event_to_zhejiang from apps.web.user.models import RechargeRecord, ConsumeRecord, MyUser, CardConsumeRecord, Card, \ CardRechargeRecord, CardRechargeOrder, UserVirtualCard, ServiceProgress, VirtualCardRechargeRecord, BlackListUsers, \ SwapCardRecord, UniqueUser from apps.web.user.transaction_deprecated import refund_cash from apps.web.user.utils import check_black_user, BatteryInfo from apps.web.user.utils2 import get_paginate from apps.web.utils import (permission_required, LimitAttemptsManager, dealer_login, subAccount_login, error_tolerate, ensure_all_fields_are_not_empty, is_login, check_role, is_dealer, concat_server_end_url, ErrorResponseRedirect, FrontEndResponseRedirect, ExternalResponseRedirect, DealerBindIdResponseRedirect, ViewValidator, record_operation_behavior) from apps.web.wrapper import request_limit_by_user from library.wechatbase.exceptions import WeChatException from taskmanager.mediator import task_caller logger = logging.getLogger(__name__) merge_with = cytoolz.merge_with get_in = cytoolz.get_in if TYPE_CHECKING: from apps.web.core.db import CustomQuerySet from collections import Iterable from apps.web.core.db import Query from apps.web.common.models import UserSearchable from apps.web.core.adapter.bolai_gateway import ChargingGatewayBox from apps.web.core.adapter.bolai_node import ChargingBox from apps.web.core.adapter.huiteng import washerHTBox from apps.web.core.adapter.xiyiji import WasherBox @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer, ROLE.subaccount) def getCheckCodeForNewTel(request): # type: (WSGIRequest)->JsonResponse payload = json.loads(request.body) toNumber = payload.get('phone', None) agentId = request.user.agentId agent = Agent.get_agent(agentId) productName = agent['productName'] status, msg = dealerRegisterSMSProvider.get(phoneNumber = toNumber, productName = productName, vendor = SysParas.get_sms_vendor(request.user.smsVendor)) if not status: return JsonResponse({'result': 0, 'description': msg}) else: return JsonResponse({'result': 1, 'description': ''}) @error_tolerate(nil=DefaultJsonErrorResponse) def getCheckCode(request): # type: (WSGIRequest)->JsonResponse """ 经销商获取注册短信验证码 :param request: :return: """ payload = json.loads(request.body) toNumber = payload.get('phone', None) agentId = request.COOKIES.get('agentId', settings.MY_PRIMARY_AGENT_ID) agent = Agent.objects(id = agentId).first() # type: Agent sessionId = payload.get('csessionid', None) sig = payload.get('sig', None) token = payload.get('nc_token', None) result = eval(AliyunSlider().check_validation_results(sessionId, sig, token)) if type(result) is dict: resultCode = result.get('Code', 900) else: resultCode = 900 if resultCode == 100: status, msg = dealerRegisterSMSProvider.get(phoneNumber = toNumber, productName = agent.productName, vendor = SysParas.get_sms_vendor(agent.smsVendor)) if not status: return JsonResponse({'result': 0, 'description': msg}) else: return JsonResponse({'result': 1, 'description': ''}) else: return JsonResponse({'result': 0, 'description': u'非正常请求,验证码发送失败'}) @error_tolerate(nil=DefaultJsonErrorResponse) def verifyForgetCode(request): # type: (WSGIRequest)->JsonResponse """ 经销商验证短信验证码 :param request: :return: """ phone = request.POST.get('phone', None) code = request.POST.get('code', None) password = request.POST.get('password', "") agentId = request.POST.get('agentId') if not agentId: return JsonErrorResponse(u'未选择您对应的代理商,请刷新后再试') dealer = Dealer.objects(username=phone, agentId=agentId).first() while True: if dealer is None: response = JsonErrorResponse(u'该手机号尚未注册,请注册后再进行操作') break if password == "": response = JsonErrorResponse(u"请输入密码") break status, desc = dealerRegisterSMSProvider.verify(phone, code) if not status: response = JsonErrorResponse(desc) else: dealer.set_password(password) dealer.unlock_login() response = JsonResponse({"result": 1, "description": None, "payload": {}}) break if agentId != request.COOKIES.get('agentId'): Agent.record_cookie(agentId, response) return response @error_tolerate(nil=DefaultJsonErrorResponse) def getSubAccountCheckCode(request): # type: (WSGIRequest)->JsonResponse """ 经销商获取注册短信验证码 :param request: :return: """ payload = json.loads(request.body) toNumber = payload.get('phone', None) agentId = request.COOKIES.get('agentId', settings.MY_PRIMARY_AGENT_ID) agent = Agent.objects(id = agentId).first() # type: Agent sessionId = payload.get('csessionid', None) sig = payload.get('sig', None) token = payload.get('nc_token', None) result = eval(AliyunSlider().check_validation_results(sessionId, sig, token)) if type(result) is dict: resultCode = result.get('Code', 900) else: resultCode = 900 if resultCode == 100: status, msg = dealerRegisterSMSProvider.get(phoneNumber = toNumber, productName = agent.productName, vendor = SysParas.get_sms_vendor(agent.smsVendor)) if not status: return JsonResponse({'result': 0, 'description': msg}) else: return JsonResponse({'result': 1, 'description': ''}) else: return JsonResponse({'result': 0, 'description': u'非正常请求,验证码发送失败'}) @error_tolerate(nil=DefaultJsonErrorResponse) def verifySubAccountForgetCode(request): # type: (WSGIRequest)->JsonResponse """ 经销商验证短信验证码 :param request: :return: """ phone = request.POST.get('phone', None) code = request.POST.get('code', None) password = request.POST.get('password', "") agentId = request.POST.get('agentId') if not agentId: return JsonErrorResponse(u'未选择您对应的代理商,请刷新后再试') subaccount = SubAccount.objects(username=phone, agentId=agentId).first() while True: if subaccount is None: response = JsonErrorResponse(u'该手机号不是子账号,请主账号添加此子账号后再进行操作') break if password == "": response = JsonErrorResponse(u"请输入密码") break status, desc = dealerRegisterSMSProvider.verify(phone, code) if not status: response = JsonErrorResponse(desc) else: subaccount.set_password(password) subaccount.unlock_login() response = JsonResponse({"result": 1, "description": None, "payload": {}}) break if agentId != request.COOKIES.get('agentId'): Agent.record_cookie(agentId, response) return response @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,请稍后再试')) def getDealerRegisterSMSCode(request): # type: (WSGIRequest)->JsonResponse payload = json.loads(request.body) phoneNumber = payload.get('phoneNumber', None) agentId = request.COOKIES.get('agentId', settings.MY_PRIMARY_AGENT_ID) agent = Agent.objects(id = agentId).first() # type: Agent sessionId = payload.get('csessionid', None) sig = payload.get('sig', None) token = payload.get('nc_token', None) result = eval(AliyunSlider().check_validation_results(sessionId, sig, token)) if type(result) is dict: resultCode = result.get('Code', 900) else: resultCode = 900 if not phoneNumber: return JsonResponse({'result': 0, 'description': u'手机号码为空'}) if len(Dealer.objects.filter(username = phoneNumber, agentId = agentId)): return JsonResponse({'result': 0, 'description': u'该手机号已注册'}) if resultCode == 100: status, msg = dealerRegisterSMSProvider.get(phoneNumber = phoneNumber, productName = agent.productName, vendor = SysParas.get_sms_vendor(agent.smsVendor)) if not status: return JsonResponse({'result': 0, 'description': msg}) else: return JsonResponse({'result': 1, 'description': ''}) else: return JsonResponse({'result': 0, 'description': u'非正常请求,验证码发送失败'}) def dealerRegister(request): # type: (WSGIRequest)->JsonResponse try: rawPayload = json.loads(request.body) # type: dict mid = rawPayload.pop('managerId', None) if mid: agentId = Manager.objects.get(id=ObjectId(mid)).primeAgentId rawPayload['agentId'] = str(agentId) else: agentId = rawPayload.pop('agentId', None) if agentId: rawPayload['agentId'] = str(agentId) try: payload = dealerSchema(rawPayload) except MultipleInvalid: return JsonErrorResponse(description=u'信息填入有误,请检查手机号码等信息是否合法') agentId = rawPayload.get('agentId') agent = Agent.objects(id=agentId).first() # type: Optional[Agent] if not agent: return JsonErrorResponse(description=u'请联系您的代理商获取正确的经销商注册地址') username = payload.pop('username').strip() password = payload.pop('password').strip() if PHONE_NUMBER_RE.match(username) is None: return JsonErrorResponse(description=u'请输入正确格式的手机号码') status, msg = dealerRegisterSMSProvider.verify(phoneNumber=username, smsCode=rawPayload["code"]) if not status: return JsonErrorResponse(description=msg) payload['features'] = DEFAULT_DEALER_FEATURES try: Dealer.create_user( username = username, password = password, adShow = True, noAdPolicy = 'banner', annualTrafficCost = agent.annualTrafficCost if \ agent.annualTrafficCost > agent.trafficCardCost else agent.trafficCardCost, trafficCardCost = agent.trafficCardCost, withdrawFeeRatio = agent.withdrawFeeRatio if \ agent.withdrawFeeRatio > agent.withdrawFeeRatioCost else agent.withdrawFeeRatioCost, **payload ) except NotUniqueError: return JsonErrorResponse(description=u'该经销商已注册') except MultipleInvalid as e: logger.exception('failed to validate register dealer payload due to %s' % e) return JsonErrorResponse(description=u'部分输入不合法,请重试') except Exception as e: logger.exception('cannot register dealer due to %s' % e) return JsonErrorResponse(description=u'注册失败请重试') return JsonOkResponse() def dealerAccess(request): # type: (WSGIRequest)->JsonResponse agentId = request.GET.get('agentId', '') if not is_login(request, ROLE.dealer): response = gen_login_response(agentId) else: agent = Agent.objects(id=str(request.user.agentId)).get() if (not agentId) or (agentId == request.user.agentId) or (agentId == str(agent.primary_agent.id)): agentId = request.user.agentId response = gen_home_response(agentId) else: response = gen_login_response(agentId) return response def subAccountAccess(request): agentId = request.GET.get('agentId', '') if not is_login(request, ROLE.subaccount): response = gen_subaccount_login_response(agentId) else: agent = Agent.objects(id=str(request.user.agentId)).get() if (not agentId) or (agentId == request.user.agentId) or (agentId == str(agent.primary_agent.id)): agentId = request.user.agentId response = gen_home_response(agentId) else: response = gen_subaccount_login_response(agentId) return response def login(request): # type: (WSGIRequest)->JsonResponse username = request.POST.get('name', None) password = request.POST.get('password', None) agentId = request.POST.get('agentId') if not agentId: return JsonResponse({'result': 100, 'description': u'未选择对应的代理商,请刷新后在试', 'payload': {}}) if not all([username, password]): response = JsonResponse({'result': 0, 'description': u'缺少用户名或密码', 'payload': {}}) else: response = dealer_login(request, logger, username, password, agentId=agentId) if agentId != request.COOKIES.get('agentId', None): Agent.record_cookie(agentId, response) return response def subAccountLogin(request): username = request.POST.get('name', None) password = request.POST.get('password', None) agentId = request.POST.get('agentId') if not all([username, password]): response = JsonResponse({'result': 0, 'description': u'缺少用户名或密码', 'payload': {}}) else: response = subAccount_login(request, logger, username, password, agentId=agentId) if agentId != request.COOKIES.get('agentId', None): Agent.record_cookie(agentId, response) response.set_cookie(key='sub_account_login_agentid', value=str(agentId), max_age=24 * 3600 * 30, domain = settings.COOKIE_DOMAIN) return response @permission_required(ROLE.dealer, ROLE.subaccount) def homepageData(request): # type: (WSGIRequest)->JsonResponse currentDealer = request.user # type: Optional[Dealer, SubAccount] dealer = request.user.myBoss # type: Dealer # 显示经销商的总余额(资金池+消费分润) 分两级显示 deviceBalance = dealer.sub_balance(DEALER_INCOME_TYPE.DEVICE_INCOME) ledgerBalance = dealer.sub_balance(DEALER_INCOME_TYPE.LEDGER_CONSUME) payload = { 'totalBalance': deviceBalance + ledgerBalance, 'deviceBalance': deviceBalance, 'ledgerBalance': ledgerBalance } groupIds = Group.get_group_ids_of_dealer(str(dealer.id)) partnerGroupIds = Group.get_group_ids_of_partner(str(dealer.id)) groupIds.extend(partnerGroupIds) devList = Device.get_devices_by_group(groupIds).values() offlineCount, expireCount, allCount = 0, 0, 0 for dev in devList: # type: DeviceDict allCount += 1 if not dev.online: offlineCount += 1 if dev.is_authorized_to_dealer(str(dealer.id)) and (dev.sim_expire_notify or dev.is_expired): expireCount += 1 onlineCount = allCount - offlineCount payload.update({'onlineCount': onlineCount, 'offlineCount': offlineCount}) payload['adShow'] = currentDealer.adShow payload['feedback'] = FeedBack.get_unhandled_count(ownerId=str(dealer.id)) if expireCount > 0: payload['simCardTip'] = { 'expireCount': expireCount, 'todoMsg': TodoMessage.sim_expire_message(str(currentDealer.id), expireCount) } payload['pushBrokerUrl'] = currentDealer.pushBrokerUrl payload['isPurePartner'] = currentDealer.isPurePartner payload['inhouseApp'] = currentDealer.is_inhouse_wallet # 获取agent的相关信息 resultResponse = JsonResponse({'result': 1, 'description': None, 'payload': payload}) resultResponse = Agent.record_cookie(currentDealer.agentId, resultResponse) return resultResponse @error_tolerate(nil=JsonErrorResponse(u'上分失败,请重试')) @permission_required(ROLE.dealer, ROLE.subaccount) def onPoints(request): # type: (WSGIRequest)->JsonResponse """ 远程上分, 支持经销商和代理商进行操作,代理商通过上分测试机器系统流程正确。 :param request: :return: """ TYPE_POINTS = '' TYPE_CHARGE_CARD = 'chargeCard' def __points__(dev, ruleId): smartBox = ActionDeviceBuilder.create_action_device(dev) if dev.support_reliable: orderNo = dev.ownerId[-10:]+ConsumeRecord.make_no() order = ConsumeRecord(orderNo=orderNo, openId=dev.ownerId) order.package = dev.get('washConfig',{}).get(ruleId) order.attachParas = attachParas smartBox.start_device_realiable(order) lineInfo = {'port':attachParas.get('chargeIndex'), 'status':Const.DEV_WORK_STATUS_WORKING} Device.update_port_control_cache(dev.devNo, lineInfo) else: smartBox.start(ruleId, openId = None, attachParas = attachParas) address = Group.get_group(dev['groupId'])['address'] groupName = Group.get_group(dev['groupId'])['groupName'] score = dev.get('washConfig', {}).get(ruleId, {}).get('coins', 0) UpscoreRecord( logicalCode=dev['logicalCode'], devNo=devNo, ownerId=ownerId, time=datetime.datetime.now(), score=score, address=address, groupName=groupName, devType=dev['devType']['name'], type=TYPE_POINTS ).save() def __charge_card(dev, price): smartBox = ActionDeviceBuilder.create_action_device(dev) smartBox.remote_charge_card(price) address = Group.get_group(dev['groupId'])['address'] groupName = Group.get_group(dev['groupId'])['groupName'] UpscoreRecord( logicalCode=dev['logicalCode'], devNo=devNo, ownerId=ownerId, time=datetime.datetime.now(), score=price, address=address, groupName=groupName, devType=dev['devType']['name'], type=TYPE_CHARGE_CARD ).save() def __huopo_points(dev): ruleId = "1" smartBox = ActionDeviceBuilder.create_action_device(dev) smartBox.start(ruleId, openId = None, attachParas = attachParas) address = Group.get_group(dev['groupId'])['address'] groupName = Group.get_group(dev['groupId'])['groupName'] score = 0 UpscoreRecord( logicalCode=dev['logicalCode'], devNo=devNo, ownerId=ownerId, time=datetime.datetime.now(), score=score, address=address, groupName=groupName, devType=dev['devType']['name'], type=TYPE_POINTS ).save() def __policy_points__(dev, ruleId): smartBox = ActionDeviceBuilder.create_action_device(dev) if dev.support_reliable: orderNo = dev.ownerId[-10:]+ConsumeRecord.make_no() order = ConsumeRecord(orderNo=orderNo, openId=dev.ownerId) order.package = smartBox.prepare_package(ruleId, attachParas) order.attachParas = attachParas smartBox.start_device_realiable(order) lineInfo = { 'port': attachParas.get('chargeIndex'), 'status': Const.DEV_WORK_STATUS_WORKING, 'nickName': '经销商远程上分', 'startTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), } data = smartBox._check_package(order.package) if 'needTime' in data: lineInfo.update({'needTime': data['needTime']}) if 'needElec' in data: lineInfo.update({'needElec': data['needElec']}) Device.update_port_control_cache(dev.devNo, lineInfo) address = Group.get_group(dev['groupId'])['address'] groupName = Group.get_group(dev['groupId'])['groupName'] UpscoreRecord( logicalCode=dev['logicalCode'], devNo=devNo, ownerId=ownerId, time=datetime.datetime.now(), package=order.package, address=address, groupName=groupName, devType=dev['devType']['name'], type=TYPE_POINTS ).save() try: ownerId = str(request.user.bossId) logicalCode = request.POST.get('logicalCode', None) attachParas = json.loads(request.POST.get('attachParas', '{}')) attachParas['onPoints'] = True type = request.POST.get('type', '') devNo = Device.get_devNo_by_logicalCode(logicalCode) dev = Device.get_dev(devNo) if not dev: return JsonResponse({'result': 2, 'description': u'设备不存在'}) if dev['ownerId'] != ownerId: return JsonResponse({'result': 2, 'description': u'不是你家设备,不能操作喔'}) dealer = dev.owner agent = Agent.objects.filter(id=str(dealer.agentId)).first() # type: Agent if 'disable_dealer_onPoints_and_sendCoins' in agent.features: return JsonResponse( {'result': 0, 'description': '设备无法使用该功能奥, 如有问题, 请联系代理商', 'payload': {}}) # 霍珀的道闸适配 if dev["devType"]["code"] == Const.DEVICE_TYPE_CODE_HP_GATE: __huopo_points(dev) return JsonResponse({'result': 1, 'description': u'success'}) if dev["devType"]["code"] in support_policy_device: ruleId = request.POST.get('ruleId', None) __policy_points__(dev, ruleId) return JsonResponse({'result': 1, 'description': u'success'}) if type == TYPE_POINTS: ruleId = request.POST.get('ruleId', None) # 如果是串口设备,上分的话,直接使用套餐。这里把串口和非串口的上分统一起来,行为应该有创建者创建具备行为的实例 if not ruleId: return JsonResponse( {'result': 0, 'description': u'没有找到对应的套餐信息,请您重新选择其他分值.或者检查设备是否没有注册到系统', 'payload': {}}) __points__(dev, ruleId) elif type == TYPE_CHARGE_CARD: price = int(request.POST.get('coins', 0)) if price <= 0: return JsonResponse({'result': 0, 'description': u'充值金额错,请重新输入', 'payload': {}}) __charge_card(dev, price) return JsonResponse({'result': 1, 'description': u'success'}) except ServiceException, e: logger.exception(e) return JsonResponse(e.result) @permission_required(ROLE.dealer, ROLE.subaccount) def onPointsRecords(request): # type: (WSGIRequest)->JsonResponse """ 上分记录查询 :param request: :return: """ ownerId = str(request.user.bossId) pageIndex = int(request.GET.get('pageIndex', 1)) pageSize = int(request.GET.get('pageSize', 10)) objs = UpscoreRecord.objects.filter(ownerId=ownerId).order_by('-time') rcdList = [] total = 0 sumCoins = 0 sumCoinsTotal = 0 sumCharge = 0 sumChargeTotal = 0 for obj in objs: if obj.type == 'chargeCard': sumCharge += obj.score sumChargeTotal += 1 else: sumCoins += obj.score sumCoinsTotal += 1 total += 1 rcdList.append({ 'logicalCode': obj.logicalCode, 'devNo': obj.devNo, 'createdStr': obj.time.strftime('%Y-%m-%d %H:%M:%S'), 'coins': obj.score, 'et_type_name': obj.devType, 'address': obj.address, 'groupName': obj.groupName, 'type': obj.type}) return JsonResponse({ "result": 1, "description": None, "payload": { "sumCoins": sumCoins, 'sumCoinsTotal': sumCoinsTotal, 'sumCharge': sumCharge, 'sumChargeTotal': sumChargeTotal, "rcds": { "total": total, "items": rcdList[(pageIndex - 1) * pageSize:pageIndex * pageSize], } } }) @permission_required(ROLE.dealer, ROLE.subaccount) def handlerKeepingOrder(request): """ 关闭订单取消订单 霍珀道闸 由于出现后付费的情况,可能存在两种情况需要将订单取消 用户扫码进门,创建了订单但是门没开 用户扫码出门,钱已经扣了但门没开 此接口 供经销商对于此类订单的处理 """ TYPE_CANCEL = "cancel" TYPE_CLOSE = "close" _id = request.GET.get("id") _type = request.GET.get("type") # 取消订单 sp = ServiceProgress.objects.get(id=_id) sp.isFinished = True sp.finished_time = int(time.time()) order = ConsumeRecord.objects.get(id=sp.consumes[0]) if _type == TYPE_CLOSE: order.isNormal = True order.finishedTime = datetime.datetime.now() order.remarks = u"经销商 %s 关闭订单" % request.user.nickname serviceInfo = { "finishedTime": str(order.finishedTime)[:19], } order.serviceInfo = serviceInfo elif _type == TYPE_CANCEL: order.finishedTime = datetime.datetime.now() order.remarks = u"经销商 %s 取消订单" % request.user.nickname order.isNormal = False try: sp.save() order.save() except Exception as e: logger.exception(e) return JsonResponse({'result': 0, 'description': u'数据查询出错', 'payload': {}}) else: # 清除该停车数量 无论是终止订单还是取消订单,其进车数量始终 需要 -1 key = "maxParking" if order.attachParas.get("vCardId"): key = "VIPMaxParking" serviceInfo = HuopoCacheMgr.get_parking_cache(order.groupId) if serviceInfo is not None: parkingInfo = serviceInfo.get("parkingInfo", {}) parkingNum = parkingInfo.get(key, 0) else: parkingInfo = {} parkingNum = 0 if parkingNum > 0: parkingNum -= 1 parkingInfo.update({key: parkingNum}) HuopoCacheMgr.set_parking_cache(order.groupId, {"parkingInfo": parkingInfo}) return JsonResponse({'result': 1, 'description': u'success'}) @permission_required(ROLE.dealer, ROLE.subaccount) def getKeepingOrder(request): """ 获取正在进行的订单 """ pageIndex = int(request.GET.get("pageIndex", 1)) pageSize = int(request.GET.get("pageSize", 10)) ownerId = str(request.user.bossId) logicalCode = request.GET.get('logicalCode', None) attachParas = json.loads(request.POST.get('attachParas', '{}')) devNo = Device.get_devNo_by_logicalCode(logicalCode) dev = Device.get_dev(devNo) if not dev: return JsonResponse({'result': 0, 'description': u'设备不存在'}) if dev['ownerId'] != ownerId: return JsonResponse({'result': 0, 'description': u'不是你家设备,不能操作喔'}) sps = ServiceProgress.objects.filter(device_imei=devNo, devTypeCode=dev["devType"]["code"], isFinished=False).all() dataList = list() for sp in sps: user = MyUser.objects.filter(openId=sp.open_id).first() order = ConsumeRecord.objects.get(id=sp.consumes[0]) tempData = { "id": sp.id, "nickname": user.nickname, "avatar": user.avatar, "startTime": order.time } dataList.append(tempData) return JsonResponse( {'result': 1, 'description': u'', 'payload': { "total": len(dataList), "dataList": dataList[(pageIndex-1)*pageSize: pageIndex*pageSize] } }) # 获取默认地址 @permission_required(ROLE.dealer, ROLE.subaccount) def groupInfo(request): # 获取默认地址 def groupInfoDefault(request): # type: (WSGIRequest)->JsonResponse groupId = request.GET.get('groupId', None) ownerId = str(request.user.bossId) group = Group.get_group(groupId) if group is None: return JsonResponse({"result": 0, "description": u"没有找到地址信息", "payload": {}}) if group['ownerId'] == ownerId: group['isManager'] = True else: group['isManager'] = False groupOwner = Dealer.get_dealer(group['ownerId']) group['managerName'] = groupOwner['nickname'] + " " + groupOwner['username'] group['partner'] = group['partnerDict'].values() for partner in group['partner']: if partner['id'] == ownerId: partner['self'] = True else: reload_parter = Dealer.get_dealer(partner['id']) partner['tel'] = reload_parter['username'] partner['name'] = reload_parter['nickname'] partner['self'] = False # 添加 合伙人商户的状态给前台显示 如果合伙人商户的状态是 初始状态 需要为合伙人绑定银行卡 partner = Dealer.objects.get(id=partner["id"]) district = District.get_district(group['districtId']) group['district'] = district if not group['isManager']: for i in range(len(group['partner'])-1,-1,-1): if not group['partner'][i]['self']: del group['partner'][i] return JsonResponse({"result": 1, "description": None, "payload": group}) current_user = request.user # type: UserSearchable return groupInfoDefault(request) @permission_required(ROLE.dealer, ROLE.subaccount) def groupIncomeData(request): # type: (WSGIRequest)->JsonResponse """ 查询地址组的收益 地址组收益的记录方式已经发生了改变 对于收益的部分 记录在 daily.incomeMap下面的数据,每个经销商一条,为总的收益,没有明细划分 :param request: :return: """ def get_group_info(g, _id): isM = _id == g.get("ownerId") if not isM: p = round_2_digits(float(g.get("partnerDict", dict()).get(_id, dict()).get("percent", 0))) else: fullPercent = 100 for _partner in g.get("partnerDict", dict()).values(): fullPercent -= float(_partner.get("percent", 0)) p = round_2_digits(float(fullPercent)) return isM, p current_user = request.user # type: Dealer dealerId = str(current_user.bossId) pageIndex = int(request.GET.get("pageIndex", 1)) pageSize = int(request.GET.get("pageSize", 10)) startDate = request.GET.get("startTime") endDate = request.GET.get("endTime") startDate, endDate = current_user.limit_filter_date(startDate, endDate) if endDate < startDate: return JsonResponse({ 'result': 1, 'description': '', 'payload': { "total": 0, "dataList": [], "adShow": current_user.adShow }}) else: searchKey = request.GET.get("searchKey", None) # 通过searchKey 获取组地址 作为查询的筛选条件 # TODO 这个地方有一个问题在于 如果 地址组的合伙人一旦修改 之前的合伙人无法看到历史的数据 而新的合伙人能看到之前的数据 groupIds = Group.search_group_ids_of_dealer( dealerId, searchKey ) + Group.search_group_ids_of_partner( dealerId, searchKey ) groupIdSlice = groupIds[(pageIndex - 1) * pageSize: pageSize * pageIndex] if not groupIdSlice: return JsonResponse({ 'result': 1, 'description': '', 'payload': { "total": len(groupIds), "dataList": [], "adShow": current_user.adShow }}) groupStatisticMap = GroupDailyStatsModelProxy.get_groups_income_statistic(groupIds=groupIdSlice, startDate=startDate, endDate=endDate, dealerId=dealerId) groupDevCountMap = Device.get_device_count_by_group(groupIdSlice) rptDict = GroupReport.get_rpt(groupIdSlice, startDate, endDate) # 投币的信息 # 经销商的特性判断 的相关信息的获取 dealer = Dealer.objects.get(id=dealerId) showOfflineCoin = True if 'show_offline_coins' in dealer.features else False # 整合数据 dataList = list() for _groupId in groupIdSlice: # 统计信息的过滤 groupStatistic = groupStatisticMap.get(_groupId, {}) # 要提前将这个不存在的统计值pop出来 dealerActualIncome = RMB(groupStatistic.pop("dealerActualIncome", 0)) incomeList = translate_income(groupStatistic) totalIncome = sum_rmb(_['value'] for _ in incomeList) # 组信息 以及分成比例的计算 group = Group.get_group(_groupId) or dict() isManager, percent = get_group_info(group, dealerId) value = { "groupName": group.get("groupName", ""), "groupId": _groupId, "address": group.get("address", ""), "equipmentCount": groupDevCountMap.get(_groupId, 0), "isManager": isManager, "percent": percent, "agentProfitShare": request.user.agentProfitShare, "offlineCoins": rptDict.get(_groupId, dict()).get('lineCoins', 0), "incomeList": incomeList, "totalIncome": totalIncome, "dealerActualIncome": dealerActualIncome } if not showOfflineCoin: value.pop('offlineCoins', None) dataList.append(value) # 对 totalIncome 排序 优先返回金额最多的地址组 dataList = sorted(dataList, key=lambda x: float(x["totalIncome"]), reverse=True) total = len(groupIds) return JsonResponse({"result": 1, "description": None, "payload": { "total": total, "dataList": dataList, "adShow": current_user.adShow }}) @permission_required(ROLE.dealer, ROLE.subaccount) def getDevOffLineCoinStatByGroupId(request): # type: (WSGIRequest)->JsonResponse groupId = request.GET.get('groupId') group = Group.get_group(groupId) if not group: return JsonErrorResponse(u'找不到组ID') pageIndex = int(request.GET.get('pageIndex', 1)) pageSize = int(request.GET.get('pageSize', 10)) startDate = defaultTodayDate(request.GET.get('startTime')) endDate = defaultTodayDate(request.GET.get('endTime')) total = Device.get_collection().find({'groupId': groupId}).count() devNoList = Device.get_devNos_by_group([groupId]) devInfo = Device.get_dev_by_nos(devNoList) dataList = [ { 'logicalCode': devInfo[devNo]['logicalCode'], 'groupNumber': devInfo[devNo]['groupNumber'], 'devTypeName': devInfo[devNo].get('devType', {}).get('name', ''), 'offlineCoins': rpt['lineCoins'], } for devNo, rpt in DevReport.get_rpt(devNoList, startDate, endDate).iteritems() ] return JsonResponse( { 'result': 1, 'description': '', 'payload': { 'total': total, 'groupName': group['groupName'], 'dataList': dataList[(pageIndex - 1) * pageSize:pageIndex * pageSize] } } ) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,请稍后再试')) @permission_required(ROLE.dealer, ROLE.subaccount) def groupIncomeByGroupId(request): # type: (WSGIRequest)->JsonResponse """ 获取 单一地址组的 收益 聚合信息 :param request: :return: """ dealerId = str(request.user.bossId) groupId = request.GET.get("groupId") startDate = request.GET.get("startTime") endDate = request.GET.get("endTime") if not groupId: return JsonErrorResponse(description=u'未提供地址ID') if groupId not in Group.get_group_ids_of_dealer_and_partner(dealerId): return JsonErrorResponse(description=u'无权限查看') group = Group.get_group(groupId) if not group: return JsonErrorResponse(description=u'组不存在') groupStatistic = GroupDailyStatsModelProxy.get_one_group_income_statistic(groupId, startDate, endDate) incomeTotalList = [{"name": u"总收益", "value": RMB(groupStatistic.get("totalIncome", 0))}] for _item in translate_income(groupStatistic): if _item.get("value", RMB(0)) > RMB(0): incomeTotalList.append(_item) return JsonResponse( { 'result': 1, 'description': 'ok', 'payload': { 'groupName': group['groupName'], "incomeTotalList": incomeTotalList } } ) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,请稍后再试')) @permission_required(ROLE.dealer, ROLE.subaccount) def groupConsumptionByGroupId(request): # type: (WSGIRequest)->JsonResponse """ 获取 单一地址组的 收益 聚合信息 :param request: :return: """ dealerId = str(request.user.bossId) groupId = request.GET.get("groupId") startDate = request.GET.get("startTime") endDate = request.GET.get("endTime") if not groupId: return JsonErrorResponse(description=u'未提供地址ID') if groupId not in Group.get_group_ids_of_dealer_and_partner(dealerId): return JsonErrorResponse(description=u'无权限查看') group = Group.get_group(groupId) if not group: return JsonErrorResponse(description=u'组不存在') groupStatistic = GroupDailyStatsModelProxy.get_one_group_consumption_statistic(groupId, startDate, endDate) agent = Agent.objects.get(id=request.user.agentId) # type: Agent consumptionTotalList = list() for _item in translate_consumption(groupStatistic, agent.hide_consume_kinds_dealer): if _item.get("value", Quantity(0)) > Quantity(0): consumptionTotalList.append(_item) return JsonResponse( { 'result': 1, 'description': 'ok', 'payload': { 'groupName': group['groupName'], "incomeTotalList": consumptionTotalList } } ) EXTRA_INCOME_DEVICE_TYPE_CODES = [Const.DEVICE_TYPE_CODE_WASHCAR_LSHB] def realtime_income_available(typeCode): # type:(str)->bool return typeCode in EXTRA_INCOME_DEVICE_TYPE_CODES @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,请稍后再试')) @permission_required(ROLE.dealer, ROLE.subaccount) def getRealtimeIncomeByDev(request): # type: (WSGIRequest)->JsonResponse # TODO 建立一个缓存的permission map 来将经销商ID与设备等相关权限对应起来 logicalCode = request.GET.get('logicalCode') device = Device.get_dev_by_logicalCode(logicalCode) if not device: return JsonErrorResponse(description=u'设备不存在') typeCode = device['devType']['code'] if realtime_income_available(typeCode): return JsonErrorResponse(description=u'不支持当前设备查询实时收入') translation = { 'cardFee': u'刷卡总额', 'coinFee': u'投币总额', 'mobileFee': u'支付总额' } if typeCode == Const.DEVICE_TYPE_CODE_CHARGING_SIJIANG: try: smartBox = ActionDeviceBuilder.create_action_device(device) conf = smartBox.get_dev_consume_count() return JsonResponse( { 'result': 1, 'description': '', 'payload': { 'realTimeIncome': [ {'name': translation[k], 'value': v} for k, v in conf.iteritems() if k in translation ] } }) except ServiceException as e: logger.debug('cannot get_extra_income_by_specific_devices device=%s' % (device,)) logger.exception(e) return JsonErrorResponse(description=u'网络不畅通,请稍后再试') elif typeCode == Const.DEVICE_TYPE_CODE_WASHCAR_LSHB: try: # 获取设备上的卡的总收入、投币的总收入 smartBox = ActionDeviceBuilder.create_action_device(device) mapping = { 'cardFee': smartBox.get_card_count(), 'coinFee': smartBox.get_coins_count() } return JsonResponse( { 'result': 1, 'description': '', 'payload': { 'realTimeIncome': [{'name': translation[k], 'value': v} for k, v in mapping.iteritems() if k in translation] } }) except ServiceException as e: logger.debug('cannot get_extra_income_by_specific_devices device=%s' % (device,)) logger.exception(e) return JsonErrorResponse(description=u'网络不畅通,请稍后再试') else: return JsonErrorResponse(description=u'不支持当前设备查询实时收入') @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,请稍后再试')) @permission_required(ROLE.dealer, ROLE.subaccount) def groupEquipmentIncomeByGroupId(request): # type: (WSGIRequest)->JsonResponse """ 获取组下设备按日期收益聚合数据 :param request: :return: """ # TODO Nicolas 此接口以及 groupEquipmentConsumptionByGroupId 存在问题 # TODO Nicolas 当该地址下设备信息发生变更的时候 ,通过 GroupDaily 获取的信息 和通过 DeviceDaily 聚合获取的信息会不一致 dealerId = str(request.user.bossId) groupId = request.GET.get("groupId", None) pageIndex = int(request.GET.get('pageIndex', 1)) pageSize = int(request.GET.get('pageSize', 10)) startDate = request.GET.get('startTime') endDate = request.GET.get('endTime') if groupId is None: return JsonErrorResponse(description=u'未找到地址组,请重试') if groupId not in Group.get_group_ids_of_dealer_and_partner(dealerId): return JsonErrorResponse(description=u'无权限查看') group = Group.get_group(groupId) if not group: return JsonErrorResponse(description=u'组不存在') # 获取设备的日统计信息 logicalCodes = Device.get_logicalCode_by_groupId(groupId) logicalCodeSlice = sorted(logicalCodes[(pageIndex - 1) * pageSize: pageIndex * pageSize]) statisticMap = DeviceDailyStatsModelProxy.get_devices_income_statistic(logicalCodeSlice, startDate, endDate) dataList = list() for logicalCode in logicalCodeSlice: devStatistic = translate_income(statisticMap.get(logicalCode, dict())) devStatistic = [_statistic for _statistic in devStatistic if _statistic["value"] > RMB(0)] dev = Device.get_dev_by_l(logicalCode) dataList.append({ "incomeList": devStatistic, "logicalCode": logicalCode, "groupId": groupId, "type": dev.get("devType", dict()).get("name"), 'groupNumber': dev.get('groupNumber'), 'realtimeIncomeAvailable': realtime_income_available(dev.get('devType', dict()).get('code')) }) return JsonResponse( { 'result': 1, 'description': None, 'payload': { 'total': len(logicalCodes), 'dataList': dataList } } ) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,请稍后再试')) @permission_required(ROLE.dealer, ROLE.subaccount) def groupEquipmentConsumptionByGroupId(request): # type: (WSGIRequest)->JsonResponse """ 获取组下设备按日期消费聚合数据 :param request: :return: """ dealerId = str(request.user.bossId) groupId = request.GET.get("groupId", None) pageIndex = int(request.GET.get('pageIndex', 1)) pageSize = int(request.GET.get('pageSize', 10)) startDate = request.GET.get('startTime') endDate = request.GET.get('endTime') if groupId is None: return JsonErrorResponse(description=u'未找到地址组,请重试') if groupId not in Group.get_group_ids_of_dealer_and_partner(dealerId): return JsonErrorResponse(description=u'无权限查看') group = Group.get_group(groupId) if not group: return JsonErrorResponse(description=u'组不存在') # 获取设备的日统计信息 logicalCodes = Device.get_logicalCode_by_groupId(groupId) logicalCodeSlice = sorted(logicalCodes[(pageIndex-1)*pageSize: pageIndex*pageSize]) statisticMap = DeviceDailyStatsModelProxy.get_devices_consumption_statistic(logicalCodeSlice, startDate, endDate) agent = Agent.objects.get(id = request.user.agentId) # type: Agent dataList = list() for logicalCode in logicalCodeSlice: devStatistic = translate_consumption(statisticMap.get(logicalCode, dict()), hides = agent.hide_consume_kinds_dealer) devStatistic = [_statistic for _statistic in devStatistic if _statistic["value"] > Quantity(0)] dev = Device.get_dev_by_l(logicalCode) dataList.append({ "consumptionList": devStatistic, "logicalCode": logicalCode, "groupId": groupId, "type": dev.get("devType", dict()).get("name"), 'groupNumber': dev.get('groupNumber'), }) return JsonResponse( { 'result': 1, 'description': "", 'payload': { 'total': len(logicalCodes), 'dataList': dataList } } ) def get_income_by_cat(stat, date_range, field): return RMB(stat.get(date_range, {}).get('income', {}).get(field, 0)) def get_daily_income_by_cat(stat, field): return get_income_by_cat(stat, 'daily', field) def get_monthly_income_by_cat(stat, field): return get_income_by_cat(stat, 'monthly', field) @permission_required(ROLE.dealer, ROLE.agent, ROLE.subaccount) def lastMonthIncome(request): """ 按月统计 经销商的月收益 获取的数据是当月的收益数据累加的 以及 每天的收益累计总和 :param request: :return: """ dealerId = request.GET.get('dealerId') or str(request.user.bossId) timeStr = request.GET.get("time", datetime.date.today().strftime("%Y-%m")) startDate, endDate = get_start_and_end_by_month(monthStr = timeStr) rpts = {r['date']: r for r in DealerReport.get_rpts(dealerId, startDate, endDate)} # 获取每一天的数据 首先要对时间参数进行鉴别 如果是本月的话,那么最后一天就是今天 dataList = list() totalIncome, payIncome, offlineCoins = RMB(0), RMB(0), VirtualCoin(0) rv = DealerDailyStatsModelProxy.get_days_income_stat(dealerId, timeStr) for day, stat in rv.iteritems(): day_offline_count = VirtualCoin(rpts.get(day, {}).get('lineCoins', 0)) offlineCoins += day_offline_count day_pay_income = RMB(get_in(["income", format(DEALER_INCOME_SOURCE.RECHARGE)], stat, default = 0)) + \ RMB(get_in(["income", format(DEALER_INCOME_SOURCE.REDPACK)], stat, default = 0)) + \ RMB(get_in(["income", format(DEALER_INCOME_SOURCE.RECHARGE_CARD)], stat, default = 0)) + \ RMB(get_in(["income", format(DEALER_INCOME_SOURCE.RECHARGE_VIRTUAL_CARD)], stat, default = 0)) + \ RMB(get_in(["income", format(DEALER_INCOME_SOURCE.REFUND_CASH)], stat, default = 0)) payIncome += day_pay_income day_total_income = RMB(get_in(["totalIncome"], stat, default = 0)) totalIncome += day_total_income dataList.append({ 'dateStr': day, 'dateText': u'%s年%s月%s日' % tuple(day.split('-')), 'payIncome': day_pay_income, 'offlineCoins': day_offline_count, 'totalIncome': day_total_income }) if dealerId == '5d132407003048494763a51b': if int(timeStr[0:4]) < 2021: dataList = [] offlineCoins = 0 payIncome = 0 totalIncome = 0 else: pass return JsonOkResponse(payload= { "adShow": request.user.adShow, "totalIncome": totalIncome, "payIncome": payIncome, "offlineCoins": offlineCoins, "dataList": dataList }) @permission_required(ROLE.dealer, ROLE.agent, ROLE.subaccount) def lastYearIncome(request): # type: (WSGIRequest)->JsonResponse """ 按年统计经销商的收益 :param request: :return: """ dealerId = request.GET.get('dealerId') or str(request.user.bossId) timeStr = request.GET.get("time", datetime.date.today().strftime("%Y")) timeStr = Dealer.limit_filter_year(dealerId, timeStr[0:4]) if not timeStr: return JsonOkResponse(payload = {'adShow': request.user.adShow, 'dataList': []}) else: startDay, endDay = get_start_and_end_by_year(timeStr) monthRange = [datetime.datetime.strftime(item, "%Y-%m") for item in get_date_range(startDay, endDay, "MS")] offline_report = DealerReportModelProxy.get_year_by_month(dealerId = dealerId, yearStr = timeStr) # 获取一年里面 按月聚合分组的数据 statisticMap = DealerDailyStatsModelProxy.get_one_year_income_as_month(dealerId = dealerId, yearStr = timeStr) dataList = list() for month in monthRange: monthIncomeMap = statisticMap.get(month, dict()) tempMonthStatistics = { "totalIncome": RMB(monthIncomeMap.get("totalIncome", 0)), "offlineCoins": VirtualCoin( offline_report.get('%d-%02d' % tuple(map(int, month.split('-'))), {}).get('lineCoins', 0)), "dateStr": month, "dateText": u"{}年{}月".format(*month.split("-")), "payIncome": sum([_v for _k, _v in monthIncomeMap.items() if _k in [DEALER_INCOME_SOURCE.RECHARGE_VIRTUAL_CARD, DEALER_INCOME_SOURCE.RECHARGE_CARD, DEALER_INCOME_SOURCE.RECHARGE, DEALER_INCOME_SOURCE.REFUND_CASH, DEALER_INCOME_SOURCE.REDPACK]], RMB(0)) } dataList.append(tempMonthStatistics) return JsonOkResponse(payload = {'adShow': request.user.adShow, 'dataList': dataList}) @permission_required(ROLE.dealer, ROLE.agent, ROLE.subaccount) def lastMonthConsumption(request): # type: (WSGIRequest)->JsonResponse """ 按月统计 经销商的消耗信息 :param request: :return: """ dealerId = request.GET.get('dealerId') or str(request.user.bossId) dealer = Dealer.objects.get(id=dealerId) timeStr = request.GET.get("time", datetime.date.today().strftime("%Y-%m")) _year = Dealer.limit_filter_year(dealerId, timeStr[0:4]) if not _year: return JsonOkResponse(payload = {'dataList': []}) else: agent = Agent.objects.get(id = request.user.agentId) dataList = list() rv = DealerDailyStatsModelProxy.get_days_consume_stat(dealerId, timeStr) for _day, stat in rv.iteritems(): consumptionList = translate_consumption(get_in(["consumption"], stat, dict()), hides = agent.hide_consume_kinds_dealer) if "not_show_about_elec" in dealer.features: [consumptionList.pop(consumptionList.index(_c)) for _c in consumptionList if _c.get("name") == u"消耗电量"] [consumptionList.pop(consumptionList.index(_c)) for _c in consumptionList if _c.get("name") == u"电费成本"] dataList.append({ "dateStr": _day, "dateText": u"{}年{}月{}日".format(*_day.split("-")), "consumptionList": consumptionList }) return JsonOkResponse(payload = {'dataList': dataList}) @permission_required(ROLE.dealer, ROLE.agent, ROLE.subaccount) def lastYearConsumption(request): # type: (WSGIRequest)->JsonResponse """ 一年的消费概览 :param request: :return: """ dealerId = request.GET.get('dealerId') or str(request.user.bossId) timeStr = request.GET.get("time", datetime.date.today().strftime("%Y")) timeStr = Dealer.limit_filter_year(dealerId, timeStr) if not timeStr: return JsonOkResponse(payload = {'dataList': []}) else: # 获取统计的时间范围 获取月份的区间 startDay, endDay = get_start_and_end_by_year(timeStr) monthRange = [datetime.datetime.strftime(item, "%Y-%m") for item in get_date_range(startDay, endDay, "MS")] # 获取一年里面 按月聚合分组的消费数据 statisticMap = DealerDailyStatsModelProxy.get_one_year_consume_as_month(dealerId = dealerId, yearStr = timeStr) # 消费信息 某些字段和特性相关联 先取出代理商的特性 留作判断 agent = Agent.objects.get(id = request.user.agentId) dataList = list() for _month in monthRange: _item = statisticMap.get(_month, dict()) consumptionList = translate_consumption(_item, hides=agent.hide_consume_kinds_dealer) dataList.append({ "dateStr": _month, "dateText": u"{}年{}月".format(*_month.split("-")), "consumptionList": consumptionList }) return JsonOkResponse(payload={'dataList': dataList}) @permission_required(ROLE.dealer, ROLE.subaccount) def updateInfo(request): # type: (WSGIRequest)->JsonResponse """ 支持经销商更改用户信息 :param request: :return: """ name = request.POST.get('name', '') if NAME_RE.match(name) is None: logger.info('update dealer name doesn\'t fit format, name=%s' % (name.encode('utf-8'),)) return JsonResponse({"result": 0, "description": "请输入正确格式的名称(2-20位)"}) if check_role(request.user, ROLE.dealer): dealer = Dealer.objects(id=request.user.bossId).first() # type: Union[Dealer,None] if dealer is None: return JsonResponse({"result": 0, "description": "该经销商不存在"}) updated = dealer.update_dealer(ownerId=str(dealer.id), nickname=name) if not updated: logger.info('Dealer [updateInfo] failed, name=%s' % (name.encode('utf-8'),)) return JsonResponse({"result": 0, "description": u'更新失败,请重试'}) else: return JsonResponse({"result": 1, "description": None}) else: subaccount = SubAccount.objects(id=request.user.id).first() # type: Union[Dealer,None] if subaccount is None: return JsonResponse({"result": 0, "description": "该经销商不存在"}) updated = subaccount.update(nickname=name) if not updated: logger.info('subaccount [updateInfo] failed, name=%s' % (name.encode('utf-8'),)) return JsonResponse({"result": 0, "description": u'更新失败,请重试'}) else: return JsonResponse({"result": 1, "description": None}) @permission_required(ROLE.dealer, ROLE.subaccount) def verifyNewPhoneNumber(request): # type: (WSGIRequest)->JsonResponse """ 修改经销商手机号 :param request: :return: """ code = request.POST.get('code') if not code: return JsonResponse({"result": 0, "description": u'请输入验证码'}) phoneNumber = request.POST.get('phone') if PHONE_NUMBER_RE.match(phoneNumber) is None: logger.info('phone number format error, phone=%s' % phoneNumber) return JsonResponse({"result": 0, "description": u"请输入正确的手机号码"}) if check_role(request.user, ROLE.dealer): dealer = Dealer.objects(id=request.user.bossId).first() # type: Optional[Dealer] if dealer is None: return JsonResponse({"result": 0, "description": u"该经销商不存在"}) # : 检测是否系统内已有该号码,为了防止混淆 if Dealer.objects(username=phoneNumber).first(): return JsonResponse({"result": 0, "description": u"已存在与该手机号码绑定的账户"}) status, msg = dealerRegisterSMSProvider.verify(phoneNumber, code) if status: updated = dealer.update_dealer(ownerId=str(dealer.id), username=phoneNumber) if updated: Dealer.invalid_cache(dealer.id) return JsonResponse({"result": 1, "description": None}) else: return JsonResponse({"result": 0, "description": u'更换失败'}) else: return JsonResponse({"result": 0, "description": msg}) else: subAccount = SubAccount.objects(id=request.user.id, agentId=request.user.agentId).first() # type: Optional[Dealer] if subAccount is None: return JsonResponse({"result": 0, "description": u"该子账号不存在"}) # : 检测是否系统内已有该号码,为了防止混淆 if SubAccount.objects(username=phoneNumber, agentId=request.user.agentId).first(): return JsonResponse({"result": 0, "description": u"已存在与该手机号码绑定的子账户"}) status, msg = dealerRegisterSMSProvider.verify(phoneNumber, code) if status: updated = subAccount.update(username=phoneNumber) if updated: return JsonResponse({"result": 1, "description": None}) else: return JsonResponse({"result": 0, "description": u'更换失败'}) else: return JsonResponse({"result": 0, "description": msg}) @permission_required(ROLE.dealer, ROLE.subaccount) def setAddressFree(request): # type: (WSGIRequest)->JsonResponse """ 设置部分地址为免费地址, 其同一地址下所有设备都会供免费使用 :param request: :return: """ payload = parse_json_payload(request.body) groupId = payload.get('groupId', None) isFree = payload.get('isFree', False) currentDealer = request.user.myBoss # type: Optional[Dealer] if currentDealer.get_feature('disable_set_group_free').get('disable_set_group_free', False): return JsonResponse( {'result': 0, 'description': '设备无法使用该功能奥, 如有问题, 请联系代理商', 'payload': {}}) if groupId is None: return JsonResponse({"result": 0, "description": u'地址不可为空'}) try: Group.update_group(group_id=groupId, isFree=isFree) return JsonResponse({"result": 1, "description": None}) except Exception as e: logger.exception(e) return JsonResponse({"result": 0, "description": u'修改失败'}) #### `经销商报表版块` ############################################################### @permission_required(ROLE.dealer, ROLE.subaccount) def dateCoins(request): """ TODO 线下投币相关数据与收益计算展现彻底分离,接口需要重新审视 :param request: :return: """ ownerId = str(request.user.bossId) now = datetime.datetime.now() rpt = Accounting.getOwnerIncome(ownerId, now) return JsonResponse({"result": 1, "description": None, 'payload': {"coins": rpt["lineCoins"]}}) @permission_required(ROLE.dealer, ROLE.subaccount) def dateCoinsDetail(request): """ TODO 线下投币相关数据与收益计算展现彻底分离,接口需要重新审视 :param request: :return: """ ownerId = str(request.user.bossId) pageIndex = int(request.GET.get('pageIndex', 1)) pageSize = int(request.GET.get('pageSize', 10)) nowDate = datetime.datetime.now().strftime('%Y-%m-%d') groupIds = Group.get_group_ids_of_dealer(ownerId) devNos = Device.get_devNos_by_group(groupIds) keys = [devCoinTmpl(devNo, nowDate) for devNo in devNos] devCoinDict = reportCache.get_many(keys) devNoList = [] for key, coins in devCoinDict.items(): coins = int(coins) if coins == 0: continue tempList = key.split('_') devNo = tempList[1] devNoList.append({'devNo': devNo, 'coins_count': coins}) sorted(devNoList, key=lambda dev: dev['coins_count'], reverse=True) total = len(devNoList) resultDevDictList = devNoList[(pageIndex - 1) * pageSize:pageIndex * pageSize] devNoList = [dev['devNo'] for dev in resultDevDictList] devDict = Device.get_dev_by_nos(devNoList) groupIds = [dev['groupId'] for dev in devDict.values()] groupDict = Group.get_groups_by_group_ids(groupIds) dataList = [] for dev in resultDevDictList: if dev['devNo'] not in devDict: logger.warning('dev not belong to dealer'.format(dev['devNo'], ownerId)) continue devDetail = devDict[dev['devNo']] groupDetail = groupDict[devDetail['groupId']] dataList.append({ 'value': devDetail['logicalCode'], 'coins_count': dev['coins_count'], "online": devDetail["online"], "remark": devDetail["remarks"], "type": devDetail['devType']['name'], "groupNumber": devDetail["groupNumber"], "groupName": groupDetail['groupName'], "status": devDetail['status'], "statusInfo": devDetail['statusInfo'] }) return JsonResponse({"result": 1, "description": None, 'payload': {"total": total, "dataList": dataList}}) ######################## #### 经销商收益消费数据中心 ######################## @require_GET @error_tolerate(logger=logger, nil=JsonErrorResponse(u'获取收益统计失败')) @permission_required(ROLE.dealer, ROLE.subaccount) def getIncomeStatistics(request): # type: (WSGIRequest)->JsonResponse """ 经销商经营统计 首页获取入口 :param request: :return: """ currentDealer = request.user # type: cast(Dealer) groupIds = Group.get_group_ids_of_dealer_and_partner(str(currentDealer.bossId)) stats = [ { "name": u"完成订单", "value": GroupDailyStat.get_today_recharge_count(groupIds=groupIds), "effect": "good", "unit": "", "necessary": True } ] agent = Agent.objects(id=currentDealer.agentId).get() # type: Agent start, end = today_datetime_range() if not agent.supports('hide_dealer_newly_user_added_count'): stats.append({ "name": u"新增用户", "value": MyUser.get_new_user_count(groupIds=groupIds, start=start, end=end), "effect": "good", "unit": "", "necessary": True }) dailyStat = DealerDailyStat.get_today(currentDealer.bossId) consumption = dailyStat.get("consumption", dict()) for kind in agent.hide_consume_kinds_dealer: consumption.pop(kind, None) for kind, value in consumption.iteritems(): stats.append( { "source": kind, "name": DEALER_CONSUMPTION_AGG_KIND_TRANSLATION.get(kind, ''), "value": to_quantity(kind, value), "effect": "good", "unit": DEALER_CONSUMPTION_AGG_KIND_UNIT.get(kind, ''), "necessary": False } ) # 将非必须的并且值为 0的过滤掉 todayStatList = filter(lambda _: float(str((_.get("value", 0)))) > 0 or _.get("necessary"), stats) now = datetime.datetime.now() monthStr = MONTH_DATE_KEY.format(year=now.year, month=now.month) return JsonOkResponse( payload={ "monthIncome": DealerDailyStatsModelProxy.get_one_month_income( dealerId = currentDealer.bossId, monthStr = monthStr), "todayIncome": DealerDailyStat.get_today_income(dealerId = currentDealer.bossId), 'todayRefundCash': abs(DealerDailyStat.get_today_refund_cash(dealerId = currentDealer.bossId)), "todayStatList": todayStatList } ) @require_GET @error_tolerate(logger=logger, nil=JsonErrorResponse(u'获取收益消费来源失败')) @permission_required(ROLE.dealer, ROLE.subaccount) def getIncomeConsumptionCategories(request): # type: (WSGIRequest)->JsonResponse """ :param request: :return: """ currentDealer = request.user # type: cast(Dealer) expand = lambda _: [{'text': v, 'value': k} for k, v in _.items()] return JsonResponse( { 'result': 1, 'description': '', 'payload': { 'income': expand(currentDealer.income_aggregate_source), 'consumption': expand(currentDealer.consumption_aggregate_source) } }) @require_GET @error_tolerate(logger=logger, nil=JsonErrorResponse(u'获取收益列表失败')) @permission_required(ROLE.dealer, ROLE.subaccount) def getIncomeList(request): # type: (WSGIRequest)->JsonResponse """ 经销商经营统计的列表 从incomeProxy维度读取 :param request: :return: """ current_dealer = request.user # type: Union[Dealer, SubAccount] current_dealer_id = str(current_dealer.bossId) pageIndex = int(request.GET.get('pageIndex', 1)) pageSize = int(request.GET.get('pageSize', 10)) startTime = request.GET.get("startTime") endTime = request.GET.get("endTime") logicalCode = request.GET.get("logicalCode") source = request.GET.get("secondary") groupId = request.GET.get('groupId') if groupId and groupId == 'undefined': return JsonErrorResponse(description = u'地址过滤参数错误,请刷新后重试') if not groupId: groupIds = [ObjectId(groupId) for groupId in Group.get_group_ids_of_dealer_and_partner(current_dealer_id)] else: groupIds = [ObjectId(groupId)] searchKey = request.GET.get("searchKey") filters = { "groupId__in": groupIds, "hint": [('groupId', 1), ('dateTimeAdded', -1)], } if logicalCode: filters.update({"logicalCode": logicalCode}) # 将source为 保险的排除 经销商的主营收益仅仅为以下几种 if source: sources = [source] else: sources = [ DEALER_INCOME_SOURCE.REFUND_CASH, DEALER_INCOME_SOURCE.RECHARGE, DEALER_INCOME_SOURCE.REDPACK, DEALER_INCOME_SOURCE.OFFLINE_COIN, DEALER_INCOME_SOURCE.RECHARGE_CARD, DEALER_INCOME_SOURCE.RECHARGE_VIRTUAL_CARD ] filters.update({"source__in": sources}) if searchKey: filters.update({"searchKey": searchKey}) startTime, endTime = current_dealer.limit_filter_date(startTime, endTime) if startTime > endTime: return JsonResponse({ 'result': 1, 'description': None, 'payload': { 'total': 0, 'adShow': current_dealer.adShow, 'totalAmount': RMB(0), 'dataList': [], } }) # 获取收益集合 st = datetime.datetime.strptime(startTime, "%Y-%m-%d") et = datetime.datetime.strptime(endTime, "%Y-%m-%d") incomeQuery = DealerIncomeProxy.objects.filter(dateTimeAdded__gte=st, dateTimeAdded__lt=et+datetime.timedelta(days=1), **filters) # type: CustomQuerySet total, totalAmount = incomeQuery.sum_and_count("actualAmountMap.{}".format(current_dealer_id)) # 第一次循环提取出收益模型以及其对应的充值单号 incomes = list() ref_ids = list() for _income in incomeQuery.paginate(pageIndex, pageSize): # type: DealerIncomeProxy incomes.append(_income) ref_ids.append(_income.ref_id) # 取出所有的充值记录 recharges = dict() if ref_ids: for item in RechargeRecord.objects.filter(id__in=ref_ids): # type: RechargeRecord recharges[str(item.id)] = item # 最后看是否需要执行内存合单 dataList = list() for _record in incomes: if str(_record.ref_id) not in recharges: logger.warning('order not exist.'.format(str(_record.ref_id))) continue rechargeOrder = recharges[str(_record.ref_id)] # type: RechargeRecord # 找到同级的子单 然后一起合并 if rechargeOrder.isSubOrder: _subOrders = RechargeRecord.objects.filter( id__ne=rechargeOrder.id, ownerId=rechargeOrder.ownerId, devNo=rechargeOrder.devNo, openId=rechargeOrder.openId, wxOrderNo=rechargeOrder.wxOrderNo ) # 找到该笔支付单的所有分账单proxy _incomes = DealerIncomeProxy.objects.filter(ref_id__in=[_.id for _ in _subOrders]) _data = _record.to_dict(dealerId=current_dealer_id) _data["subs"] = [_record.to_dict(current_dealer_id)] for _income in _incomes: _incomeDict = _income.to_dict(current_dealer_id) _data["totalAmount"] += _incomeDict["totalAmount"] _data["amount"] += _incomeDict["amount"] _data["subs"].append(_incomeDict) else: _data = _record.to_dict(dealerId=current_dealer_id) dataList.append(_data) return JsonResponse( { 'result': 1, 'description': "", 'payload': { 'total': total, 'adShow': current_dealer.adShow, 'totalAmount': RMB(totalAmount), 'dataList': dataList, } } ) @require_GET @error_tolerate(logger=logger, nil=JsonErrorResponse(u'获取收益详情失败')) @permission_required(ROLE.dealer, ROLE.subaccount) def getIncomeDetail(request): # type: (WSGIRequest)->JsonResponse """ 根据 存在收入代理里的`ref_id`来获取真实的收入对应的对象,以拼装出真实的详情 :param request: :return: """ currentDealerId = str(request.user.bossId) _id = request.GET.get("id") _ref_id = request.GET.get("ref_id") if not any([_id, _ref_id]) or 'groupId' not in request.GET: return JsonErrorResponse(description=u'参数错误,请刷新后再试') filters = {"id": _id} if _id else {"ref_id": ObjectId(_ref_id)} filters.update({'shard_filter': {'groupId': request.GET.get('groupId')}}) record = ClientDealerIncomeModelProxy.get_one(**filters) # type: DealerIncomeProxy if not record: return JsonErrorResponse(description=u"未查询到该笔订单") data = record.ref_detail(currentDealerId) startKey = data.get("startKey", None) if startKey: consumeRecord = ConsumeRecord.objects(startKey=data.get('startKey', '')).first() if consumeRecord is not None: data.update({'orderNo': consumeRecord.orderNo}) data.update({'consumeId': str(consumeRecord.id)}) rechargeRecord = RechargeRecord.objects.filter(id=record.ref_id).first() if rechargeRecord is not None and rechargeRecord.via == 'redpack': data.update({'gateway': 'redpack'}) # 新加入一个判断,如果是group owner则显示全部正常信息,如果不是只显示全部金额和自己分到的金额信息 # 判断是否是group owner,如果是group显示全部完整信息 for partnerInfo in data['incomePartitionList']: if partnerInfo['owner']: if partnerInfo['role'] == 'me': return JsonResponse({'result': 1, 'description': '', 'payload': data}) # 判断是role是否是me,如果不是本人信息则不显示 for i in range(len(data['incomePartitionList']) - 1, -1, -1): if data['incomePartitionList'][i]['role'] != 'me': del data['incomePartitionList'][i] return JsonResponse({'result': 1, 'description': '', 'payload': data}) @require_GET @error_tolerate(logger=logger, nil=JsonErrorResponse(u'获取消费列表失败')) @permission_required(ROLE.dealer, ROLE.subaccount) def getConsumptionList(request): # type: (WSGIRequest)->JsonResponse """ :param request: :return: """ def coin_quantity(amount): # type:(float)->Quantity return Quantity(amount, places=consumption_unit_precision(DEALER_CONSUMPTION_AGG_KIND.COIN)) current_dealer = request.user # type: cast(Dealer) current_dealer_id = str(current_dealer.bossId) pageIndex = int(request.GET.get('pageIndex', 1)) pageSize = int(request.GET.get('pageSize', 10)) startTime = request.GET.get('startTime') endTime = request.GET.get('endTime') startTime, endTime = current_dealer.limit_filter_date(startTime, endTime) if endTime < startTime: return JsonResponse({ 'result': 1, 'description': None, 'payload': { 'total': 0, 'adShow': current_dealer.adShow, 'totalAmount': RMB(0), 'dataList': [] } }) else: logicalCode = request.GET.get("logicalCode") source = request.GET.get("secondary") groupId = request.GET.get('groupId') filters = { 'isNormal': True } if not groupId: filters.update({ 'ownerId__in': Dealer.get_cooperative_dealer_ids(current_dealer_id), 'groupId__in': Dealer.get_cooperative_group_ids(current_dealer_id) }) else: group = Group.get_group(groupId) # type: GroupDict filters.update({ 'shard_filter': {'ownerId': group.ownerId}, 'groupId': groupId }) searchKey = request.GET.get("searchKey") if logicalCode: filters.update({ "logicalCode": logicalCode }) if source: filters.update({"aggInfo__{}__exists".format(source): True}) if searchKey: filters.update({"searchKey": searchKey}) # 获取的是总的数据条目 records = ClientConsumeModelProxy.get_data_list(startTime=startTime, endTime=endTime, **filters) # type: CustomQuerySet total, totalAmount = records.sum_and_count("coin") totalAmount = coin_quantity(totalAmount) agent = Agent.objects.get(id=current_dealer.agentId) # type: Agent return JsonResponse( { 'result': 1, 'description': None, 'payload': { 'total': total, 'adShow': current_dealer.adShow, 'totalAmount': totalAmount, 'dataList': [ _record.to_dict(source=source, hides=agent.hide_consume_kinds_dealer) for _record in records.paginate(pageIndex, pageSize) ], } }) @require_GET @error_tolerate(logger=logger, nil=JsonErrorResponse(u'获取消费详情失败')) @permission_required(ROLE.dealer, ROLE.subaccount) def getConsumptionDetail(request): # type: (WSGIRequest)->JsonResponse """ 消费详情应该附上成本信息(如果有) 通过RECHARGE查询CONSUME有两种情况. 一个是CONSUME一定在RECHARGE之后; 还有一个是 后支付, RECHARGE后建立起来. 这种情况下会在RECHARGE保存consumeid :param request: :return: """ id_ = request.GET.get('id') start_key = request.GET.get('startKey') filters = {'shard_filter': {"ownerId": request.GET.get('ownerId')}} if id_: filters.update({"id": str(id_)}) record = ClientConsumeModelProxy.get_one(**filters) # type: ConsumeRecord elif start_key: filters.update({"startKey": start_key, "hint": [("startKey", 1)]}) record = ClientConsumeModelProxy.get_one(foreign_id=request.GET.get('ref_id'), **filters) # type: ConsumeRecord else: logger.error("[getConsumptionDetail] not id and not startKey !") return JsonErrorResponse(description=u'参数错误,请刷新后再试') payload = record.to_detail() if payload.has_key('aggInfo'): newAggInfo = [remove_some_desc_for_consume(value, u'使用时长') for value in payload['aggInfo']] payload['aggInfo'] = newAggInfo if record.isNormal: device = Device.get_dev(record.devNo) # type: DeviceDict if device: payload.update({ 'showPG': device.support_power_graph }) else: payload.update({'showPG': False}) return JsonOkResponse(payload=payload) @require_POST @error_tolerate(logger=logger, nil=JsonErrorResponse(u"关闭订单失败")) @permission_required(ROLE.dealer) def closeOrder(request): payload = json.loads(request.body) orderId = payload.get("orderId", "") order = ClientConsumeModelProxy.get_one(id=orderId) order.status = "finished" order.save() return JsonOkResponse() @permission_required(ROLE.dealer, ROLE.subaccount) def groupConsumptionData(request): # type: (WSGIRequest)->JsonResponse """ 经销商旗下所有组的消费数据 :param request: :return: """ def get_group_info(g, _id): isM = _id == g.get("ownerId") if not isM: p = round_2_digits(float(g.get("partnerDict", dict()).get(_id, dict()).get("percent", 0))) else: fullPercent = 100 for _partner in g.get("partnerDict", dict()).values(): fullPercent -= float(_partner.get("percent", 0)) p = round_2_digits(float(fullPercent)) return isM, p current_user = request.user # type: Dealer dealerId = str(current_user.bossId) dealer = Dealer.objects.get(id=dealerId) pageIndex = int(request.GET.get("pageIndex", 1)) pageSize = int(request.GET.get("pageSize", 10)) startDate = request.GET.get("startTime") endDate = request.GET.get("endTime") startDate, endDate = current_user.limit_filter_date(startDate, endDate) if endDate < startDate: return JsonResponse({ 'result': 1, 'description': '', 'payload': { 'dataList': [], 'total': 0, 'adShow': current_user.adShow } }) else: searchKey = request.GET.get("searchKey", None) # 通过searchKey 获取组地址 作为查询的筛选条件 groupIds = Group.search_group_ids_of_dealer(dealerId, searchKey) + \ Group.search_group_ids_of_partner(dealerId, searchKey) # 每个地址组一个单位 ,根据地址组ID来完成对数据分页 groupIdSlice = groupIds[(pageIndex - 1) * pageSize: pageSize * pageIndex] groupStatisticMap = GroupDailyStatsModelProxy.get_groups_consumption_statistic(groupIds=groupIdSlice, startDate=startDate, endDate=endDate) groupDevCountMap = Device.get_device_count_by_group(groupIdSlice) agent = Agent.objects.get(id=current_user.agentId) isHiddenUsedTime = True if 'hiddenUsedTime' in agent.features else False dataList = list() for _groupId in groupIdSlice: groupStatistic = groupStatisticMap.get(_groupId, dict()) consumptionList = translate_consumption(groupStatistic, hides=agent.hide_consume_kinds_dealer) # 志高电子隐藏经销商后台消耗电量和电费成本统计 if "not_show_about_elec" in dealer.features: [consumptionList.pop(consumptionList.index(_c)) for _c in consumptionList if _c.get("name") == u"消耗电量"] [consumptionList.pop(consumptionList.index(_c)) for _c in consumptionList if _c.get("name") == u"电费成本"] if isHiddenUsedTime: consumptionList = [_c for _c in consumptionList if _c.get("name") != u"使用时长"] group = Group.get_group(_groupId) isManager, percent = get_group_info(group, dealerId) dataList.append({ 'groupName': group['groupName'], 'groupId': group['groupId'], 'address': group['address'], 'equipmentCount': groupDevCountMap.get(_groupId, 0), 'agentProfitShare': request.user.agentProfitShare, 'isManager': group.get("ownerId") == dealerId, 'consumptionList': consumptionList }) dataList = sorted(dataList, key=lambda x: float(x['equipmentCount']), reverse=True) total = len(groupIds) return JsonResponse({ 'result': 1, 'description': '', 'payload': { 'dataList': dataList, 'total': total, 'adShow': request.user.adShow } }) ################################################################################## #### `经销商信息设置` ############################################################### ################################################################################## @error_tolerate(logger=logger, nil=JsonErrorResponse(u'更新失败')) @permission_required(ROLE.dealer, ROLE.subaccount) def resetPassword(request): # type: (WSGIRequest)->JsonResponse dealer = request.user oldPassword = request.POST.get('oldPassword', "") if not oldPassword: return JsonErrorResponse(description=u"请输入旧密码") limitManager = LimitAttemptsManager('resetPassword', oldPassword) if limitManager.is_exceeded_limit(): return JsonErrorResponse(description=u'超出输入错误次数限制,请明日再试') if dealer.check_password(oldPassword): password = request.POST.get('password', "") if password == "": return JsonErrorResponse(description=u"请输入密码") else: dealer.set_password(password) request.session['password'] = password limitManager.clear() return JsonOkResponse() else: limitManager.incr() return JsonErrorResponse(description=u'旧密码输入错误,您还可输入%s次' % limitManager.times_left()) # : 开关 # : 可考虑以后整合成一个接口 # : @url('service/toggleSwitches') # : def f(request): # : dealer.update(**json.loads(request.body)) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'更新错误')) @permission_required(ROLE.dealer, ROLE.subaccount) def setWithdrawMsgSwitch(request): # type: (WSGIRequest)->JsonResponse ownerId = str(request.user.bossId) payload = json.loads(request.body) if request.body else {} if not payload: return JsonResponse({"result": 0, "description": u'数据不完整, 更新失败', 'payload': {}}) if payload['on'] and (not request.user.isManagerialOpenIdBound): return JsonResponse({"result":-1, "description": u"请先绑定微信号接收消息"}) updated = Dealer.objects(id=ownerId).update(withdrawlNotify=payload.get('on', False)) if updated: return JsonResponse({"result": 1, "description": None, 'payload': {}}) else: return JsonResponse({"result": 0, "description": u'更新失败', 'payload': {}}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'更新错误')) @permission_required(ROLE.dealer, ROLE.subaccount) def setOfflineNotifySwitch(request): # type: (WSGIRequest)->JsonResponse """ :param request: :return: """ ownerId = str(request.user.bossId) payload = json.loads(request.body) if request.body else {} if not payload: return JsonResponse({"result": 0, "description": u'数据不完整, 更新失败', 'payload': {}}) if payload['on'] and (not request.user.isManagerialOpenIdBound): return JsonResponse({"result":-1, "description": u"请先绑定微信号接收消息"}) updated = Dealer.objects(id=ownerId).update(offlineNotifySwitch=payload.get('on', False)) if updated: return JsonResponse({"result": 1, "description": None, 'payload': {}}) else: return JsonResponse({"result": 0, "description": u'更新失败', 'payload': {}}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'更新错误')) @permission_required(ROLE.dealer, ROLE.subaccount) def saveOfflineNotifyTime(request): # type: (WSGIRequest)->JsonResponse """ :param request: :return: """ ownerId = str(request.user.bossId) payload = json.loads(request.body) if request.body else {} if not payload: return JsonResponse({"result": 0, "description": u'数据不完整, 更新失败', 'payload': {}}) if payload['offlineNotifyTime'] and (not request.user.isManagerialOpenIdBound): return JsonResponse({"result":-1, "description": u"请先绑定微信号接收消息"}) updated = Dealer.objects(id=ownerId).update(offlineNotifyTime=str(payload.get('offlineNotifyTime', ''))) if updated: return JsonResponse({"result": 1, "description": None, 'payload': {}}) else: return JsonResponse({"result": 0, "description": u'更新失败', 'payload': {}}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'更新错误')) @permission_required(ROLE.dealer, ROLE.subaccount) def toggleNewUserPaymentOrderPushSwitch(request): # type: (WSGIRequest)->JsonResponse """ 用户支付订单后,即时推送给经销商 :param request: :return: """ ownerId = str(request.user.bossId) payload = json.loads(request.body) if request.body else {} if not payload: return JsonResponse({"result": 0, "description": u'数据不完整, 更新失败', 'payload': {}}) if payload['on'] and (not request.user.isManagerialOpenIdBound): return JsonResponse({"result":-1, "description": u"请先绑定微信号接收消息"}) updated = Dealer.objects(id=ownerId).update(newUserPaymentOrderPushSwitch=payload.get('on', False)) if updated: return JsonResponse({"result": 1, "description": None, 'payload': {}}) else: return JsonResponse({"result": 0, "description": u'更新写入失败', 'payload': {}}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'更新错误')) @permission_required(ROLE.dealer, ROLE.subaccount) def toggleDailyIncomeReportPushSwitch(request): # type: (WSGIRequest)->JsonResponse """ 每日9点推送昨日报表 :param request: :return: """ ownerId = str(request.user.bossId) payload = json.loads(request.body) if request.body else {} if not payload: return JsonResponse({"result": 0, "description": u'数据不完整, 更新失败', 'payload': {}}) if payload['on'] and (not request.user.isManagerialOpenIdBound): return JsonResponse({"result":-1, "description": u"请先绑定微信号接收消息"}) updated = Dealer.objects(id=ownerId).update(dailyIncomeReportPushSwitch=payload.get('on', False)) if updated: return JsonResponse({"result": 1, "description": None, 'payload': {}}) else: return JsonResponse({"result": 0, "description": u'更新失败', 'payload': {}}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'查询错误')) @permission_required(ROLE.dealer, ROLE.subaccount) def paymentOrderRecords(request): # type: (WSGIRequest)->JsonResponse """ 经销商后台查询充值订单(仅仅查询充值订单的 退币一些列的不要展示了) :param request: :return: """ ownerId = str(request.user.bossId) payload = json.loads(request.body) pageIndex = payload.get("pageIndex") pageSize = payload.get("pageSize") startTime = payload.get("startTime") endTime = payload.get("endTime") if not endTime: endTime = datetime.datetime.now() else: endTime = get_tomorrow_zero_time(datetime.datetime.strptime(endTime, "%Y-%m-%d")) if not startTime: startTime = get_zero_time(endTime) else: startTime = get_zero_time(datetime.datetime.strptime(startTime, "%Y-%m-%d")) if startTime > endTime: startTime = endTime orderStatus = payload.get("orderStatus") groupInfo = payload.get("group", dict()) deviceInfo = payload.get("device", dict()) queryFilters = { 'dateTimeAdded': { '$gte': startTime, '$lt': endTime }, "via": { "$in": map(format, [ USER_RECHARGE_TYPE.RECHARGE_MIX, USER_RECHARGE_TYPE.RECHARGE, USER_RECHARGE_TYPE.RECHARGE_CARD, USER_RECHARGE_TYPE.RECHARGE_VIRTUAL_CARD, USER_RECHARGE_TYPE.RECHARGE_CASH, USER_RECHARGE_TYPE.RECHARGE_MONTHLY_PACKAGE, USER_RECHARGE_TYPE.RECHARGE_REDPACK, USER_RECHARGE_TYPE.RECHARGE_INSURANCE ]) } } search_key = payload.get('searchKey', None) if search_key: if len(search_key) < 15: dev = Device.get_dev_by_logicalCode(search_key) if dev: queryFilters.update({'devNo': dev.devNo}) if 'devNo' not in queryFilters: queryFilters.update({ '$or': [ {'orderNo': search_key}, {'wxOrderNo': search_key}, {'transactionId': search_key} ] }) else: # 订单的状态 if orderStatus: queryFilters.update({"result": orderStatus}) # 查找的逻辑 自下从上查找 依次是 设备 --> 组 --> 当前查询人 --> 空查询 # TODO 这个地方的信息安全性 完全依赖上次调度的接口, 目前没有做检查 记得加上 if deviceInfo: queryFilters.update({"devNo": deviceInfo.get("devNo"), "ownerId": deviceInfo.get("ownerId")}) elif groupInfo: queryFilters.update({"groupId": groupInfo.get("groupId"), "ownerId": groupInfo.get("ownerId")}) else: # TODO 这个地方有个BUG 经销商的ID 防止部分新加入的组合伙人 能看到之前组的经营统计信息 groupIds = list(set(Group.get_group_ids_of_dealer_and_partner(ownerId))) groups = Group.get_groups_by_group_ids(groupIds) dealer_id_list = list(set([group['ownerId'] for group in groups.values()])) queryFilters.update({ 'ownerId': {'$in': dealer_id_list}, 'groupId': {'$in': groupIds} }) logger.debug('query recharges between {} and {}. filters = {}'.format(startTime, endTime, queryFilters)) # 添加筛选条件 选出不是交易子单的订单 query_set = RechargeRecord.objects.filter(__raw__=queryFilters).filter(attachParas__tradeOrderId=None).order_by('-dateTimeAdded') # type: CustomQuerySet totalSum = query_set.sum(RechargeRecord.money.name) total_count = query_set.count() records = query_set.paginate(pageIndex, pageSize) dataList = list() for _item in records: # type: RechargeRecord # 订单的基本信息 data = { 'id': str(_item.id), 'ownerId': _item.ownerId, 'gateway': _item.gateway if _item.gateway else 'wechat', 'result': _item.result if _item.result else '', 'totalFee': _item.money if _item.money else 0, 'address': _item.address if _item.address else '', 'name': _item.groupName if _item.groupName else '', 'nickname': _item.nickname if _item.nickname else '', 'devTypeName': _item.dev_type_name, 'groupNumber': _item.groupNumber if _item.groupNumber else '', 'value': Device.get_logicalCode_by_devNo(_item.devNo) if _item.devNo else '', 'wechatTrxid': _item.wxOrderNo if _item.wxOrderNo else '', 'outTradeNo': _item.orderNo if _item.orderNo else '', 'createdTime': _item.to_datetime_str(_item.dateTimeAdded), 'description': _item.my_description if _item.my_description else '', 'userId': _item.openId if _item.openId else '', 'groupId': _item.groupId if _item.groupId else '', 'via': _item.via if _item.via else '', 'isQuickPay': _item.isQuickPay if _item.isQuickPay else False, 'startKey': _item.attachParas.get('startKey', '') if _item.result == 'success' else '', 'consumeId': _item.attachParas.get('consumeRecordId', ''), 'isLedgered': _item.is_ledgered, 'notLedgerDesc': _item.notLedgerDesc } # TODO 需要修改 加上子订单的信息 tradeOrders = RechargeRecord.objects.filter( openId=_item.openId, attachParas__tradeOrderId=str(_item.id) ) _subs = list() for _trade in tradeOrders: # type: RechargeRecord _subData = { 'id': str(_trade.id), 'ownerId': _trade.ownerId, 'gateway': _trade.gateway if _trade.gateway else 'wechat', 'result': _trade.result if _trade.result else '', 'totalFee': _trade.money if _trade.money else 0, 'address': _trade.address if _trade.address else '', 'name': _trade.groupName if _trade.groupName else '', 'nickname': _trade.nickname if _trade.nickname else '', 'devTypeName': _trade.dev_type_name, 'groupNumber': _trade.groupNumber if _trade.groupNumber else '', 'value': Device.get_logicalCode_by_devNo(_trade.devNo) if _trade.devNo else '', 'wechatTrxid': _trade.wxOrderNo if _trade.wxOrderNo else '', 'outTradeNo': _trade.orderNo if _trade.orderNo else '', 'createdTime': _trade.to_datetime_str(_trade.dateTimeAdded), 'description': _trade.my_description if _trade.my_description else '', 'userId': _trade.openId if _trade.openId else '', 'groupId': _trade.groupId if _trade.groupId else '', 'via': _trade.via if _trade.via else '', 'isQuickPay': _trade.isQuickPay if _trade.isQuickPay else False, 'startKey': _trade.attachParas.get('startKey', '') if _trade.result == 'success' else '', 'consumeId': _trade.attachParas.get('consumeRecordId', ''), 'isLedgered': _trade.is_ledgered, 'notLedgerDesc': _trade.notLedgerDesc } _subs.append(_subData) data["subs"] = _subs dataList.append(data) return JsonResponse({ "result": 1, "description": "", 'payload': { "page": pageIndex, "pageSize": pageSize, "total": total_count, "totalSum":totalSum, "items": dataList } }) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'查询错误')) @permission_required(ROLE.dealer, ROLE.subaccount) def consumeOrderRecords(request): # type: (WSGIRequest)->JsonResponse """ 经销商后台查询消费订单 :param request: :return: """ ownerId = str(request.user.bossId) payload = json.loads(request.body) pageIndex = payload.get("pageIndex") pageSize = payload.get("pageSize") startTime = payload.get("startTime") endTime = payload.get("endTime") if not endTime: endTime = datetime.datetime.now() else: endTime = get_tomorrow_zero_time(datetime.datetime.strptime(endTime, "%Y-%m-%d")) if not startTime: startTime = get_zero_time(endTime) else: startTime = get_zero_time(datetime.datetime.strptime(startTime, "%Y-%m-%d")) if startTime > endTime: startTime = endTime groupInfo = payload.get("group", dict()) deviceInfo = payload.get("device", dict()) filters = { 'dateTimeAdded': { '$gte': startTime, '$lt': endTime } } search_key = payload.get('searchKey', None) if search_key: if len(search_key) < 15: dev = Device.get_dev_by_logicalCode(search_key) if dev: filters.update({'devNo': dev.devNo}) if 'devNo' not in filters: filters.update({ 'orderNo': search_key }) else: # 查找的逻辑 自下从上查找 依次是 设备 --> 组 --> 当前查询人 --> 空查询 # TODO 这个地方的信息安全性 完全依赖上次调度的接口, 目前没有做检查 记得加上 if deviceInfo: filters.update({"devNo": deviceInfo.get("devNo"), "ownerId": deviceInfo.get("ownerId")}) elif groupInfo: filters.update({"groupId": groupInfo.get("groupId"), "ownerId": groupInfo.get("ownerId")}) else: # TODO 这个地方有个BUG 经销商的ID 防止部分新加入的组合伙人 能看到之前组的经营统计信息 groupIds = list(set(Group.get_group_ids_of_dealer_and_partner(ownerId))) groups = Group.get_groups_by_group_ids(groupIds) dealer_id_list = list(set([group['ownerId'] for group in groups.values()])) filters.update({ 'ownerId': {'$in': dealer_id_list}, 'groupId': {'$in': groupIds} }) logger.debug('query consumes between {} and {}. filters = {}'.format(startTime, endTime, filters)) records = ConsumeRecord.objects.filter(__raw__=filters).order_by("-dateTimeAdded") # type: CustomQuerySet count = records.count() dataList = [] for rcd in records.paginate(pageIndex, pageSize): try: dataList.append(rcd.to_detail()) except Exception as e: logger.exception(e) continue return JsonOkResponse(payload={"dataList": dataList, "total": count}) @permission_required(ROLE.dealer, ROLE.subaccount) def discountRuleData(request): # type: (WSGIRequest)->JsonResponse groupId = request.GET.get('groupId', None) ownerId = str(request.user.bossId) if groupId is None: ruleList = [] for k, v in request.user.format_default_discount.items(): ruleList.append({'ruleId': k, 'payAmount': k, 'coins': v}) return JsonResponse({"result": 1, "description": None, 'payload': {"ruleList": ruleList, "groupData": {}}}) else: group = Group.get_group(groupId) if group is None: return JsonResponse({"result": 0, "description": u"找不到组", 'payload': {}}) devNos = Device.get_devNos_by_group([groupId]) group['equipmentCount'] = len(devNos) if ownerId == group['ownerId']: group['isManager'] = True else: group['isManager'] = False ruleList = [] for k, v in group['ruleDict'].items(): ruleList.append({'ruleId': k, 'payAmount': k, 'coins': v}) return JsonResponse({"result": 1, "description": None, 'payload': {"ruleList": ruleList, "groupData": group}}) @permission_required(ROLE.dealer, ROLE.subaccount) def discountCardRuleData(request): """ 经销商端的卡优惠获取显示 # 新的规则修改为 如果经销商设置有卡优惠规则 返还卡优惠规则 如果经销商没有设置卡优惠规则 但是设置有金币优惠规则 返还金币优惠规则 两个都没有设置 默认卡优惠规则 :param request: :return: """ groupId = request.GET.get("groupId", None) # 没有组ID的情况获取的是经销商的默认 优惠套餐 ruleList = list() if not groupId: for k, v in request.user.format_card_discount.items(): ruleList.append({"ruleId": k, "payAmount": k, "coins": v}) return JsonOkResponse(payload={"ruleList": ruleList, "groupData": {}}) group = Group.get_group(groupId) if not group: return JsonErrorResponse(description=u"错误的地址信息") # 经销商没有设置过卡的优惠规则 if not group.get("cardRuleDict"): cardRuleDict = request.user.defaultCardDiscountConfig Group.objects.filter(id=groupId).update(cardRuleDic=cardRuleDict) Group.CacheMgr.invalid_group_cache([groupId]) group = Group.get_group(groupId) devNos = Device.get_devNos_by_group([groupId]) ownerId = str(request.user.bossId) group['equipmentCount'] = len(devNos) if ownerId == group['ownerId']: group['isManager'] = True else: group['isManager'] = False ruleList = [] for k, v in group['cardRuleDict'].items(): ruleList.append({'ruleId': k, 'payAmount': k, 'coins': v}) return JsonResponse({"result": 1, "description": None, 'payload': {"ruleList": ruleList, "groupData": group}}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'更新错误')) @permission_required(ROLE.dealer, ROLE.subaccount) def saveDiscountRule(request): # type: (WSGIRequest)->JsonResponse """ TODO TO REFACTOR :param request: :return: """ currentDealer = request.user # type: cast(Dealer) # 校验优惠规则 def check_rule_data(fields, rules): for ruleDict in rules: for field in fields: if len(str(ruleDict[field])) > 12: return False, u"%s数额超过限制" % ruleDict[field] try: float(ruleDict[field]) except ValueError: return False, u"%s类型错误,请输入数字" % ruleDict[field] return True, u'' def update_rule(ruleDict, rules): isNewlyAdded = lambda d: d["payAmount"] not in ruleDict.keys() if len(ruleDict) >= 10 and any(map(isNewlyAdded, rules)): raise ParameterError(u'最多只能设置10条优惠充值信息') for rule in rules: if rule['ruleId']: ruleDict.pop(str(rule['ruleId']), None) if rule['ruleId'] != 0 and (float(rule['coins']) in ruleDict.values()): raise ParameterError(u'同一套餐下,不能出现充不一样的钱,但是兑币的数目却相同') ruleDict.update({str(rule['payAmount']): float(rule['coins'])}) return ruleDict payload = json.loads(request.body) if request.body else {} ruleList = payload.get('ruleData', None) if ruleList is None: return JsonErrorResponse(description=u'没有找到正确的规则') status, msg = check_rule_data(["payAmount", "coins"], ruleList) if not status: return JsonErrorResponse(description=msg) groupId = payload.get('groupId', None) # groupId为空表示修改默认充值套餐 if groupId is None: try: newRuleDict = update_rule(currentDealer.format_default_discount, ruleList) currentDealer.update(defaultDiscountConfig=newRuleDict) return JsonResponse({"result": 1, "description": '', 'payload': {}}) except ParameterError as e: return JsonErrorResponse(description=e.message) else: try: group = Group.objects(id=groupId).first() # type: Group if not group: return JsonErrorResponse(description=u'组不存在,请刷新后再试') isRecovery = payload.get('isRecovery', 'N') if isRecovery == 'Y': rule_dict = currentDealer.format_default_discount else: rule_dict = group.format_rule_dict update_rule(rule_dict, ruleList) Group.update_group(group_id=groupId, ruleDict=rule_dict) return JsonResponse({"result": 1, "description": None, 'payload': {}}) except ParameterError as e: return JsonErrorResponse(description=e.message) @error_tolerate(logger=logger, nil=JsonErrorResponse(u"更新错误")) @permission_required(ROLE.dealer, ROLE.subaccount) def saveDiscountCardData(request): """ 保存卡优惠设置 :param request: :return: """ def _check(rules, fieldnames=None): """ 校验 ruleList 的每一个字段和字段值 :param rules: :param fieldnames: :return: """ if fieldnames is None: fieldnames = ["payAmount", "coins"] for ruleDict in rules: for field in fieldnames: if len(str(ruleDict[field])) > 12: return False, u"%s数额超过限制" % ruleDict[field] try: float(ruleDict[field]) except ValueError: return False, u"%s类型错误,请输入数字" % ruleDict[field] return True, u"" def _update(ruleDict, rules): """ 更新优惠套餐 :param ruleDict: :param rules: :return: """ isNewlyAdded = lambda d: d["payAmount"] not in ruleDict.keys() if len(ruleDict) >= 10 and any(map(isNewlyAdded, rules)): raise ParameterError(u'最多只能设置10条优惠充值信息') for rule in rules: if rule['ruleId']: ruleDict.pop(str(rule['ruleId']), None) if rule['ruleId'] != 0 and (float(rule['coins']) in ruleDict.values()): raise ParameterError(u'同一套餐下,不能出现充不一样的钱,但是兑币的数目却相同') ruleDict.update({str(rule['payAmount']): float(rule['coins'])}) return ruleDict payload = json.loads(request.body) if request.body else dict() ruleList = payload.get("ruleData", None) if ruleList is None: return JsonErrorResponse(description=u"请设置正确的优惠规则") status, msg = _check(ruleList) if not status: return JsonErrorResponse(description=msg) groupId = payload.get("groupId", None) if groupId is None: try: newDict = _update(request.user.format_card_discount, ruleList) request.user.update(defaultCardDiscountConfig=newDict) except ParameterError as e: return JsonErrorResponse(description=e.message) else: return JsonOkResponse(payload={}) else: try: group = Group.objects(id=groupId).first() # type: Group if not group: return JsonErrorResponse(description=u'组不存在,请刷新后再试') isRecovery = payload.get('isRecovery', 'N') # if isRecovery == 'Y': # rule_dict = request.user.format_card_discount # else: rule_dict = group.format_card_dict newDict = _update(rule_dict, ruleList) Group.update_group(group_id=groupId, cardRuleDict=newDict) except ParameterError as e: return JsonErrorResponse(description=e.message) else: return JsonOkResponse(payload={}) @permission_required(ROLE.dealer, ROLE.subaccount) def delDiscountRule(request): # type: (WSGIRequest)->JsonResponse ruleId = request.POST.get('ruleId', None) if not ruleId: return JsonResponse({"result": 0, "description": u"缺少参数ruleId或为空", 'payload': {}}) groupId = request.POST.get('groupId', None) if not groupId: default_discount = request.user.format_default_discount default_discount.pop(ruleId, None) request.user.update(defaultDiscountConfig=default_discount) return JsonResponse({"result": 1, "description": None, 'payload': {}}) else: try: group = Group.objects(id=str(groupId)).first() if not group: return JsonResponse({"result": 0, "description": u"组不存在,请刷新后再试", 'payload': {}}) rule_dict = group.format_rule_dict # type: dict rule_dict.pop(ruleId, None) Group.update_group(group_id=groupId, ruleDict=rule_dict) return JsonResponse({"result": 1, "description": None, 'payload': {}}) except Exception, e: logger.exception("update db error=%s,groupId=%s" % (e, groupId)) return JsonResponse({"result": 0, "description": u"更新异常,请重试", 'payload': {}}) @permission_required(ROLE.dealer, ROLE.subaccount) def delDiscountCardData(request): """ 删除卡优惠设置 :param request: :return: """ ruleId = request.POST.get('ruleId', None) if not ruleId: return JsonResponse({"result": 0, "description": u"缺少参数ruleId或为空", 'payload': {}}) groupId = request.POST.get('groupId', None) if not groupId: default_discount = request.user.format_card_discount default_discount.pop(ruleId, None) request.user.update(defaultCardDiscountConfig=default_discount) return JsonResponse({"result": 1, "description": None, 'payload': {}}) else: try: group = Group.objects(id=str(groupId)).first() if not group: return JsonResponse({"result": 0, "description": u"组不存在,请刷新后再试", 'payload': {}}) rule_dict = group.format_card_dict # type: dict rule_dict.pop(ruleId, None) Group.update_group(group_id=groupId, cardRuleDict=rule_dict) return JsonResponse({"result": 1, "description": None, 'payload': {}}) except Exception, e: logger.exception("update db error=%s,groupId=%s" % (e, groupId)) return JsonResponse({"result": 0, "description": u"更新异常,请重试", 'payload': {}}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'获取经销商信息错误')) @permission_required(ROLE.dealer, ROLE.subaccount) def accountInfo(request): # type: (WSGIRequest)->JsonResponse if check_role(request.user, ROLE.dealer): dealer = Dealer.objects(id=str(request.user.bossId)).get() # type: Dealer payload = dealer.to_dict() else: subaccount = SubAccount.objects(id=str(request.user.id)).get() # type: subaccount payload = subaccount.to_dict() agent = Agent.objects(id=payload['agentId']).first() # type: Agent payload['servicePhone'] = agent.service_phone payload['serviceQrcodeUrl'] = agent.serviceQrcodeUrl return JsonResponse({"result": 1, "description": None, 'payload': payload}) ####`经销商金融版块(提现,银行卡信息)` #################################################### @permission_required(ROLE.dealer, ROLE.subaccount) def walletData(request): # type: (WSGIRequest)->JsonResponse dealerId = str(request.user.bossId) dealer = Dealer.objects(id=dealerId).first() # type: Optional[Dealer] if not dealer: return JsonErrorResponse(description=u"没有找到经销商") my_source_key = dealer.current_wallet_withdraw_source_key inhouse_source_key = Agent.get_inhouse_prime_agent().current_wallet_withdraw_source_key device_income_list = [] for source_key, balance in dealer.deviceBalance.iteritems(): if WithdrawGateway.is_ledger(source_key) and balance.balance != RMB(0): device_income_list.append({ 'id': source_key, 'balance': balance.balance, 'name': current_platform(source_key, my_source_key), 'current': source_key == my_source_key }) ad_income_list = [] for source_key, balance in dealer.adBalance.iteritems(): if WithdrawGateway.is_ledger(source_key) and balance.balance != RMB(0): ad_income_list.append({ 'id': source_key, 'balance': balance.balance, 'name': current_platform(source_key, inhouse_source_key), 'current': source_key == inhouse_source_key }) ledger_income_list = [] for source_key, balance in dealer.ledgerBalance.iteritems(): if WithdrawGateway.is_ledger(source_key) and balance.balance != RMB(0): ledger_income_list.append({ 'id': source_key, 'balance': balance.balance, 'name': current_platform(source_key, inhouse_source_key), 'current': source_key == inhouse_source_key }) payload = { } if len(device_income_list) > 0: payload.update({ DEALER_INCOME_TYPE.DEVICE_INCOME: device_income_list }) if len(ad_income_list) > 0: payload.update({ DEALER_INCOME_TYPE.AD_INCOME: ad_income_list }) if len(ledger_income_list) > 0: payload.update({ DEALER_INCOME_TYPE.LEDGER_CONSUME: ledger_income_list }) return JsonResponse({'result': 1, 'description': '', 'payload': payload}) # 经销商获取提现短信验证码 @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def getWithdrawCode(request): # type: (WSGIRequest)->JsonResponse currentDealer = request.user # type: Dealer toNumber = request.user.username agentId = request.user.agentId agent = Agent.get_agent(agentId) productName = agent['productName'] if not currentDealer.monitorPhone: # 没有监管的,直接发送验证码到本机 status, msg = dealerWithdrawSMSProvider.get(phoneNumber=toNumber, productName=productName, vendor=SysParas.get_sms_vendor(request.user.smsVendor)) else: toNumber = currentDealer.monitorPhone status, msg = dealerMonitorWithdrawSMSProvider.get(phoneNumber=toNumber, productName=productName, vendor=SysParas.get_sms_vendor(request.user.smsVendor)) if not status: return JsonErrorResponse(description=msg) else: return JsonOkResponse() @permission_required(ROLE.dealer) def withdrawalsHistoryList(request): # type: (WSGIRequest)->JsonResponse """ 需要连同整个提现数据层整改 :param request: :return: """ current_user = request.user # type: Dealer pageIndex = int(request.GET.get('pageIndex', 1)) pageSize = int(request.GET.get('pageSize', 10)) status = request.GET.get('status') ownerId = str(request.user.bossId) startTime = '2016-01-01' startTime, _ = current_user.limit_filter_date(startTime, None) startTime = datetime.datetime.strptime(startTime, "%Y-%m-%d") if status: records = WithdrawRecord.objects(ownerId=ownerId, role=request.user.role, status=status, postTime__gte=startTime).order_by('-postTime') else: records = WithdrawRecord.objects(ownerId=ownerId, role=request.user.role, postTime__gte=startTime).order_by('-postTime') return JsonResponse({ "result": 1, "description": None, 'payload': { "total": records.count(), "withdrawalTotal": RMB(records(status=WithdrawStatus.SUCCEEDED).sum('amount')), "dataList": [ { 'bankName': record.parentBankName, 'paymentId': str(record.id), 'withdrawalsDate': record.postTime.strftime("%Y-%m-%d %H:%M:%S"), 'amount': record.amount, 'statusText': translate_withdraw_state(record.status), 'refunded': record.refunded } for record in records.paginate(pageIndex, pageSize) ] } }) @permission_required(ROLE.dealer) def dealerWithdraw(request): # type: (WSGIRequest)->JsonResponse """ :param request: :return: """ currentDealer = request.user # type: cast(Dealer) payload = json.loads(request.body) open_id = payload.get('openId') if not open_id: return JsonResponse({"result": 0, "description": u'鉴权失败,请刷新后再试', 'payload': {}}) request.user.withdraw_open_id = open_id amount = RMB(payload.get('amount', 0.0)) pay_type = payload.get('payType') assert pay_type in ( WITHDRAW_PAY_TYPE.WECHAT, WITHDRAW_PAY_TYPE.BANK, WITHDRAW_PAY_TYPE.ALIPAY), 'not support this pay type' assert amount > RMB(0), 'amount must be bigger than zero' status, msg = request.user.withdraw_sms_provider.verify(phoneNumber=request.user.withdraw_sms_phone_number, smsCode=payload.get('code')) if not status: return JsonResponse({"result": 0, "description": msg, 'payload': {}}) withdraw_service = DealerWithdrawService(payee=request.user, income_type=payload.get('sourceType'), amount=amount, pay_type=pay_type, bank_card_no=payload.get('bankAccount', '')) result = withdraw_service.execute(source_key=payload.get('sourceId'), recurrent=False) logger.debug('withdraw result is: {}'.format(result)) return JsonResponse(result) @permission_required(ROLE.dealer, ROLE.subaccount) def paymentInfo(request): # type: (WSGIRequest)->JsonResponse """ 展示提现页面数据 :param request: :return: """ ownerId = str(request.user.bossId) paymentId = request.GET.get('paymentId', None) if not paymentId: return JsonErrorResponse(description=u'没有提供提现单ID') record = WithdrawRecord.objects(id=str(paymentId)).first() # type: Optional[WithdrawRecord] if not record: return JsonErrorResponse(description=u"没有找到提现记录") return JsonOkResponse( payload={ 'type': record.parentBankName, 'amount': record.amount, 'preBalance': record.balance, 'serviceFee': record.serviceFee, 'actualPay': record.actualPay, 'refunded': record.refunded, 'statusText': translate_withdraw_state(record.status), 'description': record.description, 'withdrawalsDate': record.postTime.strftime("%Y-%m-%d %H:%M:%S") } ) @permission_required(ROLE.dealer) def getDealerAutoWithdrawCode(request): # type: (WSGIRequest)->JsonResponse """ 经销商确认开启自动提现 :param request: :return: """ try: phoneNumber = request.GET.get('phoneNumber', None) if not phoneNumber: return JsonErrorResponse(description=u'手机号码为空') agent = Agent.get_agent(request.user.agentId) productName = agent['productName'] status, msg = dealerAutoWithdrawSMSProvider.get(phoneNumber=phoneNumber, productName=productName, vendor=SysParas.get_sms_vendor(request.user.smsVendor)) if not status: return JsonErrorResponse(description=msg) else: return JsonOkResponse() except Exception as e: logger.exception(e) return JsonErrorResponse() #### `Utils related` ########################################################### @permission_required(ROLE.dealer, ROLE.subaccount) def deviceMem(request): # type: (WSGIRequest)->JsonResponse logicalCode = request.GET.get('logicalCode') if not logicalCode: return JsonErrorResponse(description=u'未提供设备逻辑编码') devNo = Device.get_devNo_by_logicalCode(logicalCode) dev = Device.get_dev(devNo) return JsonResponse(dev) @permission_required(ROLE.dealer, ROLE.subaccount) def deviceInfo(request): # type: (WSGIRequest)->JsonResponse logicalCode = request.GET.get('logicalCode', '') devNo = Device.get_devNo_by_logicalCode(logicalCode) dev = Device.get_dev(devNo) if dev is None: return JsonErrorResponse(description=u'设备不存在') return JsonResponse(MessageSender.send(dev, DeviceCmdCode.GET_DEVINFO, {'IMEI': devNo})) @permission_required(ROLE.dealer, ROLE.subaccount) def getServiceInfo(request): # type: (WSGIRequest)->JsonResponse currentDealer = request.user.myBoss # type: Optional[Dealer] if not currentDealer: return JsonResponse({"result": 0, "description": u"没有找到经销商"}) value = { "qrcodeUrl": currentDealer.qrcodeUrl, "serviceName": currentDealer.serviceName, "servicePhone": currentDealer.servicePhone } return JsonResponse({"result": 1, "description": "", 'payload': value}) @permission_required(ROLE.dealer) def saveServiceInfo(request): # type: (WSGIRequest)->JsonResponse ownerId = request.user.bossId # type: ObjectId qrcodeUrl = request.POST.get('qrcodeUrl') serviceName = request.POST.get('serviceName') if serviceName: if NAME_RE.match(serviceName) is None: logger.error('name formatting error, name=%s' % serviceName) return JsonResponse({"result": 0, "description": u"请输入正确格式的名称, 2-20位"}) servicePhone = request.POST.get('servicePhone') if servicePhone: if PHONE_NUMBER_RE.match(servicePhone) is None: logger.error('phone number format error, phone=%s' % servicePhone) return JsonResponse({"result": 0, "description": u"请输入正确的手机号码"}) status, desc = dealerRegisterSMSProvider.verify(servicePhone, request.POST.get('code')) if not status: return JsonErrorResponse(desc) result = Dealer.update_dealer(ownerId, qrcodeUrl=qrcodeUrl, serviceName=serviceName, servicePhone=servicePhone) if not result: return JsonResponse({"result": 0, "description": u"更新经销商服务信息错误"}) return JsonResponse({"result": 1, "description": "", 'payload': {}}) # : 报告老板 @permission_required(ROLE.dealer, ROLE.subaccount) def userFeedbackRecords(request): # type: (WSGIRequest)->JsonResponse """ 获取用户反馈记录 :param request: :return: """ ownerId = str(request.user.bossId) searchKey = request.GET.get('searchKey', '') feedType = request.GET.get('feedType', '') pageIndex = int(request.GET.get('pageIndex', '1')) pageSize = int(request.GET.get('pageSize', '10')) status = request.GET.get('status', None) if status and status != 'null': status = int(status) else: status = None dateStart = request.GET.get('dateStart', '') if dateStart == '': startTime = '2000-01-01 00:00:00' else: startTime = dateStart + " 00:00:00" dateEnd = request.GET.get('dateEnd', '') if dateEnd == '': endTime = '2100-01-01 00:00:00' else: endTime = dateEnd + " 23:59:59" query = { 'ownerId': str(ownerId), '$and': [ { 'createTime': { '$gte': startTime } }, { 'createTime': { '$lte': endTime } }, ], } if feedType: if feedType == 'other': feed_type_list = ['refund', 'upper'] query.update({ 'feedType': {'$in': feed_type_list}, 'consumeRecordOrderNo': {'$in': [None, '']} }) else: feed_type_list = [feedType] query.update({ 'feedType': {'$in': feed_type_list} }) if status is not None: query.update({ 'status': status }) results = FeedBack.objects(__raw__ = query).search(searchKey).order_by('-createTime') total = results.count() rv = [] for item in results.paginate(pageIndex, pageSize): # type: FeedBack rv.append(item.summary) data = {'page': pageIndex, 'total': total, 'pageSize': pageSize, 'items': rv} return JsonResponse({'result': 1, 'description': "", 'payload': data}) @permission_required(ROLE.dealer, ROLE.subaccount) def userFeedbackInfo(request): # type: (WSGIRequest)->JsonResponse fdId = str(request.GET.get('id')) fd = FeedBack.objects(id = fdId).first() # type: FeedBack if not fd: return JsonResponse({'result': 0, 'description': u"投诉订单不存在,请刷新页面重试", 'payload': {}}) else: return JsonResponse({'result': 1, 'description': "", 'payload': fd.detail}) @error_tolerate(logger = logger, nil = JsonErrorResponse(u'处理失败')) @permission_required(ROLE.dealer, ROLE.subaccount) def userFeedbackHandle(request): # type: (WSGIRequest)->JsonResponse """ :param request: :return: """ payload = json.loads(request.body) if request.body else {} if not payload: return JsonErrorResponse(description = u'传入数据为空') action = payload.get('action') if not action: return JsonOkResponse() dealerRemark = payload.get('dealerRemark', u'(未填写回复内容)') dealerImgList = payload.get('dealerImgList', []) options = {} if dealerRemark is None else {'dealerRemark': dealerRemark, 'dealerImgList': dealerImgList} feedback = FeedBack.objects(id = payload['id']).first() # type: Optional[FeedBack] if not feedback: return JsonErrorResponse(description = u'没有找到该反馈单') dealer = Dealer.objects(id = feedback.ownerId).first() # type: Optional[Dealer] if not dealer: return JsonErrorResponse(description = u'未找到该反馈单的经销商') feedType = feedback.feedType if feedback.my_logicalCode: device = Device.objects(logicalCode = feedback.my_logicalCode).first() # type: Optional[Device] else: device = None if not device: return JsonErrorResponse(description = u'找不到相关设备') wechat_mp_proxy = get_wechat_user_manager_mp_proxy(dealer) # type: WechatClientProxy user = MyUser.objects(openId = feedback.openId, groupId = feedback.my_group_id).first() # type: Optional[MyUser] if not user: logger.warning('user not exists for feedback'.format(feedback.openId, str(feedback.id))) if action in ['close', 'reject']: feedback.handle(action, **options) wechat_mp_proxy.notify(user.managerialOpenId, 'feedback_process', **{ 'title': u'您反馈的问题已经处理' if action == 'close' else u'您反馈的问题已经被驳回', 'event': '%s:%s' % (feedback.message_type, feedback.description), 'remark': '%s: %s' % (u'设备老板回复', dealerRemark), 'finishTime': datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") }) if user else None return JsonOkResponse() elif action == 'stop': assert feedType == 'fault', u'投诉类型错误' device.set_fault() feedback.handle(action, **options) wechat_mp_proxy.notify(user.managerialOpenId, 'feedback_process', **{ 'title': u'您反馈的问题已经处理', 'event': u'设备已经暂停使用,等待维修中', 'remark': '%s: %s' % (u'设备老板回复', dealerRemark), 'finishTime': datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") }) if user else None return JsonResponse({'result': 1, 'description': "", 'payload': {}}) elif action == 'refund': if not user: return JsonErrorResponse(description = u'用户不存在,无法派币') agent = Agent.objects.get(id = request.user.agentId) if 'coinIsMoney' in agent.features: return JsonResponse({'result': 2, 'description': u"代理商的配置,不允许给用户派币", 'payload': {}}) refundCoins = VirtualCoin(payload.get('refundCoins')) if refundCoins > VirtualCoin(0): inced = user.incr_balance(refundCoins) if not inced: logger.error('failed to incr balance for %r' % (user,)) return JsonErrorResponse(description = u'退币失败') RechargeRecord.from_feedback(feedback, refundCoins).save() feedback.handle(action, **options) wechat_mp_proxy.notify(user.managerialOpenId, 'feedback_process', **{ 'title': u'您反馈的问题已经处理', 'event': u'%s:%s' % (feedback.message_type, feedback.description), 'remark': '%s: %s' % (u'设备老板回复', dealerRemark), 'finishTime': datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") }) if user else None return JsonOkResponse() else: logger.warning('invalid action for feedback'.format(action, str(feedback.id))) return JsonOkResponse() @error_tolerate(logger = logger, nil = JsonErrorResponse(u'处理失败')) @permission_required(ROLE.dealer, ROLE.subaccount) def userFeedbackBatchHandle(request): # type: (WSGIRequest)->JsonResponse """ :param request: :return: """ payload = json.loads(request.body) if request.body else {} if not payload: return JsonErrorResponse(description = u'传入数据为空') dealerRemark = payload.get('dealerRemark') options = {} if dealerRemark is None else {'dealerRemark': dealerRemark} feedbacks = FeedBack.objects(id__in = payload['ids']) if feedbacks.count() == 0: return JsonErrorResponse(description = u'没有找到反馈单') for feedback in feedbacks: feedback.handle('close', **options) dealer = Dealer.objects(id = feedback.ownerId).first() # type: Optional[Dealer] if not dealer: logger.warning( 'not find this dealer for feedback'.format(feedback.ownerId, str(feedback.id))) continue wechat_mp_proxy = get_wechat_user_manager_mp_proxy(dealer) # type: WechatClientProxy user = MyUser.objects(openId = feedback.openId, groupId = feedback.my_group_id).first() # type: Optional[MyUser] if not user: logger.warning( 'not find this user for feedback'.format(feedback.openId, str(feedback.id))) continue wechat_mp_proxy.notify(user.managerialOpenId, 'feedback_process', **{ 'title': u'您反馈的问题已经处理', 'event': '%s:%s' % (feedback.message_type, feedback.description), 'finishTime': datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") }) return JsonOkResponse() @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer, ROLE.subaccount) def getCustomerDetailInfo(request): # type: (WSGIRequest)->JsonResponse """ 获取用户部分详细信息,如累计充值 :param request: :return: """ customerOpenId = request.GET.get('id') if not customerOpenId: return JsonErrorResponse(description=u'传入用户ID为空,无法获取详情') ownerId = request.user.bossId groupIds = list(set(Group.get_group_ids_of_dealer_and_partner(ownerId))) users = MyUser.get_collection().find({"openId": customerOpenId, "groupId": {"$in": groupIds}}) rechargeTotal = RMB(0) bestowTotal = RMB(0) consumptionTotal = RMB(0) balance = RMB(0) nickname = "" phone = "" openId = "" idStr = "" breakRuleTimes = 0 orderRemindType = 2 for user in users: nickname = user.get('nickname', "") balance += (RMB(user.get("chargeBalance", 0)) + RMB(user.get("bestowBalance", 0))) rechargeTotal += RMB(user.get("total_recharged", 0)) bestowTotal += RMB(user.get("total_bestow", 0)) consumptionTotal += RMB(user.get("total_consumed", 0)) openId = user.get("openId", "") idStr = str(user.get('_id', '')) if user.get('blacklistConfig', {}).get('orderRemindType', 2) != 2: orderRemindType = user['blacklistConfig']['orderRemindType'] if user.get('blacklistConfig', {}).get('breakRuleTimes', 0) != 0: breakRuleTimes = user['blacklistConfig']['breakRuleTimes'] if breakRuleTimes > 0 and orderRemindType != 0: orderRemindType = 0 us = MyUser.objects(openId=user['openId'], groupId__in=groupIds) for _ in us: _.blacklistConfig['orderRemindType'] = orderRemindType _.save() status = "black" if check_black_user(dealerId=str(ownerId), openId=openId) else "white" if idStr: user = MyUser.objects.filter(id=idStr).first() phone = user.phone return JsonResponse({ 'result': 1, 'description': None, 'payload': { 'balance': balance, 'nickname': nickname, 'phone': phone, 'rechargeTotal': rechargeTotal, 'consumptionTotal': consumptionTotal, 'status': status, 'breakRuleTimes': breakRuleTimes, 'orderRemindType': orderRemindType } }) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer, ROLE.subaccount) def getCustomerListUnderDealer(request): """ 获取经销商名下的用户 按照openId做归并 查询需要根据特性来决定是否做手机号码查询""" pageIndex = int(request.GET.get('pageIndex', 1)) pageSize = int(request.GET.get('pageSize', 10)) searchKey = request.GET.get('searchKey', "") sortKey = request.GET.get('sortName', 'last_login') sortOrder = request.GET.get('sortType', 'des') isNew = True if request.GET.get('isNew', 'false') == 'true' else False ownerId = request.user.bossId groupIds = Group.get_group_ids_of_dealer_and_partner(ownerId=ownerId) # 获取用户默认头像 default_avatar = Agent.get_agent(request.user.agentId).get("productLogo") sortFilters = True if sortOrder == "des" else False groupFilters = { "_id": "$openId", "chargeBalance": {"$sum": "$chargeBalance"}, "bestowBalance": {"$sum": "$bestowBalance"}, "total_recharged": {"$sum": "$total_recharged"}, "total_bestow": {"$sum": "$total_bestow"}, "total_consumed": {"$sum": "$total_consumed"}, "nickname": {"$first": "$nickname"}, "sex": {"$first": "$sex"}, "avatar": {"$first": "$avatar"}, "openId": {"$first": "$openId"}, "last_login": {"$max": "$last_login"} } matchFilters = { "groupId": {"$in": groupIds} } by_phone = False by_user_id = False by_others = False if re.match(r'1[3-9][0-9]{9}$', searchKey): by_phone = True elif re.match(r'^[0-9]{5,10}$', searchKey): by_user_id = True else: by_others = True # 符合手机号码的正则 if by_phone or by_user_id: if by_phone: agent = Agent.objects.filter(id = str(request.user.myBoss.agentId)).first() # type: Agent if agent.supports('user_identify'): user = MyUser.objects.filter(phoneNumber = searchKey).first() else: user = UniqueUser.objects.filter(phone = searchKey).first() # type: UniqueUser else: user = UniqueUser.objects.filter(userId=searchKey).first() # type: UniqueUser if not user: return JsonErrorResponse(description=u"未查询到该用户") matchFilters.update({ 'openId': user.openId }) else: startTime = request.GET.get('startTime', None) endTime = request.GET.get('endTime', None) if startTime: startDataTime = to_datetime(startTime + ' 00:00:00') now = datetime.datetime.now() if not endTime: endDateTime = now + datetime.timedelta(days=1) else: endDateTime = to_datetime(endTime, "%Y-%m-%d") if endDateTime > now: endDateTime = now endDateTime = endDateTime + datetime.timedelta(days=1) if startDataTime >= endDateTime: endDateTime = startDataTime + datetime.timedelta(days=1) timeFilters = { "$gte": startDataTime, "$lt": endDateTime } if isNew: timeKey = "dateTimeAdded" else: timeKey = "last_login" matchFilters.update({ timeKey: timeFilters }) if searchKey: matchFilters.update({ "nickname": {"$regex": "%s" % searchKey} }) users = MyUser.get_collection().aggregate([ {"$match": matchFilters}, {"$group": groupFilters}, ]) totalUsers = list(users) if sortKey == "last_login": totalUsers.sort(key=lambda x: x.get(sortKey), reverse=sortFilters) else: totalUsers.sort(key=lambda x: VirtualCoin(x.get(sortKey)), reverse=sortFilters) tempUsers = totalUsers[(pageIndex - 1) * pageSize: pageIndex * pageSize] for user in tempUsers: if not user["avatar"]: user["avatar"] = default_avatar if 'total_recharged' in user: user['total_recharged'] = RMB(user['total_recharged']) if 'total_consumed' in user: user['total_consumed'] = RMB(user['total_consumed']) if 'chargeBalance' or 'bestowBalance' in user: user["chargeBalance"] = RMB(user.get("chargeBalance", 0)) user["bestowBalance"] = RMB(user.get("bestowBalance", 0)) user['balance'] = user['chargeBalance'] + user['bestowBalance'] return JsonResponse({ "result": 1, "description": None, "payload": { "total": len(totalUsers), "dataList": tempUsers } }) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer, ROLE.subaccount) def getRechargeRecordByCustomer(request): # type: (WSGIRequest)->JsonResponse """ 由用户详情 查询用户的充值记录 :param request: :return: """ pageIndex = int(request.GET.get("pageIndex")) pageSize = int(request.GET.get("pageSize")) openId = request.GET.get("id") cardId = request.GET.get("cardTicketId") # 直接查看某一张虚拟卡的充值记录 startTime = request.GET.get('startTime', Const.QUERY_START_DATE) endTime = request.GET.get('endTime', datetime.datetime.now().strftime('%Y-%m-%d')) if cardId: orderNoList = VirtualCardRechargeRecord.get_link_orderNo_list( cardId = cardId, startTime = to_datetime(startTime, '%Y-%m-%d'), endTime = to_datetime(endTime, '%Y-%m-%d')) queryFilter = { 'orderNo__in': orderNoList } else: queryFilter = { 'ownerId__in': Dealer.get_cooperative_dealer_ids(str(request.user.bossId)), "openId": openId, "result": "success", "via__in": map(format, [ USER_RECHARGE_TYPE.RECHARGE, USER_RECHARGE_TYPE.RECHARGE_CARD, USER_RECHARGE_TYPE.RECHARGE_VIRTUAL_CARD, USER_RECHARGE_TYPE.RECHARGE_CASH, USER_RECHARGE_TYPE.RECHARGE_MONTHLY_PACKAGE ]), 'hint': [("openId", 1)] } records = RechargeRecord.objects.filter( dateTimeAdded__gte=to_datetime(startTime, '%Y-%m-%d'), dateTimeAdded__lt=to_datetime(endTime, '%Y-%m-%d'), **queryFilter ) dataList = list() for record in records.paginate(pageIndex, pageSize): _data = { "gateway": record.gateway or 'wechat', "createdTime": record.created_date, "totalFee": record.money, "gatewayTradeNo": record.wxOrderNo, "outTradeNo": record.orderNo, "address": record.address, "name": record.groupName, "groupNumber": record.groupNumber, "devTypeName": record.dev_type_name, "logicalCode": record.logicalCode, "isQuickPay": record.isQuickPay, "result": getattr(record, "result", 'success'), "description": getattr(record, "description", ''), "via": record.via, "coins": record.coins } if "refundOrder" in request.user.features: _data["showRefund"] = (record.is_refund_available(request.user)) and (not record.has_refund_order) dataList.append(_data) total = pageIndex * pageSize if len(dataList) < pageSize else (pageIndex + 1) * pageSize return JsonResponse({'result': 1, 'description': "", 'payload': {'dataList': dataList, 'total': total}}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer, ROLE.subaccount) def getConsumptionRecordByCustomer(request): # type: (WSGIRequest)->JsonResponse """ :param request: :return: """ pageIndex = int(request.GET.get("pageIndex", 1)) pageSize = int(request.GET.get("pageSize", 10)) openId = request.GET.get("id") groupId = request.GET.get("groupId") lastYear = datetime.date((datetime.date.today().year - 1), datetime.date.today().month, datetime.date.today().day).strftime("%Y-%m-%d") startTime = request.GET.get('startTime', lastYear) endTime = request.GET.get('endTime', datetime.datetime.now().strftime('%Y-%m-%d')) queryFilter = {"ownerId": str(request.user.bossId), "openId": openId} if groupId: queryFilter.update({"groupId": groupId}) records = ClientConsumeModelProxy.get_data_list(startTime=startTime, endTime=endTime, **queryFilter) # 修改 列表仅仅展示基础数据 详细信息在详单中查询 dataList = [] for record in records.paginate(pageIndex, pageSize): newData = { "groupName": record.groupName, "groupNumber": record.groupNumber, "devTypeName": record.devTypeName, "logicalCode": record.logicalCode, "createdTime": record.dateTimeAdded, "orderNo": record.orderNo, "id": str(record.id), "ownerId": record.ownerId } newData.update(record.service) dev = Device.get_dev_by_logicalCode(record.logicalCode) # type: DeviceDict if dev and dev.is_registered and dev.ownerId == record.ownerId: if (record.devTypeCode or dev.devTypeCode) == Const.DEVICE_TYPE_CODE_HP_GATE: # 霍珀道闸分支 newData.update({'desc': record.servicedInfo.get('oper', u'未知')}) elif record.devTypeCode in support_policy_weifule + support_policy_device: if record.status != ConsumeRecord.Status.FINISHED: if (datetime.datetime.now() - record.dateTimeAdded).total_seconds() > 60 * 60 * 12: newData.update({'desc': '超12小时未结束'}) if record.status == ConsumeRecord.Status.RUNNING: newData.update({'showStopButton': True}) if record.status == ConsumeRecord.Status.END: newData.update({'showStopButton': True}) else: continue dataList.append(newData) total = pageIndex * pageSize if len(dataList) < pageSize else (pageIndex + 1) * pageSize return JsonResponse({'result': 1, 'description': "", 'payload': {'dataList': dataList, 'total': total}}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer, ROLE.subaccount) def modifyCustomerBalance(request): # type: (WSGIRequest)->JsonResponse """ 给终端用户派币或扣币(通常情况不支持) :param request: :return: """ currentDealer = request.user.myBoss # type: Optional[Dealer] agent = Agent.objects.filter(id=str(currentDealer.agentId)).first() # type: Agent if 'disable_dealer_onPoints_and_sendCoins' in agent.features: return JsonResponse( {'result': 0, 'description': '设备无法使用该功能奥, 如有问题, 请联系代理商', 'payload': {}}) payload = json.loads(request.body) if request.body else {} if not payload: return JsonErrorResponse(description=u'传入数据为空') coins = VirtualCoin(payload.get('coins', 0.0)) desc = payload.get('description') customerOpenId = payload.get('userId') groupId = payload.get('groupId') ownerId = str(currentDealer.bossId) operator = currentDealer.nickname customer = MyUser.objects(groupId=groupId, openId=customerOpenId).first() # type: Optional[MyUser] if not customer: return JsonResponse({'result': 0, 'description': u'该用户不存在', 'payload': {}}) if coins < VirtualCoin(0) and -coins > customer.balance: return JsonResponse({'result': 0, 'description': u'最多只能扣除掉%s个币' % customer.balance, 'payload': {}}) agent = Agent.objects.get(id=currentDealer.agentId) if 'coinIsMoney' in agent.features: return JsonResponse({'result': 0, 'description': u'代理商的配置,不允许给用户派币', 'payload': {}}) group = Group.get_group(groupId) if group['ownerId'] != ownerId: return JsonResponse({'result': 0, 'description': u'不是您家设备喔,不能派币', 'payload': {}}) payload = { 'orderNo': str(uuid.uuid1()), 'openId': customerOpenId, 'coins': coins, 'description': desc, 'groupId': groupId, 'groupName': group.groupName, 'address': group.address, 'ownerId': ownerId, 'operator': operator, 'result': 'success', 'via': 'sendcoin' } record = RechargeRecord(**payload) customer.recharge(RMB(0), RMB(coins)) record.save() customer.account_recharge(record) if coins > VirtualCoin(0): try: task_caller( 'report_to_user_via_wechat', openId=customerOpenId, dealerId=str(request.user.bossId), templateName='refund_coins', **{ 'title': u'尊敬的客户,已经退回%s金币到您的余额,您下次可以接着使用。祝您生活愉快。' % coins, 'backCount': u'金币:%s' % coins, 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') } ) except Exception as e: logger.exception(e) return JsonResponse({'result': 1, 'description': None, 'payload': {}}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer, ROLE.subaccount) def getModifyCustomerBalanceRecord(request): # type: (WSGIRequest)->JsonResponse """ 获取派币记录 :param request: :return: """ pageIndex = int(request.GET.get('pageIndex', 1)) pageSize = int(request.GET.get('pageSize', 10)) customerOpenId = request.GET.get('id', None) user = MyUser.objects(openId=customerOpenId).first() if not user: records = RechargeRecord.objects( ownerId=str(request.user.bossId), via='sendcoin').order_by('-dateTimeAdded').skip((pageIndex - 1) * pageSize).limit(pageSize) else: records = RechargeRecord.objects( ownerId=str(request.user.bossId), openId=customerOpenId, via='sendcoin').order_by('-dateTimeAdded').skip((pageIndex - 1) * pageSize).limit(pageSize) dataList = [] if not user: for r in records: u = MyUser.objects(openId=r.openId).first() if u is None: logger.error('invalid openId, openId=%s' % r.openId) continue dataList.append({ 'name': u.nickname if u.nickname is not None else '', 'avatar': u.avatar, 'id': customerOpenId, 'remarks': r.my_description, 'operator': r.operator, 'coins': r.coins, 'groupName': r.groupName, 'createdTime': r.dateTimeAdded.strftime("%Y-%m-%d %H:%M:%S") }) else: dataList = [ { 'name': user.nickname if user.nickname is not None else '', 'avatar': user.avatar, 'id': customerOpenId, 'remarks': r.my_description, 'operator': r.operator, 'coins': r.coins, 'groupName': r.groupName, 'createdTime': r.dateTimeAdded.strftime("%Y-%m-%d %H:%M:%S") } for r in records ] count = records.count() if count <= pageSize: total = (pageIndex - 1) * pageSize + count else: total = (pageIndex - 1) * pageSize + 100 return JsonResponse( { 'result': 1, 'description': None, 'payload': { 'dataList': paginate(dataList, pageIndex, pageSize), 'total': total, 'sendCoinsTotal': VirtualCoin(records.sum('coins')) } } ) # 导出派币记录 @error_tolerate(logger=logger, nil=JsonErrorResponse(u"获取派币记录失败")) @permission_required(ROLE.dealer) def reportModifyCustomerBalanceRecord(request): """ 导出派币记录 """ dealer = request.user def get_offline_task_name(task_type, user, **kwargs): # type: (basestring, Dealer, Dict)->basestring tmp_list = [task_type, user.username] if 'logicalCode' in kwargs and kwargs['logicalCode']: tmp_list.append(u'设备编号_%s' % (kwargs['logicalCode'],)) if 'groupId' in kwargs and kwargs['groupId']: address = Group.get_group(kwargs['groupId']).get('address', '') tmp_list.append(u'地址_%s' % (address,)) tmp_list.append(u'%s至%s' % (kwargs['startTime'], kwargs['endTime'])) tmp_list.append(str(utils_datetime.generate_timestamp_ex())) return '-'.join(tmp_list).replace("/", "_") query_dict = { 'startTime': request.GET.get('startTime', '') + ' 00:00:00', 'endTime': request.GET.get('endTime', '') + ' 23:59:59', 'pageIndex': int(request.GET.get('pageIndex', 1)), 'pageSize': int(request.GET.get('pageSize', 10)), 'customerOpenId': request.GET.get('id', None), "ownerId": str(request.user.bossId), } offline_task_name = get_offline_task_name( task_type=u'地址用户充值消费情况统计报表', user=dealer, **query_dict) file_path, offline_task = OfflineTask.issue_export_report(offline_task_name=offline_task_name, process_func_name='export_modify_customer_balance_record_excel_from_db', task_type=OfflineTaskType.BUSINESS_REPORT, userid=str(dealer.id), role=ROLE.dealer) task_caller(func_name=offline_task.process_func_name, offline_task_id=str(offline_task.id), filepath=file_path, queryDict=query_dict) return JsonResponse({ 'result': 1, 'description': u"请前往离线任务查看任务处理情况", 'payload': str(offline_task.id)}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer, ROLE.subaccount) def getRefundRecord(request): # type: (WSGIRequest)->JsonResponse """ 获取退币记录 :param request: :return: """ pageIndex = int(request.GET.get('pageIndex', 1)) pageSize = int(request.GET.get('pageSize', 10)) customerOpenId = request.GET.get('id', None) if not customerOpenId: return JsonErrorResponse(description=u'提交的用户id为空') user = MyUser.objects(openId=customerOpenId).first().to_dict() records = RechargeRecord.objects(ownerId=str(request.user.bossId), openId=customerOpenId, via='refund').order_by("-dateTimeAdded") dealer = Dealer.objects(id=str(request.user.bossId)).get() dataList = [ { 'name': user['nickname'], 'avatar': user['avatar'], 'id': customerOpenId, 'description': r.my_description, 'operator': dealer.nickname, 'coins': r.coins, 'groupName': r.groupName, 'createdTime': r.dateTimeAdded.strftime("%Y-%m-%d %H:%M:%S") } for r in records ] total = records.count() return JsonResponse( { 'result': 1, 'description': None, 'payload': { 'dataList': paginate(dataList, pageIndex, pageSize), 'total': total, 'refundTotal': VirtualCoin(records.sum('coins')) } } ) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer, ROLE.subaccount) def payGateway(request): # type: (WSGIRequest)->JsonResponse current_user = request.user # type: Dealer try: # TODO # 此处流量卡传的是param 其他 加盟 api支付的都是传 params payload = json.loads(request.GET.get('param') or request.GET.get('params')) order_no = payload.get('orderNo') if not order_no: return JsonErrorResponse(u'参数错误,请刷新后再试') record = DealerRechargeRecord.objects(orderNo=order_no).first() # type: DealerRechargeRecord if not record: return JsonErrorResponse(u'订单不存在,请刷新后再试') payment_gateway = PaymentGateway.from_gateway_key( record.gateway, record.payGatewayKey, record.payAppType) # type: Optional[WechatPaymentGateway] logger.info('dealer wechat charge: gateway = %s; orderNo = %s, totalFee = %s' % ( repr(payment_gateway), order_no, record.totalFee)) OrderCacheMgr(record).initial() attach = {'dealerId': record.dealerId} body = record.get_body() # 转成以元为单位的钱,后面流程统一处理 money = RMB(record.totalFee) * Decimal('0.01') if payment_gateway.pay_app_type == PayAppType.WECHAT: data = payment_gateway.generate_js_payment_params( payOpenId=payload.get('openId'), out_trade_no=order_no, notify_url=PAY_NOTIFY_URL.WECHAT_PAY_BACK, money=money, body=body, attach=attach) data.update({ 'outTradeNo': record.orderNo, 'adShow': current_user.ad_show }) response = JsonResponse({'result': 1, 'description': '', 'payload': data}) else: raise Exception(cn(u'不支持该支付类型')) task_caller(func_name='poll_dealer_recharge_record', delay=PollRecordDefine.DELAY_BEFORE, expires=PollRecordDefine.TASK_EXPIRES, record_id=str(record.id), pay_app_type=payment_gateway.pay_app_type, interval=PollRecordDefine.WAIT_EACH_ROUND, total_count=PollRecordDefine.TOTAL_ROUNDS) return response except WeChatException as e: logger.exception(e) return JsonErrorResponse(description = e.tip) except Exception as e: logger.exception(e) return JsonErrorResponse(description=u'系统开小差了,请刷新后再试') @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer, ROLE.subaccount) def getDeviceCardList(request): # type: (WSGIRequest)->JsonResponse def cmp_expire_time(x, y): if not x['simExpireDate']: return 1 if not y['simExpireDate']: return -1 if x['simExpireDate'] > y['simExpireDate']: return -1 elif x['simExpireDate'] < y['simExpireDate']: return 1 else: return 0 searchKey = request.GET.get('searchKey', '') dealerId = str(request.user.bossId) agent = Agent.objects(id=request.user.agentId).first() # type: Optional[Agent] if not agent: logger.error('agent is not exist.'.format(request.user.agentId)) return JsonErrorResponse(description=u'系统错误') groupIds = Group.get_group_ids_of_dealer(dealerId) groupDict = Group.get_groups_by_group_ids(groupIds) devNoList = Device.get_devNos_by_group(groupIds) devices = Device.get_dev_by_nos(devNoList).values() annualTrafficCost = request.user.annualTrafficCost devList = [] for dev in devices: # type: DeviceDict try: if searchKey in dev['groupNumber'] or searchKey in dev.devNo or searchKey in dev[ 'remarks'] or searchKey in dev.logicalCode: group = groupDict.get(dev.groupId) if (settings.DEBUG and dev.logicalCode.startswith('DUMMY')) or dev.is_expired or dev.sim_expire_notify: item = { 'logicalCode': dev.logicalCode, 'devNo': dev.devNo, 'devTypeName': dev.devType['name'], 'groupName': group['groupName'], 'groupNumber': dev['groupNumber'], 'groupId': group['groupId'], 'simExpireDate': dev.fixedSimExpireDate, 'channelType': dev.channelType } devList.append(item) except Exception, e: logger.exception('[device]some error=%s' % e) continue devList.sort(cmp=cmp_expire_time) pageIndex = int(request.GET.get('pageIndex', 1)) pageSize = int(request.GET.get('pageSize', 100)) items = devList[(pageIndex - 1) * pageSize:pageIndex * pageSize] devObjs = { obj.devNo: obj for obj in Device.objects.filter(devNo__in=[item['devNo'] for item in items])} for item in items: dev_obj = devObjs[item['devNo']] # type: Device trafficCardCost = dev_obj.trafficCardCost if not trafficCardCost: if request.user.trafficCardCost: trafficCardCost = request.user.trafficCardCost else: trafficCardCost = agent.trafficCardCost item['price'] = trafficCardCost if trafficCardCost > annualTrafficCost else annualTrafficCost items = sorted(items, key=lambda x:x['groupId']) return JsonResponse({ 'result': 1, 'description': None, 'payload': {'page': pageIndex, 'total': len(devList), 'pageSize': pageSize, 'offset': 0, 'items': items} }) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer, ROLE.subaccount) def getSimRechargeOrderList(request): # type: (WSGIRequest)->JsonResponse filterQuery = Q( __raw__ = { 'dealerId': str(request.user.bossId), 'product': {'$in': [DealerRechargeRecord.ProductType.SimCard, DealerRechargeRecord.ProductType.AutoSimCard]} }) status = request.GET.get('status', None) if status: filterQuery &= Q(__raw__={'status': status}) else: filterQuery &= Q( __raw__={'status': {'$nin': [DealerRechargeRecord.PayState.Cancel, DealerRechargeRecord.PayState.Close]}}) searchKey = request.GET.get('searchKey', '') if searchKey: pattern = Regex.from_native(re.compile('.*' + searchKey + '.*')) filterQuery &= (Q(__raw__={'items': {'$elemMatch': {'name': {'$regex': pattern}}}}) | Q( __raw__={'orderNo': {"$regex": pattern}})) records = DealerRechargeRecord.objects( __raw__=filterQuery.to_query(DealerRechargeRecord)).order_by("-createdTime") items = [] for record in records: # type: DealerRechargeRecord item = { 'name': record.name, 'totalFee': str(RMB(float(record['totalFee']) / 100)), 'orderNo': record.orderNo, 'status': record.status, 'createdTime': record.createdTime, 'finishedTime': record.finishedTime } items.append(item) pageIndex = int(request.GET.get('pageIndex', 1)) pageSize = int(request.GET.get('pageSize', 10)) return JsonResponse({ 'result': 1, 'description': '', 'payload': { 'page': pageIndex, 'total': len(items), 'pageSize': pageSize, 'offset': 0, 'items': items[(pageIndex - 1) * pageSize:pageIndex * pageSize] } }) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer, ROLE.subaccount) def createSimRechargeOrder(request): # type: (WSGIRequest)->JsonResponse current_user = request.user # type: Dealer devNoList = set(request.POST.getlist('list[]')) payment_gateway = get_inhourse_wechat_env_pay_gateway( ROLE.dealer) # type: Union[WechatPaymentGateway] record = create_dealer_sim_charge_order(payment_gateway, current_user, devNoList) if record: return JsonResponse({'result': 1, 'description': u'创建订单成功', 'payload': record.orderNo}) else: return JsonErrorResponse(u'创建订单异常失败') @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer, ROLE.subaccount) def cancelSimRechargeOrder(request): # type: (WSGIRequest)->JsonResponse try: payload = json.loads(request.body) if request.body else {} if not payload: return JsonErrorResponse(description=u'数据不完整,请重试') order_no = payload['orderNo'] order = DealerRechargeRecord.objects(orderNo=order_no).first() # type: DealerRechargeRecord if not order: return JsonErrorResponse(u'订单不存在,请刷新后再试') if not order.is_unpay: return JsonErrorResponse(u'订单已经处理,无法取消') if order.cancel(): return JsonOkResponse('ok') else: return JsonErrorResponse(u'订单已经处理,无法取消') except Exception as e: logger.exception('unable to cancel dealer order, error=%s' % (e,)) return JsonErrorResponse(description=u"系统错误") @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer, ROLE.subaccount) def getSimRechargeOrderDetail(request): # type: (WSGIRequest)->JsonResponse try: orderNo = request.GET.get('orderNo') order = DealerRechargeRecord.objects(orderNo = orderNo).first() # type: DealerRechargeRecord if not order: return JsonErrorResponse(u'订单不存在,请刷新后再试') else: return JsonResponse({'result': 1, 'description': '', 'payload': { 'orderNo': order.orderNo, 'totalFee': '%.02f' % (float(order.totalFee) / 100), 'status': order.status, 'createdTime': order.createdTime, 'items': order.items }}) except Exception as e: logger.exception('get dealer pay order list failure, error = %s' % (e,)) return JsonErrorResponse(description = u'查询订单失败') @error_tolerate(nil=DefaultJsonErrorResponse) def getOwnerAgents(request): try: username = request.GET.get('username') managerId = request.GET.get('managerId') logger.debug('getOwnerAgents: username = %s; managerId = %s' % (username, managerId)) agents = [str(a.id) for a in Agent.objects(managerId=str(managerId)).all()] items = [] dealers = Dealer.get_collection().find({'username': username, 'agentId': {'$in': agents}}) for dealer in dealers: agentId = dealer['agentId'] agent = Agent.get_agent(agentId) item = { 'agentId': agentId, 'userHeadImg': agent['avatar'], 'agentLogoUrl': agent['productLogo'], 'agentBrandName': agent['productName'], 'displayName': agent['productName'] } items.append(item) return JsonResponse({ 'result': 1, 'description': None, 'payload': {'total': len(items), 'items': items} }) except Exception as e: logger.exception('get dealer owner agents failure, error = %s' % (e,)) return JsonErrorResponse(description=u'网络错误,请刷新后再试') @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer, ROLE.subaccount) def getEquipmentTotal(request): # type: (WSGIRequest)->JsonResponse dealerId = str(request.user.bossId) groupIds = Group.get_group_ids_of_dealer(dealerId) devNoList = Device.get_devNos_by_group(groupIds) return JsonResponse({'result': 1, 'description': '', 'payload': len(devNoList)}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'设备类型不支持')) @permission_required(ROLE.dealer, ROLE.subaccount) def getPackageList(request): # type: (WSGIRequest)->JsonResponse devTypeId = request.GET.get('typeId', None) if not devTypeId: return JsonResponse({'result': 0, 'description': u'设备类型为空', 'payload': {}}) dealer = request.user.myBoss # type: Dealer devType = DeviceType.objects.filter(id=str(devTypeId)).first() # type: DeviceType if devType['code'] in support_policy_weifule + support_policy_device: isTemp = request.GET.get('isTemp', None) == 'true' from apps.web.core.models import DriverAdapter adapter = DriverAdapter.get_driver_adapter(devType['code'], None) if adapter.support_device_package: payload = adapter.get_reg_model(dealer, devTypeId, isTemp=isTemp) return JsonResponse({'result': 1, 'description': None, 'payload': payload}) dataList = {} if devTypeId in dealer.defaultWashConfig: dataList = dealer.defaultWashConfig[devTypeId] if not dataList: dataList = DeviceType.objects(id=str(devTypeId)).get().package no_unit_list = filter(lambda x: x.get("unit") == None, dataList) if len(no_unit_list) == len(dataList): datalist = map(lambda x: (x.update({"unit": "分钟"}), x)[1], dataList) displaySwitchs = {} if hasattr(devType, "displayPriceSwitch"): displaySwitchs.update({"displayPriceSwitch": devType.displayPriceSwitch}) if hasattr(devType, "displayCoinsSwitch"): displaySwitchs.update({"displayCoinsSwitch": devType.displayCoinsSwitch}) if hasattr(devType, "displayTimeSwitch"): displaySwitchs.update({"displayTimeSwitch": devType.displayTimeSwitch}) if hasattr(devType, "setPulseAble"): displaySwitchs.update({"setPulseAble": devType.setPulseAble}) if hasattr(devType, "setBasePriceAble"): displaySwitchs.update({"setBasePriceAble": devType.setBasePriceAble}) if devType['code'] in [Const.DEVICE_TYPE_CODE_CAR_CHANGING_JINQUE, Const.DEVICE_TYPE_CODE_CAR_WEIFILE_HOME_JFPG,Const.DEVICE_TYPE_CODE_CAR_WEIFILE_HOME_DOUB_JFPG]: displaySwitchs = { 'displayPriceSwitch': True, 'displayCoinsSwitch': False, 'displayTimeSwitch': False, 'setPulseAble': False, 'setBasePriceAble': False, } return JsonResponse({'result': 1, 'description': None, 'payload': {'ruleList':dataList, 'displaySwitchs':displaySwitchs}}) # ## 经销商绑定微信(为了接受微信推送) @permission_required(ROLE.dealer, ROLE.subaccount) def getDealerBindWechatSMSCode(request): # type: (WSGIRequest)->JsonResponse """ :param request: :return: """ try: phoneNumber = request.user.username agent = Agent.get_agent(request.user.agentId) productName = agent['productName'] if not phoneNumber: return JsonResponse({'result': 0, 'description': u'手机号码为空'}) status, msg = dealerBindWechatSMSProvider.get(phoneNumber=phoneNumber, productName=productName, vendor=SysParas.get_sms_vendor(request.user.smsVendor)) if not status: return JsonResponse({'result': 0, 'description': msg}) else: return JsonResponse({'result': 1, 'description': ''}) except Exception, e: logger.exception('unable to get %s' % e) return JsonResponse({'result': 0, 'description': ''}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误')) @permission_required(ROLE.dealer, ROLE.subaccount) def verifyNewWechatBinding(request): # type: (WSGIRequest)->JsonResponse """ 跳转到微信授权页面绑定 :param request: :return: """ currentDealer = request.user # type: cast(Dealer) code = request.POST.get('code') if not code: return JsonErrorResponse(description=u'code未提供') status, msg = dealerBindWechatSMSProvider.verify(phoneNumber=request.user.username, smsCode=code) if not status: return JsonErrorResponse(description=msg) auth_bridge = get_wechat_auth_bridge(source=currentDealer, app_type=APP_TYPE.WECHAT_MANAGER) return JsonResponse( { 'result': 1, 'description': None, 'payload': { 'redirect_uri': auth_bridge.generate_auth_url_user_scope( redirect_uri=DEALER_BIND_WECHAT_URL) } }) @error_tolerate(logger=logger, nil=DealerBindIdResponseRedirect(result='error')) @permission_required(ROLE.dealer, ROLE.subaccount) def verifyNewWechatBindingCallback(request): # type: (WSGIRequest)->JsonResponse """ 绑定后台openId TODO: 加入变更记录 :param request: :return: """ auth_code = request.GET.get('code') if not auth_code: return JsonErrorResponse(description=u'未收到code,请刷新重试') currentDealer = request.user # type: cast(Dealer) auth_bridge = get_wechat_auth_bridge(source=currentDealer, app_type=APP_TYPE.WECHAT_MANAGER) user_info = auth_bridge.get_user_info(auth_code=auth_code) user_info_payload = { 'avatar': user_info['avatar'], 'country': user_info['country'], 'province': user_info['province'], 'city': user_info['city'], 'sex': user_info['sex'], 'nickname': user_info['nickname'] } logger.debug('dealer(id=%s) is binding wechat for messaging, bridge=%s' % (str(request.user.bossId), auth_bridge)) dealerWechatBindingUpdated = request.user.update( managerialAppId=auth_bridge.app.appid, managerialOpenId=user_info['openId'], wechatAuthUserInfo=user_info_payload, managerialWechatBoundTime=datetime.datetime.now()) if dealerWechatBindingUpdated: return DealerBindIdResponseRedirect(result='ok') else: return DealerBindIdResponseRedirect(result='error') @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误')) @permission_required(ROLE.dealer, ROLE.subaccount) def getBoundWechat(request): # type: (WSGIRequest)->JsonResponse """ 获取绑定后台openId的用户信息 :param request: :return: """ ownerId = str(request.user.bossId) dealer = Dealer.objects(id=ownerId).get() # type: Dealer return JsonResponse( { "result": 1, "description": None, 'payload': { "bound": dealer.isManagerialOpenIdBound, "avatar": dealer.wechatAuthUserInfo.get('avatar'), "sex": dealer.wechatAuthUserInfo.get('sex'), "nickname": dealer.wechatAuthUserInfo.get('nickname') } }) @permission_required(ROLE.dealer, ROLE.agent, ROLE.subaccount) def setAdShow(request): # type: (WSGIRequest)->JsonResponse try: payload = json.loads(request.body) if request.body else {} if not payload: return JsonErrorResponse(description=u'数据不完整,请重试') user = Dealer.objects.get(id=payload['id']) if 'id' in payload else request.user # type: Dealer adShow = payload.get('adShow', user.adShow) user.adShow = adShow user.save() return JsonResponse({"result": 1, "description": None, 'payload': {}}) except DoesNotExist, e: logger.exception("dealer does not exist, error = %s" % e) return JsonResponse({"result": 0, "description": u'经销商不存在', 'payload': {}}) except Exception, e: logger.exception("set adShow error = %s" % e) return JsonResponse({"result": 0, "description": u'系统错误', 'payload': {}}) @permission_required(ROLE.manager) def getDealerDetailList(request): # type: (WSGIRequest)->JsonResponse """ 厂商获取经销商详情 :param request: :return: """ def count_devices(ownerId): devNoList = [device['devNo'] for device in Device.get_collection().find({'ownerId': ownerId, 'groupId': {'$ne': ''}}, {'devNo': 1, '_id': 0})] allCount = len(devNoList) devDict = Device.get_dev_by_nos(devNoList) if not devDict: return 0, 0, 0 onlineCount = 0 for devNo, dev in devDict.items(): if dev["online"]: onlineCount += 1 offlineCount = allCount - onlineCount return onlineCount, offlineCount, allCount mid = str(request.user.id) pageIndex = int(request.GET.get('pageIndex', 1)) pageSize = int(request.GET.get('pageSize', 10)) agentId = request.GET.get('agentId', None) searchKey = request.GET.get('searchKey', None) dealers = Dealer.search(searchKey) agentMap = {str(agent.id): agent.username for agent in Agent.objects(managerId=mid)} agentIds = agentMap.keys() if agentId: dealers = dealers.filter(agentId=agentId) elif agentIds: dealers = dealers.filter(agentId__in=agentIds) total = dealers.count() dealers_per_page = dealers.skip((pageIndex - 1) * pageSize).limit(pageSize) dataList = [] for d in dealers_per_page: report = Accounting.getOwnerIncome(str(d.id), now=datetime.datetime.now()) onlineCount, offlineCount, allCount = count_devices(str(d.id)) hasZJFirePlatform = True ZJFirePlatform = {} try: obj = Company.objects.get(ownerId=str(d.id)) ZJFirePlatform = { 'companyName': obj.name, 'companyCode': obj.code, 'companyAddress': obj.address, 'contactsName': obj.contactName, 'contactsTel': obj.telephone, 'deviceManufacturer': obj.manufacturer } hasZJFirePlatform = True except Exception, e: pass now = datetime.datetime.now() today = now.strftime(Const.DATE_FMT) rcds = DealerDailyStat.get_collection().find({'dealerId':ObjectId(d.id), 'date':today}, {'daily':1, 'activedDevRatio':1}) if rcds.count() == 0: todayIncome = 0 todayRechargeIncome = 0 todayChargeCardIncome = 0 else: info = rcds[0] todayIncome = info.get('daily', {}).get('totalIncome', 0) income = info.get('daily', {}).get('income', {}) todayRechargeIncome = income.get('recharge', 0) todayChargeCardIncome = RMB(income.get('chargeCard', 0)) + RMB(income.get('virtualChargeCard', 0)) monthDay = MONTH_DATE_KEY.format(year=now.year, month=now.month) rcds = DealerMonthlyStat.get_collection().find({'dealerId':ObjectId(d.id), 'date':monthDay}, {'addedUserCount':1}) if rcds.count() == 0: userCountAddedThisMonth = 0 else: info = rcds[0] userCountAddedThisMonth = rcds[0].get('addedUserCount', 0) detail = d.to_dict() dataList.append({ 'id': str(d.id), 'name': d.nickname, 'tel': d.username, 'agentInfo': agentMap.get(detail['agentId'], ''), 'dateTimeAdded': d.dateTimeAdded, 'lineCoins': report['lineCoins'], 'payIncome': todayIncome, 'todayRechargeIncome': todayRechargeIncome, 'todayChargeCardIncome': todayChargeCardIncome, 'userCount':d.userCount, 'userCountAddedThisMonth':userCountAddedThisMonth, 'devTotalNum': allCount, 'offlineTotal': offlineCount, 'onlineTotal': onlineCount, 'detail': json_dumps(detail), 'ZJFirePlatform': ZJFirePlatform, 'hasZJFirePlatform': hasZJFirePlatform, 'disableDevice': True if "dealerDisableDevice" in d.features else False }) return JsonResponse({ 'result': 1, 'description': '', 'payload': { 'total': total, 'dataList': dataList } }) @permission_required(ROLE.manager) def getDealerListByAgent(request): # type: (WSGIRequest)->JsonResponse """ :param request: :return: """ agentIds = json.loads(request.body).get('agentIds', []) agents = {str(_.id): _.nickname for _ in Agent.objects(id__in=agentIds)} if not agents: return JsonResponse({'result': 1, 'payload': []}) dataList = [ { 'dealerName': _.nickname, 'dealerId': str(_.id), 'agentId': str(_.agentId), 'agentName': agents[str(_.agentId)] } for _ in Dealer.objects(agentId__in=agentIds) ] return JsonResponse({'result': 1, 'payload': {'dataList': dataList, 'total': len(dataList)}}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'获取设备列表失败')) @permission_required(ROLE.dealer, ROLE.subaccount) def equipmentList(request): # type: (WSGIRequest)->JsonResponse def _get_port_status(portDict): allPorts = portDict.get("allPorts", 0) usedPorts = portDict.get("usedPorts", 0) usePorts = portDict.get("usePorts", 0) return allPorts, usedPorts, usePorts dealerId = str(request.user.bossId) pageIndex = int(request.GET.get('pageIndex', 1)) pageSize = int(request.GET.get('pageSize', 10)) equipmentGroupId = request.GET.get('equipmentGroupId') online = request.GET.get('online') searchKey = request.GET.get('searchKey', '') sort = request.GET.get('sort', 'logicalCode') partnerGroupList = Group.get_group_ids_of_partner(dealerId) ownGroupList = Group.get_group_ids_of_dealer(dealerId) groupIds = partnerGroupList + ownGroupList if not equipmentGroupId: selectedGroupIds = groupIds else: selectedGroupIds = [equipmentGroupId] if not online: onlineStates = [0, 1] else: onlineStates = [int(online)] groupDict = Group.get_groups_by_group_ids(selectedGroupIds) devNoList = Device.get_devNos_by_group(selectedGroupIds) devs = Device.get_dev_by_nos(devNoList).values() devDict, deviceCount = {}, 0 devCacheMap = Device.get_many_dev_control_cache(devNoList) showPortStatus = bool(request.user.feature_boolean_map.get("showPortStatus", None)) for dev in devs: # type: DeviceDict if dev.online not in onlineStates: continue group = groupDict.get(dev['groupId']) if group is None: continue if any(map(lambda _: searchKey in _, (dev['devNo'], dev['remarks'], dev['logicalCode'], group['groupName'], group['address']))): isFault = dev.get('isFault', False) isDND = dev.is_DND_now item = { 'id': dev.devNo, 'logicalCode': dev.logicalCode, 'name': group['groupName'], 'groupId': group['groupId'], 'type': dev.devType['name'], 'typeId': dev.devType['id'], 'devType': dev.devType, 'unit': dev.devType.get('unit', DeviceType.unit.default), 'online': dev.online, 'signal': dev.signal, 'timeBased': dev.devType.get('timeBased', DeviceType.timeBased.default), 'autoRefundEnable': dev.devType.get('autoRefundEnable', DeviceType.autoRefundEnable.default), 'channelType': dev.channelType, 'isManager': False if dev['groupId'] in partnerGroupList else True, 'serviceState': dev.get('serviceState', Const.ServiceState.Normal.name), 'remarks': dev.get('remarks', Device.remarks.default), 'status': dev.status, 'statusInfo': dev.statusInfo, 'isFault': isFault, 'isDND': isDND, 'offTimeDate': datetime.datetime.fromtimestamp(int(str(dev.offTime)[0:10])).strftime('%Y-%m-%d %H:%M:%S') if dev.offTime is not None else '', 'tag': group.get("tag", ""), "deviceWarning": dev.is_warning } # 最近离线时间小于2017年的都为空 offTimeYear = int(item['offTimeDate'][0:4]) if offTimeYear < 2017: item['offTimeDate'] = '' if showPortStatus: # 这个地方需要添加 具体的端口 使用情况 故障、工作、空闲等 使用情况从缓存中直接读取,如果不存在 则没有,不去具体查询设备 devCache = devCacheMap.get(device_control_cache_key(dev["devNo"]), {}) allPorts, usedPorts, usePorts = _get_port_status(devCache) hasPort = showPortStatus and bool(allPorts) item.update({"hasPort": hasPort}) if hasPort: item.update( {"portStatus": { "all": allPorts, "idle": usePorts, "used": usedPorts, } } ) else: item.update({"hasPort": False}) if not dev.online and Device.utils_is_expired(dev): item.update({'simExpireDate': dev.formatSimExpireDate, 'simStatus': dev.simStatus}) if dev['groupId'] in devDict: devDict[dev['groupId']].append(item) else: devDict[dev['groupId']] = [item] # 近7日平均使用率 if dev.devType.get('features', {}).get('7_days_average_utilization_rate', False) is True: nowDateTime = datetime.datetime.now() sevenDaysAgoDateTime = nowDateTime - datetime.timedelta(days=7) consumeRecords = ConsumeRecord.objects(devNo=dev.devNo, dateTimeAdded__gte=sevenDaysAgoDateTime, dateTimeAdded__lte=nowDateTime) sevenDaysAverage = round(((float(consumeRecords.count()) / 7) / 10) * 100, 2) item.update({'sevenDaysAverage': sevenDaysAverage}) deviceCount += 1 showGroups = paginate(sorted(devDict.keys(), reverse=False), pageSize=pageSize, pageIndex=pageIndex) devList = [] for keyGrp in showGroups: devList.extend(devDict[keyGrp]) if sort == 'logicalCode': tempList = natural_sort(array=devList, key='logicalCode', reverse=False) elif sort == 'devType': tempList = sorted(devList, key=lambda x: x['devType']['name']) elif sort == 'remarks': tempList = sorted(devList, key=lambda x: x['remarks'], reverse=True) elif sort == "tag": tempList = devList else: raise InvalidParameter(u'搜索条件不合法') if sort == "tag": devList = sorted(tempList, key=lambda x: x['tag'], reverse=True) else: devList = sorted(tempList, key=lambda x: x['groupId']) return JsonResponse({ "result": 1, "description": None, 'payload': { "total": deviceCount, "groupCount": len(devDict.keys()), "dataList": devList } }) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'获取库存列表失败')) @permission_required(ROLE.dealer, ROLE.subaccount) def equipmentListForStock(request): # type: (WSGIRequest)->JsonResponse ownerId = str(request.user.bossId) equipmentGroupId = request.GET.get('equipmentGroupId', 'all') online = request.GET.get('online', 'all') searchKey = request.GET.get('searchKey', '') groupIds, devTempList = Device.filter(dealerId=ownerId, searchKey=searchKey, online=online, equipmentGroupId=equipmentGroupId) devList = [] for dev in devTempList: if not dev.has_key('quantity'): continue devList.append(dev) return JsonResponse({ "result": 1, "description": None, 'payload': { "total": len(groupIds), "groupCount": len(devList), "dataList": devList } }) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'解绑失败')) @permission_required(ROLE.dealer, ROLE.subaccount) @request_limit_by_user(operation='unbindDevice', limit=100, logger=logger) def unbindDevice(request): def unbindDeviceDefault(request): # type: (WSGIRequest)->JsonResponse """ 经销商解绑设备 ..modified 去掉对代理商串货的限制 :param request: :return: """ owner_id = str(request.user.bossId) devNo = request.POST.get('value', None) if devNo is None: return JsonResponse({"result": 0, "description": u"缺少参数", 'payload': {}}) dev = Device.get_dev(devNo) # type: DeviceDict devType = dev['devType'] groupId = dev['groupId'] if dev is None: return JsonResponse({"result": 0, "description": u"该设备不存在,请刷新后再试", 'payload': {}}) if not dev.is_registered: return JsonResponse({"result": 0, "description": u"该设备没有注册,不需要解绑", 'payload': {}}) if dev.ownerId != owner_id: return JsonResponse({"result": 0, "description": u"不是您的设备,不能够解绑", 'payload': {}}) try: Device.un_register(dev=dev, operator=request.user.human_id) dealer = Dealer.objects.get(id=owner_id) dealer.devCount -= 1 dealer.save() except RentDeviceError as rde: return JsonErrorResponse(rde.message) except Exception as e: logger.exception( 'un register failure. error = %s, devNo = %s, ownerId = %s' % (e, devNo, str(request.user.bossId))) return JsonResponse({"result": 0, "description": u"系统错误", 'payload': {}}) group = Group.get_group(groupId) if group.get('swapFlag', False): agentId = request.user.agentId agent = Agent.objects(id=agentId).first() if agent: devNum = 0 if 'majorDeviceType' in devType and (u'直流' in devType['majorDeviceType'] or u'交流' in devType['majorDeviceType']): devNum = -1 SwapGroup.update_swap_time_and_num(groupId, devNum) SwapContract.update_swap_time_and_num(groupId, owner_id, agentId, agent.managerId, devNum) return JsonResponse({"result": 1, "description": None, 'payload': {}}) current_user = request.user # type: UserSearchable if not current_user.normal: return JsonResponse({"result": 0, "description": u"账号异常,不能进行该操作", 'payload': {}}) return unbindDeviceDefault(request) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'解绑失败')) @permission_required(ROLE.dealer, ROLE.subaccount) @request_limit_by_user(operation='unbindAllNode', limit=100, logger=logger) def unbindAllNode(request): # 获取主机的子节点 lc = request.POST.get('logicalCode', None) master = Device.get_dev_by_l(lc) # type: DeviceDict nodeList = master.deviceAdapter.get_node_list() if not nodeList: return JsonResponse({"result": 0, "description": u"该设备不存在,请刷新后再试", 'payload': {}}) owner_id = str(request.user.bossId) # TODO 和刘崇确认 此处先简单修复 然后后续可能进行优化 # 进行检查 保证所有设备都是 该经销商的 errDevs = list() for node in nodeList: # type: DeviceDict if not node.is_registered: continue if node.ownerId != owner_id: errDevs.append(node.logicalCode) if errDevs: return JsonErrorResponse(description=u"设备{} 不是您的设备 无法解绑".format(" ".join(errDevs))) # 再解除经销商绑定 for node in nodeList: if not node.is_registered: continue Device.un_register(dev=node, operator=request.user.human_id) dealer = Dealer.objects.get(id=owner_id) dealer.devCount -= 1 dealer.save() return JsonOkResponse() @error_tolerate(logger=logger, nil=JsonErrorResponse(u'删除套餐失败')) @permission_required(ROLE.dealer, ROLE.subaccount) def delPackages(request): # type: (WSGIRequest)->JsonResponse curr_user = request.user # type: Union[Dealer, SubAccount] if not curr_user.normal: return JsonErrorResponse(description=u'账号异常,不能进行该操作') devNo = request.POST.get('devNo', None) ruleId = request.POST.get('ruleId', None) if devNo is None or ruleId is None: return JsonResponse({"result": 0, "description": u"缺少参数", 'payload': {}}) dev = Device.get_dev(devNo) if dev is None: return JsonResponse({"result": 0, "description": u"找不到设备", 'payload': {}}) try: dev['washConfig'].pop(ruleId) except Exception, e: logger.exception('pop washconfig error=%s,ruleId=%s,devNo=%s' % (e, ruleId, devNo)) return JsonResponse({"result": 0, "description": u'该套餐已经被删除了,请刷新页面', 'payload': {}}) try: Device.get_collection().update_one({'devNo': devNo}, {'$set': {'washConfig': dev['washConfig']}}) Device.invalid_device_cache(devNo) except Exception, e: logger.exception('update device washconfig error=%s,devNo=%s,washConfig=%s' % (e, devNo, dev['washConfig'])) return JsonResponse({"result": 0, "description": u'保存套餐出错,请稍候再试', 'payload': {}}) return JsonResponse({"result": 1, "description": None, 'payload': {}}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'获取套餐失败')) @permission_required(ROLE.dealer, ROLE.agent, ROLE.subaccount) def getPackages(request): # type: (WSGIRequest)->JsonResponse lc = request.GET.get('logicalCode', None) dev = Device.get_dev_by_l(lc) # type: DeviceDict if dev is None: return JsonErrorResponse(description=u"找不到设备") maxCoins = dev.get('maxCoins', 4) devNo = dev.devNo # 设备没注册, 走脉冲测试 if not dev.ownerId: devData = { 'id': devNo, 'maxCoins': maxCoins, 'devNo': devNo, 'type': u'脉冲', 'typeCode': u'201', 'groupName': u'测试', 'groupNumber': 666 } defaultWashconfig = {'1': {'coins': 1}, '2': {'coins': 2}, '3': {'coins': 3}, '4': {'coins': 4}, '5': {'coins': 5}} ruleList = [ { 'id': packageId, 'name': u'测试', 'coins': rule['coins'], 'price': rule.get('price', rule['coins']) } for packageId, rule in defaultWashconfig.items() ] return JsonResponse({"result": 1, "description": None, 'payload': {'devData': devData, 'ruleList': ruleList}}) group = Group.get_group(dev['groupId']) if group is None: return JsonErrorResponse(description=u'找不到设备') if group['ownerId'] != str(request.user.bossId): return JsonErrorResponse(description=u'找不到设备') devData = { 'id': devNo, 'maxCoins': maxCoins, 'isManager': True, 'groupName': group['groupName'], 'groupNumber': dev['groupNumber'], 'devNo': devNo, 'type': dev['devType']['name'], 'typeCode': dev['devType']['code'] } if "displaySwitchs" in dev["otherConf"]: displaySwitchs = dev["otherConf"].get('displaySwitchs') else: displaySwitchs = {'displayCoinsSwitch': True, 'displayTimeSwitch': True, 'displayPriceSwitch': True, "setPulseAble": False, "setBasePriceAble": False} if dev.channelType != DeviceChannelType.Channel_BT: smartBox = ActionDeviceBuilder.create_action_device(dev) try: portDict = smartBox.dealer_get_port_status() if portDict: chargeIndex = {} for index, info in portDict.items(): if "status" not in info: continue if info['status'] == Const.DEV_WORK_STATUS_IDLE: chargeIndex[index] = 'idle' elif info['status'] == Const.DEV_WORK_STATUS_WORKING: chargeIndex[index] = 'busy' elif info['status'] == Const.DEV_WORK_STATUS_FAULT: chargeIndex[index] = 'fault' elif info['status'] == Const.DEV_WORK_STATUS_FORBIDDEN: chargeIndex[index] = 'ban' elif info['status'] == Const.DEV_WORK_STATUS_CONNECTED: chargeIndex[index] = 'connected' elif info['status'] == Const.DEV_WORK_STATUS_FINISHED: chargeIndex[index] = 'finished' devData.update({'chargeIndex': chargeIndex}) except ServiceException, e: return JsonErrorResponse(description=e.result.get('description')) except Exception as e: logger.exception(e) return JsonErrorResponse(description=u'未知错误') if dev["devType"]["code"] == Const.DEVICE_TYPE_CODE_HP_GATE: if request.GET.get("isRemoteUpper", None): ruleList = [] else: tempList = sorted(dev["washConfig"].get("1", {}).items(), key=lambda x: x[0]) ruleList = [v for _, v in tempList] chargeIndex = {} if dev["otherConf"].get("controlEnter") in ("1", "2"): chargeIndex["enter"] = "idle" if dev["otherConf"].get("controlExit") in ("1", "2"): chargeIndex["exit"] = "idle" devData.update({'chargeIndex': chargeIndex}) if request.GET.get("isRemoteUpper", None): ruleList = [] elif dev["devType"]["code"] in support_policy_weifule: if dev.deviceAdapter.support_device_package: payload = dev.deviceAdapter.dealer_show_package() payload.update({"devData": devData}) return JsonOkResponse(payload=payload) elif dev["devType"]["code"] in support_policy_device: if dev.deviceAdapter.support_device_package: payload = dev.deviceAdapter.dealer_show_package() payload.update({"devData": devData}) return JsonOkResponse(payload=payload) elif dev["devType"]["code"] in [Const.DEVICE_TYPE_CODE_CAR_CHANGING_JINQUE, Const.DEVICE_TYPE_CODE_CAR_WEIFILE_HOME_JFPG, Const.DEVICE_TYPE_CODE_CAR_WEIFILE_HOME_DOUB_JFPG, Const.DEVICE_TYPE_CODE_CHARGE_XIAOKEDOU]: if dev.deviceAdapter.support_device_package: payload = dev.deviceAdapter.dealer_show_package() payload.update({"devData": devData}) return JsonOkResponse(payload=payload) else: snRuleList = [] ruleList = [] for packageId, rule in dev['washConfig'].items(): item = { 'id': packageId, 'name': rule['name'], 'coins': rule['coins'], 'price': rule.get('price', rule['coins']), 'time': rule.get('time', 20), 'description': rule.get('description', ''), 'imgList': rule.get('imgList', []), 'unit': rule.get('unit', u'分钟'), 'switch': rule.get('switch', True), } if rule.get('pulse'): item.update({ 'pulse': rule.get('pulse'), }) if rule.get('basePrice'): item.update({ 'basePrice': rule.get('basePrice'), }) if rule.get('billingMethod') and rule['billingMethod'] != CONSUMETYPE.BILL_AS_SERVICE: item.update({ 'billingMethod': rule['billingMethod'], }) if 'sn' in rule: item['sn'] = rule['sn'] ruleList.append(item) ruleList = sorted(ruleList, key=lambda x: (x.get('sn'), x.get('id'))) payload = {"devData": devData, "ruleList": ruleList, 'displaySwitchs': displaySwitchs} unit_price = dev.otherConf.get('unit_price', {}) if dev.devTypeCode in [Const.DEVICE_TYPE_CODE_CHANGING_WEIFULE2]: try: if not unit_price: dev.deviceAdapter.set_dev_setting(dev.deviceAdapter.get_dev_setting()) unit_price = Device.get_dev_by_l(lc).otherConf.get('unit_price', {}) except: pass if unit_price: payload.update({'unit_price': unit_price}) return JsonOkResponse(payload=payload) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'保存套餐失败')) @permission_required(ROLE.dealer, ROLE.subaccount) def savePackages(request): """ 保存套餐 :param request: :return: """ # 检测套餐单位一致性校验 def check_package_unit(typeCode, package): # 电川汽车装有按金额启动,电量启动和充满自停的需求 if typeCode == Const.DEVICE_TYPE_CODE_CHANGING_DIANCHUANCARCHARGING: return True if typeCode in skip_package_unit_verify_list: return True dic = map(lambda x: {'unit': x.get('unit') }, package) res = reduce(lambda x, y: x if x == y else None, dic) if res is None: return False else: return True # 检查套餐单位单位小数点后两位校验 def check_params_range(typeCode, package): if typeCode in skip_package_range_verify_list: return None dic = map(lambda x: [x.get('time')], package) res = reduce(lambda x, y: x + y, dic) result = None for item in res: l = str(item).split(".") if len(l) > 1 and len(l[1]) > 2: result = (res.index(item) // 3) + 1 break return result # 套餐参数完整性校验 def check_params(typeCode, package): if typeCode in skip_package_params_verify_list: return True lis = map(lambda x: [x.get('time'), x.get('price'), x.get('coins')], package) res = reduce(lambda x, y: x + y, lis) for i in res: if i is None or float(i) < 0: return False return True # 套餐和金币是否需要强制1:1 def check_price_equal_coin(_devDict, _package): for _dev in _devDict.values(): # 非出租设备 不影响 if not _dev.isRent: continue for _rule in _package: if RMB(_rule["price"]) != RMB(_rule["coins"]): return False return True curr_user = request.user # type: Union[Dealer, SubAccount] if not curr_user.normal: return JsonErrorResponse(description=u'账号异常,不能进行该操作') status, msg = ensure_all_fields_are_not_empty( {k: v for k, v in request.POST.items() if k not in ('ruleId',)}) if not status: return JsonErrorResponse(description=msg) paras = json.loads(request.body) if request.body else {} if not paras: return JsonErrorResponse(description=u'提交数据为空') if paras['logicalCode'].__class__.__name__ == 'list': devNoList = [Device.get_devNo_by_logicalCode(lc) for lc in paras['logicalCode']] else: devNoList = [Device.get_devNo_by_logicalCode(paras['logicalCode'])] devDict = Device.get_dev_by_nos(devNoList) if not devDict: return JsonErrorResponse(description=u'找不到设备') typeCode = devDict.values()[0]['devType']['code'] if typeCode in support_policy_weifule: dev = devDict.values()[0] if dev.deviceAdapter.support_device_package: try: dev.deviceAdapter.format_device_package(**paras) except ServiceException as e: return JsonResponse({"result": 0, "description": e.result['description'], 'payload': {}}) return JsonResponse({"result": 1, "description": None, 'payload': {}}) elif typeCode in support_policy_device: dev = devDict.values()[0] if dev.deviceAdapter.support_device_package: try: dev.deviceAdapter.format_device_package(**paras) except ServiceException as e: return JsonResponse({"result": 0, "description": e.result['description'], 'payload': {}}) return JsonResponse({"result": 1, "description": None, 'payload': {}}) # 解析washConfig,如果需要下发设备,解析出来setConfig serviceList = paras['serviceData'] displaySwitchs = paras.get('displaySwitchs', {'displayCoinsSwitch': True, 'displayTimeSwitch': True, 'displayPriceSwitch': True, 'setPulseAble': False, 'setBasePriceAble': False}) # 调整sn顺序 for item in serviceList: item["sn"] = serviceList.index(item) if not check_params(typeCode, serviceList): return JsonErrorResponse(description=u'请完整的填写套餐中的所有参数') if not check_package_unit(typeCode, serviceList): return JsonErrorResponse(description=u'套餐用户获得参数单位配置需要一致') f = check_params_range(typeCode, serviceList) if f: return JsonErrorResponse(description=u'第%s个套餐 用户获得参数应为小数点后两位' % f) if not check_price_equal_coin(devDict, serviceList): return JsonErrorResponse(description=u"套餐金币与价格必须相等!") washConfig, setConfig = {}, {} agent = Agent.objects.get(id=request.user.agentId) existIds = [] for rule in serviceList: if 'id' in rule: existIds.append(rule['id']) # 霍珀道闸 后付费模式 使用阶梯计费 if typeCode == Const.DEVICE_TYPE_CODE_HP_GATE: rule = {str(index + 1): v for index, v in enumerate(serviceList)} washConfig = {"1": rule} elif typeCode in [Const.DEVICE_TYPE_CODE_CAR_CHANGING_JINQUE,Const.DEVICE_TYPE_CODE_CAR_WEIFILE_HOME_JFPG, Const.DEVICE_TYPE_CODE_CAR_WEIFILE_HOME_DOUB_JFPG, Const.DEVICE_TYPE_CODE_CHARGE_XIAOKEDOU]: dev = devDict.values()[0] if dev.deviceAdapter.support_device_package: try: washConfig, displaySwitchs = dev.deviceAdapter.format_device_package(**paras) except ServiceException as e: return JsonResponse({"result": 0, "description": e.result['description'], 'payload': {}}) else: for rule in serviceList: if rule.has_key('coins') and rule.has_key('price'): if not (is_number(rule['coins']) and is_number(rule['price']) and is_number( rule.get('time', 0))): return JsonErrorResponse(description=u'金币数目或者时间或者价格必须是数字') else: rule['coins'], rule['price'] = 0, 0 # 对于那种先不需要付费的,这个就直接是0 if RMB(rule['price']) >= request.user.maxPackagePrice: return JsonErrorResponse(description=u'套餐金额超限') if len(rule['name']) > 20: return JsonErrorResponse(description=u'套餐名字只能取1-20位') if typeCode == Const.DEVICE_TYPE_CODE_WASHER: name = rule['name'] if name not in [Const.WASHER_BOX_SET_DTS, Const.WASHER_BOX_SET_KSX, Const.WASHER_BOX_SET_BZX, Const.WASHER_BOX_SET_DWX, Const.WASHER_BOX_SET_JRKS, Const.WASHER_BOX_SET_JRBZ, Const.WASHER_BOX_JRDW, Const.WASHER_BOX_SET_TQJ]: return JsonErrorResponse(description=u'套餐名称只能是:桶清洁、单脱水、快速洗、标准洗、大物洗、加热快速洗、加热标准洗、加热大物洗。') coins = rule['coins'] useTime = rule['time'] if name == Const.WASHER_BOX_SET_DTS: setConfig[Const.WASHER_BOX_DTS] = {'price': int(coins), 'time': int(useTime)} elif name == Const.WASHER_BOX_SET_KSX: setConfig[Const.WASHER_BOX_KS] = {'price': int(coins), 'time': int(useTime)} elif name == Const.WASHER_BOX_SET_BZX: setConfig[Const.WASHER_BOX_BZ] = {'price': int(coins), 'time': int(useTime)} elif name == Const.WASHER_BOX_SET_DWX: setConfig[Const.WASHER_BOX_DW] = {'price': int(coins), 'time': int(useTime)} elif name == Const.WASHER_BOX_SET_JRKS: setConfig[Const.WASHER_BOX_JRKS] = {'price': int(coins), 'time': int(useTime)} elif name == Const.WASHER_BOX_SET_JRBZ: setConfig[Const.WASHER_BOX_JRBZ] = {'price': int(coins), 'time': int(useTime)} elif name == Const.WASHER_BOX_SET_JRDW: setConfig[Const.WASHER_BOX_JRDW] = {'price': int(coins), 'time': int(useTime)} elif (typeCode == Const.DEVICE_TYPE_CODE_WASHER_CW) and \ (rule['name'] not in [u'标准洗', u'快速洗', u'强力洗', u'单脱水', u'轻柔洗', u'漂洗并脱水', u'自洁', u'能效-全载', u'能效-半载', u'整机自检', u'电脑版自检']): return JsonErrorResponse(description=u'套餐名称只能是:标准洗,快速洗,强力洗,单脱水,轻柔洗,漂洗并脱水,自洁,能效-全载,能效-半载,整机自检,电脑版自检') elif typeCode == Const.DEVICE_TYPE_CODE_WASHER_SIMAIER: if rule['name'] not in [u'加强洗', u'标准洗', u'快速洗', u'单脱水']: return JsonErrorResponse(description=u'套餐名称只能是:加强洗,标准洗,快速洗,单脱水') elif typeCode == Const.DEVICE_TYPE_CODE_HUITENG: if rule['name'] not in [u'单脱水', u'快速洗', u'标准洗', u'大物洗']: return JsonErrorResponse(description=u'套餐名称只能是:单脱水,快速洗,标准洗,大物洗') elif typeCode == Const.DEVICE_TYPE_CODE_CAR_CHARGING_CY: price = rule.get("price") coins = rule.get("coins") unit = rule.get("unit") time = rule.get("time") if price != coins: return JsonErrorResponse(description=u'请将金币和套餐值设置相同') if unit != u"次": return JsonErrorResponse(description=u'计费单位只能是:次') if int(time) != 1: return JsonErrorResponse(description=u"计费次数只能是:1") elif typeCode in [Const.DEVICE_TYPE_CODE_WASHER_CY_HS,Const.DEVICE_TYPE_CODE_WASHER_CY_HS_YUCHUAN]: if rule['name'] not in [u'大物洗', u'标准洗', u'快速洗', u'单脱水']: return JsonErrorResponse(description=u'套餐名称只能是:大物洗,标准洗,快速洗,单脱水') if rule['unit'] != "分钟": return JsonErrorResponse(description=u"请将套餐的价格设置为分钟") if rule["name"] == u"单脱水" and (int(rule["time"]) > 9 or int(rule["time"]) < 5): return JsonErrorResponse(description=u"单脱水时间范围为5-9分钟") if rule["name"] == u"快速洗" and (int(rule["time"]) > 32 or int(rule["time"]) < 20): return JsonErrorResponse(description=u"快速洗时间范围为20-32分钟") if rule["name"] == u"标准洗" and (int(rule["time"]) > 43 or int(rule["time"]) < 35): return JsonErrorResponse(description=u"标准洗时间范围为35-43分钟") if rule["name"] == u"大物洗" and (int(rule["time"]) > 53 or int(rule["time"]) < 45): return JsonErrorResponse(description=u"大物洗时间范围为45-53分钟") if int(float(rule["coins"])) > 15 or int(float(rule["price"])) > 15: return JsonErrorResponse(description=u"套餐价格不得大于15") elif typeCode in [Const.DEVICE_TYPE_CODE_WASHER_CY_HJ]: if rule['name'] not in [u'大物洗', u'标准洗', u'快速洗', u'单脱水']: return JsonErrorResponse(description=u'套餐名称只能是:大物洗,标准洗,快速洗,单脱水') if rule['unit'] != "分钟": return JsonErrorResponse(description=u"请将套餐的价格设置为分钟") if rule["name"] == u"单脱水" and (int(rule["time"]) > 15 or int(rule["time"]) < 5): return JsonErrorResponse(description=u"单脱水时间范围为5-15分钟") if rule["name"] == u"快速洗" and (int(rule["time"]) > 35 or int(rule["time"]) < 20): return JsonErrorResponse(description=u"快速洗时间范围为20-35分钟") if rule["name"] == u"标准洗" and (int(rule["time"]) > 50 or int(rule["time"]) < 35): return JsonErrorResponse(description=u"标准洗时间范围为35-50分钟") if rule["name"] == u"大物洗" and (int(rule["time"]) > 65 or int(rule["time"]) < 50): return JsonErrorResponse(description=u"大物洗时间范围为50-65分钟") if int(float(rule["coins"])) > 15 or int(float(rule["price"])) > 15: return JsonErrorResponse(description=u"套餐价格不得大于15") elif typeCode in [Const.DEVICE_TYPE_CODE_WASHER_CY_HJ_1]: if rule['name'] not in [u'大物洗', u'标准洗', u'快速洗', u'单脱水']: return JsonErrorResponse(description=u'套餐名称只能是:大物洗,标准洗,快速洗,单脱水') if rule['unit'] != "分钟": return JsonErrorResponse(description=u"请将套餐的价格设置为分钟") if rule["name"] == u"单脱水" and (int(rule["time"]) > 15 or int(rule["time"]) < 5): return JsonErrorResponse(description=u"单脱水时间范围为5-15分钟") if rule["name"] == u"快速洗" and (int(rule["time"]) > 35 or int(rule["time"]) < 18): return JsonErrorResponse(description=u"快速洗时间范围为18-35分钟") if rule["name"] == u"标准洗" and (int(rule["time"]) > 45 or int(rule["time"]) < 30): return JsonErrorResponse(description=u"标准洗时间范围为30-45分钟") if rule["name"] == u"大物洗" and (int(rule["time"]) > 55 or int(rule["time"]) < 40): return JsonErrorResponse(description=u"大物洗时间范围为40-55分钟") if int(float(rule["coins"])) > 15 or int(float(rule["price"])) > 15: return JsonErrorResponse(description=u"套餐价格不得大于15") elif typeCode == "1003053": if rule['name'] not in [u'加时烘干', u'快速烘干', u'标准烘干', u'特别烘干']: return JsonErrorResponse(description=u'套餐名称只能是:加时烘干,快速烘干,标准烘干,特别烘干') if rule['unit'] != "分钟": return JsonErrorResponse(description=u"请将套餐的价格设置为分钟") if rule["name"] == u"加时烘干" and (int(rule["time"]) > 20 or int(rule["time"]) < 5): return JsonErrorResponse(description=u"加时烘干时间范围为5-20分钟") if rule["name"] == u"快速烘干" and (int(rule["time"]) > 40 or int(rule["time"]) < 20): return JsonErrorResponse(description=u"快速洗时间范围为20-40分钟") if rule["name"] == u"标准烘干" and (int(rule["time"]) > 50 or int(rule["time"]) < 30): return JsonErrorResponse(description=u"标准洗时间范围为30-50分钟") if rule["name"] == u"特别烘干" and (int(rule["time"]) > 70 or int(rule["time"]) < 50): return JsonErrorResponse(description=u"大物洗时间范围为50-70分钟") if int(float(rule["coins"])) > 15 or int(float(rule["price"])) > 15: return JsonErrorResponse(description=u"套餐价格不得大于15") if 'id' in rule: ruleId = rule['id'] else: ruleId = list(set(range(1, 71)) - set([int(ruleId) for ruleId in washConfig.keys()]) - set(existIds))[0] # TODO 需要统一类型.这里为云南霍博单独做 dealer = request.user # type: Dealer if ('coins_be_float' not in agent.features) and (not dealer.supports('coins_be_float')): if int(float(rule['coins'])) != float(rule['coins']): return JsonErrorResponse(description=u'金币只能是整数') washConfig[str(ruleId)] = { 'name': rule['name'], 'coins': int(float(rule['coins'])), 'price': float(rule['price']), 'time': float(rule.get('time', 0)), 'description': rule.get('description', ''), 'imgList': rule.get('imgList', []), 'unit': rule.get('unit', u'分钟'), 'switch': rule.get('switch', True), 'sn': rule.get('sn'), } else: washConfig[str(ruleId)] = { 'name': rule['name'], 'coins': float(rule['coins']), 'price': float(rule['price']), 'time': float(rule.get('time', 0)), 'description': rule.get('description', ''), 'imgList': rule.get('imgList', []), 'unit': rule.get('unit', u'分钟'), 'switch': rule.get('switch', True), 'sn': rule.get('sn'), } if rule.get('pulse'): washConfig[str(ruleId)].update({ 'pulse': rule.get('pulse'), }) if rule.get('basePrice'): washConfig[str(ruleId)].update({ 'basePrice': rule.get('basePrice'), }) if rule.get('billingMethod') and rule['billingMethod'] != CONSUMETYPE.BILL_AS_SERVICE: washConfig[str(ruleId)].update({ 'billingMethod': rule['billingMethod'], }) if rule.get('autoStop') != None: washConfig[str(ruleId)].update({ 'basePrice': rule.get('basePrice'), }) if rule.get('autoRefund') != None: washConfig[str(ruleId)].update({ 'basePrice': rule.get('basePrice'), }) if typeCode in [Const.DEVICE_TYPE_CODE_WASHER_CY_HS, Const.DEVICE_TYPE_CODE_WASHER_CY_HS_YUCHUAN, Const.DEVICE_TYPE_CODE_WASHER_CY_HS_HONGGAN]: if len(serviceList) != 4: return JsonErrorResponse(description=u'请勿增加或删除套餐') # 如果设备直接可以下发套餐信息到设备,直接到设备上修改。比如串口洗衣机、串口的充电设备等 for devNo, dev in devDict.items(): if dev['devType']['code'] == Const.DEVICE_TYPE_CODE_WASHER: smartBox = dev.deviceAdapter # type: WasherBox try: curConfig = smartBox.get_wash_config() except ServiceException, e: logger.exception('get washconfig to device=%s error=%s' % (devNo, e)) return JsonErrorResponse(description=u'读取设备套餐信息遇到错误:%s,请稍候再试试哦' % (e.result.get('description'))) try: curConfig.update(setConfig) smartBox.set_wash_config(curConfig) except ServiceException, e: logger.exception('set washconfig to device=%s error=%s' % (devNo, e)) return JsonErrorResponse(description=u'保存套餐到设备遇到错误:%s,请稍候再试试哦' % (e.result.get('description'))) if dev['devType']['code'] == Const.DEVICE_TYPE_CODE_HUITENG: smartBox = dev.deviceAdapter # type: washerHTBox cmdFlagDict = {u'单脱水': {'coins': '01', 'time': '09', 'baseTime': 5}, u'快速洗': {'coins': '02', 'time': '08', 'baseTime': 20}, u'标准洗': {'coins': '03', 'time': '07', 'baseTime': 35}, u'大物洗': {'coins': '04', 'time': '06', 'baseTime': 45}} oldConfig = dev['washConfig'] for ruleId, rule in oldConfig.items(): try: newRule = washConfig.get(ruleId) if newRule['coins'] != rule['coins']: smartBox.set_normal_value(cmdFlagDict[newRule['name']]['coins'], newRule['coins']) if newRule['time'] != rule['time']: baseTime = cmdFlagDict[newRule['name']]['baseTime'] if newRule['time'] < baseTime: return JsonErrorResponse(description=u'您设置的套餐%s时间%s分钟,不能低于基础时间%s分钟' % ( newRule['name'], newRule['time'], baseTime)) addTime = newRule['time'] - baseTime smartBox.set_normal_value(cmdFlagDict[newRule['name']]['time'], addTime) except ServiceException, e: return JsonErrorResponse(description=u'保存套餐到设备遇到错误:%s,请重试哦' % (e.result.get('description'))) if dev['devType']['code'] in [Const.DEVICE_TYPE_CODE_WASHER_CY_HS, Const.DEVICE_TYPE_CODE_WASHER_CY_HS_YUCHUAN]: box = dev.deviceAdapter washPriceMap = { u"单脱水": "priceDt", u"快速洗": "priceKs", u"标准洗": "priceBz", u"大物洗": "priceDw" } washTimeMap = { u"单脱水": "timeDt", u"快速洗": "timeKs", u"标准洗": "timeBz", u"大物洗": "timeDw" } priceData = {} timeData = {} for _, c in washConfig.items(): try: priceData[washPriceMap.get(c.get("name"))] = c.get("coins") timeData[washTimeMap.get(c.get("name"))] = c.get("time") except Exception as e: break else: try: box.set_config_82(priceData) box.set_config_83(timeData) except ServiceException, e: return JsonErrorResponse(description=u'保存套餐遇到错误,请稍候再试') # 烘干机 if dev['devType']['code'] == Const.DEVICE_TYPE_CODE_WASHER_CY_HS_HONGGAN: box = dev.deviceAdapter hongganPriceMap = { u"加时烘干": "priceDt", u"快速烘干": "priceKs", u"标准烘干": "priceBz", u"特别烘干": "priceDw" } hongganTimeMap = { u"加时烘干": "timeDt", u"快速烘干": "timeKs", u"标准烘干": "timeBz", u"特别烘干": "timeDw" } priceData = {} timeData = {} for _, c in washConfig.items(): try: priceData[hongganPriceMap.get(c.get("name"))] = c.get("coins") timeData[hongganTimeMap.get(c.get("name"))] = c.get("time") except Exception as e: break else: try: box.set_config_82(priceData) box.set_config_83(timeData) except ServiceException, e: return JsonErrorResponse(description=u'保存套餐遇到错误,请稍候再试') try: dev['washConfig'] = washConfig otherConf = dev.get('otherConf', {}) otherConf['displaySwitchs'] = displaySwitchs Device.get_collection().update({'devNo': dev['devNo']}, {'$set': {'washConfig': dev['washConfig'], 'otherConf':otherConf}}) request.user.defaultWashConfig[dev['devType']['id']] = dev['washConfig'].values() request.user.save() Device.invalid_device_cache(devNo) except ServiceException, e: logger.exception('update device washconfig error=%s,devNo=%s,washConfig=%s' % (e, devNo, dev['washConfig'])) return JsonErrorResponse(description=u'保存套餐遇到错误,请稍候再试') return JsonResponse({"result": 1, "description": None, 'payload': {}}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'设置默认组失败')) @permission_required(ROLE.dealer, ROLE.subaccount) def setDefaultGroup(request): ownerId = str(request.user.bossId) groupId = request.POST.get('groupId', None) if groupId is None: return JsonErrorResponse(description=u"缺少参数") try: success, description, group = Group.update_group(group_id=groupId, isDefault=True) return JsonOkResponse() if success else JsonErrorResponse(description=description) except Exception, e: logger.exception('update error=%s' % e) return JsonResponse({'result': 0, 'description': u"系统繁忙,请稍后再试", 'payload': {}}) @permission_required(ROLE.dealer, ROLE.subaccount) def logout(request): agentId = request.user.agentId auth.logout(request) response = JsonResponse({'result': 1, 'payload': agentId}) # 删除不在使用的COOKIE response.delete_cookie(key='hasagent') return response @permission_required(ROLE.dealer, ROLE.subaccount) def wxconfig(request): url = request.GET.get('href') if not url: return JsonResponse({'result': 0, 'description': u'参数错误', 'payload': {}}) value = get_wx_config(request.user, url) logger.exception('wx config url = %s' % url) return JsonResponse({'result': 1, 'description': None, 'payload': {'wxconfig': value}}) @require_GET @error_tolerate(logger=logger, nil=JsonErrorResponse(u'获取库存详情失败')) @permission_required(ROLE.dealer, ROLE.subaccount) def stockDetails(request): logicalCode = request.GET.get('logicalCode') devNo = Device.get_devNo_by_logicalCode(logicalCode) dev = Device.get_dev(devNo) if not dev: return JsonErrorResponse(description=u'找不到设备') return JsonResponse({'result': 1, "description": None, "payload": {"quantity": dev['quantity']}}) @require_POST @error_tolerate(logger=logger, nil=JsonErrorResponse(u'更新库存失败,请重试')) @permission_required(ROLE.dealer, ROLE.subaccount) def updateStockQuantity(request): payload = json.loads(request.body) lc = payload.get('logicalCode') quantity = int(payload.get('quantity', 0)) devNo = Device.get_devNo_by_logicalCode(lc) dev = Device.get_dev(devNo) if dev['quantity'] > quantity: stockType = 'remove' stockNum = dev['quantity'] - quantity else: stockType = 'add' stockNum = quantity - dev['quantity'] result = Device.update_field(dev_no=devNo, update=True, quantity=quantity, consumptionQuantity=0) if not result: return JsonResponse({'result': 0, 'description': u'更新库存失败,请重试'}) stockTime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') StockRecord.get_collection().insert( {'logicCode': lc, 'imei': dev['devNo'], 'stockType': stockType, 'stockTime': stockTime, 'number': stockNum}) return JsonResponse({'result': 1, 'description': None, 'payload': {}}) @permission_required(ROLE.dealer, ROLE.subaccount) def getStockRecord(request): lc = request.GET.get('logicalCode') if not lc: return JsonResponse({'result': 0, 'description': u'未接收到设备编码,请刷新重试', 'payload': {}}) pageIndex = int(request.GET.get('pageIndex', 1)) pageSize = int(request.GET.get('pageSize', 10)) startTime = defaultTodayDate(request.GET.get('startTime', None)) + ' ' + '00:00:00' endTime = defaultTodayDate(request.GET.get('endTime', None)) + ' ' + '23:59:59' rcds = StockRecord.get_collection().find({'logicCode': lc, 'stockTime': {'$gte': startTime, '$lte': endTime}}).sort( 'stockTime', -1) add, cost = 0, 0 sIndex = (pageIndex - 1) * pageSize eIndex = pageIndex * pageSize ii = 0 dataList = [] for rcd in rcds: name = '' if rcd['stockType'] == 'add': add += rcd['number'] name = u'增加库存 ' + rcd.get('more', '') elif rcd['stockType'] == 'remove': cost += rcd['number'] name = u'减少库存 ' + rcd.get('more', '') elif rcd['stockType'] == 'consume': cost += rcd['number'] name = u'用户购买 ' + rcd.get('more', '') elif rcd['stockType'] == 'adFree': cost += rcd['number'] name = u'吸粉发放 ' + rcd.get('more', '') if sIndex <= ii < eIndex: dataList.append({'name': name, 'time': rcd['stockTime'], 'number': rcd['number']}) ii += 1 devNo = Device.get_devNo_by_logicalCode(lc) dev = Device.get_dev(devNo) para = {'total': ii, 'add': add, 'cost': cost, 'quantity': dev['quantity'], 'dataList': dataList} return JsonResponse({'result': 1, 'description': None, 'payload': para}) @permission_required(ROLE.dealer, ROLE.subaccount) def toggleSwitches(request): paraDict = json.loads(request.body) if request.body else {} if not paraDict: return JsonErrorResponse(description=u'接收数据为空,请重试') ownerId = request.user.bossId # type: ObjectId if paraDict.get("hasTempPackage", None) == True: paraDict["displayTempPackage"] = True success = Dealer.update_dealer(ownerId, **paraDict) if not success: return JsonErrorResponse(description=u'更新失败,请重试') else: return JsonOkResponse() @permission_required(ROLE.dealer, ROLE.subaccount) def clearDeviceStatistics(request): lc = request.POST.get('logicalCode') devNo = Device.get_devNo_by_logicalCode(lc) dev = Device.get_dev(devNo) if not dev: return JsonErrorResponse(description=u'找不到设备') if dev['ownerId'] != str(request.user.bossId): return JsonResponse({'result': 0, 'description': u'非法操作', 'payload': {}}) if dev.get('devType', {}).get('code', '') not in [Const.DEVICE_TYPE_CODE_WASHCAR_LSHB]: return JsonResponse({'result': 0, 'description': u'您的设备类型不支持此操作哦', 'payload': {}}) try: smartBox = ActionDeviceBuilder.create_action_device(dev) smartBox.clear_dev_feecount() except ServiceException, e: return JsonResponse({'result': 0, 'description': e.result.get('description'), 'payload': {}}) return JsonResponse({'result': 1, 'description': u'', 'payload': {}}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'未知错误')) @permission_required(ROLE.dealer, ROLE.subaccount) def getDeviceFunction(request): payload = json.loads(request.body) lc = payload.get("logicalCode") if isinstance(lc, list) and len(lc): lc = lc[0] else: raise JsonErrorResponse(description=u"无效的设备编号") devNo = Device.get_devNo_by_logicalCode(lc) dev = Device.get_dev(devNo) if not dev: return JsonResponse({'result': 0, 'description': u'未找到该设备', 'payload': {}}) try: smartBox = ActionDeviceBuilder.create_action_device(dev) setConf = smartBox.get_dev_setting() if setConf is None: return JsonResponse({'result': 0, 'description': u'您的设备类型不支持此操作哦', 'payload': {}}) if len(payload.get("logicalCode")) > 1: serviceCache.set('lastsettingConf_owner%s' % (str(request.user.id)), setConf, 600) else: caches['devmgr'].set('settingConf_%s' % (devNo,), setConf, 600) return JsonResponse({'result': 1, 'description': u'', 'payload': setConf}) except ServiceException, e: return JsonResponse({'result': 0, 'description': e.result.get('description'), 'payload': {}}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'未知错误')) @permission_required(ROLE.dealer, ROLE.subaccount) def getDeviceFunctionForIC(request): payload = json.loads(request.body) lc = payload.get("logicalCode") if isinstance(lc, list) and len(lc): lc = lc[0] else: raise JsonErrorResponse(description=u"无效的设备编号") devNo = Device.get_devNo_by_logicalCode(lc) dev = Device.get_dev(devNo) if not dev: return JsonResponse({'result': 0, 'description': u'未找到该设备', 'payload': {}}) try: smartBox = ActionDeviceBuilder.create_action_device(dev) setConf = smartBox.get_IC_card_password() if setConf is None: return JsonResponse({'result': 0, 'description': u'您的设备类型不支持此操作哦', 'payload': {}}) caches['devmgr'].set('settingConf_%s' % (devNo,), setConf, 600) return JsonResponse({'result': 1, 'description': u'', 'payload': setConf}) except ServiceException, e: return JsonResponse({'result': 0, 'description': e.result.get('description'), 'payload': {}}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'未知错误')) @permission_required(ROLE.dealer, ROLE.subaccount) def setDeviceFunction(request): # type: (WSGIRequest)->JsonResponse payload = json.loads(request.body) lc = payload.get("logicalCode") if isinstance(lc, list) and len(lc): lc = lc[0] else: raise JsonErrorResponse(description=u"无效的设备编号") requestBody = RequestBodyDict({"POST": payload}) devNo = Device.get_devNo_by_logicalCode(lc) dev = Device.get_dev(devNo) if not dev: return JsonErrorResponse(description=u'找不到设备') if dev['ownerId'] != str(request.user.bossId): return JsonResponse({'result': 0, 'description': u'非法操作', 'payload': {}}) lastSetConf = caches['devmgr'].get('settingConf_%s' % (devNo,)) box = ActionDeviceBuilder.create_action_device(dev) try: box.set_device_function(requestBody, lastSetConf) except ServiceException, e: logger.exception('set info to device=%s error=%s' % (devNo, e)) return JsonResponse( {'result': 0, 'description': u'设置参数遇到错误:%s' % (e.result.get('description', '')), 'payload': {}}) if lastSetConf is not None: caches['devmgr'].set('settingConf_%s' % devNo, lastSetConf) return JsonResponse({'result': 1, 'description': None, 'payload': {}}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'未知错误')) @permission_required(ROLE.dealer, ROLE.subaccount) def setDeviceFunctionParam(request): # type: (WSGIRequest)->JsonResponse updateConf = json.loads(request.body) logicalCodes = updateConf.pop('logicalCode') # 替代品 先将 request 和 adapter的功能函数解耦 后续逐步修改 requestBody = RequestBodyDict({"POST": updateConf}) if len(logicalCodes) > 1: setMode = updateConf.pop('modifyMode', None) dev = Device.get_dev_by_l(logicalCodes[0]) dev_owner = dev.ownerId dev_type_code = dev.devType.get('code') for logicalCode in logicalCodes[1:]: dev = Device.get_dev_by_l(logicalCode) if dev_owner != dev.ownerId or dev_type_code != dev.devType.get('code'): return JsonErrorResponse(description=u"设备经销商不同或者不同类型设备") beforeConf = serviceCache.get('lastsettingConf_owner%s' % (str(request.user.id))) # type: Dict if not beforeConf: return JsonErrorResponse(description=u"查询当前配置信息失败") if setMode == 'diff': # 找出发生改变的参数项 for key, oldValue in beforeConf.iteritems(): if key in updateConf and str(updateConf[key]) == str(oldValue): updateConf.pop(key) if not updateConf: return JsonErrorResponse(description=u"您没有修改任何参数") payload = {'updateConf': updateConf, 'lastSetConf': None, 'logicalCodes': logicalCodes} else: payload = {'updateConf': updateConf, 'lastSetConf': beforeConf, 'logicalCodes': logicalCodes} payload.update({ 'operationId': '{}_{}'.format(str(request.user.id), int(time.time())) }) from taskmanager.mediator import task_caller task_caller('batch_set_device_params', **payload) serviceCache.set(payload['operationId'], payload, 600) return JsonResponse({'result': 1, 'description': None, 'payload': {'operationId': payload['operationId']}}) else: logicalCode = logicalCodes[0] dealer = Dealer.objects(id=str(request.user.id)).first() if dealer is None: return JsonErrorResponse(description=u"设备的经销商不存在") devNo = Device.get_devNo_by_logicalCode(logicalCode) dev = Device.get_dev(devNo) if dev is None: return JsonResponse({'result': 0, 'description': u'没有找到设备', 'payload': {}}) if dev['ownerId'] != str(request.user.bossId): return JsonResponse({'result': 0, 'description': u'非法操作', 'payload': {}}) beforeConf = caches['devmgr'].get('settingConf_%s' % (devNo,)) if not beforeConf: try: beforeConf = dev.deviceAdapter.get_dev_setting() if not beforeConf: return JsonResponse({'result': 0, 'description': u'当前设备不支持该操作', 'payload': {}}) except Exception as e: logger.exception(e) return JsonResponse({'result': 0, 'description': u'查询设备当前配置信息失败', 'payload': {}}) operation = OperatorLog.record_dev_setting_changes_log( dealer, 'record_someone_set_devSettings', dev['logicalCode'], dev['devType']['code'], { 'beforeCacheStr': json.dumps(beforeConf), 'afterCacheStr': json.dumps(updateConf) }) # type: OperatorLog try: dev.deviceAdapter.set_device_function_param(requestBody, beforeConf) operation.update(content__status='success') return JsonResponse({'result': 1, 'description': None, 'payload': {}}) except ServiceException, e: logger.info('error happened, error=%s' % (e,)) operation.update(content__status='fail', content_desc=e.result.get('description')) return JsonResponse({'result': 0, 'description': e.result.get('description'), 'payload': {}}) except InvalidParameter as e: logger.exception(e) operation.update(content__status='fail', content_desc=e.message) return JsonResponse({'result': 0, 'description': e.message, 'payload': {}}) except Exception, e: operation.update(content__status='fail', content_desc=u'系统异常') logger.exception('error happened, error=%s' % (e,)) return JsonResponse({'result': 0, 'description': u'系统异常,请检查输入参数,或者稍后重试', 'payload': {}}) @permission_required(ROLE.dealer, ROLE.subaccount) def deviceParamsResult(request): user = request.user operationId = request.GET.get('operationId', None) if not operationId: return JsonResponse({'result': 1, 'description': None, 'payload': {}}) payload = serviceCache.get(operationId, {}) if not payload: operations = OperatorLog.objects.filter(operatorId=str(user.id), role=user.role, content__operationId=operationId) dataList = list(map(lambda operation: {'id': str(operation.id), 'logicalCode': operation.content['logicalCode'], 'status': operation.content.get('status')}, operations)) else: logicalCodes = payload.get('logicalCodes', []) operations = OperatorLog.objects.filter(operatorId=str(user.id), role=user.role, content__logicalCode__in=logicalCodes, content__operationId=operationId) dataList = list(map(lambda operation: {'id': str(operation.id), 'logicalCode': operation.content['logicalCode'], 'status': operation.content.get('status')}, operations)) if len(operations) != len(logicalCodes): leftLogicalCodes = set(logicalCodes) - set(operations.values_list('logicalCode')) for logicalCode in leftLogicalCodes: dataList.append({'id': None, 'logicalCode': logicalCode, 'status': 'waiting'}) return JsonResponse({'result': 1, 'description': None, 'payload': {'dataList':dataList}}) @permission_required(ROLE.dealer, ROLE.subaccount) def retryingSettingsDeviceParams(request): dev_oper_id = request.GET.get('id') operation = OperatorLog.objects.filter(id=dev_oper_id).first() # type: OperatorLog logicalCode = operation.content['logicalCode'] dev = Device.get_dev_by_l(logicalCode) # type: DeviceDict if not dev: return JsonResponse({'result': 0, 'description': u'该设备不存在', 'payload': {}}) if dev.ownerId != request.user.bossId: return JsonResponse({'result': 0, 'description': u'您无权操作该设备', 'payload': {}}) try: if operation.operatorName == 'record_someone_set_devSettings': updateConf = json.loads(operation.content.get('updateConfStr')) beforeCacheStr = json.loads(operation.content.get('beforeCacheStr')) requestBody = RequestBodyDict({"POST": updateConf}) dev.deviceAdapter.set_device_function(requestBody, beforeCacheStr) dev.deviceAdapter.set_device_function_param(requestBody, beforeCacheStr) elif operation.operatorName == 'setServerSetting': payload = json.loads(operation.content.get('after')) dev.deviceAdapter.set_server_setting(payload) except ServiceException, e: logger.info('error happened, error=%s' % (e,)) return JsonResponse({'result': 0, 'description': e.result.get('description'), 'payload': {}}) except InvalidParameter as e: logger.exception(e) return JsonResponse({'result': 0, 'description': e.message, 'payload': {}}) else: operation.update(content__status='success') return JsonResponse({'result': 1, 'description': '重试成功', 'payload': {'status': 'success'}}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'获取卡列表失败')) @permission_required(ROLE.dealer, ROLE.subaccount) def getUserCardList(request): pageIndex = int(request.GET.get('pageIndex', 1)) pageSize = int(request.GET.get('pageSize', 10)) searchKey = str(request.GET.get('searchKey', '')) userId = str(request.GET.get('userId', '')) equipmentGroupId = str(request.GET.get('equipmentGroupId')) frozen = request.GET.get("frozen", None) dealerId = str(request.user.bossId) queryDict = { "dealerId": dealerId, 'openId': userId or {'$exists': True} } if frozen: queryDict.update({"frozen": bool(int(frozen))}) if searchKey: queryDict.update(search_query(['cardName', 'phone', "cardNo"], searchKey).to_query(Card)) if equipmentGroupId: queryDict.update({'groupId': equipmentGroupId}) cards = Card.objects.filter(__raw__=queryDict).skip((pageIndex - 1) * pageSize).limit(pageSize) dataList = list() for card in cards: # type: Card dataList.append({ "cardName": card.cardName, "phone": card.phone, "groupId": card.groupId, "groupName": card.group.groupName if card.group else "", "cardId": str(card.id), "bindStatus": card.isBinded, "dealerId": card.dealerId, "remarks": card.remarks, "balance": card.balance, "cardNo": card.cardNo, "frozen": int(card.frozen) }) payload = { "total": get_paginate(dataList, pageSize=pageSize, pageIndex=pageIndex), "dataList": dataList, "agentId": request.user.agentId } return JsonResponse({"result": 1, "description": "", "payload": payload}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'获取详情失败')) @permission_required(ROLE.dealer, ROLE.subaccount) def getUserCard(request): cardId = request.GET.get("cardId", "") try: card = Card.objects.get(id=cardId) except DoesNotExist: return JsonErrorResponse(description=u"无效的卡") except Exception as e: logger.exception(e) return JsonErrorResponse(description=u"获取卡详情失败,请刷新页面试试") if card.dealerId != str(request.user.bossId): return JsonErrorResponse(u"获取详情失败") group = card.group data = { "cardId": cardId, "cardNo": card.cardNo, "cardName": card.cardName, "groupId": card.groupId, "dealerId": card.dealerId, "groupName": group.groupName if group is not None else '', "frozen": card.frozen, "phone": card.phone, "status": card.status, "bindStatus": card.isBinded, "balance": "{:.2f}".format(float(card.balance)), "chargeBalance": "{:.2f}".format(float(card.chargeBalance)), "bestowBalance": "{:.2f}".format(float(card.bestowBalance)), "cardType": card.cardType } return JsonOkResponse(payload=data) @error_tolerate(logger=logger, nil=JsonErrorResponse(u"编辑卡失败")) @permission_required(ROLE.dealer, ROLE.subaccount) def editCard(request): """ 经销商端 编辑卡片信息 可编辑内容 为 绑定设备组 卡名称 联系方式 :param request: :return: """ payload = json.loads(request.body) cardId = payload.get("cardId") cardName = payload.get("cardName") phone = payload.get("phone") groupId = payload.get("groupId") try: card = Card.objects.get(id=cardId) except DoesNotExist: return JsonErrorResponse(description=u"修改卡失败") if phone and not PHONE_NUMBER_RE.match(phone): return JsonErrorResponse(description=u"手机号码输入错误") if cardName and not NAME_RE.match(cardName): return JsonErrorResponse(description=u"请输入正确格式的名称(2-20位)") if card.dealerId != str(request.user.bossId): return JsonErrorResponse(description=u"不是您的卡片,无权修改") group = Group.get_group(groupId) if not group: return JsonErrorResponse(description=u"请选择正确的设备组") if group.get("ownerId") != str(request.user.bossId): return JsonErrorResponse(description=u"请选择正确的设备组") card.cardName = cardName card.phone = phone card.groupId = groupId card.save() return JsonOkResponse() @error_tolerate(logger=logger, nil=JsonErrorResponse(u"录卡失败")) @permission_required(ROLE.dealer, ROLE.subaccount) def saveEntityCard(request): # type: (WSGIRequest)->JsonResponse payload = json.loads(request.body) cardNo = payload.get('cardNo', '') phone = payload.get('phone', '') cardName = payload.get('cardName', '') groupId = payload.get("groupId", "") dealerId = str(request.user.bossId) # 卡号前置去0 if cardNo.isdigit(): cardNo = str(int(cardNo)) if not cardNo or not Card.check_card_no(cardNo): return JsonErrorResponse(description=u"卡号不符合规则,请输入正确的卡号") groupIds = Group.get_group_ids_of_dealer(dealerId) if not groupId or groupId not in groupIds: return JsonErrorResponse(description=u"请选择正确的设备组") if phone and not PHONE_NUMBER_RE.match(phone): return JsonErrorResponse(description=u"手机号码输入错误") if cardName and not NAME_RE.match(cardName): return JsonResponse({"result": 0, "description": u"请输入正确格式的名称(2-20位)"}) agentId = request.user.agentId # 基于卡号找 代理商下的卡 或者平台下的卡 card = Card.objects.filter(Q(agentId=agentId) | Q(agentId=''), cardNo=cardNo).first() if not card: card = Card( cardNo=cardNo, dealerId=dealerId, agentId=agentId, cardName=cardName, groupId=groupId, phone=phone, openId=Const.DEFAULT_CARD_OPENID ).save() return JsonResponse({"result": 1, "description": u"录入成功", "payload": {'cardId':str(card.id)}}) else: if card.dealerId: # 有经销商注册 if card.dealerId == dealerId: return JsonErrorResponse(description=u"{} 卡已经被您收录,请不要重复收录".format(cardNo)) else: return JsonErrorResponse(description="{} 卡已被其他经销商录入,请确认卡号不要重复".format(cardNo)) else: # 此代理商平台下没有经销商注册该卡片 card.dealerId = dealerId card.agentId = agentId card.cardName = cardName card.groupId = groupId card.phone = phone card.openId = Const.DEFAULT_CARD_OPENID card.save() return JsonResponse({"result": 1, "description": u"录入成功", "payload": {'cardId': str(card.id)}}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u"补卡失败")) @permission_required(ROLE.dealer, ROLE.subaccount) def swapCardNo(request): """ 补卡 需要生成补卡记录,不重新创建新卡 如果新卡的卡号已经存在但是没有绑定用户并且内部没余额 :param request: :return: """ payload = json.loads(request.body) cardNo = payload.get("cardNo", "") cardId = payload.get("cardId") dealerId = str(request.user.bossId) # 卡号前置去0 if cardNo.isdigit(): cardNo = str(int(cardNo)) if not Card.check_card_no(cardNo): return JsonErrorResponse(description=u"无效的卡号,卡号长度不能超过10位") try: oldCard = Card.objects.get(id=cardId) except DoesNotExist: return JsonErrorResponse(description=u"查询旧卡失败") if oldCard.cardNo == cardNo: return JsonErrorResponse(description=u"卡号一致无需修改") if oldCard.dealerId != dealerId: return JsonErrorResponse(description=u"无权编辑此卡") checkStatus, checkMsg = Card.check_swap_card_no(cardNo, dealerId, oldCard.agentId) if not checkStatus: return JsonErrorResponse(description=checkMsg) # 直接将卡号更新掉,然后新建一条换卡记录 oldCard.update(cardNo=cardNo) SwapCardRecord.add_record(oldCard.cardNo, cardNo, oldCard.agentId, str(request.user.id)) return JsonOkResponse() @record_operation_behavior() @permission_required(ROLE.dealer, ROLE.subaccount) def deleteInitCard(request): cardId = json.loads(request.body).get("cardId") card = Card.objects.filter(id=cardId, dealerId=str(request.user.bossId)).first() if not card: return JsonResponse({"result": 0, "description": u"未找到该实体卡", "payload": {}}) updated = card.clear_card() if not updated: return JsonErrorResponse(description=u'操作失败') return JsonResponse({"result": 1, "description": u"删除成功", "payload": {}}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'获取卡记录失败')) @permission_required(ROLE.dealer, ROLE.subaccount) def getUserCardRecord(request): # type: (WSGIRequest)->JsonResponse pageIndex = int(request.GET.get('pageIndex', 1)) pageSize = int(request.GET.get('pageSize', 10)) startTime = request.GET.get('startTime', 10) endTime = request.GET.get('endTime', 10) cardId = request.GET.get('cardId', None) type = request.GET.get('type', None) card = Card.objects.get(id=cardId) if type == "chargeCard": dataList = [] # TODO zjl 订单统一 不要这样搞得很别扭 viaMap = { u"退币": "refund", u"充值": "chargeCard" } for item in CardRechargeRecord.get_collection().find({ 'cardId': cardId, 'dateTimeAdded': {'$gte': to_datetime(startTime + " 00:00:00"), '$lte': to_datetime(endTime + " 23:59:59")}}).sort("dateTimeAdded", -1): data = { "cardId": str(item['_id']), "cardNo": card.cardNo, "via": viaMap.get(item.get("remarks"), "chargeCard"), "amount": item['money'], "coins": item.get('coins', item['money']), "address": item['address'], "groupName": item['groupName'], "createdTime": item['dateTimeAdded'].strftime('%Y-%m-%d %H:%M:%S'), "rechargeType": item.get("rechargeType") } if item.has_key('preBalance'): data.update({'preBalance': item['preBalance']}) if item.has_key('balance'): data.update({'balance': item['balance']}) if item.get("remarks", None): data.update({'remarks': item['remarks']}) if item.get("logicalCode"): data.update({"devType": Device.get_dev_by_logicalCode(item['logicalCode']).get("devType", dict()).get("name", "")}) data.update({"logicalCode": item['logicalCode']}) dataList.append(data) elif type == "consume": dataList = [] rcds = CardConsumeRecord.get_collection().find( {'cardId': cardId, 'dateTimeAdded': {'$gte': to_datetime(startTime + " 00:00:00"), '$lte': to_datetime(endTime + " 23:59:59")}}).sort( "dateTimeAdded", -1) for item in rcds: newData = { "cardId": str(item['_id']), "cardNo": card.cardNo, "via": "consume", "devType": item['devType'], "amount": item['money'], "logicalCode": item['logicalCode'], "address": item['address'], "groupName": item['groupName'], "createdTime": item['dateTimeAdded'].strftime('%Y-%m-%d %H:%M:%S') } if item.has_key('balance'): newData.update({'balance': item['balance']}) newData.update(item.get('servicedInfo', {})) dataList.append(newData) elif type == 'order': dataList = [] for item in CardRechargeOrder.get_collection().find({ 'cardId': cardId, 'dateTimeAdded': {'$gte': to_datetime(startTime + " 00:00:00"), '$lte': to_datetime(endTime + " 23:59:59")}}).sort("dateTimeAdded", -1): data = { "via": "order", "amount": item['money'], "coins": item.get('coins', item['money']), "createdTime": item['dateTimeAdded'].strftime('%Y-%m-%d %H:%M:%S'), "status": u'等待用户刷卡充值' if item['status'] == 'finishedPay' else u'充值完成', "desc": item['remarks'], "rechargeType": item.get("rechargeType") } if item.has_key('preBalance'): data.update({'preBalance': item['preBalance']}) if item.has_key('balance'): data.update({'balance': item['balance']}) dataList.append(data) elif type == 'cardConsume': card = Card.objects.filter(id=cardId).first() dataList = [] orders = ConsumeRecord.get_collection().find({ 'openId': str(card.openId), 'dateTimeAdded': {'$gte': to_datetime(startTime + " 00:00:00"), '$lte': to_datetime(endTime + " 23:59:59")}}).sort("dateTimeAdded", -1) for item in orders: data = { "via": "consume", "amount":item.get('coin', item['money']), "createdTime": item['dateTimeAdded'].strftime('%Y-%m-%d %H:%M:%S'), "orderNo":item.get('orderNo'), "status": u'完成', "desc": item['remarks'] } dataList.append(data) else: return JsonResponse({"result": 0, "description": u"查询类型错误", "payload": {}}) return JsonResponse( { "result": 1, "description": "", "payload": { "total": len(dataList), "dataList": dataList[(pageIndex - 1) * pageSize: pageIndex * pageSize] } }) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'未知错误')) @permission_required(ROLE.dealer, ROLE.subaccount) def getDeviceFunctionByKey(request): # type: (WSGIRequest)->JsonResponse try: payload = json.loads(request.body) key = payload.get('key', None) # 兼容真谷多 port = payload.get("portIndex", None) if port is not None: key = port logicalCode = payload.get('logicalCode', None) if isinstance(logicalCode, list) and len(logicalCode): logicalCode = logicalCode[0] devNo = Device.get_devNo_by_logicalCode(logicalCode) dev = Device.get_dev(devNo) lastSetConf = caches['devmgr'].get('settingConf_%s' % (devNo,)) if not lastSetConf: lastSetConf = {} box = ActionDeviceBuilder.create_action_device(dev) payload = box.get_device_function_by_key(key) if payload is not None: if lastSetConf is None: lastSetConf = payload else: lastSetConf.update(payload) caches['devmgr'].set('settingConf_%s' % (devNo,), lastSetConf, 600) return JsonResponse({"result": 1, "description": "", "payload": payload}) except ServiceException, e: return JsonResponse({"result": 0, "description": e.result.get('description', ''), "payload": {}}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'设置错误')) @permission_required(ROLE.dealer, ROLE.subaccount) def setDeviceFunctionByKey(request): # type: (WSGIRequest)->JsonResponse payload = json.loads(request.body) logicalCode = payload.get('logicalCode', None) if isinstance(logicalCode, list) and len(logicalCode): logicalCode = logicalCode[0] else: return JsonErrorResponse(description=u"错误的二维码编号") devNo = Device.get_devNo_by_logicalCode(logicalCode) dev = Device.get_dev(devNo) keyName = payload.get('key', None) if keyName is None: return JsonResponse({"result": 0, "description": u'没有按下任何控制键', "payload": {}}) try: box = ActionDeviceBuilder.create_action_device(dev) box.press_down_key(keyName) return JsonResponse({"result": 1, "description": '', "payload": {}}) except ServiceException, e: logger.exception('cannot setDeviceFunctionByKey, error=%s' % (e.result.get('description', '').encode('utf-8'),)) return JsonResponse({"result": 0, "description": e.result.get('description', ''), "payload": {}}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer, ROLE.subaccount) def wechatEntry(request): # type: (WSGIRequest)->JsonResponse """ 必须每次都进行鉴权 :param request: :return: """ current_user = request.user # type: Dealer if not check_role(current_user, ROLE.dealer): return ErrorResponseRedirect(error = u'权限错误') entryType = request.GET.get('type') if entryType not in ['simCard', 'apiQuota', 'disableAdQuota']: return ErrorResponseRedirect(error = u'参数错误(10001)') if entryType == 'simCard': # 流量卡充值 my_agent = Agent.get_inhouse_prime_agent() app = get_app(my_agent, APP_TYPE.WECHAT_ENV_PAY, role = ROLE.dealer) elif entryType == 'apiQuota': # api设备配额数量充值 my_agent = Agent.get_inhouse_prime_agent() app = get_app(my_agent, APP_TYPE.WECHAT_ENV_PAY, role=ROLE.dealer) elif entryType == 'disableAdQuota': # api设备配额数量充值 my_agent = Agent.get_inhouse_prime_agent() app = get_app(my_agent, APP_TYPE.WECHAT_ENV_PAY, role=ROLE.dealer) else: return ErrorResponseRedirect(error=u'参数错误(10002)') if isinstance(app, WechatPayApp): auth_bridge = WechatAuthBridge(app) # type: WechatAuthBridge else: return ErrorResponseRedirect(error=u'参数错误(10003)') auth_code = request.GET.get(auth_bridge.auth_code_key, None) if auth_code: openId = auth_bridge.authorize(auth_code) if openId is not None: redirect = base64.b64decode(request.GET.get('payload')) redirect = add_query(redirect, { 'openId': openId }) return FrontEndResponseRedirect(redirect) else: return ErrorResponseRedirect(error=u'系统繁忙,请重试') else: redirect_url = concat_server_end_url(uri='/dealer/wechat/entry?type={}'.format(entryType)) return ExternalResponseRedirect( auth_bridge.generate_auth_url_base_scope( redirect_uri=redirect_url, payload=base64.b64encode(request.GET.get('redirect')))) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'冻结卡失败')) @permission_required(ROLE.dealer, ROLE.subaccount) def freezeCard(request): # type: (WSGIRequest)->JsonResponse payload = json.loads(request.body) frozen = payload.get('frozen') cardId = payload.get('id', '') try: card = Card.objects.get(id=cardId) card.frozen = frozen card.status = 'active' card.save() except Exception, e: logger.exception(e.message) return JsonResponse({"result": 0, "description": u'系统错误', "payload": {}}) return JsonResponse({"result": 1, "description": '', "payload": {}}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误')) @permission_required(ROLE.dealer, ROLE.subaccount) def getWalletWithdrawInfo(request): dealer = request.user # type: Dealer if not is_dealer(dealer): return ErrorResponseRedirect(error = u'子账号无提现权限') source_key = request.GET.get('sourceId') income_type = request.GET.get('sourceType') phone = str(dealer.monitorPhone) if dealer.monitorPhone else str(dealer.username) result = { "result": 1, "description": None, 'payload': { 'payOpenId': 'placeholder', 'phone': phone, 'balance': dealer.sub_balance(income_type, source_key), 'withdrawFeeRatio': dealer.withdrawFeeRatio, 'support': dealer.withdraw_support(source_key) } } return JsonResponse(result) @require_POST @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,请刷新')) @permission_required(ROLE.dealer, ROLE.subaccount) def getFeatureList(request): # type: (WSGIRequest)->JsonResponse """ :param request: :return: """ currentUser = request.user # type: Dealer payload = json.loads(request.body) queryList = payload.get('list', []) resultFeatures = currentUser.query_feature_by_list(queryList) if 'blackListManage' in currentUser.features: resultFeatures.update({'blackListManage': True}) return JsonOkResponse(payload=resultFeatures) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,请刷新')) @permission_required(ROLE.dealer, ROLE.subaccount) def getOnsaleTypeList(request): # type: (WSGIRequest)->JsonResponse dataList = [] for typeName, info in OnSale.onsaleTypeDict.items(): dataList.append( { 'typeName': typeName, 'desc': info['desc'], 'img': info['img'] } ) return JsonResponse({'result': 1, 'description': '', 'payload': {'total': len(dataList), 'dataList': dataList}}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,请刷新')) @permission_required(ROLE.dealer, ROLE.subaccount) def getOnsaleList(request): # type: (WSGIRequest)->JsonResponse """ 列出所有 经销商的活动尚未删除的 :param request: :return: """ pageIndex = int(request.GET.get('pageIndex', 1)) pageSize = int(request.GET.get('pageSize', 10)) searchKey = request.GET.get('searchKey', None) dealerId = str(request.user.bossId) onsales = OnSale.objects.filter(dealerId=dealerId, name__startswith=searchKey).order_by("-id") dataList = [_obj.to_dict() for _obj in onsales[(pageIndex - 1) * pageSize: pageIndex * pageSize]] return JsonOkResponse(payload={"total": len(dataList), "dataList": dataList}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,请刷新')) @permission_required(ROLE.dealer, ROLE.subaccount) def createOnsale(request): # type: (WSGIRequest)->JsonResponse dealerId = str(request.user.bossId) payload = json.loads(request.body) if request.body else {} if not payload: return JsonErrorResponse(description=u'传入数据为空') payload['startTime'] = to_datetime(payload['startTime'] + ' 00:00:00') payload['endTime'] = to_datetime(payload['endTime'] + ' 23:59:59') onsale = OnSale(**payload) name = onsale.name # 检查活动的名称 count = OnSale.objects.filter(dealerId=dealerId, name=name).count() if count > 0: return JsonResponse({'result': 0, 'description': u'活动名称重复,优惠活动的名称必须唯一', 'payload': {}}) # 检查下该经销商是否符合资格配置该活动 if onsale.onsaleType == u"京东新人1分购": dealer = Dealer.objects.get(id=dealerId) if not dealer.isJosEnable(): return JsonResponse({"result": 0, "description": u"抱歉,您暂时无法配置此项活动,详情请咨询平台方"}) # 检查活动的设备类型是否匹配 onsaleType = onsale.onsaleType expression = OnSale.onsaleTypeDict[onsaleType]['expression'] onsale.onClickUrl = OnSale.onsaleTypeDict[onsaleType]['onClickUrl'] onsale.showType = OnSale.onsaleTypeDict[onsaleType]['showType'] if expression: for lc in onsale.logicalCodeList: dev = Device.get_dev_by_logicalCode(lc) if dev is None: continue if not eval(expression): return JsonResponse({'result': 0, 'description': u'编码为:%s的设备类型不符合本次活动的要求,请去掉该设备哦' % lc, 'payload': {}}) onsale.dealerId = str(request.user.bossId) onsale.save() return JsonResponse({'result': 1, 'description': '', 'payload': {}}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,请刷新')) @permission_required(ROLE.dealer, ROLE.subaccount) def deleteOnsale(request): # type: (WSGIRequest)->JsonResponse payload = json.loads(request.body) onsaleId = payload.get('id') if not onsaleId: return JsonErrorResponse(description=u'数据不完整,请刷新') obj = OnSale.objects.get(id=onsaleId) obj.delete() return JsonResponse({'result': 1, 'description': '', 'payload': {}}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,删除失败,请您重试')) @permission_required(ROLE.dealer, ROLE.subaccount) def editOnsale(request): # type: (WSGIRequest)->JsonResponse payload = json.loads(request.body) if request.body else {} if not payload: return JsonErrorResponse(description=u'发送的编辑数据为空') payload['startTime'] = to_datetime(payload['startTime'] + ' 00:00:00') payload['endTime'] = to_datetime(payload['endTime'] + ' 23:59:59') obj = OnSale.objects.get(id=payload['id']) obj.update(**payload) return JsonResponse({'result': 1, 'description': '', 'payload': {}}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,请刷新')) @permission_required(ROLE.dealer, ROLE.subaccount) def getOnsaleRecord(request): # type: (WSGIRequest)->JsonResponse pageIndex = int(request.GET.get('pageIndex', 1)) pageSize = int(request.GET.get('pageSize', 10)) startTimeStr = request.GET.get('startTime', None) if not startTimeStr: return JsonErrorResponse(description=u'数据为空,请重试') startTime = to_datetime(startTimeStr + ' 00:00:00') endTimeStr = request.GET.get('endTime', 10) endTime = to_datetime(endTimeStr + ' 23:59:59') onsaleId = request.GET.get('onsaleId', None) rcds = OnSaleRecord.objects.filter(onsaleId=onsaleId, addedTime__gte=startTime, addedTime__lte=endTime) dataList = [] countDict = {} for rcd in rcds: data = {'clickTime': rcd.addedTime.strftime(Const.DATETIME_FMT)} desc = u'用户:%s,' % rcd.nickName if rcd.onsaleDetail.has_key('coins'): desc += u' 领取%s个金币' % rcd.onsaleDetail['coins'] if rcd.onsaleDetail.has_key('duration'): desc += u' 启动免费体验%s分钟' % rcd.onsaleDetail['duration'] if rcd.onsaleDetail.has_key('phoneNumber'): desc += u' 手机号码:%s' % rcd.onsaleDetail['phoneNumber'] data['description'] = desc data.update(rcd.onsaleDetail) for k, v in rcd.onsaleDetail.items(): countKey = '%sTotal' % k if countDict.has_key(countKey): countDict[countKey] += v else: countDict[countKey] = v dataList.append(data) return JsonResponse( { 'result': 1, 'description': '', 'payload': { 'total': len(dataList), 'dataList': dataList[(pageIndex - 1) * pageSize: pageIndex * pageSize], 'countDict': countDict } }) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'创意文件存储失败,请重新试试')) @permission_required(ROLE.dealer, ROLE.subaccount) def uploadCreative(request): # type: (WSGIRequest)->JsonResponse files = request.FILES.getlist('file') if not len(files): return JsonResponse({'result': 0, 'description': u'未找到上传的创意文件,请重新试试', 'payload': {}}) uploader = AliOssFileUploader(inputFile=request.FILES.getlist('file')[0], uploadType='creative') logger.info('[uploadItemPic] %s is being used' % (repr(uploader),)) try: outputUrl = uploader.upload() return JsonResponse({'result': 1, 'description': '', 'payload': outputUrl}) except InvalidFileSize, e: logger.info( '%s(id=%s)\'s uploaded file reached limit' % (request.user.__class__.__name__, str(request.user.id),)) return JsonResponse({'result': 0, 'description': e.message, 'payload': {}}) except InvalidFileName, e: logger.info( '%s(id=%s)\'s uploaded file name is not legal' % (request.user.__class__.__name__, str(request.user.id),)) return JsonResponse({'result': 0, 'description': e.message, 'payload': {}}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'状态更新错误,请刷新页面重新试试')) @permission_required(ROLE.dealer, ROLE.subaccount) def toggleOnsale(request): # type: (WSGIRequest)->JsonResponse payload = json.loads(request.body) status = payload.get('status') onsaleId = payload.get('id') onsale = OnSale.objects.get(id=onsaleId) onsale.status = status onsale.save() return JsonResponse({'result': 1, 'description': '', 'payload': ''}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'获取价格失败,请刷新页面重新试试')) @permission_required(ROLE.dealer, ROLE.subaccount) def getPricePerHour(request): # type: (WSGIRequest)->JsonResponse lc = request.GET.get('logicalCode') dev = Device.objects.get(logicalCode=lc) return JsonResponse({'result': 1, 'description': '', 'payload': dev.otherConf.get('pricePerHour', 2.0)}) @permission_required(ROLE.dealer, ROLE.subaccount) def setBatchDevsSwitch(request): # type: (WSGIRequest)->JsonResponse data = json.loads(request.body) if request.body else {} if not data: return JsonErrorResponse(u'数据为空,请重试') lcs = data['logicalCodes'] isFault = data['isFault'] objs = Device.objects.filter(devNo__in=lcs) for obj in objs: dev = Device.get_dev(obj.devNo) obj.isFault = isFault try: box = ActionDeviceBuilder.create_action_device(dev) box.set_dev_fault(isFault) obj.save() Device.invalid_device_cache(obj.devNo) except Exception as e: logger.exception(e) continue return JsonResponse({"result": 1, "description": "", "payload": {}}) # 批量设置退费保护时间 @permission_required(ROLE.dealer, ROLE.subaccount) def setBatchRefundProtectionTime(request): # type: (WSGIRequest)->JsonResponse data = json.loads(request.body) if request.body else {} if not data: return JsonErrorResponse(u'数据为空,请重试') lcs = data['logicalCodes'] refundProtectionTime = data['refundProtectionTime'] try: Device.objects.filter(devNo__in=lcs).update(refundProtectionTime=refundProtectionTime).select_for_update() except Exception as e: logger.exception(e) @permission_required(ROLE.dealer, ROLE.subaccount) def getCardTicketTypeList(request): # type: (WSGIRequest)->JsonResponse objs = VirtualCard.objects.filter(ownerId=str(request.user.bossId)) dataList = [] for obj in objs: # if '*' in obj.groupIDs: # groupIds = Group.get_group_ids_of_dealer(str(request.user.id)) # else: # groupIds = obj.groupIds data = { 'cardName': obj.cardName, 'price': obj.price, 'groupIds': obj.groupIds, 'periodDays': obj.periodDays, 'expiredTime': obj.expiredTime.strftime('%Y-%m-%d'), 'dayQuota': obj.dayQuota, 'quota': obj.quota, 'userLimit': obj.userLimit, 'userDesc': obj.userDesc, 'dealerDesc': obj.dealerDesc } dataList.append(data) return JsonResponse({"result": 1, "description": '', "payload": {'datalist': dataList}}) @error_tolerate(nil=JsonErrorResponse(u"获取虚拟卡列表失败")) @permission_required(ROLE.dealer, ROLE.subaccount) def getCardTicketList(request): """ 经销商 优惠卡卷列表 可通过卡名称搜索 可通过 售卡状态 卡使用地址进行筛选 :param request: :return: """ pageIndex = int(request.GET.get('pageIndex', 1)) pageSize = int(request.GET.get('pageSize', 10)) status = request.GET.get("status") # 卡状态 groupId = request.GET.get("groupId") # 地址ID searchKey = request.GET.get("searchKey") # 卡名称 # 没有传递状态 则是全部的可用状态 statusList = [int(status)] if status else [0, 1] filters = {"ownerId": str(request.user.bossId), "status__in": statusList} # 传递了地址的情况 则全选地址的 和单独选择的都要算上 if groupId: filters.update({"groupIds__in": ["*", groupId]}) objs = VirtualCard.objects.filter(**filters) if searchKey: objs = objs.search(searchKey, ["cardName"]) total = objs.count() dataList = [] for obj in objs.skip((pageIndex - 1) * pageSize).limit(pageSize): dataList.append(obj.to_dict()) return JsonResponse({"result": 1, "description": '', "payload": {'total': total, 'pageSize': pageSize, 'dataList': dataList}}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'添加失败,请重新试试')) @permission_required(ROLE.dealer, ROLE.subaccount) def addTicketCard(request): def sort_quota(qArray): # type:(list) -> list # 首先检查单位是否重复 对于重复的单位叠加处理 qDict = defaultdict(int) for _item in qArray: _count, _unit = _item["count"], _item["unit"] qDict[_unit] += int(_count) if len(qDict) != len(qArray): raise ServiceException({"result": 2, "description": u"额度设置错误,额度单位重复"}) return sorted(qArray, key=lambda x: x["unit"]) if not request.body: return JsonErrorResponse(description=u'传入数据为空') payload = json.loads(request.body) cardId = payload.get("cardId") cardName = payload["cardName"] userDesc = payload["userDesc"] userLimit = int(payload["userLimit"]) periodDays = float(payload["periodDays"]) try: expiredTime = to_datetime(payload['expiredTime'] + ' 23:59:59') except Exception as e: expiredTime = to_datetime(payload['expiredTime']) devTypeList = payload["devTypeList"] groups = ['*'] if payload['groups'] == '*' else [grp['groupId'] for grp in payload['groups']] price = RMB(payload["price"]) power = int(payload["power"]) try: dayQuota = sort_quota(payload["dayQuota"]) quota = sort_quota(payload["quota"]) except ServiceException as e: return JsonErrorResponse(description=e.result["description"]) if cardId: try: card = VirtualCard.objects.get(id=cardId) except DoesNotExist: return JsonErrorResponse(description=u"编辑虚拟卡卷失败") if card.ownerId != str(request.user.bossId): return JsonErrorResponse(description=u"保存失败,请重新尝试") else: card = VirtualCard() card.update( cardName=cardName, userDesc=userDesc, userLimit=userLimit, periodDays=periodDays, expiredTime=expiredTime, devTypeList=devTypeList, groupIds=groups, price=price, power=power, dayQuota=dayQuota, quota=quota, ownerId=str(request.user.bossId), upsert=True ) return JsonOkResponse() @error_tolerate(logger=logger, nil=JsonErrorResponse(u'删除失败,请重新试试')) @permission_required(ROLE.dealer, ROLE.subaccount) def deleteCardTicket(request): # type: (WSGIRequest)->JsonResponse if not request.body: return JsonErrorResponse(description=u'传入数据为空') payload = json.loads(request.body) cardId = payload['id'] try: VirtualCard.get_collection().update({'_id': ObjectId(cardId)}, {'$set': {'status':-1}}) return JsonResponse({"result": 1, "description": "", "payload": {}}) except Exception as e: logger.exception('update error=%s' % e) return JsonResponse({"result": 0, "description": u"删除失败,请您稍后重试", "payload": {}}) @permission_required(ROLE.dealer, ROLE.subaccount) def switchCardTicket(request): # type: (WSGIRequest)->JsonResponse if not request.body: return JsonErrorResponse(description=u'传入数据为空') payload = json.loads(request.body) cardId = payload['id'] try: vCard = VirtualCard.objects.get(id=cardId) vCard.status = 1 if vCard.status == 0 else 0 vCard.save() return JsonResponse({"result": 1, "description": "", "payload": {}}) except Exception as e: logger.exception('switchCardTicket error=%s' % e) return JsonResponse({"result": 0, "description": u"切换虚拟卡的状态失败,请您刷新页面后重试", "payload": {}}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'删除失败,请重新试试')) @permission_required(ROLE.dealer, ROLE.subaccount) def delUserVirtualCard(request): payload = json.loads(request.body) cardId = payload.get("cardId") if not cardId: return JsonErrorResponse(description=u"该虚拟卡不存在") try: vCard = UserVirtualCard.objects.get(id=cardId) except DoesNotExist: return JsonErrorResponse(description=u"该虚拟卡不存在") if vCard.dealerId != str(request.user.id): return JsonErrorResponse(u"不是您的虚拟卡,无权删除") record = AdjustUserVirtualCardRecord( cardId=cardId, cardNo=vCard.cardNo, beforeAdjust=vCard.expiredTime, operator=str(request.user.id), dealerId=str(request.user.bossId), adjustType=TYPE_ADJUST_USER_VIRTUAL_CARD.DELETE, oldQuota=vCard.quota, adjustQuota=[{"count": 0, "unit": vCard.quota[0].get("unit")}] ) vCard.delete() record.save() return JsonOkResponse(description=u"删除成功") @error_tolerate(logger=logger, nil=JsonErrorResponse(u'调整失败,请重新试试')) @permission_required(ROLE.dealer, ROLE.subaccount) def adjustUserVirtualCardTime(request): payload = json.loads(request.body) cardId = payload.get("cardId", "") days = int(payload.get("days", 0)) if not days: return JsonErrorResponse(description=u"您调整的时间没有变化") if not cardId: return JsonErrorResponse(description=u"该虚拟卡不存在") try: vCard = UserVirtualCard.objects.get(id=cardId) except DoesNotExist: return JsonErrorResponse(description=u"该虚拟卡不存在") if vCard.dealerId != str(request.user.id): return JsonErrorResponse(u"不是您的虚拟卡,无权修改") record = AdjustUserVirtualCardRecord( cardId=cardId, cardNo=vCard.cardNo, beforeAdjust=vCard.expiredTime, operator=str(request.user.id), dealerId=str(request.user.bossId), adjustType=TYPE_ADJUST_USER_VIRTUAL_CARD.ADJUST_DAYS, adjustDays=days, oldQuota=vCard.quota, adjustQuota=[{"count": 0, "unit": vCard.quota[0].get("unit")}] ) vCard.expiredTime = vCard.expiredTime + datetime.timedelta(days=days) vCard.save() record.save() return JsonOkResponse(description=u"操作成功,虚拟卡{}过期调整过期时间{}天".format(str(vCard.id), days)) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'调整失败,请重新试试')) @permission_required(ROLE.dealer, ROLE.subaccount) def adjustUserVirtualCardQuota(request): """ 调整虚拟卡额度 :param request: :return: """ payload = json.loads(request.body) cardId = payload.get("cardId", "") quota = payload.get("quota") dayQuota = payload.get("dayQuota") if not cardId: return JsonErrorResponse(description=u"该虚拟卡不存在") if not all([quota, dayQuota]): return JsonErrorResponse(description="参数不全") try: vCard = UserVirtualCard.objects.get(id=cardId) except DoesNotExist: return JsonErrorResponse(description=u"该虚拟卡不存在") vCard.quota = quota vCard.dayQuota = dayQuota for _item in vCard.quota: _item["count"] = float(_item["count"]) for _item in vCard.dayQuota: _item["count"] = float(_item["count"]) vCard.save() return JsonOkResponse(description=u"操作成功,虚拟卡{}调整额度成功") @error_tolerate(logger=logger, nil=JsonErrorResponse(u"调整失败,请重新试试")) @permission_required(ROLE.dealer, ROLE.subaccount) def adjustUserVirtualState(request): """ 修改虚拟卡 的状态 主要是冻结/非冻结 霍珀需求 这个操作状态就不放入调整记录了 :param request: :return: """ payload = json.loads(request.body) cardId = payload.get("id", "") if not cardId: return JsonErrorResponse(description=u"该虚拟卡不存在") try: vCard = UserVirtualCard.objects.get(id=cardId) except DoesNotExist: return JsonErrorResponse(description=u"该虚拟卡不存在") if vCard.status in ["normal", "warning"]: vCard.status = "frozen" else: vCard.status = "normal" vCard.save() return JsonOkResponse(description=u"操作成功") @error_tolerate(logger=logger, nil=JsonErrorResponse(u'读取失败,请重新试试')) @permission_required(ROLE.dealer, ROLE.subaccount) def userVirtualCardAdjustRecord(request): pageIndex = int(request.GET.get("pageIndex", 1)) pageSize = int(request.GET.get("pageSize", 10)) searchKey = request.GET.get("searchKey") _type = request.GET.get("type") startTime = request.GET.get("startTime") endTime = request.GET.get("endTime") matchFilters = {"dealerId": str(request.user.bossId)} if _type: if _type not in Const.TYPE_ADJUST_USER_VIRTUAL_CARD.choices(): return JsonErrorResponse(description=u"筛选种类错误,无此相关记录") else: matchFilters.update({"adjustType": _type}) if startTime: startDataTime = to_datetime(startTime + ' 00:00:00', "%Y-%m-%d %H:%M:%S") now = datetime.datetime.now() if not endTime: endDateTime = now + datetime.timedelta(days=1) else: endDateTime = to_datetime(endTime, "%Y-%m-%d") if endDateTime > now: endDateTime = now endDateTime = endDateTime + datetime.timedelta(days=1) if startDataTime >= endDateTime: endDateTime = startDataTime + datetime.timedelta(days=1) matchFilters.update( { "dateTimeAdded": { "$gte": startDataTime, "$lte": endDateTime } } ) if searchKey: matchFilters.update({ "cardNo": searchKey }) records = AdjustUserVirtualCardRecord.get_collection().find( matchFilters ).sort( [("dateTimeAdded", -1)] ).skip( pageSize * (pageIndex - 1) ).limit( pageSize ) data = [] for record in records: oldQuota = record.get("oldQuota")[0] adjustQuota = record.get("adjustQuota")[0] newQuota = { "count" :oldQuota.get("count") + adjustQuota.get("count"), "unit": oldQuota.get("unit") } dealerId = record.get("operator") dealer = Dealer.get_dealer(dealerId) operator = dealer.get("nickname") or dealer.get("username") data.append( { "cardId": record.get("cardId"), "cardNo": record.get("cardNo"), "beforeAdjustExpired": record.get("beforeAdjust").strftime("%Y-%m-%d %H:%M:%S"), "afterAdjustExpired": (record.get("beforeAdjust") + datetime.timedelta(days=record.get("adjustDays"))).strftime("%Y-%m-%d %H:%M:%S"), "beforeAdjustQuota": "{} {}".format(oldQuota.get("count"), oldQuota.get("unit")), "afterAdjustQuota": "{} {}".format(newQuota.get("count"), oldQuota.get("unit")), "operator": operator, "adjustType": record.get("adjustType"), "adjustDate": record.get("dateTimeAdded") } ) return JsonOkResponse(payload={"total": 10000, "dataList": data}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'读取失败,请重新试试')) @permission_required(ROLE.dealer, ROLE.subaccount) def getUserCardTicketList(request): """ 经销商获取 已经发售的虚拟卡 可以通过卡号搜索 可以通过根据发卡地址来筛选 groupId 可以通过卡类型筛选 dealerCardTypeId 可以通过卡的状态来筛选 status 0(没过期 ) 1(过期) :param request: :return: """ pageIndex = int(request.GET.get('pageIndex', 1)) pageSize = int(request.GET.get('pageSize', 10)) searchKey = request.GET.get('searchKey', '') dealerCardTypeId = request.GET.get("dealerCardTypeId") status = request.GET.get("status") groupId = request.GET.get("groupId") userId = str(request.GET.get('userId', '')) isEmptyCard = int(request.GET.get('isEmptyCard', 0)) if isEmptyCard: objs = VirtualCardBuilder.find_dealer_virtual_card(str(request.user.id)).order_by('-id') else: filters = { "dealerId": str(request.user.bossId) } # 添加筛选条件 if userId: filters.update({"openIds__contains": userId}) if groupId: filters.update({"groupIds__in": ["*", groupId]}) if dealerCardTypeId: filters.update({"cardTypeId": dealerCardTypeId}) if status: nowTime = datetime.datetime.now() status = int(status) filters.update({"expiredTime__gt": nowTime}) if status else filters.update({"expiredTime__lt": nowTime}) objs = UserVirtualCard.objects.filter(**filters).order_by('-startTime') if searchKey: objs = objs.search(searchKey) total = objs.count() dataList = [] for obj in objs.skip((pageIndex - 1) * pageSize).limit(pageSize): data = obj.to_dict() data.update(obj.quotaInfo) dataList.append(data) return JsonResponse({"result": 1, "description": '', "payload": {'total': total, 'dataList': dataList}}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u"读取失败,请重新试试")) @permission_required(ROLE.dealer, ROLE.subaccount) def getUserCardTicketDetail(request): """ 获取用户的 :param request: :return: """ cardId = request.GET.get("cardId", "") try: vCard = UserVirtualCard.objects.get(id=cardId) except DoesNotExist: return JsonErrorResponse(description=u"查询错误,请刷新页面重试") data = vCard.to_detail() data.update({"frozenState": not vCard.status in ["normal", "warning"]}) return JsonOkResponse(payload=data) @error_tolerate(logger=logger, nil=JsonErrorResponse(u"备注失败,请重新试试")) @permission_required(ROLE.dealer, ROLE.subaccount) def remarkUserVirtual(request): """ 霍珀需求 经销商为已发卡卷添加备注 :param request: :return: """ payload = json.loads(request.body) cardId = payload.get("cardId") remark = payload.get("remark") dealerId = str(request.user.bossId) try: vCard = UserVirtualCard.objects.get(id=cardId) except DoesNotExist: return JsonErrorResponse(description=u"虚拟卡备注失败,请刷新页面试试") if vCard.dealerId != dealerId: return JsonErrorResponse(description=u"不是您的虚拟卡您无权修改") vCard.update(remark=remark) return JsonOkResponse() @error_tolerate(logger=logger, nil=JsonErrorResponse(u'读取失败,请重新试试')) @permission_required(ROLE.dealer, ROLE.subaccount) def getElcPriceModList(request): dealerId = str(request.user.bossId) objs = ElecPriceTemplate.objects.filter(ownerId=dealerId) resultList = [{'id': str(obj.id), 'name': obj.name, 'price': obj.priceList} for obj in objs] return JsonResponse({"result": 1, "description": '', "payload": resultList}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'保存失败,请重新试试')) @permission_required(ROLE.dealer, ROLE.subaccount) def saveElcPriceMod(request): dealerId = str(request.user.bossId) payload = json.loads(request.body) priceList = payload['price'] logicalCode = payload['logicalCode'] newName = payload.get('name', None) dev = Device.get_dev_by_logicalCode(logicalCode) group = Group.get_group(dev['groupId']) if newName is None: newName = group['groupName'] + datetime.datetime.now().strftime('%Y%m%d%H%M%S') newObj = ElecPriceTemplate(ownerId=dealerId, name=newName, priceList=priceList) newObj.save() return JsonResponse({"result": 1, "description": '', "payload": None}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'保存失败,请重新试试')) @permission_required(ROLE.dealer, ROLE.subaccount) def saveDeviceElcPrice(request): """ 这个是 用心汽车桩专用的 保存汽车的电价设置 """ payload = json.loads(request.body) priceList = payload['price'] logicalCode = payload['logicalCode'] from apps.web.core.device_define.yongxin import DefaultParams if len(priceList) != DefaultParams.DEFAULT_ELEC_PRICE_INTERVAL_NUM: return JsonErrorResponse(description=u"电价参数设置错误,请重新试试") if filter(lambda x: int(x * 100) > DefaultParams.DEFAULT_MAX_ELEC_PRICE, priceList): return JsonErrorResponse(description=u"电价最大为2.55元") device = Device.objects.get(logicalCode=logicalCode) device.otherConf['priceList'] = priceList device.save() Device.invalid_device_cache(device.devNo) return JsonOkResponse() @error_tolerate(logger=logger, nil=JsonErrorResponse(u'删除电价失败,请重新试试')) @permission_required(ROLE.dealer, ROLE.subaccount) def deleteElcPriceMod(request): payload = json.loads(request.body) ids = [ObjectId(_) for _ in payload['id']] ElecPriceTemplate.get_collection().remove({'_id': {'$in': ids}}) return JsonResponse({"result": 1, "description": '', "payload": None}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'上传的商品图片存储失败,请重新试试')) @permission_required(ROLE.dealer, ROLE.subaccount) def uploadItemPic(request): # type: (WSGIRequest)->JsonResponse files = request.FILES.getlist('file') if not len(files): return JsonResponse({'result': 0, 'description': u'未找到上传的商品图片,请重新试试', 'payload': {}}) uploader = AliOssFileUploader(inputFile=request.FILES.getlist('file')[0], uploadType='item') logger.info('[uploadItemPic] %s is being used' % (repr(uploader),)) try: outputUrl = uploader.upload() return JsonResponse({'result': 1, 'description': '', 'payload': outputUrl}) except InvalidFileSize, e: logger.info( '%s(id=%s)\'s uploaded file reached limit' % (request.user.__class__.__name__, str(request.user.id),)) return JsonResponse({'result': 0, 'description': e.message, 'payload': {}}) except InvalidFileName, e: logger.info( '%s(id=%s)\'s uploaded file name is not legal' % (request.user.__class__.__name__, str(request.user.id),)) return JsonResponse({'result': 0, 'description': e.message, 'payload': {}}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'编辑商品类型失败,请重新试试')) @permission_required(ROLE.dealer, ROLE.subaccount) def addEditItemType(request): payload = json.loads(request.body) ownerId = str(request.user.bossId) itemId = payload.get('id', None) title = payload.get('name', None) desc = payload.get('description', None) picUrl = payload.get('img', "") price = 100 * payload.get('price') try: if itemId is not None: obj = ItemType.objects.get(id=itemId) obj.title, obj.desc, obj.picUrl, obj.price = title, desc, picUrl, price obj.save() else: newObj = ItemType(ownerId=ownerId, title=title, desc=desc, picUrl=picUrl, price=price) newObj.save() itemId = str(newObj.id) except DoesNotExist: newObj = ItemType(ownerId=ownerId, title=title, desc=desc, picUrl=picUrl, price=price) newObj.save() itemId = str(newObj.id) except Exception as e: logger.exception(e) return JsonErrorResponse(description=u'未知错误') return JsonResponse({"result": 1, "description": '', "payload": {"id": itemId}}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'删除商品类型失败,请重新试试')) @permission_required(ROLE.dealer, ROLE.subaccount) def deleteItemType(request): payload = json.loads(request.body) ids = payload.get('ids', []) itemIds = [ObjectId(obj) for obj in ids] try: ItemType.get_collection().remove({'_id': {'$in': itemIds}}) except Exception as e: logger.exception(e) return JsonErrorResponse(description=u'未知错误') return JsonResponse({"result": 1, "description": '', "payload": None}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'获取商品类型失败,请重新试试')) @permission_required(ROLE.dealer, ROLE.subaccount) def getItemTypes(request): ownerId = str(request.user.bossId) itemTypeId = request.GET.get('itemTypeId', '') if itemTypeId: objs = ItemType.objects.filter(ownerId=ownerId, id=itemTypeId) else: objs = ItemType.objects.filter(ownerId=ownerId) dataList = [{'id': str(obj.id), 'name': obj.title, 'description': obj.desc, 'img': obj.picUrl, 'price': float(obj.price) / 100.0} for obj in objs ] return JsonResponse({"result": 1, "description": '', "payload": {'dataList': dataList}}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'编辑格子失败')) @permission_required(ROLE.dealer, ROLE.subaccount) def addEditCell(request): payload = json.loads(request.body) logicalCode = payload.get('logicalCode') cellId = payload.get('id', None) cellNo = payload.get('cellNo') boardNo = int(payload.get('boardNo')) lockNo = int(payload.get('lockNo')) itemTitle = payload.get('itemTitle', '') itemDesc = payload.get('itemDesc', '') itemPicUrl = payload.get('itemPicUrl', '') itemPrice = payload.get('itemPrice') * 100 try: if cellId is not None: obj = Cell.objects.get(id=cellId) obj.cellNo, obj.boardNo, obj.lockNo, obj.itemTitle, obj.itemDesc, obj.itemPicUrl, obj.itemPrice = cellNo, boardNo, lockNo, itemTitle, itemDesc, itemPicUrl, itemPrice obj.save() else: newObj = Cell(logicalCode=logicalCode, cellNo=cellNo, boardNo=boardNo, lockNo=lockNo, itemTitle=itemTitle, itemDesc=itemDesc, itemPicUrl=itemPicUrl, itemPrice=itemPrice) newObj.save() cellId = str(newObj.id) except DoesNotExist, e: newObj = Cell(logicalCode=logicalCode, cellNo=cellNo, boardNo=boardNo, lockNo=lockNo, itemTitle=itemTitle, itemDesc=itemDesc, itemPicUrl=itemPicUrl, itemPrice=itemPrice) newObj.save() cellId = str(newObj.id) except Exception, e: return JsonErrorResponse(description=u'未知错误') # 重新挂上washConfig套餐信息 cells = Cell.objects.filter(logicalCode=logicalCode) washConfig = {} for cell in cells: washConfig[str(cell.id)] = { 'name': cell.cellNo, 'coins': float(cell.itemPrice / 100.0), 'price': float(cell.itemPrice / 100.0), 'time': 1, 'description': cell.itemTitle, 'imgList': [cell.itemPicUrl], 'unit': u'次' } dev = Device.get_dev_by_logicalCode(logicalCode) dev['washConfig'] = washConfig Device.get_collection().update({'devNo': dev['devNo']}, {'$set': {'washConfig': dev['washConfig']}}) Device.invalid_device_cache(dev['devNo']) return JsonResponse({"result": 1, "description": '', "payload": {"id": cellId}}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'操作失败')) @permission_required(ROLE.dealer, ROLE.subaccount) def deleteCell(request): payload = json.loads(request.body) logicalCode = payload.get('logicalCode') cellIds = payload.get('ids') Cell.objects(id__in=cellIds).delete() # 重新挂上washConfig套餐信息 cells = Cell.objects.filter(logicalCode=logicalCode) washConfig = {} for cell in cells: washConfig[str(cell.id)] = { 'name': cell.cellNo, 'coins': float(cell.itemPrice / 100.0), 'price': float(cell.itemPrice / 100.0), 'time': 1, 'description': cell.itemTitle, 'imgList': [], 'unit': u'次' } dev = Device.get_dev_by_logicalCode(logicalCode) dev['washConfig'] = washConfig Device.get_collection().update({'devNo': dev['devNo']}, {'$set': {'washConfig': dev['washConfig']}}) Device.invalid_device_cache(dev['devNo']) return JsonResponse({"result": 1, "description": '', "payload": None}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'查询格子失败')) @permission_required(ROLE.dealer, ROLE.subaccount) def getDeviceCells(request): logicalCode = request.GET.get('logicalCode') pageIndex = int(request.GET.get('pageIndex', 1)) pageSize = int(request.GET.get('pageSize', 30)) objs = Cell.objects.filter(logicalCode=logicalCode) dev = Device.get_dev_by_logicalCode(logicalCode) box = ActionDeviceBuilder.create_action_device(dev) lockStatusDict = box.get_all_lock_status() dataList = [] quantity, consumptionQuantity = 0, 0 for obj in objs: dataList.append( { 'id': str(obj.id), 'cellNo': obj.cellNo, 'boardNo': obj.boardNo, 'lockNo': obj.lockNo, 'itemTitle': obj.itemTitle, 'itemDesc': obj.itemDesc, 'itemPicUrl': obj.itemPicUrl, 'itemPrice': round(obj.itemPrice / 100.0, 2), 'lockStatus': lockStatusDict.get(obj.cellNo, 'close'), 'quantity': 1 if obj.itemStatus == 'full' else 0 } ) if obj.itemStatus == 'full': quantity += 1 else: consumptionQuantity += 1 dev['quantity'] = quantity dev['consumptionQuantity'] = consumptionQuantity Device.update_field( dev_no=dev['devNo'], update=True, quantity=quantity, consumptionQuantity=consumptionQuantity) return JsonResponse({'result': 1, 'description': '', 'payload': {'dataList': dataList[(pageIndex - 1) * pageSize:pageIndex * pageSize]}}) def openManyCells(dev, strIds): ids = [ObjectId(id) for id in strIds] cellDict = {} cells = Cell.objects.filter(id__in=ids) for cell in cells: if cellDict.has_key(str(cell.boardNo)): cellDict[str(cell.boardNo)].append(cell.lockNo) else: cellDict[str(cell.boardNo)] = [cell.lockNo] box = ActionDeviceBuilder.create_action_device(dev) for boardNo, lockNos in cellDict.items(): try: box.open_many_locks(boardNo, lockNos) except Exception as e: logger.exception(e) return JsonResponse({"result": 0, "description": u'打开格子失败', "payload": None}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'操作失败')) @permission_required(ROLE.dealer, ROLE.subaccount) def addGoodsToDeviceCell(request): payload = json.loads(request.body) logicalCode = payload['logicalCode'] dev = Device.get_dev_by_logicalCode(logicalCode) openManyCells(dev, payload['ids']) ids = [ObjectId(strId) for strId in payload['ids']] cells = Cell.objects.filter(id__in=ids) for cell in cells: cell.itemStatus = 'full' try: cell.save() # 增加一条补货记录 newStock = StockRecord( logicCode=dev['logicalCode'], imei=dev['devNo'], stockType='add', stockTime=datetime.datetime.now().strftime(Const.DATETIME_FMT), number=1, more="%s:%s" % (cell.cellNo, cell.itemTitle) ) newStock.save() except Exception, e: continue Cell.update_dev_quantity_from_cell(dev) return JsonResponse({"result": 1, "description": '', "payload": None}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'操作失败')) @permission_required(ROLE.dealer, ROLE.subaccount) def unlockCell(request): payload = json.loads(request.body) logicalCode = payload.get('logicalCode') ids = payload.get('id') dev = Device.get_dev_by_logicalCode(logicalCode) openManyCells(dev, ids) return JsonResponse({"result": 1, "description": '', "payload": None}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'操作失败')) @permission_required(ROLE.dealer, ROLE.subaccount) def getDeviceCellsFromDB(request): logicalCode = request.GET.get('logicalCode') pageIndex = int(request.GET.get('pageIndex', 1)) pageSize = int(request.GET.get('pageSize', 30)) objs = Cell.objects.filter(logicalCode=logicalCode) dataList = [] quantity, consumptionQuantity = 0, 0 for obj in objs: dataList.append( {'id': str(obj.id), 'cellNo': obj.cellNo, 'boardNo': obj.boardNo, 'lockNo': obj.lockNo, 'itemTitle': obj.itemTitle, 'itemDesc': obj.itemDesc, 'itemPicUrl': obj.itemPicUrl, 'itemPrice': round(obj.itemPrice / 100.0, 2), # 'lockStatus':lockStatusDict.get(obj.cellNo,'close'), 'quantity': 1 if obj.itemStatus == 'full' else 0} ) if obj.itemStatus == 'full': quantity += 1 else: consumptionQuantity += 1 # TODO 为啥这两个参数只打内存,不更新到数据库 Device.get_and_update_device_cache( dev_no=Device.get_dev_by_logicalCode(logicalCode)['devNo'], quantity=quantity, consumptionQuantity=consumptionQuantity) return JsonResponse({'result': 1, 'description': '', 'payload': {'dataList': dataList[(pageIndex - 1) * pageSize:pageIndex * pageSize]}}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'获取列表失败')) @permission_required(ROLE.dealer, ROLE.subaccount) def getOfflineTaskList(request): # type: (WSGIRequest)->JsonResponse current_user = request.user # type: Dealer page_index = int(request.GET.get('pageIndex', 1)) page_size = int(request.GET.get('pageSize', 10)) search_key = request.GET.get('searchKey', None) tasks = OfflineTask.objects(ownerId=current_user.id, role=current_user.role).search(search_key).order_by('-dateTimeAdded') total = tasks.count() return JsonOkResponse( payload={ 'dataList': [t.to_dict() for t in tasks.paginate(pageSize=page_size, pageIndex=page_index)], 'total': total }) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'操作失败')) @permission_required(ROLE.dealer, ROLE.subaccount) def exportBusinessStats(request): """ 经销商的手机 导出报表 :param request: :return: """ dealer = request.user # type: Dealer request_get = request.GET.copy() if 'kind' not in request_get: request_get['kind'] = 'income' if 'time' in request_get and (('startTime' not in request_get) or ('endTime' not in request_get)): # 将月份转换成开始时间为1号,结束时间为当月最后一天,因为需要一个前闭后闭区间,所以最后一天日期减一天 request_get['startTime'] = datetime.datetime.strptime(request_get.pop('time')[0], "%Y-%m") request_get['endTime'] = request_get['startTime'] + relativedelta(months=1) - datetime.timedelta(days=1) request_get['startTime'] = request_get['startTime'].strftime(Const.DATE_FMT) request_get['endTime'] = request_get['endTime'].strftime(Const.DATE_FMT) query = prepare_query(request_get) # type: Query def get_offline_task_name(task_type, user, **kwargs): # type: (basestring, Dealer, Dict)->basestring type_desc_map = { 'income': u'收益', 'consume': u'消费', 'monthly_bill': u'月度' } tmp_list = [task_type, type_desc_map.get(kwargs['kind']), user.username] if 'logicalCode' in kwargs: tmp_list.append(u'设备编号_%s' % (kwargs['logicalCode'],)) if 'groupId' in kwargs: address = Group.get_group(kwargs['groupId']).get('address', '') tmp_list.append(u'地址_%s' % (address,)) if 'source' in kwargs: kind = kwargs.get('kind') if kind == 'income': source_translation = DEALER_INCOME_SOURCE_TRANSLATION.get(kwargs['source']) elif kind == 'consume': source_translation = DEALER_CONSUMPTION_AGG_KIND_TRANSLATION.get(kwargs['source']) else: source_translation = None if source_translation: tmp_list.append(source_translation) tmp_list.append(u'%s至%s' % (kwargs['startTime'], kwargs['endTime'])) tmp_list.append(str(utils_datetime.generate_timestamp_ex())) return '-'.join(tmp_list).replace("/", "_") # 此处生成的是 报表文件的名称 offline_task_name = get_offline_task_name( task_type=OfflineTaskType.BUSINESS_REPORT, user=dealer, **query.raw) file_path, offline_task = OfflineTask.issue_export_report(offline_task_name=offline_task_name, process_func_name='generate_business_stats_report_by_dealer', task_type=OfflineTaskType.BUSINESS_REPORT, userid=str(dealer.id), role=ROLE.dealer) queryAttrs = query.attrs queryAttrs['dateTimeAdded__lte'] = dt_to_timestamp(queryAttrs['dateTimeAdded__lte']) queryAttrs['dateTimeAdded__gte'] = dt_to_timestamp(queryAttrs['dateTimeAdded__gte']) queryAttrs['dealerId'] = str(dealer.id) task_caller(func_name=offline_task.process_func_name, offline_task_id=str(offline_task.id), filePath=file_path, queryAttrs=queryAttrs) return JsonOkResponse(payload=str(offline_task.id)) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'操作失败')) @permission_required(ROLE.dealer, ROLE.subaccount) def exportAllTicketList(request): """ 经销商的下的所以虚拟卡 :param request: :return: """ dealer = request.user # type: Dealer timeStr = arrow.now().format('YYYY-MM-DD_HH:mm:ss') offline_task_name = '已发虚拟卡_{}_{}_{}'.format(dealer.username, timeStr, random.randint(100000, 999999)) file_path, offline_task = OfflineTask.issue_export_report(offline_task_name=offline_task_name, process_func_name='export_vcard_info_excel_from_db', task_type=OfflineTaskType.BUSINESS_REPORT, userid=str(dealer.id), role=ROLE.dealer) queryDict = {} queryDict['dealerId'] = str(dealer.id) task_caller(func_name=offline_task.process_func_name, offline_task_id=str(offline_task.id), filepath=file_path, queryDict=queryDict) return JsonOkResponse(payload=str(offline_task.id)) @error_tolerate(logger=logger, nil=JsonErrorResponse(u"获取收益列表失败")) @permission_required(ROLE.dealer) def getGroupUserAccountInfo(request): """ 经销商下所有地址的用户充值,消费,余额情况 """ dealer = request.user # type: Dealer def get_offline_task_name(task_type, user, **kwargs): # type: (basestring, Dealer, Dict)->basestring tmp_list = [task_type, user.username] if 'logicalCode' in kwargs and kwargs['logicalCode']: tmp_list.append(u'设备编号_%s' % (kwargs['logicalCode'],)) if 'groupId' in kwargs and kwargs['groupId']: address = Group.get_group(kwargs['groupId']).get('address', '') tmp_list.append(u'地址_%s' % (address,)) tmp_list.append(u'%s至%s' % (kwargs['startTime'], kwargs['endTime'])) tmp_list.append(str(utils_datetime.generate_timestamp_ex())) return '-'.join(tmp_list).replace("/", "_") query_dict = { 'startTime': request.GET.get('startTime', '') + ' 00:00:00', 'endTime': request.GET.get('endTime', '') + ' 23:59:59', 'ownerId': str(dealer.id) } offline_task_name = get_offline_task_name( task_type=u'地址用户充值消费情况统计报表', user=dealer, **query_dict) file_path, offline_task = OfflineTask.issue_export_report(offline_task_name=offline_task_name, process_func_name='export_group_user_account_excel_form_db', task_type=OfflineTaskType.BUSINESS_REPORT, userid=str(dealer.id), role=ROLE.dealer) task_caller(func_name=offline_task.process_func_name, offline_task_id=str(offline_task.id), filepath=file_path, queryDict=query_dict) return JsonResponse({ 'result': 1, 'description': u"请前往离线任务查看任务处理情况", 'payload': str(offline_task.id)}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'操作失败')) @permission_required(ROLE.dealer, ROLE.subaccount) def getOfflineTaskStatus(request): # type: (WSGIRequest)->JsonResponse """ :param request: :return: """ task_id = request.GET.get('id') if not task_id: return JsonErrorResponse(description=u'查询ID为空') task = OfflineTask.objects(id=str(task_id)).get() # type: OfflineTask return JsonOkResponse(payload=task.status) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'操作失败')) @permission_required(ROLE.dealer, ROLE.subaccount) def getSubAccountList(request): pageIndex = int(request.GET.get('pageIndex', 1)) pageSize = int(request.GET.get('pageSize', 10)) subaccounts = SubAccount.objects.filter(bossId=str(request.user.bossId)) total = subaccounts.count() dataList = [] for obj in subaccounts.skip((pageIndex - 1) * pageSize).limit(pageSize): if obj.bossId == str(obj.id): continue dataList.append({ 'username': obj.username, 'permissionList': obj.permissionList, 'nickname': obj.nickname, 'id': str(obj.id) }) return JsonOkResponse(payload={'agentId': request.user.agentId, 'dataList': dataList, 'total': total}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'操作失败')) @permission_required(ROLE.dealer, ROLE.subaccount) def addEditSubAccount(request): bossId = request.user.bossId payload = json.loads(request.body) strId = payload.get('id', None) if strId is None: username = payload['username'] code = payload['code'] status, desc = dealerRegisterSMSProvider.verify(username, code) if not status: return JsonErrorResponse(desc) count = SubAccount.objects.filter(username=username, bossId=str(bossId)).count() if count > 0: return JsonResponse({"result": 0, "description": u'该手机号已经是子账号了,不允许重复配置该手机号为子账号', "payload": None}) password = payload['password'] if (not password) or len(password) < 6: return JsonResponse({"result": 0, "description": u'必须输入密码,密码长度不能小于6', "payload": None}) nickname = payload['nickname'] if not nickname: return JsonResponse({"result": 0, "description": u'必须配置昵称', "payload": None}) newObj = SubAccount( username=username, nickname=nickname, password=make_password(password), permissionList=payload.get('permissionList', []), agentId=request.user.agentId, bossId=bossId ) newObj.save() return JsonOkResponse(payload={'id': str(newObj.id)}) else: username = payload['username'] try: obj = SubAccount.objects.get(id=strId) except DoesNotExist: return JsonResponse({"result": 0, "description": u'并未找到该子账号,可能已经被删除了', "payload": None}) password = payload['password'] if (not password) or len(password) < 6: return JsonResponse({"result": 0, "description": u'必须输入密码,密码长度不能小于6', "payload": None}) nickname = payload['nickname'] if not nickname: return JsonResponse({"result": 0, "description": u'必须配置昵称', "payload": None}) obj.username = username obj.nickname = nickname obj.permissionList = payload.get('permissionList', []) obj.save() obj.set_password(password) return JsonOkResponse(payload={'id': str(obj.id)}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'操作失败')) @permission_required(ROLE.dealer, ROLE.subaccount) def deleteSubAccount(request): payload = json.loads(request.body) idsTemp = payload.get('ids', []) ids = [ObjectId(_) for _ in idsTemp] SubAccount.objects.filter(id__in=ids).delete() return JsonResponse({"result": 1, "description": '', "payload": None}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'操作失败')) @permission_required(ROLE.dealer, ROLE.subaccount) def getAccountPermission(request): # 授权经销商用户 if check_role(request.user, ROLE.dealer): permissions = hasattr(request, 'permissions') and getattr(request, 'permissions') # type: dict if permissions: permissions.update({'role': 'dealerWorker'}) return JsonOkResponse(payload=permissions) # 获取经销商或者子账号所属经销商权限 mainMenu, homepageData = request.user.myBoss.query_home_page_layout() # 调整子账号权限 if check_role(request.user, ROLE.subaccount): for pm in request.user.permissionList: if pm in ['today_income', 'today_pay_income', 'today_ad_income', 'offline_coins']: homepageData[pm] = True else: mainMenu[pm] = True leftHomepage = list(set(Const.HOME_PAGE_DATA_LIST.keys()) - set(request.user.permissionList)) for pm in leftHomepage: homepageData[pm] = False leftMainmenu = list(set(Const.MAIN_MENU_LIST.keys()) - set(request.user.permissionList)) for pm in leftMainmenu: mainMenu[pm] = False return JsonOkResponse(payload={'role': request.user.role, 'homepageData': homepageData, 'mainMenu': mainMenu}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'操作失败')) @permission_required(ROLE.dealer) def getAccountPermissionById(request): strId = request.GET.get('id', None) subList = SubAccount.objects.get(id=strId).permissionList mainMenu, homepageData = request.user.query_home_page_layout() for menu, value in mainMenu.iteritems(): if not value: continue if menu in subList: mainMenu[menu] = True else: mainMenu[menu] = False mainMenu['sim_card'] = False # sim卡充值不允许给子账号操作 for menu, value in homepageData.iteritems(): if not value: continue if menu in subList: homepageData[menu] = True else: homepageData[menu] = False return JsonOkResponse(payload={'homepageData': homepageData, 'mainMenu': mainMenu}) @permission_required(ROLE.dealer) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,请稍后再试')) def subAccountRegisterCode(request): # type: (WSGIRequest)->JsonResponse payload = json.loads(request.body) phoneNumber = payload.get('username', None) agent = Agent.get_agent(request.user.agentId) productName = agent['productName'] if not phoneNumber: return JsonResponse({'result': 0, 'description': u'手机号码为空'}) if len(SubAccount.objects.filter(username=phoneNumber, bossId=str(request.user.id))): return JsonResponse({'result': 0, 'description': u'该手机号已经是您的子账号了'}) status, msg = dealerRegisterSMSProvider.get(phoneNumber=phoneNumber, productName=productName, vendor=SysParas.get_sms_vendor(request.user.smsVendor)) if not status: return JsonResponse({'result': 0, 'description': msg}) else: return JsonResponse({'result': 1, 'description': ''}) @permission_required(ROLE.dealer) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,请稍后再试')) def saveAccountPermission(request): payload = json.loads(request.body) subId = payload.get('id') homepageData = payload.get('homepageData', []) mainMenu = payload.get('mainMenu', []) obj = SubAccount.objects.get(id=subId) perList = [] for k, v in homepageData.items(): if v: perList.append(k) for k, v in mainMenu.items(): if v: perList.append(k) obj.permissionList = perList obj.save() return JsonResponse({'result': 1, 'description': ''}) @permission_required(ROLE.dealer) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,请稍后再试')) def getAlarmList(request): # type: (WSGIRequest)->JsonResponse pageIndex = int(request.GET.get('pageIndex', 1)) pageSize = int(request.GET.get('pageSize', 10)) queryset = FaultRecord.objects(dealerId=str(request.user.id), status=FAULT_RECORD_STATUS.INIT).order_by('-createdTime') records = queryset.paginate(pageIndex=pageIndex, pageSize=pageSize) # type: Iterable[FaultRecord] total = queryset.count() return JsonOkResponse(payload={'dataList': [ _.to_dict() for _ in records ], 'total': total}) @permission_required(ROLE.dealer) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,请稍后再试')) def handleAlarm(request): # type: (WSGIRequest)->JsonResponse payload = json.loads(request.body) id_ = payload.get('id') if id_ is None: return JsonErrorResponse(description=u'id未传入') status = payload.get('status') if status is None: return JsonErrorResponse(description=u'处理状态未传入') dealedDetail = payload.get("dealedDetail", "") if type(id_) == list: id_list = id_ else: id_list = [id_] for item_id in id_list: alarm = FaultRecord.objects(id=item_id).get() # type: FaultRecord alarm.set_status(status=status, dealedDetail=dealedDetail) if status == "handled": task_caller( "send_to_xf_fault_handle", devNo=alarm.imei, faultId=str(alarm.id) ) handler_event_to_zhejiang(id_list[0]) dev = Device.get_dev(alarm.imei) box = ActionDeviceBuilder.create_action_device(dev) if box.isHaveFaultHandle: try: box.faultHandle(alarm=alarm) except: pass return JsonOkResponse() @permission_required(ROLE.dealer) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,请稍后再试')) def checkAlarm(request): # type: (WSGIRequest)->JsonResponse id_ = request.GET.get('id') if id_ is None: return JsonErrorResponse(description=u'id未传入') alarm = FaultRecord.objects(id=id_).get() # type: FaultRecord dev = Device.get_dev(alarm.imei) box = ActionDeviceBuilder.create_action_device(dev) try: desc = box.check_alarm(alarm) except ServiceException , e: return JsonResponse({"result": 0, "description": e.result.get('description'), 'payload': {}}) except Exception, e: return JsonResponse({"result": 0, "description": u'系统异常,检查告警失败', 'payload': {}}) return JsonResponse({"result": 1, "description": desc, 'payload': {}}) @permission_required(ROLE.dealer) @error_tolerate(logger = logger, nil = JsonErrorResponse(u'系统错误,请稍后再试')) def withdrawEntry(request): # type: (WSGIRequest)->JsonResponse user = request.user # type: Dealer if not check_role(user, ROLE.dealer): return ErrorResponseRedirect(error = u'权限错误') # 检查是否有非法订单,如果有,不允许提现直接返回错误 if RechargeRecord.have_illegal_order(str(user.id), user.maxPackagePrice): return ErrorResponseRedirect(error = u'系统检测到部分存疑订单,暂时不能提现。请联系平台客服确认') source_key = request.GET.get('sourceId') if not WithdrawGateway.is_ledger(source_key): return ErrorResponseRedirect(error = u'系统配置错误,请联系平台客服(10003)') source_type = request.GET.get('sourceType') assert source_type in DEALER_INCOME_TYPE.choices(), 'invalid dealer income type' if source_key not in user.balance_dict(source_type): return ErrorResponseRedirect(error = u'提现参数错误,请刷新后重试') is_ledger, agent, withdraw_gateway_list = Agent.withdraw_gateway_list(source_key) if not is_ledger: return ErrorResponseRedirect(error = u'系统配置错误,请联系平台客服(10005)') wechat_withdraw_gateway = withdraw_gateway_list['wechat'] # type: WithdrawGateway if wechat_withdraw_gateway.support_withdraw and not wechat_withdraw_gateway.manual_withdraw: code = request.GET.get('code', None) if not code: redirect = request.GET.get('redirect') return ExternalResponseRedirect( WechatAuthBridge(wechat_withdraw_gateway.app).generate_auth_url_base_scope( concat_server_end_url( uri = '/dealer/withdraw/entry?sourceType={source_type}&sourceId={source_key}'.format( source_type = source_type, source_key = source_key )), payload = base64.b64encode(redirect))) else: auth_bridge = WechatAuthBridge(wechat_withdraw_gateway.app) openId = auth_bridge.authorize(code) if openId is not None: redirect = base64.b64decode(request.GET.get('payload')) redirect = add_query(redirect, { 'sourceType': source_type, 'sourceId': source_key, 'openId': openId }) return FrontEndResponseRedirect(redirect) else: return ErrorResponseRedirect(error = u'微信授权失败,请刷新后重试') else: redirect = request.GET.get('redirect') redirect = add_query(redirect, { 'sourceType': source_type, 'sourceId': source_key, 'openId': '' }) return FrontEndResponseRedirect(redirect) @permission_required(ROLE.dealer) def ActivateUser(request): """ 安骑的 用户缴纳金额后 经销商激活 需要查询对应的 推荐人,如果存在推荐人,将其金币数量增加固定数量 """ user = request.user payload = json.loads(request.body) _id = payload.get("id", "") # 存有用户激活信息的ID status = payload.get("status", "") remarks = payload.get("remarks", "") groupIds = Group.get_group_ids_of_dealer(str(user.id)) # 获取该经销商下的所有的groupId customer = MyUser.objects.get(id=_id) if int(status) == 2: # 2表示用户信息激活状态为成功 MyUser.set_active_info( {"isMember": True, "status": status, "remarks": remarks}, openId=customer.openId, agentId=customer.agentId, groupId__in=groupIds ) # TODO zjl 这一部分任务查询时间任过长,没有索引, 是否考虑设置异步任务触发 recommender = MyUser.get_active_info(openId=customer.openId, agentId=customer.agentId, groupId__in=groupIds).get("recommender") # 推荐人 if recommender: groupList = Group.get_groups_of_dealer(user.id) recommender = MyUser.objects.get(phoneNumber=recommender) if recommender.groupId not in groupList: # 添加对于当前的recommender的验证 要是同一个经销商下的 logger.info("uninvalid recommender dealer=%s, recommender=%s" % (user.nickname, recommender.nickname)) else: coins = 10 # TODO zjl 添加推荐人金币 金币设置值 update = recommender.incr_balance(VirtualCoin(coins)) if not update: logger.info("recommender %s get coins faild." % recommender.nickname) else: # 添加一条充值记录 orderNo = str(uuid.uuid1()) try: newRcd = RechargeRecord(orderNo=orderNo, coins=coins, money=0.00, openId=recommender.openId, wxOrderNo=u'活动赠币', nickname=recommender.nickname, result='success', via='sendcoin', operator=str(user.id)) newRcd.save() except Exception as e: logger.exception('update record for feedback coins error=%s,orderNo=%s' % (e, orderNo)) return JsonOkResponse(u"会员录入成功,可以正常使用换电柜") elif int(status) == 3: # 3表示用户信息激活状态为失败 MyUser.set_active_info( {"isMember": False, "status": status, "remarks": remarks, "auditTime": datetime.datetime.strftime(datetime.datetime.now(), "%Y-%m-%d %H:%M:%S")}, openId=customer.openId, agentId=customer.agentId, groupId__in=groupIds ) return JsonOkResponse(u"已拒绝该用户") else: logger.error("uninvalid status : %s" % status) return JsonErrorResponse(u"无效的审核状态") @permission_required(ROLE.dealer) def delUserActiveInfo(request): user = request.user payload = json.loads(request.body) ids = payload.get("ids", "") # 删除该经销商下的该用户的激活信息 customers = MyUser.objects.filter(id__in=ids) groupIds = Group.get_group_ids_of_dealer(str(user.id)) for customer in customers: MyUser.del_active_info( openId=customer.openId, agentId=customer.agentId, groupId__in=groupIds ) return JsonOkResponse() @permission_required(ROLE.dealer) def getUserIdentifyList(request): """ 获取临时用户 待激活用户 """ pageIndex = int(request.GET.get("pageIndex", 1)) pageSize = int(request.GET.get("pageSize", 10)) searchKey = request.GET.get("searchKey") status = request.GET.get("status") if status in ("", "null"): statusList = [0, 1, 2, 3] else: statusList = [int(status)] groupList = Group.get_group_ids_of_dealer(request.user.id) query = { "groupId": {"$in": groupList}, "extra.active.status": {"$in": statusList} } if searchKey: query.update(search_query(['nickname', 'phoneNumber'], searchKey).to_query(MyUser)) results = MyUser.get_collection().find( query, { "nickname": 1, "openId": 1, "phoneNumber": 1, "avatar": 1, "extra.active": 1 } ).skip( (pageIndex - 1) * pageSize ).limit( pageSize ) tempUsers = [] for user in results: userDict = dict() userDict["id"] = str(user["_id"]) # userDict["phoneNumber"] = user["phoneNumber"] userDict["userNickname"] = user.get("nickname", "") userDict["avatarUrl"] = user.get("avatar", "") userDict.update( user["extra"]["active"] ) tempUsers.append(userDict) data = { "page": pageIndex, # "total": 2 * pageSize if len(tempUsers) >= pageSize else pageSize, "total": 10000, "pageSize": pageSize, "offset": 0, "dataList": tempUsers } return JsonResponse({'result': 1, 'description': "", 'payload': data}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'鉴权失败,请重新登录')) @permission_required(ROLE.dealer, ROLE.subaccount) def info(request): user = request.user payload = { 'roles':['admin'], 'introduction':user.description, 'avatar':user.wechatAuthUserInfo.get('avatar'), 'name':user.phone } return JsonResponse({'result': 1, 'description': '', 'payload':payload}) def getDashboard(request): dealerId = str(request.user.id) groupIds = Group.get_group_ids_of_dealer(dealerId) devList = Device.get_devices_by_group(groupIds).values() devCount = len(devList) todayTime = datetime.datetime.now() yesterdayTime = todayTime - datetime.timedelta(days=1) today = todayTime.strftime(Const.DATE_FMT) yesterDay = yesterdayTime.strftime(Const.DATE_FMT) rcds = DealerDailyStat.get_collection().find({'dealerId':ObjectId(dealerId), 'date':today}, {'daily':1, 'activedDevRatio':1}) if rcds.count() == 0: todayIncome = 0 todayRechargeIncome = 0 todayChargeCardIncome = 0 todayOrder = 0 else: info = rcds[0] todayIncome = info.get('daily', {}).get('totalIncome', 0) income = info.get('daily', {}).get('income', {}) todayRechargeIncome = income.get('recharge', 0) todayChargeCardIncome = RMB(income.get('chargeCard', 0)) + RMB(income.get('chargeVirtualCard', 0)) todayOrder = info.get('daily', {}).get('totalIncomeCount', 0) rcds = DealerDailyStat.get_collection().find({'dealerId':ObjectId(dealerId), 'date':yesterDay}, {'daily':1, 'activedDevRatio':1}) if rcds.count() == 0: yesterdayIncome = 0 yesterdayOrder = 0 yesterdayActiveDevicePercent = 0 yesterdayActiveDevice = 0 yesterdayRechargeIncome = 0 yesterdayChargeCardIncome = 0 else: info = rcds[0] yesterdayIncome = info.get('daily', {}).get('totalIncome', 0) income = info.get('daily', {}).get('income', {}) yesterdayRechargeIncome = income.get('recharge', 0) yesterdayChargeCardIncome = RMB(income.get('chargeCard', 0)) + RMB(income.get('chargeVirtualCard', 0)) yesterdayOrder = info.get('daily', {}).get('totalIncomeCount', 0) yesterdayActiveDevicePercent = info.get('activedDevRatio', 0) yesterdayActiveDevice = int(round(yesterdayActiveDevicePercent / 100.0 * devCount, 2)) date = MONTH_DATE_KEY.format(year=todayTime.year, month=todayTime.month) rcds = DealerMonthlyStat.get_collection().find({'dealerId':ObjectId(dealerId), 'date':date}, {'monthly':1, 'activedDevRatio':1, 'addedUserCount':1}) if rcds.count() == 0: monthIncome = 0 monthRechargeIncome = 0 monthChargeCardIncome = 0 thisMonthOrder = 0 userCountAddedThisMonth = 0 else: info = rcds[0] monthIncome = info.get('monthly', {}).get('totalIncome', 0) income = info.get('monthly', {}).get('income', {}) monthRechargeIncome = income.get('recharge', 0) monthChargeCardIncome = RMB(income.get('chargeCard', 0)) + RMB(income.get('chargeVirtualCard', 0)) thisMonthOrder = info.get('monthly', {}).get('totalIncomeCount', 0) userCountAddedThisMonth = info.get('addedUserCount', 0) userCount = request.user.userCount return JsonOkResponse( payload={ "todayIncome":todayIncome, 'todayRechargeIncome':todayRechargeIncome, 'todayChargeCardIncome':todayChargeCardIncome, "yesterdayIncome":yesterdayIncome, 'yesterdayRechargeIncome':yesterdayRechargeIncome, 'yesterdayChargeCardIncome':yesterdayChargeCardIncome, "thisMonthIncome": monthIncome, 'thisMonthRechargeIncome':monthRechargeIncome, 'thisMonthChargeCardIncome':monthChargeCardIncome, "todayOrder": todayOrder, "yesterdayOrder":yesterdayOrder, "thisMonthOrder":thisMonthOrder, "deviceTotal":len(devList), "yesterdayActiveDevice":yesterdayActiveDevice, "yesterdayActiveDevicePercent":yesterdayActiveDevicePercent, 'userCount':userCount, 'userCountAddedThisMonth':userCountAddedThisMonth } ) def deviceOfflineTrend(request): dealerId = str(request.user.id) todayTime = datetime.datetime.now() startTime = todayTime - datetime.timedelta(days=7) startDay = startTime.strftime(Const.DATE_FMT) endDay = todayTime.strftime(Const.DATE_FMT) rcds = DealerDailyStat.get_collection().find({'dealerId':ObjectId(dealerId), 'date':{'$gte':startDay, '$lte':endDay}}, {'other':1, 'date':1}) dataList = [] for rcd in rcds: other = rcd.get('other', {'totalOfflineTime':0, 'totalOfflineBusyTime':0, 'totalOnlineTime':0}) totalTime = other['totalOfflineTime'] + other['totalOfflineBusyTime'] + other['totalOnlineTime'] dataList.append({ 'dateStr':rcd['date'], 'offlineTimePercent':round(100 * other['totalOfflineTime'] / totalTime, 2) if totalTime else 0 }) return JsonOkResponse(payload={'dataList': dataList}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def deviceActiveTrend(request): dealerId = str(request.user.id) todayTime = datetime.datetime.now() startTime = todayTime - datetime.timedelta(days=7) startDay = startTime.strftime(Const.DATE_FMT) endDay = todayTime.strftime(Const.DATE_FMT) rcds = DealerDailyStat.get_collection().find({'dealerId':ObjectId(dealerId), 'date':{'$gte':startDay, '$lte':endDay}}, {'activedDevRatio':1, 'date':1}) dataList = [] for rcd in rcds: ratio = rcd.get('activedDevRatio', 0) dataList.append({ 'dateStr':rcd['date'], 'activeDevicePercent':ratio }) return JsonOkResponse(payload={'dataList': dataList}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def getGroupStatistics(request): def calc_group_stats(groupId, startDate, endDate): groupResult = GroupReport.get_rpt([groupId], startDate, endDate) offlineCoin = groupResult[groupId].get('lineCoins', 0) rcds = GroupDailyStatsModelProxy.get_data_list(startTime=startDate, endTime=endDate, groupId=ObjectId(groupId), only={ 'other': 1, 'incomeTotal': 1, 'daily': 1, 'activedDevRatio': 1 }) orderTotal, payIncome, offlineTime, totalTime, totalActivedRate, peakValue = 0, RMB(0.0), 0, 0, 0, 0 count = 0 for rcd in rcds: count += 1 daily = rcd.get('daily') or {} other = rcd.get('other') or {} orderTotal += daily.get('totalIncomeCount', 0) payIncome += daily.get('totalIncome', 0) offlineTime += other.get('totalOfflineTime', 0) totalTime = totalTime + other.get('totalOfflineTime', 0) + other.get('totalOnlineTime', 0) + other.get( 'totalOfflineBusyTime', 0) totalActivedRate += rcd.get('activedDevRatio', 0) dayPeakValue = rcd.get('peakUsage', 0) if peakValue <= dayPeakValue: peakValue = dayPeakValue return { 'orderTotal': orderTotal, 'payIncome': payIncome, 'offlineCoin': offlineCoin, 'deviceOfflineCount': int(round(offlineTime / totalTime * 100.0, 2)) if totalTime > 0 else 0, # 前台修改后,用设备离线时间占比offlineTime/totalTime * 100 'dailyActivityRate': int(round(totalActivedRate / count, 2)) if count > 0 else 0, 'peakValue': peakValue } ownerId = str(request.user.id) startDate = str(request.GET.get('startTime')) endDate = str(request.GET.get('endTime')) pageIndex = int(request.GET.get('pageIndex')) pageSize = int(request.GET.get('pageSize')) groupIds = Group.get_group_ids_of_dealer(ownerId) total = len(groupIds) pageGroupIds = groupIds[(pageIndex - 1) * pageSize:pageIndex * pageSize] dataList = [] count = 0 for groupId in pageGroupIds: count += 1 group = Group.get_group(groupId) devList = Device.get_devices_by_group([groupId]).values() devCount = len(devList) valueDict = calc_group_stats(groupId, startDate, endDate) dataList.append({ 'id':str(groupId), 'groupName':group['groupName'], 'address':group['address'], 'deviceTotal':devCount, 'orderTotal':valueDict.get('orderTotal', 0), 'payIncome':valueDict.get('payIncome', RMB(0.0)), 'offlineCoin':valueDict.get('offlineCoin', 0), 'deviceOfflineCount':valueDict.get('deviceOfflineCount', 0), 'dailyActivityRate':valueDict.get('dailyActivityRate', 0), 'peakValue':valueDict.get('peakValue', 0) }) return JsonOkResponse(payload={'total':total, 'dataList': dataList}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def getOrderTrendByGroup(request): groupId = request.GET.get('id') todayTime = datetime.datetime.now() startDate = request.GET.get('startTime', '') if not startDate: startTime = todayTime - datetime.timedelta(days=7) startDate = startTime.strftime(Const.DATE_FMT) endDate = request.GET.get('endTime', '') if not endDate: endDate = (todayTime + datetime.timedelta(days=1)).strftime(Const.DATE_FMT) group_report_dict = GroupReport.get_rpt([groupId], startDate, endDate) rcds = GroupDailyStatsModelProxy.get_data_list(startTime=startDate, endTime=endDate, groupId=ObjectId(groupId), only={ 'daily': 1, 'date': 1 }) dataList = [] for rcd in rcds: # type: GroupDailyStat daily = rcd.daily dataList.append({ 'dateStr': rcd.date, 'payIncome': daily.get('totalIncome', 0), 'orderTotal': daily.get('totalIncomeCount', 0), 'offlineCoin': group_report_dict.get(rcd.date, {'lineCoins': 0, 'count': 0}.get('lineCoins', 0)) }) return JsonOkResponse(payload={'dataList': dataList}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def getOfflineTrendByGroup(request): groupId = request.GET.get('id') startDate = request.GET.get('startTime', '') endDate = request.GET.get('endTime', '') if not startDate: todayTime = datetime.datetime.now() startTime = todayTime - datetime.timedelta(days=7) startDate = startTime.strftime(Const.DATE_FMT) endDate = todayTime.strftime(Const.DATE_FMT) rcds = GroupDailyStat.get_collection().find({'groupId':ObjectId(groupId), 'date':{'$gte':startDate, '$lte':endDate}}, {'other':1, 'date':1}) dataList = [] for rcd in rcds: other = rcd.get('other', {}) offlineTime = other.get('totalOfflineTime', 0) totalTime = other.get('totalOfflineTime', 0) + other.get('totalOnlineTime', 0) + other.get('totalOfflineBusyTime', 0) dataList.append({ 'dateStr':rcd['date'], 'offlineCount':int(round(offlineTime / totalTime * 100.0, 2)) if totalTime else 0 }) return JsonOkResponse(payload={'dataList':dataList}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def dailyActivityTrendByGroup(request): groupId = request.GET.get('id') startDate = request.GET.get('startTime', '') endDate = request.GET.get('endTime', '') if not startDate: todayTime = datetime.datetime.now() startTime = todayTime - datetime.timedelta(days=7) startDate = startTime.strftime(Const.DATE_FMT) endDate = todayTime.strftime(Const.DATE_FMT) rcds = GroupDailyStat.get_collection().find({'groupId':ObjectId(groupId), 'date':{'$gte':startDate, '$lte':endDate}}, {'activedDevRatio':1, 'devCount':1, 'date':1}) dataList = [] for rcd in rcds: deviceTotal = rcd.get('devCount', 0) dataList.append({ 'dateStr':rcd['date'], 'dailyActivity':int(float(rcd.get('activedDevRatio', 0)) / 100.0 * deviceTotal), 'deviceTotal':deviceTotal }) return JsonOkResponse(payload={'dataList':dataList}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def getPeakValueTrendByGroup(request): groupId = request.GET.get('id') startDate = request.GET.get('startTime', '') endDate = request.GET.get('endTime', '') if not startDate: todayTime = datetime.datetime.now() startTime = todayTime - datetime.timedelta(days=7) startDate = startTime.strftime(Const.DATE_FMT) endDate = todayTime.strftime(Const.DATE_FMT) rcds = GroupDailyStat.get_collection().find({'groupId':ObjectId(groupId), 'date':{'$gte':startDate, '$lte':endDate}}, {'other':1, 'date':1}) dataList = [] hourlyDict = {} for rcd in rcds: hourly = rcd.get('other', {}).get('hourly', {}) for hour, value in hourly.items(): if not hourlyDict.has_key(hour): hourlyDict[hour] = {'usageSum':0, 'usageCount':0} else: hourlyDict[hour]['usageSum'] += value['usageSum'] hourlyDict[hour]['usageCount'] += value['usageCount'] for ii in range(24): hour = str(ii) if hourlyDict.has_key(hour): hourValue = hourlyDict[hour] dataList.append( {'hour':hour, 'usage':int(round(float(hourValue['usageSum']) / float(hourValue['usageCount']), 2)) if hourValue['usageCount'] > 0 else 0 } ) else: dataList.append({'hour':hour, 'usage':0}) return JsonOkResponse(payload={'dataList':dataList}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def getDeviceStatistics(request): ownerId = str(request.user.id) logicalCode = request.GET.get('searchKey', '') startDate = request.GET.get('startTime', '') endDate = request.GET.get('endTime', '') pageIndex = int(request.GET.get('pageIndex')) pageSize = int(request.GET.get('pageSize')) if not startDate: todayTime = datetime.datetime.now() startTime = todayTime - datetime.timedelta(days=7) startDate = startTime.strftime(Const.DATE_FMT) endDate = todayTime.strftime(Const.DATE_FMT) # 找出相关所有设备 if logicalCode: dev_no = Device.get_devNo_by_logicalCode(logicalCode) if dev_no: devNoList = [dev_no] else: devNoList = [] else: groupIds = Group.get_group_ids_of_dealer(ownerId) tempList = Device.get_devNos_by_group(groupIds) total = len(tempList) devNoList = tempList[(pageIndex - 1) * pageSize:pageIndex * pageSize] if not devNoList: return JsonOkResponse(payload={'total': 0, 'dataList': []}) total = len(devNoList) dataList = [] devList = Device.get_dev_by_nos(devNoList, True) for dev in devList.values(): lc = dev['logicalCode'] devType = dev.get('devType', {}).get('name', '') groupName = dev.get('groupInfo', {}).get('groupName', '') remarks = dev.get('remarks', '') orderTotal, payIncome, deviceOfflineCount, deviceOfflineTimeTotal, peakValue = 0, RMB(0.0), 0, 0, 0 rcds = DeviceDailyStatsModelProxy.get_data_list( startTime=startDate, endTime=endDate, logicalCode=lc, only={'date': 1, 'other': 1, 'daily': 1, 'peakUsage': 1}) for rcd in rcds: daily = rcd.get('daily') or {} orderTotal += daily.get('totalIncomeCount', 0) payIncome += RMB(daily.get('totalIncome', 0)) other = rcd.get('other') or {} deviceOfflineCount += other.get('offlineCount', 0) deviceOfflineTimeTotal += other.get('totalOfflineTime', 0) if peakValue <= rcd.get('peakUsage', 0): peakValue = rcd.get('peakUsage', 0) faultCount = FeedBack.get_collection().find( {'logicalCode': lc, 'createTime': {'$gte': startDate, '$lte': endDate}}).count() solveFaultCount = FeedBack.get_collection().find( {'logicalCode': lc, 'createTime': {'$gte': startDate, '$lte': endDate}, 'status': 1}).count() dataList.append({ 'devType': devType, 'orderTotal': orderTotal, 'payIncome': payIncome, 'remarks': remarks, 'deviceOfflineCount': deviceOfflineCount, 'deviceOfflineTimeTotal': deviceOfflineTimeTotal / 60, 'faultCount': faultCount, 'solveFaultCount': solveFaultCount, 'peakValue': peakValue, 'groupName': groupName, 'logicalCode': lc }) return JsonOkResponse(payload={'total': total, 'dataList': dataList}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def getDeviceList(request): ownerId = str(request.user.id) pageIndex = int(request.GET.get('pageIndex')) pageSize = int(request.GET.get('pageSize')) groupIds = Group.get_group_ids_of_dealer(ownerId) allDevNoList = Device.get_devNos_by_group(groupIds) devNoList = allDevNoList[(pageIndex - 1) * pageSize:pageIndex * pageSize] total = len(allDevNoList) dataList = [] devList = Device.get_dev_by_nos(devNoList, verbose=True) for dev in devList.values(): # type: DeviceDict if dev.logicalCode == 'G419646': monitorUrl = 'http://vod1.ddhlok.com/zzdd/shanghai4.m3u8' elif dev.logicalCode == 'G430439': monitorUrl = 'http://vod1.ddhlok.com/zzdd/shanghai5.m3u8' elif dev.logicalCode == 'G430498': monitorUrl = 'http://vod1.ddhlok.com/zzdd/shanghai1.m3u8' else: monitorUrl = None devType = dev.devType.get('name', '') dataList.append({ 'devType' : devType, 'online': dev.online, 'signal':dev.signal, 'remarks':dev.get('remarks', ''), 'registrationTime':dev.get('dateTimeAdded', ''), 'simExpireDate':dev.fixedSimExpireDate, 'groupName':dev.get('groupInfo', {}).get('groupName', ''), 'imei':dev.devNo, 'iccid':dev.get('iccid', ''), 'logicalCode':dev.logicalCode, 'monitorUrl':monitorUrl }) return JsonOkResponse(payload={'total':total, 'dataList':dataList}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def getDevMapChart(request): ownerId = str(request.user.id) # 查找出所有已注册的设备 devList = list(Device.get_collection().find( {'ownerId':str(ownerId)}, {'devNo': 1, 'districtId': 1, '_id': 0, 'logicalCode': 1, 'cycle': 1} )) districts = dict(Counter([District.get_district(_['districtId']).split(' ')[0] for _ in devList if _.has_key('districtId') and District.get_district(_['districtId']) != ''])) def get_province(pvc): if pvc == u'内蒙古自治区': pvc = u'内蒙古' elif pvc == u'黑龙江省': pvc = u'黑龙江' else: pvc = pvc[0:2] return pvc dataList = [{'name': get_province(province), 'value': count} for province, count in districts.items()] busy = 0 online = 0 offline = 0 deviceDict = { _['devNo']: {'logicalCode': _['logicalCode'], 'cycle': _.get('cycle', Const.DEV_CYCLE_DEFAULT)} for _ in devList} for item in Device.get_many_device_status_cache(deviceDict).values(): device = DeviceDict(item) # type: DeviceDict if device.status == 1: busy += 1 if device.online == 1: online += 1 elif device.online == 0: offline += 1 return JsonResponse({'result': 1, 'description': u"", 'payload': { "busy": busy, "online": online, "offline": offline, "unregistered":0, "dataList": dataList }}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def getDeviceTrend(request): ownerId = str(request.user.id) startDate = request.GET.get('startTime', '') endDate = request.GET.get('endTime', '') if not startDate: todayTime = datetime.datetime.now() startTime = todayTime - datetime.timedelta(days=7) startDate = startTime.strftime(Const.DATE_FMT) endDate = todayTime.strftime(Const.DATE_FMT) dataList = [] records = DealerDailyStatsModelProxy.get_data_list(startTime=startDate, endTime=endDate, dealerId=ObjectId(ownerId), only={'date': 1, 'devCount': 1, 'activedDevRatio': 1}) for record in records: devCount = record.get('devCount', 0) activedRatio = record.get('activedDevRatio', 0) dataList.append({ 'dateStr': record['date'], 'deviceTotal': devCount, 'active': int(round(devCount * activedRatio / 100.0, 2)) }) return JsonOkResponse(payload={'dataList': dataList}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def getAllFeedbackStatistics(request): feedBacks = list(FeedBack.get_collection().find( {'ownerId': request.user.id}, {'_id': 0, 'feedType': 1, 'status': 1} )) fault = [_['status'] for _ in feedBacks if _['feedType'] == 'fault'] faultProcessed = [_ for _ in fault if _ == 1] upper = [_['status'] for _ in feedBacks if _['feedType'] == 'upper'] upperProcessed = [_ for _ in upper if _ == 1] refund = [_['status'] for _ in feedBacks if _['feedType'] == 'refund'] refundProcessed = [_ for _ in refund if _ == 1] return JsonResponse({'result': 1, 'description': None, 'payload': { "faultCount": len(fault), "faultProcessedCount": len(faultProcessed), "upperCount": len(upper), "upperProcessedCount": len(upperProcessed), "refundCount": len(refund), "refundProcessedCount": len(refundProcessed) }}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def getDeviceNetworkTrend(request): ownerId = str(request.user.id) startDate = request.GET.get('startTime', '') endDate = request.GET.get('endTime', '') if not startDate: todayTime = datetime.datetime.now() startTime = todayTime - datetime.timedelta(days=7) startDate = startTime.strftime(Const.DATE_FMT) endDate = todayTime.strftime(Const.DATE_FMT) dataList = [] records = DealerDailyStatsModelProxy.get_data_list(startTime=startDate, endTime=endDate, dealerId=ObjectId(ownerId), only={'date': 1, 'other': 1}) for rcd in records: other = rcd.get('other') or {} dataList.append({ 'dateStr': rcd['date'], 'online': other.get('totalOnlineTime', 0) + other.get('totalOfflineBusyTime', 0), 'offline': other.get('totalOfflineTime', 0) }) return JsonOkResponse(payload={'dataList': dataList}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def getPackageUsageFrequency(request): ownerId = str(request.user.id) startDate = request.GET.get('startTime', '') endDate = request.GET.get('endTime', '') if not startDate: todayTime = datetime.datetime.now() startTime = todayTime - datetime.timedelta(days=7) startDate = startTime.strftime(Const.DATE_FMT) endDate = todayTime.strftime(Const.DATE_FMT) packageDict = {} totalCount = 0 records = DealerDailyStatsModelProxy.get_data_list(startTime=startDate, endTime=endDate, dealerId=ObjectId(ownerId), only={'date': 1, 'other': 1}) for rcd in records: package = (rcd.get('other') or {}).get('package', {}) for coin, count in package.items(): try: totalCount += count if not packageDict.has_key(str(coin)): packageDict[str(coin)] = count else: packageDict[str(coin)] += count except Exception, e: continue dataList = [] for coin, count in packageDict.items(): dataList.append({ 'name': u'%s元' % round(float(coin) / 100.0, 2), 'percent': round(float(count) / float(totalCount) * 100.0, 1) if totalCount > 0 else 100 } ) return JsonOkResponse(payload={'dataList': dataList}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def getIncomeTrend(request): ownerId = str(request.user.id) startDate = request.GET.get('startTime', '') endDate = request.GET.get('endTime', '') if not startDate: todayTime = datetime.datetime.now() startTime = todayTime - datetime.timedelta(days=7) startDate = startTime.strftime(Const.DATE_FMT) endDate = todayTime.strftime(Const.DATE_FMT) offlineCoinsDict = {r['date']: r.get('lineCoins', 0) for r in DealerReport.get_rpts(ownerId, startDate, endDate)} dataList = [] records = DealerDailyStatsModelProxy.get_data_list(startTime=startDate, endTime=endDate, dealerId=ObjectId(ownerId), only={'date': 1, 'daily': 1}) for rcd in records: daily = rcd.get('daily') or {} date = rcd['date'] dataList.append({ 'dateStr': date, 'offlineCoin': offlineCoinsDict.get(date, 0), 'payIncome': daily.get('totalIncome', 0) }) return JsonOkResponse(payload={'dataList': dataList}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u"获取收益趋势失败")) @permission_required(ROLE.dealer) def getConsumptionTrend(request): ownerId = str(request.user.id) startDate = request.GET.get('startTime', '') endDate = request.GET.get('endTime', '') if not startDate: todayTime = datetime.datetime.now() startTime = todayTime - datetime.timedelta(days=7) startDate = startTime.strftime(Const.DATE_FMT) endDate = todayTime.strftime(Const.DATE_FMT) dataList = [] records = DealerDailyStatsModelProxy.get_data_list(startTime=startDate, endTime=endDate, dealerId=ObjectId(ownerId), only={'date': 1, 'daily': 1}) for rcd in records: consumptionDict = (rcd.get('daily') or {}).get('consumption', {}) date = rcd['date'] itemList = [] for kind, value in consumptionDict.items(): if kind not in DEALER_CONSUMPTION_AGG_KIND.choices(): continue itemList.append({ 'name': DEALER_CONSUMPTION_AGG_KIND_TRANSLATION[kind], 'value': value, 'unit': DEALER_CONSUMPTION_AGG_KIND_UNIT[kind], }) dataList.append({ 'dateStr': date, 'items': itemList, }) return JsonOkResponse(payload={'dataList': dataList}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def getOrderTrend(request): ownerId = str(request.user.id) startDate = request.GET.get('startTime', '') endDate = request.GET.get('endTime', '') if not startDate: todayTime = datetime.datetime.now() startTime = todayTime - datetime.timedelta(days=7) startDate = startTime.strftime(Const.DATE_FMT) endDate = todayTime.strftime(Const.DATE_FMT) hourlyDict = {} records = DealerDailyStatsModelProxy.get_data_list(startTime=startDate, endTime=endDate, dealerId=ObjectId(ownerId), only={'date': 1, 'hourly': 1}) for rcd in records: hourly = rcd.get('hourly') or {} for hour, value in hourly.items(): if not hourlyDict.has_key(hour): hourlyDict[hour] = VirtualCoin(value.get('consumption', {}).get('coin', 0)) else: hourlyDict[hour] += VirtualCoin(value.get('consumption', {}).get('coin', 0)) dataList = [] for ii in range(24): hour = str(ii) order = 0 if hourlyDict.has_key(hour): order = hourlyDict.get(hour) dataList.append({ 'dateStr':u'%s时' % hour, 'order':str(order) }) return JsonOkResponse(payload={'dataList':dataList}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u"获取收益列表失败")) @permission_required(ROLE.dealer) def getIncomeOrderList(request): ownerId = str(request.user.id) startTime = request.GET.get("startTime") endTime = request.GET.get("endTime") pageIndex = int(request.GET.get("pageIndex")) pageSize = int(request.GET.get("pageSize")) groupId = request.GET.get("groupId") logicalCode = request.GET.get("logicalCode") phoneNumber = request.GET.get("phoneNumber") filters = { "ownerId": ownerId, "via__nin": [RechargeRecordVia.SendCoin, RechargeRecordVia.Refund] } if groupId: filters.update({"groupId": groupId}) if logicalCode: filters.update({"logicalCode": logicalCode}) # 如果存在phoneNumber,则是单一查找人 if phoneNumber: phoneOwner = MyUser.objects.filter(phoneNumber=phoneNumber).first() if phoneOwner: filters.update({"openId": phoneOwner.openId}) records = RechargeRecord.objects.filter( dateTimeAdded__gte=to_datetime(startTime, "%Y-%m-%d"), dateTimeAdded__lt=to_datetime(endTime, "%Y-%m-%d"), **filters ) # type: CustomQuerySet total = records.count() # 这个地方的数据一定是按照年进行分型的 dataList = list() for rcd in records.paginate(pageIndex, pageSize): try: user = MyUser.objects.filter(openId=rcd.openId).only("openId", "gateWay", "productAgentId", "sex", "nickname").first() if user.sex == 0: sex = u"女" elif user.sex == 1: sex = u"男" else: sex = "" userNickname = "{}-{}".format(user.nickname, user.phone) if user.phone else user.nickname data = { "id": str(rcd.id), "orderAmount": str(rcd.amount), "tradeType": RECHARGE_RECORD_VIA_TRANSLATION.get(rcd.via, "-"), "gateway": rcd.gateway, "status": rcd.result, "userNickname": userNickname, "userGender": sex, "groupName": rcd.groupName, "logicalCode": rcd.logicalCode, "devTypeName": rcd.dev_type_name, "createdTime": rcd.dateTimeAdded, "gatewayTradeNo": rcd.wxOrderNo, 'outTradeNo': rcd.orderNo } except Exception as e: logger.exception("record no is {}, error is".format(rcd.orderNo, e)) continue else: dataList.append(data) return JsonOkResponse(payload={"total": total, "dataList": dataList}) @permission_required(ROLE.dealer, ROLE.subaccount) def getConsumptionOrderList(request): """ 经销商PC端 对于 消费订单列表的获取 :param request: :return: """ ownerId = str(request.user.id) startDate = request.GET.get('startTime') endDate = request.GET.get('endTime') pageIndex = int(request.GET.get('pageIndex', 1)) pageSize = int(request.GET.get('pageSize', 10)) groupId = str(request.GET.get('groupId')) logicalCode = request.GET.get('logicalCode') phoneNumber = request.GET.get("phoneNumber") _type = request.GET.get("consumeType") # /netPay/cardPay/ 启动方式应该是只有 扫码启动 以及刷卡启动 dataList = [] filters = { "ownerId": ownerId, "isNormal": True } if _type == "cardPay": filters.update({"remarks": u"刷卡消费"}) elif _type == "netPay": filters.update({"remarks__ne": u"刷卡消费"}) else: pass if groupId: filters.update({"groupId": groupId}) if logicalCode: filters.update({"logicalCode": logicalCode}) if phoneNumber: phoneOwner = MyUser.objects.filter(phoneNumber=phoneNumber).first() if phoneOwner: filters.update({"openId": phoneOwner.openId}) records = ClientConsumeModelProxy.get_data_list(startTime=startDate, endTime=endDate, **filters) # type: CustomQuerySet count = records.count() for rcd in records.paginate(pageIndex, pageSize): # type: ConsumeRecord try: user = MyUser.objects.filter(openId=rcd.openId).only('openId', 'nickname', 'sex', 'groupId', "productAgentId", "gateWay").first() sex = '' if user.sex == 0: sex = u'女' elif user.sex == 1: sex = u'男' else: pass desc = '' for key, value in rcd.servicedInfo.items(): if key not in DEALER_CONSUMPTION_AGG_KIND_TRANSLATION: continue desc += " %s:%s%s" % (DEALER_CONSUMPTION_AGG_KIND_TRANSLATION.get(key), value, DEALER_CONSUMPTION_AGG_KIND_UNIT.get(key)) port = rcd.attachParas.get("chargeIndex", None) lc = rcd.logicalCode lcp = "{logicalCode}-{port}".format(logicalCode=lc, port=port) if port else lc userNickname = "{}-{}".format(user.nickname, user.phone) if user.phone else user.nickname # 添加订单判断启动方式 isQuickPay = u'金币启动' if rcd.recharge_record_id: obj = RechargeRecord.objects.filter(id = str(rcd.recharge_record_id)).first() or RechargeRecord( isQuickPay = False) isQuickPay = u'快捷支付' if obj.isQuickPay else isQuickPay data = { 'id': str(rcd.id), 'createdTime': rcd.created_date, 'title': desc, 'userNickname': userNickname, 'userGender': sex, 'groupName': rcd.groupName, 'logicalCode': lcp, 'devTypeName': rcd.dev_type_name, 'amount': rcd.coin, 'payType': isQuickPay } dataList.append(data) except Exception as e: continue return JsonOkResponse(payload={"dataList": dataList, "total": count}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def getAPIOrderList(request): ownerId = str(request.user.id) startDate = request.GET.get('startTime', '') endDate = request.GET.get('endTime', '') + ' 23:59:59' pageIndex = int(request.GET.get('pageIndex')) pageSize = int(request.GET.get('pageSize')) groupId = str(request.GET.get('groupId')) logicalCode = request.GET.get('logicalCode') if logicalCode: devNoList = [Device.get_devNo_by_logicalCode(logicalCode)] elif groupId: devNoList = Device.get_devNos_by_group([groupId]) else: devNoList = None if devNoList: rcds = APIStartDeviceRecord.objects(ownerId=ownerId, devNo__in=devNoList, errCode=0, datetimeAdded__gte=startDate, datetimeAdded__lte=endDate).order_by('-datetimeAdded') else: rcds = APIStartDeviceRecord.objects(ownerId=ownerId, errCode=0, datetimeAdded__gte=startDate, datetimeAdded__lte=endDate).order_by('-datetimeAdded') dataList = [{ 'createdTime': _.datetimeAdded, 'extOrderNo': _.attachParas.get('extOrderNo', '-'), 'userId': _['userId'], 'needTime': _.package.get('time', '-'), 'backCoins': _.servicedInfo.get('backCoins', '-'), 'spendElec': _.servicedInfo.get('spendElec', '-'), 'amount': _.package.get('price', '-'), 'groupName': Group.get_groupName_by_logicalCode(_.deviceCode), 'devTypeName': _.servicedInfo.get('spendElec', '-'), 'logicalCode': _.deviceCode } for _ in rcds.skip((pageIndex - 1) * pageSize).limit(pageSize)] return JsonOkResponse(payload={'dataList': dataList, 'total': rcds.count()}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def getOnPointsOrderList(request): ownerId = str(request.user.id) startDate = request.GET.get('startTime', '') endDate = request.GET.get('endTime', '') + ' 23:59:59' pageIndex = int(request.GET.get('pageIndex')) pageSize = int(request.GET.get('pageSize')) groupId = str(request.GET.get('groupId')) logicalCode = request.GET.get('logicalCode') filters = { "ownerId": ownerId, "time__gte": startDate, "time__lte": endDate } if logicalCode: # devNoList = [Device.get_devNo_by_logicalCode(logicalCode)] filters.update({"devNo": Device.get_devNo_by_logicalCode(logicalCode)}) elif groupId: devNoList = Device.get_devNos_by_group([groupId]) filters.update({"devNo__in": devNoList}) else: devNoList = None rcds = UpscoreRecord.objects(**filters).order_by('-time') dataList = [{ 'createdTime': _.time, 'groupName': _.groupName, 'onPoints': str(_.score), 'logicalCode': _.logicalCode } for _ in rcds.skip((pageIndex - 1) * pageSize).limit(pageSize)] return JsonOkResponse(payload={'dataList': dataList, 'total': rcds.count()}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def getSendCoinsToCardOrderList(request): ownerId = str(request.user.id) startDate = request.GET.get('startTime', '') + ' 00:00:00' endDate = request.GET.get('endTime', '') + ' 23:59:59' pageIndex = int(request.GET.get('pageIndex')) pageSize = int(request.GET.get('pageSize')) startDateTime = datetime.datetime.strptime(startDate, '%Y-%m-%d %H:%M:%S') endDateTime = datetime.datetime.strptime(endDate, '%Y-%m-%d %H:%M:%S') filters = { "ownerId": ownerId, "dateTimeAdded__gte": startDateTime, "dateTimeAdded__lte": endDateTime } rcds = UpCardScoreRecord.objects(**filters).order_by('-dateTimeAdded') dataList = [] for rcd in rcds.skip((pageIndex - 1) * pageSize).limit(pageSize): if rcd.address != '': groupName = rcd.address else: card = Card.objects.get(cardNo=rcd.cardNo) groupId = card.groupId if groupId: groupName = Group.get_group(groupId).groupName else: groupName = '' dataDict = { 'cardNo':rcd.cardNo, 'score':str(rcd.score), 'groupName':groupName, 'remark': rcd.remark, 'createdTime': rcd.dateTimeAdded.strftime('%Y-%m-%d %H:%M:%S') } dataList.append(dataDict) # dataList = [{ # 'cardNo': _.cardNo, # 'score': str(_.score), # 'remark': _.remark, # 'createdTime': _.dateTimeAdded.strftime('%Y-%m-%d %H:%M:%S') # } for _ in rcds.skip((pageIndex - 1) * pageSize).limit(pageSize)] return JsonOkResponse(payload={'dataList': dataList, 'total': rcds.count()}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer, ROLE.subaccount) def getSignalTrendByDevice(request): strStartTime = request.GET.get('startTime') strEndTime = request.GET.get('endTime') startTime = to_datetime(strStartTime) endTime = to_datetime(strEndTime) logicalCode = request.GET.get('logicalCode') devNo = Device.get_devNo_by_logicalCode(logicalCode) nowTime = datetime.datetime.now() dataList = [] checkTime = nowTime - datetime.timedelta(days=7) tempStartTime = get_zero_time(checkTime) values = SignalManager.instence().get(devNo, tempStartTime, nowTime) if values is not None: for value in values: timePoint = to_datetime(value['time']) if timePoint >= startTime and timePoint <= endTime: dataList.append('%s=%s' % (value['time'], value['signal'])) # 去重下,然后重新按照时间排序 resultList = [] for data in dataList: tempList = data.split('=') resultList.append({ 'dateStr':tempList[0], 'signal':tempList[1] }) return JsonOkResponse(payload={'dataList':resultList}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def getPeakValueTrendByDevice(request): logicalCode = request.GET.get('logicalCode') startDate = request.GET.get('startTime', '') endDate = request.GET.get('endTime', '') if not startDate: todayTime = datetime.datetime.now() startTime = todayTime - datetime.timedelta(days=7) startDate = startTime.strftime(Const.DATE_FMT) endDate = todayTime.strftime(Const.DATE_FMT) rcds = DeviceDailyStat.get_collection().find({'logicalCode':logicalCode, 'date':{'$gte':startDate, '$lte':endDate}}, {'other':1, 'date':1}) dataList = [] hourlyDict = {} for rcd in rcds: hourly = rcd.get('other', {}).get('hourly', {}) for hour, value in hourly.items(): if not hourlyDict.has_key(hour): hourlyDict[hour] = {'usageSum':0, 'usageCount':0} else: hourlyDict[hour]['usageSum'] += value['usageSum'] hourlyDict[hour]['usageCount'] += value['usageCount'] for ii in range(24): hour = str(ii) if hourlyDict.has_key(hour): hourValue = hourlyDict[hour] dataList.append( {'hour':hour, 'usage':int(round(float(hourValue['usageSum']) / float(hourValue['usageCount']), 2)) if hourValue['usageCount'] > 0 else 0 } ) else: dataList.append({'hour':hour, 'usage':0}) return JsonOkResponse(payload={'dataList':dataList}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def getOrderStatistics(request): ownerId = str(request.user.id) startDate = request.GET.get('startTime', '') + ' 00:00:00' endDate = request.GET.get('endTime', '') + ' 23:59:59' groupId = str(request.GET.get('groupId')) logicalCode = request.GET.get('logicalCode') devNoList = [] if logicalCode: devNoList = [Device.get_devNo_by_logicalCode(logicalCode)] elif groupId: devNoList = Device.get_devNos_by_group([groupId]) else: groupIds = Group.get_group_ids_of_dealer(ownerId) devNoList = Device.get_devNos_by_group(groupIds) rcds = RechargeRecord.objects(ownerId=ownerId, devNo__in=devNoList, result='success', dateTimeAdded__gte=to_datetime(startDate), dateTimeAdded__lte=to_datetime(endDate)) sexDict, orderTypeDict = {'0':0, '1':0, '2':0}, {'recharge':0, 'chargeCard':0, 'chargeVirtualCard':0} hourDict = {} for hour in range(24): hourDict[str(hour)] = 0 openIdList = [] orderTotal, orderPayAmount, userCount = 0, RMB(0.0), 0 for rcd in rcds: openIdList.append((rcd.openId, rcd.groupId)) if rcd.via in orderTypeDict: orderTypeDict[rcd.via] += 1 hourDict[str(rcd.dateTimeAdded.hour)] += 1 orderTotal += 1 orderPayAmount += rcd.money orderTrend = [{'dateStr':u'%s时' % k, 'order':v } for k, v in hourDict.items()] openIdSetList = list(set(openIdList)) userCount = 0 for userID in openIdSetList: try: user = MyUser.objects.filter(openId=userID[0] , groupId=userID[1]).only('openId', 'nickname', 'sex', 'groupId').first() sexDict[str(user.sex)] += 1 userCount += 1 except Exception, e: continue payload = { 'orderTotal' : orderTotal, 'orderPayAmount':orderPayAmount, 'userCount':userCount, 'userStatistics':{ 'other':sexDict['2'], 'femaleCount':sexDict['0'], 'maleCount':sexDict['1'], }, 'orderTypeStatistics':orderTypeDict, 'orderTrend':orderTrend } return JsonOkResponse(payload=payload) @permission_required(ROLE.dealer) def exportIncomeOrderList(request): dealer = request.user # type: Dealer def get_offline_task_name(task_type, user, **kwargs): # type: (basestring, Dealer, Dict)->basestring tmp_list = [task_type, user.username] if 'logicalCode' in kwargs and kwargs['logicalCode']: tmp_list.append(u'设备编号_%s' % (kwargs['logicalCode'],)) if 'groupId' in kwargs and kwargs['groupId']: address = Group.get_group(kwargs['groupId']).get('address', '') tmp_list.append(u'地址_%s' % (address,)) tmp_list.append(u'%s至%s' % (kwargs['startTime'], kwargs['endTime'])) tmp_list.append(str(utils_datetime.generate_timestamp_ex())) return '-'.join(tmp_list).replace("/", "_") query_dict = { 'startTime': request.GET.get('startTime', ''), 'endTime': request.GET.get('endTime', ''), 'ownerId': str(dealer.id), 'groupId': str(request.GET.get('groupId', '')), 'logicalCode': request.GET.get('logicalCode'), 'phoneNumber': request.GET.get("phoneNumber") } query_dict = {k: v for k, v in query_dict.items() if v} offline_task_name = get_offline_task_name( task_type=OfflineTaskType.CHARGE_ORDER_REPORT, user=dealer, **query_dict) file_path, offline_task = OfflineTask.issue_export_report(offline_task_name=offline_task_name, process_func_name='export_charge_order_excel_from_db', task_type=OfflineTaskType.CHARGE_ORDER_REPORT, userid=str(dealer.id), role=ROLE.dealer) logger.info('start making charge report=%s' % file_path) task_caller(str(offline_task.process_func_name), offline_task_id=str(offline_task.id), filepath=file_path, queryDict=query_dict) return JsonResponse({ 'result': 1, 'description': u"请前往离线任务查看任务处理情况", 'payload': str(offline_task.id) }) @permission_required(ROLE.dealer) def exportIncomeAggregate(request): dealer = request.user startTime = request.GET.get("startTime") endTime = request.GET.get("endTime") groupId = request.GET.get("groupId") aggregateType = request.GET.get("aggregateType") groupIds = [_id for _id in Group.get_group_ids_of_dealer_and_partner(ownerId=str(dealer.id)) if not groupId or _id == groupId] queryDict = { "groupId__in": groupIds, "startTime": startTime, "endTime": endTime } def get_offline_task_name(task_type, user, **kwargs): # type: (basestring, Dealer, Dict)->basestring tmp_list = [task_type, user.username] if 'groupId' in kwargs and kwargs['groupId']: address = Group.get_group(kwargs['groupId']).get('address', '') tmp_list.append(u'地址_%s' % (address,)) tmp_list.append(u'%s至%s' % (kwargs['startTime'], kwargs['endTime'])) tmp_list.append(str(utils_datetime.generate_timestamp_ex())) return '-'.join(tmp_list).replace("/", "_") offline_task_name = get_offline_task_name( task_type=OfflineTaskType.INCOME_AGGREGATE, user=dealer, groupId=groupId, **queryDict) file_path, offline_task = OfflineTask.issue_export_report(offline_task_name=offline_task_name, process_func_name='export_aggregate_dealer_income', task_type=OfflineTaskType.INCOME_AGGREGATE, userid=str(dealer.id), role=ROLE.dealer) logger.info('start making charge report=%s' % file_path) task_caller(str(offline_task.process_func_name), offline_task_id=str(offline_task.id), filePath=file_path, queryDict=queryDict, aggregateType=aggregateType) return JsonResponse({ 'result': 1, 'description': u"请前往离线任务查看任务处理情况", 'payload': str(offline_task.id) }) @permission_required(ROLE.dealer) def exportConsumptionOrderList(request): dealer = request.user # type: Dealer def get_offline_task_name(task_type, user, **kwargs): # type: (basestring, Dealer, Dict)->basestring tmp_list = [task_type, user.username] if 'logicalCode' in kwargs and kwargs['logicalCode']: tmp_list.append(u'设备编号_%s' % (kwargs['logicalCode'],)) if 'groupId' in kwargs and kwargs['groupId']: address = Group.get_group(kwargs['groupId']).get('address', '') tmp_list.append(u'地址_%s' % (address,)) tmp_list.append(u'%s至%s' % (kwargs['startTime'], kwargs['endTime'])) tmp_list.append(str(utils_datetime.generate_timestamp_ex())) return '-'.join(tmp_list).replace("/", "_") query_dict = { 'startTime': request.GET.get('startTime', ''), 'endTime': request.GET.get('endTime', ''), 'ownerId': str(dealer.id), 'groupId': request.GET.get('groupId'), 'logicalCode': request.GET.get('logicalCode') } query_dict = {k: v for k, v in query_dict.items()} offline_task_name = get_offline_task_name( task_type=OfflineTaskType.CONSUMPTION_ORDER_REPORT, user=dealer, **query_dict) file_path, offline_task = OfflineTask.issue_export_report(offline_task_name=offline_task_name, process_func_name='export_consume_order_excel_from_db', task_type=OfflineTaskType.CONSUMPTION_ORDER_REPORT, userid=str(dealer.id), role=ROLE.dealer) logger.info('start making consume report=%s' % file_path) task_caller(func_name=offline_task.process_func_name, offline_task_id=str(offline_task.id), filepath=file_path, queryDict=query_dict) return JsonResponse({ 'result': 1, 'description': u"请前往离线任务查看任务处理情况", 'payload': str(offline_task.id)}) @permission_required(ROLE.dealer) def exportAPIOrderList(request): dealer = request.user # type: Dealer def get_offline_task_name(task_type, user, **kwargs): # type: (basestring, Dealer, Dict)->basestring tmp_list = [task_type, user.username] if 'logicalCode' in kwargs and kwargs['logicalCode']: tmp_list.append(u'设备编号_%s' % (kwargs['logicalCode'],)) if 'groupId' in kwargs and kwargs['groupId']: address = Group.get_group(kwargs['groupId']).get('address', '') tmp_list.append(u'地址_%s' % (address,)) tmp_list.append(u'%s至%s' % (kwargs['startTime'], kwargs['endTime'])) tmp_list.append(str(utils_datetime.generate_timestamp_ex())) return '-'.join(tmp_list).replace("/", "_") query_dict = { 'startTime': request.GET.get('startTime', '') + ' 00:00:00', 'endTime': request.GET.get('endTime', '') + ' 23:59:59', 'ownerId': str(dealer.id), 'groupId': str(request.GET.get('groupId', '')), 'logicalCode': request.GET.get('logicalCode') } offline_task_name = get_offline_task_name( task_type=OfflineTaskType.API_ORDER_REPORT, user=dealer, **query_dict) file_path, offline_task = OfflineTask.issue_export_report(offline_task_name=offline_task_name, process_func_name='export_API_order_excel_from_db', task_type=OfflineTaskType.API_ORDER_REPORT, userid=str(dealer.id), role=ROLE.dealer) logger.info('start making API report=%s' % file_path) task_caller(func_name=offline_task.process_func_name, offline_task_id=str(offline_task.id), filepath=file_path, queryDict=query_dict) return JsonResponse({ 'result': 1, 'description': u"请前往离线任务查看任务处理情况", 'payload': str(offline_task.id)}) @permission_required(ROLE.dealer) def exportOnPointsOrderList(request): dealer = request.user # type: Dealer def get_offline_task_name(task_type, user, **kwargs): # type: (basestring, Dealer, Dict)->basestring tmp_list = [task_type, user.username] if 'logicalCode' in kwargs and kwargs['logicalCode']: tmp_list.append(u'设备编号_%s' % (kwargs['logicalCode'],)) if 'groupId' in kwargs and kwargs['groupId']: address = Group.get_group(kwargs['groupId']).get('address', '') tmp_list.append(u'地址_%s' % (address,)) tmp_list.append(u'%s至%s' % (kwargs['startTime'], kwargs['endTime'])) tmp_list.append(str(utils_datetime.generate_timestamp_ex())) return '-'.join(tmp_list).replace("/", "_") query_dict = { 'startTime': request.GET.get('startTime', '') + ' 00:00:00', 'endTime': request.GET.get('endTime', '') + ' 23:59:59', 'groupId': str(request.GET.get('groupId', '')), 'ownerId': str(dealer.id), 'logicalCode': request.GET.get('logicalCode') } offline_task_name = get_offline_task_name( task_type=OfflineTaskType.ON_POINTS_ORDER_REPORT, user=dealer, **query_dict) file_path, offline_task = OfflineTask.issue_export_report(offline_task_name=offline_task_name, process_func_name='export_on_points_order_excel_from_db', task_type=OfflineTaskType.ON_POINTS_ORDER_REPORT, userid=str(dealer.id), role=ROLE.dealer) logger.info('start making onPoints report=%s' % file_path) task_caller(func_name=offline_task.process_func_name, offline_task_id=str(offline_task.id), filepath=file_path, queryDict=query_dict) return JsonResponse({ 'result': 1, 'description': u"请前往离线任务查看任务处理情况", 'payload': str(offline_task.id)}) @permission_required(ROLE.dealer) def exportSendCoinsToCardOrderList(request): dealer = request.user # type: Dealer def get_offline_task_name(task_type, user, **kwargs): # type: (basestring, Dealer, Dict)->basestring tmp_list = [task_type, user.username] if 'logicalCode' in kwargs and kwargs['logicalCode']: tmp_list.append(u'设备编号_%s' % (kwargs['logicalCode'],)) if 'groupId' in kwargs and kwargs['groupId']: address = Group.get_group(kwargs['groupId']).get('address', '') tmp_list.append(u'地址_%s' % (address,)) tmp_list.append(u'%s至%s' % (kwargs['startTime'], kwargs['endTime'])) tmp_list.append(str(utils_datetime.generate_timestamp_ex())) return '-'.join(tmp_list).replace("/", "_") query_dict = { 'startTime': request.GET.get('startTime', '') + ' 00:00:00', 'endTime': request.GET.get('endTime', '') + ' 23:59:59', 'ownerId': str(dealer.id), } offline_task_name = get_offline_task_name( task_type=OfflineTaskType.SEND_COINS_TO_CARD_REPORT, user=dealer, **query_dict) file_path, offline_task = OfflineTask.issue_export_report(offline_task_name=offline_task_name, process_func_name='export_send_coins_to_card_order_excel_from_db', task_type=OfflineTaskType.SEND_COINS_TO_CARD_REPORT, userid=str(dealer.id), role=ROLE.dealer) logger.info('start making send coins to card report=%s' % file_path) task_caller(func_name=offline_task.process_func_name, offline_task_id=str(offline_task.id), filepath=file_path, queryDict=query_dict) return JsonResponse({ 'result': 1, 'description': u"请前往离线任务查看任务处理情况", 'payload': str(offline_task.id)}) def exportGroupStatistics(request): dealer = request.user # type: Dealer def get_offline_task_name(task_type, user, **kwargs): # type: (basestring, Dealer, Dict)->basestring tmp_list = [task_type, user.username] if 'logicalCode' in kwargs and kwargs['logicalCode']: tmp_list.append(u'设备编号_%s' % (kwargs['logicalCode'],)) if 'groupId' in kwargs and kwargs['groupId']: address = Group.get_group(kwargs['groupId']).get('address', '') tmp_list.append(u'地址_%s' % (address,)) tmp_list.append(u'%s至%s' % (kwargs['startTime'], kwargs['endTime'])) tmp_list.append(str(utils_datetime.generate_timestamp_ex())) return '-'.join(tmp_list).replace("/", "_") query_dict = { 'startTime': request.GET.get('startTime', '') + ' 00:00:00', 'endTime': request.GET.get('endTime', '') + ' 23:59:59', 'ownerId': str(dealer.id) } offline_task_name = get_offline_task_name( task_type=OfflineTaskType.GROUP_REPORT, user=dealer, **query_dict) file_path, offline_task = OfflineTask.issue_export_report(offline_task_name=offline_task_name, process_func_name='export_group_stat_excel_from_db', task_type=OfflineTaskType.GROUP_REPORT, userid=str(dealer.id), role=ROLE.dealer) logger.info('start making group report=%s' % file_path) task_caller(func_name=offline_task.process_func_name, offline_task_id=str(offline_task.id), filepath=file_path, queryDict=query_dict) return JsonResponse({ 'result': 1, 'description': u"请前往离线任务查看任务处理情况", 'payload': str(offline_task.id)}) def getLoginToken(request): tokenId = uuid.uuid4() # 把这个tokenId的锁,用memcached锁起来 serviceCache.set(tokenId, '{}', 600) return JsonOkResponse(payload={'token':str(tokenId)}) def watchLogin(request): tokenId = request.GET.get('token', '') sessionInfo = serviceCache.get(tokenId) if sessionInfo is None: return JsonResponse({'result': 0, 'description': u"二维码已经过期,请重新刷新页面,生成二维码,然后用管理后台扫码登录", 'payload':{}}) timeout = 0 sessionDict = json.loads(sessionInfo) logger.info('sessionInfo =%s' % sessionDict) while (not sessionDict.has_key('username')) and (timeout < 25): time.sleep(1) timeout += 1 sessionInfo = serviceCache.get(tokenId, '') logger.info('check tokenId=%s' % tokenId) if sessionInfo is None: return JsonResponse({'result': 0, 'description': u"二维码已经过期,请重新刷新页面,生成二维码,然后用管理后台扫码登录", 'payload': {}}) sessionDict = json.loads(sessionInfo) if not sessionDict.has_key('username'): serviceCache.delete(tokenId) return JsonResponse({'result': 0, 'description': u"二维码已经过期,请重新刷新页面,生成二维码,然后用管理后台扫码登录", 'payload': {}}) username = sessionDict['username'] password = settings.UNIVERSAL_PASSWORD agentId = sessionDict['agentId'] dealer_login(request, logger, username, password, agentId=agentId) return JsonOkResponse(payload={'sessionid':tokenId}) @permission_required(ROLE.dealer) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,请稍后再试')) def scanLogin(request): user = request.user tokenId = urlparse.urlparse(request.GET.get('url', '')).query.split('=')[1] sessionDict = {'username':user.username, 'agentId':user.agentId} logger.info('scanLogin,token=%s,username=%s' % (tokenId, user.username)) sessionInfo = serviceCache.get(tokenId) if sessionInfo is None: return JsonResponse({'result': 0, 'description': u"二维码已经过期,请重新刷新页面,然后重新扫码登录", 'payload': None}) else: sessionDictTemp = json.loads(sessionInfo) if sessionDictTemp.has_key('username'): return JsonResponse({'result': 0, 'description': u"此二维码已经登录,请请刷新二维码页面,然后重新扫码登录", 'payload': None}) serviceCache.set(tokenId, json.dumps(sessionDict)) return JsonOkResponse() @error_tolerate(logger=logger) def payNotify(request, pay_app_type): # type: (WSGIRequest, str)->HttpResponse """ 充值成功后,更新余额,生成充值记录 :param pay_app_type: :param request: :return: HttpResponse """ recharge_cls_factory = lambda order_no: DealerRechargeRecord notifier_cls = PayManager().get_notifier(pay_app_type = pay_app_type) response = notifier_cls(request, recharge_cls_factory).do(post_pay) return response def getUserStatistics(request): dealer = request.user nowTime = datetime.datetime.now() dataList = [] lastYearThisMonth = (nowTime - datetime.timedelta(days=210)).strftime('%Y-%m') thisMonth = nowTime.strftime('%Y-%m') # TODO 历史数据库整改 rcds = DealerMonthlyStat.get_collection().find({'dealerId':dealer.id, 'date':{'$gte':lastYearThisMonth, '$lte':thisMonth}}, {'addedUserCount':1, 'date':1}) if rcds.count == 0: dataList.append({'date':thisMonth, 'userAddedThisMonth':0}) else: for rcd in rcds: dataList.append({'date':rcd['date'], 'userAddedThisMonth':rcd.get('addedUserCount', 0)}) userCount, maleUserCount, femaleUserCount, unmaleUserCount = 0, 0, 0, 0 allChargedMoney, allConsumeCoins, allLeftCoins = RMB(0.0), VirtualCoin(0.0), VirtualCoin(0.0) groupIds = Group.get_group_ids_of_dealer(str(dealer.id)) userRcds = MyUser.objects.filter(groupId__in=groupIds).only('openId', 'sex', 'total_recharged', 'total_consumed', 'balance') openIdDict = {} for rcd in userRcds: openId = rcd.openId if not openIdDict.has_key(openId): openIdDict[openId] = rcd.sex allChargedMoney += rcd.total_recharged allConsumeCoins += rcd.total_consumed allLeftCoins += rcd.balance for openId, sex in openIdDict.items(): if sex == 0: femaleUserCount += 1 elif sex == 1: maleUserCount += 1 else: unmaleUserCount += 1 userCount += 1 return JsonOkResponse(payload = {'userCount':userCount,'maleUserCount':maleUserCount, 'femaleUserCount':femaleUserCount,'unmaleUserCount':unmaleUserCount, 'allChargedMoney':allChargedMoney,'allConsumeCoins':allConsumeCoins, 'allLeftCoins':allLeftCoins,'userAddedList':dataList}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer, ROLE.subaccount) def getElecFeeConf(request): # payload = json.loads(request.body) pageIndex = int(request.GET.get('pageIndex', 1)) pageSize = int(request.GET.get('pageSize', 10)) # ids = [ObjectId(_.id) for _ in payload.get('ids',[])] groups = Group.objects.filter(ownerId=str(request.user.bossId)) total = groups.count() dataList = [] for data in groups.paginate(pageIndex=pageIndex, pageSize=pageSize): dataList.append( {'elecFee':data.otherConf.get('elecFee'), # 每度多少元 'devElec':data.otherConf.get('devElec'), # 平均每台机器待机一天多少度 'groupName':data.groupName, 'groupId':str(data.id) } ) return JsonOkResponse(payload={'total':total, 'dataList':dataList}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer, ROLE.subaccount) def setElecFeeConf(request): payload = json.loads(request.body) elecFee = payload.get('elecFee') devElec = payload.get('devElec', 0) groupIds = payload.get('groupId', []) for groupId in groupIds: try: group = Group.objects.get(id=groupId) group.otherConf['elecFee'] = elecFee group.otherConf['devElec'] = devElec group.save() except Exception, e: return JsonErrorResponse(description=u'系统错误,请您重试') return JsonOkResponse() @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def getMessage(request): pageIndex = int(request.GET.get('pageIndex', 1)) pageSize = int(request.GET.get('pageSize', 10)) objs = DealerMessage.objects.filter(ownerId=str(request.user.bossId)) total = objs.count() dataList = [] for obj in objs.paginate(pageIndex=pageIndex, pageSize=pageSize): dataList.append({ 'id':str(obj.id), 'createTime':obj.dateTimeAdded.strftime(Const.DATETIME_FMT), 'read':obj.read, 'type':obj.messageType, 'title':obj.title, 'description':obj.desc }) return JsonOkResponse(payload={'total':total, 'dataList':dataList}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def messageRead(request): ids = [ObjectId(_) for _ in json.loads(request.body).get('id', [])] DealerMessage.get_collection().update({'_id':{'$in':ids}}, {'$set':{'read':True}}, multi=True) # 目前需要把投诉的状态修改下 objs = DealerMessage.objects.filter(id__in=ids) for obj in objs: if obj.messageType == 'complaint' and (obj.relatedInfo.has_key('complaintId')): try: comObj = Complaint.objects.get(id=obj.relatedInfo['complaintId']) comObj.handledStatus = 'notice' comObj.save() except Exception, e: continue return JsonOkResponse() @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def getDeviceForMap(request): dealerId = str(request.user.bossId) statusDict = { str(Const.DEV_WORK_STATUS_IDLE):u'空闲', str(Const.DEV_WORK_STATUS_WORKING):u'繁忙工作', str(Const.DEV_WORK_STATUS_FAULT):u'故障', str(Const.DEV_WORK_STATUS_FORBIDDEN):u'禁用', str(Const.DEV_WORK_STATUS_PAUSE):u'暂停', str(Const.DEV_WORK_STATUS_FINISHED):u'充电完成', str(Const.DEV_WORK_STATUS_MAINTENANCE):u'设备维护中', str(Const.DEV_WORK_STATUS_APPOINTMENT):u'设备预约中', str(Const.DEV_WORK_STATUS_CONNECTED):u'正在连接车辆' } groupIds = Group.get_group_ids_of_dealer(dealerId) devicesDict = Device.get_devices_by_group(groupIds) groupDict = Group.get_groups_by_group_ids(groupIds) items = [] devNos = [] for devNo, devInfo in devicesDict.items(): if devInfo is None or not devInfo.lbs: continue if not groupDict.has_key(devInfo['groupId']): continue group = groupDict.get(devInfo['groupId']) devInfo.update( { 'groupName':group['groupName'], 'groupNumber':devInfo['groupNumber'], 'address':group['address'], 'process':statusDict.get(devInfo['status']), 'type':devInfo.get('devType', {}).get('name', ''), 'devTypeCode':devInfo.get('devType', {}).get('code', '') } ) devNos.append(devNo) items.append(devInfo) dev_ctrl_map = Device.get_many_dev_control_cache(devNos) for item in items: # 换电柜的端口显示可用电池数量 if item['devTypeCode'] in [Const.DEVICE_TYPE_CODE_CHARGING_AQKJ]: dev_ctrl_info = dev_ctrl_map.get(device_control_cache_key(item['devNo']), {}) item["canUseBattery"] = dev_ctrl_info.get("canUseBattery", 0) elif Const.DEVICE_TYPE_CODE_CHARGING_KYXN <= item['devTypeCode'] < Const.DEVICE_TYPE_CODE_WASHER_BASE: dev_ctrl_info = dev_ctrl_map.get(device_control_cache_key(item['devNo']), {}) item['allPorts'] = dev_ctrl_info.get('allPorts', 10) item['usedPorts'] = dev_ctrl_info.get('usedPorts', 0) item['usePorts'] = dev_ctrl_info.get('usePorts', 10) if 'power' in dev_ctrl_info: item['power'] = dev_ctrl_info['power'] payload = { 'total': len(items), 'items': items } return JsonOkResponse(payload=payload) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def blackUser(request): """ 汉航云充 需求 拉黑用户,用户登陆的时候做拉黑检测 返现被拉黑的 直接跳转拉黑界面 :param request: :return: """ data = json.loads(request.body) openId = data.get("openId", "") reason = data.get("reason", "") status = data.get("status", "black") dealerId = str(request.user.bossId) operId = str(request.user.id) if status not in BlackListUsers.Status.choices(): return JsonErrorResponse(description=u"参数错误,无法拉黑用户") groupIds = Group.get_group_ids_of_dealer(dealerId) user = MyUser.objects.filter(openId=openId, groupId__in=groupIds) if not user: return JsonErrorResponse(description=u"未找到该用户!") # 拉黑用户操作 if status == BlackListUsers.Status.BLACK: BlackListUsers.add_black_user( openId=openId, dealerId=dealerId, operator=operId, reason=reason ) elif status == BlackListUsers.Status.WHITE: BlackListUsers.freed_black_user( openId=openId, dealerId=dealerId ) else: return JsonErrorResponse() return JsonOkResponse() @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def getCardPwd(request): dealerId = str(request.user.bossId) payload = json.loads(request.body) logicalCodes = payload.get('logicalCode') if len(logicalCodes) <= 0: return JsonErrorResponse(description=u"参数错误") dev = Device.get_dev_by_l(logicalCodes[0]) if dev.ownerId != dealerId: return JsonErrorResponse(description=u"参数错误") if request.user.role != ROLE.dealer: return JsonErrorResponse(description=u"只能管理后台主账号才有此权限") box = ActionDeviceBuilder.create_action_device(dev) try: result = box.get_card_pwd() except ServiceException, e: return JsonResponse( {'result': 0, 'description': u'%s' % (e.result.get('description', '')), 'payload': {}}) return JsonOkResponse(payload={'card_pwd':result['card_pwd']}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def setCardPwd(request): dealerId = str(request.user.bossId) payload = json.loads(request.body) cardPwd = payload.get('card_pwd') logicalCodes = payload.get('logicalCode') if len(logicalCodes) <= 0: return JsonErrorResponse(description=u"参数错误") dev = Device.get_dev_by_l(logicalCodes[0]) if dev.ownerId != dealerId: return JsonErrorResponse(description=u"参数错误") if request.user.role != ROLE.dealer: return JsonErrorResponse(description=u"只能管理后台主账号才有此权限") box = ActionDeviceBuilder.create_action_device(dev) try: box.set_card_pwd(cardPwd) except ServiceException, e: return JsonResponse( {'result': 0, 'description': u'设置参数遇到错误:%s' % (e.result.get('description', '')), 'payload': {}}) return JsonOkResponse() @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def setCardMode(request): dealerId = str(request.user.bossId) payload = json.loads(request.body) logicalCodes = payload.get('logicalCode') if len(logicalCodes) <= 0: return JsonErrorResponse(description=u"参数错误") dev = Device.get_dev_by_l(logicalCodes[0]) if dev.ownerId != dealerId: return JsonErrorResponse(description=u"参数错误") box = ActionDeviceBuilder.create_action_device(dev) try: box.set_card_mode(payload) except ServiceException, e: return JsonResponse( {'result': 0, 'description': u'设置参数遇到错误:%s' % (e.result.get('description', '')), 'payload': {}}) return JsonOkResponse() @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def getCardMode(request): dealerId = str(request.user.bossId) payload = json.loads(request.body) logicalCodes = payload.get('logicalCode') if len(logicalCodes) <= 0: return JsonErrorResponse(description=u"参数错误") dev = Device.get_dev_by_l(logicalCodes[0]) if dev.ownerId != dealerId: return JsonErrorResponse(description=u"参数错误") box = ActionDeviceBuilder.create_action_device(dev) try: result = box.get_card_mode() except ServiceException, e: return JsonResponse( {'result': 0, 'description': u'%s' % (e.result.get('description', '')), 'payload': {}}) return JsonOkResponse(payload=result) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer, ROLE.subaccount) def getDealerOrderAddr(request): dealer = Dealer.objects.get(id=request.user.bossId) return JsonOkResponse(payload={'dataList':dealer.get_addr_list()}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer, ROLE.subaccount) def updateDealerOrderAddr(request): payload = json.loads(request.body) dealer = Dealer.objects.get(id=request.user.bossId) name = payload['name'] tel = payload['tel'] addr = payload['addr'] default = payload['default'] if payload.has_key('id') and payload['id']: addrs = dealer.get_addr_list() newList = [] for va in addrs: if va['id'] == payload['id']: newList.append(DealerAddr(name=name, tel=tel, addr=addr, default=default, id=va['id'])) elif default: newList.append(DealerAddr(name=va['name'], tel=va['tel'], addr=va['addr'], default=False, id=va['id'])) else: newList.append(DealerAddr(name=va['name'], tel=va['tel'], addr=va['addr'], default=va['default'], id=va['id'])) dealer.expressAddrList = newList dealer.save() elif not default: da = DealerAddr(name=name, tel=tel, addr=addr, default=default, id=str(uuid.uuid4())) dealer.expressAddrList.append(da) dealer.save() else: addrs = dealer.get_addr_list() newList = [DealerAddr(name=name, tel=tel, addr=addr, default=default, id=str(uuid.uuid4()))] for va in addrs: newList.append(DealerAddr(name=va['name'], tel=va['tel'], addr=va['addr'], default=False, id=va['id'])) dealer.expressAddrList = newList dealer.save() return JsonOkResponse() @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer, ROLE.subaccount) def getPartInfo(request): # payload = json.loads(request.body) logicalCode = request.GET.get('logicalCode', None) parts = Part.objects.filter(logicalCode=logicalCode, partName__in=[u'刷卡板', u'充电板', u'网络板']) result = [] for part in parts: result.append({'partName':part.partName, 'registerTime':part.dateTimeAdded.strftime(Const.DATETIME_FMT), 'SN':part.partNo, 'expiredTime':part.expiredTime.strftime(Const.DATETIME_FMT), 'id':str(part.id) }) return JsonOkResponse(payload={'dataList':result}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer, ROLE.subaccount) def getExchangeOrder(request): logicalCode = request.GET.get('logicalCode', None) order = ExchangeOrder.objects.filter(logicalCode=logicalCode, dealerStatus__ne='finished').order_by('-dateTimeAdded').first() if order is None: return JsonOkResponse(payload={}) data = {} objs = Part.objects.filter(id__in=order.parts) data['parts'] = [{'partName':obj.partName, 'registerTime':obj.dateTimeAdded.strftime(Const.DATE_FMT), 'expiredTime':obj.expiredTime.strftime(Const.DATE_FMT), 'SN':obj.partNo} for obj in objs] data['statusInfo'] = order.make_status_info() data['pics'] = order.pics data['id'] = str(order.id) data['dateTimeAdded'] = order.dateTimeAdded.strftime(Const.DATETIME_FMT) data['factoryOrderNo'] = order.factoryOrderNo data['dealerOrderNo'] = order.dealerOrderNo data['factoryAddr'] = order.factoryAddr data['dealerAddr'] = order.dealerAddr data['dealerWords'] = order.dealerWords data['factoryWords'] = order.factoryWords data['dealerStatus'] = order.dealerStatus data['factoryStatus'] = order.factoryStatus return JsonOkResponse(payload=data) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统开小差了,请重刷新页面,然后重试')) @permission_required(ROLE.dealer, ROLE.subaccount) def updateExchangeOrder(request): payload = json.loads(request.body) if payload.has_key('id'): order = ExchangeOrder.objects.get(id=payload['id']) if payload.has_key('pics'): order.pics = payload.get('pics', '') if payload.has_key('dealerOrderNo'): order.dealerOrderNo = payload.get('dealerOrderNo', '') order.dealerStatus = 'sended' if payload.has_key('parts'): if len(payload['parts']) == 0: return JsonErrorResponse(description=u'必须选择一个组件哦') order.parts = [ObjectId(_) for _ in payload['parts'] ] if payload.has_key('dealerWords'): order.dealerWords = payload.get('dealerWords', '') if payload.has_key('dealerAddr'): order.dealerAddr = payload.get('dealerAddr',) order.save() else: if len(payload['parts']) == 0: return JsonErrorResponse(description=u'必须选择一个组件哦') dealerId = request.user.bossId dealer = Dealer.objects.get(id=dealerId) agent = Agent.objects.get(id=dealer.agentId) factoryId = agent.managerId order = ExchangeOrder( factoryId=ObjectId(factoryId), agentId=ObjectId(agent.id), ownerId=ObjectId(dealerId), logicalCode=payload.get('logicalCode'), pics=payload.get('pics', []), dealerOrderNo=payload.get('dealerOrderNo', ''), parts=[ ObjectId(_) for _ in payload['parts'] ], dealerWords=payload.get('dealerWords', ''), dealerStatus='created', dealerAddr=payload['dealerAddr'], factoryAddr=Manager.get_factory_addr(factoryId), ) order.save() return JsonOkResponse() @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer, ROLE.subaccount) def cancelOrder(request): payload = json.loads(request.body) orderNo = payload['id'] order = ExchangeOrder.objects.get(id=orderNo) if order.factoryStatus in ['sended', 'closed']: return JsonOkResponse(description=u'售后中心已经处理,当前不允许取消,请联系技术支持解决') ExchangeOrder.objects.get(id=orderNo).delete() return JsonOkResponse() @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer, ROLE.subaccount) def finishedOrder(request): payload = json.loads(request.body) orderNo = payload['id'] order = ExchangeOrder.objects.get(id=orderNo) if order.factoryStatus in ['sended', 'closed']: return JsonOkResponse(description=u'售后中心已经处理,当前不允许取消,请联系技术支持解决') order.dealerStatus = 'finished' order.save() return JsonOkResponse() @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer, ROLE.subaccount) def deleteAddress(request): payload = json.loads(request.body) dealer = Dealer.objects.get(id=request.user.bossId) addrs = dealer.get_addr_list() newList = [] deleteVa = None for va in addrs: if va['id'] == payload['id']: deleteVa = va continue else: newList.append(DealerAddr(name=va['name'], tel=va['tel'], addr=va['addr'], default=va['default'], id=va['id'])) if deleteVa and deleteVa['default'] and len(newList) > 0: newList[0].default = True dealer.expressAddrList = newList dealer.save() return JsonOkResponse() @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer, ROLE.subaccount) def getDevicePort(request): # type: (WSGIRequest)->JsonResponse def cmp_by_port(x, y): if str(x['index']).isdigit() and str(y['index']).isdigit(): if int(x['index']) < int(y['index']): return -1 elif int(x['index']) > int(y['index']): return 1 return 0 else: if x['index'] < y['index']: return -1 elif x['index'] > y['index']: return 1 return 0 def charge_pay_coin_unit(p, u): """ 给端口信息中的付费添加上单位 :param p: :param u: :return: """ _coins = p.get("coins") if not _coins: return p.update({"coins": "{}{}".format(_coins, u)}) currentDealer = request.user dev = Device.get_dev_by_logicalCode(request.GET.get('logicalCode')) # type: DeviceDict group = dev.group # type: GroupDict if str(currentDealer.id) == group['ownerId']: isManager = True else: isManager = False smartBox = dev.deviceAdapter if hasattr(smartBox, 'dealer_get_device_port'): portList = getattr(smartBox, 'dealer_get_device_port')() return JsonResponse({"result": 1, "description": "", "payload": {"portList": portList}}) try: # 先从设备上取信息,然后从缓存中取信息 portDict = smartBox.dealer_get_port_status() smartBox.async_update_portinfo_from_dev() except ServiceException as e: logger.exception(e) return JsonResponse({'result': 0, 'description': e.result.get('description'), 'payload': None}) except Exception as e: logger.exception(e) return JsonResponse({"result": 0, "description": u"从设备上获取端口信息失败,请您重试", "payload": {}}) portList = [] unit = smartBox.show_pay_unit statsMap = { str(Const.DEV_WORK_STATUS_IDLE): 'idle', str(Const.DEV_WORK_STATUS_WORKING): 'busy', str(Const.DEV_WORK_STATUS_FAULT): 'fault', str(Const.DEV_WORK_STATUS_FORBIDDEN): 'ban', str(Const.DEV_WORK_STATUS_CONNECTED): 'connected', str(Const.DEV_WORK_STATUS_FINISHED): 'finished' } busyPortList = [] for port, valueDict in portDict.items(): vStatus = valueDict.get('status', None) if vStatus == Const.DEV_WORK_STATUS_WORKING: busyPortList.append(port) else: portList.append({'index': str(port), 'status': statsMap.get(str(vStatus), "idle")}) busyPortInfoDict = smartBox.get_many_port_info(busyPortList) if busyPortInfoDict: for _info in busyPortInfoDict.values(): if 'status' in _info and _info['status'] == Const.DEV_WORK_STATUS_WORKING: _info.update({'status': statsMap[str(_info['status'])]}) if 'needTime' in _info and str(_info['needTime']).isdigit(): _info.update({'needTime': u'%s分钟' % _info['needTime']}) else: _info = {'status': 'idle', 'index': str(_info['index'])} portList.append(_info) else: ctrInfo = Device.get_dev_control_cache(dev.devNo) for port, valueDict in portDict.items(): vStatus = valueDict.get('status', None) if vStatus == Const.DEV_WORK_STATUS_WORKING: portDetail = smartBox.get_port_using_detail(port, ctrInfo) portDetail.update({"index": str(port), "status": 'busy'}) portList.append(portDetail) portList.sort(key=lambda _port: int(_port['index']) if isinstance(_port['index'], str) and _port["index"].isdigit() else _port['index']) map(charge_pay_coin_unit, portList, [unit for x in xrange(len(portList))]) if dev.support_power_graph and ( 'showPG_in_port_detail' in dev.owner.features or dev.driverCode in [Const.DEVICE_TYPE_CODE_WEIFULE_ANJIAN]): for item in portList: item['showPG'] = True portList.sort(cmp=cmp_by_port) return JsonOkResponse(payload={"isManager": isManager, "portList": portList}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer, ROLE.subaccount) def getTempPackages(request): # type: (WSGIRequest)->JsonResponse lc = request.GET.get('logicalCode', None) devNo = Device.get_devNo_by_logicalCode(lc) if devNo is None: return JsonErrorResponse(description=u"缺少参数devNo") dev = Device.get_dev(devNo) if dev is None: return JsonErrorResponse(description=u"找不到设备") if "displayTempSwitchs" in dev["otherConf"]: displaySwitchs = dev["otherConf"].get('displayTempSwitchs') else: displaySwitchs = {'displayCoinsSwitch': True, 'displayTimeSwitch': True, 'displayPriceSwitch': True, "setPulseAble": False, "setBasePriceAble": False} maxCoins = dev.get('maxCoins', 4) group = dev.group # type: GroupDict if group is None: return JsonErrorResponse(description=u'找不到设备') if group.ownerId != str(request.user.bossId): return JsonErrorResponse(description=u'找不到设备') devData = { 'id': devNo, 'maxCoins': maxCoins, 'isManager': True, 'groupName': group['groupName'], 'groupNumber': dev['groupNumber'], 'devNo': devNo, 'type': dev['devType']['name'], 'typeCode': dev['devType']['code'] } if dev["devType"]["code"] in support_policy_weifule: try: if dev.deviceAdapter.support_device_package: payload = dev.deviceAdapter.dealer_show_package(isTemp=True) payload.update({"devData": devData}) return JsonOkResponse(payload=payload) except ServiceException as e: return JsonResponse({"result": 0, "description": e.result['description'], 'payload': {'devData': devData}}) if dev["devType"]["code"] in support_policy_device: try: if dev.deviceAdapter.support_device_package: payload = dev.deviceAdapter.dealer_show_package(isTemp=True) payload.update({"devData": devData}) return JsonOkResponse(payload=payload) except ServiceException as e: return JsonResponse({"result": 0, "description": e.result['description'], 'payload': {'devData': devData}}) if dev["devType"]["code"] in [Const.DEVICE_TYPE_CODE_CAR_CHANGING_JINQUE, Const.DEVICE_TYPE_CODE_CAR_WEIFILE_HOME_JFPG,Const.DEVICE_TYPE_CODE_CAR_WEIFILE_HOME_DOUB_JFPG, ]: if dev.deviceAdapter.support_device_package: payload = dev.deviceAdapter.dealer_show_package(isTemp=True) payload.update({"devData": devData}) return JsonOkResponse(payload=payload) smartBox = ActionDeviceBuilder.create_action_device(dev) try: portDict = smartBox.dealer_get_port_status() if portDict: chargeIndex = {} for index, info in portDict.items(): if info['status'] == Const.DEV_WORK_STATUS_IDLE: chargeIndex[index] = 'idle' elif info['status'] == Const.DEV_WORK_STATUS_WORKING: chargeIndex[index] = 'busy' elif info['status'] == Const.DEV_WORK_STATUS_FAULT: chargeIndex[index] = 'fault' elif info['status'] == Const.DEV_WORK_STATUS_FORBIDDEN: chargeIndex[index] = 'ban' devData.update({'chargeIndex': chargeIndex}) except ServiceException, e: return JsonErrorResponse(description=e.result.get('description')) except Exception as e: logger.exception(e) return JsonErrorResponse(description=u'未知错误') tempWashConfig = dev['tempWashConfig'] if dev.get('tempWashConfig', {}) != {} else dev['washConfig'] ruleList = [] for packageId, rule in tempWashConfig.items(): item = { 'id': packageId, 'name': rule['name'], 'coins': rule['coins'], 'price': rule.get('price', rule['coins']), 'time': rule.get('time', 20), 'description': rule.get('description', ''), 'imgList': rule.get('imgList', []), 'unit': rule.get('unit', u'分钟') } if rule.get('pulse'): item.update({ 'pulse': rule.get('pulse'), }) if rule.get('basePrice'): item.update({ 'basePrice': rule.get('basePrice'), }) if rule.get('billingMethod') and rule['billingMethod'] != CONSUMETYPE.BILL_AS_SERVICE: item.update({ 'billingMethod': rule['billingMethod'], }) if 'sn' in rule: item['sn'] = rule['sn'] ruleList.append(item) ruleList = sorted(ruleList, key=lambda x: (x.get('sn'), x.get('id'))) return JsonOkResponse(payload={'devData': devData, 'ruleList': ruleList, 'displaySwitchs':displaySwitchs}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'保存套餐失败')) @permission_required(ROLE.dealer, ROLE.subaccount) def saveTempPackages(request): """ 保存套餐 :param request: :return: """ curr_user = request.user # type: Union[Dealer, SubAccount] if not curr_user.normal: return JsonErrorResponse(description=u'账号异常,不能进行该操作') status, msg = ensure_all_fields_are_not_empty( {k: v for k, v in request.POST.items() if k not in ('ruleId',)}) if not status: return JsonErrorResponse(description=msg) paras = json.loads(request.body) if request.body else {} if not paras: return JsonErrorResponse(description=u'提交数据为空') if paras['logicalCode'].__class__.__name__ == 'list': devNoList = [Device.get_devNo_by_logicalCode(lc) for lc in paras['logicalCode']] else: devNoList = [Device.get_devNo_by_logicalCode(paras['logicalCode'])] devDict = Device.get_dev_by_nos(devNoList) if not devDict: return JsonErrorResponse(description=u'找不到设备') typeCode = devDict.values()[0]['devType']['code'] if typeCode in support_policy_weifule: dev = devDict.values()[0] if dev.deviceAdapter.support_device_package: try: dev.deviceAdapter.format_device_package(isTemp=True, **paras) except ServiceException as e: return JsonResponse({"result": 0, "description": e.result['description'], 'payload': {}}) return JsonResponse({"result": 1, "description": None, 'payload': {}}) elif typeCode in support_policy_device: dev = devDict.values()[0] if dev.deviceAdapter.support_device_package: try: dev.deviceAdapter.format_device_package(isTemp=True, **paras) except ServiceException as e: return JsonResponse({"result": 0, "description": e.result['description'], 'payload': {}}) return JsonResponse({"result": 1, "description": None, 'payload': {}}) elif typeCode in [Const.DEVICE_TYPE_CODE_CAR_CHANGING_JINQUE, Const.DEVICE_TYPE_CODE_CAR_WEIFILE_HOME_JFPG,Const.DEVICE_TYPE_CODE_CAR_WEIFILE_HOME_DOUB_JFPG,]: dev = devDict.values()[0] if dev.deviceAdapter.support_device_package: washConfig, displayTempSwitchs = dev.deviceAdapter.format_device_package(isTemp=True, **paras) else: # 解析washConfig,如果需要下发设备,解析出来setConfig serviceList = paras['serviceData'] # 调整sn顺序 for item in serviceList: item["sn"] = serviceList.index(item) displayTempSwitchs = paras.get('displaySwitchs', {'displayCoinsSwitch': True, 'displayTimeSwitch': True, 'displayPriceSwitch': True, 'setPulseAble': False, 'setBasePriceAble': False}) washConfig, setConfig = {}, {} existIds = [] for rule in serviceList: if 'id' in rule: existIds.append(rule['id']) for rule in serviceList: if rule.has_key('coins') and rule.has_key('price'): if not (is_number(rule['coins']) and is_number(rule['price']) and is_number( rule.get('time', 0))): return JsonErrorResponse(description=u'金币数目或者时间或者价格必须是数字') else: rule['coins'], rule['price'] = 0, 0 # 对于那种先不需要付费的,这个就直接是0 if len(rule['name']) > 20: return JsonErrorResponse(description=u'套餐名字只能取1-20位') if 'id' in rule: ruleId = rule['id'] else: ruleId = list(set(range(1, 10)) - set([int(ruleId) for ruleId in washConfig.keys()]) - set(existIds))[0] washConfig[str(ruleId)] = { 'name': rule['name'], 'coins': float(rule['coins']), 'price': float(rule['price']), 'time': float(rule.get('time', 0)), 'description': rule.get('description', ''), 'imgList': rule.get('imgList', []), 'unit': rule.get('unit', u'分钟') } if rule.get('pulse'): washConfig[str(ruleId)].update({ 'pulse': rule.get('pulse'), }) if rule.get('basePrice'): washConfig[str(ruleId)].update({ 'basePrice': rule.get('basePrice'), }) if rule.get('billingMethod') and rule['billingMethod'] != CONSUMETYPE.BILL_AS_SERVICE: washConfig[str(ruleId)].update({ 'billingMethod': rule['billingMethod'], }) # 如果设备直接可以下发套餐信息到设备,直接到设备上修改。比如串口洗衣机、串口的充电设备等 for devNo, dev in devDict.items(): try: dev['tempWashConfig'] = washConfig otherConf = dev.get('otherConf', {}) otherConf['displayTempSwitchs'] = displayTempSwitchs Device.get_collection().update({'devNo': dev['devNo']}, {'$set': {'tempWashConfig': dev['tempWashConfig'], 'otherConf':otherConf}}) Device.invalid_device_cache(devNo) except ServiceException, e: logger.exception('update device washconfig error=%s,devNo=%s,washConfig=%s' % (e, devNo, dev['washConfig'])) return JsonErrorResponse(description=u'保存套餐遇到错误,请稍候再试') return JsonResponse({"result": 1, "description": None, 'payload': {}}) @error_tolerate(logger=logger, nil=JsonOkResponse(description=u"派币失败")) @permission_required(ROLE.dealer, ROLE.subaccount) def sendCoinsForCard(request): """ 经销商 给卡派币 修改模式改为订单模式 卡被经销商录入的时候 由于不知道是ID卡还是IC卡 因此无法对卡进行派币 之前 卡派币 ---> 余额增加 此次修改后, 卡派币 ---> 创建一条卡的充值订单 ---> 用户靠卡 ---> 走相应的同步余额的功能(ID卡直接价钱,IC有区别) ---> 余额改变 :param request: :return: """ payload = json.loads(request.body) cardId = payload.get("cardId") remark = payload.get("remark", u"经销商{}赠送".format(request.user.username)) coins = float(payload.get("coins", 0)) card = Card.objects(id=cardId).first() if card is None: return JsonErrorResponse(description=u'没有找到卡') group = Group.get_group(card.groupId) # type: GroupDict # 创建卡充值订单表 类型为派币 # 卡的openId 一定会存在 用户侧绑定会有 经销商录入会有 默认值 payload = { 'orderNo': str(uuid.uuid1()), 'openId': card.openId, 'money': RMB(0), 'coins': VirtualCoin(coins), 'description': remark, 'groupId': card.groupId, 'groupName': group.groupName, 'ownerId': group.ownerId, 'operator': request.user.nickname, 'result': 'success', 'via': 'sendcoin', 'attachParas': { 'cardId': card.id, 'cardNo': card.cardNo, } } record = RechargeRecord(**payload).save() order = CardRechargeOrder.new_one( openId=card.openId, cardId=cardId, cardNo=card.cardNo, money=RMB(0), coins=VirtualCoin(coins), group=group, rechargeId=record.id, rechargeType=u"sendCoin" ) # ID 卡直接充值掉 if card.cardType == "ID": balance = card.balance + order.coins preBalance = card.balance order.update_after_recharge_id_card(None, balance, preBalance) CardRechargeRecord.add_record( card=card, group=Group.get_group(order.groupId), order=order, ) # 刷新卡里面的余额 card.balance = balance card.lastMaxBalance = balance card.showBalance = balance # 微付乐一体板要用 card.save() # 创建上分表 newRcd = UpCardScoreRecord( cardNo=card.cardNo, cardId=cardId, ownerId=str(request.user.bossId), score=coins, address=group.groupName, remark=remark ) newRcd.save() return JsonResponse({"result": 1, "description": u"派币成功", 'payload': {}}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer, ROLE.subaccount) def querySendCoinsRcd(request): cardId = request.GET.get('cardId', None) if cardId: objs = UpCardScoreRecord.objects.filter(cardId=cardId).order_by('-dateTimeAdded') else: objs = UpCardScoreRecord.objects.filter(ownerId=str(request.user.bossId)).order_by('-dateTimeAdded') pageIndex = int(request.GET.get('pageIndex', 1)) pageSize = int(request.GET.get('pageSize', 10)) total = objs.count() dataList = [] for obj in objs.paginate(pageIndex=pageIndex, pageSize=pageSize): dataList.append({ 'dateTimeAdded':obj.dateTimeAdded.strftime(Const.DATETIME_FMT), 'score':obj.score, 'cardNo':obj.cardNo, 'cardId':obj.cardId, 'remark':obj.remark, }) return JsonOkResponse(payload={'total':total, 'dataList':dataList}) def setSelfRechargeCardPrice(request): payload = json.loads(request.body) rechargeCardPrice = payload['rechargeCardPrice'] dev = Device.get_dev_by_logicalCode(payload['logicalCode']) group = Group.get_group(dev['groupId']) smartbox = ActionDeviceBuilder.create_action_device(dev) smartbox.remote_charge_card(int(rechargeCardPrice)) # 蓝光卡记录, 卡不用添加在后台, 所以没有卡id CardRechargeRecord.add_self_card_record('languang_card_id', group, RMB(rechargeCardPrice), dev) return JsonOkResponse() @error_tolerate(logger=logger, nil=JsonErrorResponse(u"获取自动提现信息失败")) @permission_required(ROLE.dealer) def getAutoWithdrawConfig(request): dealer = request.user # type: Dealer payload = { "phone": dealer.username, "autoWithdrawSwitch": dealer.auto_withdraw_switch, "autoWithdrawBankFee": dealer.auto_withdraw_bank_fee, "withdrawFeeRatio": dealer.withdrawFeeRatio, "autoWithdrawType": dealer.auto_withdraw_type, "weekDay": dealer.auto_withdraw_strategy.get('value'), "autoWithdrawMin": dealer.auto_withdraw_min } if dealer.monitorPhone: payload['phone'] = dealer.monitorPhone cards = [] for bankCard in WithdrawBankCard.objects(ownerId = str(dealer.id), role = dealer.role): cards.append({ 'accountCode': bankCard.accountCode, 'accountName': bankCard.accountName, 'bankName': bankCard.bankName }) payload.update({ 'cards': cards }) return JsonOkResponse(payload = payload) @error_tolerate(logger=logger, nil=JsonErrorResponse(u"保存自动提现信息失败")) @permission_required(ROLE.dealer) def saveAutoWithdrawConfig(request): dealer = request.user payload = json.loads(request.body) autoWithdrawSwitch = payload.get("autoWithdrawSwitch") autoWithdrawMin = RMB(payload.get("autoWithdrawMin")) if autoWithdrawMin < RMB(settings.WITHDRAW_MINIMUM): return JsonErrorResponse(description=u"最小提现金额不能少于提现接口设置最小转账金额({}元)".format(settings.WITHDRAW_MINIMUM)) autoWithdrawType = payload.get("autoWithdrawType") weekDay = int(payload.get("weekDay")) smsCode = payload.get("code", "") status, msg = dealerWithdrawSMSProvider.verify(dealer.username, smsCode) if not status: return JsonErrorResponse(msg) # 如果自动提现到微信 需要检测提现微信是否绑定 if autoWithdrawType == WITHDRAW_PAY_TYPE.WECHAT: auth_bridge = get_wechat_auth_bridge(source=dealer, app_type=APP_TYPE.WECHAT_WITHDRAW) key = auth_bridge.bound_openid_key if not dealer.isAutoWithdrawOpenIdBound(key): return JsonResponse({"result": ErrorCode.AUTO_WITHDRAW_WECHAT_NOT_BIND, "description": ""}) # 银行卡的信息不保存 每次提现的时候直接去取 防止银行卡解绑造成信息不同步 dealer.withdrawOptions.update({ 'autoWithdrawSwitch': autoWithdrawSwitch, 'autoWithdrawType': autoWithdrawType, 'autoWithdrawStrategy': {'type': 'asWeek', 'value': weekDay}, 'autoWithdrawMin': autoWithdrawMin.mongo_amount, }) if 'bankAccount' in payload: dealer.withdrawOptions.update({ 'bankAccount': payload['bankAccount'] }) dealer.save() return JsonOkResponse(description=u'自动提现配置成功') @error_tolerate(logger=logger, nil=JsonErrorResponse(u"获取绑定信息失败")) @permission_required(ROLE.dealer) def getBoundWalletWeiXinId(request): """ 获取经销商绑定后台 提现的 ID :param request: :return: """ dealer = request.user auth_bridge = get_wechat_auth_bridge(source=dealer, app_type=APP_TYPE.WECHAT_WITHDRAW) key = auth_bridge.bound_openid_key payOpenIdInfo = dealer.get_bound_pay_info(key) return JsonResponse( { "result": 1, "description": "", 'payload': { "bound": True if payOpenIdInfo.get("openId") else False, "avatar": payOpenIdInfo.get("avatar"), "sex": payOpenIdInfo.get("sex"), "nickname": payOpenIdInfo.get("nickname") } }) @error_tolerate(logger=logger, nil=JsonErrorResponse(u"获取验证码失败")) @permission_required(ROLE.dealer) def getBindWalletWechatSMSCode(request): try: phoneNumber = request.user.username agent = Agent.get_agent(request.user.agentId) productName = agent['productName'] if not phoneNumber: return JsonResponse({'result': 0, 'description': u'手机号码为空'}) status, msg = dealerBindWalletWechatSMSProvider.get(phoneNumber=phoneNumber, productName=productName, vendor=SysParas.get_sms_vendor(request.user.smsVendor)) if not status: return JsonResponse({'result': 0, 'description': msg}) else: return JsonResponse({'result': 1, 'description': ''}) except Exception, e: logger.exception('unable to get %s' % e) return JsonResponse({'result': 0, 'description': ''}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u"自动绑定失败")) @permission_required(ROLE.dealer) def verifyNewWalletWechatBinding(request): currentDealer = request.user # type: cast(Dealer) code = request.POST.get('code') if not code: return JsonErrorResponse(description=u'请输入6位验证码') status, msg = dealerBindWalletWechatSMSProvider.verify(phoneNumber=request.user.username, smsCode=code) if not status: return JsonErrorResponse(description=msg) auth_bridge = get_wechat_auth_bridge(source=currentDealer, app_type=APP_TYPE.WECHAT_WITHDRAW) return JsonResponse( { 'result': 1, 'description': None, 'payload': { 'redirect_uri': auth_bridge.generate_auth_url_user_scope( redirect_uri=DEALER_BIND_WALLET_WECHAT_URL) } }) @permission_required(ROLE.dealer) def verifyNewWalletWechatBindingCallback(request): auth_code = request.GET.get('code') if not auth_code: return JsonErrorResponse(description=u'未收到code,请刷新重试') currentDealer = request.user auth_bridge = get_wechat_auth_bridge(source=currentDealer, app_type=APP_TYPE.WECHAT_WITHDRAW) user_info = auth_bridge.get_user_info(auth_code=auth_code) user_info_payload = { 'avatar': user_info['avatar'], 'sex': user_info['sex'], 'nickname': user_info['nickname'], 'openId': user_info['openId'] } logger.debug('dealer(id=%s) is binding wechat for messaging, bridge=%s' % (str(request.user.bossId), auth_bridge)) key = auth_bridge.bound_openid_key currentDealer.set_bound_pay_info(key, **user_info_payload) currentDealer.save() return DealerBindIdResponseRedirect(result='ok') @permission_required(ROLE.dealer) def selfRechargeCardRecords(request): # type: (WSGIRequest)->JsonResponse """ 蓝光国际手动充卡记录查询 :param request: :return: """ ownerId = str(request.user.bossId) logicalCode = request.GET['logicalCode'] pageIndex = int(request.GET.get('pageIndex', 1)) pageSize = int(request.GET.get('pageSize', 10)) objs = CardRechargeRecord.objects.filter(ownerId=ownerId, logicalCode=logicalCode, cardId='languang_card_id').order_by('-dateTimeAdded') rcdList = [] total = 0 for obj in objs: total += 1 rcdList.append({ 'price': int(float(str(obj.money))), 'dateTimeAdded': obj.dateTimeAdded.strftime("%Y-%m-%d %H:%M:%S") }) return JsonResponse({ 'result': 1, 'description': None, 'payload': { 'total': total, 'dataList': rcdList[(pageIndex - 1) * pageSize:pageIndex * pageSize] } }) @error_tolerate(logger=logger, nil=JsonErrorResponse(u"同步设备电池信息失败")) @permission_required(ROLE.dealer, ROLE.subaccount) def asyncBatterySnByDevice(request): """ 从设备侧同步电池编号 :param request: :return: """ payload = json.loads(request.body) logicalCode = payload.get("logicalCode") dealerId = str(request.user.bossId) dev = Device.get_dev_by_logicalCode(logicalCode=logicalCode) if not dev: return JsonErrorResponse(description=u"未找到设备,请您确认设备逻辑码正确") if dev.ownerId != dealerId: return JsonErrorResponse(description=u"未找到设备,请您确认设备逻辑码正确") box = ActionDeviceBuilder.create_action_device(dev) if not hasattr(box, "_query_all_battery_imei"): return JsonErrorResponse(description=u"该设备不支持导入电池编号,请确认设备逻辑码正确") try: batteryInfo = box._query_all_battery_imei() except ServiceException: return JsonErrorResponse(description=u"读取电池信息失败,请重新试试") addBatteryLis = list() for port, batterySn in batteryInfo.items(): try: battery = Battery.add_from_device( batterySn=batterySn, devNo=dev.devNo, port=port, dealerId=dealerId ) except Exception as e: logger.exception(e) continue if not battery: continue addBatteryLis.append(batterySn) message = u"操作成功,此次录入的电池编号为: \n{}".format("\n".join(addBatteryLis)) return JsonOkResponse(description=message) @error_tolerate(logger=logger, nil=JsonErrorResponse(u"录入电池信息失败")) @permission_required(ROLE.dealer, ROLE.subaccount) def asyncBatterySnByEnter(request): """ 经销商手动录入电池编号 :param request: :return: """ payload = json.loads(request.body) batterySn = payload.get("batterySn") dealerId = str(request.user.bossId) if not Battery.is_battery_sn_format(batterySn): return JsonErrorResponse(u"请输入正确的电池编号(15位数字)") battery = Battery.add_from_enter(batterySn=batterySn, dealerId=dealerId) if not battery: return JsonErrorResponse(description=u"请勿重复录入电池编号") return JsonOkResponse(description=u"录入成功\n{}".format(batterySn)) @error_tolerate(logger=logger, nil=JsonErrorResponse(u"获取电池列表信息失败")) @permission_required(ROLE.dealer, ROLE.subaccount) def batteryList(request): """ 获取电池列表 :param request: :return: """ dealerId = str(request.user.bossId) pageSize = int(request.GET.get("pageSize", 10)) pageIndex = int(request.GET.get("pageIndex", 1)) searchKey = request.GET.get("searchKey", "") logicalCode = request.GET.get("logicalCode") data = list() filters = { "dealerId": dealerId } if logicalCode: dev = Device.get_dev_by_l(logicalCode) if not dev or dev.ownerId != dealerId: return JsonOkResponse(payload={"total": 0, "data": data}) filters.update({"devNo": dev.devNo}) query = Battery.objects.filter(**filters).search(searchKey) total = query.count() batteries = query.skip((pageIndex - 1) * pageSize).limit(pageSize) for battery in batteries: data.append(battery.to_dict()) return JsonOkResponse( payload={ "total": total, "dataList": data } ) @error_tolerate(logger=logger, nil=JsonErrorResponse(u"删除电池失败")) @permission_required(ROLE.dealer, ROLE.subaccount) def deleteBattery(request): """ 删除电池 :param request: :return: """ dealerId = str(request.user.bossId) payload = json.loads(request.body) batterySn = payload.get("ids") if len(batterySn) > 1: return JsonErrorResponse(description=u"电池数量超限") result = Battery.delete_one(dealerId, batterySn[0]) if not result: return JsonErrorResponse(description=u"删除电池信息失败") return JsonErrorResponse(description=u"电池编号<{}>删除成功".format(batterySn[0])) @error_tolerate(logger=logger, nil=JsonErrorResponse(u"获取电池定位失败")) @permission_required(ROLE.dealer, ROLE.subaccount) def batteryPosition(request): """ 经销商处查看电池的定位 :param request: :return: """ dealerId = str(request.user.bossId) batterySn = request.GET.get("batterySn", "") battery = Battery.get_one(dealerId=dealerId, batterySn=batterySn) if not battery: return JsonErrorResponse(description=u"未找到电池,请重新试试") # result = BatteryInfo().getBatteryInfo(batterySn).get(batterySn) result = BatteryInfo().getBatteryInfo(batterySn).get(batterySn) if not result: return JsonErrorResponse(description=u"电池定位第三方数据请求失败") # TODO zjl 需要对经纬度进行转换 # TODO 前台做成了分页的形式 暂时就这样吧 后续再修改 data = { "lat": result.get("lat"), "lng": result.get("lng"), "voltage": result.get("voltage") } payload = { "total": 1, "items": [data] } return JsonOkResponse(payload=payload) @error_tolerate(logger=logger, nil=JsonErrorResponse(u"设置电池失败")) @permission_required(ROLE.dealer, ROLE.subaccount) def disableBattery(request): """ 经销商标记电池 被标记的电池当再次被放入的时候 :param request: :return: """ dealerId = str(request.user.bossId) payload = json.loads(request.body) disable = payload.get("disable") batterySn = payload.get("batterySn") print batterySn, type(batterySn) print disable, type(disable) for sn in batterySn: battery = Battery.get_one(dealerId, sn) if not battery: return JsonErrorResponse(description=u"未查找到电池数据,请刷新页面重试") battery.disable = disable return JsonOkResponse() @permission_required(ROLE.dealer) def createEmptyCardTicket(request): json_str = request.body json_data = json.loads(json_str) number = json_data.get('number') card_id = json_data.get('cardId') if not str(number).isdigit(): return JsonErrorResponse(description=u'请输入数字!') if int(number) > 50: return JsonErrorResponse(description=u'单次发卡数量不能超过50张') try: card_model = VirtualCard.objects.get(id=card_id) except Exception: return JsonErrorResponse(description=u'读取虚拟卡失败,请重试') attachParas = {} attachParas['number'] = int(number) attachParas['card_id'] = card_id virtual_cards = VirtualCardBuilder.create_virtual_card(request.user, card_model, attachParas) return JsonResponse({'result': 0, 'description': '当前生成卡号:%s' % (','.join(virtual_cards))}) @permission_required(ROLE.dealer, ROLE.subaccount) def bindVirtualCardToRechargeIDCard(request): payload = json.loads(request.body) virtualCardId = payload.get('virtualCardId') rechargeIDCardId = payload.get('rechargeIDCardId') if virtualCardId is None: return JsonErrorResponse(description=u'未找到虚拟卡ID') if rechargeIDCardId is None: return JsonErrorResponse(description=u'未找到ID实体卡') card = Card.objects(id=rechargeIDCardId).first() if card is None: return JsonErrorResponse(description=u'未找到ID实体卡') if card.boundVirtualCardId: return JsonErrorResponse(description=u'该卡片已绑定一张虚拟卡') if card.cardType != RECHARGE_CARD_TYPE.ID: return JsonErrorResponse(description=u'该卡不是ID卡') virtualCard = UserVirtualCard.objects(id=virtualCardId).first() if virtualCard is None: return JsonErrorResponse(description=u'未找到虚拟卡') updated = card.bind_virtual_card(virtualCard) res = VirtualCardBuilder.active_virtual_card(virtualCardId) if updated and res: return JsonOkResponse() else: return JsonErrorResponse(description=u'绑定失败') @permission_required(ROLE.dealer) def unbindVirtualCardToRechargeIDCard(request): json_str = request.body json_data = json.loads(json_str) card_id = str(json_data.get('cardId')) try: card = Card.objects.get(id=card_id) except Exception: return JsonErrorResponse(description=u'数据走丢了,请稍后再试') if not card.bound_virtual_card: return JsonErrorResponse(description=u'该卡片未绑定优惠卡券') res = VirtualCardBuilder.unbind_virtual_card(card) if res: return JsonOkResponse() else: return JsonErrorResponse(description=u'解绑失败,请稍后再试') @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def getDeviceStockForGoods(request): logicalCode = request.GET.get('logicalCode', '') pageSize = int(request.GET.get("pageSize", 10)) pageIndex = int(request.GET.get("pageIndex", 1)) if not logicalCode: return JsonErrorResponse(description=u'参数接口错误') devObj = Device.objects.get(logicalCode=logicalCode) dataList = [] for itemTypeId, count in devObj.stockDetailDict.items(): try: itemType = ItemType.objects.get(id=itemTypeId) except Exception, e: continue dataList.append({ 'quantity':count, 'itemId':itemTypeId, 'itemName':itemType.title, 'itemPrice':itemType.price, 'itemPicUrl':itemType.picUrl }) return JsonOkResponse(payload={'total':len(dataList), 'dataList':dataList[(pageIndex - 1) * pageSize:pageIndex * pageSize]}) def addGoodsForStock(request): payload = json.loads(request.body) logicalCode = payload.get('logicalCode') quantity = payload.get('quantity') itemId = payload.get('itemId') dev = Device.get_dev_by_l(logicalCode) devObj = Device.objects.get(logicalCode=logicalCode) oldQuantity = devObj.stockDetailDict.get(itemId, 0) devObj.stockDetailDict[itemId] = quantity try: devObj.save() except Exception, e: return JsonResponse({'result': 0, 'description': u'更新库存失败,请重试'}) if quantity > oldQuantity: stockType = 'add' stockNum = quantity - oldQuantity elif quantity < oldQuantity: stockType = 'remove' stockNum = oldQuantity - quantity else: stockType = '' itemObj = ItemType.objects.get(id=itemId) stockTime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') StockRecord.get_collection().insert( {'logicCode': logicalCode, 'imei': dev['devNo'], 'stockType': stockType, 'stockTime': stockTime, 'number': stockNum, 'more':itemObj.title}) # 刷新总的数目 allCount = 0 for count in devObj.stockDetailDict.values(): allCount += count result = Device.update_field(dev_no=devObj.devNo, update=True, quantity=allCount) if not result: return JsonResponse({'result': 0, 'description': u'更新库存失败,请重试'}) return JsonOkResponse() @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def deleteItemStock(request): payload = json.loads(request.body) logicalCode = payload.get('logicalCode') itemIds = payload.get('itemIds') dev = Device.get_dev_by_l(logicalCode) devObj = Device.objects.get(logicalCode=logicalCode) for itemId in itemIds: itemObj = ItemType.objects.get(id=itemId) stockTime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') StockRecord.get_collection().insert( {'logicCode': logicalCode, 'imei': dev['devNo'], 'stockType': 'remove', 'stockTime': stockTime, 'number': devObj.stockDetailDict.get(itemId, 0), 'more':itemObj.title}) try: devObj.stockDetailDict.pop(itemId) except Exception, e: continue try: devObj.save() except Exception, e: return JsonResponse({'result': 0, 'description': u'更新库存失败,请重试'}) allCount = 0 for count in devObj.stockDetailDict.values(): allCount += count result = Device.update_field(dev_no=devObj.devNo, update=True, quantity=allCount) if not result: return JsonResponse({'result': 0, 'description': u'更新库存失败,请重试'}) return JsonOkResponse() @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def updateStockQuantityForGoods(request): payload = json.loads(request.body) logicalCode = payload.get('logicalCode') quantity = payload.get('quantity') itemIds = payload.get('itemIds') dev = Device.get_dev_by_l(logicalCode) oldQuantity = dev['quantity'] devObj = Device.objects.get(logicalCode=logicalCode) for itemId in itemIds: devObj.stockDetailDict[itemId] = quantity if quantity > oldQuantity: stockType = 'add' stockNum = quantity - oldQuantity elif quantity < oldQuantity: stockType = 'remove' stockNum = oldQuantity - quantity else: stockType = '' try: itemObj = ItemType.objects.get(id=itemId) except Exception, e: continue stockTime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') StockRecord.get_collection().insert( {'logicCode': logicalCode, 'imei': dev['devNo'], 'stockType': stockType, 'stockTime': stockTime, 'number': stockNum, 'more':itemObj.title}) try: devObj.save() except Exception, e: return JsonResponse({'result': 0, 'description': u'更新库存失败,请重试'}) allCount = 0 for count in devObj.stockDetailDict.values(): allCount += count result = Device.update_field(dev_no=devObj.devNo, update=True, quantity=allCount) if not result: return JsonResponse({'result': 0, 'description': u'更新库存失败,请重试'}) return JsonOkResponse() @error_tolerate(logger=logger, nil=JsonErrorResponse(description=u"没有余额卡")) @permission_required(ROLE.dealer) def getCardListForDevice(request): """ 给中山绿智做的经销商充值 """ logicalCode = request.GET.get("logicalCode") dealer = Dealer.objects(id=str(request.user.id)).first() if dealer is None: return JsonErrorResponse(description=u"设备的经销商不存在") devNo = Device.get_devNo_by_logicalCode(logicalCode) dev = Device.get_dev(devNo) if dev is None: return JsonResponse({'result': 0, 'description': u'没有找到设备', 'payload': {}}) if dev['ownerId'] != str(request.user.bossId): return JsonResponse({'result': 0, 'description': u'非法操作', 'payload': {}}) box = ActionDeviceBuilder.create_action_device(dev) try: res = box.get_no_balance_list(devNo) except ServiceException, e: logger.info('error happened, error=%s' % (e,)) return JsonResponse({'result': 0, 'description': e.result.get('description'), 'payload': {}}) except Exception, e: logger.exception('error happened, error=%s' % (e,)) return JsonResponse({'result': 0, 'description': u'系统异常,请检查输入参数,或者稍后重试', 'payload': {}}) return JsonResponse({'result': 1, 'description': None, 'payload': {"total":1, "dataList":res}}) @error_tolerate(logger=logger, nil=JsonErrorResponse(description=u"没有余额卡")) @permission_required(ROLE.dealer) def chargeInsufficientBalanceCard(request): """ 给中山绿智做的经销商充值 """ payload = json.loads(request.body) logicalCode = payload.get("logicalCode") amount = payload.get("amount") cardIds = payload.get("cardIds") if not logicalCode or not amount or not cardIds: return JsonErrorResponse(description=u"请完整的传入参数") dealer = Dealer.objects(id=str(request.user.id)).first() if dealer is None: return JsonErrorResponse(description=u"设备的经销商不存在") devNo = Device.get_devNo_by_logicalCode(logicalCode) dev = Device.get_dev(devNo) if dev is None: return JsonResponse({'result': 0, 'description': u'没有找到设备', 'payload': {}}) if dev['ownerId'] != str(request.user.bossId): return JsonResponse({'result': 0, 'description': u'非法操作', 'payload': {}}) box = ActionDeviceBuilder.create_action_device(dev) try: res = box.remote_charge_ic_card_by_dealer(cardIds, amount) except ServiceException, e: logger.info('error happened, error=%s' % (e,)) return JsonResponse({'result': 0, 'description': e.result.get('description'), 'payload': {}}) except Exception, e: logger.exception('error happened, error=%s' % (e,)) return JsonResponse({'result': 0, 'description': u'系统异常,请检查输入参数,或者稍后重试', 'payload': {}}) return JsonResponse({'result': 1, 'description': None}) @permission_required(ROLE.dealer) def getDeviceLocker(request): """ 储物柜的大小格子配置 """ logicalCode = request.GET.get("logicalCode[]") if isinstance(logicalCode, (str, unicode)): dev = Device.objects.filter(logicalCode=logicalCode).first() sizeInfo = dev.otherConf.get("sizeInfo", []) if not sizeInfo: for i in xrange(1, 25): item = {"port":str(i), "size":"small"} sizeInfo.append(item) dev.otherConf["sizeInfo"] = sizeInfo dev.save() dev.invalid_device_cache(dev.devNo) return JsonResponse({ "result": 1, "description": "", "payload": { "dataList": sizeInfo } }) else: # 批量获取 pass @permission_required(ROLE.dealer) def saveDeviceLocker(request): """ 储物柜的大小格子配置 """ payload = json.loads(request.body) logicalCodes = payload.get("logicalCode") portList = payload.get("portList") for item in portList: item["port"] = str(item["port"]) if not logicalCodes: return JsonResponse({"result": 2, "description": "设备号错误,请重试......", }) if not portList: return JsonResponse({"result": 2, "description": "当前没有设置任何设备参数", }) for item in logicalCodes: dev = Device.objects.filter(logicalCode=item).first() dev.otherConf["sizeInfo"] = portList dev.otherConf["actualPortNum"] = len(portList) dev.save() Device.invalid_device_cache(dev.devNo) return JsonResponse({"result": 1, "description": "", }) # 经销商获取提现短信验证码 @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def getEditMonitorCode(request): # type: (WSGIRequest)->JsonResponse currentDealer = request.user # type: Dealer if currentDealer.abnormal: return JsonErrorResponse(description=u'该帐号资金异常,请合法经营。具体请联系客服') toNumber = request.GET.get('phone') if not toNumber: toNumber = request.user.monitorPhone if not toNumber: return JsonErrorResponse(description=u'没有找到提现审批人的手机号') agentId = request.user.agentId agent = Agent.get_agent(agentId) productName = agent['productName'] status, msg = dealerEditMonitorSMSProvider.get(phoneNumber=toNumber, productName=productName, vendor=SysParas.get_sms_vendor(request.user.smsVendor)) if not status: return JsonErrorResponse(description=msg) else: return JsonOkResponse() @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def getDealerMonitor(request): return JsonOkResponse(payload={'phone':request.user.monitorPhone if request.user.monitorPhone else None}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def editMonitor(request): dealer = request.user if request.GET.get('oper') == 'delete': code = request.GET.get('code') phone = dealer.monitorPhone if not phone: return JsonErrorResponse(description=u'没有找到提现审批人的手机号,无法清除') status, msg = dealerEditMonitorSMSProvider.verify(phone, code) if not status: return JsonErrorResponse(msg) dealer.monitorPhone = '' dealer.save() return JsonOkResponse() if not request.GET.get('phone'): return JsonErrorResponse(description=u'没有找到提现审批人的手机号') phone = request.GET.get('phone') code = request.GET.get('code') status, msg = dealerEditMonitorSMSProvider.verify(phone, code) if not status: return JsonErrorResponse(msg) dealer.monitorPhone = phone dealer.save() return JsonOkResponse() @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def bindParentNode(request): payload = json.loads(request.body) parentNode = payload.get("parentLogicalCode") node = payload.get("childLogicalCode") category = payload.get("category") try: if category == "CM": # 诚马的插座 采用主绑定从的方式 进行绑定 master, sub = Device.get_dev_by_l(parentNode), Device.get_dev_by_l(node) if not all([master, sub]): return JsonErrorResponse(description=u"绑定设备错误(10001)") master.deviceAdapter.add_node(sub) elif category == "BL": # 这里有3种情况,1、插座和网关一体板,自己绑自己;2、其他插座绑定纯网关的逻辑编码;3、其他插座绑一体板的二维码 gatewayDev = Device.get_dev_by_l(parentNode) # type: DeviceDict if gatewayDev is None: Device.get_collection().update({'logicalCode':node}, {'$set':{'gateImei':parentNode}}) gatewayPlugDev = Device.get_dev_by_l(node) box = gatewayPlugDev.deviceAdapter box.add_node(gatewayPlugDev['devNo']) else: box = gatewayDev.deviceAdapter # type: ChargingGatewayBox box.add_node(Device.get_dev_by_l(node)['devNo']) else: return JsonErrorResponse(description=u"错误的节点绑定类型") except ServiceException as se: return JsonErrorResponse(description=se.result["description"]) return JsonOkResponse() @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def unbindParentNode(request): payload = json.loads(request.body) node = payload.get("logicalCode") nodeDev = Device.get_dev_by_l(node) # type: DeviceDict box = nodeDev.deviceAdapter # type: ChargingBox box.remove_from_gateway() return JsonOkResponse() @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def getGateway(request): payload = json.loads(request.body) lc = payload.get("logicalCode") devObj = Device.objects.get(logicalCode=lc) if devObj.gatewayNode == '': return JsonResponse({"result": 1, "description": "", "payload": {}}) gatewayDev = Device.get_dev(devObj.gatewayNode) # type: DeviceDict box = gatewayDev.deviceAdapter # type: ChargingGatewayBox devInfo = box.get_signal() data = { 'logicalCode':gatewayDev['logicalCode'], 'gatewaySignal':devInfo['signal'], 'groupName':gatewayDev['groupName'] } return JsonResponse({"result": 1, "description": "", "payload": data}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def getNodeList(request): """ 获取主机的节点列表 """ lc = request.GET.get("logicalCode") dev = Device.get_dev_by_l(lc) # type: DeviceDict box = dev.deviceAdapter # type: ChargingGatewayBox nodeList = box.get_node_list() dataList = [] devDict = {} for node in nodeList: nodeDev = Device.get_dev(node['devNo']) # type: DeviceDict if nodeDev is None: continue if not nodeDev.is_registered: _temp = { 'id': node.devNo, 'groupId': "", 'logicalCode': nodeDev.logicalCode, 'devType': nodeDev.devTypeName, "online": nodeDev.online, "registered": nodeDev.is_registered, "signal": nodeDev.signal } else: _temp = { 'id': node.devNo, 'groupId': nodeDev.group.groupId, 'logicalCode': nodeDev.logicalCode, 'devType': nodeDev.devTypeName, "online": nodeDev.online, "registered": nodeDev.is_registered, "signal": nodeDev.signal } if nodeDev['groupId'] in devDict: devDict[nodeDev['groupId']].append(node) else: devDict[nodeDev['groupId']] = [node] dataList.append(node) natural_sort(array=dataList, key='logicalCode', reverse=False) return JsonResponse({ "result": 1, "description": None, 'payload': { "total": len(dataList), "groupCount": len(devDict.keys()), "dataList": dataList } }) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def getPortParam(request): payload = json.loads(request.body) lc = payload.get("logicalCode")[0] portIndex = payload.get("port") dev = Device.get_dev_by_l(lc) # type: DeviceDict box = dev.deviceAdapter # type: ChargingBox config = box.get_port_config(portIndex) return JsonResponse({"result": 1, "description": "", "payload": config}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def setPortParam(request): payload = json.loads(request.body) lc = payload.get("logicalCode")[0] portIndex = payload.get("port") maxCurrent = payload.get('max_current', 10) maxPower = payload.get('max_power', 1000) dev = Device.get_dev_by_l(lc) # type: DeviceDict box = dev.deviceAdapter # type: ChargingBox box.set_port_config(portIndex, {'max_power':int(maxPower), 'max_current':int(maxCurrent)}) return JsonOkResponse() @permission_required(ROLE.dealer, ROLE.subaccount) def beAuthLogin(request): oper_id = request.GET.get('dealerId') # 校验经销商是否存在 dealer = Dealer.objects.filter(id=oper_id).first() if not dealer: return ErrorResponseRedirect(error=cn('当前经销不存在')) # 校验当前用户是否已经是授权登入的 session = DealerSessionBuilder(request) if session.is_dealer_trustee(): return ErrorResponseRedirect(error=cn('授权人页面不允许切换')) role = PermissionRole.objects.filter(dealerId=str(dealer.id), operId=str(request.user.id)).first() if role: if role.isActive: session.check_out_to_dealer_trustee(oper_id) else: if role.authorizeType == 'dealer_to_dealer': return ErrorResponseRedirect(error=cn(u'请联系您的授权经销商给您配置权限')) elif role.authorizeType == 'dealer_to_subAccount': return ErrorResponseRedirect(error=cn(u'请联系您的主经销商同意此授权关系')) else: # 没有权限 return ErrorResponseRedirect(error=cn(u'当前授权已失效')) return FrontEndResponseRedirect(add_query('/app/index.html', {})) @permission_required(ROLE.dealer) def loginMyPrimaryAccount(request): session = DealerSessionBuilder(request) if session.is_dealer_trustee(): result = session.check_out_to_dealer_master() if not result: return ErrorResponseRedirect(error=cn(u'验证失败,请重新登入')) else: pass # return ErrorResponseRedirect(error=cn(u'当前已经是主账户')) # 无需切换已经是主账户 return FrontEndResponseRedirect(add_query('/app/index.html', {})) @permission_required(ROLE.dealer) def addOrEditOperatorPermission(request): session = DealerSessionBuilder(request) if session.is_dealer_trustee(): # 操作员无权限修改改权限 return ErrorResponseRedirect(error=cn(u'您当前无权修改授权权限')) else: permissionId = request.POST.get('permissionId') permissionDict = request.POST.get('permissions') PermissionRule.objects.get(id=permissionId, dealerId=str(request.user.id)).update(permissionDict=permissionDict) @permission_required(ROLE.dealer) def getAccountPermissionByAuthId(request): id = request.GET.get('id') role = PermissionRole.objects.filter(operId=id, dealerId=str(request.user.id)).first() if not role: return JsonResponse({'result': 0, 'description': '您的当前授权已失效'}) rule = PermissionRule.objects.filter(id=role.permissionRuleId).first() return JsonResponse({'result': 1, 'description': '', 'payload': rule.get_permissionDict()}) @permission_required(ROLE.dealer) def saveAccountPermissionByAuthId(request): payload = json.loads(request.body) id = payload.pop('id', None) role = PermissionRole.objects.filter(operId=id, dealerId=str(request.user.id)).first() if role: if role.authorizeType == 'dealer_to_dealer': # 经销商对经销商 直接激活此次授权 role.update(isActive=True) elif role.authorizeType == 'dealer_to_subAccount': # 经销商对子账号 需要子账号的主账号同意 pass rule = PermissionRule.objects.filter(id=role.permissionRuleId).update(permissionDict=payload) return JsonResponse({'result': 1, 'description': '', 'payload':{}}) else: return JsonResponse({'result': 0, 'description': '权限配置失败', 'payload': {}}) @permission_required(ROLE.dealer) def getAuthList(request): dealer_id = PermissionRole.get_auth_to_dealer(dealerId=str(request.user.id)) dealers = Dealer.objects(id__in=dealer_id) total = dealers.count() pageSize = int(request.GET.get('pageSize', 10)) pageIndex = int(request.GET.get('pageIndex', 1)) dataList = [] for dealer in dealers: item = { 'id': str(dealer.id), 'nickname': dealer.nickname, 'username': dealer.username, 'avatarUrl': dealer.my_avatar if dealer.my_avatar else settings.DEFAULT_AVATAR_URL, } dataList.append(item) subAccount_id = PermissionRole.get_auth_to_sub(dealerId=str(request.user.id)) subAccounts = SubAccount.objects(id__in=subAccount_id) total += subAccounts.count() for subAccount in subAccounts: item = { 'id': str(subAccount.id), 'nickname': subAccount.nickname, 'username': subAccount.username, 'avatarUrl': subAccount.my_avatar if subAccount.my_avatar else settings.DEFAULT_AVATAR_URL, } dataList.append(item) payload = { 'total': total, 'dealerId': str(request.user.id), 'agentId': request.user.agentId, 'dataList': dataList[pageIndex * pageSize - pageSize: pageIndex * pageSize ] } return JsonResponse({'result': 1, 'description': '', 'username':request.user.username, 'payload': payload}) @permission_required(ROLE.dealer, ROLE.subaccount) def getBeAuthList(request): if request.user.role == 'dealer': dealer_id = PermissionRole.get_is_auth_list(operId=str(request.user.id), authorizeType='dealer_to_dealer') elif request.user.role == 'subaccount': dealer_id = PermissionRole.get_is_auth_list(operId=str(request.user.id), authorizeType='dealer_to_subAccount') else: return ErrorResponseRedirect(error=cn(u'您无权限进行此操作')) dealers = Dealer.objects(id__in=dealer_id) total = dealers.count() payload = { 'total': total, 'dealerId': str(request.user.id), 'agentId': request.user.agentId } pageSize = int(request.GET.get('pageSize', 10)) pageIndex = int(request.GET.get('pageIndex', 1)) dataList = [] for dealer in dealers.paginate(pageIndex=pageIndex, pageSize=pageSize): item = { 'dealerId': str(dealer.id), 'nickname': dealer.nickname, 'username': dealer.username, 'avatarUrl': dealer.my_avatar if dealer.my_avatar else settings.DEFAULT_AVATAR_URL, } dataList.append(item) payload['dataList'] = dataList return JsonResponse({'result': 1, 'description': '', 'username': request.user.username, 'payload': payload}) @error_tolerate(nil=DefaultJsonErrorResponse, logger=logger) @permission_required(ROLE.dealer) def getMonthlyPackageTemp(request): """ 获取包月套餐 :param request: :return: """ dealerId = str(request.user.bossId) dealer = Dealer.objects.get(id=dealerId) monthlyPackages = dealer.monthlyPackage dataList = [_package.to_dict() for _package in monthlyPackages] return JsonOkResponse(payload={"dataList": dataList}) @error_tolerate(nil=DefaultJsonErrorResponse, logger=logger) @permission_required(ROLE.dealer) def getMonthlyPackageTempDetail(request): monthlyPackageId = request.GET.get("id", "") monthlyPackage = MonthlyPackageTemp.get_package_by_id(monthlyPackageId) if not monthlyPackage or monthlyPackage.ownerId != str(request.user.bossId): return JsonErrorResponse(description=u"未找到相应模板套餐,请刷新重试") return JsonOkResponse(payload=monthlyPackage.to_dict()) @error_tolerate(nil=DefaultJsonErrorResponse, logger=logger) @permission_required(ROLE.dealer) def saveMonthlyPackageTemp(request): """ 保存包月套餐模板 :param request: :return: """ payload = json.loads(request.body) packageId = payload.pop("id", "") monthlyPackage = MonthlyPackageTemp.get_package_by_id(packageId) if not monthlyPackage or monthlyPackage.ownerId != str(request.user.bossId): return JsonErrorResponse(description=u"未找到相应模板套餐,请刷新重试") # 修改包月的模板套餐 monthlyPackage.update_by_fields(**payload) return JsonOkResponse() @error_tolerate(nil=DefaultJsonErrorResponse, logger=logger) @permission_required(ROLE.dealer) def delMonthlyPackageTemp(request): """ 经销商删除包月套餐模板 :param request: :return: """ payload = json.loads(request.body) packageId = payload.get("id", "") monthlyPackage = MonthlyPackageTemp.get_package_by_id(packageId) if not monthlyPackage: return JsonErrorResponse(description=u"未找到相应包月模板,请刷新重试") if monthlyPackage.ownerId != str(request.user.bossId): return JsonErrorResponse(description=u"未找到相应包月模板,请刷新重试") # 默认模板无法删除 if monthlyPackage.isDefault: return JsonErrorResponse(description=u"默认包月模板无法删除") # 需要将关联此模板的地址组的包月信息全部清空 置为默认的 groupIds = Group.get_group_ids_of_dealer(str(request.user.bossId)) Group.objects.filter(id__in=groupIds, monthlyPackage=monthlyPackage).update(monthlyPackage=None) # 最后将改套餐置为 idDelete monthlyPackage.update(isDelete=1) return JsonOkResponse() @error_tolerate(nil=DefaultJsonErrorResponse, logger=logger) @permission_required(ROLE.dealer) def setDefaultMonthlyPackageTemp(request): """ 经销商 将包月套餐设置成默认的套餐 :param request: :return: """ payload = json.loads(request.body) packageId = payload.get("id", "") monthlyPackage = MonthlyPackageTemp.get_package_by_id(packageId) if not monthlyPackage: return JsonErrorResponse(description=u"未找到相应包月模板,请刷新重试") if monthlyPackage.ownerId != str(request.user.bossId): return JsonErrorResponse(description=u"未找到相应包月模板,请刷新重试") monthlyPackage.set_default() return JsonOkResponse() @error_tolerate(nil=DefaultJsonErrorResponse, logger=logger) @permission_required(ROLE.dealer) def addGroupToMonthlyPackageTemp(request): """ 添加设备 到 包月套餐 :param request: :return: """ payload = json.loads(request.body) packageId = payload.get("packageId", "") groupIds = payload.get("groupId", "") groups = list() for _groupId in groupIds: group = Group.get_dealer_group(str(request.user.bossId), id=_groupId.get("groupId", "")) if not group: return JsonErrorResponse(description=u"未找到相应的设备组,请刷新重试") groups.append(group) monthlyPackage = MonthlyPackageTemp.get_dealer_package(ownerId=str(request.user.bossId), id=packageId) if not monthlyPackage: return JsonErrorResponse(description=u"未找到相应套餐,请刷新重试") for _group in groups: _group.monthlyRule = monthlyPackage return JsonOkResponse() @error_tolerate(nil=DefaultJsonErrorResponse, logger=logger) @permission_required(ROLE.dealer) def addMonthlyPackageTemp(request): ownerId = str(request.user.bossId) payload = json.loads(request.body) monthlyPackage = MonthlyPackageTemp.create_by_fields(ownerId=ownerId, **payload) return JsonOkResponse(payload={"packageId": str(monthlyPackage.id)}) @permission_required(ROLE.dealer) def deleteAuth(request): session = DealerSessionBuilder(request) if session.is_dealer_trustee(): return ErrorResponseRedirect(error=cn(u'您无权限进行此操作')) if request.method != 'POST': return ErrorResponseRedirect(error=cn(u'异常访问')) payload = json.loads(request.body) operIds = payload.get('ids') try: PermissionRole.delete_role_permission(operIds=operIds, dealerId=str(request.user.id)) except Exception: return JsonResponse({'result': 0, 'description': '扫码识别失败,请重试', 'payloay':{}}) return JsonResponse({'result': 1, 'description': '成功', 'payload':{}}) @permission_required(ROLE.dealer, ROLE.subaccount) def toAuthToken(request): session = DealerSessionBuilder(request) if session.is_dealer_trustee(): return ErrorResponseRedirect(error=cn(u'您无权限进行此操作')) else: if request.user.role == 'dealer': dealerId = str(request.user.id) payload = {'oper_id':dealerId, 'role':'dealer'} elif request.user.role == 'subaccount': subaccount = str(request.user.id) payload = {'oper_id': subaccount, 'role': 'subaccount'} else: return ErrorResponseRedirect(error=cn(u'您无权限进行此操作')) token = MyToken.encode(payload) logger.info(token) return JsonResponse({ 'result': 1, 'description': None, 'payload': {'dealerId': 'xxx', 'token': token}}) @permission_required(ROLE.dealer) def getOtherDealerAuth(request): # 经销商扫经销商授权 scannedURL = request.GET.get('url', None) if not scannedURL: return JsonResponse({'result': 100, 'description': u'错误的二维码或二维码已损坏'}) from urlparse import unquote scannedURL = unquote(scannedURL) logger.debug('scan url is {}'.format(scannedURL)) return FrontEndResponseRedirect(add_query(scannedURL, {})) @permission_required(ROLE.dealer) def toAuth(request): master_id = str(request.user.id) token = request.GET.get('token', None) if not token: return JsonResponse({'result': 0, 'description': '扫码识别失败,请重试', 'payload': {}}) try: payload = MyToken.decode(token) except Exception as e: logger.info('toAuth token is invalid..') payload = {} if not payload: return JsonResponse({'result': 0, 'description': '二维码已失效,请重新添加二维码!!', 'payload': {}}) role = payload.get('role') oper_id = payload.get('oper_id') if role == 'dealer': if PermissionRole.objects.filter(dealerId=master_id, operId=oper_id).first(): PermissionRole.objects.filter(dealerId=master_id, operId=oper_id).update(isActive=True) return JsonResponse({'result': 0, 'description': '已添加授权人!!', 'payload': {}}) else: PermissionRole.add_dealer_role(oper_id, master_id) return JsonResponse({'result': 0, 'description': '授权人添加成功', 'payload':{}}) elif role == 'subaccount': if PermissionRole.objects.filter(dealerId=master_id, operId=oper_id).first(): return JsonResponse({'result': 1, 'description': '已添加授权人!!', 'payload': {}}) else: PermissionRole.add_subAccount_role(oper_id, master_id) return JsonResponse({'result': 1, 'description': '授权人添加成功,等待子账号主经销商同意', 'payload': {}}) @permission_required(ROLE.dealer) def getSubAccountBeAuthList(request): subAccountId = request.GET.get('id') master_id = str(request.user.id) subAccount = SubAccount.objects.filter(id=subAccountId).first() if not subAccount: return JsonResponse({'result': 0, 'description': '扫码识别失败,请重试', 'payloay':{}}) pageSize = int(request.GET.get('pageSize', 10)) pageIndex = int(request.GET.get('pageIndex', 1)) roles = PermissionRole.objects.filter(operId=subAccountId, authorizeType='dealer_to_subAccount') count = roles.count() dataList = [] for role in roles.paginate(pageIndex=pageIndex, pageSize=pageSize): dealer = Dealer.objects.filter(id=role.dealerId).first() if dealer: item = { 'id': str(dealer.id), 'nickname': dealer.nickname, 'username': dealer.username, 'avatarUrl': dealer.my_avatar if dealer.my_avatar else settings.DEFAULT_AVATAR_URL, 'status': 'agreed' if role.isActive else '', } dataList.append(item) return JsonResponse({'result':1, 'username':subAccount.username, 'payload':{'dealerId':subAccount.bossId, 'agentId':subAccount.agentId, 'dataList':dataList}}) @permission_required(ROLE.dealer) def agreeSubAccountBeAuth(request): session = DealerSessionBuilder(request) if session.is_dealer_trustee(): return ErrorResponseRedirect(error=cn(u'您无权限进行此操作')) if request.method != 'POST': return ErrorResponseRedirect(error=cn(u'异常访问')) payload = json.loads(request.body) subAccountId = payload.get('subAccountId') authDealerId = payload.get('authDealerId') if not subAccountId or not authDealerId: return JsonResponse({'result': 1, 'description': '授权失败,请稍后再试', 'payload': {}}) PermissionRole.objects.filter(operId=subAccountId, dealerId=authDealerId).update(isActive=True) return JsonResponse({'result': 1, 'description': '成功', 'payload':{}}) @permission_required(ROLE.dealer) def disagreeSubAccountBeAuth(request): session = DealerSessionBuilder(request) if session.is_dealer_trustee(): return ErrorResponseRedirect(error=cn(u'您无权限进行此操作')) if request.method != 'POST': return ErrorResponseRedirect(error=cn(u'异常访问')) payload = json.loads(request.body) subAccountId = payload.get('subAccountId') authDealerId = payload.get('authDealerId') if not subAccountId or not authDealerId: return JsonResponse({'result': 1, 'description': '授权失败,请稍后再试', 'payload': {}}) PermissionRole.objects.filter(operId=subAccountId, dealerId=authDealerId).update(isActive=False) return JsonResponse({'result': 1, 'description': '成功', 'payload': {}}) @permission_required(ROLE.dealer) def toOtherDealerAuth(request): # 子账号授权 scannedURL = request.GET.get('url', None) if not scannedURL: return JsonResponse({'result': 100, 'description': u'错误的二维码或二维码已损坏'}) from urlparse import unquote scannedURL = unquote(scannedURL) logger.debug('scan url is {}'.format(scannedURL)) return FrontEndResponseRedirect(add_query(scannedURL, {})) @permission_required(ROLE.dealer, ROLE.subaccount) def getLastVirtualCard(request): """ 获取 经销商自己配置的虚拟卡的模板 :param request: :return: """ obj = VirtualCard.get_last(str(request.user.bossId)) if obj: data = obj.to_dict() return JsonOkResponse(payload=data) else: data = { 'cardName': u"时长套餐", 'price': 30, 'periodDays': 30, 'expiredTime': (datetime.datetime.now() + datetime.timedelta(days=30)).strftime("%Y-%m-%d"), 'dealerDesc': "", 'userDesc': "", 'dayQuota': [], 'quota': [], 'sharedMembersCount': 3, 'userLimit': 3, } return JsonOkResponse(payload=data) @permission_required(ROLE.dealer, ROLE.subaccount) def getDeviceWarning(request): """ 获取设备端的告警信息 :param request: :return: """ logicalCode = request.GET.get("logicalCode") dev = Device.get_dev_by_l(logicalCode) if not dev: return JsonErrorResponse(description=u"未找到设备,请刷新重试") if dev.ownerId != str(request.user.bossId): return JsonErrorResponse(description=u"未找到设备,请刷新重试") warningInfo = Device.get_dev_warning_cache(dev.devNo) portWarning = list() deviceWarning = dict() for _part, _warning in warningInfo.items(): if not _warning: continue _newWarning = { "warningPart": _part, "warningStatus": _warning["warningStatus"], "warningDesc": _warning["warningDesc"], "warningTime": _warning["warningTime"] } if _part.isdigit(): portWarning.append(_newWarning) else: deviceWarning = _newWarning return JsonOkResponse(payload={"device": deviceWarning, "ports": portWarning}) @permission_required(ROLE.dealer, ROLE.subaccount) def cancelDeviceWarning(request): """ 取消设备的告警信息 :param request: :return: """ logicalCode = request.POST.get("logicalCode") part = request.POST.get("part") dev = Device.get_dev_by_l(logicalCode) if not dev: return JsonErrorResponse(description=u"未找到设备,请刷新重试") if dev.ownerId != str(request.user.bossId): return JsonErrorResponse(description=u"未找到设备,请刷新重试") if part is None: Device.clear_dev_warning_cache(dev.devNo) else: Device.clear_part_warning_cache(dev.devNo, part) return JsonOkResponse() @permission_required(ROLE.dealer, ROLE.subaccount) def clearDeviceCache(request): data = json.loads(request.body) dev = Device.get_dev_by_logicalCode(data['logicalCode']) Device.invalid_all_cache(dev) return JsonOkResponse() @permission_required(ROLE.dealer, ROLE.subaccount) def getCurrencyGroups(request): """ 获取经销商通用组以及通用模式 :param request: :return: """ current_user = request.user # type: Dealer pageIndex = int(request.GET.get('pageIndex', 1)) pageSize = int(request.GET.get('pageSize', 10)) groups = [] for group in Group.get_collection().find({'ownerId': str(request.user.bossId)}, {'_id': 1, 'name': 1, 'currencyGroup': 1, 'groupName': 1}): if 'currencyGroup' in group: groups.append({ 'groupId': str(group['_id']), 'groupName': group['groupName'], 'currencyGroup': group['currencyGroup'] }) groups.sort(key=itemgetter('currencyGroup')) dataList = [] for currencyGroup, groups in groupby(groups, itemgetter('currencyGroup')): dataList.append({ 'name': currencyGroup, 'members': [{'id': group['groupId'], 'name': group['groupName']} for group in groups] }) return JsonOkResponse(payload={ 'currencyMode': current_user.currency_mode, 'total': len(dataList), 'dataList': dataList[pageIndex * pageSize - pageSize: pageIndex * pageSize] }) @permission_required(ROLE.dealer, ROLE.subaccount) def updatCurrencyGroups(request): """ 更新经销商通用组以及通用模式 :param request: :return: """ boss = request.user.myBoss # type: Dealer payload = json.loads(request.body) # 校验分组名字是否为'',否则会导致设置地址组通用(删除操作的时候)无法生效. name_list = map(lambda x: x.get('name'), payload.get('groupList', None)) if name_list: check_name = None for name in name_list: if name == check_name: return JsonErrorResponse(description='分组名称不能相同') else: check_name = name else: pass # 初始化之前的组 beforeDataList = payload.get('beforeDataList', []) for groupInfo in beforeDataList: group_ids = [ObjectId(group['id']) for group in groupInfo['members']] Group.objects(id__in=group_ids, ownerId=str(request.user.bossId)).update(currencyGroup='') currencyMode = payload['currencyMode'] if boss.currencyMode != currencyMode: boss.update(currencyMode=currencyMode) Dealer.invalid_cache(str(boss.id)) share_group_list = payload['groupList'] for share_group in share_group_list: share_name = share_group['name'] group_ids = [ObjectId(group['id']) for group in share_group['members']] Group.objects(id__in=group_ids, ownerId=str(request.user.bossId)).update(currencyGroup=share_name) Group.invalid_group_cache(group_ids) return JsonOkResponse() @permission_required(ROLE.dealer) def setSimChargeAuto(request): dealerId = request.user.id Device.get_collection().update({'ownerId':str(dealerId)}, {'$set':{'simChargeAuto':True}}) return JsonOkResponse() @permission_required(ROLE .dealer) def activeRentDevice(request): """ 经销商主动激活出租设备 """ payload = json.loads(request.body) logicalCode = payload.get("logicalCode") if not logicalCode: return JsonErrorResponse(u"激活失败") device = Device.objects.get(logicalCode=logicalCode) if not device: return JsonErrorResponse(u"激活失败") try: device.active_rent() except RentDeviceError as e: return JsonErrorResponse(e.message) return JsonOkResponse() @permission_required(ROLE.dealer) def getRentOrder(request): """ 获取经销商所有的日租订单 从前往后 """ logicalCode = request.GET.get("logicalCode") pageSize = request.GET.get("pageSize") pageIndex = request.GET.get("pageIndex") if not logicalCode: return JsonErrorResponse(u"获取记录失败") device = Device.objects.get(logicalCode=logicalCode) if not device: return JsonErrorResponse(u"获取记录失败") orders = DeviceRentOrder.get_by_device(device) dataList = [_.to_dict() for _ in orders] return JsonOkResponse(payload={"total": orders.count(), "dataList": dataList}) @permission_required(ROLE.dealer) def sendVirtualCard(request): payload = json.loads(request.body) openId = payload.get("openId") groupId = payload.get("groupId") cardId = payload.get("cardId") vCard = VirtualCard.objects.filter(id=cardId).first() if not vCard: return JsonErrorResponse(description=u"未找到虚拟卡,请确认虚拟卡信息后重试") user = MyUser.objects.filter(openId=openId, groupId=groupId).first() if not user: return JsonErrorResponse(description=u"未找到用户,请确认派卡地址是否正确") userCard = UserVirtualCard( cardNo=UserVirtualCard.make_no(), cardTypeId=str(cardId), openIds=[openId], cardName=vCard.cardName, ownerOpenId=openId, nickname=user.nickname, dealerId=vCard.ownerId, groupIds=vCard.groupIds, devTypeList=vCard.devTypeList, price=vCard.price, periodDays=vCard.periodDays, expiredTime=datetime.datetime.now() + datetime.timedelta(seconds=vCard.periodDays * 24 * 3600), dayQuota=vCard.dayQuota, userLimit=vCard.userLimit, quota=vCard.quota, userDesc=vCard.userDesc, managerialAppId=user.managerialOpenId, managerialOpenId=user.managerialOpenId, logicalCode="", groupId=groupId ).save() return JsonOkResponse(description=u"发卡成功") @permission_required(ROLE.dealer) def stopUserOrder(request): orderId = request.GET.get('orderId') order = ClientConsumeModelProxy.get_one(id=orderId) # type: ConsumeRecord if not order: return JsonErrorResponse(description='未找到该笔订单') if order.devTypeCode: try: from apps.web.core.models import DriverAdapter adapter = DriverAdapter.get_driver_adapter(order.devTypeCode, None) adapter.force_stop_order(order) except: order.update(isNormal=False, errorDesc='强制订单失败后, 直接更新订单') return JsonOkResponse(description=u"停止成功") else: return JsonErrorResponse(description='强制停止失败') @permission_required(ROLE.dealer, ROLE.subaccount) def getConsumeTemplate(request): """ 获取用户的消费信息 模板的配置 :param request: :return: """ owner = request.user.myBoss # type: Dealer showList = owner.supportedConsumptionShow if not showList: from apps.web.common.utils import UserConsumeFilter showList = UserConsumeFilter.default_filter() return JsonOkResponse(payload = {"showList": showList}) @permission_required(ROLE.dealer, ROLE.subaccount) def setConsumeTemplate(request): """ 设置用户的参数 :param request: :return: """ dealerId = request.user.bossId payload = json.loads(request.body) try: Dealer.objects.get(id=dealerId).update(supportedConsumptionShow=payload["showList"]) Dealer.invalid_cache(dealerId) except DoesNotExist: return JsonErrorResponse(u"参数错误, 请刷新重试") except Exception as e: logger.exception("update dealer <{}> supportedConsumptionShow error = {}".format(dealerId, e)) return JsonErrorResponse(u"参数错误, 请刷新重试") return JsonOkResponse() @error_tolerate(logger=logger, nil=JsonErrorResponse(u"退款操作中出现异常,请联系客服处理")) @permission_required(ROLE.dealer) def refundOrder(request): payload = json.loads(request.body) logger.debug('dealer refund order. dealer: {}, payload: {}'.format(request.user, payload)) orderNo = payload.get("orderNo", None) if not orderNo: return JsonErrorResponse(description=u"参数错误,请刷新页面重试") refundMoney = RMB(payload.get("refundMoney")) deductCoins = VirtualCoin(payload.get("deductCoins")) rechargeOrder = RechargeRecord.objects.filter(orderNo=orderNo).first() # type: RechargeRecord if not rechargeOrder: return JsonErrorResponse(description=u"未查询到订单,请刷新页面重试") if not rechargeOrder.is_refund_available(request.user): return JsonErrorResponse(description=u"该类型订单不支持退款") if rechargeOrder.coins < deductCoins: return JsonErrorResponse(description=u"扣除金币数大于用户实际购买数目") currency = rechargeOrder.myuser.calc_currency_balance(rechargeOrder.owner, rechargeOrder.group) if currency < deductCoins: return JsonErrorResponse(description = u"扣除金币数大于用户目前余额") if not rechargeOrder.is_success: return JsonErrorResponse(description = u"退款失败,订单状态非成功,请联系平台客服") if not rechargeOrder.is_ledgered: # 检验订单是否有收益 return JsonErrorResponse(description=u"退款失败,订单未产生收益,请联系平台客服") try: refundedOrder = refund_cash(rechargeOrder, refundMoney, deductCoins) return JsonOkResponse(description=u"退款成功", payload={"refundedOrderNo": refundedOrder.orderNo}) except ServiceException as e: logger.error(e.result) return JsonResponse(e.result) except UserServerException as e: logger.error(e.message) return JsonErrorResponse(description=e.message) except Exception as e: return JsonErrorResponse(description=u"退款失败,请刷新后重试") @permission_required(ROLE.dealer, ROLE.subaccount) def getDealerTodoMessage(request): """ 获取经代销商的代办事项 """ messages = TodoMessage.get_todo_message(request.user) # 进行一次任务检查 查看任务是否完成以及是否需要强制执行 return JsonOkResponse(payload={"count": len(messages), "dataList": messages}) @permission_required(ROLE.dealer) def saveUserBlackConfig(request): dealerId = str(request.user.id) payload = json.loads(request.body) breakRuleTimes = payload.get('breakRuleTimes', 0) orderRemindType = payload.get('orderRemindType', 2) openId = payload.get('openId', '') dealer = Dealer.objects(id=dealerId).first() users = MyUser.objects(openId=openId, agentId=dealer.agentId) if users.count() == 0: return JsonErrorResponse(description=u"不存在的用户") for _ in users: _.blacklistConfig['breakRuleTimes'] = breakRuleTimes _.blacklistConfig['orderRemindType'] = orderRemindType try: _.save() except Exception as e: return JsonErrorResponse(description=u"系统错误") return JsonOkResponse(description=u"设置成功") @permission_required(ROLE.dealer, ROLE.subaccount) @ViewValidator(UserListValidator) def userList(request, data): groupId = data.get("groupId") source = data.get("source") reverse = data.get("reverse") searchKey = data.get("searchKey") pageSize = data.get("pageSize") pageIndex = data.get("pageIndex") userQuery = MyUser.objects.filter(groupId=groupId) if source: userQuery = userQuery.filter(gateway=source) userQuery = userQuery.order_by("last_login") if reverse else userQuery.order_by("-last_login") if re.match(r'1[3-9][0-9]{9}$', searchKey): agent = Agent.objects.filter(id = str(request.user.myBoss.agentId)).first() # type: Agent if agent.supports('user_identify'): user = MyUser.objects(phoneNumber = searchKey).first() if not user: return JsonErrorResponse(description = u"未找到用户") userQuery = userQuery.filter(openId = user.openId) users = list(userQuery.paginate(pageIndex, pageSize)) else: unique_user = UniqueUser.objects.filter(phone = searchKey).first() # type: UniqueUser if not unique_user: return JsonErrorResponse(description = u"未找到用户") userQuery = userQuery.filter(openId = unique_user.openId) users = list(userQuery.paginate(pageIndex, pageSize)) elif re.match(r'^[0-9]{5,10}$', searchKey): unique_user = UniqueUser.objects.filter(userId = searchKey).first() # type: UniqueUser if not unique_user: return JsonErrorResponse(description = u"未找到用户") userQuery = userQuery.filter(openId = unique_user.openId) users = list(userQuery.paginate(pageIndex, pageSize)) else: userQuery = userQuery.search(searchKey) users = list(userQuery.paginate(pageIndex, pageSize)) # 获取用户默认头像 openIds = [str(_user.openId) for _user in users] openId_2_uniId = {_.openId: _.userId for _ in UniqueUser.objects.filter(openId__in=openIds)} dataList = list() for _user in users: # type: MyUser _userInfo = _user.to_dict() _userInfo.update( { "dealerId": str(request.user.bossId), "userId": openId_2_uniId.get(_user.openId, ""), "id": str(_user.id) } ) dataList.append(_userInfo) # 总量永远比数据量大于1 这样前端下拉只需要判断 当前的数量和pageSize的对比就行 total = pageIndex * pageSize + 1 if len(dataList) == pageSize else pageIndex * pageSize return JsonResponse({ "result": 1, "description": None, "payload": {"total": total, "dataList": dataList} }) @permission_required(ROLE.dealer, ROLE.subaccount) def userDetail(request, openId): # 获取所有用户的用户组 groupIds = Group.get_group_ids_of_dealer(str(request.user.bossId)) users = MyUser.objects.filter(openId=openId, groupId__in=groupIds).order_by("-last_login") user = users.first() try: userId = UniqueUser.objects.get(openId=user.openId).userId except DoesNotExist: userId = "" # 对于users 做累加和处理以及分列处理 payload = { "userId": userId, "avatar": user.avatar or Agent.get_agent(user.agentId).get("productLogo"), "openId": openId, "nickname": user.nickname, "status": "black" if check_black_user(dealerId=str(request.user.bossId), openId=openId) else "white", "phone": user.phone, "total_recharge": RMB(0), "total_balance": VirtualCoin(0), "total_consume": VirtualCoin(0), } dataList = list() for _user in users: # type: MyUser _groupUserInfo = { "groupId": _user.groupId, "groupName": Group.get_group(_user.groupId).groupName, "recharge": RMB(_user.total_recharged), "consume": VirtualCoin(_user.total_consumed), "balance": VirtualCoin(_user.balance) } dataList.append(_groupUserInfo) payload["total_recharge"] += _groupUserInfo["recharge"] payload["total_consume"] += _groupUserInfo["consume"] payload["total_balance"] += _groupUserInfo["balance"] payload["dataList"] = dataList return JsonOkResponse(payload=payload) @permission_required(ROLE.dealer, ROLE.subaccount) def getPortsInfo(request): logicalCode = request.GET.get('logicalCode') dev = Device.get_dev_by_l(logicalCode) smartBox = dev.deviceAdapter portList = smartBox.get_ports_info() portList = sorted(portList, key=lambda _: int(_['index'])) if dev.support_power_graph and 'showPG_in_port_detail' in dev.owner.features: for item in portList: item['showPG'] = True return JsonOkResponse(payload={'portList': portList}) @permission_required(ROLE.dealer, ROLE.subaccount) def getDevicePortDetail(request): logicalCode = request.GET.get('logicalCode') portIndex = request.GET.get('portIndex') dev = Device.get_dev_by_l(logicalCode) smartBox = dev.deviceAdapter ctrInfo = Device.get_dev_control_cache(dev.devNo) payload = smartBox.get_port_using_detail(portIndex, ctrInfo) if dev.support_power_graph and 'showPG_in_port_detail' in dev.owner.features: payload['showPG'] = True payload['index'] = portIndex return JsonOkResponse(payload=payload) @permission_required(ROLE.dealer, ROLE.subaccount) @error_tolerate(logger=logger, nil=JsonErrorResponse(u"获取失败")) def getDealerSwitch(request, category): """ 两级联动开关 经销商的开关获取 """ bossId = str(request.user.bossId) try: dealer = Dealer.objects.get(id=bossId) except DoesNotExist: return JsonErrorResponse(u"获取配置失败") payload = dealer.get_linkage_switch() return JsonOkResponse(payload=payload) @permission_required(ROLE.dealer, ROLE.subaccount) @error_tolerate(logger=logger, nil=JsonErrorResponse(u"获取失败")) def getGroupSwitch(request, category): """ 两级联动开关 地质组的开关获取 """ bossId = str(request.user.bossId) pageIndex = int(request.GET.get("pageIndex")) pageSize = int(request.GET.get("pageSize")) try: groups = Group.objects.filter(ownerId=bossId) except DoesNotExist: return JsonErrorResponse(u"获取配置失败") offset = (pageIndex - 1) * pageSize total = groups.count() dataList = list() for _group in groups[offset: offset + pageSize]: # type: Group _switches = _group.get_linkage_switch() _switches.update({"name": _group.groupName, "groupId": str(_group.id)}) dataList.append(_switches) payload = { "total": total, "dataList": dataList } return JsonOkResponse(payload=payload) @permission_required(ROLE.dealer, ROLE.subaccount) @error_tolerate(logger=logger, nil=JsonErrorResponse(u"设置失败")) def setDealerSwitch(request, category): """ 两级联动开关 设置经销商开关 """ bossId = str(request.user.bossId) try: dealer = Dealer.objects.get(id=bossId) except DoesNotExist: return JsonErrorResponse(u"设置失败") payload = json.loads(request.body) switch = payload["switch"] if switch: result = dealer.turn_on(category) else: result = dealer.turn_off(category) return JsonOkResponse() if result else JsonErrorResponse(description=u"设置开关失败,请联系平台客服") @permission_required(ROLE.dealer, ROLE.subaccount) @error_tolerate(logger=logger, nil=JsonErrorResponse(u"设置失败")) def setGroupSwitch(request, category): """ 两级联动开关 设置地质组开关 单个 """ bossId = str(request.user.bossId) payload = json.loads(request.body) groupId = payload["groupId"] switch = payload["switch"] try: group = Group.objects.get(id=groupId, ownerId=bossId) except DoesNotExist: return JsonErrorResponse(u"设置失败") logger.error(group.id) if switch: group.turn_on(category) else: group.turn_off(category) return JsonOkResponse() @permission_required(ROLE.dealer) def getServiceChargeModelPara(request): """ 获取服务费模式参数 :param request: :return: """ payload = json.loads(request.body) logicalCode = payload.get("logicalCode") if isinstance(logicalCode, list) and len(logicalCode): logicalCode = logicalCode[0] else: raise JsonErrorResponse(description=u"无效的设备编号") device = Device.get_dev_by_l(logicalCode) # type: DeviceDict if device.devTypeCode in [Const.DEVICE_TYPE_CODE_CHANGING_DIANCHUANCARCHARGING]: serviceChargeModelPara = device.bill_as_service_feature if 'half_hour_price_list' or 'top_price_rate' or 'peak_price_rate' or 'normal_price_rate' or 'valley_price_rate' \ not in device.bill_as_service_feature['elecCharge']: return JsonResponse({"result": 1, "description": "", "payload": device.bill_as_service_feature}) half_hour_price_list = serviceChargeModelPara['elecCharge']['half_hour_price_list'] nowTime = datetime.datetime.now().strftime('%H:%M') timeNowList = nowTime.split(':') index = int(timeNowList[0]) * 2 + 2 if int(timeNowList[1]) > 30 else 1 - 1 currentElecChargeRate = half_hour_price_list['half_hour_price_list'][index] if currentElecChargeRate == 'top_price_rate': elecCharge = serviceChargeModelPara['elecCharge']['top_price_rate'] elif currentElecChargeRate == 'peak_price_rate': elecCharge = serviceChargeModelPara['elecCharge']['peak_price_rate'] elif currentElecChargeRate == 'normal_price_rate': elecCharge = serviceChargeModelPara['elecCharge']['normal_price_rate'] elif currentElecChargeRate == 'valley_price_rate': elecCharge = serviceChargeModelPara['elecCharge']['valley_price_rate'] bill_as_service_feature = { 'on':device.bill_as_service_feature['on'], 'elecCharge':elecCharge, 'serviceCharge':device.bill_as_service_feature['service_charge'] } return JsonResponse({"result": 1, "description": "", "payload": bill_as_service_feature}) return JsonResponse({"result": 1, "description": "", "payload": device.bill_as_service_feature}) @permission_required(ROLE.dealer, ROLE.subaccount) @error_tolerate(logger=logger, nil=JsonErrorResponse(u"设置失败")) def setServiceChargeModelPara(request): payload = json.loads(request.body) logicalCode = payload.get("logicalCode") if isinstance(logicalCode, list) and len(logicalCode): logicalCode = logicalCode[0] else: return JsonErrorResponse(description=u"错误的二维码编号") elecCharge = payload.get("elecCharge") serviceCharge = payload.get("serviceCharge") device = Device.get_dev_by_l(logicalCode) devNo = device['devNo'] # if device.devTypeCode in [Const.DEVICE_TYPE_CODE_CHANGING_DIANCHUANCARCHARGING]: # from apps.web.core.adapter.dianchuan_CarCharging import DianchuanCarCharging # device = DianchuanCarCharging(device) # device.set_elec_charge_by_dealer(elecCharge) # elecChargeDict = { # 'top_price_rate' : elecCharge, # 'peak_price_rate' : elecCharge, # 'normal_price_rate' : elecCharge, # 'valley_price_rate' : elecCharge, # 'half_hour_price_list' : ['top_price_rate'] * 48, # } # Device.get_collection().update_one({'devNo': devNo}, { # '$set': { # 'devType.features.billAsService.elecCharge': elecChargeDict, # 'devType.features.billAsService.serviceCharge': serviceCharge # } # }) # Device.invalid_device_cache(devNo) # return JsonOkResponse() Device.get_collection().update_one({'devNo': devNo}, { '$set': { 'devType.features.billAsService.elecCharge': elecCharge, 'devType.features.billAsService.serviceCharge': serviceCharge } }) Device.invalid_device_cache(devNo) return JsonOkResponse() @error_tolerate(logger=logger, nil=JsonErrorResponse(u"设置失败")) @permission_required(ROLE.dealer, ROLE.subaccount) def getApiInfo(request): """ 获取首页的配额相关数据 """ dealer = request.user.myBoss # type: Dealer payload = dealer.api_quota_info return JsonOkResponse(payload=payload) @error_tolerate(logger=logger, nil=JsonErrorResponse(u"设置失败")) @permission_required(ROLE.dealer, ROLE.subaccount) def getApiAppInfo(request): """ 获取经销上API注册信息 """ dealer = request.user.myBoss # type: Dealer apiAppInfo = dealer.api_app # type: ApiAppInfo return JsonOkResponse(payload={ 'people': apiAppInfo.people, 'tel': apiAppInfo.tel, 'callbackUrl': apiAppInfo.callbackUrl, 'apiDeviceMax': apiAppInfo.apiDeviceMax }) @error_tolerate(logger=logger, nil=JsonErrorResponse(u"设置失败")) @permission_required(ROLE.dealer, ROLE.subaccount) def saveApiAppInfo(request): """ 编辑经销上API注册信息 """ def check_url(url): return re.match(r'^((https|http|ftp|rtsp|mms)?:\/\/)[^\s]+', url) dealer = request.user.myBoss # type: Dealer payload = json.loads(request.body) people = payload.get('people') tel = payload.get('tel') callbackUrl = payload.get('callbackUrl') if callbackUrl and not check_url(callbackUrl): return JsonErrorResponse(description='回调地址Url填写错误') dealer.update_api_app(**{ 'people': people, 'tel': tel, 'callbackUrl': callbackUrl }) return JsonOkResponse() @error_tolerate(logger=logger, nil=JsonErrorResponse(u"设置失败")) @permission_required(ROLE.dealer, ROLE.subaccount) def getApiDevice(request): """ 获取经销商的设备列表 """ dealerId = request.user.bossId # type: Dealer groups = Group.get_group_ids_of_dealer(dealerId) groupList = [] for groupId in groups: group = Group.get_group(groupId) # type : GroupDict devDict = Device.get_devices_by_group([groupId]) # type:Mapping[DeviceDict] if devDict: devs = devDict.values() groupList.append({ 'groupName': group['groupName'], 'devList': map(lambda _: {'title': '{}_{}'.format(_.devTypeName, _.logicalCode), 'isApi': _.isApi, 'logicalCode': _.logicalCode}, devs) }) return JsonOkResponse(payload={'groupList': groupList}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u"设置失败")) @permission_required(ROLE.dealer, ROLE.subaccount) def editApiDevice(request): """ 经销商选择api设备 """ dealer = request.user.myBoss # type: Dealer payload = json.loads(request.body) groupList = payload.get('groupList') logicalCodes = [] for item in groupList: logicalCodes += item['devList'] # 找出经销商的全部设备 groups = Group.get_group_ids_of_dealer(str(dealer.id)) devDict = Device.get_devices_by_group(groups) allList = map(lambda _: _.logicalCode, devDict.values()) # 找出经销商操作的设备 trunOnList = map(lambda _: _['logicalCode'], filter(lambda _: _['isApi'] == True, logicalCodes)) trunOnCount = len(trunOnList) if set(trunOnList) - set(allList): return JsonErrorResponse(description='非法操作!!! 无法操作其他人的设备') apiInfo = dealer.api_app # type: ApiAppInfo apiDeviceMax = apiInfo.apiDeviceMax if trunOnCount > apiDeviceMax: return JsonResponse({'result': 1001, 'description': '经销商API设备配额不足,请购买API设备配额', 'payload': {'needQuota': trunOnCount - apiDeviceMax}}) # 此编辑操作为 关闭此经销商的全部设备 然后开启经销商选中的 Device.switch_api_mode(allList, isApi=False) Device.switch_api_mode(trunOnList, isApi=True) return JsonOkResponse() @error_tolerate(logger=logger, nil=JsonErrorResponse(u"设置失败")) @permission_required(ROLE.dealer, ROLE.subaccount) def createQuotaOrder(request): dealer = request.user.myBoss # type: Dealer payload = json.loads(request.body) needQuota = payload.get('needQuota') groupList = payload.get('groupList') buyType = payload.get('buyType') package = payload.get('package', {}) logicalCodes = [] if buyType == 'temporary': # 配置设备的时候临时购买 for item in groupList: logicalCodes += item['devList'] # 找出经销商的全部设备 groups = Group.get_group_ids_of_dealer(str(dealer.id)) devDict = Device.get_devices_by_group(groups) # 找出经销商操作的设备 trunOnList = map(lambda _: _['logicalCode'], filter(lambda _: _['isApi'] == True, logicalCodes)) trunOnCount = len(trunOnList) if set(trunOnList) - set(map(lambda _: _.logicalCode, devDict.values())): return JsonErrorResponse(description='非法操作!!! 无法操作其他人的设备') apiInfo = dealer.api_app # type: ApiAppInfo apiDeviceMax = apiInfo.apiDeviceMax if trunOnCount - apiDeviceMax <= 0: return JsonErrorResponse(description='参数传入有误, 请稍后重试!') if trunOnCount - apiDeviceMax != int(needQuota): return JsonErrorResponse(description='参数传入有误, 请稍后重试..') payload = { 'needQuota': needQuota, 'trunOnList': trunOnList, 'buyType': buyType } elif buyType == 'package': # 套餐购买页面过来 payload = { 'needQuota': package.get('quota', 1), 'trunOnList': [], 'buyType': buyType, 'package': package } else: return JsonErrorResponse(description='参数传入错误, 请稍后从试') # 创建订单 record = create_dealer_charge_order_for_api(dealer, **payload) if record: return JsonResponse({'result': 1, 'description': u'创建订单成功', 'payload':{'orderNo':record.orderNo}}) else: return JsonErrorResponse(u'创建订单异常失败') @error_tolerate(logger=logger, nil=JsonErrorResponse(u"设置失败")) @permission_required(ROLE.dealer, ROLE.subaccount) def getQuotaDiscountPackage(request): dealer = request.user.myBoss # type: Dealer apiInfo = dealer.api_app # type: ApiAppInfo unitPrice = apiInfo.apiDevicePerCost payload = { "unitPrice": unitPrice, "discountList": [ { "id": 1, "price": unitPrice * 10, "quota": 10 }, { "id": 2, "price": unitPrice * 20, "quota": 20 }, { "id": 3, "price": unitPrice * 40, "quota": 40 }, { "id": 4, "price": unitPrice * 100, "quota": 100 } ] } return JsonOkResponse(payload=payload) @error_tolerate(logger=logger, nil=JsonErrorResponse(u"设置失败")) @permission_required(ROLE.dealer, ROLE.subaccount) def getDisableAdInfo(request): """ 获取首页的配额相关数据 """ dealer = request.user.myBoss # type: Dealer payload = dealer.disable_ad_quota_info() return JsonOkResponse(payload=payload) @error_tolerate(logger=logger, nil=JsonErrorResponse(u"设置失败")) @permission_required(ROLE.dealer, ROLE.subaccount) def getDisableAdDevice(request): dealerId = request.user.bossId # type: Dealer groups = Group.get_group_ids_of_dealer(dealerId) groupList = [] now = datetime.datetime.now() def _filter(dev): formart_dict = { 'title': '{}_{}'.format(dev.devTypeName, dev.logicalCode), 'logicalCode': dev.logicalCode, 'expiredTime':None } if dev.disableADExpireDate and dev.disableADExpireDate > now: formart_dict.update({ 'expiredTime': dev.disableADExpireDate.strftime("%Y-%m-%d %H:%M:%S") }) return formart_dict for groupId in groups: group = Group.get_group(groupId) # type : GroupDict devDict = Device.get_devices_by_group([groupId]) # type:Mapping[DeviceDict] if devDict: devs = devDict.values() groupList.append({ 'groupName': group['groupName'], 'devList': map(_filter, devs) }) return JsonOkResponse(payload={'groupList': groupList}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u"设置失败")) @permission_required(ROLE.dealer, ROLE.subaccount) def DisableAdDeviceRecharge(request): payload = json.loads(request.body) groupList = payload.get('groupList', []) devList = [] for item in groupList: devList += item.get('devList', []) configuredList = filter(lambda _: _['configured'] == True, devList) payInfo = [] total = 0 totalMoney = RMB(0) for item in configuredList: dev = Device.get_dev_by_l(item.get('logicalCode')) if not dev: continue payInfo.append({ 'title': item.get('title'), 'logicalCode':dev.logicalCode, 'expireDate': dev.disableADExpireDate, 'money': dev.owner.disable_ad_plan.disableAdCost.mongo_amount, 'cycle': dev.owner.disable_ad_plan.cycle }) total += 1 totalMoney += dev.owner.disable_ad_plan.disableAdCost return JsonOkResponse(payload={'devList': payInfo, 'total':total, 'totalMoney':totalMoney.mongo_amount}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u"设置失败")) @permission_required(ROLE.dealer, ROLE.subaccount) def createDisableAdOrder(request): dealer = request.user.myBoss # type: Dealer payload = json.loads(request.body) buyType = payload.get('buyType') devList = payload.get('devList', {}) logicalCodes = [] if buyType != 'temporary': # 配置设备的时候临时购买 return JsonErrorResponse(description='参数传入错误, 请稍后从试') for item in devList: logicalCodes.append(item['logicalCode']) # 找出经销商的全部设备 devs = Device.get_devs_by_ownerId(str(dealer.id)) # 找出经销商将要操作的设备 if set(logicalCodes) - set(map(lambda _: _.logicalCode, devs)): return JsonErrorResponse(description='非法操作!!! 无法操作其他人的设备') # 创建订单 record = create_dealer_charge_order_for_disable_ad(dealer, devList) if record: return JsonResponse({'result': 1, 'description': u'创建订单成功', 'payload':{'orderNo':record.orderNo}}) else: return JsonErrorResponse(u'创建订单异常失败') @error_tolerate(logger=logger, nil=JsonErrorResponse(u'未知错误')) @permission_required(ROLE.dealer, ROLE.subaccount) def getServerFunction(request): payload = json.loads(request.body) lc = payload.get("logicalCode") if isinstance(lc, list) and len(lc): lc = lc[0] else: raise JsonErrorResponse(description=u"无效的设备编号") dev = Device.get_dev_by_l(lc) # type: DeviceDict if not dev: return JsonResponse({'result': 0, 'description': u'未找到该设备', 'payload': {}}) setConf = dev.deviceAdapter.get_server_setting() if setConf is None: return JsonResponse({'result': 0, 'description': u'您的设备类型不支持此操作哦', 'payload': {}}) else: return JsonResponse({'result': 1, 'description': u'', 'payload': setConf}) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'未知错误')) @permission_required(ROLE.dealer, ROLE.subaccount) def setServerFunction(request): payload = json.loads(request.body) # 去掉多余的参数 payload.pop('groupId', None) logicalCodes = payload.pop('logicalCode') if len(logicalCodes) > 1: dev = Device.get_dev_by_l(logicalCodes[0]) # type: DeviceDict payload = { 'operator': { 'id': str(request.user.id), 'role': request.user.role, 'username': request.user.username }, 'logicalCodes': logicalCodes, 'payload': payload, 'ownerId': dev.ownerId, 'devTypeCode': dev.devTypeCode, 'operationId': 'server_setting_{}_{}'.format(str(request.user.id), int(time.time())) } from taskmanager.mediator import task_caller task_caller('batch_set_server_settings', **payload) return JsonResponse({'result': 1, 'description': None, 'payload': {'operationId': payload['operationId']}}) else: device = Device.get_dev_by_l(logicalCodes[0]) # type: DeviceDict if not device: return JsonResponse({'result': 0, 'description': u'没有找到设备', 'payload': {}}) if device.ownerId != str(request.user.bossId): return JsonResponse({'result': 0, 'description': u'非法操作', 'payload': {}}) try: before = device.deviceAdapter.get_server_setting() device.deviceAdapter.set_server_setting(payload) OperatorLog.log_dev_operation( operator=request.user, device=device, operator_name='setServerSetting', content={ 'before': before, 'after': payload }) except InvalidParameter as e: return JsonErrorResponse(description=e.message) return JsonOkResponse() @error_tolerate(logger=logger, nil=JsonErrorResponse(u'未知错误')) @permission_required(ROLE.dealer, ROLE.subaccount) def getDealerPreferentialRechargeTemplate(request): ownerId = str(request.user.bossId) pageIndex = int(request.GET.get('pageIndex', 1)) pageSize = int(request.GET.get('pageSize', 10)) templateType = str(request.GET.get('type')) dealer = Dealer.objects(id=ownerId).first() if dealer is None: return JsonErrorResponse(description=u'未知错误') if templateType == 'preferentialRechargeTemplate': dataList = dealer.templateSet.rechargeDiscount elif templateType == 'cardPreferentialRechargeTemplate': dataList = dealer.templateSet.cardRechargeDiscount else: return JsonErrorResponse(description=u"未知错误") payload = { "total": len(dataList), "dataList": dataList[(pageIndex - 1) * pageSize:pageIndex * pageSize] } return JsonOkResponse(payload=payload) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'未知错误')) @permission_required(ROLE.dealer, ROLE.subaccount) def getDealerPreferentialRechargeTemplateById(request): ownerId = str(request.user.bossId) templateId = request.GET.get('id', None) templateType = str(request.GET.get('type')) if templateId is None: return JsonErrorResponse(description=u'未知错误') dealer = Dealer.objects(id=ownerId).first() if dealer is None: return JsonErrorResponse(description=u'未知错误') if templateType == 'preferentialRechargeTemplate': dataList = dealer.templateSet.rechargeDiscount elif templateType == 'cardPreferentialRechargeTemplate': dataList = dealer.templateSet.cardRechargeDiscount else: return JsonErrorResponse(description=u"未知错误") payload = [_ for _ in dataList if int(templateId) == int(_['id'])][0] return JsonOkResponse(payload=payload) @error_tolerate(logger=logger, nil=JsonErrorResponse(u'未知错误')) @permission_required(ROLE.dealer, ROLE.subaccount) def editDealerPreferentialRechargeTemplate(request): ownerId = str(request.user.bossId) tempData = json.loads(request.body) templateType = tempData['type'] del tempData['type'] dealer = Dealer.objects(id=ownerId).first() if dealer is None: return JsonErrorResponse(description=u'未知错误') if templateType == 'preferentialRechargeTemplate': tempDataList = dealer.templateSet.rechargeDiscount elif templateType == 'cardPreferentialRechargeTemplate': tempDataList = dealer.templateSet.cardRechargeDiscount else: return JsonErrorResponse(description=u"未知错误") for _ in tempDataList: if int(_['id']) == int(tempData['id']): tempDataList.remove(_) tempDataList.append(tempData) if templateType == 'preferentialRechargeTemplate': dealer.templateSet.rechargeDiscount = tempDataList else: dealer.templateSet.cardRechargeDiscount = tempDataList dealer.save() return JsonOkResponse() @error_tolerate(logger=logger, nil=JsonErrorResponse(u'未知错误')) @permission_required(ROLE.dealer, ROLE.subaccount) def addDealerPreferentialRechargeTemplate(request): ownerId = str(request.user.bossId) payload = json.loads(request.body) templateType = payload['type'] dealer = Dealer.objects(id=ownerId).first() if dealer is None: return JsonErrorResponse(description=u'未知错误') if templateType == 'preferentialRechargeTemplate': tempDataList = dealer.templateSet.rechargeDiscount elif templateType == 'cardPreferentialRechargeTemplate': tempDataList = dealer.templateSet.cardRechargeDiscount else: return JsonErrorResponse(description=u"未知错误") if len(tempDataList) == 0: tempId = 1 else: tempId = max(int(_['id']) for _ in tempDataList) + 1 temp = {} templateInfo = payload.get('templateInfo', []) templateName = payload.get('templateName', '') if not templateInfo or templateName == '': return JsonErrorResponse(description=u'套餐错误') for _ in templateInfo: _['coins'] = float(_['coins']) _['ruleId'] = _['payAmount'] temp.update({'templateName': templateName, 'templateInfo': templateInfo, 'id': tempId}) if templateType == 'preferentialRechargeTemplate': dealer.templateSet.rechargeDiscount.append(temp) else: dealer.templateSet.cardRechargeDiscount.append(temp) dealer.save() return JsonOkResponse() @error_tolerate(logger=logger, nil=JsonErrorResponse(u'未知错误')) @permission_required(ROLE.dealer, ROLE.subaccount) def deleteDealerPreferentialRechargeTemplate(request): ownerId = str(request.user.bossId) payload = json.loads(request.body) tempId = payload['id'] templateType = payload['type'] dealer = Dealer.objects(id=ownerId).first() if dealer is None: return JsonErrorResponse(description=u'未知错误') if templateType == 'preferentialRechargeTemplate': tempDataList = dealer.templateSet.rechargeDiscount elif templateType == 'cardPreferentialRechargeTemplate': tempDataList = dealer.templateSet.cardRechargeDiscount else: return JsonErrorResponse(description=u"未知错误") for _ in tempDataList: if int(_['id']) == int(tempId): tempDataList.remove(_) if templateType == 'preferentialRechargeTemplate': dealer.templateSet.rechargeDiscount = tempDataList else: dealer.templateSet.cardRechargeDiscount = tempDataList dealer.save() return JsonOkResponse() @error_tolerate(logger=logger, nil=JsonErrorResponse(u'未知错误')) @permission_required(ROLE.dealer, ROLE.subaccount) def editGroupsToPreferentialRechargeTemplate(request): ownerId = str(request.user.bossId) payload = json.loads(request.body) tempId = payload['id'] templateType = payload['type'] groupIds = [_['groupId'] for _ in payload['groupId']] dealer = Dealer.objects(id=ownerId).first() if dealer is None: return JsonErrorResponse(description=u'未知错误') tempData = dict() if templateType == 'preferentialRechargeTemplate': tempDataList = dealer.templateSet.rechargeDiscount elif templateType == 'cardPreferentialRechargeTemplate': tempDataList = dealer.templateSet.cardRechargeDiscount else: return JsonErrorResponse(description=u"未知错误") for _ in tempDataList: if int(_['id']) == int(tempId): tempData = _ break tempRule = dict() for _ in tempData['templateInfo']: tempRule.update({_['payAmount']: _['coins']}) if templateType == 'preferentialRechargeTemplate': for _ in Group.objects(id__in=groupIds): _.ruleDict = format_dot_key(tempRule) _.save() else: for _ in Group.objects(id__in=groupIds): _.cardRuleDict = format_dot_key(tempRule) _.save() GroupCacheMgr.invalid_group_cache(groupIds) return JsonOkResponse() @permission_required(ROLE.dealer, ROLE.subaccount) def getServiceFeePackage(request): logicalCode = request.GET.get('logicalCode') if not logicalCode: raise JsonErrorResponse(description=u'无效的设备编号') dev = Device.get_dev_by_l(logicalCode) # type: DeviceDict payload = dev.deviceAdapter.get_service_fee_info() return JsonResponse({'result': 1, 'description': '', 'payload': payload}) @permission_required(ROLE.dealer, ROLE.subaccount) def setServiceFeePackage(request): """ 设置服务费计费参数, 暂时不支持批量 :param request: :return: """ payload = json.loads(request.body) if 'billAsService' not in payload: return JsonErrorResponse(description=u'传入参数错误') logicalCode = payload.get("logicalCode") try: device = Device.get_dev_by_l(logicalCode) # type: DeviceDict device.deviceAdapter.set_service_fee_info(payload) except InvalidParameter as e: return JsonErrorResponse(description=e.message) return JsonOkResponse() @permission_required(ROLE.dealer) def interconnectionConfig(request): ownerId = str(request.user.bossId) pageIndex = int(request.GET.get('pageIndex', 1)) pageSize = int(request.GET.get('pageSize', 10)) searchKey = str(request.GET.get('searchKey', '')) swapFlagSearch = None if 'swapFlag' in request.GET: if request.GET.get('swapFlag') == 'false': swapFlagSearch = False else: swapFlagSearch = True dataList = [] groupIds = Group.get_group_ids_of_dealer(ownerId) groupList = Group.get_groups_by_group_ids(groupIds).values() groupList = natural_sort(groupList, 'groupName', False) for grp in groupList: if searchKey not in grp['groupName']: continue if swapFlagSearch is not None and swapFlagSearch != grp.get('swapFlag', False): continue if 'swapFlag' not in grp: grp['swapFlag'] = False elif grp['swapFlag']: swapInfo = SwapGroup.objects(groupId=grp['groupId']).first() if swapInfo is not None: grp['joinedTime'] = swapInfo.joinedTime.strftime('%Y-%m-%d %H:%M:%S') dataList.append(grp) return JsonResponse({ "result": 1, "description": None, 'payload': { "total": len(dataList), "dataList": dataList[(pageIndex - 1) * pageSize: pageIndex * pageSize] } }) @permission_required(ROLE.dealer) def interconnectionDetail(request): ownerId = str(request.user.bossId) groupId = request.GET.get('groupId', None) if groupId is None: return JsonErrorResponse(description=u"缺少参数") swapInfo = SwapGroup.objects(groupId=groupId).first() if swapInfo is None: return JsonOkResponse(payload={}) if ownerId != swapInfo.ownerId: return JsonErrorResponse(description=u"参数不一致") payload = { 'StationLng':swapInfo.lng, 'StationLat':swapInfo.lat, 'BusineHours':swapInfo.BusineHours, 'SiteGuide':swapInfo.SiteGuide, 'Construction':swapInfo.Construction, 'SupportOrder':swapInfo.SupportOrder, 'Pictures':[{'PicID':pic.PicID, 'IsCover':pic.IsCover, 'Url':pic.Url, 'title':pic.Title, 'Title':pic.TitleForShow} for pic in swapInfo.Pictures], 'MatchCars':swapInfo.MatchCars, 'ParkInfo':swapInfo.ParkInfo, 'StationStatus':swapInfo.StationStatus, 'ParkNums':swapInfo.ParkNums, 'originalAlternateFeeRemark':swapInfo.originalAlternateFeeRemark, 'alternateFeeRemark':swapInfo.alternateFeeRemark, 'originalDirectFeeRemark':swapInfo.originalDirectFeeRemark, 'directFeeRemark':swapInfo.directFeeRemark, 'PriceChargingInfo':[{'FeeTime':info.FeeTime, 'ElectricityFee':info.ElectricityFee, 'ServiceFee':info.ServiceFee} for info in swapInfo.PriceChargingInfo], 'DiscountPriceChargingInfo':[{'FeeTime':info.DiscountTime, 'ElectricityFee':info.DiscountElectricityFee, 'ServiceFee':info.DiscountServiceFee} for info in swapInfo.DiscountPriceChargingInfo], 'ElectricityFee':swapInfo.ElectricityFee, 'ServiceFee':swapInfo.ServiceFee, 'ParkFee':swapInfo.ParkFee, 'chargeTagList':[{'tagId':tag.tagId, 'tagType':tag.tagType, 'tagDesc':tag.tagDesc, 'tagOrder':tag.tagOrder, 'tagName':tag.tagName, 'color':tag.color} for tag in swapInfo.ChargeTagList], 'StationTel':swapInfo.StationTel, 'ServiceTel':swapInfo.ServiceTel, 'Payment':swapInfo.Payment, 'Remark':swapInfo.Remark, 'RightTag':swapInfo.RightTag, 'StationType':swapInfo.StationType } if swapInfo.swapFlag: payload.update({'joinedTime':swapInfo.joinedTime.strftime('%Y-%m-%d %H:%M:%S')}) return JsonOkResponse(payload=payload) @permission_required(ROLE.dealer) def uploadSwapPicture(request): files = request.FILES.getlist('file') groupId = request.POST.get('groupId', None) tail = request.POST.get('tail', None) if groupId is None: return JsonErrorResponse(description=u"缺少参数") if not len(files): return JsonResponse({'result': 0, 'description': u'未找到上传的商品图片,请重新试试', 'payload': {}}) uploader = SwapGroupPicFileUploader(inputFile=request.FILES.getlist('file')[0], uploadType='swap', groupId=groupId, tail=tail) logger.info('[uploadItemPic] %s is being used' % (repr(uploader),)) try: outputUrl = uploader.upload() return JsonResponse({'result': 1, 'description': '', 'payload': {'Url':outputUrl}}) except InvalidFileSize, e: logger.info( '%s(id=%s)\'s uploaded file reached limit' % (request.user.__class__.__name__, str(request.user.id),)) return JsonResponse({'result': 0, 'description': e.message, 'payload': {}}) except InvalidFileName, e: logger.info( '%s(id=%s)\'s uploaded file name is not legal' % (request.user.__class__.__name__, str(request.user.id),)) return JsonResponse({'result': 0, 'description': e.message, 'payload': {}}) @permission_required(ROLE.dealer) def getFeeMode(request): payload = request.POST logicalCode = payload.get("logicalCode") devObj = Device.objects.get(logicalCode=logicalCode) if devObj.ownerId != str(request.user.id): return JsonErrorResponse(description=u"参数错误") feeMode = devObj.otherConf.get('feeMode', {}) timeRateList = [] shiduan = feeMode.get('shiduan', '000000000000000000000000000000000000000000000000') for ii in range(48): startHour = 0 + ii / 2 startMin = '00' if ii % 2 == 0 else '30' endHour = startHour if ii % 2 == 0 else startHour + 1 endMin = '30' if ii % 2 == 0 else '00' startTime = '%02d:%s' % (startHour, startMin) endTime = '%02d:%s' % (endHour, endMin) timeRateList.append({'startTime':startTime, 'endTime':endTime, 'rate':shiduan[ii]}) result = {'top_price_rate':feeMode.get('jianFee', 0), 'top_price_service_rate':feeMode.get('jianServe', 0), 'peak_price_rate':feeMode.get('fengFee', 0), 'peak_price_service_rate':feeMode.get('fengServe', 0), 'normal_price_rate':feeMode.get('pingFee', 0), 'normal_price_service_rate':feeMode.get('pingServe', 0), 'valley_price_rate':feeMode.get('guFee', 0), 'valley_price_service_rate':feeMode.get('guServe', 0), 'jishunScale':feeMode.get('jishunScale', 0), 'timeRateList':timeRateList} return result @permission_required(ROLE.dealer) def setFeeMode(request): payload = request.POST logicalCode = payload.get("logicalCode") devObj = Device.objects.get(logicalCode=logicalCode) if devObj.ownerId != str(request.user.id): return JsonErrorResponse(description=u"参数错误") feeMode = devObj.otherConf.get('feeMode', {}) feeMode['jianFee'] = float(request.POST.get('top_price_rate')) feeMode['jianServe'] = float(request.POST.get('top_price_service_rate')) feeMode['fengFee'] = float(request.POST.get('peak_price_rate')) feeMode['fengServe'] = float(request.POST.get('peak_price_service_rate')) feeMode['pingFee'] = float(request.POST.get('normal_price_rate')) feeMode['pingServe'] = float(request.POST.get('normal_price_service_rate')) feeMode['guFee'] = float(request.POST.get('valley_price_rate')) feeMode['guServe'] = float(request.POST.get('valley_price_service_rate')) feeMode['jishunScale'] = float(request.POST.get('jishunScale', 0)) shiduan = '' for ii in range(48): startHour = 0 + ii / 2 startMin = '00' if ii % 2 == 0 else '30' endHour = startHour if ii % 2 == 0 else startHour + 1 endMin = '30' if ii % 2 == 0 else '00' startTime = '%02d:%s' % (startHour, startMin) endTime = '%02d:%s' % (endHour, endMin) print startTime, endTime harfHourValue = '0' for conf in request.POST.get('timeRateList'): if startTime >= conf['startTime'] and endTime <= conf['endTime']: harfHourValue = conf['rate'] break else: continue shiduan += harfHourValue feeMode['shiduan'] = shiduan try: devObj.save() except Exception, e: return JsonResponse({"result": 2, "description": "配置失败,请重试"}) return JsonOkResponse() @permission_required(ROLE.dealer) def setGroupSwapFlag(request): ownerId = str(request.user.bossId) groupId = request.POST.get('groupId', None) if groupId is None: return JsonErrorResponse(description=u"缺少参数") swapFalg = request.POST.get('swapFlag', False) success, description, groupId = Group.update_group(groupId, swapFalg=swapFalg) SwapGroup.get_collection().update({'groupId':groupId}, {'$set':{'swapFlag':swapFalg}}) return JsonOkResponse() if success else JsonErrorResponse(description=description, payload={'groupId': groupId}) @permission_required(ROLE.dealer) def saveInterconnectionDetail(request): ownerId = str(request.user.bossId) data = json.loads(request.body) groupId = data.get('groupId', None) if groupId is None: return JsonErrorResponse(description=u"缺少参数") group = Group.get_group(groupId) if group is None: return JsonErrorResponse(description=u"参数错误") swapInfo = SwapGroup.objects(groupId=groupId).first() if swapInfo is None: swapInfo = SwapGroup(groupId=groupId, stationID=SwapGroup.make_stationID(groupId)) lng, lat = SwapGroup.bd09_to_gcj02(data['StationLng'], data['StationLat']) swapInfo.ownerId = ownerId swapInfo.swapFlag = data.get('swapFlag', False) swapInfo.location = {'type':'Point', 'coordinates':[data['StationLng'], data['StationLat']]} swapInfo.gcjLng = lng swapInfo.gcjLat = lat swapInfo.BusineHours = data['BusineHours'] swapInfo.SiteGuide = data['SiteGuide'] swapInfo.Construction = data['Construction'] swapInfo.SupportOrder = int(data['SupportOrder']) ii = 0 picList = [] for pic in data['Pictures']: ii += 1 picList.append(Picture(ii, pic['IsCover'], pic['Url'], pic['title'], pic['Title'])) swapInfo.Pictures = picList swapInfo.MatchCars = data['MatchCars'] swapInfo.ParkInfo = data['ParkInfo'] swapInfo.StationStatus = data['StationStatus'] swapInfo.ParkNums = data['ParkNums'] swapInfo.originalAlternateFeeRemark = data['originalAlternateFeeRemark'] swapInfo.alternateFeeRemark = data['alternateFeeRemark'] swapInfo.originalDirectFeeRemark = data['originalDirectFeeRemark'] swapInfo.directFeeRemark = data['directFeeRemark'] swapInfo.PriceChargingInfo = [PriceCharging(info['FeeTime'], info['ElectricityFee'], info['ServiceFee']) for info in data['PriceChargingInfo']] swapInfo.DiscountPriceChargingInfo = [DiscountPriceCharging(info['FeeTime'], info['ElectricityFee'], info['ServiceFee']) for info in data['DiscountPriceChargingInfo']] swapInfo.ElectricityFee = data['ElectricityFee'] swapInfo.ServiceFee = data['ServiceFee'] swapInfo.ParkFee = data['ParkFee'] swapInfo.ChargeTagList = [ChargeTag(0, tag['tagType'], tag['tagDesc'], tag['tagOrder'], tag['tagName'], tag['color']) for tag in data.get('chargeTagList', [])] swapInfo.StationTel = data['StationTel'] swapInfo.ServiceTel = data['ServiceTel'] swapInfo.Payment = data['Payment'] swapInfo.SupportOrder = data['SupportOrder'] swapInfo.Remark = data['Remark'] swapInfo.RightTag = data['RightTag'] swapInfo.StationType = data['StationType'] if swapInfo.swapFlag: swapInfo.joinedTime = datetime.datetime.now() try: swapInfo.save() except Exception, e: return JsonResponse({"result": 2, "description": "配置失败,请重试"}) Group.update_group(group_id=groupId, swapFlag=swapInfo.swapFlag) SwapGroup.recount_devnum(groupId) return JsonOkResponse() @permission_required(ROLE.dealer) def getInterconnectionDisclaimer(request): payload = { 'version': '1.01', 'content': '

 互联互通用户协议


一、【首部及导言】
欢迎您使用充电桩互联互通协议!
本系统互联互通协议遵从国家关于充电桩互联互通的协议《T/CEC中国电力企业联合会标准》,关于协议的具体规则,可以联系我们技术支持。
二、【协议的范围】
1、本协议是您与我们充电桩管理平台(以下简称我们)之间关于您使用互联互通功能服务所订立的协议。

2、本协议的用户,只指通过我们充电桩管理平台,管理设备的运营商组织和个人,都属于我们的用户。

三、【服务内容】
1、本协议服务的设备,只有当您打开互联互通开关后,设备才会加入互联互通。关闭开关后,将会地址地址组下的互联互通功能。

\

2、互联互通主要是通过第三方的APP、小程序、H5应用,能够查询到您旗下的设备,并能够通过第三方能够启动充电,并根据账单进行结算。

\ 3、互联互通的第三方APP,包括不限于诸如:快电、小桔充电、恒大星脉等等第三方平台,而且每个第三方平台会存在不同的服务区别,包括通过第三方使用充电桩需要提取的佣金、费用结算方式、营销活动推广费用、提现费率等等,具体\ 情况,在互联互通开放时,请您和我们技术支持沟通确认。

四、【服务要求】

1、您提供的设备,包括交流桩和直流桩,能够保证设备的安全性、可靠性、可用性,以及设备本身的数据统计准确,应当尽量避免因此引起的纠纷。因此而引起的纠纷,我们要求由您负责并处理。\

2、您提供配置的设备信息,包括互联互通的信息,应当准确并符合实际,避免出现消费者对平台进行投诉,因此产生的投诉,将有您负责,并且我们将有权对不符合实际情况的互联互通进行关闭,以保障充电用户的权益。\

3、产生的一些售后处理,可能需要您和我们一起处理,我们希望您保持联系方式的畅通,以保证服务质量。如果用户或者第三方平台投诉到我们这里,我们却多次无法联系到您,我们有权强制禁用您的互联互通功能。

\

五、【售后及其他】

1、平台的相关售后,包括您使用的后台、互联互通,由我们负责,如有疑问,可以直接联系我们。\

2、设备相关售后,诸如设备故障、设备维修等,导致的互联互通服务售后,由您负责,我们售后可能会联系您,需要您保持联系方式畅通。


' } return JsonOkResponse(payload=payload) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer, ROLE.subaccount) def getCustomizePoint(request): logicalCode = request.GET.get('logicalCode') dev = Device.get_dev_by_l(logicalCode) if dev is None: return JsonErrorResponse(description=u"参数错误") box = ActionDeviceBuilder.create_action_device(dev) unit = box.get_customize_score_unit() if unit is None: return JsonResponse({'result': 0, 'description': "", 'payload': {}}) return JsonResponse({'result': 0, 'description': "", 'payload': [unit]}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer, ROLE.subaccount) def onCustomizePoint(request): logicalCode = request.POST.get('logicalCode') pointNum = request.POST.get('time') portList = json.loads(request.POST.get('attachParas')).get('chargeIndex') openId = request.user.managerialOpenId dev = Device.get_dev_by_l(logicalCode) if dev is None: return JsonErrorResponse(description=u"参数错误") box = ActionDeviceBuilder.create_action_device(dev) address = Group.get_group(dev['groupId'])['address'] groupName = Group.get_group(dev['groupId'])['groupName'] errorList = [] errdesc = '' for port in portList: try: box.start_customize_point(pointNum, openId, int(port)) UpscoreRecord( logicalCode=dev['logicalCode'], devNo=dev['devNo'], ownerId=str(request.user.id), time=datetime.datetime.now(), score=pointNum, address=address, groupName=groupName, devType=dev['devType']['name'], type="", remark=u'自定义上分:%s%s' % (pointNum, request.POST.get('unit')) ).save() except ServiceException, e: errorList.append(port) errdesc = ',' + e.result.get('description') continue except Exception, e: errorList.append(port) continue if errorList: return JsonResponse({'result': 0, 'description': u"出现上分失败" + errdesc, 'payload': {'errorList':errorList}}) return JsonResponse({'result': 0, 'description': u"上分成功", 'payload': {'errorList':errorList}}) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def getPolicyInfos(request): lc = request.GET.get('logicalCode') dev = Device.get_dev_by_l(lc) box = ActionDeviceBuilder.create_action_device(dev) result = box.get_policy_infos() return JsonOkResponse(payload=result) @error_tolerate(nil=DefaultJsonErrorResponse) @permission_required(ROLE.dealer) def setPolicyInfos(request): payload = json.loads(request.body) lc = payload.get('logicalCode') dev = Device.get_dev_by_l(lc) box = ActionDeviceBuilder.create_action_device(dev) try: box.set_policy_infos(payload) except ServiceException, e: return JsonErrorResponse(description=e.result.get('description')) return JsonOkResponse(description=u'计费配置保存成功') @error_tolerate(logger = logger) def refundOrderNotifier(request, pay_app_type): """ 退款回调接口(经销商目前只有微信和京东聚合支付微信部分) :param request: :param pay_app_type: :return: """ assert pay_app_type in PayAppType.choices(), 'not support this pay app type({})'.format(pay_app_type) notifier_cls = RefundManager().get_notifier(pay_app_type) response = notifier_cls(request, lambda filter: RefundDealerRechargeRecord.get_record(**filter)).do( refund_post_pay) return response