feat: 查看门禁权限并支持删除
This commit is contained in:
parent
b4cc887f79
commit
b479db9f89
|
|
@ -17,14 +17,25 @@ from rest_framework.exceptions import ParseError
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
|
|
||||||
|
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']
|
||||||
|
|
||||||
|
|
||||||
class EmployeeSimpleSerializer(CustomModelSerializer):
|
class EmployeeSimpleSerializer(CustomModelSerializer):
|
||||||
belong_dept_name = serializers.CharField(source='belong_dept.name', 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)
|
post_name = serializers.CharField(source='post.name', read_only=True)
|
||||||
location = serializers.SerializerMethodField()
|
location = serializers.SerializerMethodField()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Employee
|
model = Employee
|
||||||
fields = ['id', 'type', 'name', 'belong_dept', 'belong_dept_name', 'post', 'post_name', 'photo', 'third_info', 'number', 'id_number', 'location']
|
fields = ['id', 'type', 'name', 'belong_dept', 'belong_dept_name', 'post',
|
||||||
|
'post_name', 'photo', 'third_info', 'number', 'id_number', 'location']
|
||||||
|
|
||||||
def get_location(self, obj):
|
def get_location(self, obj):
|
||||||
key_str = 'ep_{}'.format(obj.id)
|
key_str = 'ep_{}'.format(obj.id)
|
||||||
|
|
@ -40,7 +51,8 @@ class EmployeeSimpleSerializer(CustomModelSerializer):
|
||||||
|
|
||||||
|
|
||||||
class EmployeeCreateUpdateSerializer(CustomModelSerializer):
|
class EmployeeCreateUpdateSerializer(CustomModelSerializer):
|
||||||
id_number = serializers.CharField(label="身份证号", validators=[check_id_number_e])
|
id_number = serializers.CharField(
|
||||||
|
label="身份证号", validators=[check_id_number_e])
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Employee
|
model = Employee
|
||||||
|
|
@ -72,7 +84,8 @@ class EmployeeCreateUpdateSerializer(CustomModelSerializer):
|
||||||
instance = super().update(instance, validated_data)
|
instance = super().update(instance, validated_data)
|
||||||
if old_photo != instance.photo: # 如果照片有变动,需要更新人脸库
|
if old_photo != instance.photo: # 如果照片有变动,需要更新人脸库
|
||||||
# 使用的是face_recongition
|
# 使用的是face_recongition
|
||||||
face_data, msg = HrmService.get_facedata_from_img_x(settings.BASE_DIR + instance.photo)
|
face_data, msg = HrmService.get_facedata_from_img_x(
|
||||||
|
settings.BASE_DIR + instance.photo)
|
||||||
in_face_data = instance.face_data
|
in_face_data = instance.face_data
|
||||||
if face_data:
|
if face_data:
|
||||||
if isinstance(in_face_data, dict):
|
if isinstance(in_face_data, dict):
|
||||||
|
|
@ -104,17 +117,19 @@ class EmployeeCreateUpdateSerializer(CustomModelSerializer):
|
||||||
if instance.type in ['employee', 'remployee']:
|
if instance.type in ['employee', 'remployee']:
|
||||||
start_time = None
|
start_time = None
|
||||||
end_time = None
|
end_time = None
|
||||||
if instance.third_info.get('dh_face_card', None) is None and instance.type == 'employee': # 如果是正式员工,给长时间期限
|
# 如果是正式员工,给长时间期限
|
||||||
|
if instance.third_info.get('dh_face_card', None) is None and instance.type == 'employee':
|
||||||
start_time = now
|
start_time = now
|
||||||
end_time = now + timedelta(days=7300)
|
end_time = now + timedelta(days=7300)
|
||||||
if instance.job_state in [20, 30] and old_job_state == 10: # 离职或退休
|
if instance.job_state in [20, 30] and old_job_state == 10: # 离职或退休
|
||||||
start_time = now
|
start_time = now
|
||||||
end_time = now + timedelta(hours=8)
|
end_time = now + timedelta(hours=8)
|
||||||
elif instance.job_state == 10 and old_job_state in [20, 30] and instance.type == 'employee': # 正式员工重新在职
|
# 正式员工重新在职
|
||||||
|
elif instance.job_state == 10 and old_job_state in [20, 30] and instance.type == 'employee':
|
||||||
start_time = now
|
start_time = now
|
||||||
end_time = now + timedelta(days=7300)
|
end_time = now + timedelta(days=7300)
|
||||||
HrmService.sync_dahua_employee(ep=instance, old_photo=old_photo,
|
HrmService.sync_dahua_employee(ep=instance, old_photo=old_photo,
|
||||||
start_time=start_time, end_time=end_time)
|
start_time=start_time, end_time=end_time)
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -124,7 +139,8 @@ class EmployeeImproveSerializer(CustomModelSerializer):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Employee
|
model = Employee
|
||||||
fields = ['photo', 'id_number', 'email', 'gender', 'signature', 'photo_f', 'signature_f', 'phone']
|
fields = ['photo', 'id_number', 'email', 'gender',
|
||||||
|
'signature', 'photo_f', 'signature_f', 'phone']
|
||||||
extra_kwargs = {
|
extra_kwargs = {
|
||||||
'number': {'required': True},
|
'number': {'required': True},
|
||||||
'photo': {'required': True},
|
'photo': {'required': True},
|
||||||
|
|
@ -147,7 +163,8 @@ class ChannelAuthoritySerializer(serializers.Serializer):
|
||||||
class EmployeeSerializer(CustomModelSerializer):
|
class EmployeeSerializer(CustomModelSerializer):
|
||||||
belong_dept_ = DeptSimpleSerializer(source='belong_dept', read_only=True)
|
belong_dept_ = DeptSimpleSerializer(source='belong_dept', read_only=True)
|
||||||
user_ = UserSimpleSerializer(source='user', read_only=True)
|
user_ = UserSimpleSerializer(source='user', read_only=True)
|
||||||
belong_dept_name = serializers.CharField(source='belong_dept.name', 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)
|
post_name = serializers.CharField(source='post.name', read_only=True)
|
||||||
blt_ = serializers.SerializerMethodField()
|
blt_ = serializers.SerializerMethodField()
|
||||||
photo_f = MyFilePathField(source='photo', read_only=True)
|
photo_f = MyFilePathField(source='photo', read_only=True)
|
||||||
|
|
@ -161,7 +178,7 @@ class EmployeeSerializer(CustomModelSerializer):
|
||||||
def get_blt_(self, obj):
|
def get_blt_(self, obj):
|
||||||
if hasattr(obj, 'blt'):
|
if hasattr(obj, 'blt'):
|
||||||
from apps.third.serializers import TDeviceSimpleSerializer
|
from apps.third.serializers import TDeviceSimpleSerializer
|
||||||
return TDeviceSimpleSerializer(instance=obj.blt).data
|
return TDeviceSimpleSerializer(instance=obj.blt).data
|
||||||
# if hasattr(obj, 'tdevice'):
|
# if hasattr(obj, 'tdevice'):
|
||||||
# from apps.third.serializers import TDeviceSimpleSerializer
|
# from apps.third.serializers import TDeviceSimpleSerializer
|
||||||
# return TDeviceSimpleSerializer(instance=obj.tdevice).data
|
# return TDeviceSimpleSerializer(instance=obj.tdevice).data
|
||||||
|
|
@ -197,6 +214,7 @@ class ClockRecordListSerializer(serializers.ModelSerializer):
|
||||||
model = ClockRecord
|
model = ClockRecord
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
class ClockRecordSimpleSerializer(serializers.ModelSerializer):
|
class ClockRecordSimpleSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ClockRecord
|
model = ClockRecord
|
||||||
|
|
@ -218,7 +236,8 @@ class CertificateCreateUpdateSerializer(CustomModelSerializer):
|
||||||
|
|
||||||
|
|
||||||
class CertificateSerializer(CustomModelSerializer):
|
class CertificateSerializer(CustomModelSerializer):
|
||||||
employee_name = serializers.CharField(source='employee.name', read_only=True)
|
employee_name = serializers.CharField(
|
||||||
|
source='employee.name', read_only=True)
|
||||||
file_f = MyFilePathField(source='file', read_only=True)
|
file_f = MyFilePathField(source='file', read_only=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
@ -228,4 +247,4 @@ class CertificateSerializer(CustomModelSerializer):
|
||||||
|
|
||||||
class CorrectSerializer(serializers.Serializer):
|
class CorrectSerializer(serializers.Serializer):
|
||||||
start_time = serializers.DateTimeField()
|
start_time = serializers.DateTimeField()
|
||||||
end_time = serializers.DateTimeField()
|
end_time = serializers.DateTimeField()
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ class HrmService:
|
||||||
Returns:
|
Returns:
|
||||||
_type_: _description_
|
_type_: _description_
|
||||||
"""
|
"""
|
||||||
if not settings.DAHUA_ENABLED: # 如果大华没启用, 直接返回
|
if not settings.DAHUA_ENABLED: # 如果大华没启用, 直接返回
|
||||||
return
|
return
|
||||||
dh_id = ep.third_info.get('dh_id', None)
|
dh_id = ep.third_info.get('dh_id', None)
|
||||||
dh_photo = ep.third_info.get('dh_photo', None)
|
dh_photo = ep.third_info.get('dh_photo', None)
|
||||||
|
|
@ -68,7 +68,8 @@ class HrmService:
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
if ep.photo != old_photo and ep.photo:
|
if ep.photo != old_photo and ep.photo:
|
||||||
_, res = dhClient.request(**dhapis['person_img_upload'], file_path_rela=ep.photo)
|
_, res = dhClient.request(
|
||||||
|
**dhapis['person_img_upload'], file_path_rela=ep.photo)
|
||||||
dh_photo = res["fileUrl"]
|
dh_photo = res["fileUrl"]
|
||||||
json_data.update(
|
json_data.update(
|
||||||
{
|
{
|
||||||
|
|
@ -98,7 +99,8 @@ class HrmService:
|
||||||
"email": ep.email,
|
"email": ep.email,
|
||||||
"sex": 1 if ep.gender == '男' else 2
|
"sex": 1 if ep.gender == '男' else 2
|
||||||
}
|
}
|
||||||
_, res = dhClient.request(**dhapis['person_img_upload'], file_path_rela=ep.photo)
|
_, res = dhClient.request(
|
||||||
|
**dhapis['person_img_upload'], file_path_rela=ep.photo)
|
||||||
dh_photo = res["fileUrl"]
|
dh_photo = res["fileUrl"]
|
||||||
json_data.update(
|
json_data.update(
|
||||||
{
|
{
|
||||||
|
|
@ -129,16 +131,20 @@ class HrmService:
|
||||||
if start_time is None: # 如果时间段未提供,跳过更新操作
|
if start_time is None: # 如果时间段未提供,跳过更新操作
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
startDate = timezone.localtime(start_time).strftime("%Y-%m-%d %H:%M:%S")
|
startDate = timezone.localtime(
|
||||||
endDate = timezone.localtime(end_time).strftime("%Y-%m-%d %H:%M:%S")
|
start_time).strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
endDate = timezone.localtime(
|
||||||
|
end_time).strftime("%Y-%m-%d %H:%M:%S")
|
||||||
json_data = {
|
json_data = {
|
||||||
"cardNumber": cardNumber,
|
"cardNumber": cardNumber,
|
||||||
"startDate": startDate,
|
"startDate": startDate,
|
||||||
"endDate": endDate,
|
"endDate": endDate,
|
||||||
"departmentId": departmentId,
|
"departmentId": departmentId,
|
||||||
}
|
}
|
||||||
_, res = dhClient.request(**dhapis['card_update'], json=json_data)
|
_, res = dhClient.request(
|
||||||
cls.save(ep, data={'dh_face_card_start': startDate, 'dh_face_card_end': endDate})
|
**dhapis['card_update'], json=json_data)
|
||||||
|
cls.save(
|
||||||
|
ep, data={'dh_face_card_start': startDate, 'dh_face_card_end': endDate})
|
||||||
return cardNumber
|
return cardNumber
|
||||||
else:
|
else:
|
||||||
_, res = dhClient.request(**dhapis['card_gen_id'])
|
_, res = dhClient.request(**dhapis['card_gen_id'])
|
||||||
|
|
@ -147,10 +153,13 @@ class HrmService:
|
||||||
if start_time is None: # 如果未规定时间范围, 默认1小时
|
if start_time is None: # 如果未规定时间范围, 默认1小时
|
||||||
now = datetime.now()
|
now = datetime.now()
|
||||||
startDate = now.strftime("%Y-%m-%d %H:%M:%S")
|
startDate = now.strftime("%Y-%m-%d %H:%M:%S")
|
||||||
endDate = (now+timedelta(minutes=60)).strftime("%Y-%m-%d %H:%M:%S")
|
endDate = (now+timedelta(minutes=60)
|
||||||
|
).strftime("%Y-%m-%d %H:%M:%S")
|
||||||
else:
|
else:
|
||||||
startDate = timezone.localtime(start_time).strftime("%Y-%m-%d %H:%M:%S")
|
startDate = timezone.localtime(
|
||||||
endDate = timezone.localtime(end_time).strftime("%Y-%m-%d %H:%M:%S")
|
start_time).strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
endDate = timezone.localtime(
|
||||||
|
end_time).strftime("%Y-%m-%d %H:%M:%S")
|
||||||
json_data = {
|
json_data = {
|
||||||
"id": cardId,
|
"id": cardId,
|
||||||
"cardNumber": cardNumber,
|
"cardNumber": cardNumber,
|
||||||
|
|
@ -180,7 +189,9 @@ class HrmService:
|
||||||
from apps.third.models import TDevice
|
from apps.third.models import TDevice
|
||||||
dh_face_card = ep.third_info.get('dh_face_card', None)
|
dh_face_card = ep.third_info.get('dh_face_card', None)
|
||||||
if dh_dchannels:
|
if dh_dchannels:
|
||||||
pass
|
# 只分配系统里有的
|
||||||
|
dh_dchannels = list(TDevice.objects.filter(
|
||||||
|
code__in=dh_dchannels).values_list('code', flat=True))
|
||||||
else:
|
else:
|
||||||
# 查找可授予的门禁通道号
|
# 查找可授予的门禁通道号
|
||||||
dh_dchannels = list(TDevice.objects.filter(type=TDevice.DEVICE_DCHANNEL,
|
dh_dchannels = list(TDevice.objects.filter(type=TDevice.DEVICE_DCHANNEL,
|
||||||
|
|
@ -201,7 +212,8 @@ class HrmService:
|
||||||
while ind < 8:
|
while ind < 8:
|
||||||
time.sleep(6)
|
time.sleep(6)
|
||||||
try:
|
try:
|
||||||
dhClient.request(**dhapis['card_door_authority'], json=json_data)
|
dhClient.request(
|
||||||
|
**dhapis['card_door_authority'], json=json_data)
|
||||||
break
|
break
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
ind = ind + 1
|
ind = ind + 1
|
||||||
|
|
@ -220,6 +232,13 @@ class HrmService:
|
||||||
# elif is_ok == 'error':
|
# elif is_ok == 'error':
|
||||||
# raise APIException(**DH_REQUEST_ERROR)
|
# raise APIException(**DH_REQUEST_ERROR)
|
||||||
cls.save(ep, data={'dh_dchannels': dh_dchannels})
|
cls.save(ep, data={'dh_dchannels': dh_dchannels})
|
||||||
|
from apps.third.models import DoorAuth
|
||||||
|
DoorAuth.objects.filter(employee=ep).delete()
|
||||||
|
drs = []
|
||||||
|
for i in dh_dchannels:
|
||||||
|
drs.append(
|
||||||
|
DoorAuth(employee=ep, dchannel=TDevice.objects.get(code=i)))
|
||||||
|
DoorAuth.objects.bulk_create(drs)
|
||||||
return dh_dchannels
|
return dh_dchannels
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
@ -243,10 +262,11 @@ class HrmService:
|
||||||
nodeCode = data['info']['extend']['acsChannelCode']
|
nodeCode = data['info']['extend']['acsChannelCode']
|
||||||
swip_time = data['info']['extend']['swingTime']
|
swip_time = data['info']['extend']['swingTime']
|
||||||
e_type = data['info']['extend']['enterOrExit']
|
e_type = data['info']['extend']['enterOrExit']
|
||||||
cls.swipe_next(nodeCode, id_number, swip_time, e_type, data['info']['extend'])
|
cls.swipe_next(nodeCode, id_number, swip_time,
|
||||||
|
e_type, data['info']['extend'])
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def swipe_offline(cls, data:dict):
|
def swipe_offline(cls, data: dict):
|
||||||
"""离线刷卡推送记录处理
|
"""离线刷卡推送记录处理
|
||||||
"""
|
"""
|
||||||
for i in data['infoArray']:
|
for i in data['infoArray']:
|
||||||
|
|
@ -256,9 +276,9 @@ class HrmService:
|
||||||
swip_time = i['swingTime']
|
swip_time = i['swingTime']
|
||||||
e_type = i['enterOrExit']
|
e_type = i['enterOrExit']
|
||||||
cls.swipe_next(nodeCode, id_number, swip_time, e_type, i)
|
cls.swipe_next(nodeCode, id_number, swip_time, e_type, i)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def swipe_next(cls, nodeCode: str, id_number: str, swip_time: str, e_type:int, detail:dict):
|
def swipe_next(cls, nodeCode: str, id_number: str, swip_time: str, e_type: int, detail: dict):
|
||||||
from apps.rpm.models import Rpj
|
from apps.rpm.models import Rpj
|
||||||
from apps.vm.models import Visit
|
from apps.vm.models import Visit
|
||||||
|
|
||||||
|
|
@ -267,15 +287,17 @@ class HrmService:
|
||||||
state=Visit.V_WORKING)
|
state=Visit.V_WORKING)
|
||||||
Rpj.objects.filter(state=Rpj.RPJ_ENTER, remployees__employee__id_number=id_number).update(
|
Rpj.objects.filter(state=Rpj.RPJ_ENTER, remployees__employee__id_number=id_number).update(
|
||||||
state=Rpj.RPJ_WORKING)
|
state=Rpj.RPJ_WORKING)
|
||||||
|
|
||||||
# 打卡处理
|
# 打卡处理
|
||||||
device = TDevice.objects.filter(code=nodeCode).first()
|
device = TDevice.objects.filter(code=nodeCode).first()
|
||||||
ep = Employee.objects.filter(id_number=id_number, type__in=["employee", "remployee"]).first()
|
ep = Employee.objects.filter(id_number=id_number, type__in=[
|
||||||
|
"employee", "remployee"]).first()
|
||||||
if device and device.is_clock and ep:
|
if device and device.is_clock and ep:
|
||||||
tzinfo = tz.gettz('Asia/Shanghai')
|
tzinfo = tz.gettz('Asia/Shanghai')
|
||||||
s_time_f = datetime.strptime(swip_time, "%Y-%m-%d %H:%M:%S").replace(tzinfo=tzinfo)
|
s_time_f = datetime.strptime(
|
||||||
|
swip_time, "%Y-%m-%d %H:%M:%S").replace(tzinfo=tzinfo)
|
||||||
first_time = datetime(year=s_time_f.year, month=s_time_f.month, day=s_time_f.day,
|
first_time = datetime(year=s_time_f.year, month=s_time_f.month, day=s_time_f.day,
|
||||||
hour=0, minute=0, second=0, tzinfo=tzinfo)
|
hour=0, minute=0, second=0, tzinfo=tzinfo)
|
||||||
end_time = datetime(year=s_time_f.year, month=s_time_f.month, day=s_time_f.day,
|
end_time = datetime(year=s_time_f.year, month=s_time_f.month, day=s_time_f.day,
|
||||||
hour=23, minute=59, second=59, tzinfo=tzinfo)
|
hour=23, minute=59, second=59, tzinfo=tzinfo)
|
||||||
|
|
||||||
|
|
@ -288,13 +310,13 @@ class HrmService:
|
||||||
card_type = 20
|
card_type = 20
|
||||||
elif e_type == 3:
|
elif e_type == 3:
|
||||||
time_10_x = datetime(year=s_time_f.year, month=s_time_f.month,
|
time_10_x = datetime(year=s_time_f.year, month=s_time_f.month,
|
||||||
day=s_time_f.day, hour=7, minute=20, second=0, tzinfo=tzinfo)
|
day=s_time_f.day, hour=7, minute=20, second=0, tzinfo=tzinfo)
|
||||||
time_10_y = datetime(year=s_time_f.year, month=s_time_f.month,
|
time_10_y = datetime(year=s_time_f.year, month=s_time_f.month,
|
||||||
day=s_time_f.day, hour=11, minute=0, second=0, tzinfo=tzinfo)
|
day=s_time_f.day, hour=11, minute=0, second=0, tzinfo=tzinfo)
|
||||||
time_20_x = datetime(year=s_time_f.year, month=s_time_f.month,
|
time_20_x = datetime(year=s_time_f.year, month=s_time_f.month,
|
||||||
day=s_time_f.day, hour=16, minute=0, second=0, tzinfo=tzinfo)
|
day=s_time_f.day, hour=16, minute=0, second=0, tzinfo=tzinfo)
|
||||||
time_20_y = datetime(year=s_time_f.year, month=s_time_f.month,
|
time_20_y = datetime(year=s_time_f.year, month=s_time_f.month,
|
||||||
day=s_time_f.day, hour=18, minute=10, second=0, tzinfo=tzinfo)
|
day=s_time_f.day, hour=18, minute=10, second=0, tzinfo=tzinfo)
|
||||||
if time_10_x < s_time_f < time_10_y:
|
if time_10_x < s_time_f < time_10_y:
|
||||||
card_type = 10
|
card_type = 10
|
||||||
elif time_20_x < s_time_f < time_20_y:
|
elif time_20_x < s_time_f < time_20_y:
|
||||||
|
|
@ -302,9 +324,10 @@ class HrmService:
|
||||||
if card_type == 30:
|
if card_type == 30:
|
||||||
note = '非打卡时间范围'
|
note = '非打卡时间范围'
|
||||||
trigger = 'panel'
|
trigger = 'panel'
|
||||||
|
|
||||||
# 先直接创建记录
|
# 先直接创建记录
|
||||||
cr = ClockRecord.objects.filter(employee=ep, create_time=s_time_f).first()
|
cr = ClockRecord.objects.filter(
|
||||||
|
employee=ep, create_time=s_time_f).first()
|
||||||
if cr:
|
if cr:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
|
@ -312,7 +335,7 @@ class HrmService:
|
||||||
cr.employee = ep
|
cr.employee = ep
|
||||||
cr.create_time = s_time_f
|
cr.create_time = s_time_f
|
||||||
cr.type = card_type
|
cr.type = card_type
|
||||||
cr.exception_type = None
|
cr.exception_type = None
|
||||||
cr.trigger = trigger
|
cr.trigger = trigger
|
||||||
cr.detail = detail
|
cr.detail = detail
|
||||||
cr.note = note
|
cr.note = note
|
||||||
|
|
@ -323,34 +346,38 @@ class HrmService:
|
||||||
cr_10_q = ClockRecord.objects.filter(
|
cr_10_q = ClockRecord.objects.filter(
|
||||||
type=10, employee=ep, create_time__gte=first_time, create_time__lte=end_time)
|
type=10, employee=ep, create_time__gte=first_time, create_time__lte=end_time)
|
||||||
first_obj = cr_10_q.order_by('create_time').first()
|
first_obj = cr_10_q.order_by('create_time').first()
|
||||||
cr_10_q.exclude(id=first_obj.id).update(type=30, exception_type=None)
|
cr_10_q.exclude(id=first_obj.id).update(
|
||||||
|
type=30, exception_type=None)
|
||||||
elif card_type == 20:
|
elif card_type == 20:
|
||||||
# 查找当天的出门记录
|
# 查找当天的出门记录
|
||||||
cr_20_q = ClockRecord.objects.filter(
|
cr_20_q = ClockRecord.objects.filter(
|
||||||
type=20, employee=ep, create_time__gte=first_time, create_time__lte=end_time)
|
type=20, employee=ep, create_time__gte=first_time, create_time__lte=end_time)
|
||||||
last_obj = cr_20_q.order_by('-create_time').first()
|
last_obj = cr_20_q.order_by('-create_time').first()
|
||||||
cr_20_q.exclude(id=last_obj.id).update(type=30, exception_type=None)
|
cr_20_q.exclude(id=last_obj.id).update(
|
||||||
|
type=30, exception_type=None)
|
||||||
# 判断是否有异常
|
# 判断是否有异常
|
||||||
# 找到最近的上下打卡时间不一定是当天的
|
# 找到最近的上下打卡时间不一定是当天的
|
||||||
cr_e = ClockRecord.objects.filter(create_time__lt=last_obj.create_time, employee=ep, type__in=[10, 20]).order_by('-create_time').first()
|
cr_e = ClockRecord.objects.filter(create_time__lt=last_obj.create_time, employee=ep, type__in=[
|
||||||
|
10, 20]).order_by('-create_time').first()
|
||||||
if cr_e and last_obj:
|
if cr_e and last_obj:
|
||||||
time_d = last_obj.create_time - cr_e.create_time
|
time_d = last_obj.create_time - cr_e.create_time
|
||||||
if cr_e.type == 10:
|
if cr_e.type == 10:
|
||||||
if time_d < timedelta(hours=7):
|
if time_d < timedelta(hours=7):
|
||||||
last_obj.exception_type = ClockRecord.E_TYPE_LESS
|
last_obj.exception_type = ClockRecord.E_TYPE_LESS
|
||||||
last_obj.save()
|
last_obj.save()
|
||||||
elif time_d > timedelta(hours=14):
|
elif time_d > timedelta(hours=14):
|
||||||
last_obj.exception_type = ClockRecord.E_TYPE_MORE
|
last_obj.exception_type = ClockRecord.E_TYPE_MORE
|
||||||
last_obj.save()
|
last_obj.save()
|
||||||
elif time_d > timedelta(hours=10):
|
elif time_d > timedelta(hours=10):
|
||||||
last_obj.exception_type = ClockRecord.E_TYPE_ADD
|
last_obj.exception_type = ClockRecord.E_TYPE_ADD
|
||||||
last_obj.save()
|
last_obj.save()
|
||||||
elif cr_e.type == 20:
|
elif cr_e.type == 20:
|
||||||
last_obj.exception_type = ClockRecord.E_TYPE_MISS
|
last_obj.exception_type = ClockRecord.E_TYPE_MISS
|
||||||
last_obj.save()
|
last_obj.save()
|
||||||
|
|
||||||
# 记录在岗情况
|
# 记录在岗情况
|
||||||
last_obj_t = ClockRecord.objects.filter(employee=ep, type__in=[10,20]).order_by('-create_time').first()
|
last_obj_t = ClockRecord.objects.filter(
|
||||||
|
employee=ep, type__in=[10, 20]).order_by('-create_time').first()
|
||||||
if last_obj_t:
|
if last_obj_t:
|
||||||
update_fields = {'last_check_time': last_obj_t.create_time}
|
update_fields = {'last_check_time': last_obj_t.create_time}
|
||||||
if last_obj_t.type == 10:
|
if last_obj_t.type == 10:
|
||||||
|
|
@ -358,48 +385,48 @@ class HrmService:
|
||||||
else:
|
else:
|
||||||
update_fields['is_atwork'] = False
|
update_fields['is_atwork'] = False
|
||||||
Employee.objects.filter(id=ep.id).update(**update_fields)
|
Employee.objects.filter(id=ep.id).update(**update_fields)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# 此处可触发安全帽事件逻辑
|
# 此处可触发安全帽事件逻辑
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_facedata_from_img_x(cls, img_path):
|
def get_facedata_from_img_x(cls, img_path):
|
||||||
import face_recognition
|
import face_recognition
|
||||||
try:
|
try:
|
||||||
picture_of_me = face_recognition.load_image_file(img_path)
|
picture_of_me = face_recognition.load_image_file(img_path)
|
||||||
my_face_encoding = face_recognition.face_encodings(picture_of_me, num_jitters=2)[0]
|
my_face_encoding = face_recognition.face_encodings(
|
||||||
|
picture_of_me, num_jitters=2)[0]
|
||||||
face_data_list = my_face_encoding.tolist()
|
face_data_list = my_face_encoding.tolist()
|
||||||
return face_data_list, ''
|
return face_data_list, ''
|
||||||
except:
|
except:
|
||||||
return None, '人脸数据获取失败请重新上传图片'
|
return None, '人脸数据获取失败请重新上传图片'
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def face_compare_from_base64(cls, base64_data):
|
def face_compare_from_base64(cls, base64_data):
|
||||||
import face_recognition
|
import face_recognition
|
||||||
filename = str(uuid.uuid4())
|
filename = str(uuid.uuid4())
|
||||||
filepath = settings.BASE_DIR +'/temp/face_' + filename +'.png'
|
filepath = settings.BASE_DIR + '/temp/face_' + filename + '.png'
|
||||||
with open(filepath, 'wb') as f:
|
with open(filepath, 'wb') as f:
|
||||||
f.write(base64_data)
|
f.write(base64_data)
|
||||||
try:
|
try:
|
||||||
unknown_picture = face_recognition.load_image_file(filepath)
|
unknown_picture = face_recognition.load_image_file(filepath)
|
||||||
unknown_face_encoding = face_recognition.face_encodings(unknown_picture, num_jitters=2)[0]
|
unknown_face_encoding = face_recognition.face_encodings(
|
||||||
|
unknown_picture, num_jitters=2)[0]
|
||||||
os.remove(filepath)
|
os.remove(filepath)
|
||||||
except:
|
except:
|
||||||
os.remove(filepath)
|
os.remove(filepath)
|
||||||
return None, '识别失败,请调整位置'
|
return None, '识别失败,请调整位置'
|
||||||
|
|
||||||
# 匹配人脸库
|
# 匹配人脸库
|
||||||
face_datas = cache.get('face_datas_dlib', None) # 使用的是face_datas_dlib作为key的
|
# 使用的是face_datas_dlib作为key的
|
||||||
|
face_datas = cache.get('face_datas_dlib', None)
|
||||||
if face_datas is None:
|
if face_datas is None:
|
||||||
from apps.hrm.tasks import update_all_facedata_cache
|
from apps.hrm.tasks import update_all_facedata_cache
|
||||||
update_all_facedata_cache()
|
update_all_facedata_cache()
|
||||||
face_datas = cache.get('face_datas_dlib')
|
face_datas = cache.get('face_datas_dlib')
|
||||||
results = face_recognition.compare_faces(face_datas['datas'],
|
results = face_recognition.compare_faces(face_datas['datas'],
|
||||||
unknown_face_encoding, tolerance=0.45)
|
unknown_face_encoding, tolerance=0.45)
|
||||||
face_distances = face_recognition.face_distance(face_datas['datas'], unknown_face_encoding)
|
face_distances = face_recognition.face_distance(
|
||||||
|
face_datas['datas'], unknown_face_encoding)
|
||||||
best_match_index = np.argmin(face_distances)
|
best_match_index = np.argmin(face_distances)
|
||||||
if results[best_match_index]:
|
if results[best_match_index]:
|
||||||
epId = face_datas['eps'][best_match_index]
|
epId = face_datas['eps'][best_match_index]
|
||||||
|
|
@ -408,7 +435,7 @@ class HrmService:
|
||||||
# first_match_index = results.index(True)
|
# first_match_index = results.index(True)
|
||||||
# # 识别成功
|
# # 识别成功
|
||||||
# ep = Employee.objects.get(id=face_datas['eps'][first_match_index])
|
# ep = Employee.objects.get(id=face_datas['eps'][first_match_index])
|
||||||
# return ep, ''
|
# return ep, ''
|
||||||
return None, '人脸未匹配,请调整位置'
|
return None, '人脸未匹配,请调整位置'
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
@ -416,7 +443,7 @@ class HrmService:
|
||||||
from apps.utils.face import face_find
|
from apps.utils.face import face_find
|
||||||
# from deepface import DeepFace
|
# from deepface import DeepFace
|
||||||
img_name = str(uuid.uuid4())
|
img_name = str(uuid.uuid4())
|
||||||
img_path = settings.BASE_DIR +'/temp/face_' + img_name +'.jpg'
|
img_path = settings.BASE_DIR + '/temp/face_' + img_name + '.jpg'
|
||||||
with open(img_path, 'wb') as f:
|
with open(img_path, 'wb') as f:
|
||||||
f.write(base64_data)
|
f.write(base64_data)
|
||||||
# db_path = os.path.join(settings.BASE_DIR, 'media/face')
|
# db_path = os.path.join(settings.BASE_DIR, 'media/face')
|
||||||
|
|
@ -443,7 +470,8 @@ class HrmService:
|
||||||
def get_facedata_from_img(cls, img_path):
|
def get_facedata_from_img(cls, img_path):
|
||||||
try:
|
try:
|
||||||
from deepface import DeepFace
|
from deepface import DeepFace
|
||||||
embedding_objs = DeepFace.represent(img_path=img_path, model_name='Facenet')
|
embedding_objs = DeepFace.represent(
|
||||||
|
img_path=img_path, model_name='Facenet')
|
||||||
return embedding_objs[0]["embedding"], ''
|
return embedding_objs[0]["embedding"], ''
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return None, '人脸数据获取失败请重新上传图片'
|
return None, '人脸数据获取失败请重新上传图片'
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
# Generated by Django 3.2.12 on 2023-10-09 02:54
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
import django.utils.timezone
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('hrm', '0015_clockrecord_note'),
|
||||||
|
('third', '0008_alter_tdevice_employee'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='DoorAuth',
|
||||||
|
fields=[
|
||||||
|
('id', models.CharField(editable=False, help_text='主键ID', max_length=20, primary_key=True, serialize=False, verbose_name='主键ID')),
|
||||||
|
('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')),
|
||||||
|
('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')),
|
||||||
|
('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')),
|
||||||
|
('dchannel', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='third.tdevice', verbose_name='关联门通道')),
|
||||||
|
('employee', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='hrm.employee', verbose_name='关联用户')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -31,7 +31,8 @@ class TDevice(BaseModel):
|
||||||
(DEVICE_PANEL, '面板机')
|
(DEVICE_PANEL, '面板机')
|
||||||
)
|
)
|
||||||
type = models.PositiveSmallIntegerField('设备类型', choices=DEVICE_CHOICE)
|
type = models.PositiveSmallIntegerField('设备类型', choices=DEVICE_CHOICE)
|
||||||
code = models.CharField('设备唯一标识', max_length=50, db_index=True, unique=True)
|
code = models.CharField('设备唯一标识', max_length=50,
|
||||||
|
db_index=True, unique=True)
|
||||||
name = models.CharField('名称', max_length=50, null=True, blank=True)
|
name = models.CharField('名称', max_length=50, null=True, blank=True)
|
||||||
location = models.JSONField('位置信息', default=dict,
|
location = models.JSONField('位置信息', default=dict,
|
||||||
null=False, blank=True)
|
null=False, blank=True)
|
||||||
|
|
@ -39,13 +40,15 @@ class TDevice(BaseModel):
|
||||||
verbose_name='所在区', null=True, blank=True)
|
verbose_name='所在区', null=True, blank=True)
|
||||||
areas = models.ManyToManyField(Area, verbose_name='覆盖区',
|
areas = models.ManyToManyField(Area, verbose_name='覆盖区',
|
||||||
related_name='tareas', blank=True)
|
related_name='tareas', blank=True)
|
||||||
obj_cate = models.CharField('绑定对象', max_length=20, help_text='people/...', null=True, blank=True)
|
obj_cate = models.CharField(
|
||||||
|
'绑定对象', max_length=20, help_text='people/...', null=True, blank=True)
|
||||||
employee = models.OneToOneField(Employee, verbose_name='当前绑定人员', on_delete=models.SET_NULL,
|
employee = models.OneToOneField(Employee, verbose_name='当前绑定人员', on_delete=models.SET_NULL,
|
||||||
null=True, blank=True, related_name='blt')
|
null=True, blank=True, related_name='blt')
|
||||||
is_clock = models.BooleanField('是否打卡设备', default=False)
|
is_clock = models.BooleanField('是否打卡设备', default=False)
|
||||||
access_list = models.JSONField('自动下发人员类型', default=list,
|
access_list = models.JSONField('自动下发人员类型', default=list,
|
||||||
null=False, blank=True, help_text='employee/remployee/visitor/driver')
|
null=False, blank=True, help_text='employee/remployee/visitor/driver')
|
||||||
mtask_uid = models.CharField('监控任务ID', max_length=100, null=True, blank=True) # 废弃字段
|
mtask_uid = models.CharField(
|
||||||
|
'监控任务ID', max_length=100, null=True, blank=True) # 废弃字段
|
||||||
# algos = models.ManyToManyField('ecm.eventcate', through='ecm.algochannel', blank=True)
|
# algos = models.ManyToManyField('ecm.eventcate', through='ecm.algochannel', blank=True)
|
||||||
third_info = models.JSONField('三方信息', default=dict,
|
third_info = models.JSONField('三方信息', default=dict,
|
||||||
null=False, blank=True)
|
null=False, blank=True)
|
||||||
|
|
@ -62,9 +65,12 @@ class BltBind(BaseModel):
|
||||||
)
|
)
|
||||||
type = models.PositiveSmallIntegerField('绑定类型', default=10, help_text='10(绑定)/20(解绑)',
|
type = models.PositiveSmallIntegerField('绑定类型', default=10, help_text='10(绑定)/20(解绑)',
|
||||||
choices=BIND_TYPE_CHOICES)
|
choices=BIND_TYPE_CHOICES)
|
||||||
obj_cate = models.CharField('绑定对象', max_length=20, help_text='people/...', null=True, blank=True)
|
obj_cate = models.CharField(
|
||||||
blt = models.ForeignKey(TDevice, verbose_name='关联标签', on_delete=models.CASCADE)
|
'绑定对象', max_length=20, help_text='people/...', null=True, blank=True)
|
||||||
employee = models.ForeignKey(Employee, verbose_name='关联人员', on_delete=models.CASCADE, null=True, blank=True)
|
blt = models.ForeignKey(TDevice, verbose_name='关联标签',
|
||||||
|
on_delete=models.CASCADE)
|
||||||
|
employee = models.ForeignKey(
|
||||||
|
Employee, verbose_name='关联人员', on_delete=models.CASCADE, null=True, blank=True)
|
||||||
|
|
||||||
|
|
||||||
class Tlog(BaseModel):
|
class Tlog(BaseModel):
|
||||||
|
|
@ -83,3 +89,10 @@ class Tlog(BaseModel):
|
||||||
errors = models.TextField(null=True, blank=True)
|
errors = models.TextField(null=True, blank=True)
|
||||||
params = models.JSONField(null=True, blank=True)
|
params = models.JSONField(null=True, blank=True)
|
||||||
body = models.JSONField(null=True, blank=True)
|
body = models.JSONField(null=True, blank=True)
|
||||||
|
|
||||||
|
|
||||||
|
class DoorAuth(BaseModel):
|
||||||
|
employee = models.ForeignKey(
|
||||||
|
Employee, verbose_name='关联用户', on_delete=models.CASCADE)
|
||||||
|
dchannel = models.ForeignKey(
|
||||||
|
TDevice, verbose_name='关联门通道', on_delete=models.CASCADE)
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from apps.am.models import Area
|
from apps.am.models import Area
|
||||||
from apps.hrm.serializers import EmployeeSimpleSerializer
|
from apps.hrm.serializers import EmployeeSimpleSerializer, EmployeeShortSerializer
|
||||||
from apps.third.models import BltBind, TDevice, Tlog
|
from apps.third.models import BltBind, TDevice, Tlog, DoorAuth
|
||||||
from apps.utils.serializers import CustomModelSerializer
|
from apps.utils.serializers import CustomModelSerializer
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
|
|
||||||
|
|
@ -23,6 +23,7 @@ class TDeviceSerializer(CustomModelSerializer):
|
||||||
def get_mtask_(self, obj):
|
def get_mtask_(self, obj):
|
||||||
return cache.get('vchannel_' + obj.code, {})
|
return cache.get('vchannel_' + obj.code, {})
|
||||||
|
|
||||||
|
|
||||||
class TDeviceUpdateSerializer(CustomModelSerializer):
|
class TDeviceUpdateSerializer(CustomModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = TDevice
|
model = TDevice
|
||||||
|
|
@ -30,7 +31,8 @@ class TDeviceUpdateSerializer(CustomModelSerializer):
|
||||||
|
|
||||||
def update(self, instance, validated_data):
|
def update(self, instance, validated_data):
|
||||||
if validated_data.get('access_list', []):
|
if validated_data.get('access_list', []):
|
||||||
validated_data['access_list'] = ['employee', 'remployee', 'visitor']
|
validated_data['access_list'] = [
|
||||||
|
'employee', 'remployee', 'visitor']
|
||||||
return super().update(instance, validated_data)
|
return super().update(instance, validated_data)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -48,10 +50,14 @@ class RequestCommonSerializer(serializers.Serializer):
|
||||||
('delete', 'delete')
|
('delete', 'delete')
|
||||||
)
|
)
|
||||||
url = serializers.CharField(label='请求地址', required=False)
|
url = serializers.CharField(label='请求地址', required=False)
|
||||||
method = serializers.ChoiceField(label='请求方法', choices=method_choice, required=False)
|
method = serializers.ChoiceField(
|
||||||
params = serializers.JSONField(label='请求参数', required=False, allow_null=True)
|
label='请求方法', choices=method_choice, required=False)
|
||||||
json = serializers.JSONField(label='请求body(json格式)', required=False, allow_null=True)
|
params = serializers.JSONField(
|
||||||
code = serializers.CharField(label='请求短标识', required=False, allow_null=True)
|
label='请求参数', required=False, allow_null=True)
|
||||||
|
json = serializers.JSONField(
|
||||||
|
label='请求body(json格式)', required=False, allow_null=True)
|
||||||
|
code = serializers.CharField(
|
||||||
|
label='请求短标识', required=False, allow_null=True)
|
||||||
|
|
||||||
|
|
||||||
class BindAreaSerializer(serializers.Serializer):
|
class BindAreaSerializer(serializers.Serializer):
|
||||||
|
|
@ -90,7 +96,8 @@ class BltSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
|
|
||||||
class BltQuerySerializer(serializers.ModelSerializer):
|
class BltQuerySerializer(serializers.ModelSerializer):
|
||||||
depts = serializers.ListField(child=serializers.CharField(), label="部门ID列表", required=False)
|
depts = serializers.ListField(
|
||||||
|
child=serializers.CharField(), label="部门ID列表", required=False)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = TDevice
|
model = TDevice
|
||||||
|
|
@ -107,4 +114,14 @@ class BltBindCreateSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
|
|
||||||
class BltCreatesSerializer(serializers.Serializer):
|
class BltCreatesSerializer(serializers.Serializer):
|
||||||
macs = serializers.ListField(child=serializers.CharField(), label='标签mac列表')
|
macs = serializers.ListField(
|
||||||
|
child=serializers.CharField(), label='标签mac列表')
|
||||||
|
|
||||||
|
|
||||||
|
class DoorAuthSerializer(CustomModelSerializer):
|
||||||
|
employee_ = EmployeeShortSerializer(source='employee', read_only=True)
|
||||||
|
dchannel_ = TDeviceSimpleSerializer(source='dchannel', read_only=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = DoorAuth
|
||||||
|
fields = '__all__'
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,10 @@ dhapis = {
|
||||||
"url": "/evo-apigw/evo-accesscontrol/1.0.0/card/accessControl/doorAuthority",
|
"url": "/evo-apigw/evo-accesscontrol/1.0.0/card/accessControl/doorAuthority",
|
||||||
"method": "post"
|
"method": "post"
|
||||||
},
|
},
|
||||||
|
"card_door_authority_delete": {
|
||||||
|
"url": "/evo-apigw/evo-accesscontrol/1.0.0/card/accessControl/doorAuthority/deleteSingleCardPrivilege",
|
||||||
|
"method": "post"
|
||||||
|
},
|
||||||
"mq_subscribe": {
|
"mq_subscribe": {
|
||||||
"url": "/evo-apigw/evo-event/1.0.0/subscribe/mqinfo",
|
"url": "/evo-apigw/evo-event/1.0.0/subscribe/mqinfo",
|
||||||
"method": "post"
|
"method": "post"
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ from email.mime import base
|
||||||
from django.urls import path, include
|
from django.urls import path, include
|
||||||
from rest_framework import routers
|
from rest_framework import routers
|
||||||
from apps.third.views import DahuaTestView, DhCommonViewSet, SpTestView, SpeakerViewSet, XxCommonViewSet, XxTestView
|
from apps.third.views import DahuaTestView, DhCommonViewSet, SpTestView, SpeakerViewSet, XxCommonViewSet, XxTestView
|
||||||
from apps.third.views_d import BltViewSet, TDeviceViewSet, TlogViewSet
|
from apps.third.views_d import BltViewSet, TDeviceViewSet, TlogViewSet, DoorAuthViewSet
|
||||||
|
|
||||||
API_BASE_URL = 'api/third/'
|
API_BASE_URL = 'api/third/'
|
||||||
HTML_BASE_URL = 'third/'
|
HTML_BASE_URL = 'third/'
|
||||||
|
|
@ -14,6 +14,7 @@ router.register('speaker', SpeakerViewSet, basename='api_speaker')
|
||||||
router.register('tdevice', TDeviceViewSet, basename='tdevice')
|
router.register('tdevice', TDeviceViewSet, basename='tdevice')
|
||||||
router.register('tlog', TlogViewSet, basename='tlog')
|
router.register('tlog', TlogViewSet, basename='tlog')
|
||||||
router.register('tdevice/blt', BltViewSet, basename='blt')
|
router.register('tdevice/blt', BltViewSet, basename='blt')
|
||||||
|
router.register('doorauth', DoorAuthViewSet, basename='doorauth')
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path(API_BASE_URL, include(router.urls)),
|
path(API_BASE_URL, include(router.urls)),
|
||||||
path(API_BASE_URL + 'dahua/test/', DahuaTestView.as_view()),
|
path(API_BASE_URL + 'dahua/test/', DahuaTestView.as_view()),
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
from apps.third.filters import TDeviceFilterSet
|
from apps.third.filters import TDeviceFilterSet
|
||||||
from apps.third.models import BltBind, TDevice, Tlog
|
from apps.third.models import BltBind, TDevice, Tlog, DoorAuth
|
||||||
from apps.third.serializers import BindAreaSerializer, BltBindCreateSerializer, BltQuerySerializer, BltSerializer, LabelLocationSerializer, TDeviceSerializer, TDeviceUpdateSerializer, TlogSerializer
|
from apps.third.serializers import BindAreaSerializer, BltBindCreateSerializer, BltQuerySerializer, BltSerializer, LabelLocationSerializer, TDeviceSerializer, TDeviceUpdateSerializer, TlogSerializer, DoorAuthSerializer
|
||||||
from apps.utils.viewsets import CustomGenericViewSet
|
from apps.utils.viewsets import CustomGenericViewSet
|
||||||
from rest_framework.mixins import ListModelMixin, CreateModelMixin
|
from rest_framework.mixins import ListModelMixin, CreateModelMixin
|
||||||
from apps.third.dahua import dhClient
|
from apps.third.dahua import dhClient
|
||||||
|
|
@ -131,13 +131,15 @@ class TDeviceViewSet(ListModelMixin, UpdateModelMixin, DestroyModelMixin, Custom
|
||||||
"""
|
"""
|
||||||
三方设备接口
|
三方设备接口
|
||||||
"""
|
"""
|
||||||
perms_map = {'get': '*', 'put': 'tdevice.update', 'delete': 'tdevice.delete'}
|
perms_map = {'get': '*', 'put': 'tdevice.update',
|
||||||
|
'delete': 'tdevice.delete'}
|
||||||
queryset = TDevice.objects.all()
|
queryset = TDevice.objects.all()
|
||||||
serializer_class = TDeviceSerializer
|
serializer_class = TDeviceSerializer
|
||||||
update_serializer_class = TDeviceUpdateSerializer
|
update_serializer_class = TDeviceUpdateSerializer
|
||||||
ordering = ['-create_time']
|
ordering = ['-create_time']
|
||||||
filterset_class = TDeviceFilterSet
|
filterset_class = TDeviceFilterSet
|
||||||
select_related_fields = ['employee', 'area', 'employee__post', 'employee__belong_dept']
|
select_related_fields = ['employee', 'area',
|
||||||
|
'employee__post', 'employee__belong_dept']
|
||||||
|
|
||||||
def list(self, request, *args, **kwargs):
|
def list(self, request, *args, **kwargs):
|
||||||
queryset = self.filter_queryset(self.get_queryset())
|
queryset = self.filter_queryset(self.get_queryset())
|
||||||
|
|
@ -170,7 +172,7 @@ class TDeviceViewSet(ListModelMixin, UpdateModelMixin, DestroyModelMixin, Custom
|
||||||
'includeSubOwnerCodeFlag': True,
|
'includeSubOwnerCodeFlag': True,
|
||||||
'channelCodeList': codes,
|
'channelCodeList': codes,
|
||||||
'pageSize': len(codes)
|
'pageSize': len(codes)
|
||||||
}
|
}
|
||||||
_, res = dhClient.request(**dhapis['channel_list'], json=json)
|
_, res = dhClient.request(**dhapis['channel_list'], json=json)
|
||||||
codes_dict = {}
|
codes_dict = {}
|
||||||
for i in res['pageData']:
|
for i in res['pageData']:
|
||||||
|
|
@ -211,7 +213,7 @@ class TDeviceViewSet(ListModelMixin, UpdateModelMixin, DestroyModelMixin, Custom
|
||||||
# ckey = 'vchannel_' + id
|
# ckey = 'vchannel_' + id
|
||||||
# cache.delete(ckey)
|
# cache.delete(ckey)
|
||||||
# return Response()
|
# return Response()
|
||||||
|
|
||||||
@action(methods=['post'], detail=False, perms_map={'post': '*'},
|
@action(methods=['post'], detail=False, perms_map={'post': '*'},
|
||||||
serializer_class=Serializer)
|
serializer_class=Serializer)
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
|
|
@ -227,7 +229,8 @@ class TDeviceViewSet(ListModelMixin, UpdateModelMixin, DestroyModelMixin, Custom
|
||||||
_, res = xxClient.request(**xxapis['blt_list'], json=json)
|
_, res = xxClient.request(**xxapis['blt_list'], json=json)
|
||||||
blt_list = res['recordList']
|
blt_list = res['recordList']
|
||||||
for i in blt_list:
|
for i in blt_list:
|
||||||
TDevice.objects.get_or_create(code=i['mac'], defaults={"code": i['mac'], "type": TDevice.DEVICE_BLT})
|
TDevice.objects.get_or_create(code=i['mac'], defaults={
|
||||||
|
"code": i['mac'], "type": TDevice.DEVICE_BLT})
|
||||||
return Response()
|
return Response()
|
||||||
|
|
||||||
@action(methods=['post'], detail=False, perms_map={'post': '*'},
|
@action(methods=['post'], detail=False, perms_map={'post': '*'},
|
||||||
|
|
@ -254,7 +257,8 @@ class TDeviceViewSet(ListModelMixin, UpdateModelMixin, DestroyModelMixin, Custom
|
||||||
td = TDevice(code=i['sn'], type=TDevice.DEVICE_SPEAKER)
|
td = TDevice(code=i['sn'], type=TDevice.DEVICE_SPEAKER)
|
||||||
td.name = i['name']
|
td.name = i['name']
|
||||||
td.save()
|
td.save()
|
||||||
TDevice.objects.filter(type=TDevice.DEVICE_SPEAKER).exclude(code__in=t_l).delete() # 移除不需要的
|
TDevice.objects.filter(type=TDevice.DEVICE_SPEAKER).exclude(
|
||||||
|
code__in=t_l).delete() # 移除不需要的
|
||||||
return Response()
|
return Response()
|
||||||
|
|
||||||
@action(methods=['post'], detail=False, perms_map={'post': '*'},
|
@action(methods=['post'], detail=False, perms_map={'post': '*'},
|
||||||
|
|
@ -280,10 +284,12 @@ class TDeviceViewSet(ListModelMixin, UpdateModelMixin, DestroyModelMixin, Custom
|
||||||
if td:
|
if td:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
td = TDevice(code=i['channelCode'], type=TDevice.DEVICE_VCHANNEL)
|
td = TDevice(code=i['channelCode'],
|
||||||
|
type=TDevice.DEVICE_VCHANNEL)
|
||||||
td.name = i['channelName']
|
td.name = i['channelName']
|
||||||
td.save()
|
td.save()
|
||||||
TDevice.objects.filter(type=TDevice.DEVICE_VCHANNEL).exclude(code__in=t_l).delete()
|
TDevice.objects.filter(type=TDevice.DEVICE_VCHANNEL).exclude(
|
||||||
|
code__in=t_l).delete()
|
||||||
return Response()
|
return Response()
|
||||||
|
|
||||||
@action(methods=['post'], detail=False, perms_map={'post': '*'},
|
@action(methods=['post'], detail=False, perms_map={'post': '*'},
|
||||||
|
|
@ -307,7 +313,8 @@ class TDeviceViewSet(ListModelMixin, UpdateModelMixin, DestroyModelMixin, Custom
|
||||||
if td:
|
if td:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
td = TDevice(code=i['channelCode'], type=TDevice.DEVICE_DCHANNEL)
|
td = TDevice(code=i['channelCode'],
|
||||||
|
type=TDevice.DEVICE_DCHANNEL)
|
||||||
td.name = i['channelName']
|
td.name = i['channelName']
|
||||||
# td.access_list = ['employee', 'remployee', 'visitor']
|
# td.access_list = ['employee', 'remployee', 'visitor']
|
||||||
td.save()
|
td.save()
|
||||||
|
|
@ -325,7 +332,8 @@ class TDeviceViewSet(ListModelMixin, UpdateModelMixin, DestroyModelMixin, Custom
|
||||||
serializer.is_valid(raise_exception=True)
|
serializer.is_valid(raise_exception=True)
|
||||||
vdata = serializer.validated_data
|
vdata = serializer.validated_data
|
||||||
code = vdata['code']
|
code = vdata['code']
|
||||||
blt = TDevice.objects.filter(code=code, type=TDevice.DEVICE_BLT).first()
|
blt = TDevice.objects.filter(
|
||||||
|
code=code, type=TDevice.DEVICE_BLT).first()
|
||||||
if blt:
|
if blt:
|
||||||
if vdata['type'] == BltBind.BLT_BIND and vdata['employee']:
|
if vdata['type'] == BltBind.BLT_BIND and vdata['employee']:
|
||||||
if blt.employee:
|
if blt.employee:
|
||||||
|
|
@ -385,13 +393,14 @@ class TDeviceViewSet(ListModelMixin, UpdateModelMixin, DestroyModelMixin, Custom
|
||||||
request.data.update({
|
request.data.update({
|
||||||
'unitTypeList': ["1"],
|
'unitTypeList': ["1"],
|
||||||
'includeSubOwnerCodeFlag': True
|
'includeSubOwnerCodeFlag': True
|
||||||
})
|
})
|
||||||
_, res = dhClient.request(**dhapis['channel_list'], json=request.data)
|
_, res = dhClient.request(**dhapis['channel_list'], json=request.data)
|
||||||
codes = []
|
codes = []
|
||||||
if res.get('pageData', None):
|
if res.get('pageData', None):
|
||||||
for i in res['pageData']:
|
for i in res['pageData']:
|
||||||
codes.append(i['channelCode'])
|
codes.append(i['channelCode'])
|
||||||
tds_info = TDeviceSerializer(instance=TDevice.objects.filter(code__in=codes), many=True).data
|
tds_info = TDeviceSerializer(
|
||||||
|
instance=TDevice.objects.filter(code__in=codes), many=True).data
|
||||||
tds_dict = {}
|
tds_dict = {}
|
||||||
for i in tds_info:
|
for i in tds_info:
|
||||||
tds_dict[i['code']] = i
|
tds_dict[i['code']] = i
|
||||||
|
|
@ -414,7 +423,8 @@ class TDeviceViewSet(ListModelMixin, UpdateModelMixin, DestroyModelMixin, Custom
|
||||||
codes = []
|
codes = []
|
||||||
for i in res['rows']:
|
for i in res['rows']:
|
||||||
codes.append(i['sn'])
|
codes.append(i['sn'])
|
||||||
tds_info = TDeviceSerializer(instance=TDevice.objects.filter(code__in=codes), many=True).data
|
tds_info = TDeviceSerializer(
|
||||||
|
instance=TDevice.objects.filter(code__in=codes), many=True).data
|
||||||
tds_dict = {}
|
tds_dict = {}
|
||||||
for i in tds_info:
|
for i in tds_info:
|
||||||
tds_dict[i['code']] = i
|
tds_dict[i['code']] = i
|
||||||
|
|
@ -435,13 +445,14 @@ class TDeviceViewSet(ListModelMixin, UpdateModelMixin, DestroyModelMixin, Custom
|
||||||
request.data.update({
|
request.data.update({
|
||||||
'unitTypeList': ["7"],
|
'unitTypeList': ["7"],
|
||||||
'includeSubOwnerCodeFlag': True
|
'includeSubOwnerCodeFlag': True
|
||||||
})
|
})
|
||||||
_, res = dhClient.request(**dhapis['channel_list'], json=request.data)
|
_, res = dhClient.request(**dhapis['channel_list'], json=request.data)
|
||||||
codes = []
|
codes = []
|
||||||
if res.get('pageData', None):
|
if res.get('pageData', None):
|
||||||
for i in res['pageData']:
|
for i in res['pageData']:
|
||||||
codes.append(i['channelCode'])
|
codes.append(i['channelCode'])
|
||||||
tds_info = TDeviceSerializer(instance=TDevice.objects.filter(code__in=codes), many=True).data
|
tds_info = TDeviceSerializer(
|
||||||
|
instance=TDevice.objects.filter(code__in=codes), many=True).data
|
||||||
tds_dict = {}
|
tds_dict = {}
|
||||||
for i in tds_info:
|
for i in tds_info:
|
||||||
tds_dict[i['code']] = i
|
tds_dict[i['code']] = i
|
||||||
|
|
@ -527,3 +538,29 @@ class TlogViewSet(ListModelMixin, CustomGenericViewSet):
|
||||||
queryset = Tlog.objects.all()
|
queryset = Tlog.objects.all()
|
||||||
serializer_class = TlogSerializer
|
serializer_class = TlogSerializer
|
||||||
filterset_fields = ['result', 'id']
|
filterset_fields = ['result', 'id']
|
||||||
|
|
||||||
|
|
||||||
|
class DoorAuthViewSet(ListModelMixin, DestroyModelMixin, CustomGenericViewSet):
|
||||||
|
"""
|
||||||
|
list: 门禁权限
|
||||||
|
|
||||||
|
门禁权限
|
||||||
|
"""
|
||||||
|
perms_map = {'get': '*', 'delete': 'doorauth.delete'}
|
||||||
|
queryset = DoorAuth.objects.all()
|
||||||
|
serializer_class = DoorAuthSerializer
|
||||||
|
filterset_fields = ['dchannel', 'employee']
|
||||||
|
select_related_fields = ['dchannel', 'employee']
|
||||||
|
search_fields = ['employee__name']
|
||||||
|
|
||||||
|
@transaction.atomic
|
||||||
|
def perform_destroy(self, instance):
|
||||||
|
dh_face_card = instance.employee.third_info['dh_face_card']
|
||||||
|
rdict = {
|
||||||
|
"cardNumber": dh_face_card,
|
||||||
|
"cardPrivilegeDetails": [
|
||||||
|
{"privilegeType": 1, "resouceCode": instance.dchannel.code},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
dhClient.request(**dhapis['card_door_authority_delete'], json=rdict)
|
||||||
|
instance.delete()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue