363 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
			
		
		
	
	
			363 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
 | 
						|
from django.conf import settings
 | 
						|
from django.db import transaction
 | 
						|
from django.utils import timezone
 | 
						|
from rest_framework import serializers
 | 
						|
from rest_framework.decorators import action
 | 
						|
from rest_framework.exceptions import ParseError
 | 
						|
from rest_framework.mixins import ListModelMixin
 | 
						|
from rest_framework.permissions import AllowAny, IsAuthenticated
 | 
						|
from rest_framework.response import Response
 | 
						|
 | 
						|
from apps.hrm.errors import NO_NEED_LEVEL_REMARK
 | 
						|
from apps.hrm.filters import (CertificateFilterSet, ClockRecordFilterSet, EmployeeFilterSet,
 | 
						|
                              NotWorkRemarkFilterSet)
 | 
						|
from apps.hrm.models import Certificate, ClockRecord, Employee, NotWorkRemark
 | 
						|
from apps.hrm.serializers import (CertificateCreateUpdateSerializer, CertificateSerializer, ChannelAuthoritySerializer,
 | 
						|
                                  ClockRecordListSerializer,
 | 
						|
                                  EmployeeCreateUpdateSerializer, EmployeeDetailSerializer, EmployeeImproveSerializer,
 | 
						|
                                  EmployeeNotWorkRemarkSerializer,
 | 
						|
                                  EmployeeSerializer,
 | 
						|
                                  ClockRecordSimpleSerializer,
 | 
						|
                                  NotWorkRemarkListSerializer, CorrectSerializer)
 | 
						|
from apps.hrm.services import HrmService
 | 
						|
 | 
						|
from apps.third.dahua import dhClient
 | 
						|
from apps.third.tapis import dhapis
 | 
						|
from apps.utils.export import export_excel
 | 
						|
from apps.utils.viewsets import CustomGenericViewSet, CustomModelViewSet
 | 
						|
 | 
						|
epTypeOptions = {'employee': '正式员工', 'remployee': '相关方',
 | 
						|
                 'visitor': '访客', 'driver': '货车司机'}
 | 
						|
epStateOptions = {10: '在职', 20: '离职', 30: '退休'}
 | 
						|
crOptions = {10: '上班打卡', 20: '下班打卡', 30: ''}
 | 
						|
crEoptions = {10: '在岗时间短', 20: '在岗时间长', 30: '缺卡', 40: '加班'}
 | 
						|
 | 
						|
# Create your views here.
 | 
						|
 | 
						|
 | 
						|
