feat: 打卡记录增加忽略记录项目并进行代码优化

This commit is contained in:
caoqianming 2023-03-15 18:07:42 +08:00
parent 7cec134265
commit 16daa861bd
5 changed files with 110 additions and 166 deletions

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.12 on 2023-03-15 07:40
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('hrm', '0009_alter_clockrecord_exception_type'),
]
operations = [
migrations.AlterField(
model_name='clockrecord',
name='type',
field=models.PositiveSmallIntegerField(choices=[(10, '上班打卡'), (20, '下班打卡'), (30, '忽略')], default=10, verbose_name='打卡类型'),
),
]

View File

@ -79,9 +79,11 @@ class ClockRecord(BaseModel):
"""
ClOCK_ON = 10
CLOCK_OFF = 20
CLOCK_ING = 30
type_choice = (
(ClOCK_ON, '上班打卡'),
(CLOCK_OFF, '下班打卡'),
(CLOCK_ING, '忽略'), # 尽量不用
)
E_TYPE_LESS = 10
E_TYPE_MORE = 20

View File

@ -211,10 +211,11 @@ class HrmService:
"""
id_number = data['info']['extend'].get('paperNumber', None)
if id_number:
nodeCode = data['info']['nodeCode']
detail = {'id':data['info']['extend']['id']}
nodeCode = data['info']['extend']['acsChannelCode']
swip_time = data['info']['extend']['swingTime']
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, detail)
@classmethod
def swipe_offline(cls, data:dict):
@ -223,177 +224,88 @@ class HrmService:
for i in data['infoArray']:
id_number = i.get('paperNumber', None)
if id_number:
detail = {'id':i['id']}
nodeCode = i['acsChannelCode']
swip_time = i['swingTime']
e_type = i['enterOrExit']
Thread(target=cls.swipe_next, args=(nodeCode, id_number, swip_time, e_type, i), daemon=True).start()
cls.swipe_next(nodeCode, id_number, swip_time, e_type, detail)
@classmethod
def swipe_next(cls, nodeCode: str, id_number: str, swip_time: str, e_type:int, detail:dict):
from apps.vm.models import Visit
from apps.rpm.models import Rpj
# 进行相关方/访客项目更新
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)
# 打卡处理
device = TDevice.objects.filter(code=nodeCode).first()
if device:
ep = Employee.objects.filter(id_number=id_number, type__in=["employee", "remployee"]).first()
if device and device.is_clock and ep:
tzinfo = tz.gettz('Asia/Shanghai')
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,
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,
hour=23, minute=59, second=59, tzinfo=tzinfo)
if device.is_clock:
# 如果设置为关联考勤
# myLogger.info(data['info']['extend'])
if e_type == 1:
# 如果是进门
ep = Employee.objects.filter(id_number=id_number, type__in=["employee", "remployee"]).first()
# 如果是内部/相关方员工创建上班打卡记录(更新)
if ep:
cr_10 = ClockRecord.objects.filter(
type=10, employee=ep, create_time__gte=first_time, create_time__lte=end_time).first()
if cr_10:
if s_time_f < cr_10.create_time:
cr_10.create_time = s_time_f
cr_10.trigger = 'door'
cr_10.detail = detail
cr_10.save()
else:
cr_10 = ClockRecord()
cr_10.type = 10
cr_10.employee = ep
cr_10.trigger = 'door'
cr_10.detail = detail
cr_10.create_time = s_time_f
cr_10.save()
ep.is_atwork = True
ep.last_check_time = s_time_f
ep.save()
elif e_type == 2:
# 如果是出门
ep = Employee.objects.filter(id_number=id_number, type__in=[
"employee", "remployee"]).first()
# 如果是内部/相关方员工创建下班打卡记录(更新)
if ep:
cr_20 = ClockRecord.objects.filter(
type=20, employee=ep, create_time__gte=first_time, create_time__lte=end_time).first()
if cr_20:
cr_20.exception_type = None
if s_time_f > cr_20.create_time:
cr_20.create_time = s_time_f
cr_20.trigger = 'door'
cr_20.detail = detail
cr_20.save()
else:
cr_20 = ClockRecord()
cr_20.type = 20
cr_20.employee = ep
cr_20.trigger = 'door'
cr_20.detail = detail
cr_20.create_time = s_time_f
cr_20.save()
ep.is_atwork = False
ep.last_check_time = s_time_f
ep.save()
# 判断是否有异常
# 找到最近的打卡时间
cr_e = ClockRecord.objects.filter(create_time__lt=cr_20.create_time, employee=ep).exclude(id=cr_20.id).order_by('-create_time').first()
if cr_e:
time_d = cr_20.create_time - cr_e.create_time
if cr_e.type == 10:
if time_d < timedelta(hours=7):
cr_20.exception_type = ClockRecord.E_TYPE_LESS
cr_20.save()
elif time_d > timedelta(hours=14):
cr_20.exception_type = ClockRecord.E_TYPE_MORE
cr_20.save()
elif time_d > timedelta(hours=9):
cr_20.exception_type = ClockRecord.E_TYPE_ADD
cr_20.save()
elif cr_e.type == 20:
cr_20.exception_type = ClockRecord.E_TYPE_MISS
cr_20.save()
elif e_type == 3:
# 如果不确定根据时间来
card_type = None
time_10_x = datetime(year=s_time_f.year, month=s_time_f.month,
day=s_time_f.day, hour=3, minute=0, second=0, tzinfo=tzinfo)
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)
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)
time_20_y = datetime(year=s_time_f.year, month=s_time_f.month,
day=s_time_f.day, hour=23, minute=0, second=0, tzinfo=tzinfo)
if time_10_x < s_time_f < time_10_y:
card_type = 10
elif time_20_x < s_time_f < time_20_y:
card_type = 20
if card_type:
ep = Employee.objects.filter(id_number=id_number, type__in=[
"employee", "remployee"]).first()
# 如果是内部/相关方员工创建下班打卡记录(更新)
if ep and card_type == 10:
cr_10 = ClockRecord.objects.filter(
type=10, employee=ep, create_time__gte=first_time, create_time__lte=end_time).first()
if cr_10:
if s_time_f < cr_10.create_time:
cr_10.create_time = s_time_f
cr_10.trigger = 'panel'
cr_10.detail = detail
cr_10.save()
else:
cr_10 = ClockRecord()
cr_10.type = 10
cr_10.employee = ep
cr_10.trigger = 'panel'
cr_10.detail = detail
cr_10.create_time = s_time_f
cr_10.save()
ep.is_atwork = True
ep.last_check_time = s_time_f
ep.save()
elif ep and card_type == 20:
cr_20 = ClockRecord.objects.filter(
type=20, employee=ep, create_time__gte=first_time, create_time__lte=end_time).first()
if cr_20:
cr_20.exception_type = None
if s_time_f > cr_20.create_time:
cr_20.create_time = s_time_f
cr_20.trigger = 'panel'
cr_20.detail = detail
cr_20.save()
else:
cr_20 = ClockRecord()
cr_20.type = 20
cr_20.employee = ep
cr_20.trigger = 'panel'
cr_20.detail = detail
cr_20.create_time = s_time_f
cr_20.save()
ep.is_atwork = False
ep.last_check_time = s_time_f
ep.save()
# 判断是否有异常
# 找到最近的打卡时间
cr_e = ClockRecord.objects.filter(create_time__lt=cr_20.create_time, employee=ep).exclude(id=cr_20.id).order_by('-create_time').first()
if cr_e:
time_d = cr_20.create_time - cr_e.create_time
if cr_e.type == 10:
if time_d < timedelta(hours=7):
cr_20.exception_type = ClockRecord.E_TYPE_LESS
cr_20.save()
elif time_d > timedelta(hours=14):
cr_20.exception_type = ClockRecord.E_TYPE_MORE
cr_20.save()
elif time_d > timedelta(hours=9):
cr_20.exception_type = ClockRecord.E_TYPE_ADD
cr_20.save()
elif cr_e.type == 20:
cr_20.exception_type = ClockRecord.E_TYPE_MISS
cr_20.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)
card_type = 30
trigger = 'door'
if e_type == 1:
card_type = 10
elif e_type == 2:
card_type = 20
else:
trigger = 'panel'
# 此处可触发安全帽事件逻辑
# 先直接创建记录
ClockRecord.objects.get_or_create(employee=ep, create_time=s_time_f, defaults={'type':card_type, 'employee':ep, 'trigger': trigger, 'detail': detail, 'create_time': s_time_f})
if card_type == 10:
# 查找当天的进门记录
cr_10_q = ClockRecord.objects.filter(
type=10, employee=ep, create_time__gte=first_time, create_time__lte=end_time)
first_obj = cr_10_q.order_by('create_time').first()
cr_10_q.exclude(id=first_obj.id).update(type=30)
elif card_type == 20:
# 查找当天的出门记录
cr_20_q = ClockRecord.objects.filter(
type=20, employee=ep, create_time__gte=first_time, create_time__lte=end_time)
last_obj = cr_20_q.order_by('-create_time').first()
cr_20_q.exclude(id=last_obj.id).update(type=30)
# 判断是否有异常
# 找到最近的上下打卡时间不一定是当天的
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:
time_d = last_obj.create_time - cr_e.create_time
if cr_e.type == 10:
if time_d < timedelta(hours=7):
last_obj.exception_type = ClockRecord.E_TYPE_LESS
last_obj.save()
elif time_d > timedelta(hours=14):
last_obj.exception_type = ClockRecord.E_TYPE_MORE
last_obj.save()
elif time_d > timedelta(hours=9):
last_obj.exception_type = ClockRecord.E_TYPE_ADD
last_obj.save()
elif cr_e.type == 20:
last_obj.exception_type = ClockRecord.E_TYPE_MISS
last_obj.save()
# 记录在岗情况
last_obj_t = ClockRecord.objects.filter(employee=ep, type__in=[10,20]).order_by('-create_time').first()
if last_obj_t:
ep.last_check_time = last_obj_t.create_time
if last_obj_t.type == 10:
ep.is_atwork = True
else:
ep.is_atwork = False
ep.save()
# 此处可触发安全帽事件逻辑

