316 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
			
		
		
	
	
			316 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
from datetime import timedelta
 | 
						|
from rest_framework.serializers import ModelSerializer
 | 
						|
from rest_framework import serializers
 | 
						|
from apps.hrm.services import HrmService
 | 
						|
from apps.utils.fields import MyFilePathField
 | 
						|
from django.utils import timezone
 | 
						|
 | 
						|
 | 
						|
from apps.utils.serializers import CustomModelSerializer
 | 
						|
from apps.utils.constants import EXCLUDE_FIELDS
 | 
						|
from apps.hrm.models import Certificate, ClockRecord, Employee, NotWorkRemark, Attendance
 | 
						|
from apps.system.serializers import DeptSimpleSerializer, UserSimpleSerializer
 | 
						|
from django.db import transaction
 | 
						|
from django.core.cache import cache
 | 
						|
from apps.utils.tools import check_id_number_strict, get_info_from_id
 | 
						|
from rest_framework.exceptions import ParseError
 | 
						|
from django.conf import settings
 | 
						|
import datetime
 | 
						|
 | 
						|
 | 
						|
class EmployeeShortSerializer(CustomModelSerializer):
 | 
						|
    belong_dept_name = serializers.CharField(
 | 
						|
        source='belong_dept.name', read_only=True)
 | 
						|
 | 
						|
    class Meta:
 | 
						|
        model = Employee
 | 
						|
        fields = ['id', 'name', 'belong_dept_name',
 | 
						|
                  'user', 'third_info', 'type']
 | 
						|
 | 
						|
 | 
						|
class EmployeeSimpleSerializer(CustomModelSerializer):
 | 
						|
    belong_dept_name = serializers.CharField(
 | 
						|
        source='belong_dept.name', read_only=True)
 | 
						|
    post_name = serializers.CharField(source='post.name', read_only=True)
 | 
						|
    location = serializers.SerializerMethodField()
 | 
						|
 | 
						|
    class Meta:
 | 
						|
        model = Employee
 | 
						|
        fields = ['id', 'type', 'name', 'belong_dept', 'belong_dept_name', 'post',
 | 
						|
                  'post_name', 'photo', 'third_info', 'number', 'id_number', 'location']
 | 
						|
 | 
						|
    def get_location(self, obj):
 | 
						|
        key_str = 'ep_{}'.format(obj.id)
 | 
						|
        return cache.get(key_str, None)
 | 
						|
 | 
						|
# class EmployeeBaseSerializer(CustomModelSerializer):
 | 
						|
#     def save(self, **kwargs):
 | 
						|
#         if self.validated_data.get('user', None):
 | 
						|
#             user = self.validated_data['user']
 | 
						|
#             self.validated_data['name'] = user.name
 | 
						|
#             self.validated_data['belong_dept'] = user.belong_dept
 | 
						|
#         return super().save(**kwargs)
 | 
						|
 | 
						|
 | 
						|