class EmployeeViewSet(CustomModelViewSet):
 | 
						|
    """
 | 
						|
    人员管理
 | 
						|
    """
 | 
						|
    queryset = Employee.objects.exclude(user__is_superuser=True)
 | 
						|
    select_related_fields = ['user']
 | 
						|
    filterset_class = EmployeeFilterSet
 | 
						|
    serializer_class = EmployeeSerializer
 | 
						|
    retrieve_serializer_class = EmployeeDetailSerializer
 | 
						|
    create_serializer_class = EmployeeCreateUpdateSerializer
 | 
						|
    update_serializer_class = EmployeeCreateUpdateSerializer
 | 
						|
    partial_update_serializer_class = EmployeeCreateUpdateSerializer
 | 
						|
    search_fields = ['name', 'number', 'user__username', 'id_number', 'id', 'phone']
 | 
						|
    ordering = ['-pk']
 | 
						|
 | 
						|
    # def filter_queryset(self, queryset):
 | 
						|
    #     if not self.detail:
 | 
						|
    #         self.request.query_params._mutable = True
 | 
						|
    #         self.request.query_params.setdefault('type', 'employee')
 | 
						|
    #     return super().filter_queryset(queryset)
 | 
						|
 | 
						|
    @action(methods=['get'], detail=False, perms_map={'get': '*'},
 | 
						|
            serializer_class=serializers.Serializer)
 | 
						|
    def info(self, request, pk=None):
 | 
						|
        """个人信息
 | 
						|
 | 
						|
        个人信息
 | 
						|
        """
 | 
						|
        user = request.user
 | 
						|
        ep, _ = Employee.objects.get_or_create(user=user,
 | 
						|
                                               defaults={
 | 
						|
                                                   "user": user,
 | 
						|
                                                   "name": user.name,
 | 
						|
                                                   "phone": user.phone,
 | 
						|
                                                   "belong_dept": user.belong_dept,
 | 
						|
                                                   "post": user.post,
 | 
						|
                                                   "type": user.type
 | 
						|
                                               })
 | 
						|
        return Response(EmployeeSerializer(instance=ep).data)
 | 
						|
 | 
						|
    @action(methods=['post'], detail=False, permission_classes=[IsAuthenticated],
 | 
						|
            serializer_class=EmployeeImproveSerializer)
 | 
						|
    @transaction.atomic
 | 
						|
    def improve_info(self, request, *args, **kwargs):
 | 
						|
        """完善个人信息
 | 
						|
 | 
						|
        完善个人信息
 | 
						|
        """
 | 
						|
        user = request.user
 | 
						|
        ep = user.employee
 | 
						|
        serializer = EmployeeImproveSerializer(instance=ep, data=request.data)
 | 
						|
        serializer.is_valid(raise_exception=True)
 | 
						|
        vdata = serializer.validated_data
 | 
						|
        if vdata.get('photo', None):
 | 
						|
            dhClient.request(**dhapis['person_img_upload'],
 | 
						|
                             file_path_rela=vdata['photo'])
 | 
						|
        serializer.save()
 | 
						|
        if ep.type == 'remployee':
 | 
						|
            from apps.rpm.services import sync_to_rep
 | 
						|
            sync_to_rep(ep)
 | 
						|
        elif ep.type in ['visitor', 'driver']:
 | 
						|
            from apps.vm.services import sync_to_visitor
 | 
						|
            sync_to_visitor(ep)
 | 
						|
        return Response()
 | 
						|
 | 
						|
    @action(methods=['post'], detail=True, perms_map={'post': 'employee.notworkremark'},
 | 
						|
            serializer_class=EmployeeNotWorkRemarkSerializer)
 | 
						|
    def not_work_remark(self, request, pk=None):
 | 
						|
        """
 | 
						|
        填写离岗说明
 | 
						|
        """
 | 
						|
        serializer = self.get_serializer(data=request.data)
 | 
						|
        serializer.is_valid(raise_exception=True)
 | 
						|
        obj = self.get_object()
 | 
						|
        if not obj.is_atwork:
 | 
						|
            remark = request.data.get('not_work_remark', '')
 | 
						|
            obj.not_work_remark = remark
 | 
						|
            obj.save()
 | 
						|
            now = timezone.now()
 | 
						|
            instance, created = NotWorkRemark.objects.get_or_create(
 | 
						|
                not_work_date=now.date(),
 | 
						|
                user=obj.user,
 | 
						|
                defaults={
 | 
						|
                    "not_work_date": now.date(),
 | 
						|
                    "user": obj.user,
 | 
						|
                    "remark": remark,
 | 
						|
                    "create_by": request.user,
 | 
						|
                }
 | 
						|
            )
 | 
						|
            if not created:
 | 
						|
                instance.remark = remark
 | 
						|
                instance.update_by = request.user
 | 
						|
                instance.save()
 | 
						|
            return Response()
 | 
						|
        raise ParseError(**NO_NEED_LEVEL_REMARK)
 | 
						|
 | 
						|
    @transaction.atomic
 | 
						|
    @action(methods=['post'], detail=True, perms_map={'post': 'employee.channel_authority'},
 | 
						|
            serializer_class=serializers.Serializer)
 | 
						|
    def channel_authority(self, request, pk=None):
 | 
						|
        """重新门禁授权
 | 
						|
 | 
						|
        重新门禁授权
 | 
						|
        """
 | 
						|
        obj = self.get_object()
 | 
						|
        if obj.third_info.get('dh_face_card', None):
 | 
						|
            HrmService.door_auth(ep=obj)
 | 
						|
        else:
 | 
						|
            raise ParseError('该员工缺少主卡')
 | 
						|
        # objs = Employee.objects.filter(pk__in=vdata['pks'], third_info__dh_face_card__isnull=False)
 | 
						|
        # infos = objs.values('third_info')
 | 
						|
        # cards = []
 | 
						|
        # for i in infos:
 | 
						|
        #     if isinstance(i['third_info'], dict) and 'dh_face_card' in i['third_info']:
 | 
						|
        #         cards.append(i['third_info']['dh_face_card'])
 | 
						|
        # details = []
 | 
						|
        # for i in vdata['channels']:
 | 
						|
        #     details.append({
 | 
						|
        #         "privilegeType": 1,
 | 
						|
        #         "resouceCode": i
 | 
						|
        #     })
 | 
						|
        # if cards and details:
 | 
						|
        #     json_data = {
 | 
						|
        #         "cardNumbers": cards,
 | 
						|
        #         "timeQuantumId": 1,
 | 
						|
        #         "cardPrivilegeDetails": details
 | 
						|
        #     }
 | 
						|
        #     dhClient.request(**dhapis['card_door_authority'], json=json_data)
 | 
						|
        #     for i in objs:
 | 
						|
        #         i.third_info['dh_channels'] = vdata['channels']
 | 
						|
        #     Employee.objects.bulk_update(objs, fields=['third_info'])
 | 
						|
        return Response()
 | 
						|
 | 
						|
    @transaction.atomic
 | 
						|
    @action(methods=['post'], detail=False, perms_map={'post': 'employee.face_bind_1'},
 | 
						|
            serializer_class=serializers.Serializer)
 | 
						|
    def face_bind_1(self, request, pk=None):
 | 
						|
        """同步人脸库1
 | 
						|
 | 
						|
        全部人脸库
 | 
						|
        """
 | 
						|
        # 获取设备
 | 
						|
        # json_data = {
 | 
						|
        #     "pageNum": 1,
 | 
						|
        #     "pageSize": 1000,
 | 
						|
        #     "ownerCodes": ['001'],
 | 
						|
        #     "showChildNodeData": 1,
 | 
						|
        #     # "isOnline":1
 | 
						|
        # }
 | 
						|
        # _, res = dhClient.request(**dhapis['dev_page'], json=json_data)
 | 
						|
        # devs = []
 | 
						|
        # if res['pageData']:
 | 
						|
        #     for i in res['pageData']:
 | 
						|
        #         devs.append(i['deviceCode'])
 | 
						|
        # 编辑人像库
 | 
						|
        json_data = {
 | 
						|
            "groupid": settings.DAHUA_FACEGROUPID_1,
 | 
						|
            "groupname": "全体人员",
 | 
						|
            "groupdetail": "全体人员",
 | 
						|
            "grouptype": 3,
 | 
						|
            "deviceCodeList": [settings.DAHUA_IVSS_CODE],
 | 
						|
            "syncState": 0
 | 
						|
        }
 | 
						|
        dhClient.request(**dhapis['face_group_update'], json=json_data)
 | 
						|
        # 人像绑定
 | 
						|
        dhClient.face_bind()
 | 
						|
        return Response()
 | 
						|
 | 
						|
    @action(methods=['get'], detail=False, perms_map={'get': 'employee.face_bind_1'},
 | 
						|
            serializer_class=serializers.Serializer)
 | 
						|
    def face_status_1(self, request, pk=None):
 | 
						|
        """人像下发状态
 | 
						|
 | 
						|
        人像下发状态
 | 
						|
        """
 | 
						|
        params = {'id': settings.DAHUA_FACEGROUPID_1}
 | 
						|
        _, res = dhClient.request(**dhapis['face_group_info'], params=params)
 | 
						|
        return Response(res)
 | 
						|
 | 
						|
    @action(methods=['get'], detail=False, perms_map={'get': '*'},
 | 
						|
            serializer_class=serializers.Serializer)
 | 
						|
    def export_excel(self, request, pk=None):
 | 
						|
        """导出excel
 | 
						|
        导出excel
 | 
						|
        """
 | 
						|
        field_data = ['人员类型', '人员', '手机号', '身份证号', '所属部门', '在职状态', '定位卡号']
 | 
						|
        queryset = self.filter_queryset(self.get_queryset())
 | 
						|
        if queryset.count() > 1000:
 | 
						|
            raise ParseError('数据量超过1000,请筛选后导出')
 | 
						|
        odata = EmployeeSerializer(queryset, many=True).data
 | 
						|
        # 处理数据
 | 
						|
        data = []
 | 
						|
        for i in odata:
 | 
						|
            data.append(
 | 
						|
                [epTypeOptions[i['type']],
 | 
						|
                 i['name'],
 | 
						|
                 i['phone'],
 | 
						|
                 i['id_number'],
 | 
						|
                 i.get('belong_dept_name', ''),
 | 
						|
                 epStateOptions[i['job_state']],
 | 
						|
                 i['blt_'].get('code', '') if 'blt_' in i and i['blt_'] else '']
 | 
						|
            )
 | 
						|
        return Response({'path': export_excel(field_data, data, '人员信息')})
 | 
						|
 | 
						|
 | 
						|
