打卡接口

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): def __str__(self):
return self.name 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 apps.system.models import User
from rest_framework.serializers import ModelSerializer from rest_framework.serializers import ModelSerializer
from rest_framework import serializers from rest_framework import serializers
from .models import Employee from .models import ClockRecord, Employee
from apps.system.serializers import UserListSerializer, UserSimpleSerializer from apps.system.serializers import UserListSerializer, UserSimpleSerializer
from django.db.models.query import Prefetch from django.db.models.query import Prefetch
@ -23,3 +23,13 @@ class EmployeeSerializer(ModelSerializer):
class FaceLoginSerializer(serializers.Serializer): class FaceLoginSerializer(serializers.Serializer):
base64 = serializers.CharField() 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 django.db.models import base
from rest_framework import urlpatterns 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 django.urls import path, include
from rest_framework.routers import DefaultRouter from rest_framework.routers import DefaultRouter
router = DefaultRouter() router = DefaultRouter()
router.register('employee', EmployeeViewSet, basename='employee') router.register('employee', EmployeeViewSet, basename='employee')
router.register('clock_record', ClockRecordViewSet, basename='clock_record')
urlpatterns = [ urlpatterns = [
path('facelogin/', FaceLogin.as_view()), path('facelogin/', FaceLogin.as_view()),
path('', include(router.urls)), path('', include(router.urls)),

View File

@ -1,10 +1,13 @@
from django.shortcuts import render from django.shortcuts import render
from pytz import timezone
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet, GenericViewSet 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.system.mixins import CreateUpdateModelAMixin, OptimizationMixin
from apps.hrm.models import Employee from apps.hrm.models import ClockRecord, Employee
from apps.hrm.serializers import EmployeeSerializer, FaceLoginSerializer from apps.hrm.serializers import ClockRecordListSerializer, EmployeeSerializer, FaceClockCreateSerializer, FaceLoginSerializer
import face_recognition import face_recognition
from django.conf import settings from django.conf import settings
from django.core.cache import cache from django.core.cache import cache
@ -12,8 +15,9 @@ import logging
from rest_framework.generics import CreateAPIView from rest_framework.generics import CreateAPIView
from rest_framework import status from rest_framework import status
from rest_framework_simplejwt.tokens import RefreshToken from rest_framework_simplejwt.tokens import RefreshToken
from rest_framework import exceptions
from apps.system.models import User from apps.system.models import User
from apps.system.serializers import UserSimpleSerializer
logger = logging.getLogger('log') logger = logging.getLogger('log')
@ -50,9 +54,51 @@ class EmployeeViewSet(CreateUpdateModelAMixin, OptimizationMixin, UpdateModelMix
except: except:
logger.error('人脸识别出错') 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 base64
import os
def tran64(s): def tran64(s):
missing_padding = len(s) % 4 missing_padding = len(s) % 4
@ -70,41 +116,13 @@ class FaceLogin(CreateAPIView):
""" """
人脸识别登录 人脸识别登录
""" """
# serializer = FaceLoginSerializer(data=request.data) base64_data = base64.urlsafe_b64decode(tran64(request.data.get('base64').replace(' ', '+')))
# serializer.is_valid(raise_exception=True) user, msg = HRMService.face_compare_from_base64(base64_data)
filename = str(uuid.uuid4()) if user:
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) refresh = RefreshToken.for_user(user)
return Response({ return Response({
'refresh': str(refresh), 'refresh': str(refresh),
'access': str(refresh.access_token), 'access': str(refresh.access_token),
'username':user.username 'username':user.username
}) })
return Response('未找到对应用户', status=status.HTTP_400_BAD_REQUEST) 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 from django.db import transaction
class WareHouseSerializer(serializers.ModelSerializer): class WareHouseSerializer(serializers.ModelSerializer):
create_by_ = UserSimpleSerializer('create_by', read_only=True) 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( superior = models.ForeignKey(
'self', null=True, blank=True, on_delete=models.SET_NULL, verbose_name='上级主管') 'self', null=True, blank=True, on_delete=models.SET_NULL, verbose_name='上级主管')
roles = models.ManyToManyField(Role, blank=True, verbose_name='角色') roles = models.ManyToManyField(Role, blank=True, verbose_name='角色')
is_atwork = models.BooleanField('当前在岗', default=False)
class Meta: class Meta:
verbose_name = '用户信息' verbose_name = '用户信息'