factory/apps/hrm/services.py

276 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.dahua import dhClient
from apps.utils.tools import rannum, ranstr
from datetime import datetime, timedelta
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: # 如果未规定时间范围, 默认1小时
startDate = now.strftime("%Y-%m-%d %H:%M:%S")
endDate = (now+timedelta(minutes=60)).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)
# 此处可触发安全帽事件逻辑