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']
|