class EmployeeCreateUpdateSerializer(CustomModelSerializer):
 | 
						|
    id_number = serializers.CharField(
 | 
						|
        label="身份证号", validators=[check_id_number_strict])
 | 
						|
 | 
						|
    class Meta:
 | 
						|
        model = Employee
 | 
						|
        exclude = EXCLUDE_FIELDS + ['is_atwork', 'last_check_time',
 | 
						|
                                    'not_work_remark',
 | 
						|
                                    'third_info',
 | 
						|
                                    'type', 'phone', 'belong_dept', 'post', 'user']
 | 
						|
        extra_kwargs = {
 | 
						|
            'number': {'required': True},
 | 
						|
            'photo': {'required': True},
 | 
						|
            'id_number': {'required': True},
 | 
						|
        }
 | 
						|
 | 
						|
    @transaction.atomic
 | 
						|
    def create(self, validated_data):
 | 
						|
        instance = super().create(validated_data)
 | 
						|
        if instance.type == 'employee':
 | 
						|
            # 如果是内部员工
 | 
						|
            HrmService.sync_dahua_employee(ep=instance)
 | 
						|
        return instance
 | 
						|
 | 
						|
    def update(self, instance, validated_data):
 | 
						|
        id_number = validated_data['id_number']
 | 
						|
        ret = get_info_from_id(id_number)
 | 
						|
        validated_data['gender'] = ret['gender']
 | 
						|
        old_photo = instance.photo
 | 
						|
        old_job_state = instance.job_state
 | 
						|
        old_name = instance.name
 | 
						|
        instance = super().update(instance, validated_data)
 | 
						|
        if old_photo != instance.photo:  # 如果照片有变动,需要更新人脸库
 | 
						|
            # 使用的是face_recongition
 | 
						|
            face_data, msg = HrmService.get_facedata_from_img_x(
 | 
						|
                settings.BASE_DIR + instance.photo)
 | 
						|
            in_face_data = instance.face_data
 | 
						|
            if face_data:
 | 
						|
                if isinstance(in_face_data, dict):
 | 
						|
                    in_face_data['dlib'] = face_data
 | 
						|
                    instance.face_data = in_face_data
 | 
						|
                    instance.save()
 | 
						|
                else:
 | 
						|
                    instance.face_data = {'dlib': face_data}
 | 
						|
                    instance.save()
 | 
						|
            else:
 | 
						|
                raise ParseError(msg)
 | 
						|
            from apps.hrm.tasks import update_all_facedata_cache
 | 
						|
            update_all_facedata_cache.delay()
 | 
						|
        if instance.user and instance != old_name:
 | 
						|
            instance.user.name = instance.name
 | 
						|
            instance.user.save()
 | 
						|
        if instance.type == 'remployee':  # 如果是相关方
 | 
						|
            from apps.rpm.services import sync_to_rep
 | 
						|
            sync_to_rep(instance)
 | 
						|
        elif instance.type in ['visitor', 'driver']:  # 如果是访客或司机
 | 
						|
            from apps.vm.services import sync_to_visitor
 | 
						|
            sync_to_visitor(instance)
 | 
						|
        if instance.job_state in [20, 30] and instance.user:  # 如果离职了删除账户
 | 
						|
            instance.user.is_deleted = True
 | 
						|
            instance.user.save()
 | 
						|
            # 同时去除门禁授权
 | 
						|
        # 如果是正式员工或相关方且有门禁权限:
 | 
						|
        now = timezone.now()
 | 
						|
        if instance.type in ['employee', 'remployee']:
 | 
						|
            start_time = None
 | 
						|
            end_time = None
 | 
						|
            # 如果是正式员工,给长时间期限
 | 
						|
            if instance.third_info.get('dh_face_card', None) is None and instance.type == 'employee':
 | 
						|
                start_time = now
 | 
						|
                end_time = now + timedelta(days=7300)
 | 
						|
            if instance.job_state in [20, 30] and old_job_state == 10:  # 离职或退休
 | 
						|
                start_time = now
 | 
						|
                end_time = now + timedelta(hours=8)
 | 
						|
            # 正式员工重新在职
 | 
						|
            elif instance.job_state == 10 and old_job_state in [20, 30] and instance.type == 'employee':
 | 
						|
                start_time = now
 | 
						|
                end_time = now + timedelta(days=7300)
 | 
						|
            HrmService.sync_dahua_employee(ep=instance, old_photo=old_photo,
 | 
						|
                                           start_time=start_time, end_time=end_time)
 | 
						|
        return instance
 | 
						|
 | 
						|
 | 
						|
class EmployeeImproveSerializer(CustomModelSerializer):
 | 
						|
    photo_f = MyFilePathField(source='photo', read_only=True)
 | 
						|
    signature_f = MyFilePathField(source='signature', read_only=True)
 | 
						|
 | 
						|
    class Meta:
 | 
						|
        model = Employee
 | 
						|
        fields = ['photo', 'id_number', 'email', 'gender',
 | 
						|
                  'signature', 'photo_f', 'signature_f', 'phone']
 | 
						|
        extra_kwargs = {
 | 
						|
            'number': {'required': True},
 | 
						|
            'photo': {'required': True},
 | 
						|
            'id_number': {'required': True},
 | 
						|
        }
 | 
						|
 | 
						|
    def update(self, instance, validated_data):
 | 
						|
        id_number = validated_data['id_number']
 | 
						|
        ret = get_info_from_id(id_number)
 | 
						|
        validated_data['gender'] = ret['gender']
 | 
						|
        return super().update(instance, validated_data)
 | 
						|
 | 
						|
 | 
						|
