打卡接口

This commit is contained in:
caoqianming 2022-01-21 13:41:54 +08:00
parent 50ed7ea9ec
commit 509404994a
9 changed files with 150 additions and 51 deletions

View File

@ -0,0 +1,9 @@
from django_filters import rest_framework as filters
from apps.hrm.models import ClockRecord
class ClockRecordFilterSet(filters.FilterSet):
create_time_start = filters.DateFilter(field_name="create_time", lookup_expr='gte')
create_time_end = filters.DateFilter(field_name="create_time", lookup_expr='lte')
class Meta:
model = ClockRecord
fields = ['create_by', 'create_time_start', 'create_time_end']

View File

@ -36,8 +36,12 @@ class Employee(CommonAModel):
def __str__(self):
return self.name
# class Attendance(CommonADModel):
# """
# 出勤记录
# """
class ClockRecord(CommonADModel):
"""
打卡记录
"""
ClOCK_WORK1 = 10
type_choice = (
(ClOCK_WORK1, '上班打卡'),
)
type = models.PositiveSmallIntegerField('打卡类型', choices=type_choice, default=ClOCK_WORK1)

View File

@ -1,7 +1,7 @@
from apps.system.models import User
from rest_framework.serializers import ModelSerializer
from rest_framework import serializers
from .models import Employee
from .models import ClockRecord, Employee
from apps.system.serializers import UserListSerializer, UserSimpleSerializer
from django.db.models.query import Prefetch
@ -23,3 +23,13 @@ class EmployeeSerializer(ModelSerializer):
class FaceLoginSerializer(serializers.Serializer):
base64 = serializers.CharField()
class FaceClockCreateSerializer(serializers.Serializer):
base64 = serializers.CharField()
class ClockRecordListSerializer(serializers.ModelSerializer):
create_by_ = UserSimpleSerializer(source='create_by', read_only=True)
class Meta:
model = ClockRecord
fields = '__all__'

View File

@ -0,0 +1,37 @@
from django.conf import settings
import uuid
import face_recognition
import os
from apps.hrm.models import Employee
from apps.system.models import User
class HRMService:
def face_compare_from_base64(cls, base64_data):
filename = str(uuid.uuid4())
filepath = settings.BASE_DIR +'/temp/' + filename +'.png'
with open(filepath, 'wb') as f:
f.write(base64_data)
try:
unknown_picture = face_recognition.load_image_file(filepath)
unknown_face_encoding = face_recognition.face_encodings(unknown_picture)[0]
os.remove(filepath)
except:
os.remove(filepath)
return None, '头像解码失败'
# 匹配人脸库
user_faces = Employee.objects.filter(face_data__isnull=False, user__is_active=True).values('user', 'face_data')
user_l = []
face_l = []
for i in user_faces:
user_l.append(i['user'])
face_l.append(i['face_data'])
results = face_recognition.compare_faces(face_l, unknown_face_encoding, tolerance=0.5)
for index, value in enumerate(results):
if value:
# 识别成功
user = User.objects.get(id=user_l[index])
return user, ''
return None, '识别失败'

View File

