员工创建与更新与大华联动,通道授权

This commit is contained in:
caoqianming 2022-04-18 11:02:55 +08:00
parent c400fd79b4
commit 2c2172e990
29 changed files with 427 additions and 328 deletions

View File

@ -1 +1,4 @@
NO_NEED_LEVEL_REMARK = {"code":"no_need_level_remark", "detail":"无需填写离岗说明"}
NO_NEED_LEVEL_REMARK = {"code":"no_need_level_remark", "detail":"无需填写离岗说明"}
PHONE_F_WRONG = {"code":"phone_f_wrong", "detail":"手机号格式错误"}
PHONE_EXIST = {"code":"phone_exist", "detail":"手机号已存在"}
DH_PHOTO_FALI = {"code":"dh_photo_fail", "detail":"大华照片人脸提取失败"}

View File

@ -1,4 +1,4 @@
# Generated by Django 3.2.6 on 2021-08-13 09:16
# Generated by Django 3.2.12 on 2022-04-13 06:34
from django.conf import settings
from django.db import migrations, models
@ -11,29 +11,75 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
('system', '0003_remove_user_phone'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Employee',
name='NotWorkRemark',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('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='删除标记')),
('number', models.CharField(blank=True, max_length=50, null=True, unique=True, verbose_name='人员编号')),
('not_work_date', models.DateField(verbose_name='未打卡日期')),
('remark', models.CharField(blank=True, max_length=200, null=True, verbose_name='未打卡说明')),
('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='notworkremark_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')),
('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='notworkremark_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='用户')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='Employee',
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='删除标记')),
('name', models.CharField(max_length=20, verbose_name='姓名')),
('phone', models.CharField(blank=True, max_length=11, null=True, verbose_name='手机号')),
('email', models.EmailField(blank=True, max_length=254, null=True, verbose_name='邮箱号')),
('number', models.CharField(blank=True, max_length=50, null=True, verbose_name='人员编号')),
('photo', models.CharField(blank=True, max_length=1000, null=True, verbose_name='证件照')),
('ID_number', models.CharField(blank=True, max_length=100, null=True, verbose_name='身份证号')),
('id_number', models.CharField(blank=True, max_length=100, null=True, verbose_name='身份证号')),
('gender', models.CharField(default='', max_length=10, verbose_name='性别')),
('signature', models.CharField(blank=True, max_length=200, null=True, verbose_name='签名图片')),
('birthday', models.DateField(blank=True, null=True, verbose_name='出生年月日')),
('qualification', models.CharField(blank=True, max_length=50, null=True, verbose_name='学历')),
('job_state', models.IntegerField(choices=[(10, '在职'), (20, '离职')], default=1, verbose_name='在职状态')),
('face_data', models.JSONField(blank=True, null=True, verbose_name='人脸识别数据')),
('is_atwork', models.BooleanField(default=False, verbose_name='当前在岗')),
('show_atwork', models.BooleanField(default=True, verbose_name='是否展示在岗状态')),
('last_check_time', models.DateTimeField(blank=True, null=True, verbose_name='打卡时间')),
('not_work_remark', models.CharField(blank=True, max_length=200, null=True, verbose_name='当前未打卡说明')),
('third_info', models.JSONField(blank=True, default=dict, null=True, verbose_name='三方信息')),
('belong_dept', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='employee_belong_dept', to='system.dept', verbose_name='所属部门')),
('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='employee_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')),
('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='employee_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='employee_user', to=settings.AUTH_USER_MODEL)),
('user', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='employee_user', to=settings.AUTH_USER_MODEL, verbose_name='系统账号')),
],
options={
'verbose_name': '员工补充信息',
'verbose_name_plural': '员工补充信息',
},
),
migrations.CreateModel(
name='ClockRecord',
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='删除标记')),
('type', models.PositiveSmallIntegerField(choices=[(10, '上班打卡')], default=10, verbose_name='打卡类型')),
('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='clockrecord_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')),
('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='clockrecord_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')),
],
options={
'abstract': False,
},
),
]

View File

