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_e, 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_e])
 | |
| 
 | |
|     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)
 |