277 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
			
		
		
	
	
			277 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
| from rest_framework.exceptions import ParseError, APIException
 | |
| import logging
 | |
| import time
 | |
| from apps.hrm.models import ClockRecord, Employee
 | |
| from apps.third.errors import DH_REQUEST_ERROR
 | |
| from apps.third.models import TDevice
 | |
| from apps.third.tapis import dhapis
 | |
| from apps.third.clients import dhClient
 | |
| from apps.utils.tools import rannum, ranstr
 | |
| from datetime import datetime
 | |
| from django.utils import timezone
 | |
| myLogger = logging.getLogger('log')
 | |
| 
 | |
| 
 | |
| 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 = 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:
 | |
|                 departmentId = ep.belong_dept.third_info['dh_id']
 | |
|             except Exception:
 | |
|                 pass
 | |
|         if ep.third_info.get('dh_id', None):  # 如果有大华信息
 | |
|             dh_id = ep.third_info['dh_id']
 | |
|             dh_photo = ep.third_info['dh_photo']
 | |
|             json_data = {
 | |
|                 "service": "ehs",
 | |
|                 "id": dh_id,
 | |
|                 "name": ep.name,
 | |
|                 "code": ep.number if ep.number else ranstr(6),
 | |
|                 "paperType": 111,
 | |
|                 "paperNumber": ep.id_number,
 | |
|                 "paperAddress": "default",
 | |
|                 "departmentId": departmentId,
 | |
|                 "phone": ep.phone,
 | |
|                 "email": ep.email,
 | |
|                 "sex": 1 if ep.gender == '男' else 2,
 | |
|                 "biosignatureTypeList": [3],
 | |
|                 "personBiosignatures": [{
 | |
|                     "type": 3,
 | |
|                     "index": 1,
 | |
|                     "path": dh_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(
 | |
|                     {
 | |
|                         "biosignatureTypeList": [3],
 | |
|                         "personBiosignatures": [{
 | |
|                             "type": 3,
 | |
|                             "index": 1,
 | |
|                             "path": dh_photo
 | |
|                         }]
 | |
|                     }
 | |
|                 )
 | |
|             dhClient.request(**dhapis['person_update'], json=json_data)
 | |
|         else:
 | |
|             _, res = dhClient.request(**dhapis['person_gen_id'])
 | |
|             dh_id = res['id']
 | |
|             json_data = {
 | |
|                 "service": "ehs",
 | |
|                 "id": dh_id,
 | |
|                 "name": ep.name,
 | |
|                 "code": ep.number if ep.number else ranstr(6),
 | |
|                 "paperType": 111,
 | |
|                 "paperNumber": ep.id_number,
 | |
|                 "paperAddress": "default",
 | |
|                 "departmentId": departmentId,
 | |
|                 "phone": ep.phone,
 | |
|                 "email": ep.email,
 | |
|                 "sex": 1 if ep.gender == '男' else 2
 | |
|             }
 | |
|             _, res = dhClient.request(**dhapis['person_img_upload'], file_path_rela=ep.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)
 | |
|             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)
 | |
|         # 授予门禁权限
 | |
|         dh_dchannels = cls.door_auth(ep=ep)
 | |
|         return {'dh_id': dh_id, 'dh_photo': dh_photo, 'dh_face_card': dh_face_card, 'dh_dchannels': dh_dchannels}
 | |
| 
 | |
|     @classmethod
 | |
|     def open_face_card(cls, ep, dh_id, departmentId, start_time, end_time):
 | |
|         """开人脸卡/有卡就更新卡时间
 | |
|         """
 | |
|         if ep.third_info.get('dh_face_card', None):
 | |
|             cardNumber = ep.third_info.get('dh_face_card')
 | |
|             # 如果有人脸卡就执行更新操作
 | |
|             if start_time is None:  # 如果时间段未提供,跳过更新操作
 | |
|                 pass
 | |
|             else:
 | |
|                 startDate = start_time.strftime("%Y-%m-%d %H:%M:%S")
 | |
|                 endDate = end_time.strftime("%Y-%m-%d %H:%M:%S")
 | |
|                 json_data = {
 | |
|                     "cardNumber": cardNumber,
 | |
|                     "startDate": startDate,
 | |
|                     "endDate": endDate,
 | |
|                     "departmentId": departmentId,
 | |
|                 }
 | |
|                 _, res = dhClient.request(**dhapis['card_update'], json=json_data)
 | |
|             return cardNumber
 | |
|         else:
 | |
|             _, res = dhClient.request(**dhapis['card_gen_id'])
 | |
|             cardId = res['id']
 | |
|             cardNumber = str(ep.id)[3:8] + rannum(5)
 | |
|             now = datetime.now()
 | |
|             if start_time is None:  # 如果未规定时间范围, 默认50年
 | |
|                 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")
 | |
|             else:
 | |
|                 startDate = start_time.strftime("%Y-%m-%d %H:%M:%S")
 | |
|                 endDate = end_time.strftime("%Y-%m-%d %H:%M:%S")
 | |
|             json_data = {
 | |
|                 "id": cardId,
 | |
|                 "cardNumber": cardNumber,
 | |
|                 "category": 0,
 | |
|                 "cardType": 0,
 | |
|                 "personId": dh_id,
 | |
|                 "departmentId": departmentId,
 | |
|                 "startDate": startDate,
 | |
|                 "endDate": endDate
 | |
|             }
 | |
|             _, res = dhClient.request(**dhapis['card_add'], json=json_data)
 | |
|             time.sleep(8)  # 等待确保生成卡片
 | |
|             cls.save(ep, data={'dh_face_card': cardNumber})
 | |
|             return cardNumber
 | |
| 
 | |
|     @classmethod
 | |
|     def door_auth(cls, ep: Employee, dh_dchannels: list = []):
 | |
|         """授予门禁权限
 | |
|         """
 | |
|         from apps.third.models import TDevice
 | |
|         dh_face_card = ep.third_info.get('dh_face_card', None)
 | |
|         if dh_dchannels:
 | |
|             pass
 | |
|         else:
 | |
|             # 查找可授予的门禁通道号
 | |
|             dh_dchannels = list(TDevice.objects.filter(type=TDevice.DEVICE_DCHANNEL,
 | |
|                                                        access_list__contains=ep.type).values_list('code', flat=True))
 | |
|         if dh_dchannels:
 | |
|             details = []
 | |
|             for i in dh_dchannels:
 | |
|                 details.append({
 | |
|                     "privilegeType": 1,
 | |
|                     "resouceCode": i
 | |
|                 })
 | |
|             json_data = {
 | |
|                 "cardNumbers": [dh_face_card],
 | |
|                 "timeQuantumId": 1,
 | |
|                 "cardPrivilegeDetails": details
 | |
|             }
 | |
|             is_ok, res = dhClient.request(**dhapis['card_door_authority'], json=json_data, raise_exception=False)
 | |
|             if is_ok == 'fail' and '44999999' in res['code']:
 | |
|                 time.sleep(6)
 | |
|                 dhClient.request(**dhapis['card_door_authority'], json=json_data)
 | |
|             elif is_ok == 'fail':
 | |
|                 raise ParseError(**res)
 | |
|             elif is_ok == 'error':
 | |
|                 raise APIException(**DH_REQUEST_ERROR)
 | |
|             cls.save(ep, data={'dh_dchannels': dh_dchannels})
 | |
|         return dh_dchannels
 | |
| 
 | |
|     @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):
 | |
|         """
 | |
|         刷卡事件/用于记录考勤
 | |
|         """
 | |
|         from apps.vm.models import Visit
 | |
|         from apps.rpm.models import Rpj
 | |
|         nodeCode = data['info']['nodeCode']
 | |
|         device = TDevice.objects.filter(code=nodeCode).first()
 | |
| 
 | |
|         if device:
 | |
|             id_number = data['info']['extend'].get('paperNumber', None)
 | |
|             if id_number:  # 如果有身份证号
 | |
|                 if device.is_clock:
 | |
|                     # 如果设置为关联考勤
 | |
|                     # myLogger.info(data['info']['extend'])
 | |
|                     if data['info']['extend']['enterOrExit'] == 1:
 | |
|                         # 如果是进门
 | |
|                         ep = Employee.objects.filter(id_number=id_number, type__in=["employee", "remployee"]).first()
 | |
|                         # 如果是内部/相关方员工创建上班打卡记录(更新)
 | |
|                         if ep and ep.is_atwork is False:
 | |
|                             now = timezone.now()
 | |
|                             cr_10 = ClockRecord.objects.filter(
 | |
|                                 type=10, employee=ep, create_time__year=now.year, create_time__month=now.month, create_time__day=now.day).first()
 | |
|                             if cr_10:
 | |
|                                 if now < cr_10.create_time:
 | |
|                                     cr_10.create_time = now
 | |
|                                     cr_10.trigger = 'door'
 | |
|                                     cr_10.detail = data['info']['extend']
 | |
|                                     cr_10.save()
 | |
|                             else:
 | |
|                                 cr_10 = ClockRecord()
 | |
|                                 cr_10.type = 10
 | |
|                                 cr_10.employee = ep
 | |
|                                 cr_10.trigger = 'door'
 | |
|                                 cr_10.detail = data['info']['extend']
 | |
|                                 cr_10.save()
 | |
|                             ep.is_atwork = True
 | |
|                             ep.last_check_time = now
 | |
|                             ep.save()
 | |
|                     elif data['info']['extend']['enterOrExit'] == 2:
 | |
|                         # 如果是出门
 | |
|                         id_number = data['info']['extend']['paperNumber']
 | |
|                         if id_number:
 | |
|                             ep = Employee.objects.filter(id_number=id_number, type="employee").first()
 | |
|                             # 如果是内部/相关方员工创建下班打卡记录(更新)
 | |
|                             if ep and ep.is_atwork:
 | |
|                                 now = timezone.now()
 | |
|                                 cr_20 = ClockRecord.objects.filter(
 | |
|                                     type=20, employee=ep, create_time__year=now.year, create_time__month=now.month, create_time__day=now.day).first()
 | |
|                                 if cr_20:
 | |
|                                     if now > cr_20.create_time:
 | |
|                                         cr_20.create_time = now
 | |
|                                         cr_20.trigger = 'door'
 | |
|                                         cr_20.detail = data['info']['extend']
 | |
|                                         cr_20.save()
 | |
|                                 else:
 | |
|                                     cr_20 = ClockRecord()
 | |
|                                     cr_20.type = 20
 | |
|                                     cr_20.employee = ep
 | |
|                                     cr_20.trigger = 'door'
 | |
|                                     cr_20.detail = data['info']['extend']
 | |
|                                     cr_20.save()
 | |
|                                 ep.is_atwork = False
 | |
|                                 ep.last_check_time = now
 | |
|                                 ep.save()
 | |
| 
 | |
|                 # 进行相关方/访客项目更新
 | |
|                 Visit.objects.filter(state=Visit.V_ENTER, visitors__employee__id_number=id_number).update(
 | |
|                     state=Visit.V_WORKING)
 | |
|                 Rpj.objects.filter(state=Rpj.RPJ_ENTER, remployees__employee__id_number=id_number).update(
 | |
|                     state=Rpj.RPJ_WORKING)
 | |
| 
 | |
|                 # 此处可触发安全帽事件逻辑
 |