diff --git a/apps/hrm/migrations/0004_alter_employee_phone.py b/apps/hrm/migrations/0004_alter_employee_phone.py new file mode 100644 index 00000000..1909f07c --- /dev/null +++ b/apps/hrm/migrations/0004_alter_employee_phone.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.12 on 2022-07-13 08:51 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('hrm', '0003_employee_post'), + ] + + operations = [ + migrations.AlterField( + model_name='employee', + name='phone', + field=models.CharField(blank=True, max_length=11, null=True, verbose_name='手机号'), + ), + ] diff --git a/apps/hrm/models.py b/apps/hrm/models.py index 7b3fd192..01ee146b 100755 --- a/apps/hrm/models.py +++ b/apps/hrm/models.py @@ -24,7 +24,7 @@ class Employee(CommonBModel): verbose_name='系统账号', on_delete=models.PROTECT, null=True, blank=True) name = models.CharField('姓名', max_length=20) - phone = models.CharField('手机号', max_length=11, null=True, blank=True, unique=True) + phone = models.CharField('手机号', max_length=11, null=True, blank=True) email = models.EmailField('邮箱号', null=True, blank=True) number = models.CharField('人员编号', max_length=50, null=True, blank=True) photo = models.CharField('证件照', max_length=1000, null=True, blank=True) @@ -40,6 +40,7 @@ class Employee(CommonBModel): not_work_remark = models.CharField('当前未打卡说明', null=True, blank=True, max_length=200) third_info = models.JSONField('三方信息', default=dict, null=False, blank=True) # 主要是定位卡信息 post = models.ForeignKey(Post, verbose_name='所属岗位', on_delete=models.SET_NULL, null=True, blank=True) + class Meta: verbose_name = '员工补充信息' diff --git a/apps/hrm/services.py b/apps/hrm/services.py index 7e1f075c..a659db28 100755 --- a/apps/hrm/services.py +++ b/apps/hrm/services.py @@ -1,3 +1,4 @@ +from os import access from apps.hrm.models import Employee from apps.third.models import TDevice from apps.third.tapis import dhapis @@ -10,20 +11,19 @@ class HrmService: @classmethod def sync_dahua_employee(cls, ep: Employee, old_photo='', start_time=None, end_time=None): - """同步大华信息 + """同步大华信息(员工/卡片/门禁) Args: ep (Employee): 人员实例 old_photo (str, optional): 原照片地址. Defaults to ''. start_time (_type_, optional): 开人脸卡起始时间. Defaults to None. end_time (_type_, optional): 开人脸卡结束时间. Defaults to None. - Returns: _type_: _description_ """ - dh_id = None - dh_photo = None - dh_face_card = None + dh_id = ep.third_info.get('dh_id', None) + dh_photo = ep.third_info.get('dh_photo', None) + dh_face_card = ep.third_info.get('dh_face_card', None) departmentId = 1 if ep.belong_dept: try: @@ -52,7 +52,7 @@ class HrmService: "path": dh_photo }] } - if ep.photo != old_photo: + if ep.photo != old_photo and ep.photo: _, res = dhClient.request(**dhapis['person_img_upload'], file_path_rela=ep.photo) dh_photo = res["fileUrl"] json_data.update( @@ -66,19 +66,10 @@ class HrmService: } ) dhClient.request(**dhapis['person_update'], json=json_data) - # 开人脸卡 长时间 - if ep.job_state in [Employee.JOB_ON]: - dh_face_card = cls.open_face_card( - ep=ep, dh_id=dh_id, departmentId=departmentId, start_time=start_time, end_time=end_time) + ep = cls.save(ep, data={'dh_face_card': dh_face_card}) else: _, res = dhClient.request(**dhapis['person_gen_id']) dh_id = res['id'] - departmentId = 1 - if ep.belong_dept: - try: - departmentId = ep.belong_dept.third_info['dh_id'] - except Exception: - pass json_data = { "service": "ehs", "id": dh_id, @@ -105,10 +96,12 @@ class HrmService: } ) _, res = dhClient.request(**dhapis['person_add'], json=json_data) - # 开人脸卡 - if ep.job_state in [Employee.JOB_ON]: - dh_face_card = cls.open_face_card( - ep=ep, dh_id=dh_id, departmentId=departmentId, start_time=start_time, end_time=end_time) + ep = cls.save(ep, data={'dh_id': dh_id, 'dh_photo': dh_photo}) + # 开人脸卡 + dh_face_card = cls.open_face_card( + ep=ep, dh_id=dh_id, departmentId=departmentId, start_time=start_time, end_time=end_time) + # 授予门禁权限 + cls.door_auth(ep=ep, dh_face_card=dh_face_card) return {'dh_id': dh_id, 'dh_photo': dh_photo, 'dh_face_card': dh_face_card} @classmethod @@ -153,13 +146,42 @@ class HrmService: "endDate": endDate } _, res = dhClient.request(**dhapis['card_add'], json=json_data) + cls.save(ep, data={'dh_face_card': cardNumber}) return cardNumber @classmethod - def door_auth(cls): + def door_auth(cls, ep: Employee, dh_face_card: str): """授予门禁权限 """ - pass + from apps.third.models import TDevice + # 查找可授予的门禁 + door_codes = list(TDevice.objects.filter(type=TDevice.DEVICE_DCHANNEL, + access_list__contains=ep.type).values_list('code', flat=True)) + details = [] + for i in door_codes: + details.append({ + "privilegeType": 1, + "resouceCode": i + }) + + json_data = { + "cardNumbers": [dh_face_card], + "timeQuantumId": 1, + "cardPrivilegeDetails": details + } + dhClient.request(**dhapis['card_door_authority'], json=json_data) + cls.save(ep, data={'dh_dchannels': door_codes}) + return door_codes + + @classmethod + def save(cls, ep: Employee, data: dict): + """更新third_info + """ + ti = ep.third_info + ti.update(data) + ep.third_info = ti + ep.save() + return ep @classmethod def swipe(cls, data: dict): diff --git a/apps/system/migrations/0003_alter_user_phone.py b/apps/system/migrations/0003_alter_user_phone.py new file mode 100644 index 00000000..22af7104 --- /dev/null +++ b/apps/system/migrations/0003_alter_user_phone.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.12 on 2022-07-13 08:51 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('system', '0002_user_post'), + ] + + operations = [ + migrations.AlterField( + model_name='user', + name='phone', + field=models.CharField(blank=True, max_length=11, null=True, verbose_name='手机号'), + ), + ] diff --git a/apps/system/models.py b/apps/system/models.py index 3684e570..878066da 100755 --- a/apps/system/models.py +++ b/apps/system/models.py @@ -122,7 +122,7 @@ class User(AbstractUser, CommonBModel): """ type = models.CharField('账号类型', max_length=10, default='employee') name = models.CharField('姓名', max_length=20, null=True, blank=True) - phone = models.CharField('手机号', max_length=11, null=True, blank=True, unique=True) + phone = models.CharField('手机号', max_length=11, null=True, blank=True) avatar = models.CharField( '头像', default='/media/default/avatar.png', max_length=100, null=True, blank=True) superior = models.ForeignKey( diff --git a/apps/vm/services.py b/apps/vm/services.py index 7f19943a..f3e83150 100644 --- a/apps/vm/services.py +++ b/apps/vm/services.py @@ -26,12 +26,15 @@ def visit_audit_end(ticket): # 更新企业访客人员库 for i in Vpeople.objects.filter(visit=visit): visitor = i.visitor - ep = Employee.objects.filter(id_number=visitor.id_number, type='visitor').first() + if visitor.id_number and visitor.photo: + ep = Employee.objects.filter(id_number=visitor.id_number, type='visitor').first() + else: + ep = Employee.objects.filter(name=visitor.name, type='visitor', id_number=None).first() if ep: pass else: ep = Employee() - ep.id_number = visitor.id_number + ep.id_number = visitor.id_number ep.name = visitor.name ep.phone = visitor.phone ep.photo = visitor.photo diff --git a/apps/wf/views.py b/apps/wf/views.py index b7dbcbbe..5811e768 100755 --- a/apps/wf/views.py +++ b/apps/wf/views.py @@ -259,7 +259,7 @@ class TicketViewSet(CreateUpdateCustomMixin, CreateModelMixin, ListModelMixin, R with transaction.atomic(): ticket = WfService.handle_ticket(ticket=ticket, transition=vdata['transition'], new_ticket_data=new_ticket_data, handler=request.user, - suggestion=vdata['suggestion']) + suggestion=vdata.get('suggestion', '')) return Response(TicketSerializer(instance=ticket).data) @action(methods=['post'], detail=True, perms_map={'post': '*'}) @@ -280,7 +280,7 @@ class TicketViewSet(CreateUpdateCustomMixin, CreateModelMixin, ListModelMixin, R ticket.save() TicketFlow.objects.create(ticket=ticket, state=ticket.state, ticket_data=WfService.get_ticket_all_field_value(ticket), - suggestion=vdata['suggestion'], participant_type=State.PARTICIPANT_TYPE_PERSONAL, + suggestion=vdata.get('suggestion', ''), participant_type=State.PARTICIPANT_TYPE_PERSONAL, intervene_type=Transition.TRANSITION_INTERVENE_TYPE_DELIVER, participant=request.user, transition=None) return Response()