创建用户时默认部门为空

This commit is contained in:
caoqianming 2022-04-12 14:14:06 +08:00
parent 1e81f38343
commit b4db266dd9
9 changed files with 32 additions and 182 deletions

1
apps/hrm/errors.py Normal file
View File

@ -0,0 +1 @@
NO_NEED_LEVEL_REMARK = {"code":"no_need_level_remark", "detail":"无需填写离岗说明"}

View File

@ -2,12 +2,12 @@ from django.db import models
from django.db.models.query import QuerySet from django.db.models.query import QuerySet
from apps.system.models import User from apps.system.models import User
from apps.utils.models import CommonADModel, CommonAModel from apps.utils.models import CommonADModel, CommonAModel, CommonBModel
class Employee(CommonAModel): class Employee(CommonBModel):
""" """
员工信息 员工信息
""" """
@ -28,7 +28,7 @@ class Employee(CommonAModel):
id_number = models.CharField('身份证号', max_length=100, null=True, blank=True) id_number = models.CharField('身份证号', max_length=100, null=True, blank=True)
gender = models.CharField('性别', max_length=10, default='') gender = models.CharField('性别', max_length=10, default='')
signature = models.CharField('签名图片', max_length=200, null=True, blank=True) signature = models.CharField('签名图片', max_length=200, null=True, blank=True)
birthday = models.DateField('出生年月', null=True, blank=True) birthday = models.DateField('出生年月', null=True, blank=True)
qualification = models.CharField('学历', max_length=50, null=True, blank=True) qualification = models.CharField('学历', max_length=50, null=True, blank=True)
job_state = models.IntegerField('在职状态', choices=jobstate_choices, default=1) job_state = models.IntegerField('在职状态', choices=jobstate_choices, default=1)
face_data = models.JSONField('人脸识别数据', null=True, blank=True) face_data = models.JSONField('人脸识别数据', null=True, blank=True)

View File

@ -2,13 +2,13 @@ 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 utils.mixins import DynamicFieldsSerializerMixin from apps.utils.serializers import CustomModelSerializer
from .models import ClockRecord, Employee, NotWorkRemark
from apps.system.serializers import OrganizationSimpleSerializer, UserSimpleSerializer
class EmployeeSerializer(DynamicFieldsSerializerMixin, ModelSerializer): from .models import ClockRecord, Employee, NotWorkRemark
name = serializers.CharField(source='user.name', read_only=True) from apps.system.serializers import DeptSimpleSerializer,UserSimpleSerializer
dept_ = OrganizationSimpleSerializer(source='user.dept', read_only=True)
class EmployeeSerializer(CustomModelSerializer):
belong_dept_ = DeptSimpleSerializer(source='user.belong_dept', read_only=True)
class Meta: class Meta:
model = Employee model = Employee
exclude = ['face_data'] exclude = ['face_data']
@ -17,13 +17,6 @@ class EmployeeNotWorkRemarkSerializer(ModelSerializer):
class Meta: class Meta:
model = Employee model = Employee
fields = ['not_work_remark'] fields = ['not_work_remark']
class FaceLoginSerializer(serializers.Serializer):
base64 = serializers.CharField()
class FaceClockCreateSerializer(serializers.Serializer):
base64 = serializers.CharField()
class ClockRecordListSerializer(serializers.ModelSerializer): class ClockRecordListSerializer(serializers.ModelSerializer):
create_by_ = UserSimpleSerializer(source='create_by', read_only=True) create_by_ = UserSimpleSerializer(source='create_by', read_only=True)

View File

@ -1,50 +0,0 @@
from django.conf import settings
import uuid
import face_recognition
import os
from apps.hrm.models import Employee
from apps.hrm.tasks import update_all_user_facedata_cache
from apps.system.models import User
from django.core.cache import cache
class HRMService:
@classmethod
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, num_jitters=2)[0]
os.remove(filepath)
except:
os.remove(filepath)
return None, '识别失败,请调整位置'
# 匹配人脸库
face_datas = cache.get('face_datas')
if face_datas is None:
update_all_user_facedata_cache()
face_datas = cache.get('face_datas')
face_users = cache.get('face_users')
results = face_recognition.compare_faces(face_datas,
unknown_face_encoding, tolerance=0.45)
for index, value in enumerate(results):
if value:
# 识别成功
user = User.objects.get(id=face_users[index])
return user, ''
return None, '人脸未匹配,请调整位置'
@classmethod
def get_facedata_from_img(cls, img_path):
try:
photo_path = settings.BASE_DIR + img_path
picture_of_me = face_recognition.load_image_file(photo_path)
my_face_encoding = face_recognition.face_encodings(picture_of_me, num_jitters=2)[0]
face_data_list = my_face_encoding.tolist()
return face_data_list, ''
except:
return None, '人脸数据获取失败请重新上传图片'

