337 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			337 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Python
		
	
	
	
| import json
 | |
| import random
 | |
| import warnings
 | |
| from calendar import timegm
 | |
| from datetime import datetime
 | |
| 
 | |
| 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
 | |
| 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,
 | |
|                                             jwt_payload_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 .exports import export_consumer
 | |
| from .models import Company, Consumer, PaySubject, SendCode
 | |
| from .serializers import CompanySerializer, ConsumerSerializer
 | |
| 
 | |
| appid = 'wxf1e9471c93f05ad6'
 | |
| secret = '4bf7f9bd6c52634586bbe792a1f0a834'
 | |
| sms_appid = '100172'
 | |
| sms_appsecret = '00b8681c-0ce6-41c8-a867-904c1891c78a'
 | |
| sms_url = 'https://sms.zhenzikj.com'
 | |
| 
 | |
| def jwt_payload_handler(user):
 | |
|     payload = {
 | |
|         'user_id': user.pk,
 | |
|         'type':'consumer',
 | |
|         '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 CompanyViewSet(ModelViewSet):
 | |
|     """
 | |
|     客户企业:增删改查
 | |
|     """
 | |
|     perms_map = [
 | |
|         {'get': 'company_list'}, {'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']
 | |
| 
 | |
| class ConsumerViewSet(ModelViewSet):
 | |
|     """
 | |
|     学员:增删改查
 | |
|     """
 | |
|     perms_map = [
 | |
|         {'get': 'consumer_list'}, {'post': 'consumer_create'},
 | |
|         {'put': 'consumer_update'}, {'delete': 'consumer_delete'}]
 | |
|     queryset = Consumer.objects.filter(is_delete=0).all()
 | |
|     serializer_class = ConsumerSerializer
 | |
|     pagination_class = CommonPagination
 | |
|     ordering_fields = ('id','company','create_time', 'username', 'workscope')
 | |
|     ordering = ['-create_time']
 | |
|     filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
 | |
|     filterset_fields = ('company',)
 | |
|     search_fields = ('^name','^username','^company__name')
 | |
| 
 | |
|     def get_queryset(self):
 | |
|         queryset = self.queryset
 | |
|         queryset = self.get_serializer_class().setup_eager_loading(queryset)  
 | |
|         return queryset
 | |
| 
 | |
|     def create(self, request, *args, **kwargs):
 | |
|         serializer = self.get_serializer(data=request.data)
 | |
|         serializer.is_valid(raise_exception=True)
 | |
|         instance = serializer.save()
 | |
|         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()
 | |
|         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(soft=False)
 | |
|             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=['post'], detail=False,
 | |
|             url_path='import', url_name='import_consumer')
 | |
|     def import_consumer(self, request):
 | |
|         """
 | |
|         导入用户
 | |
|         """
 | |
|         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":"工作类别列错误!"})
 | |
|         companydict = {}
 | |
|         companys = Company.objects.filter(is_delete=0)
 | |
|         for i in companys:
 | |
|             companydict[i.name] = i.id
 | |
|         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(' ', '')
 | |
|             companyname = sheet['C'+str(m)].value
 | |
|             if companyname:
 | |
|                 companyname = companyname.replace(' ', '')
 | |
|             companyobj = Company.objects.get_or_create(name=companyname)[0]
 | |
|             workscope = sheet['d'+str(m)].value
 | |
|             if Consumer.objects.filter(username = username).exists():
 | |
|                 obj = Consumer.objects.filter(username = username).first()
 | |
|             else:
 | |
|                 obj = Consumer()
 | |
|                 obj.username = username
 | |
|             obj.name = name
 | |
|             obj.company = companyobj
 | |
|             obj.is_delete = False
 | |
|             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.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.queryset)
 | |
|         queryset = ConsumerSerializer.setup_eager_loading(queryset)  # 性能优化
 | |
|         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":"不支持解绑!"})
 | |
| 
 | |
| 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 = ConsumerSerializer(instance=consumer)
 | |
|         payload = jwt_payload_handler(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(soft=False) # 彻底删除
 | |
|                         consumer.openid = openid
 | |
|                         if avatar and nickname:
 | |
|                             consumer.avatar = avatar
 | |
|                             consumer.nickname = nickname
 | |
|                         consumer.is_delete = False
 | |
|                         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
 | |
|                         consumer.is_delete = False
 | |
|                         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) |