@ -1,35 +0,0 @@
# Generated by Django 3.2.6 on 2021-09-24 03:27
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('system', '0003_auto_20210812_0909'),
('hrm', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='employee',
name='academic',
field=models.CharField(blank=True, max_length=50, null=True, verbose_name='学历'),
),
migrations.AddField(
model_name='employee',
name='birthdate',
field=models.DateField(blank=True, null=True, verbose_name='出生年月'),
),
migrations.AddField(
model_name='employee',
name='job',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='system.position', verbose_name='岗位'),
),
migrations.AddField(
model_name='employee',
name='jobstate',
field=models.IntegerField(choices=[(1, '在职'), (2, '离职')], default=1, verbose_name='在职状态'),
),
]

View File

@ -1,18 +0,0 @@
# Generated by Django 3.2.6 on 2021-10-18 05:26
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('hrm', '0002_auto_20210924_1127'),
]
operations = [
migrations.AddField(
model_name='employee',
name='face_data',
field=models.JSONField(blank=True, null=True, verbose_name='人脸识别数据'),
),
]

View File

@ -1,32 +0,0 @@
# Generated by Django 3.2.9 on 2022-01-21 06:45
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('hrm', '0003_employee_face_data'),
]
operations = [
migrations.CreateModel(
name='ClockRecord',
fields=[
('id', models.BigAutoField(auto_created=True, 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='删除标记')),
('type', models.PositiveSmallIntegerField(choices=[(10, '上班打卡')], default=10, verbose_name='打卡类型')),
('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='clockrecord_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')),
('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='clockrecord_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')),
],
options={
'abstract': False,
},
),
]

View File

@ -1,37 +0,0 @@
# Generated by Django 3.2.9 on 2022-01-26 05:51
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('hrm', '0004_clockrecord'),
]
operations = [
migrations.RenameField(
model_name='employee',
old_name='birthdate',
new_name='birthday',
),
migrations.RenameField(
model_name='employee',
old_name='ID_number',
new_name='id_number',
),
migrations.RenameField(
model_name='employee',
old_name='jobstate',
new_name='job_state',
),
migrations.RenameField(
model_name='employee',
old_name='academic',
new_name='qualification',
),
migrations.RemoveField(
model_name='employee',
name='job',
),
]

View File

@ -1,23 +0,0 @@
# Generated by Django 3.2.9 on 2022-02-17 13:55
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('hrm', '0005_auto_20220126_1351'),
]
operations = [
migrations.AddField(
model_name='employee',
name='is_atwork',
field=models.BooleanField(default=False, verbose_name='当前在岗'),
),
migrations.AddField(
model_name='employee',
name='last_check_time',
field=models.DateTimeField(blank=True, null=True, verbose_name='打卡时间'),
),
]

View File

@ -1,41 +0,0 @@
# Generated by Django 3.2.9 on 2022-02-18 00:43
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('hrm', '0006_auto_20220217_2155'),
]
operations = [
migrations.AddField(
model_name='employee',
name='not_work_remark',
field=models.CharField(blank=True, max_length=200, null=True, verbose_name='当前未打卡说明'),
),
migrations.CreateModel(
name='NotWorkRemark',
fields=[
('id', models.BigAutoField(auto_created=True, 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='删除标记')),
('year', models.PositiveSmallIntegerField(default=2022, verbose_name='')),
('month', models.PositiveSmallIntegerField(default=2, verbose_name='')),
('day', models.PositiveSmallIntegerField(default=1, verbose_name='')),
('remark', models.CharField(blank=True, max_length=200, null=True, verbose_name='未打卡说明')),
('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='notworkremark_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')),
('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='notworkremark_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='用户')),
],
options={
'abstract': False,
},
),
]

View File

@ -1,32 +0,0 @@
# Generated by Django 3.2.9 on 2022-02-22 03:12
from django.db import migrations, models
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('hrm', '0007_auto_20220218_0843'),
]
operations = [
migrations.RemoveField(
model_name='notworkremark',
name='day',
),
migrations.RemoveField(
model_name='notworkremark',
name='month',
),
migrations.RemoveField(
model_name='notworkremark',
name='year',
),
migrations.AddField(
model_name='notworkremark',
name='not_work_date',
field=models.DateField(default=django.utils.timezone.now, verbose_name='未打卡日期'),
preserve_default=False,
),
]

