examtest/test_server/crm/views.py

650 lines
26 KiB
Python

import json
import random
import warnings
from calendar import timegm
from datetime import date, datetime, timedelta
import requests
from django.db.models import Q
from django_filters.rest_framework import DjangoFilterBackend
from openpyxl import Workbook, load_workbook
from rest_framework import status
from rest_framework.decorators import action, authentication_classes, permission_classes
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.viewsets import ModelViewSet
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework_jwt.serializers import jwt_encode_handler
from rest_framework_jwt.settings import api_settings
from crm.zhenzismsclient import ZhenziSmsClient
from examtest.models_paper import WorkScope
from question.models import Questioncat
from question.serializers import QuestionSerializer
from server import settings
from utils.custom import CommonPagination
from .filters import ConsumerFilter
from .exports import export_consumer
from .models import Company, Consumer, PaySubject, SendCode, ConsumerPerm, ConsumerRole
from .serializers import CompanySerializer, ConsumerSerializer, ConsumerPermSerializer, ConsumerRoleSerializer, ConsumerDetailSerializer
from lxml import etree
from rbac.models import UserProfile
from django.http import Http404
from .spider import getZs
import time
from server.config import *
def my_payload_handler(user, dtype="admin"):
payload = {
'user_id': user.pk,
'type':dtype,
'exp': datetime.utcnow() + api_settings.JWT_EXPIRATION_DELTA
}
if api_settings.JWT_ALLOW_REFRESH:
payload['orig_iat'] = timegm(
datetime.utcnow().utctimetuple()
)
if api_settings.JWT_AUDIENCE is not None:
payload['aud'] = api_settings.JWT_AUDIENCE
if api_settings.JWT_ISSUER is not None:
payload['iss'] = api_settings.JWT_ISSUER
return payload
class ConsumerRoleViewSet(ModelViewSet):
"""
客户角色:增删改查
"""
perms_map = [
{'get': 'consumerrole_view'}, {'post': 'consumerrole_create'},
{'put': 'consumerrole_update'}, {'delete': 'consumerrole_delete'}]
queryset = ConsumerRole.objects.filter(is_delete=0)
serializer_class = ConsumerRoleSerializer
pagination_class = None
filter_backends = [DjangoFilterBackend,SearchFilter, OrderingFilter]
search_fields = ['name','description']
ordering_fields = ['create_time']
ordering = ['-create_time']
class ConsumerPermViewSet(ModelViewSet):
"""
客户权限:增删改查
"""
perms_map = [
{'get': 'consumerperm_view'}, {'post': 'consumerperm_create'},
{'put': 'consumerperm_update'}, {'delete': 'consumerperm_delete'}]
queryset = ConsumerPerm.objects.filter(is_delete=0)
serializer_class = ConsumerPermSerializer
pagination_class = None
filter_backends = [DjangoFilterBackend,SearchFilter, OrderingFilter]
search_fields = ['name','code']
ordering_fields = ['create_time']
ordering = ['-create_time']
keys1 = ['86e0993305a427ac2d0b5371ad97f242']
def getPosition(name):
# 高德接口
url = 'http://restapi.amap.com/v3/place/text'
par = {'keywords': name, 'key': keys1[0]}
res = requests.get(url, par)
json_data = json.loads(res.text)
fdata = {}
if json_data['status'] == '1' and int(json_data['count']) > 0:
alldata = json_data['pois'][0]
fdata['cname'] = '中国'
fdata['pname'] = alldata['pname']
fdata['cityname'] = alldata['cityname']
fdata['adname'] = alldata['adname']
fdata['address'] = alldata['address']
return fdata
return None
keys2 = ['v31TjiNQoCCF1PwDVWU43yUjSoyQSdmj']
def getPosition2(name):
# 百度接口
url = 'http://api.map.baidu.com/place/v2/search'
par = {'query': name, 'ak': keys2[0], 'region':'全国', 'output':'json'}
res = requests.get(url, par)
json_data = json.loads(res.text)
fdata = {}
if len(json_data['results'])> 0 and 'province' in json_data['results'][0]:
alldata = json_data['results'][0]
fdata['cname'] = '中国'
fdata['pname'] = alldata['province']
fdata['cityname'] = alldata['city']
fdata['adname'] = alldata['area']
fdata['address'] = alldata['address'] if 'address' in alldata else ''
return fdata
return None
class CompanyViewSet(ModelViewSet):
"""
客户企业:增删改查
"""
perms_map = [
{'get': 'company_view'}, {'post': 'company_create'},
{'put': 'company_update'}, {'delete': 'company_delete'}]
queryset = Company.objects.filter(is_delete=0).all()
serializer_class = CompanySerializer
pagination_class = CommonPagination
filter_backends = [DjangoFilterBackend,SearchFilter, OrderingFilter]
search_fields = ('name',)
ordering_fields = ('id',)
ordering = ['-id']
def perform_create(self, serializer):
instance = serializer.save(create_admin=self.request.user)
if not instance.geo:
try:
geo = getPosition2(instance.name)
except:
pass
if geo:
instance.geo = geo
instance.save()
def get_queryset(self):
queryset = self.queryset
if self.request.user.is_superuser:
return queryset
roles = self.request.user.roles.values_list('name', flat=True)
if '普通管理' in roles:
queryset = queryset.filter(create_admin = self.request.user)
elif '省管理' in roles:
if self.request.user.pname:
queryset = queryset.filter(geo__pname = self.request.user.pname)
else:
return Company.objects.none()
else:
return queryset.none()
return queryset
@action(methods=['put'], detail=True, url_name='company_transfer',perms_map=[{'*':'company_transfer'}])
def transfer(self, request, *args, **kwargs):
"""
转交
"""
obj = self.get_object()
adminname = request.data.get('admin', None)
if adminname and UserProfile.objects.filter(username=adminname).exists():
adminobj = UserProfile.objects.get(username=adminname)
obj.create_admin = adminobj
obj.save()
Consumer.objects.filter(company=obj).update(create_admin=adminobj)
return Response(status=status.HTTP_200_OK)
else:
return Response({"error":"账号错误"})
@action(methods=['put'], detail=False, url_name='company_transfers',perms_map=[{'*':'company_transfers'}])
def transfers(self, request, *args, **kwargs):
"""
批量移交
"""
companys = Company.objects.filter(id__in = request.data['companys'])
adminname = request.data.get('admin', None)
if adminname and UserProfile.objects.filter(username=adminname).exists():
adminobj = UserProfile.objects.get(username=adminname)
if companys.exists():
companys.update(create_admin=adminobj)
Consumer.objects.filter(company__in = companys).update(create_admin=adminobj)
return Response(status=status.HTTP_200_OK)
else:
return Response({"error":"账号错误"})
@action(methods=['get'], detail=False, url_name='correct_geo',perms_map=[{'*':'correct_geo'}])
def correctgeo(self, request, *args, **kwargs):
"""
地理位置
"""
companys = Company.objects.filter(geo__pname__isnull=True).order_by('-create_time')
for i in companys:
geo = None
try:
geo = getPosition2(i.name)
except:
pass
if geo:
i.geo = geo
i.save()
print(str(i.id) + '-' + i.name + '-ok')
return Response(status=status.HTTP_200_OK)
class ConsumerViewSet(ModelViewSet):
"""
学员:增删改查
"""
perms_map = [
{'get': 'consumer_view'}, {'post': 'consumer_create'},
{'put': 'consumer_update'}, {'delete': 'consumer_delete'}]
queryset = Consumer.objects.all()
serializer_class = ConsumerSerializer
pagination_class = CommonPagination
ordering_fields = ('id','company','create_time', 'username', 'workscope')
ordering = ['-create_time']
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
filterset_class = ConsumerFilter
search_fields = ['name','username','company__name']
def get_queryset(self):
queryset = self.queryset
queryset = self.get_serializer_class().setup_eager_loading(queryset)
if self.request.user.is_superuser:
return queryset
if self.request.query_params.get('adminoff', None):
return queryset.filter(create_admin__isnull=True)
roles = self.request.user.roles.values_list('name', flat=True)
if '普通管理' in roles:
queryset = queryset.filter(create_admin = self.request.user)
elif '省管理' in roles:
if self.request.user.pname:
queryset = queryset.filter(company__geo__pname = self.request.user.pname)
else:
return Consumer.objects.none()
elif '本单位管理' in roles:
if self.request.user.bcompany:
queryset = queryset.filter(company = self.request.user.bcompany)
else:
return Consumer.objects.none()
else:
return queryset.none()
return queryset
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
instance = serializer.save(create_admin=request.user)
if request.data.get('subjects', None):
for i in request.data.get('subjects'):
PaySubject.objects.get_or_create(consumer = instance, subject__id=i, defaults={'consumer':instance,'subject':Questioncat.objects.get(id=i)})
return Response(serializer.data, status=status.HTTP_201_CREATED)
def update(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data)
if serializer.is_valid():
instance = serializer.save()
if instance.create_admin is None:
instance.create_admin = request.user
instance.save()
else:
return Response(serializer.errors)
PaySubject.objects.filter(consumer = instance).delete()
if request.data.get('subjects', None):
for i in request.data.get('subjects'):
PaySubject.objects.get_or_create(consumer = instance, subject__id=i, defaults={'consumer':instance,'subject':Questioncat.objects.get(id=i)})
return Response(serializer.data)
@action(methods=['post'], detail=False, url_name='consumer_deletes',perms_map=[{'*':'consumer_deletes'}])
def deletes(self, request):
"""
批量删除用户
"""
ids = request.data.get('ids', None)
if ids:
Consumer.objects.filter(id__in = ids).delete()
return Response(status=status.HTTP_200_OK)
@action(methods=['put'], detail=False, url_name='consumer_exceeddates',perms_map=[{'*':'consumer_exceeddates'}])
def exceeddates(self, request):
"""
批量用户截至期限
"""
ids = request.data.get('ids', None)
exceed_date = request.data.get('exceed_date')
if ids:
Consumer.objects.filter(id__in = ids).update(exceed_date=exceed_date)
return Response(status=status.HTTP_200_OK)
@action(methods=['get'], detail=False,
url_path='subjectpaid', url_name='subject_paid',perms_map=[{'*':'my_subject'}])
def has_paid(self, request):
"""
当前登陆消费者已付费的学科
"""
queryset = PaySubject.objects.filter(consumer = request.user)
data = queryset.values_list('subject__id',flat=True)
return Response(data)
@action(methods=['get'], detail=False,
url_path='sendcode', url_name='code_send',authentication_classes=[],permission_classes=[])
def sendcode(self, request):
'''
发送验证码
'''
client = ZhenziSmsClient(sms_url, sms_appid, sms_appsecret)
code = random.randint(1000,9999)
phone = request.query_params.get('phone')
params = {'message':'您的验证码为:' + str(code) +',5分钟内有效', 'number': phone}
result = json.loads(client.send(params))
if result['code'] == 0:
SendCode.objects.create(phone=phone, code=code)
return Response(status=status.HTTP_200_OK)
else:
return Response({'error':result['data']})
@action(methods=['post','delete','get'], detail=False,
url_path='collects', url_name='create_collects', perms_map=[{'*':'my_collects'}])
def collects(self, request):
'''
个人收藏集
'''
if request.method == 'POST':
questionId = request.data.get('question',None)
if questionId:
request.user.collects.remove(questionId)
request.user.collects.add(questionId)
return Response(status=status.HTTP_200_OK)
else:
return Response({'error':'post参数错误'})
elif request.method == 'GET':
queryset = request.user.collects.all().order_by('-update_time')
serializer = QuestionSerializer(instance=queryset,many=True)
return Response(serializer.data)
elif request.method == 'DELETE':
questionId = request.data.get('question',None)
if questionId:
request.user.collects.remove(questionId)
return Response(status=status.HTTP_200_OK)
else:
return Response({'error':'delete参数错误'})
@action(methods=['get', 'put'], detail=False,
url_path='process', url_name='exercise_process', perms_map=[{'*':'*'}])
def process(self, request):
'''
练习进度
'''
if request.method == 'GET':
process = {}
if hasattr(request.user, 'process'):
process = request.user.process
return Response({'process':process})
elif request.method == 'PUT':
if hasattr(request.user, 'process'):
request.user.process = request.data['process']
request.user.save()
return Response(status=status.HTTP_200_OK)
@action(methods=['post'], detail=False,
url_path='realinfo', url_name='get_realinfo', perms_map=[{'*':'*'}])
def realinfo(self, request):
'''
修改查询信息
'''
if isinstance(request.user, Consumer):
request.user.ID_number = request.data['ID_number']
request.user.realname = request.data['realname']
request.user.save()
return Response(status=status.HTTP_200_OK)
@action(methods=['get'], detail=False,
url_path='candidate', url_name='consumer_candidate', perms_map=[{'*':'*'}])
def candidate(self, request):
'''
证书查询
'''
candidates = getZs(request.query_params['realname'], request.query_params['ID_number'])
return Response({'candidates':candidates}, status=status.HTTP_200_OK)
@action(methods=['post'], detail=False,
url_path='import', url_name='import_consumer')
def import_consumer(self, request):
"""
导入用户
"""
role1 = ConsumerRole.objects.get(name='付费学员')
xlsxpath = request.data['path']
fullpath = settings.BASE_DIR + xlsxpath
wb = load_workbook(fullpath)
sheet = wb.worksheets[0]
# 验证文件内容
if sheet['a2'].value != '姓名':
return Response({"error":"姓名列错误!"})
if sheet['b2'].value != '账户(手机号)':
return Response({"error":"账户列错误!"})
if sheet['c2'].value != '单位':
return Response({"error":"单位列错误!"})
if sheet['d2'].value != '工作类别':
return Response({"error":"工作类别列错误!"})
if sheet['e2'].value != '角色':
return Response({"error":"角色列错误!"})
m = 3
while sheet['B'+str(m)].value:
name = sheet['A'+str(m)].value
if name:
name = name.replace(' ', '')
username = sheet['B'+str(m)].value
if username:
username = str(username).replace(' ', '').replace("\n", "")
ID_number1 = sheet['F'+str(m)].value
if ID_number1:
ID_number1 = str(ID_number1).replace(' ', '').replace("\n", "")
companyname = sheet['C'+str(m)].value
if companyname:
companyname = companyname.replace(' ', '')
#公司同名但两个管理员创建,则认为是两个公司
if Company.objects.filter(name=companyname, create_admin=request.user).exists():
companyobj = Company.objects.get(name=companyname, create_admin=request.user)
else:
companyobj = Company.objects.create(name=companyname, create_admin=request.user)
geo = None
try:
geo = getPosition2(companyobj.name)
except:
pass
if geo:
companyobj.geo = geo
companyobj.save()
workscope = sheet['d'+str(m)].value
role = sheet['e'+str(m)].value
if Consumer.objects.filter(username = username).exists():
obj = Consumer.objects.filter(username = username).first()
if obj.create_admin is None:
obj.create_admin = request.user
else:
obj = Consumer()
obj.username = username
obj.create_admin = request.user
obj.name = name
if not obj.company: #导入时避免公司变动
obj.company = companyobj
if ID_number1:
obj.ID_number1 = ID_number1
obj.save()
if workscope:
workscope = workscope.replace(' ', '')
try:
workscopeobj = WorkScope.objects.get(name=workscope)
obj.workscope = workscopeobj
PaySubject.objects.get_or_create(subject=workscopeobj.subject, consumer = obj)
except:
return Response({"error":"工作类别不存在!"})
obj.role = role1
if role:
role = role.replace(' ', '')
try:
roleobj = ConsumerRole.objects.get(name=role)
obj.role = roleobj
except:
pass
obj.exceed_date = datetime.now() + timedelta(days=90)
obj.save()
m = m + 1
return Response(status=status.HTTP_200_OK)
@action(methods=['get'], detail=False,
url_path='export', url_name='export_consumer', perms_map=[{'*':'export_consumer'}])
def export(self, request):
queryset = self.filter_queryset(self.get_queryset())
queryset = ConsumerSerializer.setup_eager_loading(queryset) # 性能优化
if queryset.count()>1000:
return Response({'error':'数据量超过1000,请筛选后导出'})
serializer = ConsumerSerializer(instance=queryset, many=True)
path = export_consumer(serializer.data)
return Response({'path': path})
@action(methods=['get'], detail=True, url_name='consumer_unbind', perms_map=[{'*':'consumer_unbind'}])
def unbind(self, request, *args, **kwargs):
obj = self.get_object()
if obj.username and obj.openid:
obj.openid = None
obj.nickname = None
obj.avatar = None
obj.save()
return Response(status=status.HTTP_200_OK)
else:
return Response({"error":"不支持解绑!"})
@action(methods=['get'], detail=False,
url_path='correctrole', url_name='correct_role', perms_map=[{'*':'correct_role'}])
def correctrole(self, request):
role0 = ConsumerRole.objects.get(name='游客')
role1 = ConsumerRole.objects.get(name='付费学员')
role2 = ConsumerRole.objects.get(name='注册用户')
for i in Consumer.objects.filter(role__isnull = True):
i.role = role0
if i.workscope and i.username:
i.role = role1
elif i.username and i.openid:
i.role = role2
i.save()
return Response(status=status.HTTP_200_OK)
@action(methods=['get'], detail=False,
url_path='correctexceed', url_name='correct_exceed', perms_map=[{'*':'correct_exceed'}])
def correctexceed(self, request):
Consumer.objects.exclude(exceed_date=None).update(exceed_date = datetime(2020,12,31))
return Response(status=status.HTTP_200_OK)
@action(methods=['get'], detail=False,
url_path='correctadmin', url_name='correct_admin', perms_map=[{'*':'correct_admin'}])
def correctadmin(self, request):
Consumer.objects.filter(name='').update(create_admin=None)
return Response(status=status.HTTP_200_OK)
@action(methods=['put'], detail=True, url_name='consumer_claim', perms_map=[{'*':'consumer_claim'}])
def claim(self, request, pk=None):
try:
obj = Consumer.objects.get(pk=pk)
if obj.username and obj.create_admin is None:
obj.create_admin = request.user
obj.save()
return Response(status=status.HTTP_200_OK)
else:
return Response({"error":"认领失败!"})
except:
raise Http404
@action(methods=['get'], detail = False, perms_map=[{'*':'*'}])
def info(self, request, *args, **kwargs):
serializer = ConsumerDetailSerializer(instance=request.user)
return Response({"userinfo":serializer.data})
from .permission import get_consumerperm_list
class ConsumerMPLoginView(APIView):
"""
小程序登陆颁发token
"""
authentication_classes=[]
permission_classes=[]
def post(self, request, *args, **kwargs):
code = request.data['code']
info = requests.get('https://api.weixin.qq.com/sns/jscode2session?appid='+appid+'&secret='+secret+'&js_code=' +
code+'&grant_type=authorization_code').content.decode('utf-8')
info = json.loads(info)
openid = info['openid']
session_key = info['session_key']
consumer = Consumer.objects.get_or_create(openid = openid)[0]
serializer = ConsumerDetailSerializer(instance=consumer)
payload = my_payload_handler(consumer, 'consumer')
token = jwt_encode_handler(payload)
return Response({"token":token,"session_key":session_key, "openid":openid, "userinfo":serializer.data})
class ConsumerLogoutView(APIView):
authentication_classes = ()
permission_classes = ()
def get(self, request, *args, **kwargs):
return Response(status=status.HTTP_200_OK)
class ConsumerRegister(APIView):
'''
验证码登陆和注册
'''
def post(self, request, *args, **kwargs):
data = request.data
phone = data.get('phone', None)
code = data.get('code', None)
avatar = data.get('avatar', None)
nickname = data.get('nickname', None)
if phone and code:
obj = SendCode.objects.filter(phone=phone).last()
if obj:
if code == obj.code: # 验证通过
consumer_queryset = Consumer.objects.filter(username=phone)
if consumer_queryset.exists(): # 是否存在
consumer = consumer_queryset.first()
if consumer.openid:
return Response({'error':'该号码已使用!'})
openid = request.user.openid
request.user.delete() # 删除
consumer.openid = openid
if avatar and nickname:
consumer.avatar = avatar
consumer.nickname = nickname
if consumer.role and consumer.role.name == '游客':
consumer.role = ConsumerRole.objects.get(name='注册用户')
# 默认工作类别是非医学Ⅲ类
if not consumer.workscope:
try:
consumer.workscope = WorkScope.objects.get(name='非医学Ⅲ类')
except:
pass
consumer.save()
return Response(status=status.HTTP_200_OK)
else:
consumer = request.user
consumer.username = phone
if avatar and nickname:
consumer.avatar = avatar
consumer.nickname = nickname
if consumer.role and consumer.role.name == '游客':
consumer.role = ConsumerRole.objects.get(name='注册用户')
# 默认工作类别是非医学Ⅲ类
if not consumer.workscope:
try:
consumer.workscope = WorkScope.objects.get(name='非医学Ⅲ类')
except:
pass
consumer.save()
return Response(status=status.HTTP_200_OK)
else:
return Response({'error':'验证码错误!'})
else:
return Response({'error':'认证错误!'})
else:
return Response({'error':'信息不全!'})
class change_remain_count(APIView):
perms_map=[{'*':'change_remain_count'}]
def get(self, request, *args, **kwargs):
# count = request.query_params.get('count', None)
# if count:
for i in Consumer.objects.all():
i.remain_count = i.remain_count + 2
i.save()
return Response(status=status.HTTP_200_OK)
from django.shortcuts import render
def candidate(request, number):
return render(request, 'index.html')