View File

@ -2,7 +2,6 @@ from __future__ import absolute_import, unicode_literals
from celery import shared_task from celery import shared_task
from apps.hrm.models import Employee from apps.hrm.models import Employee
from django.core.cache import cache
@shared_task @shared_task
@ -12,19 +11,4 @@ def update_all_employee_not_atwork():
""" """
Employee.objects.all().update(is_atwork=False, last_check_time = None, not_work_remark=None) Employee.objects.all().update(is_atwork=False, last_check_time = None, not_work_remark=None)
@shared_task
def update_all_user_facedata_cache():
"""
更新人脸数据缓存
"""
facedata_queyset = Employee.objects.filter(face_data__isnull=False,
user__is_active=True).values('user', 'face_data')
face_users = []
face_datas = []
for i in facedata_queyset:
face_users.append(i['user'])
face_datas.append(i['face_data'])
cache.set('face_users', face_users, timeout=None)
cache.set('face_datas', face_datas, timeout=None)

View File

@ -1,12 +1,9 @@
from django.shortcuts import render from django.shortcuts import render
from django.utils import timezone from django.utils import timezone
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet, GenericViewSet
from rest_framework.mixins import UpdateModelMixin, RetrieveModelMixin, CreateModelMixin, ListModelMixin from rest_framework.mixins import UpdateModelMixin, RetrieveModelMixin, CreateModelMixin, ListModelMixin
from apps.hrm.errors import NO_NEED_LEVEL_REMARK
from apps.hrm.filters import ClockRecordFilterSet, EmployeeFilterSet, NotWorkRemarkFilterSet from apps.hrm.filters import ClockRecordFilterSet, EmployeeFilterSet, NotWorkRemarkFilterSet
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, NotWorkRemark from apps.hrm.models import ClockRecord, Employee, NotWorkRemark
from apps.hrm.serializers import ClockRecordListSerializer, EmployeeNotWorkRemarkSerializer, EmployeeSerializer, FaceClockCreateSerializer, FaceLoginSerializer, NotWorkRemarkListSerializer from apps.hrm.serializers import ClockRecordListSerializer, EmployeeNotWorkRemarkSerializer, EmployeeSerializer, FaceClockCreateSerializer, FaceLoginSerializer, NotWorkRemarkListSerializer
@ -20,18 +17,20 @@ from apps.system.models import User
from apps.system.serializers import UserSimpleSerializer from apps.system.serializers import UserSimpleSerializer
from rest_framework.permissions import AllowAny from rest_framework.permissions import AllowAny
from rest_framework.decorators import action from rest_framework.decorators import action
from apps.utils.viewsets import CustomModelViewSet, CustomGenericViewSet
from rest_framework.exceptions import ParseError
# Create your views here. # Create your views here.
class EmployeeViewSet(CreateUpdateModelAMixin, OptimizationMixin, UpdateModelMixin, ListModelMixin, RetrieveModelMixin, GenericViewSet): class EmployeeViewSet(CustomModelViewSet):
""" """
员工详细信息 员工信息管理
""" """
perms_map = {'get': '*', 'put': 'employee_update'}
queryset = Employee.objects.all() queryset = Employee.objects.all()
select_related_fields = ['user']
filterset_class = EmployeeFilterSet filterset_class = EmployeeFilterSet
serializer_class = EmployeeSerializer serializer_class = EmployeeSerializer
search_fields = ['user__name', 'number', 'user__username'] search_fields = ['name', 'number', 'user__username']
ordering = ['-pk'] ordering = ['-pk']
def update(self, request, *args, **kwargs): def update(self, request, *args, **kwargs):
@ -81,107 +80,30 @@ class EmployeeViewSet(CreateUpdateModelAMixin, OptimizationMixin, UpdateModelMix
instance.update_by = request.user instance.update_by = request.user
instance.save() instance.save()
return Response() return Response()
return Response('无需填写离岗说明', status=status.HTTP_400_BAD_REQUEST) raise ParseError(**NO_NEED_LEVEL_REMARK)
class ClockRecordViewSet(CreateModelMixin, ListModelMixin, GenericViewSet): class ClockRecordViewSet(ListModelMixin, CustomGenericViewSet):
""" """
打卡记录 打卡记录
""" """
perms_map = {'get':'*', 'post':'*'} perms_map = {'get':'*', 'post':'*'}
authentication_classes = [] authentication_classes = []
permission_classes = [AllowAny] permission_classes = [AllowAny]
queryset = ClockRecord.objects.select_related('create_by').all() queryset = ClockRecord.objects.all()
select_related_fields = ['create_by']
serializer_class = ClockRecordListSerializer serializer_class = ClockRecordListSerializer
filterset_class = ClockRecordFilterSet filterset_class = ClockRecordFilterSet
ordering = ['-pk'] 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()
# 设为在岗
Employee.objects.filter(user=user).update(is_atwork=True, last_check_time=now)
return Response(UserSimpleSerializer(instance=user).data)
return Response(msg, status=status.HTTP_400_BAD_REQUEST)
return Response('非打卡时间范围', status=status.HTTP_400_BAD_REQUEST)
class NotWorkRemarkViewSet(ListModelMixin, GenericViewSet): class NotWorkRemarkViewSet(ListModelMixin, CustomGenericViewSet):
""" """
离岗说明 离岗说明
""" """
perms_map = {'get':'*'} perms_map = {'get':'*'}
queryset = NotWorkRemark.objects.select_related('user').all() queryset = NotWorkRemark.objects.all()
select_related_fields = ['user']
serializer_class = NotWorkRemarkListSerializer serializer_class = NotWorkRemarkListSerializer
filterset_class = NotWorkRemarkFilterSet filterset_class = NotWorkRemarkFilterSet
ordering = ['-pk'] ordering = ['-pk']
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)
# 可设为在岗
now = timezone.now()
now_local = timezone.localtime()
if 8<=now_local.hour<=17:
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 created:
Employee.objects.filter(user=user).update(is_atwork=True, last_check_time=now)
return Response({
'refresh': str(refresh),
'access': str(refresh.access_token),
'username':user.username,
'name':user.name
})
return Response(msg, status=status.HTTP_400_BAD_REQUEST)

