|
@@ -0,0 +1,837 @@
|
|
|
|
|
+# -*- coding: utf-8 -*-
|
|
|
|
|
+#!/usr/bin/env python
|
|
|
|
|
+
|
|
|
|
|
+"""
|
|
|
|
|
+ web.ad.views
|
|
|
|
|
+ ~~~~~~~~~
|
|
|
|
|
+"""
|
|
|
|
|
+
|
|
|
|
|
+import datetime
|
|
|
|
|
+import itertools
|
|
|
|
|
+import logging
|
|
|
|
|
+import random
|
|
|
|
|
+import traceback
|
|
|
|
|
+
|
|
|
|
|
+import simplejson as json
|
|
|
|
|
+import xmltodict
|
|
|
|
|
+from bson.objectid import ObjectId
|
|
|
|
|
+from django.core.handlers.wsgi import WSGIRequest
|
|
|
|
|
+from django.views.decorators.http import require_POST, require_GET
|
|
|
|
|
+from mongoengine.errors import NotUniqueError
|
|
|
|
|
+from typing import List, Union, Optional, Iterable, cast, TYPE_CHECKING, Dict
|
|
|
|
|
+
|
|
|
|
|
+from apilib import utils_datetime
|
|
|
|
|
+from apilib.utils import flatten
|
|
|
|
|
+from apilib.utils_datetime import dt_to_timestamp, date_to_datetime_floor, date_to_datetime_ceiling
|
|
|
|
|
+from apilib.utils_json import JsonResponse
|
|
|
|
|
+from apps import serviceCache
|
|
|
|
|
+from apps.web.ad import OfflineTaskType, MyJsonOkResponse
|
|
|
|
|
+from apps.web.ad.models import Advertisement, AdRecord, Advertiser, AdWord, AliAdLog
|
|
|
|
|
+from apps.web.ad.utils import (get_available_ads_by_user)
|
|
|
|
|
+from apps.web.agent.models import Agent
|
|
|
|
|
+from apps.web.common.validation import PASSWORD_RE
|
|
|
|
|
+from apps.web.core import ROLE
|
|
|
|
|
+from apps.web.core.db import prepare_conditions, prepare_query
|
|
|
|
|
+from apps.web.core.exceptions import InvalidPermission
|
|
|
|
|
+from apps.web.core.models import OfflineTask
|
|
|
|
|
+from apps.web.core.utils import DefaultJsonErrorResponse, parse_json_payload
|
|
|
|
|
+from apps.web.core.utils import JsonErrorResponse, JsonOkResponse
|
|
|
|
|
+from apps.web.dealer.models import Dealer
|
|
|
|
|
+from apps.web.device.models import Device
|
|
|
|
|
+from apps.web.device.models import Group
|
|
|
|
|
+from apps.web.management.models import Manager
|
|
|
|
|
+from apps.web.user.models import MyUser, Redpack
|
|
|
|
|
+from apps.web.user.utils import RedpackBuilder
|
|
|
|
|
+from apps.web.utils import advertiser_login, \
|
|
|
|
|
+ is_advertiser, is_manager, is_advertisement
|
|
|
|
|
+from apps.web.utils import error_tolerate, permission_required
|
|
|
|
|
+from taskmanager.mediator import task_caller
|
|
|
|
|
+
|
|
|
|
|
+if TYPE_CHECKING:
|
|
|
|
|
+ from apps.web.common.models import UserSearchable
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+logger = logging.getLogger(__name__)
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+@error_tolerate(nil = DefaultJsonErrorResponse)
|
|
|
|
|
+@require_POST
|
|
|
|
|
+@permission_required(ROLE.manager, ROLE.advertiser)
|
|
|
|
|
+def getAdPreAllocatedDevice(request):
|
|
|
|
|
+ # type:(WSGIRequest)->JsonResponse
|
|
|
|
|
+
|
|
|
|
|
+ """
|
|
|
|
|
+ 根据多种多样的查询条件获取供分配设备列表List[Dict]
|
|
|
|
|
+
|
|
|
|
|
+ {"devCondition":[{"agentIdList":[],"dealerIdList":[],"groupIdList":[]}],"addressTypeList":[],"devTypeList":[]}
|
|
|
|
|
+
|
|
|
|
|
+ get_devices query =
|
|
|
|
|
+ dealerIdList => Device.objects(ownerId__in=dealerIdList)
|
|
|
|
|
+ | agentIdList => Device.objects(Dealer.objects(agentId__=agentIdList)
|
|
|
|
|
+ | groupIdList => Device.objects(groupId__in=groupIdList)
|
|
|
|
|
+
|
|
|
|
|
+ devices.filter( _ => _.devType in devTypeList & _ => _.group.addressType in addressTypeList)
|
|
|
|
|
+
|
|
|
|
|
+ return [ { 'logicalCode': x, 'devType': 'y' } ]
|
|
|
|
|
+ TODO:
|
|
|
|
|
+ 优化方向,
|
|
|
|
|
+ 0. 优化解析过程
|
|
|
|
|
+ 1. 建立query解析缓存
|
|
|
|
|
+ 2. 运用mongodb pipeline
|
|
|
|
|
+ 3. 本地化部分数据(将厂商ID绑定到设备端,解绑记得清除,将地址类型也绑定到设备,解绑记得清除)
|
|
|
|
|
+ :param request:
|
|
|
|
|
+ :return:
|
|
|
|
|
+ :rtype: JsonResponse
|
|
|
|
|
+ """
|
|
|
|
|
+ query = json.loads(request.body)
|
|
|
|
|
+
|
|
|
|
|
+ currentUser = request.user #type: cast(Union[Manager, Advertiser])
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ if is_manager(currentUser):
|
|
|
|
|
+ devCondition, addressTypeList, devTypeList = query['devCondition'], query['addressTypeList'], query['devTypeList']
|
|
|
|
|
+ elif is_advertiser(currentUser):
|
|
|
|
|
+ devCondition, addressTypeList, devTypeList = currentUser.preAllocatedDeviceConditions, query['addressTypeList'], query['devTypeList']
|
|
|
|
|
+ else:
|
|
|
|
|
+ raise InvalidPermission(u'只有广告主或厂商才能查询广告投放设备')
|
|
|
|
|
+
|
|
|
|
|
+ hasDevCondition = bool(len(list(itertools.ifilter(lambda _ : _ != [], flatten(_.values() for _ in devCondition)))))
|
|
|
|
|
+ hasAddressTypeList = bool(len(addressTypeList))
|
|
|
|
|
+ hasDevTypeList = bool(len(devTypeList))
|
|
|
|
|
+
|
|
|
|
|
+ def imerge_dicts(iterable):
|
|
|
|
|
+ """
|
|
|
|
|
+ Given any number of dicts, shallow copy and merge into a new dict,
|
|
|
|
|
+ precedence goes to key value pairs in latter dicts.
|
|
|
|
|
+ """
|
|
|
|
|
+ result = {}
|
|
|
|
|
+ for dictionary in iterable:
|
|
|
|
|
+ result.update(dictionary)
|
|
|
|
|
+ return result
|
|
|
|
|
+
|
|
|
|
|
+ to_query = lambda _ : imerge_dicts( x.to_query(None) for x in prepare_conditions(_) )
|
|
|
|
|
+
|
|
|
|
|
+ def acc_or_append(q, data):
|
|
|
|
|
+ """
|
|
|
|
|
+
|
|
|
|
|
+ :param q: [{}]
|
|
|
|
|
+ :param data:
|
|
|
|
|
+ :return:
|
|
|
|
|
+ """
|
|
|
|
|
+ if not len(q):
|
|
|
|
|
+ q.append(data)
|
|
|
|
|
+ else:
|
|
|
|
|
+ for item in q:
|
|
|
|
|
+
|
|
|
|
|
+ if data == item: break
|
|
|
|
|
+
|
|
|
|
|
+ elif item['field'] == data['field'] and item['operator'] == data['operator']:
|
|
|
|
|
+ item['value'] = list(set(item['value'] + data['value']))
|
|
|
|
|
+ break
|
|
|
|
|
+ else:
|
|
|
|
|
+ q.append(data)
|
|
|
|
|
+ break
|
|
|
|
|
+
|
|
|
|
|
+ def parse_devCondition(conditions):
|
|
|
|
|
+ """
|
|
|
|
|
+ :param conditions: [{..conditions}]
|
|
|
|
|
+ :return:
|
|
|
|
|
+ """
|
|
|
|
|
+ queries = {
|
|
|
|
|
+ 'device': [],
|
|
|
|
|
+ 'dealer': [],
|
|
|
|
|
+ 'group': []
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ for cond in conditions:
|
|
|
|
|
+ # 优先级 groupIdList > dealerIdList > agentIdList
|
|
|
|
|
+ if cond['groupIdList']:
|
|
|
|
|
+ acc_or_append(queries['group'], {"field": "_id", "operator": "in", "value": [ ObjectId(_) for _ in cond['groupIdList']] })
|
|
|
|
|
+ continue
|
|
|
|
|
+ elif cond['dealerIdList']:
|
|
|
|
|
+ acc_or_append(queries['group'], {"field": "ownerId", "operator": "in", "value": map(str, cond['dealerIdList']) })
|
|
|
|
|
+ continue
|
|
|
|
|
+ elif cond['agentIdList']:
|
|
|
|
|
+ acc_or_append(queries['dealer'], {"field": "agentId", "operator": "in", "value": cond['agentIdList']})
|
|
|
|
|
+ continue
|
|
|
|
|
+
|
|
|
|
|
+ return queries
|
|
|
|
|
+
|
|
|
|
|
+ #: 生成,拼装请求,延迟请求Device到最后, 减少IO
|
|
|
|
|
+ queries = parse_devCondition(devCondition)
|
|
|
|
|
+
|
|
|
|
|
+ #: 默认只能选择某厂商下的所有设备
|
|
|
|
|
+ #acc_or_append(queries['device'],{"field": "managerId", "operator": "", "value": managerId})
|
|
|
|
|
+
|
|
|
|
|
+ #: 不选择的时候,选择所有组的设备
|
|
|
|
|
+ if not hasDevCondition:
|
|
|
|
|
+
|
|
|
|
|
+ if is_manager(currentUser):
|
|
|
|
|
+ agentIds = [ str(_['_id']) for _ in Agent.get_collection().find({'managerId': str(currentUser.id)})]
|
|
|
|
|
+ acc_or_append(queries['dealer'], {"field": "agentId", "operator": "in", "value": agentIds})
|
|
|
|
|
+
|
|
|
|
|
+ elif is_advertiser(currentUser):
|
|
|
|
|
+ agentIds = [ str(_.id) for _ in Agent.objects(managerId=currentUser.managerId) ]
|
|
|
|
|
+ acc_or_append(queries['dealer'], {"field": "agentId", "operator": "in", "value": agentIds})
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ if hasDevTypeList:
|
|
|
|
|
+ acc_or_append(queries['device'], {"field": "devType.id", "operator": "in", "value": devTypeList})
|
|
|
|
|
+
|
|
|
|
|
+ if hasAddressTypeList:
|
|
|
|
|
+ acc_or_append(queries['group'], {"field": "addressType", "operator": "in", "value": addressTypeList})
|
|
|
|
|
+
|
|
|
|
|
+ if queries['dealer']:
|
|
|
|
|
+ dealers = [ str(_['_id']) for _ in Dealer.get_collection().find(to_query(queries['dealer']), {'_id': 1}) ]
|
|
|
|
|
+ acc_or_append(queries['group'], {"field": "ownerId", "operator": "in", "value": dealers})
|
|
|
|
|
+
|
|
|
|
|
+ if queries['group']:
|
|
|
|
|
+ groups = [ str(_['_id']) for _ in Group.get_collection().find(to_query(queries['group']), {'_id': 1}) ]
|
|
|
|
|
+ acc_or_append(queries['device'], {"field": "groupId", "operator": "in", "value": groups})
|
|
|
|
|
+
|
|
|
|
|
+ if queries['device']:
|
|
|
|
|
+
|
|
|
|
|
+ dataList = [ {'logicalCode': _['logicalCode'], 'devTypeName' : _['devType'].get('name')} for _ in
|
|
|
|
|
+ Device.get_collection()
|
|
|
|
|
+ .find(to_query(queries['device']), {'logicalCode': 1, 'devType.name': 1})]
|
|
|
|
|
+
|
|
|
|
|
+ return JsonResponse({'result': 1, 'payload': {'dataList': dataList}})
|
|
|
|
|
+
|
|
|
|
|
+ return JsonResponse({'result': 1, 'payload': {'dataList': []}})
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+###: 广告增删查改
|
|
|
|
|
+
|
|
|
|
|
+@require_GET
|
|
|
|
|
+@error_tolerate(nil = DefaultJsonErrorResponse)
|
|
|
|
|
+@permission_required(ROLE.manager, ROLE.advertisement, ROLE.advertiser)
|
|
|
|
|
+def getAdList(request):
|
|
|
|
|
+ # type:(WSGIRequest)->JsonResponse
|
|
|
|
|
+ """
|
|
|
|
|
+ 获取广告列表
|
|
|
|
|
+ :param request:
|
|
|
|
|
+ :return:
|
|
|
|
|
+ """
|
|
|
|
|
+
|
|
|
|
|
+ return JsonResponse({'result': 1, 'description': '', 'payload': {'total': 0, 'dataList': []}})
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+@require_GET
|
|
|
|
|
+@error_tolerate(nil=JsonErrorResponse(u'获取广告分配设备列表失败'))
|
|
|
|
|
+@permission_required(ROLE.manager, ROLE.advertiser)
|
|
|
|
|
+def getDevListByAd(request):
|
|
|
|
|
+ # type:(WSGIRequest)->JsonResponse
|
|
|
|
|
+
|
|
|
|
|
+ """
|
|
|
|
|
+ 为了加快广告加载速度,不默认返回设备列表,只有在用户点击广告的时候才会请求设备列表
|
|
|
|
|
+ :param request:
|
|
|
|
|
+ :return:
|
|
|
|
|
+ """
|
|
|
|
|
+ adId = request.GET.get('adId')
|
|
|
|
|
+ devList = Advertisement.get_by_adId(adId=adId).devList
|
|
|
|
|
+ return JsonResponse({'result': 1, 'description': '', 'payload': {'total': len(devList), 'dataList': devList }})
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+@require_POST
|
|
|
|
|
+@error_tolerate(nil = JsonErrorResponse(u'添加广告失败'))
|
|
|
|
|
+@permission_required(ROLE.manager, ROLE.advertiser)
|
|
|
|
|
+def addAd(request):
|
|
|
|
|
+ # type:(WSGIRequest)->JsonResponse
|
|
|
|
|
+ """
|
|
|
|
|
+ 添加广告
|
|
|
|
|
+ 广告主和厂商都可以添加广告
|
|
|
|
|
+ 广告主只可配置 publicAdAvailable的广告主
|
|
|
|
|
+ :param request:
|
|
|
|
|
+ :return:
|
|
|
|
|
+ """
|
|
|
|
|
+ return JsonResponse({'result': 1, 'description': '', 'payload': {}})
|
|
|
|
|
+
|
|
|
|
|
+@require_POST
|
|
|
|
|
+@error_tolerate(nil = JsonErrorResponse(u'编辑广告失败'))
|
|
|
|
|
+@permission_required(ROLE.manager, ROLE.advertiser)
|
|
|
|
|
+def editAd(request):
|
|
|
|
|
+ # type:(WSGIRequest)->JsonResponse
|
|
|
|
|
+ """
|
|
|
|
|
+ 编辑广告
|
|
|
|
|
+ :param request:
|
|
|
|
|
+ :return:
|
|
|
|
|
+ """
|
|
|
|
|
+ return JsonResponse({'result': 1, 'description': '', 'payload': {}})
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+@require_POST
|
|
|
|
|
+@error_tolerate(nil = JsonErrorResponse(u'删除广告失败'))
|
|
|
|
|
+@permission_required(ROLE.manager, ROLE.advertiser)
|
|
|
|
|
+def deleteAd(request):
|
|
|
|
|
+ # type:(WSGIRequest)->JsonResponse
|
|
|
|
|
+ """
|
|
|
|
|
+ 删除广告
|
|
|
|
|
+ :param request:
|
|
|
|
|
+ :return:
|
|
|
|
|
+ """
|
|
|
|
|
+ return JsonResponse({'result': 1, 'description': '', 'payload': {}})
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+###: 各种过滤器
|
|
|
|
|
+
|
|
|
|
|
+@error_tolerate(nil = JsonErrorResponse(u'获取经销商列表失败'))
|
|
|
|
|
+@permission_required(ROLE.manager)
|
|
|
|
|
+def getDealerList(request):
|
|
|
|
|
+ # type:(WSGIRequest)->JsonResponse
|
|
|
|
|
+ """
|
|
|
|
|
+ 获取经销商列表
|
|
|
|
|
+ :param request:
|
|
|
|
|
+ :return:
|
|
|
|
|
+ """
|
|
|
|
|
+ agentId = request.GET.get('agentId', None)
|
|
|
|
|
+ if agentId is None:
|
|
|
|
|
+ return JsonResponse({'result': 0, 'description': u'请传入正确的参数', 'payload': {}})
|
|
|
|
|
+ dealers = [{'value': str(dealer.id), 'label': dealer.nickname} for dealer in Dealer.objects(agentId = str(agentId))]
|
|
|
|
|
+ return JsonResponse({'result': 1, 'description': '', 'payload': dealers})
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+@error_tolerate(nil = JsonErrorResponse(u'获取地址列表失败'))
|
|
|
|
|
+@permission_required(ROLE.manager)
|
|
|
|
|
+def getAddressList(request):
|
|
|
|
|
+ # type:(WSGIRequest)->JsonResponse
|
|
|
|
|
+ """
|
|
|
|
|
+ dealer->group.address
|
|
|
|
|
+ :param request:
|
|
|
|
|
+ :return:
|
|
|
|
|
+ """
|
|
|
|
|
+ dealerId = request.GET.get('id')
|
|
|
|
|
+ groupIds = Group.get_group_ids_of_dealer(dealerId)
|
|
|
|
|
+ groups = Group.get_groups_by_group_ids(groupIds)
|
|
|
|
|
+ if groups is None:
|
|
|
|
|
+ return JsonResponse({'result': 1, 'description': '', 'payload': []})
|
|
|
|
|
+ else:
|
|
|
|
|
+ groupIdAddressPair = [{'value': k, 'label': v['address']} for k, v in groups.iteritems()]
|
|
|
|
|
+ return JsonResponse({'result': 1, 'description': '', 'payload': groupIdAddressPair})
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+@error_tolerate(nil = JsonErrorResponse(u'获取设备列表失败'))
|
|
|
|
|
+@permission_required(ROLE.manager)
|
|
|
|
|
+def getDevList(request):
|
|
|
|
|
+ # type:(WSGIRequest)->JsonResponse
|
|
|
|
|
+ """
|
|
|
|
|
+ 广告系统获取设备列表
|
|
|
|
|
+ :param request:
|
|
|
|
|
+ :return:
|
|
|
|
|
+ """
|
|
|
|
|
+ groupId = request.GET.get('id')
|
|
|
|
|
+ deviceNos = Device.get_devNos_by_group([groupId])
|
|
|
|
|
+ devs = Device.get_dev_by_nos(deviceNos)
|
|
|
|
|
+ return JsonResponse(
|
|
|
|
|
+ {
|
|
|
|
|
+ 'result': 1,
|
|
|
|
|
+ 'description': '',
|
|
|
|
|
+ 'payload':
|
|
|
|
|
+ [
|
|
|
|
|
+ {'value': deviceNo, 'label': dev['logicalCode']}
|
|
|
|
|
+ for deviceNo, dev in devs.items()
|
|
|
|
|
+ ] if deviceNos else []
|
|
|
|
|
+ }
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+### 查看设备被分配的广告列表
|
|
|
|
|
+@error_tolerate(nil = JsonErrorResponse(u'查看设备广告列表失败'))
|
|
|
|
|
+@permission_required(ROLE.manager)
|
|
|
|
|
+def getDeviceAllocatedAds(request):
|
|
|
|
|
+ # type:(WSGIRequest)->JsonResponse
|
|
|
|
|
+ """
|
|
|
|
|
+
|
|
|
|
|
+ :param request:
|
|
|
|
|
+ :return:
|
|
|
|
|
+ """
|
|
|
|
|
+ logicalCode = request.GET.get('logicalCode')
|
|
|
|
|
+ return JsonResponse({'result': 1, 'description': '', 'payload': {'total': 0, 'dataList': []}})
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+### 广告数据报表
|
|
|
|
|
+@error_tolerate(nil = JsonErrorResponse(u'获取趋势列表失败'))
|
|
|
|
|
+@permission_required(ROLE.manager, ROLE.advertisement, ROLE.advertiser)
|
|
|
|
|
+def getAdFansTrend(request):
|
|
|
|
|
+ # type:(WSGIRequest)->JsonResponse
|
|
|
|
|
+ """
|
|
|
|
|
+ 获取广告效果趋势
|
|
|
|
|
+ :param request:
|
|
|
|
|
+ :return:
|
|
|
|
|
+ """
|
|
|
|
|
+
|
|
|
|
|
+ currentUser = request.user # type: cast(Union[Advertisement, Advertiser, Manager])
|
|
|
|
|
+
|
|
|
|
|
+ query = prepare_query(request.GET)
|
|
|
|
|
+ queryDict = query.raw
|
|
|
|
|
+
|
|
|
|
|
+ delta = query.attrs['dateTimeAdded__lte'] - query.attrs['dateTimeAdded__gte'] # type: datetime.timedelta
|
|
|
|
|
+ if delta.days > 90:
|
|
|
|
|
+ return JsonErrorResponse(u'只支持查询最远至90天前的数据')
|
|
|
|
|
+
|
|
|
|
|
+ #: TODO to refactor 引入校验schema
|
|
|
|
|
+ if 'adId' in queryDict:
|
|
|
|
|
+ queryDict['adId'] = int(queryDict['adId'])
|
|
|
|
|
+
|
|
|
|
|
+ if is_manager(currentUser):
|
|
|
|
|
+ queryDict['managerId'] = str(currentUser.id)
|
|
|
|
|
+ elif is_advertiser(currentUser):
|
|
|
|
|
+ queryDict['advertiserId'] = str(currentUser.id)
|
|
|
|
|
+ elif is_advertisement(currentUser):
|
|
|
|
|
+ queryDict['adId'] = int(currentUser.adId)
|
|
|
|
|
+
|
|
|
|
|
+ matchStage = {
|
|
|
|
|
+ 'createdDate':
|
|
|
|
|
+ {
|
|
|
|
|
+ '$gte': queryDict.pop('startTime'),
|
|
|
|
|
+ '$lte': queryDict.pop('endTime')
|
|
|
|
|
+ },
|
|
|
|
|
+ }
|
|
|
|
|
+ matchStage.update(queryDict)
|
|
|
|
|
+
|
|
|
|
|
+ projectStage = {
|
|
|
|
|
+ '_id': 0,
|
|
|
|
|
+ 'clicks': 1,
|
|
|
|
|
+ 'createdDate': 1,
|
|
|
|
|
+ 'fans': {'$cond': ['$converted', 1, 0]},
|
|
|
|
|
+ 'maleFans': '$features.sex.is_male',
|
|
|
|
|
+ 'femaleFans': '$features.sex.is_female'
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ projectStage.update(dict.fromkeys(AdRecord.filter_fields(), 1))
|
|
|
|
|
+
|
|
|
|
|
+ groupStage = {
|
|
|
|
|
+ '_id': '$createdDate',
|
|
|
|
|
+ 'clicks': {'$sum': '$clicks'},
|
|
|
|
|
+ 'fans': {'$sum': '$fans'},
|
|
|
|
|
+ 'show': {'$sum': '$clicks'},
|
|
|
|
|
+ 'maleFans': {'$sum': '$maleFans'},
|
|
|
|
|
+ 'femaleFans': {'$sum': '$femaleFans'}
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ aggregates = AdRecord.get_collection().aggregate(
|
|
|
|
|
+ [
|
|
|
|
|
+ {'$project': projectStage},
|
|
|
|
|
+ {'$match': matchStage},
|
|
|
|
|
+ {'$group': groupStage},
|
|
|
|
|
+ {'$addFields': {'time': '$_id'}},
|
|
|
|
|
+ {'$sort': {'time': 1}},
|
|
|
|
|
+ ]
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ return JsonResponse({'result': 1, 'description': '', 'payload': list(aggregates)})
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+@permission_required(ROLE.manager)
|
|
|
|
|
+def getAdMoneyTrend(request):
|
|
|
|
|
+ # type:(WSGIRequest)->JsonResponse
|
|
|
|
|
+ """
|
|
|
|
|
+ 收益趋势
|
|
|
|
|
+ :param request:
|
|
|
|
|
+ :return:
|
|
|
|
|
+ """
|
|
|
|
|
+ # TODO 待讨论
|
|
|
|
|
+ return JsonResponse({'result': 1, 'description': '', 'payload': []})
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+@error_tolerate(nil = DefaultJsonErrorResponse)
|
|
|
|
|
+@permission_required(ROLE.manager, ROLE.advertisement, ROLE.advertiser)
|
|
|
|
|
+def getAdFansDetail(request):
|
|
|
|
|
+ # type:(WSGIRequest)->JsonResponse
|
|
|
|
|
+ """
|
|
|
|
|
+ 获取广告效果详情列表
|
|
|
|
|
+ :param request:
|
|
|
|
|
+ :return:
|
|
|
|
|
+ """
|
|
|
|
|
+
|
|
|
|
|
+ query = prepare_query(request.GET)
|
|
|
|
|
+
|
|
|
|
|
+ currentUser = request.user # type: cast(Union[Advertisement, Advertiser, Manager])
|
|
|
|
|
+
|
|
|
|
|
+ if is_manager(currentUser):
|
|
|
|
|
+ query.attrs['managerId'] = str(currentUser.id)
|
|
|
|
|
+ elif is_advertiser(currentUser):
|
|
|
|
|
+ query.attrs['advertiserId'] = str(currentUser.id)
|
|
|
|
|
+ elif is_advertisement(currentUser):
|
|
|
|
|
+ query.attrs['adId'] = int(currentUser.adId)
|
|
|
|
|
+
|
|
|
|
|
+ cursor = AdRecord.objects(converted=True, **query.attrs)
|
|
|
|
|
+ total = cursor.count()
|
|
|
|
|
+
|
|
|
|
|
+ pagedRecords = cursor.order_by('-dateTimeAdded').paginate(pageIndex=query.pageIndex, pageSize=query.pageSize) # type: List[AdRecord]
|
|
|
|
|
+ records = [ r.to_dict() for r in pagedRecords ]
|
|
|
|
|
+
|
|
|
|
|
+ return JsonResponse({'result': 1, 'description': None, 'data': {'total': total, 'dataList': records}})
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+@error_tolerate(nil=DefaultJsonErrorResponse)
|
|
|
|
|
+def getPayAfterAd(request):
|
|
|
|
|
+ # type:(WSGIRequest)->JsonResponse
|
|
|
|
|
+ """
|
|
|
|
|
+ 获取支付后广告链接(蓝牙payAfter页面)
|
|
|
|
|
+ :param request:
|
|
|
|
|
+ :return:
|
|
|
|
|
+ """
|
|
|
|
|
+
|
|
|
|
|
+ logicalCode = request.GET.get('logicalCode', None)
|
|
|
|
|
+ if not logicalCode:
|
|
|
|
|
+ logger.debug('no logical code.')
|
|
|
|
|
+ return JsonOkResponse(description='no ads available')
|
|
|
|
|
+
|
|
|
|
|
+ device = Device.get_dev_by_logicalCode(logicalCode)
|
|
|
|
|
+ if not device:
|
|
|
|
|
+ logger.debug('no device find.')
|
|
|
|
|
+ return JsonOkResponse(description='no ads available')
|
|
|
|
|
+
|
|
|
|
|
+ ua = request.META.get('HTTP_USER_AGENT', '')
|
|
|
|
|
+
|
|
|
|
|
+ user = request.user # type: MyUser
|
|
|
|
|
+
|
|
|
|
|
+ ad_dict = Advertisement.fetch_payafter_ad(ua, user, device.owner, device)
|
|
|
|
|
+
|
|
|
|
|
+ logger.debug('ad dict is {}'.format(ad_dict))
|
|
|
|
|
+
|
|
|
|
|
+ if not ad_dict:
|
|
|
|
|
+ return JsonOkResponse(description='no ads available')
|
|
|
|
|
+ else:
|
|
|
|
|
+ return JsonResponse({'result': 1, 'description': u'', 'payload': ad_dict})
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+def taskList(request):
|
|
|
|
|
+ # type:(WSGIRequest)->JsonResponse
|
|
|
|
|
+
|
|
|
|
|
+ """
|
|
|
|
|
+ 广告适配系统
|
|
|
|
|
+ :param request:
|
|
|
|
|
+ :return:
|
|
|
|
|
+ """
|
|
|
|
|
+ try:
|
|
|
|
|
+ user = request.user # type: cast(MyUser)
|
|
|
|
|
+ devNo = request.GET.get('devNo')
|
|
|
|
|
+
|
|
|
|
|
+ if not devNo:
|
|
|
|
|
+ return JsonResponse({'result': 0, 'description': u'请首先扫码', 'payload': {}})
|
|
|
|
|
+
|
|
|
|
|
+ device = Device.get_dev(devNo)
|
|
|
|
|
+ if not device:
|
|
|
|
|
+ return JsonResponse({'result': 0, 'description': u'设备不存在', 'payload': {}})
|
|
|
|
|
+
|
|
|
|
|
+ ads = get_available_ads_by_user(device, user)
|
|
|
|
|
+ logger.debug('%s got ads(%s) on device(logicalCode=%s)' % (repr(user), ads, device['logicalCode']))
|
|
|
|
|
+
|
|
|
|
|
+ allocated_ads = [{'id': ad.adId, 'name': ad.name, 'word': ad.word, 'qrcode': ad.img} for ad in ads]
|
|
|
|
|
+ random.shuffle(allocated_ads)
|
|
|
|
|
+ return JsonResponse({'result': 1, 'description': None, 'payload': {'taskList': allocated_ads}})
|
|
|
|
|
+ except Exception as e:
|
|
|
|
|
+ logger.exception(e)
|
|
|
|
|
+ return JsonResponse({'result': 1, 'description': None, 'payload': {'taskList': []}})
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+### 广告主
|
|
|
|
|
+@error_tolerate(nil = JsonErrorResponse(u'注册失败'))
|
|
|
|
|
+def registerAdvertiser(request):
|
|
|
|
|
+ # type:(WSGIRequest)->JsonResponse
|
|
|
|
|
+
|
|
|
|
|
+ """
|
|
|
|
|
+ 注册成为广告主
|
|
|
|
|
+ :param request:
|
|
|
|
|
+ :return:
|
|
|
|
|
+ """
|
|
|
|
|
+ payload = json.loads(request.body)
|
|
|
|
|
+ try:
|
|
|
|
|
+ Advertiser.create_user(**payload)
|
|
|
|
|
+ except NotUniqueError:
|
|
|
|
|
+ return JsonErrorResponse(description = u'该手机号已注册')
|
|
|
|
|
+ return JsonResponse({'result': 1, 'description': None, 'payload': {}})
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+@error_tolerate(nil = JsonErrorResponse(u'登录失败'))
|
|
|
|
|
+def advertiserLogin(request):
|
|
|
|
|
+ # type:(WSGIRequest)->JsonResponse
|
|
|
|
|
+
|
|
|
|
|
+ """
|
|
|
|
|
+ 广告主登录
|
|
|
|
|
+ :param request:
|
|
|
|
|
+ :return:
|
|
|
|
|
+ """
|
|
|
|
|
+ payload = json.loads(request.body)
|
|
|
|
|
+ username, password = payload['username'], payload['password']
|
|
|
|
|
+ return advertiser_login(request, logger, username, password)
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+@error_tolerate(nil = JsonErrorResponse(u'修改密码失败'))
|
|
|
|
|
+@permission_required(ROLE.advertiser)
|
|
|
|
|
+def changeAdvertiserPassword(request):
|
|
|
|
|
+ # type: (WSGIRequest)->JsonResponse
|
|
|
|
|
+
|
|
|
|
|
+ currentAdvertiser = request.user # type: cast(Advertiser)
|
|
|
|
|
+ payload = json.loads(request.body)
|
|
|
|
|
+ password = payload['password']
|
|
|
|
|
+ if PASSWORD_RE.match(password) is None:
|
|
|
|
|
+ return JsonErrorResponse(description=u'密码必须大于8位,只能是数字或字母或常见特殊符号')
|
|
|
|
|
+ currentAdvertiser.set_password(payload['password'])
|
|
|
|
|
+ return JsonResponse({'result': 1})
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+@error_tolerate(nil = JsonErrorResponse(u'获取广告主信息失败'))
|
|
|
|
|
+@permission_required(ROLE.advertiser)
|
|
|
|
|
+def getAdvertiserInfo(request):
|
|
|
|
|
+ # type:(WSGIRequest)->JsonResponse
|
|
|
|
|
+
|
|
|
|
|
+ """
|
|
|
|
|
+ 获取广告主信息
|
|
|
|
|
+ :param request:
|
|
|
|
|
+ :return:
|
|
|
|
|
+ """
|
|
|
|
|
+ user = request.user # type: cast(Advertiser)
|
|
|
|
|
+ return JsonResponse(
|
|
|
|
|
+ {
|
|
|
|
|
+ 'result': 1,
|
|
|
|
|
+ 'description': '',
|
|
|
|
|
+ 'payload': {'nickname': user.nickname, 'brandName': '', 'quota': user.quota, 'role': ROLE.advertiser }
|
|
|
|
|
+ }
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+### others
|
|
|
|
|
+@error_tolerate(nil = JsonErrorResponse(u'生成报表失败'))
|
|
|
|
|
+@permission_required(ROLE.manager)
|
|
|
|
|
+def exportExcel(request):
|
|
|
|
|
+ # type:(WSGIRequest)->JsonResponse
|
|
|
|
|
+
|
|
|
|
|
+ """
|
|
|
|
|
+ 广告效果报表生成excel
|
|
|
|
|
+ :param request:
|
|
|
|
|
+ :return:
|
|
|
|
|
+ """
|
|
|
|
|
+ manager = request.user # type: cast(Manager)
|
|
|
|
|
+
|
|
|
|
|
+ def get_offline_task_name(task_type, user, **kwargs):
|
|
|
|
|
+ # type: (basestring, UserSearchable, Dict)->basestring
|
|
|
|
|
+
|
|
|
|
|
+ tmp_list = [task_type, user.username]
|
|
|
|
|
+
|
|
|
|
|
+ if 'adId' in kwargs and kwargs['adId']:
|
|
|
|
|
+ tmp_list.append(u'广告_%s' % (kwargs['adId'],))
|
|
|
|
|
+ elif 'devNo' in kwargs:
|
|
|
|
|
+ logicalCode = Device.get_logicalCode_by_devNo(kwargs['devNo'])
|
|
|
|
|
+ tmp_list.append(u'设备号_%s' % (logicalCode,))
|
|
|
|
|
+ elif 'groupId' in kwargs:
|
|
|
|
|
+ address = Group.get_group(kwargs['groupId']).get('address', '')
|
|
|
|
|
+ tmp_list.append(u'地址_%s' % (address,))
|
|
|
|
|
+ elif 'dealerId' in kwargs:
|
|
|
|
|
+ dealerName = Dealer.objects(id = str(kwargs['dealerId'])).get().nickname
|
|
|
|
|
+ tmp_list.append(u'经销商_%s' % (dealerName,))
|
|
|
|
|
+ elif 'agentId' in kwargs:
|
|
|
|
|
+ agentName = Agent.objects(id = str(kwargs['agentId'])).get().nickname
|
|
|
|
|
+ tmp_list.append(u'代理商_%s' % (agentName,))
|
|
|
|
|
+
|
|
|
|
|
+ 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 = prepare_query(request.GET)
|
|
|
|
|
+
|
|
|
|
|
+ offline_task_name = get_offline_task_name(task_type = OfflineTaskType.AD_REPORT,
|
|
|
|
|
+ user = manager,
|
|
|
|
|
+ **(query.raw))
|
|
|
|
|
+
|
|
|
|
|
+ file_path, offline_task = OfflineTask.issue_export_report(offline_task_name = offline_task_name,
|
|
|
|
|
+ process_func_name = 'generate_ad_excel_report',
|
|
|
|
|
+ task_type = OfflineTaskType.AD_REPORT,
|
|
|
|
|
+ userid = str(manager.id),
|
|
|
|
|
+ role = ROLE.manager)
|
|
|
|
|
+
|
|
|
|
|
+ #: make queryAttrs serializable
|
|
|
|
|
+ queryAttrs = query.attrs
|
|
|
|
|
+ queryAttrs['dateTimeAdded__lte'] = dt_to_timestamp(queryAttrs['dateTimeAdded__lte'])
|
|
|
|
|
+ queryAttrs['dateTimeAdded__gte'] = dt_to_timestamp(queryAttrs['dateTimeAdded__gte'])
|
|
|
|
|
+
|
|
|
|
|
+ task_caller(func_name = offline_task.process_func_name,
|
|
|
|
|
+ offline_task_id = str(offline_task.id),
|
|
|
|
|
+ filepath = file_path,
|
|
|
|
|
+ queryAttrs = queryAttrs)
|
|
|
|
|
+
|
|
|
|
|
+ return JsonResponse({
|
|
|
|
|
+ 'result': 1,
|
|
|
|
|
+ 'description': u"请前往离线任务查看任务处理情况",
|
|
|
|
|
+ 'payload': str(offline_task.id)})
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+def getDialogAd(request):
|
|
|
|
|
+ # type:(WSGIRequest)->JsonResponse
|
|
|
|
|
+
|
|
|
|
|
+ # TODO 支付前广告,待补充
|
|
|
|
|
+ return JsonResponse({
|
|
|
|
|
+ 'result': 1,
|
|
|
|
|
+ 'description': '',
|
|
|
|
|
+ 'payload': {'dataList': []}})
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+def getBannerAd(request):
|
|
|
|
|
+ # type:(WSGIRequest)->JsonResponse
|
|
|
|
|
+
|
|
|
|
|
+ logicalCode = request.GET.get('logicalCode')
|
|
|
|
|
+ dev = Device.get_dev_by_logicalCode(logicalCode)
|
|
|
|
|
+
|
|
|
|
|
+ dealer = Dealer.objects(id=str(dev['ownerId'])).only('agentId').get() # type: Dealer
|
|
|
|
|
+ agent = Agent.objects(id=str(dealer.agentId)).only('managerId').get() # type: Agent
|
|
|
|
|
+
|
|
|
|
|
+ ad = Advertisement.filter_by_top_show(managerId=agent.managerId).first() # type: Optional[Advertisement]
|
|
|
|
|
+
|
|
|
|
|
+ if not ad:
|
|
|
|
|
+ return JsonOkResponse(payload={})
|
|
|
|
|
+ else:
|
|
|
|
|
+ return JsonOkResponse(payload={'link': ad.link, 'img': ad.img})
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+@permission_required(ROLE.supermanager)
|
|
|
|
|
+@error_tolerate(nil = DefaultJsonErrorResponse)
|
|
|
|
|
+def getAdWords(request):
|
|
|
|
|
+ # type:(WSGIRequest)->JsonResponse
|
|
|
|
|
+
|
|
|
|
|
+ pageIndex = int(request.GET.get('pageIndex', 1))
|
|
|
|
|
+ pageSize = int(request.GET.get('pageSize', 10))
|
|
|
|
|
+ searchKey = request.GET.get('searchKey')
|
|
|
|
|
+ startTime = request.GET.get('startTime')
|
|
|
|
|
+ endTime = request.GET.get('endTime')
|
|
|
|
|
+
|
|
|
|
|
+ query = {}
|
|
|
|
|
+
|
|
|
|
|
+ if startTime is not None and endTime is not None:
|
|
|
|
|
+ query['dateTimeAdded__lte'] = date_to_datetime_ceiling(endTime)
|
|
|
|
|
+ query['dateTimeAdded__gte'] = date_to_datetime_floor(startTime)
|
|
|
|
|
+
|
|
|
|
|
+ total = AdWord.objects(**query).search(searchKey).count()
|
|
|
|
|
+ qs = AdWord.objects(**query).search(searchKey).paginate(pageIndex=pageIndex, pageSize=pageSize) # type: Iterable[AdWord]
|
|
|
|
|
+
|
|
|
|
|
+ return JsonOkResponse(payload={'dataList': [ _.to_dict() for _ in qs ], 'total': total})
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+@permission_required(ROLE.supermanager)
|
|
|
|
|
+@error_tolerate(nil = DefaultJsonErrorResponse)
|
|
|
|
|
+def addAdWord(request):
|
|
|
|
|
+ # type:(WSGIRequest)->JsonResponse
|
|
|
|
|
+
|
|
|
|
|
+ payload = parse_json_payload(request.body)
|
|
|
|
|
+ AdWord(**payload).save()
|
|
|
|
|
+ return JsonOkResponse()
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+@permission_required(ROLE.supermanager)
|
|
|
|
|
+@error_tolerate(nil = DefaultJsonErrorResponse)
|
|
|
|
|
+def editAdword(request):
|
|
|
|
|
+ # type:(WSGIRequest)->JsonResponse
|
|
|
|
|
+
|
|
|
|
|
+ payload = parse_json_payload(request.body)
|
|
|
|
|
+ ad_word = AdWord.objects(id=payload['id']).get()
|
|
|
|
|
+ updated = ad_word.update(**payload)
|
|
|
|
|
+ if updated:
|
|
|
|
|
+ return JsonOkResponse(payload={'description': u'更新成功'})
|
|
|
|
|
+ else:
|
|
|
|
|
+ return JsonErrorResponse(payload={'description': u'更新失败'})
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+@permission_required(ROLE.supermanager)
|
|
|
|
|
+@error_tolerate(nil = DefaultJsonErrorResponse)
|
|
|
|
|
+def deleteAdword(request):
|
|
|
|
|
+ # type:(WSGIRequest)->JsonResponse
|
|
|
|
|
+
|
|
|
|
|
+ payload = json.loads(request.body)
|
|
|
|
|
+
|
|
|
|
|
+ ids = payload.get('ids')
|
|
|
|
|
+
|
|
|
|
|
+ if not ids:
|
|
|
|
|
+ return JsonErrorResponse(description=u'')
|
|
|
|
|
+
|
|
|
|
|
+ AdWord.objects(id__in=ids).delete() # type: AdWord
|
|
|
|
|
+
|
|
|
|
|
+ return JsonOkResponse()
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+@error_tolerate(nil = DefaultJsonErrorResponse)
|
|
|
|
|
+def userGetAdword(request):
|
|
|
|
|
+ # type:(WSGIRequest)->JsonResponse
|
|
|
|
|
+
|
|
|
|
|
+ try:
|
|
|
|
|
+ user = request.user # type: cast(MyUser)
|
|
|
|
|
+
|
|
|
|
|
+ ad_word = AdWord.get_random_one() # type: AdWord
|
|
|
|
|
+
|
|
|
|
|
+ if ad_word is not None:
|
|
|
|
|
+ ad_word.incr_count(1)
|
|
|
|
|
+
|
|
|
|
|
+ title = ad_word.title
|
|
|
|
|
+
|
|
|
|
|
+ if not ad_word.autoPass:
|
|
|
|
|
+ return MyJsonOkResponse({'result': 1, 'description': '', 'payload': {'content': ad_word.promotionUrl}})
|
|
|
|
|
+
|
|
|
|
|
+ tbkCode = serviceCache.get('tbk_{}'.format(str(ad_word.id)))
|
|
|
|
|
+ if not tbkCode:
|
|
|
|
|
+ from library.aliopen.tbkapi import CreatTaokoulingReq
|
|
|
|
|
+
|
|
|
|
|
+ request = CreatTaokoulingReq(appKey = '33175347', appSecret = 'c4e2d8426d1d08ec49ef00bc40ac94d5')
|
|
|
|
|
+ request.setParams(url = ad_word.promotionUrl)
|
|
|
|
|
+ rv = xmltodict.parse(request.getResponse().content)
|
|
|
|
|
+
|
|
|
|
|
+ logger.debug('tbk code rv for {} is: {}'.format(str(ad_word.id), str(rv)))
|
|
|
|
|
+
|
|
|
|
|
+ tokens = rv['tbk_tpwd_create_response']['data']['model'].split(' ')
|
|
|
|
|
+ tbkCode = '{} {} {}'.format(tokens[0], tokens[1], title)
|
|
|
|
|
+
|
|
|
|
|
+ logger.debug('new tbk code is: {}'.format(tbkCode))
|
|
|
|
|
+
|
|
|
|
|
+ serviceCache.set('tbk_{}'.format(str(ad_word.id)), tbkCode, 60 * 60 * 2)
|
|
|
|
|
+
|
|
|
|
|
+ return MyJsonOkResponse({'result': 1, 'description': '', 'payload': {'content': tbkCode}})
|
|
|
|
|
+ else:
|
|
|
|
|
+ logger.debug('cache tbk code is: {}'.format(tbkCode))
|
|
|
|
|
+
|
|
|
|
|
+ return MyJsonOkResponse({'result': 1, 'description': '', 'payload': {'content': tbkCode}})
|
|
|
|
|
+ except Exception as e:
|
|
|
|
|
+ logger.error('exception = {}; id = {}'.format(traceback.format_exc(), str(ad_word.id)))
|
|
|
|
|
+
|
|
|
|
|
+ return MyJsonOkResponse({'result': 1, 'description': '', 'payload': {'content': ''}})
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+@error_tolerate(nil = DefaultJsonErrorResponse)
|
|
|
|
|
+def alipayCallback(request, uidType):
|
|
|
|
|
+ # type:(WSGIRequest, str)->JsonResponse
|
|
|
|
|
+
|
|
|
|
|
+ try:
|
|
|
|
|
+ uidType = uidType.upper()
|
|
|
|
|
+
|
|
|
|
|
+ payload = json.loads(request.body)
|
|
|
|
|
+
|
|
|
|
|
+ if uidType == 'CPM':
|
|
|
|
|
+ # uid = payload.get('uid')
|
|
|
|
|
+ # bid = payload.get('bid')
|
|
|
|
|
+ # try:
|
|
|
|
|
+ # AdLog.objects.get(openId=uid, bidid=bid, status__ne='finished').update(status='finished', finishedData=request.body, finishedTime=datetime.datetime.now())
|
|
|
|
|
+ # except:
|
|
|
|
|
+ # logger.info(traceback.format_exc())
|
|
|
|
|
+ pass
|
|
|
|
|
+
|
|
|
|
|
+ elif uidType == 'RH':
|
|
|
|
|
+
|
|
|
|
|
+ uid = payload.get('uid')
|
|
|
|
|
+ urlId = payload.get('ext', {}).get('id')
|
|
|
|
|
+
|
|
|
|
|
+ redpack = Redpack.take_effect(openId = uid, urlId = urlId, **{'RHCallback': request.body})
|
|
|
|
|
+ if redpack:
|
|
|
|
|
+ RedpackBuilder._set_alipay_key(uid, redpack.factoryCode, urlId, redpack.money.mongo_amount,
|
|
|
|
|
+ showType = redpack.showType)
|
|
|
|
|
+
|
|
|
|
|
+ return JsonResponse({"status": 1, "alipayOrderId": urlId})
|
|
|
|
|
+
|
|
|
|
|
+ elif uidType == 'LX':
|
|
|
|
|
+ pass
|
|
|
|
|
+
|
|
|
|
|
+ try:
|
|
|
|
|
+ AliAdLog.objects(campaignId = payload.get('campaignId'), bid = payload.get('bid')).upsert_one(
|
|
|
|
|
+ uid = payload.get('uid'), uidType = payload.get('uidtype'), campaignId = payload.get('campaignId'),
|
|
|
|
|
+ bid = payload.get('bid'), tradeTS = payload.get('tradetimestamp'), commission = payload.get('commission'))
|
|
|
|
|
+ except Exception as e:
|
|
|
|
|
+ logger.error(e)
|
|
|
|
|
+ finally:
|
|
|
|
|
+ return JsonResponse({'success': True, 'errorMsg': '', 'result': True})
|