物业 开始结束时间 计算

This commit is contained in:
ljmwkx
2024-12-22 14:44:04 +08:00
parent cf174943ba
commit bf7ea77e44
+559 -297
View File
@@ -5,6 +5,7 @@ from datetime import datetime, timedelta, time
import logging
import traceback
from odoo import api, fields, models, tools, _
from dateutil.relativedelta import relativedelta
from ...yuthon_wechat.utils.common import utils_list_page
_logger = logging.getLogger(__name__)
@@ -91,7 +92,7 @@ class HrAttendanceDetail(models.Model):
return user_list
@staticmethod
def _get_wx_attendance_data(userid_limit):
def _get_wx_attendance_data(userid_limit, now_time, start_time):
"""
获取企业微信的打卡信息
:param wx_work_checkin_api: 企业微信api
@@ -99,8 +100,8 @@ class HrAttendanceDetail(models.Model):
:return:
"""
# 先按照天抓取,时间戳
now_time = datetime.now() + timedelta(hours=8)
start_time = now_time - timedelta(days=30)
# now_time = datetime.now() + timedelta(hours=8)
# start_time = now_time - timedelta(days=30)
start_time_stamp = int(start_time.timestamp())
end_time_stamp = int(now_time.timestamp())
# 整理请求信息
@@ -239,297 +240,297 @@ class HrAttendanceDetail(models.Model):
media_list = self._check_wx_attendance_media(data)
attendance_detail_obj.attendance_detail_image_ids = media_list
except Exception as e:
_logger.error(
'检查保存之前的数据分析出想要的数据失败,异常:{0},数据信息{1},异常详情:{2}'.format(str(e), str(data),
str(traceback.format_exc())))
_logger.error('检查保存之前的数据分析出想要的数据失败,异常:{0},数据信息{1},异常详情:{2}'.format(str(e), str(data),
str(traceback.format_exc())))
userid = data.get("userid", "")
# 区分当天的上班,下班,中午打卡,合并一个
checkin_time_now = checkin_time + timedelta(hours=8) if checkin_time else None
sch_checkin_time_now = sch_checkin_time + timedelta(hours=8) if sch_checkin_time else None
current_data = (sch_checkin_time + timedelta(hours=8)).strftime("%Y-%m-%d") if sch_checkin_time_now else checkin_time_now.strftime("%Y-%m-%d")
# 同步整理当天出勤数据
attendance_obj = self.env['hr.attendance'].search(
[("userid", "=", userid), ("current_data", "=", current_data)], limit=1)
attendance_obj.attendance_type = "wx_work"
checkin_type = data.get("checkin_type", "")
exception_type = data.get("exception_type", "")
if not attendance_obj:
res_user_obj = self.env['res.users'].search([("oauth_uid", "=", userid)], limit=1)
hr_employee_obj = self.env['hr.employee'].sudo().search([("user_id", "=", res_user_obj.id)], limit=1)
if not hr_employee_obj.default_planning_role_id:
attendance_obj = self.env['hr.attendance'].sudo().create({
'employee_id': hr_employee_obj.id,
"userid": userid,
"current_data": current_data,
"attendance_type": "wx_work"
})
else:
current_datetime_start = datetime.combine(datetime.strptime(current_data, '%Y-%m-%d'), datetime.min.time())
current_datetime_end = datetime.combine(datetime.strptime(current_data, '%Y-%m-%d'), datetime.max.time())
planning_slot_id = self.env['planning.slot'].search(
[('resource_id', '=', hr_employee_obj.resource_id.id),
('start_datetime', '>=', current_datetime_start),
('start_datetime', '<=', current_datetime_end)])
if planning_slot_id:
attendance_obj = self.env['hr.attendance'].sudo().create({
'employee_id': hr_employee_obj.id,
"userid": userid,
"current_data": current_data,
"shift_id": planning_slot_id.id,
"attendance_type": "wx_work"
})
if not hr_employee_obj.default_planning_role_id:
# 获取考勤日历的上班下班时间
min_hour_from = self.env['resource.calendar'].search([])[0].attendance_ids[0].hour_from
min_hour = int(min_hour_from)
min_minute = int(min_hour_from * 10 % min_hour_from)
max_hour_to = self.env['resource.calendar'].search([])[-1].attendance_ids[0].hour_to
max_hour = int(max_hour_to)
max_minute = int(max_hour_to * 10 % max_hour_to)
if attendance_obj.is_approval:
# 已经审批修复无需再次进行更新数据
return True
# 赋值企业微信打卡数据
will_datetime_start = checkin_time.replace(hour=min_hour, minute=min_minute)
will_datetime_end = checkin_time.replace(hour=max_hour, minute=max_minute)
if exception_type != "未打卡":
if checkin_time and checkin_type == "上班打卡" and exception_type != "未打卡" and not attendance_obj.check_in:
attendance_obj.sudo().write({
"sch_check_in_time": sch_checkin_time,
"check_in": checkin_time,
"is_late_card": checkin_time > will_datetime_start,
})
elif checkin_time and checkin_type == "下班打卡" and exception_type != "未打卡" and not attendance_obj.check_out:
attendance_obj.sudo().write({
"sch_check_out_time": sch_checkin_time,
"check_out": checkin_time,
"is_early_card": will_datetime_end > checkin_time,
})
elif attendance_obj.check_in and checkin_time and checkin_type == "上班打卡" and exception_type != "未打卡" and checkin_time < attendance_obj.check_in:
attendance_obj.sudo().write({
"sch_check_in_time": sch_checkin_time,
"check_in": checkin_time,
"is_late_card": checkin_time > will_datetime_start,
})
elif attendance_obj.check_out and checkin_time and checkin_type == "下班打卡" and exception_type != "未打卡" and checkin_time > attendance_obj.check_out:
attendance_obj.sudo().write({
"sch_check_out_time": sch_checkin_time,
"check_out": checkin_time,
"is_early_card": will_datetime_end > checkin_time,
})
elif checkin_time and exception_type != "未打卡" and not attendance_obj.check_in and not attendance_obj.check_out:
attendance_obj.sudo().write({
"sch_check_in_time": sch_checkin_time,
"check_in": checkin_time,
"is_late_card": checkin_time > will_datetime_start,
})
elif checkin_time and exception_type != "未打卡" and attendance_obj.check_in and not attendance_obj.check_out:
attendance_obj.sudo().write({
"sch_check_out_time": sch_checkin_time,
"check_out": checkin_time,
"is_early_card": will_datetime_end > checkin_time,
})
elif attendance_obj.is_early_card or attendance_obj.is_late_card:
attendance_obj.sudo().write({"is_abnormal": True})
else:
attendance_obj.sudo().write({"is_no_card": True, "is_abnormal": True})
else:
current_data = datetime.strptime(current_data, '%Y-%m-%d')
# 获取当天的起始和结束时间
current_datetime_start = datetime.combine(current_data, datetime.min.time())
current_datetime_end = datetime.combine(current_data, datetime.max.time())
# 获取本人当天的班次
planning_id = self.env['planning.slot'].search([('resource_id', '=', hr_employee_obj.resource_id.id),
('start_datetime', '>=', current_datetime_start),
('start_datetime', '<=', current_datetime_end)])
if planning_id:
planning_start_time = planning_id.start_datetime + timedelta(hours=8)
planning_end_time = planning_id.end_datetime + timedelta(hours=8)
if planning_id.role_id.name == '保安部':
# {'白班': [['8:30', '9.30'], ['8:30', '9.30']]}white
# {'中班': [['8:30', '9.30'], ['8:30', '9.30']]}mid
# {'夜班': [['8:30', '9.30'], ['8:30', '9.30']]}night
# 白班上班区间
start_time = datetime.combine(current_data, time(6, 0)) + timedelta(hours=8)
end_time = datetime.combine(current_data, time(9, 0)) + timedelta(hours=8)
# 白班下班区间
start_time1 = datetime.combine(current_data, time(2, 0)) + timedelta(hours=8)
end_time1 = datetime.combine(current_data, time(4, 0)) + timedelta(hours=8)
# 中班上班区间
start_time2 = datetime.combine(current_data, time(14, 0)) + timedelta(hours=8)
end_time2 = datetime.combine(current_data, time(17, 0)) + timedelta(hours=8)
# 中班下班区间
start_time3 = datetime.combine(current_data, time(22, 0)) + timedelta(hours=8)
end_time3 = datetime.combine(current_data, time(1, 0)) + timedelta(hours=8)
# 夜班上班区间
start_time4 = datetime.combine(current_data, time(22, 0)) + timedelta(hours=8)
end_time4 = datetime.combine(current_data, time(1, 0)) + timedelta(hours=8)
# 夜班下班区间
start_time5 = datetime.combine(current_data, time(6, 0)) + timedelta(hours=8)
end_time5 = datetime.combine(current_data, time(9, 0)) + timedelta(hours=8)
if checkin_time:
planning_name = planning_id.template_id.planning_name
if start_time <= checkin_time <= end_time and planning_name == '白班':
attendance_obj.sudo().write({
"check_in": checkin_time,
"is_late_card": checkin_time > planning_start_time
})
elif start_time1 <= checkin_time <= end_time1 and planning_name == '白班':
attendance_obj.sudo().write({
"check_out": checkin_time,
"is_early_card": planning_end_time > checkin_time,
})
elif start_time2 <= checkin_time <= end_time2 and planning_name == '中班':
attendance_obj.sudo().write({
"check_in": checkin_time,
"is_late_card": checkin_time > planning_start_time
})
elif start_time3 <= checkin_time <= end_time3 and planning_name == '中班':
attendance_obj.sudo().write({
"check_out": checkin_time,
"is_early_card": planning_end_time > checkin_time,
})
elif start_time4 <= checkin_time <= end_time4 and planning_name == '夜班':
attendance_obj.sudo().write({
"check_in": checkin_time,
"is_late_card": checkin_time > planning_start_time
})
elif start_time5 <= checkin_time <= end_time5 and planning_name == '夜班':
attendance_obj.sudo().write({
"check_out": checkin_time,
"is_early_card": planning_end_time > checkin_time,
})
elif attendance_obj.is_early_card or attendance_obj.is_late_card:
attendance_obj.sudo().write({"is_abnormal": True})
else:
attendance_obj.sudo().write({"is_no_card": True, "is_abnormal": True})
# elif planning_id.role_id.name == '工程部':
# # 白班和白值上班区间
# start_time = datetime.combine(current_data, time(7, 0)) + timedelta(
# hours=8)
# end_time = datetime.combine(current_data, time(10, 0)) + timedelta(
# hours=8)
# # 白班和白值下班区间
# start_time1 = datetime.combine(current_data,
# time(16, 0)) + timedelta(hours=8)
# end_time1 = datetime.combine(current_data, time(19, 0)) + timedelta(
# hours=8)
# # 白值值班打卡区间
# start_time2 = datetime.combine(current_data,
# time(11, 30)) + timedelta(hours=8)
# end_time2 = datetime.combine(current_data, time(13, 30)) + timedelta(
# hours=8)
# # 中夜上班区间 中夜下班区间跟白班上班区间一样
# start_time3 = datetime.combine(current_data,
# time(13, 0)) + timedelta(hours=8)
# end_time3 = datetime.combine(current_data, time(16, 0)) + timedelta(
# hours=8)
# # 中夜值班打卡区间
# start_time4 = datetime.combine(current_data,
# time(20, 0)) + timedelta(hours=8)
# end_time4 = datetime.combine(current_data, time(23, 0)) + timedelta(
# hours=8)
# if planning_id:
# if checkin_time:
# if start_time <= checkin_time <= end_time and not attendance_obj.check_in and (
# planning_name in ['白班', '白值']):
# attendance_obj.sudo().write({
# "check_in": checkin_time,
# "is_late_card": checkin_time > planning_start_time
# })
# elif end_time1 <= checkin_time <= start_time1 and not attendance_obj.check_out and (
# planning_name in ['白班', '白值']):
# attendance_obj.sudo().write({
# "check_out": checkin_time,
# "is_early_card": planning_end_time > checkin_time,
# })
# elif start_time3 <= checkin_time <= end_time3 and not attendance_obj.check_in and planning_name == '中夜':
# attendance_obj.sudo().write({
# "check_in": checkin_time,
# "is_late_card": checkin_time > planning_start_time
# })
# elif start_time <= checkin_time <= end_time and not attendance_obj.check_out and planning_name == '中夜':
# attendance_obj.sudo().write({
# "check_out": checkin_time,
# "is_early_card": checkin_time > planning_start_time
# })
# elif planning_id.template_id.planning == '白值' and start_time2 <= checkin_time <= end_time2:
# attendance_obj.sudo().write({
# "sch_check_out_time": sch_checkin_time,
# "noon_duty": checkin_time,
# })
# elif planning_id.template_id.planning == '中夜' and start_time4 <= checkin_time <= end_time4:
# attendance_obj.sudo().write({
# "sch_check_out_time": sch_checkin_time,
# "night_duty": checkin_time,
# })
# # 异常情况处理,移到所有打卡逻辑之后
# if (attendance_obj.is_early_card or attendance_obj.is_late_card or
# (planning_id.template_id.planning == '白值' and not attendance_obj.noon_duty) or
# (planning_id.template_id.planning == '中夜' and not attendance_obj.night_duty)):
# attendance_obj.sudo().write({"is_abnormal": True})
# else:
# attendance_obj.sudo().write({"is_no_card": True, "is_abnormal": True})
# elif planning_id.role_id.name == '联安粮储':
# # 白班上班区间
# start_time = datetime.combine(current_data, time(7, 0)) + timedelta(
# hours=8)
# end_time = datetime.combine(current_data, time(10, 0)) + timedelta(
# hours=8)
# # 白班下班区间
# start_time1 = datetime.combine(current_data,
# time(15, 0)) + timedelta(hours=8)
# end_time1 = datetime.combine(current_data, time(18, 0)) + timedelta(
# hours=8)
# # 白值上班
# start_time2 = datetime.combine(current_data, time(8, 0)) + timedelta(
# hours=8)
# end_time2 = datetime.combine(current_data, time(10, 0)) + timedelta(
# hours=8)
# # 白值下班
# start_time4 = datetime.combine(current_data, time(4, 0)) + timedelta(
# hours=8)
# end_time4 = datetime.combine(current_data, time(7, 0)) + timedelta(
# hours=8)
# # 白值打卡区间、
# start_time3 = datetime.combine(current_data,
# time(11, 30)) + timedelta(hours=8)
# end_time3 = datetime.combine(current_data, time(13, 30)) + timedelta(
# hours=8)
# if planning_id:
# if start_time <= checkin_time <= end_time and not attendance_obj.check_in and planning_name == '白班':
# attendance_obj.sudo().write({
# "check_in": checkin_time,
# "is_late_card": checkin_time > planning_start_time
# })
# elif start_time1 <= checkin_time <= end_time1 and not attendance_obj.check_out and planning_name == '白班':
# attendance_obj.sudo().write({
# "check_out": checkin_time,
# "is_early_card": planning_end_time > checkin_time,
# })
# elif start_time2 <= checkin_time <= end_time2 and not attendance_obj.check_in and planning_name == '白值':
# attendance_obj.sudo().write({
# "check_in": checkin_time,
# "is_late_card": checkin_time > planning_start_time,
# })
# elif start_time4 <= checkin_time <= end_time4 and not attendance_obj.check_out and planning_name == '白值':
# attendance_obj.sudo().write({
# "check_out": checkin_time,
# "is_early_card": planning_end_time > checkin_time,
# })
# elif start_time3 <= checkin_time <= end_time3 and planning_name == '白值':
# attendance_obj.sudo().write({
# "noon_duty": checkin_time,
# })
# if (attendance_obj.is_early_card or attendance_obj.is_late_card or
# (planning_id.template_id.planning == '白值班' and not attendance_obj.noon_duty)):
# attendance_obj.sudo().write({"is_abnormal": True})
# else:
# attendance_obj.sudo().write({"is_no_card": True, "is_abnormal": True})
# 进行关联
attendance_detail_obj.hr_attendance_id = attendance_obj.id
return True
# def _check_wx_attendance_data(self, data, checkin_time, sch_checkin_time):
# userid = data.get("userid", "")
# # 区分当天的上班,下班,中午打卡,合并一个
# checkin_time_now = checkin_time + timedelta(hours=8) if checkin_time else None
# sch_checkin_time_now = sch_checkin_time + timedelta(hours=8) if sch_checkin_time else None
# current_data = (sch_checkin_time + timedelta(hours=8)).strftime("%Y-%m-%d") if sch_checkin_time_now else checkin_time_now.strftime("%Y-%m-%d")
# # 同步整理当天出勤数据
# attendance_obj = self.env['hr.attendance'].search(
# [("userid", "=", userid), ("current_data", "=", current_data)], limit=1)
# attendance_obj.attendance_type = "wx_work"
# checkin_type = data.get("checkin_type", "")
# exception_type = data.get("exception_type", "")
# if not attendance_obj:
# res_user_obj = self.env['res.users'].search([("oauth_uid", "=", userid)], limit=1)
# hr_employee_obj = self.env['hr.employee'].sudo().search([("user_id", "=", res_user_obj.id)], limit=1)
# if not hr_employee_obj.default_planning_role_id:
# attendance_obj = self.env['hr.attendance'].sudo().create({
# 'employee_id': hr_employee_obj.id,
# "userid": userid,
# "current_data": current_data,
# "attendance_type": "wx_work"
# })
# else:
# current_datetime_start = datetime.combine(datetime.strptime(current_data, '%Y-%m-%d'), datetime.min.time())
# current_datetime_end = datetime.combine(datetime.strptime(current_data, '%Y-%m-%d'), datetime.max.time())
# planning_slot_id = self.env['planning.slot'].search(
# [('resource_id', '=', hr_employee_obj.resource_id.id),
# ('start_datetime', '>=', current_datetime_start),
# ('start_datetime', '<=', current_datetime_end)])
# if planning_slot_id:
# attendance_obj = self.env['hr.attendance'].sudo().create({
# 'employee_id': hr_employee_obj.id,
# "userid": userid,
# "current_data": current_data,
# "shift_id": planning_slot_id.id,
# "attendance_type": "wx_work"
# })
# if not hr_employee_obj.default_planning_role_id:
# # 获取考勤日历的上班下班时间
# min_hour_from = self.env['resource.calendar'].search([])[0].attendance_ids[0].hour_from
# min_hour = int(min_hour_from)
# min_minute = int(min_hour_from * 10 % min_hour_from)
# max_hour_to = self.env['resource.calendar'].search([])[-1].attendance_ids[0].hour_to
# max_hour = int(max_hour_to)
# max_minute = int(max_hour_to * 10 % max_hour_to)
# if attendance_obj.is_approval:
# # 已经审批修复无需再次进行更新数据
# return True
# # 赋值企业微信打卡数据
# will_datetime_start = checkin_time.replace(hour=min_hour, minute=min_minute)
# will_datetime_end = checkin_time.replace(hour=max_hour, minute=max_minute)
# if exception_type != "未打卡":
# if checkin_time and checkin_type == "上班打卡" and exception_type != "未打卡" and not attendance_obj.check_in:
# attendance_obj.sudo().write({
# "sch_check_in_time": sch_checkin_time,
# "check_in": checkin_time,
# "is_late_card": checkin_time > will_datetime_start,
# })
# elif checkin_time and checkin_type == "下班打卡" and exception_type != "未打卡" and not attendance_obj.check_out:
# attendance_obj.sudo().write({
# "sch_check_out_time": sch_checkin_time,
# "check_out": checkin_time,
# "is_early_card": will_datetime_end > checkin_time,
# })
# elif attendance_obj.check_in and checkin_time and checkin_type == "上班打卡" and exception_type != "未打卡" and checkin_time < attendance_obj.check_in:
# attendance_obj.sudo().write({
# "sch_check_in_time": sch_checkin_time,
# "check_in": checkin_time,
# "is_late_card": checkin_time > will_datetime_start,
# })
# elif attendance_obj.check_out and checkin_time and checkin_type == "下班打卡" and exception_type != "未打卡" and checkin_time > attendance_obj.check_out:
# attendance_obj.sudo().write({
# "sch_check_out_time": sch_checkin_time,
# "check_out": checkin_time,
# "is_early_card": will_datetime_end > checkin_time,
# })
# elif checkin_time and exception_type != "未打卡" and not attendance_obj.check_in and not attendance_obj.check_out:
# attendance_obj.sudo().write({
# "sch_check_in_time": sch_checkin_time,
# "check_in": checkin_time,
# "is_late_card": checkin_time > will_datetime_start,
# })
# elif checkin_time and exception_type != "未打卡" and attendance_obj.check_in and not attendance_obj.check_out:
# attendance_obj.sudo().write({
# "sch_check_out_time": sch_checkin_time,
# "check_out": checkin_time,
# "is_early_card": will_datetime_end > checkin_time,
# })
# elif attendance_obj.is_early_card or attendance_obj.is_late_card:
# attendance_obj.sudo().write({"is_abnormal": True})
# else:
# attendance_obj.sudo().write({"is_no_card": True, "is_abnormal": True})
# else:
# current_data = datetime.strptime(current_data, '%Y-%m-%d')
# # 获取当天的起始和结束时间
# current_datetime_start = datetime.combine(current_data, datetime.min.time())
# current_datetime_end = datetime.combine(current_data, datetime.max.time())
# # 获取本人当天的班次
# planning_id = self.env['planning.slot'].search([('resource_id', '=', hr_employee_obj.resource_id.id),
# ('start_datetime', '>=', current_datetime_start),
# ('start_datetime', '<=', current_datetime_end)])
# if planning_id:
# planning_start_time = planning_id.start_datetime + timedelta(hours=8)
# planning_end_time = planning_id.end_datetime + timedelta(hours=8)
# if planning_id.role_id.name == '保安部':
# # {'白班': [['8:30', '9.30'], ['8:30', '9.30']]}white
# # {'中班': [['8:30', '9.30'], ['8:30', '9.30']]}mid
# # {'夜班': [['8:30', '9.30'], ['8:30', '9.30']]}night
# # 白班上班区间
# start_time = datetime.combine(current_data, time(6, 0)) + timedelta(hours=8)
# end_time = datetime.combine(current_data, time(9, 0)) + timedelta(hours=8)
# # 白班下班区间
# start_time1 = datetime.combine(current_data, time(2, 0)) + timedelta(hours=8)
# end_time1 = datetime.combine(current_data, time(4, 0)) + timedelta(hours=8)
# # 中班上班区间
# start_time2 = datetime.combine(current_data, time(14, 0)) + timedelta(hours=8)
# end_time2 = datetime.combine(current_data, time(17, 0)) + timedelta(hours=8)
# # 中班下班区间
# start_time3 = datetime.combine(current_data, time(22, 0)) + timedelta(hours=8)
# end_time3 = datetime.combine(current_data, time(1, 0)) + timedelta(hours=8)
# # 夜班上班区间
# start_time4 = datetime.combine(current_data, time(22, 0)) + timedelta(hours=8)
# end_time4 = datetime.combine(current_data, time(1, 0)) + timedelta(hours=8)
# # 夜班下班区间
# start_time5 = datetime.combine(current_data, time(6, 0)) + timedelta(hours=8)
# end_time5 = datetime.combine(current_data, time(9, 0)) + timedelta(hours=8)
# if checkin_time:
# planning_name = planning_id.template_id.planning_name
# if start_time <= checkin_time <= end_time and planning_name == '白班':
# attendance_obj.sudo().write({
# "check_in": checkin_time,
# "is_late_card": checkin_time > planning_start_time
# })
# elif start_time1 <= checkin_time <= end_time1 and planning_name == '白班':
# attendance_obj.sudo().write({
# "check_out": checkin_time,
# "is_early_card": planning_end_time > checkin_time,
# })
# elif start_time2 <= checkin_time <= end_time2 and planning_name == '中班':
# attendance_obj.sudo().write({
# "check_in": checkin_time,
# "is_late_card": checkin_time > planning_start_time
# })
# elif start_time3 <= checkin_time <= end_time3 and planning_name == '中班':
# attendance_obj.sudo().write({
# "check_out": checkin_time,
# "is_early_card": planning_end_time > checkin_time,
# })
# elif start_time4 <= checkin_time <= end_time4 and planning_name == '夜班':
# attendance_obj.sudo().write({
# "check_in": checkin_time,
# "is_late_card": checkin_time > planning_start_time
# })
# elif start_time5 <= checkin_time <= end_time5 and planning_name == '夜班':
# attendance_obj.sudo().write({
# "check_out": checkin_time,
# "is_early_card": planning_end_time > checkin_time,
# })
# elif attendance_obj.is_early_card or attendance_obj.is_late_card:
# attendance_obj.sudo().write({"is_abnormal": True})
# else:
# attendance_obj.sudo().write({"is_no_card": True, "is_abnormal": True})
# # elif planning_id.role_id.name == '工程部':
# # # 白班和白值上班区间
# # start_time = datetime.combine(current_data, time(7, 0)) + timedelta(
# # hours=8)
# # end_time = datetime.combine(current_data, time(10, 0)) + timedelta(
# # hours=8)
# # # 白班和白值下班区间
# # start_time1 = datetime.combine(current_data,
# # time(16, 0)) + timedelta(hours=8)
# # end_time1 = datetime.combine(current_data, time(19, 0)) + timedelta(
# # hours=8)
# # # 白值值班打卡区间
# # start_time2 = datetime.combine(current_data,
# # time(11, 30)) + timedelta(hours=8)
# # end_time2 = datetime.combine(current_data, time(13, 30)) + timedelta(
# # hours=8)
# # # 中夜上班区间 中夜下班区间跟白班上班区间一样
# # start_time3 = datetime.combine(current_data,
# # time(13, 0)) + timedelta(hours=8)
# # end_time3 = datetime.combine(current_data, time(16, 0)) + timedelta(
# # hours=8)
# # # 中夜值班打卡区间
# # start_time4 = datetime.combine(current_data,
# # time(20, 0)) + timedelta(hours=8)
# # end_time4 = datetime.combine(current_data, time(23, 0)) + timedelta(
# # hours=8)
# # if planning_id:
# # if checkin_time:
# # if start_time <= checkin_time <= end_time and not attendance_obj.check_in and (
# # planning_name in ['白班', '白值']):
# # attendance_obj.sudo().write({
# # "check_in": checkin_time,
# # "is_late_card": checkin_time > planning_start_time
# # })
# # elif end_time1 <= checkin_time <= start_time1 and not attendance_obj.check_out and (
# # planning_name in ['白班', '白值']):
# # attendance_obj.sudo().write({
# # "check_out": checkin_time,
# # "is_early_card": planning_end_time > checkin_time,
# # })
# # elif start_time3 <= checkin_time <= end_time3 and not attendance_obj.check_in and planning_name == '中夜':
# # attendance_obj.sudo().write({
# # "check_in": checkin_time,
# # "is_late_card": checkin_time > planning_start_time
# # })
# # elif start_time <= checkin_time <= end_time and not attendance_obj.check_out and planning_name == '中夜':
# # attendance_obj.sudo().write({
# # "check_out": checkin_time,
# # "is_early_card": checkin_time > planning_start_time
# # })
# # elif planning_id.template_id.planning == '白值' and start_time2 <= checkin_time <= end_time2:
# # attendance_obj.sudo().write({
# # "sch_check_out_time": sch_checkin_time,
# # "noon_duty": checkin_time,
# # })
# # elif planning_id.template_id.planning == '中夜' and start_time4 <= checkin_time <= end_time4:
# # attendance_obj.sudo().write({
# # "sch_check_out_time": sch_checkin_time,
# # "night_duty": checkin_time,
# # })
# # # 异常情况处理,移到所有打卡逻辑之后
# # if (attendance_obj.is_early_card or attendance_obj.is_late_card or
# # (planning_id.template_id.planning == '白值' and not attendance_obj.noon_duty) or
# # (planning_id.template_id.planning == '中夜' and not attendance_obj.night_duty)):
# # attendance_obj.sudo().write({"is_abnormal": True})
# # else:
# # attendance_obj.sudo().write({"is_no_card": True, "is_abnormal": True})
# # elif planning_id.role_id.name == '联安粮储':
# # # 白班上班区间
# # start_time = datetime.combine(current_data, time(7, 0)) + timedelta(
# # hours=8)
# # end_time = datetime.combine(current_data, time(10, 0)) + timedelta(
# # hours=8)
# # # 白班下班区间
# # start_time1 = datetime.combine(current_data,
# # time(15, 0)) + timedelta(hours=8)
# # end_time1 = datetime.combine(current_data, time(18, 0)) + timedelta(
# # hours=8)
# # # 白值上班
# # start_time2 = datetime.combine(current_data, time(8, 0)) + timedelta(
# # hours=8)
# # end_time2 = datetime.combine(current_data, time(10, 0)) + timedelta(
# # hours=8)
# # # 白值下班
# # start_time4 = datetime.combine(current_data, time(4, 0)) + timedelta(
# # hours=8)
# # end_time4 = datetime.combine(current_data, time(7, 0)) + timedelta(
# # hours=8)
# # # 白值打卡区间、
# # start_time3 = datetime.combine(current_data,
# # time(11, 30)) + timedelta(hours=8)
# # end_time3 = datetime.combine(current_data, time(13, 30)) + timedelta(
# # hours=8)
# # if planning_id:
# # if start_time <= checkin_time <= end_time and not attendance_obj.check_in and planning_name == '白班':
# # attendance_obj.sudo().write({
# # "check_in": checkin_time,
# # "is_late_card": checkin_time > planning_start_time
# # })
# # elif start_time1 <= checkin_time <= end_time1 and not attendance_obj.check_out and planning_name == '白班':
# # attendance_obj.sudo().write({
# # "check_out": checkin_time,
# # "is_early_card": planning_end_time > checkin_time,
# # })
# # elif start_time2 <= checkin_time <= end_time2 and not attendance_obj.check_in and planning_name == '白值':
# # attendance_obj.sudo().write({
# # "check_in": checkin_time,
# # "is_late_card": checkin_time > planning_start_time,
# # })
# # elif start_time4 <= checkin_time <= end_time4 and not attendance_obj.check_out and planning_name == '白值':
# # attendance_obj.sudo().write({
# # "check_out": checkin_time,
# # "is_early_card": planning_end_time > checkin_time,
# # })
# # elif start_time3 <= checkin_time <= end_time3 and planning_name == '白值':
# # attendance_obj.sudo().write({
# # "noon_duty": checkin_time,
# # })
# # if (attendance_obj.is_early_card or attendance_obj.is_late_card or
# # (planning_id.template_id.planning == '白值班' and not attendance_obj.noon_duty)):
# # attendance_obj.sudo().write({"is_abnormal": True})
# # else:
# # attendance_obj.sudo().write({"is_no_card": True, "is_abnormal": True})
# # 进行关联
# attendance_detail_obj.hr_attendance_id = attendance_obj.id
# return True
def get_hr_attendance_time(self):
"""
@@ -538,11 +539,14 @@ class HrAttendanceDetail(models.Model):
"""
# 从用户列表里获取企业微信的用户
user_list = self._get_wx_attendance_user_list()
now_time = datetime.now() + timedelta(hours=8)
start_time = now_time - timedelta(days=30)
# 企业微信获取打卡数据,要求用户分组100,分批获取打卡记录
for userid_limit in utils_list_page(user_list, 100):
# 获取企业微信的打卡信息
try:
attendance_data = self._get_wx_attendance_data(userid_limit)
attendance_data = self._get_wx_attendance_data(userid_limit, now_time, start_time)
attendance_result, response = self.sudo().env["wecom.apps"].sync_checkin_data(attendance_data)
except Exception as e:
_logger.error(
@@ -573,7 +577,265 @@ class HrAttendanceDetail(models.Model):
self._save_wx_attendance_detail_data(data, checkin_time, sch_checkin_time)
except Exception as e:
_logger.error(
'保存相关的企业微信的原始打卡信息失败,异常:{0},数据信息{1},异常详情:{2}'.format(str(e),
str(data),
str(traceback.format_exc())))
'保存相关的企业微信的原始打卡信息失败,异常:{0},数据信息{1},异常详情:{2}'.format(str(e), str(data), str(traceback.format_exc())))
# 将取回来的数据进行组织整理写入到考勤表中
user_obj = self.env['res.users'].search([])
# 暂时先用for循环,如果后期加大频率,需改成并发
for user in user_obj:
# 判断是否是微信用户
if user.oauth_uid:
# 查询当前用户区间内的所有打卡数据没有的创建
for current_date in self.divide_time_range_fixed(start_time, now_time):
# 写入打卡数据
self._do_save_wx_attendance_data(user, current_date)
return True
def _do_save_wx_attendance_data(self, user, current_date):
"""
开始 整理考勤数据
:param user:
:param current_date:
:return:
"""
# 同步整理当天出勤数据
attendance_obj = self.env['hr.attendance'].search([("userid", "=", user.id), ("current_data", "=", current_date)], limit=1)
hr_employee_obj = self.env['hr.employee'].sudo().search([("user_id", "=", user.id)], limit=1)
current_datetime_start = datetime.combine(datetime.strptime(current_date, '%Y-%m-%d'), datetime.min.time())
current_datetime_end = datetime.combine(datetime.strptime(current_date, '%Y-%m-%d'), datetime.max.time())
if not attendance_obj:
# 判断是否是 普通打卡
if not hr_employee_obj.default_planning_role_id:
attendance_obj = self.env['hr.attendance'].sudo().create({
'employee_id': hr_employee_obj.id,
"userid": user.id,
"current_data": current_date,
"attendance_type": "wx_work"
})
self._do_not_planning_role(user, current_date, attendance_obj)
else:
planning_slot_id = self.env['planning.slot'].search(
[('resource_id', '=', hr_employee_obj.resource_id.id),
('start_datetime', '>=', current_datetime_start),
('start_datetime', '<=', current_datetime_end)])
# 是否排班
if planning_slot_id:
attendance_obj = self.env['hr.attendance'].sudo().create({
'employee_id': hr_employee_obj.id,
"userid": user.id,
"current_data": current_date,
"shift_id": planning_slot_id.id,
"attendance_type": "wx_work"
})
self._do_planning_role(user, current_date, attendance_obj)
else:
# 没有排班
return True
# 查询出当前抓取微信的当前时间的所有数据
attendance_detail_obj = self.env['hr.attendance.detail'].sudo().search(
[("userid", "=", user.id),
("checkin_time", ">=", current_datetime_start),
("checkin_time", "<=", current_datetime_end)])
# 关联 打卡详情
attendance_detail_obj.hr_attendance_id = attendance_obj.id
return True
def _do_not_planning_role(self, user, current_date, attendance_obj):
"""
正常班次的 上班下班判断
:param user: 用户集合
:param current_date: 循环判断的时间
:param attendance_obj: 判断的时刻的考勤集合
:return:
"""
current_datetime_start = datetime.combine(datetime.strptime(current_date, '%Y-%m-%d'), datetime.min.time())
current_datetime_end = datetime.combine(datetime.strptime(current_date, '%Y-%m-%d'), datetime.max.time())
# 获取考勤日历的上班下班时间
min_hour_from = self.env['resource.calendar'].search([])[0].attendance_ids[0].hour_from
min_hour = int(min_hour_from)
min_minute = int(min_hour_from * 10 % min_hour_from)
max_hour_to = self.env['resource.calendar'].search([])[-1].attendance_ids[0].hour_to
max_hour = int(max_hour_to)
max_minute = int(max_hour_to * 10 % max_hour_to)
if attendance_obj.is_approval:
# 已经审批修复无需再次进行更新数据
return True
# 判断打卡情况排除未打卡情况
attendance_detail_obj = self.env['hr.attendance.detail'].sudo().search(
[("exception_type", "!=", "未打卡"),
("userid", "=", user.id),
("checkin_time", ">=", current_datetime_start),
("checkin_time", "<=", current_datetime_end)])
# 没有打卡记录说明缺卡
if len(attendance_detail_obj) <= 0:
attendance_obj.sudo().write({"is_no_card": True, "is_abnormal": True})
return True
# 打了一次卡记录说明缺卡
elif len(attendance_detail_obj) == 1:
checkin_time = attendance_detail_obj.checkin_time
will_datetime_start = checkin_time.replace(hour=min_hour, minute=min_minute)
will_datetime_end = checkin_time.replace(hour=max_hour, minute=max_minute)
if attendance_detail_obj.checkin_type == "上班打卡":
attendance_obj.sudo().write({
"sch_check_in_time": will_datetime_start,
"check_in": checkin_time,
"is_late_card": checkin_time > will_datetime_start,
"is_no_card": True,
})
elif attendance_detail_obj.checkin_type == "下班打卡":
attendance_obj.sudo().write({
"sch_check_out_time": will_datetime_end,
"check_out": checkin_time,
"is_early_card": will_datetime_end > checkin_time,
"is_no_card": True,
})
else:
# 如果是 打卡时间 早于 上班时间 判定为 上班打卡 缺下班卡
if will_datetime_start > checkin_time:
attendance_obj.sudo().write({
"sch_check_in_time": will_datetime_start,
"check_in": checkin_time,
"is_late_card": checkin_time > will_datetime_start,
"is_no_card": True,
})
# 如果是 打卡时间 晚于 下班时间 判定为 下班打卡 缺上班卡
elif will_datetime_end < checkin_time:
attendance_obj.sudo().write({
"sch_check_out_time": will_datetime_end,
"check_out": checkin_time,
"is_early_card": will_datetime_end > checkin_time,
"is_no_card": True,
})
# 既不是上班也不是下班,默认为上班打卡
else:
attendance_obj.sudo().write({
"sch_check_in_time": will_datetime_start,
"check_in": checkin_time,
"is_late_card": checkin_time > will_datetime_start,
"is_no_card": True,
})
return True
else:
# 多次打卡时间的集合
checkin_time_list = [obj.checkin_time for obj in attendance_detail_obj]
# 最早 和 最晚 时间
min_time = min(checkin_time_list)
max_time = max(checkin_time_list)
# 赋值企业微信打卡数据
will_datetime_start = min_time.replace(hour=min_hour, minute=min_minute)
will_datetime_end = max_time.replace(hour=max_hour, minute=max_minute)
# 查询最早时间上班时间 查询最晚下班时间
attendance_obj.sudo().write({
"sch_check_in_time": will_datetime_start,
"check_in": min_time,
"is_late_card": min_time > will_datetime_start,
"sch_check_out_time": will_datetime_end,
"check_out": max_time,
"is_early_card": will_datetime_end > max_time,
})
return True
def _do_planning_role(self, user, current_date, attendance_obj):
"""
带有计划的班次判断
:param user: 用户集合
:param current_date: 循环判断的时间
:param attendance_obj: 判断的时刻的考勤集合
:return:
"""
current_data = datetime.strptime(current_date, '%Y-%m-%d')
# 获取当天的起始和结束时间
current_datetime_start = datetime.combine(current_data, datetime.min.time())
current_datetime_end = datetime.combine(current_data, datetime.max.time())
# 获取本人当天的班次
hr_employee_obj = self.env['hr.employee'].sudo().search([("user_id", "=", user.id)], limit=1)
planning_id = self.env['planning.slot'].search(
[('resource_id', '=', hr_employee_obj.resource_id.id),
('start_datetime', '>=', current_datetime_start),
('start_datetime', '<=', current_datetime_end)])
if planning_id:
planning_start_time = planning_id.start_datetime + timedelta(hours=8)
planning_end_time = planning_id.end_datetime + timedelta(hours=8)
# 判断打卡情况排除未打卡情况
attendance_detail_obj = self.env['hr.attendance.detail'].sudo().search(
[("exception_type", "!=", "未打卡"),
("userid", "=", user.id),
("checkin_time", ">=", planning_start_time),
("checkin_time", "<=", planning_end_time)])
if planning_id.role_id.name == '保安部':
# {'白班': [['8:30', '9.30'], ['8:30', '9.30']]}white
# {'中班': [['8:30', '9.30'], ['8:30', '9.30']]}mid
# {'夜班': [['8:30', '9.30'], ['8:30', '9.30']]}night
# 白班上班区间
start_time = datetime.combine(current_data, time(6, 0)) + timedelta(hours=8)
end_time = datetime.combine(current_data, time(9, 0)) + timedelta(hours=8)
# 白班下班区间
start_time1 = datetime.combine(current_data, time(2, 0)) + timedelta(hours=8)
end_time1 = datetime.combine(current_data, time(4, 0)) + timedelta(hours=8)
# 中班上班区间
start_time2 = datetime.combine(current_data, time(14, 0)) + timedelta(hours=8)
end_time2 = datetime.combine(current_data, time(17, 0)) + timedelta(hours=8)
# 中班下班区间
start_time3 = datetime.combine(current_data, time(22, 0)) + timedelta(hours=8)
end_time3 = datetime.combine(current_data, time(1, 0)) + timedelta(hours=8)
# 夜班上班区间
start_time4 = datetime.combine(current_data, time(22, 0)) + timedelta(hours=8)
end_time4 = datetime.combine(current_data, time(1, 0)) + timedelta(hours=8)
# 夜班下班区间
start_time5 = datetime.combine(current_data, time(6, 0)) + timedelta(hours=8)
end_time5 = datetime.combine(current_data, time(9, 0)) + timedelta(hours=8)
# if checkin_time:
# planning_name = planning_id.template_id.planning_name
# if start_time <= checkin_time <= end_time and planning_name == '白班':
# attendance_obj.sudo().write({
# "check_in": checkin_time,
# "is_late_card": checkin_time > planning_start_time
# })
# elif start_time1 <= checkin_time <= end_time1 and planning_name == '白班':
# attendance_obj.sudo().write({
# "check_out": checkin_time,
# "is_early_card": planning_end_time > checkin_time,
# })
# elif start_time2 <= checkin_time <= end_time2 and planning_name == '中班':
# attendance_obj.sudo().write({
# "check_in": checkin_time,
# "is_late_card": checkin_time > planning_start_time
# })
# elif start_time3 <= checkin_time <= end_time3 and planning_name == '中班':
# attendance_obj.sudo().write({
# "check_out": checkin_time,
# "is_early_card": planning_end_time > checkin_time,
# })
# elif start_time4 <= checkin_time <= end_time4 and planning_name == '夜班':
# attendance_obj.sudo().write({
# "check_in": checkin_time,
# "is_late_card": checkin_time > planning_start_time
# })
# elif start_time5 <= checkin_time <= end_time5 and planning_name == '夜班':
# attendance_obj.sudo().write({
# "check_out": checkin_time,
# "is_early_card": planning_end_time > checkin_time,
# })
# elif attendance_obj.is_early_card or attendance_obj.is_late_card:
# attendance_obj.sudo().write({"is_abnormal": True})
# else:
# attendance_obj.sudo().write({"is_no_card": True, "is_abnormal": True})
return True
@staticmethod
def divide_time_range_fixed(start_time, end_time):
time_ranges = [start_time]
while start_time <= end_time:
current_date = start_time + relativedelta(days=1)
time_ranges.append(current_date.strftime("%Y-%m-%d"))
start_time = current_date
return time_ranges