133 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			133 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			Python
		
	
	
	
| from functools import update_wrapper
 | |
| from django.shortcuts import render
 | |
| from django.utils import timezone
 | |
| from rest_framework.response import Response
 | |
| from rest_framework.viewsets import ModelViewSet, GenericViewSet
 | |
| from rest_framework.mixins import UpdateModelMixin, RetrieveModelMixin, CreateModelMixin, ListModelMixin
 | |
| from apps.hrm.filters import ClockRecordFilterSet, EmployeeFilterSet
 | |
| from apps.hrm.services import HRMService
 | |
| from apps.hrm.tasks import update_all_user_facedata_cache
 | |
| from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin
 | |
| from apps.hrm.models import ClockRecord, Employee
 | |
| from apps.hrm.serializers import ClockRecordListSerializer, EmployeeSerializer, FaceClockCreateSerializer, FaceLoginSerializer
 | |
| 
 | |
| 
 | |
| 
 | |
| from rest_framework.generics import CreateAPIView
 | |
| from rest_framework import status
 | |
| from rest_framework_simplejwt.tokens import RefreshToken
 | |
| from rest_framework import exceptions
 | |
| from apps.system.models import User
 | |
| from apps.system.serializers import UserSimpleSerializer
 | |
| from rest_framework.permissions import AllowAny
 | |
| from rest_framework.decorators import action
 | |
| 
 | |
| 
 | |
| # Create your views here.
 | |
| class EmployeeViewSet(CreateUpdateModelAMixin, OptimizationMixin, UpdateModelMixin, ListModelMixin, RetrieveModelMixin, GenericViewSet):
 | |
|     """
 | |
|     员工详细信息
 | |
|     """
 | |
|     perms_map = {'get': '*', 'put': 'employee_update'}
 | |
|     queryset = Employee.objects.all()
 | |
|     filterset_class = EmployeeFilterSet
 | |
|     serializer_class = EmployeeSerializer
 | |
|     search_fields = ['user__name', 'number', 'user__username']
 | |
|     ordering = ['-pk']
 | |
|     
 | |
|     def update(self, request, *args, **kwargs):
 | |
|         partial = kwargs.pop('partial', False)
 | |
|         instance = self.get_object()
 | |
|         data = request.data
 | |
|         serializer = self.get_serializer(instance, data=data, partial=partial)
 | |
|         serializer.is_valid(raise_exception=True)
 | |
|         photo = data.get('photo', None)
 | |
|         if instance.photo != photo:
 | |
|             f_l, msg = HRMService.get_facedata_from_img(img_path=photo)
 | |
|             if f_l:
 | |
|                 serializer.save(update_by=request.user, face_data = f_l)
 | |
|                 # 更新人脸缓存
 | |
|                 update_all_user_facedata_cache.delay()
 | |
|                 return Response()
 | |
|             return Response(msg, status=status.HTTP_400_BAD_REQUEST)
 | |
|         serializer.save(update_by=request.user)
 | |
|         return Response()
 | |
| 
 | |
| 
 | |
| class ClockRecordViewSet(CreateModelMixin, ListModelMixin, GenericViewSet):
 | |
|     """
 | |
|     打卡记录
 | |
|     """
 | |
|     perms_map = {'get':'*', 'post':'*'}
 | |
|     authentication_classes = []
 | |
|     permission_classes = [AllowAny]
 | |
|     queryset = ClockRecord.objects.select_related('create_by').all()
 | |
|     serializer_class = ClockRecordListSerializer
 | |
|     filterset_class = ClockRecordFilterSet
 | |
|     ordering = ['-pk']
 | |
| 
 | |
|     def get_serializer_class(self):
 | |
|         if self.action == 'create':
 | |
|             return FaceClockCreateSerializer
 | |
|         return super().get_serializer_class()
 | |
| 
 | |
|     def create(self, request, *args, **kwargs):
 | |
|         now = timezone.now()
 | |
|         now_local = timezone.localtime()
 | |
|         if 8<=now_local.hour<=17:
 | |
|             base64_data = base64.urlsafe_b64decode(tran64(
 | |
|                 request.data.get('base64').replace(' ', '+')))
 | |
|             user, msg = HRMService.face_compare_from_base64(base64_data)
 | |
|             if user:
 | |
|                 ins, created = ClockRecord.objects.get_or_create(
 | |
|                     create_by = user, create_time__hour__range = [8,18], 
 | |
|                     create_time__year=now_local.year, create_time__month=now_local.month, 
 | |
|                     create_time__day=now_local.day,
 | |
|                     defaults={
 | |
|                         'type':ClockRecord.ClOCK_WORK1,
 | |
|                         'create_by':user,
 | |
|                         'create_time':now
 | |
|                     })
 | |
|                 if not created:
 | |
|                     ins.update_time = now
 | |
|                     ins.save()
 | |
|                 # 设为在岗
 | |
|                 user.is_atwork = True
 | |
|                 user.last_check_time = now
 | |
|                 user.save()
 | |
|                 return Response(UserSimpleSerializer(instance=user).data)
 | |
|             return Response(msg, status=status.HTTP_400_BAD_REQUEST)
 | |
|         return Response('非打卡时间范围', status=status.HTTP_400_BAD_REQUEST)
 | |
|         
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| import base64
 | |
| 
 | |
| def tran64(s):
 | |
|     missing_padding = len(s) % 4
 | |
|     if missing_padding != 0:
 | |
|         s = s+'='* (4 - missing_padding)
 | |
|     return s
 | |
| 
 | |
| class FaceLogin(CreateAPIView):
 | |
|     authentication_classes = []
 | |
|     permission_classes = []
 | |
|     serializer_class = FaceLoginSerializer
 | |
| 
 | |
| 
 | |
|     def create(self, request, *args, **kwargs):
 | |
|         """
 | |
|         人脸识别登录
 | |
|         """
 | |
|         base64_data = base64.urlsafe_b64decode(tran64(request.data.get('base64').replace(' ', '+')))
 | |
|         user, msg = HRMService.face_compare_from_base64(base64_data)
 | |
|         if user:
 | |
|             refresh = RefreshToken.for_user(user)
 | |
|             return Response({
 | |
|                 'refresh': str(refresh),
 | |
|                 'access': str(refresh.access_token),
 | |
|                 'username':user.username
 | |
|             }) 
 | |
|         return Response(msg, status=status.HTTP_400_BAD_REQUEST) |