View File

@ -12,6 +12,7 @@ from rest_framework.exceptions import ParseError, APIException
from django.db import transaction from django.db import transaction
from apps.third.tapis import dhapis from apps.third.tapis import dhapis
from rest_framework.validators import UniqueValidator from rest_framework.validators import UniqueValidator
from django.contrib.auth.hashers import make_password
class IntervalSerializer(CustomModelSerializer): class IntervalSerializer(CustomModelSerializer):
class Meta: class Meta:
@ -273,6 +274,7 @@ class UserCreateSerializer(CustomModelSerializer):
class Meta: class Meta:
model = User model = User
fields = ['username', 'name', 'avatar', 'is_active'] fields = ['username', 'name', 'avatar', 'is_active']
class PasswordChangeSerializer(serializers.Serializer): class PasswordChangeSerializer(serializers.Serializer):

View File

@ -305,14 +305,10 @@ class UserViewSet(CustomModelViewSet):
创建用户 创建用户
""" """
password = request.data.get('password', None) password = make_password('0000')
if password:
password = make_password(password)
else:
password = make_password('0000')
serializer = self.get_serializer(data=request.data) serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True) serializer.is_valid(raise_exception=True)
serializer.save(password=password) serializer.save(password=password, belong_dept=None)
return Response(data=serializer.data) return Response(data=serializer.data)
@action(methods=['put'], detail=False, @action(methods=['put'], detail=False,

View File

@ -19,7 +19,9 @@ class CustomModelSerializer(DynamicFieldsMixin, serializers.ModelSerializer):
if self.request: if self.request:
if getattr(self.request, 'user', None): if getattr(self.request, 'user', None):
validated_data['create_by'] = self.request.user validated_data['create_by'] = self.request.user
if getattr(self.request.user, 'belong_dept', None): if 'belong_dept' in validated_data: # 如果指定数据归属部门
pass
elif getattr(self.request.user, 'belong_dept', None):
validated_data['belong_dept'] = self.request.user.belong_dept validated_data['belong_dept'] = self.request.user.belong_dept
return super().create(validated_data) return super().create(validated_data)