View File

@ -1,14 +1,13 @@
from __future__ import absolute_import, unicode_literals
from celery import shared_task
from apps.hrm.models import Employee
from apps.hrm.models import Employee, ClockRecord
from dateutil import tz
from datetime import datetime, timedelta
from apps.third.dahua import dhClient
from apps.third.tapis import dhapis
from apps.hrm.services import HrmService
from django.utils import timezone
from datetime import timedelta
import time
@ -27,14 +26,22 @@ def correct_swip_task(start_time="", end_time=""):
# for i in lgs:
# HrmService.swipe(data=eval(i.data))
# 从大华历史记录校正打卡记录
now = timezone.now()
now = datetime.now()
if start_time == "":
start_time = (now - timedelta(days=1)).strftime("%Y-%m-%d %H:%M:%S")
elif end_time == "":
start_time = (now - timedelta(hours=25)).strftime("%Y-%m-%d %H:%M:%S")
if end_time == "":
end_time = now.strftime("%Y-%m-%d %H:%M:%S")
data0 = {
"pageNum":1,
"pageSize": "20",
"startSwingTime":start_time,
"endSwingTime":end_time,
"openType":"61"
}
_, count = dhClient.request(**dhapis['swipe_list_count'], json=data0)
data = {
"pageNum":1,
"pageSize":"400",
"pageSize": str(count),
"startSwingTime":start_time,
"endSwingTime":end_time,
"openType":"61"
@ -42,6 +49,7 @@ def correct_swip_task(start_time="", end_time=""):
_, res = dhClient.request(**dhapis['swipe_list'], json=data)
for i in res['pageData']:
HrmService.swipe_next(i['channelCode'], i['paperNumber'], i['swingTime'], i['enterOrExit'], i)
# ClockRecord.objects.filter(type=30).delete()
@shared_task
def correct_card_time():

View File

@ -109,7 +109,11 @@ dhapis = {
"method": "get"
},
"swipe_list": {
"url": "/evo-apigw/evo-accesscontrol/1.2.0/card/accessControl/swingCardRecord/bycondition/combined",
"url": "/evo-apigw/evo-accesscontrol/1.0.0/card/accessControl/swingCardRecord/bycondition/combined",
"method": "post"
},
"swipe_list_count": {
"url": "/evo-apigw/evo-accesscontrol/1.0.0/card/accessControl/swingCardRecord/bycondition/combinedCount",
"method": "post"
},
"dev_snap": {