View File

@ -1,18 +0,0 @@
# Generated by Django 3.2.9 on 2022-03-17 03:57
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('hrm', '0008_auto_20220222_1112'),
]
operations = [
migrations.AddField(
model_name='employee',
name='show_atwork',
field=models.BooleanField(default=True, verbose_name='是否展示在岗状态'),
),
]

View File

@ -36,7 +36,7 @@ class Employee(CommonBModel):
show_atwork = models.BooleanField('是否展示在岗状态', default=True)
last_check_time = models.DateTimeField('打卡时间', null=True, blank=True)
not_work_remark = models.CharField('当前未打卡说明', null=True, blank=True, max_length=200)
third_info = models.JSONField('三方信息', default=dict, null=True, blank=True)
class Meta:
verbose_name = '员工补充信息'
verbose_name_plural = verbose_name
@ -44,6 +44,15 @@ class Employee(CommonBModel):
def __str__(self):
return self.name
# class Card(CommonAModel):
# """
# 卡
# """
# CARD_FACE = 10
# CARD_LOCATION = 20
class NotWorkRemark(CommonAModel):
"""
离岗说明

View File

@ -1,18 +1,22 @@
from apps.system.models import User
from apps.hrm.errors import DH_PHOTO_FALI, PHONE_EXIST, PHONE_F_WRONG
from apps.system.models import Dept, User
from rest_framework.serializers import ModelSerializer
from rest_framework import serializers
from apps.utils.serializers import CustomModelSerializer
from apps.utils.constants import EXCLUDE_FIELDS
from apps.utils.tools import rannum, ranstr
from .models import ClockRecord, Employee, NotWorkRemark
from apps.system.serializers import DeptSimpleSerializer,UserSimpleSerializer
from django.db import transaction
from apps.utils.dahua import dhClient
from apps.third.tapis import dhapis
import re
from server.settings import DEBUG
from rest_framework.exceptions import ParseError
from datetime import datetime, timedelta
class EmployeeSerializer(CustomModelSerializer):
belong_dept_ = DeptSimpleSerializer(source='user.belong_dept', read_only=True)
class Meta:
model = Employee
exclude = EXCLUDE_FIELDS + ['face_data']
class EmployeeBaseSerializer(CustomModelSerializer):
def save(self, **kwargs):
if self.validated_data.get('user', None):
user = self.validated_data['user']
@ -21,6 +25,174 @@ class EmployeeSerializer(CustomModelSerializer):
return super().save(**kwargs)
def phone_check(phone):
re_phone = '^1[358]\d{9}$|^147\d{8}$|^176\d{8}$'
if not re.match(re_phone, phone):
raise serializers.ValidationError(**PHONE_F_WRONG)
return phone
class EmployeeCreateUpdateSerializer(EmployeeBaseSerializer):
phone = serializers.CharField(label="手机号", validators=[phone_check])
class Meta:
model = Employee
exclude = EXCLUDE_FIELDS + ['face_data',
'is_atwork', 'last_check_time',
'not_work_remark', 'third_info']
extra_kwargs = {
'phone': {'required': True},
'number': {'required': True},
'photo': {'required': True},
'id_number': {'required': True},
}
@transaction.atomic
def create(self, validated_data):
instance = super().create(validated_data)
if dhClient:
# 创建人员
_, res = dhClient.request(**dhapis['gen_person_id'])
personId = res['id']
departmentId = 1
if instance.belong_dept:
try:
departmentId = instance.belong_dept.third_info['dh_id']
except:
pass
json_data = {
"service":"ehs",
"id": personId,
"name": instance.name,
"code": instance.number,
"paperType": 111,
"paperNumber": instance.id_number,
"paperAddress": "default",
"departmentId": departmentId,
"phone": instance.phone,
"email": instance.email,
"sex": 1 if instance.gender == '' else 2
}
_, res = dhClient.request(**dhapis['person_img_upload'], file_path_rela=instance.photo)
dh_photo = res["fileUrl"]
json_data.update(
{
"biosignatureTypeList":[3],
"personBiosignatures":[{
"type":3,
"index":1,
"path": dh_photo
}]
}
)
_, res = dhClient.request(**dhapis['person_add'], json=json_data)
# 开人脸卡
_, res = dhClient.request(**dhapis['gen_card_id'])
cardId = res['id']
cardNumber = instance.id[:8] + rannum(2)
now = datetime.now()
startDate = now.strftime("%Y-%m-%d %H:%M:%S")
endDate = (datetime(year=now.year+50,
month=now.month, day=1)).strftime("%Y-%m-%d %H:%M:%S")
json_data = {
"id": cardId,
"cardNumber": cardNumber,
"category": 0,
"cardType": 0,
"personId": personId,
"departmentId":departmentId,
"startDate": startDate,
"endDate": endDate
}
_, res = dhClient.request(**dhapis['card_add'], json=json_data)
instance.third_info = {'dh_id':personId,
'dh_photo':dh_photo, 'dh_face_card':res['id']}
instance.save()
return instance
@transaction.atomic
def update(self, instance, validated_data):
old_photo = instance.photo
instance = super().update(instance, validated_data)
departmentId = 1
if instance.belong_dept:
try:
departmentId = instance.belong_dept.third_info['dh_id']
except:
pass
if dhClient:
third_info = instance.third_info
dh_id = instance.third_info['dh_id']
dh_photo = third_info['dh_photo']
json_data = {
"service":"ehs",
"id": dh_id,
"name": instance.name,
"code": instance.number,
"paperType": 111,
"paperNumber": instance.id_number,
"paperAddress": "default",
"departmentId": departmentId,
"phone": instance.phone,
"email": instance.email,
"sex": 1 if instance.gender == '' else 2,
"biosignatureTypeList":[3],
"personBiosignatures":[{
"type":3,
"index":1,
"path": third_info['dh_photo']
}]
}
if instance.photo != old_photo:
_, res = dhClient.request(**dhapis['person_img_upload'], file_path_rela=instance.photo)
dh_photo = res["fileUrl"]
json_data.update(
{
"biosignatureTypeList":[3],
"personBiosignatures":[{
"type":3,
"index":1,
"path": dh_photo
}]
}
)
third_info['dh_photo'] = dh_photo
dhClient.request(**dhapis['person_update'], json=json_data)
# 开人脸卡
if instance.job_state in [Employee.JOB_ON]:
if not third_info.get('dh_face_card', None):
_, res = dhClient.request(**dhapis['gen_card_id'])
cardId = res['id']
cardNumber = instance.id[:8] + rannum(2)
now = datetime.now()
startDate = now.strftime("%Y-%m-%d %H:%M:%S")
endDate = (datetime(year=now.year+50,
month=now.month, day=1)).strftime("%Y-%m-%d %H:%M:%S")
json_data = {
"id": cardId,
"cardNumber": cardNumber,
"category": 0,
"cardType": 0,
"personId": third_info['dh_id'],
"departmentId":departmentId,
"startDate": startDate,
"endDate": endDate
}
_, res = dhClient.request(**dhapis['card_add'], json=json_data)
third_info['dh_face_card'] = cardNumber
instance.save()
return instance
class ChannelAuthoritySerializer(serializers.Serializer):
pks = serializers.ListField(child=serializers.CharField(max_length=20), label="员工ID列表")
channels = serializers.ListField(child=serializers.CharField(max_length=20), label="门通道ID列表")
class EmployeeSerializer(EmployeeBaseSerializer):
belong_dept_ = DeptSimpleSerializer(source='belong_dept', read_only=True)
class Meta:
model = Employee
exclude = ['face_data']
read_only_fields = ['is_atwork', 'last_check_time', 'not_work_remark']
class EmployeeNotWorkRemarkSerializer(ModelSerializer):

View File

@ -4,7 +4,13 @@ from django.dispatch import receiver
from apps.hrm.models import Employee
from django.conf import settings
# @receiver(post_save, sender=User)
# def createEmployee(sender, instance, created, **kwargs):
# if created:
# Employee.objects.get_or_create(user=instance)
@receiver(post_save, sender=User)
def updateEmployee(sender, instance, created, **kwargs):
# if created:
# 如果账号所属部门有变动, 更新关联人员的所属部门
ep = Employee.objects.filter(user=instance).first()
if ep:
if ep.belong_dept and ep.belong_dept != instance.belong_dept:
ep.belong_dept = instance.belong_dept
ep.save()

View File

@ -1,15 +1,17 @@
from rest_framework import urlpatterns
from apps.hrm.views import ClockRecordViewSet, EmployeeViewSet, FaceLogin, NotWorkRemarkViewSet
from apps.hrm.views import ClockRecordViewSet, EmployeeViewSet, NotWorkRemarkViewSet
from django.urls import path, include
from rest_framework.routers import DefaultRouter
API_BASE_URL = 'api/hrm/'
HTML_BASE_URL = 'hrm/'
router = DefaultRouter()
router.register('employee', EmployeeViewSet, basename='employee')
router.register('clock_record', ClockRecordViewSet, basename='clock_record')
router.register('not_work_remark', NotWorkRemarkViewSet, basename='not_work_reamrk')
urlpatterns = [
path('facelogin/', FaceLogin.as_view()),
path('', include(router.urls)),
path(API_BASE_URL, include(router.urls)),
]

View File

@ -5,7 +5,7 @@ from rest_framework.mixins import UpdateModelMixin, RetrieveModelMixin, CreateMo
from apps.hrm.errors import NO_NEED_LEVEL_REMARK
from apps.hrm.filters import ClockRecordFilterSet, EmployeeFilterSet, NotWorkRemarkFilterSet
from apps.hrm.models import ClockRecord, Employee, NotWorkRemark
from apps.hrm.serializers import ClockRecordListSerializer, EmployeeNotWorkRemarkSerializer, EmployeeSerializer, FaceClockCreateSerializer, FaceLoginSerializer, NotWorkRemarkListSerializer
from apps.hrm.serializers import ClockRecordListSerializer, ChannelAuthoritySerializer, EmployeeCreateUpdateSerializer, EmployeeNotWorkRemarkSerializer, EmployeeSerializer, NotWorkRemarkListSerializer
@ -17,9 +17,14 @@ from apps.system.models import User
from apps.system.serializers import UserSimpleSerializer
from rest_framework.permissions import AllowAny
from rest_framework.decorators import action
from apps.utils.serializers import PkSerializer
from apps.utils.viewsets import CustomModelViewSet, CustomGenericViewSet
from rest_framework.exceptions import ParseError
from django.db import transaction
from datetime import datetime
from rest_framework import serializers
from apps.utils.dahua import dhClient
from apps.third.tapis import dhapis
# Create your views here.
class EmployeeViewSet(CustomModelViewSet):
@ -30,22 +35,12 @@ class EmployeeViewSet(CustomModelViewSet):
select_related_fields = ['user']
filterset_class = EmployeeFilterSet
serializer_class = EmployeeSerializer
create_serializer_class = EmployeeCreateUpdateSerializer
update_serializer_class = EmployeeCreateUpdateSerializer
partial_update_serializer_class = EmployeeCreateUpdateSerializer
search_fields = ['name', 'number', 'user__username']
ordering = ['-pk']
def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
instance = self.get_object()
data = request.data
serializer = self.get_serializer(instance, data=data, partial=partial)
serializer.is_valid(raise_exception=True)
photo = data.get('photo', None)
if instance.photo != photo:
# 调取大华接口
return Response()
serializer.save()
return Response()
@action(methods=['post'], detail=True, perms_map={'post': 'employee_notworkremark'}
, serializer_class=EmployeeNotWorkRemarkSerializer)
def not_work_remark(self, request, pk=None):
@ -77,6 +72,37 @@ class EmployeeViewSet(CustomModelViewSet):
return Response()
raise ParseError(**NO_NEED_LEVEL_REMARK)
@transaction.atomic
@action(methods=['post'], detail=False, perms_map={'post': 'employee_channel_authority'}
, serializer_class=ChannelAuthoritySerializer)
def channel_authority(self, request, pk=None):
"""门通道授权
门通道授权
"""
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
vdata = serializer.validated_data
objs = Employee.objects.filter(pk__in=vdata['pks'])
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
})
json_data = {
"cardNumbers": cards,
"timeQuantumId": 1,
"cardPrivilegeDetails": details
}
dhClient.request(**dhapis['card_door_authority'], json=json_data)
objs.update(third_info__dh_channels = vdata['channels'])
return Response()
class ClockRecordViewSet(ListModelMixin, CustomGenericViewSet):
"""

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.12 on 2022-04-18 02:36
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('monitor', '0002_alter_drfrequestlog_id'),
]
operations = [
migrations.AlterField(
model_name='drfrequestlog',
name='view_method',
field=models.CharField(blank=True, db_index=True, max_length=20, null=True),
),
]