class ChannelAuthoritySerializer(serializers.Serializer):
 | 
						|
    # pks = serializers.ListField(child=serializers.CharField(max_length=20), label="员工ID列表")
 | 
						|
    start_time = serializers.DateTimeField(label="开始时间")
 | 
						|
    end_time = serializers.DateTimeField(label="结束时间")
 | 
						|
 | 
						|
 | 
						|
class EmployeeSerializer(CustomModelSerializer):
 | 
						|
    belong_dept_ = DeptSimpleSerializer(source='belong_dept', read_only=True)
 | 
						|
    user_ = UserSimpleSerializer(source='user', read_only=True)
 | 
						|
    belong_dept_name = serializers.CharField(
 | 
						|
        source='belong_dept.name', read_only=True)
 | 
						|
    post_name = serializers.CharField(source='post.name', read_only=True)
 | 
						|
    blt_ = serializers.SerializerMethodField()
 | 
						|
    photo_f = MyFilePathField(source='photo', read_only=True)
 | 
						|
    signature_f = MyFilePathField(source='signature', read_only=True)
 | 
						|
 | 
						|
    class Meta:
 | 
						|
        model = Employee
 | 
						|
        fields = '__all__'
 | 
						|
        read_only_fields = ['is_atwork', 'last_check_time', 'not_work_remark']
 | 
						|
 | 
						|
    def get_blt_(self, obj):
 | 
						|
        if hasattr(obj, 'blt'):
 | 
						|
            from apps.third.serializers import TDeviceSimpleSerializer
 | 
						|
            return TDeviceSimpleSerializer(instance=obj.blt).data
 | 
						|
        # if hasattr(obj, 'tdevice'):
 | 
						|
        #     from apps.third.serializers import TDeviceSimpleSerializer
 | 
						|
        #     return TDeviceSimpleSerializer(instance=obj.tdevice).data
 | 
						|
        return
 | 
						|
 | 
						|
 | 
						|
class EmployeeDetailSerializer(EmployeeSerializer):
 | 
						|
    # door_range = serializers.SerializerMethodField()
 | 
						|
    location = serializers.SerializerMethodField()
 | 
						|
 | 
						|
    # def get_door_range(self, obj):
 | 
						|
    #     third_info = obj.third_info
 | 
						|
    #     dh_face_card = third_info.get('dh_face_card', None)
 | 
						|
    #     if dh_face_card:
 | 
						|
    #         _, res = dhClient.request(**dhapis['card_detail'], params={'cardNumber': dh_face_card})
 | 
						|
    #         return [res['startDate'], res['endDate']]
 | 
						|
 | 
						|
    def get_location(self, obj):
 | 
						|
        key_str = 'ep_{}'.format(obj.id)
 | 
						|
        return cache.get(key_str, None)
 | 
						|
 | 
						|
 | 
						|
class EmployeeNotWorkRemarkSerializer(ModelSerializer):
 | 
						|
    class Meta:
 | 
						|
        model = Employee
 | 
						|
        fields = ['not_work_remark']
 | 
						|
 | 
						|
 | 
						|
class ClockRecordListSerializer(serializers.ModelSerializer):
 | 
						|
    employee_ = EmployeeSimpleSerializer(source='employee', read_only=True)
 | 
						|
 | 
						|
    class Meta:
 | 
						|
        model = ClockRecord
 | 
						|
        fields = '__all__'
 | 
						|
 | 
						|
 | 
						|
class ClockRecordCreateSerializer(serializers.ModelSerializer):
 | 
						|
    clock_time = serializers.DateTimeField(label='打卡时间', required=True)
 | 
						|
 | 
						|
    class Meta:
 | 
						|
        model = ClockRecord
 | 
						|
        fields = ['id', 'type', 'employee', 'clock_time']
 | 
						|
 | 
						|
    def validate(self, attrs):
 | 
						|
        attrs['trigger'] = 'manual'
 | 
						|
        return attrs
 | 
						|
 | 
						|
 | 
						|