class ClockRecordViewSet(ListModelMixin, CustomGenericViewSet):
 | 
						|
    """
 | 
						|
    打卡记录
 | 
						|
    """
 | 
						|
    perms_map = {'get': '*', 'post': '*'}
 | 
						|
    queryset = ClockRecord.objects.all()
 | 
						|
    select_related_fields = ['employee']
 | 
						|
    search_fields = ['employee__name', 'employee__number', 'employee__phone']
 | 
						|
    serializer_class = ClockRecordListSerializer
 | 
						|
    filterset_class = ClockRecordFilterSet
 | 
						|
    ordering = ['-create_time']
 | 
						|
 | 
						|
    @action(methods=['get'], detail=False, perms_map={'get': '*'},
 | 
						|
            serializer_class=serializers.Serializer)
 | 
						|
    def export_excel(self, request, pk=None):
 | 
						|
        """导出excel
 | 
						|
        导出excel
 | 
						|
        """
 | 
						|
        field_data = ['人员类型', '人员', '编号', '身份证号', '所属部门', '触发形式', '打卡时间', '打卡推测', '异常推测']
 | 
						|
        queryset = self.filter_queryset(self.get_queryset())
 | 
						|
        odata = ClockRecordListSerializer(queryset, many=True).data
 | 
						|
        # 处理数据
 | 
						|
        data = []
 | 
						|
        for i in odata:
 | 
						|
            data.append(
 | 
						|
                [epTypeOptions[i['employee_']['type']],
 | 
						|
                 i['employee_']['name'],
 | 
						|
                 i['employee_']['number'],
 | 
						|
                 i['employee_']['id_number'],
 | 
						|
                 i['employee_'].get('belong_dept_name', ''),
 | 
						|
                 i['detail'].get('deviceName', None),
 | 
						|
                 i['create_time'],
 | 
						|
                 crOptions[i['type']],
 | 
						|
                 crEoptions[i['exception_type']] if i['exception_type'] else '']
 | 
						|
            )
 | 
						|
        return Response({'path': export_excel(field_data, data, '打卡记录')})
 | 
						|
 | 
						|
 | 
						|
    @action(methods=['post'], detail=False, perms_map={'post': '*'},
 | 
						|
            serializer_class=serializers.Serializer, logging_methods=[])
 | 
						|
    def dahua(self, request):
 | 
						|
        """
 | 
						|
        大华刷脸分页带my_info
 | 
						|
 | 
						|
        大华刷脸分页带my_info
 | 
						|
        """
 | 
						|
        request.data.update({
 | 
						|
            "openType":"61",
 | 
						|
            })
 | 
						|
        _, res = dhClient.request(**dhapis['swipe_list'], json=request.data)
 | 
						|
        ids = []
 | 
						|
        if res.get('pageData', None):
 | 
						|
            for i in res['pageData']:
 | 
						|
                ids.append(i['id'])
 | 
						|
            crs_info = ClockRecordSimpleSerializer(instance=ClockRecord.objects.filter(detail__id__in=ids), many=True).data
 | 
						|
            crs_dict = {}
 | 
						|
            for i in crs_info:
 | 
						|
                crs_dict[i['detail']['id']] = i
 | 
						|
            for i in res['pageData']:
 | 
						|
                i['my_info'] = {}
 | 
						|
                if i['id'] in crs_dict:
 | 
						|
                    i['my_info'] = crs_dict[i['id']]
 | 
						|
        return Response(res)
 | 
						|
 | 
						|
 | 
						|
    # @action(methods=['post'], detail=False, perms_map={'post': '*'},
 | 
						|
    #         serializer_class=CorrectSerializer)
 | 
						|
    # def correct_swip(self, request, pk=None):
 | 
						|
    #     """
 | 
						|
    #     重跑一段时间的打卡记录
 | 
						|
 | 
						|
    #     重跑一段时间的打卡记录
 | 
						|
    #     """
 | 
						|
    #     sr = CorrectSerializer(data=request.data)
 | 
						|
    #     sr.is_valid(raise_exception=True)
 | 
						|
    #     vdata = sr.validated_data
 | 
						|
    #     from apps.hrm.tasks import correct_swip_task
 | 
						|
    #     correct_swip_task.delay(vdata['start_time'], vdata['end_time'])
 | 
						|
    #     return Response()
 | 
						|
 | 
						|
    # @action(methods=['post'], detail=False, perms_map={'post': '*'},
 | 
						|
    #         serializer_class=CorrectSerializer)
 | 
						|
    # def correct_enter_or_exit(self, request, pk=None):
 | 
						|
    #     """
 | 
						|
    #     变更一段时间日志刷脸类型
 | 
						|
 | 
						|
    #     变更一段时间日志刷脸类型
 | 
						|
    #     """
 | 
						|
    #     from apps.monitor.models import DrfRequestLog
 | 
						|
    #     sr = CorrectSerializer(data=request.data)
 | 
						|
    #     sr.is_valid(raise_exception=True)
 | 
						|
    #     vdata = sr.validated_data
 | 
						|
    #     for i in DrfRequestLog.objects.filter(path='/api/third/dahua/c_swip/', data__contains='办公楼考勤面板'
 | 
						|
    #                                           , create_time__gte=vdata['start_time'] 
 | 
						|
    #                                           , create_time__lte=vdata['end_time']).filter(data__contains = "'enterOrExit': 1" ):
 | 
						|
    #         data = i.data
 | 
						|
    #         i.data = data.replace("'enterOrExit': 1", "'enterOrExit': 3")
 | 
						|
    #         i.save()
 | 
						|
    #     return Response()
 | 
						|
 | 
						|
class NotWorkRemarkViewSet(ListModelMixin, CustomGenericViewSet):
 | 
						|
    """
 | 
						|
    离岗说明
 | 
						|
    """
 | 
						|
    perms_map = {'get': '*'}
 | 
						|
    queryset = NotWorkRemark.objects.all()
 | 
						|
    select_related_fields = ['user']
 | 
						|
    serializer_class = NotWorkRemarkListSerializer
 | 
						|
    filterset_class = NotWorkRemarkFilterSet
 | 
						|
    ordering = ['-pk']
 | 
						|
 | 
						|
 | 
						|
class CertificateViewSet(CustomModelViewSet):
 | 
						|
    queryset = Certificate.objects.all()
 | 
						|
    create_serializer_class = CertificateCreateUpdateSerializer
 | 
						|
    update_serializer_class = CertificateCreateUpdateSerializer
 | 
						|
    serializer_class = CertificateSerializer
 | 
						|
    filterset_class = CertificateFilterSet
 | 
						|
    search_fields = ['name', 'number', 'employee__name']
 |