@ -1,11 +1,12 @@
from django.db.models import base
from rest_framework import urlpatterns
from apps.hrm.views import EmployeeViewSet, FaceLogin
from apps.hrm.views import ClockRecordViewSet, EmployeeViewSet, FaceLogin
from django.urls import path, include
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register('employee', EmployeeViewSet, basename='employee')
router.register('clock_record', ClockRecordViewSet, basename='clock_record')
urlpatterns = [
path('facelogin/', FaceLogin.as_view()),
path('', include(router.urls)),

View File

@ -1,10 +1,13 @@
from django.shortcuts import render
from pytz import timezone
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet, GenericViewSet
from rest_framework.mixins import UpdateModelMixin, RetrieveModelMixin
from rest_framework.mixins import UpdateModelMixin, RetrieveModelMixin, CreateModelMixin, ListModelMixin
from apps.hrm.filters import ClockRecordFilterSet
from apps.hrm.services import HRMService
from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin
from apps.hrm.models import Employee
from apps.hrm.serializers import EmployeeSerializer, FaceLoginSerializer
from apps.hrm.models import ClockRecord, Employee
from apps.hrm.serializers import ClockRecordListSerializer, EmployeeSerializer, FaceClockCreateSerializer, FaceLoginSerializer
import face_recognition
from django.conf import settings
from django.core.cache import cache
@ -12,8 +15,9 @@ import logging
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
logger = logging.getLogger('log')
@ -50,9 +54,51 @@ class EmployeeViewSet(CreateUpdateModelAMixin, OptimizationMixin, UpdateModelMix
except:
logger.error('人脸识别出错')
import uuid
class ClockRecordViewSet(CreateModelMixin, ListModelMixin, GenericViewSet):
"""
打卡记录
"""
perms_map = {'get':'*', 'post':'*'}
authentication_classes = []
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):
base64_data = base64.urlsafe_b64decode(tran64(request.data.get('base64').replace(' ', '+')))
user, msg = HRMService.face_compare_from_base64(base64_data)
if user:
now = timezone.now()
if 7<=now.hour<=9:
ins, created = ClockRecord.objects.get_or_create(
create_by=request.user, create_time__hour__in = [7,8],
create_time__year=now.year, create_time__month=now.month, create_time__day=now.day,
defaults={
'type':ClockRecord.ClOCK_WORK1,
'create_by':user,
'create_time':now
})
if not created:
ins.create_time = now
ins.save()
# 设为在岗
user.is_atwork = True
user.save()
return Response(UserSimpleSerializer(instance=user).data)
return Response('打卡失败', status=status.HTTP_400_BAD_REQUEST)
return Response(msg, status=status.HTTP_400_BAD_REQUEST)
import base64
import os
def tran64(s):
missing_padding = len(s) % 4
@ -70,41 +116,13 @@ class FaceLogin(CreateAPIView):
"""
人脸识别登录
"""
# serializer = FaceLoginSerializer(data=request.data)
# serializer.is_valid(raise_exception=True)
filename = str(uuid.uuid4())
filepath = settings.BASE_DIR +'/temp/' + filename +'.png'
with open(filepath, 'wb') as f:
data = tran64(request.data.get('base64').replace(' ', '+'))
f.write(base64.urlsafe_b64decode(data))
# picture_of_me = face_recognition.load_image_file(settings.BASE_DIR +'/temp/me.png')
# my_face_encoding = face_recognition.face_encodings(picture_of_me)[0]
#results = face_recognition.compare_faces([my_face_encoding], unknown_face_encoding, tolerance=0.2)
try:
unknown_picture = face_recognition.load_image_file(filepath)
unknown_face_encoding = face_recognition.face_encodings(unknown_picture)[0]
os.remove(filepath)
except:
os.remove(filepath)
return Response('头像解码失败', status=status.HTTP_400_BAD_REQUEST)
# 匹配人脸库
user_faces = Employee.objects.filter(face_data__isnull=False, user__is_active=True).values('user', 'face_data')
user_l = []
face_l = []
for i in user_faces:
user_l.append(i['user'])
face_l.append(i['face_data'])
results = face_recognition.compare_faces(face_l, unknown_face_encoding, tolerance=0.5)
for index, value in enumerate(results):
if value:
# 识别成功
user = User.objects.get(id=user_l[index])
refresh = RefreshToken.for_user(user)
return Response({
'refresh': str(refresh),
'access': str(refresh.access_token),
'username':user.username
})
return Response('未找到对应用户', status=status.HTTP_400_BAD_REQUEST)
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)

View File

@ -9,6 +9,7 @@ from apps.mtm.serializers import MaterialSimpleSerializer
from django.db import transaction
class WareHouseSerializer(serializers.ModelSerializer):
create_by_ = UserSimpleSerializer('create_by', read_only=True)

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.9 on 2022-01-21 05:41
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('system', '0003_auto_20210812_0909'),
]
operations = [
migrations.AddField(
model_name='user',
name='is_atwork',
field=models.BooleanField(default=False, verbose_name='当前在岗'),
),
]

View File

@ -116,6 +116,7 @@ class User(AbstractUser):
superior = models.ForeignKey(
'self', null=True, blank=True, on_delete=models.SET_NULL, verbose_name='上级主管')
roles = models.ManyToManyField(Role, blank=True, verbose_name='角色')
is_atwork = models.BooleanField('当前在岗', default=False)
class Meta:
verbose_name = '用户信息'