class ClockRecordSimpleSerializer(serializers.ModelSerializer):
 | 
						|
    class Meta:
 | 
						|
        model = ClockRecord
 | 
						|
        fields = ['id', 'type', 'exception_type', 'detail']
 | 
						|
 | 
						|
 | 
						|
class NotWorkRemarkListSerializer(serializers.ModelSerializer):
 | 
						|
    class Meta:
 | 
						|
        model = NotWorkRemark
 | 
						|
        fields = '__all__'
 | 
						|
 | 
						|
 | 
						|
class CertificateCreateUpdateSerializer(CustomModelSerializer):
 | 
						|
    file_f = MyFilePathField(source='file', read_only=True)
 | 
						|
 | 
						|
    class Meta:
 | 
						|
        model = Certificate
 | 
						|
        exclude = EXCLUDE_FIELDS
 | 
						|
 | 
						|
 | 
						|
class CertificateSerializer(CustomModelSerializer):
 | 
						|
    employee_name = serializers.CharField(
 | 
						|
        source='employee.name', read_only=True)
 | 
						|
    file_f = MyFilePathField(source='file', read_only=True)
 | 
						|
 | 
						|
    class Meta:
 | 
						|
        model = Certificate
 | 
						|
        fields = '__all__'
 | 
						|
 | 
						|
 | 
						|
class CorrectSerializer(serializers.Serializer):
 | 
						|
    start_time = serializers.DateTimeField()
 | 
						|
    end_time = serializers.DateTimeField()
 | 
						|
 | 
						|
 | 
						|
class AttendanceSerializer(CustomModelSerializer):
 | 
						|
    user_name = serializers.CharField(
 | 
						|
        source='user.name', read_only=True)
 | 
						|
    belong_dept_name = serializers.CharField(
 | 
						|
        source='user.belong_dept.name', read_only=True)
 | 
						|
    shift_name = serializers.CharField(source='shift.name', read_only=True)
 | 
						|
    post_name = serializers.CharField(
 | 
						|
        source='user.post.name', read_only=True)
 | 
						|
    team_name = serializers.CharField(source='team.name', read_only=True)
 | 
						|
    work_time_start = serializers.DateTimeField(read_only=True)
 | 
						|
    work_time_end = serializers.DateTimeField(read_only=True)
 | 
						|
 | 
						|
    class Meta:
 | 
						|
        model = Attendance
 | 
						|
        fields = '__all__'
 | 
						|
        extra_kwargs = {'team': {'required': True}, 'post': {'required': True}}
 | 
						|
 | 
						|
    def create(self, validated_data):
 | 
						|
        user = validated_data['user']
 | 
						|
        shift = validated_data['shift']
 | 
						|
        work_date = validated_data['work_date']
 | 
						|
        att = Attendance.objects.filter(
 | 
						|
            user=user, work_date=work_date, shift=shift).first()
 | 
						|
        if att:
 | 
						|
            att.note = validated_data.get('note', '')
 | 
						|
            att.state = validated_data['state']
 | 
						|
            att.update_by = self.context['request'].user
 | 
						|
            att.save()
 | 
						|
            return att
 | 
						|
        else:
 | 
						|
            start_time_o = shift.start_time_o
 | 
						|
            end_time_o = shift.end_time_o
 | 
						|
            if end_time_o >= start_time_o:
 | 
						|
                validated_data['work_time_start'] = datetime.datetime.combine(
 | 
						|
                    work_date, start_time_o)
 | 
						|
                validated_data['work_time_end'] = datetime.datetime.combine(
 | 
						|
                    work_date, end_time_o)
 | 
						|
            else:
 | 
						|
                validated_data['work_time_start'] = datetime.datetime.combine(
 | 
						|
                    work_date, start_time_o) - datetime.timedelta(days=1)
 | 
						|
                validated_data['work_time_end'] = datetime.datetime.combine(
 | 
						|
                    work_date, end_time_o)
 | 
						|
            return super().create(validated_data)
 | 
						|
 | 
						|
    def update(self, instance, validated_data):
 | 
						|
        new_data = {}
 | 
						|
        new_data['note'] = validated_data.get('note', '')
 | 
						|
        new_data['state'] = validated_data['state']
 | 
						|
        return super().update(instance, validated_data)
 |