View File

@ -28,7 +28,7 @@ class DrfRequestLog(BaseModel):
help_text="执行视图",
)
view_method = models.CharField(
max_length=6,
max_length=20,
null=True,
blank=True,
db_index=True,

View File

@ -1,8 +1,7 @@
SCHEDULE_WRONG = {"code":"schedule_wrong", "detail":"时间策略有误"}
PASSWORD_NOT_SAME = {"code":"password_not_same", "detail":"新旧密码不一致"}
OLD_PASSWORD_WRONG = {"code":"old_password_wrong", "detail":"旧密码错误"}
PHONE_F_WRONG = {"code":"phone_f_wrong", "detail":"手机号格式错误"}
PHONE_EXIST = {"code":"phone_exist", "detail":"手机号已存在"}
USERNAME_EXIST = {"code":"username_exist", "detail":"账户已存在"}
ROLE_NAME_EXIST = {"code":"role_name_exist", "detail":"角色名已存在"}
ROLE_CODE_EXIST = {"code":"role_code_exist", "detail":"角色标识已存在"}

View File

@ -3,7 +3,7 @@ import re
from django_celery_beat.models import PeriodicTask, CrontabSchedule, IntervalSchedule
from rest_framework import serializers
from django_celery_results.models import TaskResult
from apps.system.errors import PHONE_EXIST, PHONE_F_WRONG, ROLE_CODE_EXIST, ROLE_NAME_EXIST, USERNAME_EXIST
from apps.system.errors import ROLE_CODE_EXIST, ROLE_NAME_EXIST, USERNAME_EXIST
from apps.utils.serializers import CustomModelSerializer
from apps.utils.constants import EXCLUDE_FIELDS, EXCLUDE_FIELDS_BASE
from .models import (Dict, DictType, File, Dept, Permission, Post,
@ -210,8 +210,20 @@ class DeptCreateUpdateSerializer(CustomModelSerializer):
@transaction.atomic
def update(self, instance, validated_data):
if instance.name != validated_data.get('name', ''):
from apps.utils.dahua import dhClient
from apps.utils.dahua import dhClient
third_info = instance.third_info
if dhClient and not third_info.get('dh_id', False):
# 如果dh_id 不存在
data = {
"parentId":1,
"name":validated_data['name'],
"service":"ehs"
}
_, res = dhClient.request(**dhapis['dept_create'],json=data)
third_info['dh_id'] = res['id']
instance.third_info = third_info
instance.save()
elif instance.name != validated_data.get('name', ''):
if dhClient and instance.third_info.get('dh_id', False):
data = {
"id":instance.third_info['dh_id'],

View File

@ -11,7 +11,51 @@ dhapis = {
"dept_update":{
"url":"/evo-apigw/evo-brm/1.0.0/department/update",
"method":"put"
}
},
"gen_person_id":{
"url":"/evo-apigw/evo-brm/1.0.0/person/generate-id",
"method":"get"
},
"person_add": {
"url":"/evo-apigw/evo-brm/1.2.0/person/subsystem/add",
"method":"post"
},
"person_update": {
"url":"/evo-apigw/evo-brm/1.2.0/person/subsystem/update",
"method":"put"
},
"person_img_upload": {
"url":"/evo-apigw/evo-brm/1.2.0/person/upload/img",
"method":"post"
},
"person_detail": {
"url":"/evo-apigw/evo-brm/1.0.0/person/subsystem/{id}",
"method":"get"
},
"device_list": {
"url":"/evo-apigw/evo-brm/1.2.0/device/subsystem/page",
"method":"get"
},
"device_detail": {
"url":"/evo-apigw/evo-brm/1.0.0/device/{deviceCode}",
"method":"get"
},
"channel_list": {
"url":"/evo-apigw/evo-brm/1.2.0/device/channel/subsystem/page",
"method":"post"
},
"card_add": {
"url":"/evo-apigw/evo-brm/1.2.0/card/add",
"method":"post"
},
"gen_card_id": {
"url":"/evo-apigw/evo-brm/1.0.0/card/generate-id",
"method":"get"
},
"card_door_authority": {
"url":"/evo-apigw/evo-accesscontrol/1.0.0/card/accessControl/doorAuthority",
"method":"post"
},
}
# 寻息API接口

View File

@ -3,6 +3,7 @@ from apps.third.tapis import dhapis, xxapis
from apps.third.erros import TAPI_CODE_WRONG
from apps.utils.dahua import dhClient
from apps.utils.errors import XX_REQUEST_ERROR
from apps.utils.mixins import MyLoggingMixin
from apps.utils.xunxi import xxClient
from rest_framework.response import Response
from rest_framework.views import APIView
@ -15,45 +16,19 @@ from apps.third.serializers import RequestCommonSerializer
# Create your views here.
class DahuaTestView(APIView):
class DahuaTestView(MyLoggingMixin, APIView):
"""
大华测试接口
"""
permission_classes = [IsAuthenticated]
def get(self, request, *args, **kwargs):
data = {
"data":{
"channelId": "1001339$1$0$0",
"streamType": "1",
"type": "hls"
}
}
# ok, res = dhClient.request(
# url='/evo-apigw/admin/API/video/stream/realtime', method='post', json=data)
ok, res = dhClient.request(url='/evo-apigw/evo-brm/1.2.0/department/tree',
method='get')
# data = {
# "pageNum":1,
# "pageSize":100,
# "isOnline":1,
# "showChildNodeData":1,
# "categorys":[8]
# }
# res = dhClient.request(
# url='/evo-apigw/evo-brm/1.0.0/device/subsystem/page', method='post', json=data)
# data = {
# "channelCodeList": ["1001382$7$0$0"]
# }
# res = dhClient.request(
# url='/evo-apigw/evo-accesscontrol/1.0.0/card/accessControl/channelControl/closeDoor', method='post', json=data)
if ok == 'success':
return Response(res)
elif ok == 'fail':
raise ParseError(**res)
else:
raise APIException(**res)
# file_path_rela = '/media/default/avatar.png'
# _, res = dhClient.request(**dhapis['person_img_upload'], file_path_rela=file_path_rela)
_,res = dhClient.request(
url='/evo-apigw/evo-brm/1.0.0/person/subsystem/{}'.format(2059335),
method='get')
return Response(res)
class XxTestView(APIView):

View File

@ -7,6 +7,7 @@ from server import settings
import json
import time
from rest_framework.exceptions import APIException, ParseError
import os
requests.packages.urllib3.disable_warnings()
class DhClient:
@ -63,21 +64,31 @@ class DhClient:
自定义销毁
"""
self.isRuning = False
self.t.join()
# self.t.join()
def request(self, url:str, method:str, params=dict(), json=dict(), timeout=20, raise_exception=True):
def request(self, url:str, method:str, params=dict(), json=dict(), timeout=4, file_path_rela=None, raise_exception=True):
if self.isGetingToken:
req_num = 0
while True:
time.sleep(0.5)
if not self.isGetingToken:
self.request(url, method, params, json, timeout)
self.request(url, method, params, json, timeout, file_path_rela, raise_exception)
req_num = req_num + 1
if req_num > 4:
break
else:
r = getattr(requests, method)('{}{}'.format(settings.DAHUA_BASE_URL, url)
, headers = self.headers, params=params, json=json, verify=False)
files = None
if file_path_rela: # 相对路径
files = {'file': open(settings.BASE_DIR + file_path_rela, 'rb')}
try:
if params:
url = url.format(**params)
r = getattr(requests, method)('{}{}'.format(settings.DAHUA_BASE_URL, url)
, headers = self.headers, params=params, json=json, timeout=timeout, files=files, verify=False)
except:
if raise_exception:
raise APIException(**DH_REQUEST_ERROR)
return 'error', DH_REQUEST_ERROR
# if settings.DEBUG:
# print_roundtrip(r)
if r.status_code == 200:
@ -87,7 +98,7 @@ class DhClient:
ret = r.json()
if ret.get('code') == '27001007':
self.get_token() # 重新获取token
self.request(url, method, params, json, timeout) # 重新请求
self.request(url, method, params, json, timeout, file_path_rela, raise_exception)
else:
if ret['code'] not in ['0', '100', '00000', '1000', 0, 100, 1000]:
detail = '大华错误:' + '{}|{}{}'.format(str(ret['code']), ret.get('errMsg',''), ret.get('desc', ''))

View File

@ -68,7 +68,7 @@ class MyLoggingMixin(object):
CLEANED_SUBSTITUTE = "********************"
# logging_methods = "__all__"
logging_methods = ['POST', 'PUT', 'DELETE', 'PATCH']
logging_methods = '__all__'
sensitive_fields = {}
def __init__(self, *args, **kwargs):
@ -100,6 +100,7 @@ class MyLoggingMixin(object):
def handle_exception(self, exc):
response = super().handle_exception(exc)
self.log["errors"] = traceback.format_exc()
return response
def finalize_response(self, request, response, *args, **kwargs):
@ -230,7 +231,7 @@ class MyLoggingMixin(object):
"""
return (
self.logging_methods == "__all__" or request.method in self.logging_methods
)
) and (response.status_code not in (401, 403))
def _clean_data(self, data):
"""

View File

@ -1,5 +1,6 @@
import textwrap
import requests
import random
import string
def print_roundtrip(response, *args, **kwargs):
format_headers = lambda d: '\n'.join(f'{k}: {v}' for k, v in d.items())
@ -19,4 +20,12 @@ def print_roundtrip(response, *args, **kwargs):
res=response,
reqhdrs=format_headers(response.request.headers),
reshdrs=format_headers(response.headers),
))
))
def ranstr(num):
salt = ''.join(random.sample(string.ascii_lowercase + string.digits, num))
return salt
def rannum(num):
salt = ''.join(random.sample(string.digits, num))
return salt

View File

@ -58,7 +58,7 @@ class XxClient:
self.isRuning = False
self.t.join()
def request(self, url:str, method:str='post', params=dict(), json=dict(), timeout=20, raise_exception=True):
def request(self, url:str, method:str='post', params=dict(), json=dict(), timeout=4, raise_exception=True):
params['accessToken'] = self.token
json['username'] = self.username
json['buildId'] = settings.XX_BUILDID
@ -67,19 +67,19 @@ class XxClient:
while True:
time.sleep(0.5)
if not self.isGetingToken:
self.request(url, method, params, json, timeout)
self.request(url, method, params, json, timeout, raise_exception)
req_num = req_num + 1
if req_num > 4:
break
else:
r = getattr(requests, method)('{}{}'.format(settings.XX_BASE_URL, url)
, params=params, json=json, verify=False)
, params=params, json=json, timeout=timeout, verify=False)
# if settings.DEBUG:
# print_roundtrip(r)
ret = r.json()
if ret.get('errorCode') == '1060000':
self.get_token() # 重新获取token
self.request(url, method, params, json, timeout) # 重新请求
self.request(url, method, params, json, timeout, raise_exception) # 重新请求
else:
if ret['errorCode'] != 0:
err_detail = dict(detail='寻息错误:' + '|'.join(ret['errorMsg']),

BIN
media/default/test.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

BIN
media/default/test2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

View File

@ -52,7 +52,8 @@ INSTALLED_APPS = [
'apps.system',
'apps.auth1',
'apps.monitor',
'apps.wf'
'apps.wf',
'apps.hrm'
]
MIDDLEWARE = [

View File

@ -47,6 +47,7 @@ urlpatterns = [
path('', include('apps.third.urls')),
path('', include('apps.utils.urls')),
path('', include('apps.develop.urls')),
path('', include('apps.hrm.urls')),