From eb63ea9b4871bf285d5cbf8044d4f472f5f2ace0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=B9=8F=E5=AE=87?= <9664676+pengyuthon@user.noreply.gitee.com> Date: Thu, 4 Sep 2025 10:46:08 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yuthon_hr_attendance/models/hr_attendance.py | 15 +++++-- .../models/hr_attendance_detail_wechat.py | 39 +++++++++++++++---- .../views/hr_attendance_views.xml | 6 +-- 3 files changed, 46 insertions(+), 14 deletions(-) diff --git a/yuthon_hr_attendance/models/hr_attendance.py b/yuthon_hr_attendance/models/hr_attendance.py index 9ee452f0a..f4df8a4c3 100644 --- a/yuthon_hr_attendance/models/hr_attendance.py +++ b/yuthon_hr_attendance/models/hr_attendance.py @@ -90,7 +90,7 @@ class HrAttendance(models.Model): def compute_attendance_ids(self): for att in self.env["hr.attendance"].browse(self._context.get('active_ids', self._context.get('active_id'))): current_data = fields.Datetime.to_datetime(att.current_data) + timedelta(hours=8) - self.env["hr.attendance.detail"].compute_attendance_detail(att.employee_id, current_data.date()) + self.env["hr.attendance.detail"].compute_attendance_detail(att.employee_id, current_data.date(), is_manual= True) @api.depends('current_data') def _compute_month_status(self): @@ -257,6 +257,10 @@ class HrAttendance(models.Model): if employee_record: # 更新现有记录的缺卡状态 employee_record.write({'is_no_card': is_no_card}) + if is_no_card == True: + employee_record.write({'absenteeism_card': True, + 'is_abnormal': True + }) else: # 没有记录且需要标记为缺卡时,创建新记录 self.env['hr.attendance'].create({ @@ -890,11 +894,14 @@ class HrAttendance(models.Model): title="打卡提醒", url=url, btntxt="详细信息") - def update_id(self): + def update_abnormal(self): attendance_ids = self.env["hr.attendance"].browse( self._context.get('active_ids', self._context.get('active_id'))) - for attendance_id in attendance_ids: - attendance_id.userid = attendance_id.employee_id.user_id.id + for attendance in attendance_ids: + if attendance.is_no_card: + attendance.absenteeism_card = True + attendance.is_abnormal = True + @api.model def create(self, vals): diff --git a/yuthon_hr_attendance/models/hr_attendance_detail_wechat.py b/yuthon_hr_attendance/models/hr_attendance_detail_wechat.py index 200136409..5f645a95d 100644 --- a/yuthon_hr_attendance/models/hr_attendance_detail_wechat.py +++ b/yuthon_hr_attendance/models/hr_attendance_detail_wechat.py @@ -149,10 +149,11 @@ class HrAttendanceDetail(models.Model): current_data = fields.Datetime.to_datetime(checkin_date) + timedelta(hours=8) self.env["hr.attendance.detail"].compute_attendance_detail(record.employee_id, current_data.date()) - def compute_attendance_detail(self, employee, current_data): + def compute_attendance_detail(self, employee, current_data, is_manual= False): """重新计算逻辑 :param current_data: 打卡日期 :param employee_id: 员工 + :param is_manual: 是否是手动计算 """ # 是否在白名单 resource_user_ids = employee.resource_calendar_id.resource_user_ids.ids @@ -245,7 +246,8 @@ class HrAttendanceDetail(models.Model): ) # 获取正常上下班时间 sch_check_in_time, sch_check_out_time = self.normal_clock_in_time(template, current_data) - is_early_card, is_late_card, is_abnormal, is_warning, absenteeism_card = self.state_judgment(employee, check_in_time, check_out_time, sch_check_in_time, sch_check_out_time, current_data) + is_early_card, is_late_card, is_abnormal, is_warning, absenteeism_card, is_no_card = self.state_judgment(employee, check_in_time, check_out_time, sch_check_in_time, sch_check_out_time, current_data, is_manual) + if attendance: attendance.write({ 'check_in': check_in_time, @@ -254,6 +256,7 @@ class HrAttendanceDetail(models.Model): 'is_late_card': is_late_card, 'is_abnormal': is_abnormal, 'is_warning': is_warning, + 'is_no_card': is_no_card, 'absenteeism_card': absenteeism_card, }) else: @@ -267,6 +270,7 @@ class HrAttendanceDetail(models.Model): 'is_early_card': is_early_card, 'is_late_card': is_late_card, 'is_abnormal': is_abnormal, + 'is_no_card': is_no_card, 'is_warning': is_warning, 'absenteeism_card': absenteeism_card, }) @@ -282,6 +286,7 @@ class HrAttendanceDetail(models.Model): check_out_end = template.end_time2 else: check_out_end = template.end_time + date = current_data start_hour = int(check_in_start) start_minute = int((check_in_start - start_hour) * 60) @@ -298,6 +303,12 @@ class HrAttendanceDetail(models.Model): end_datetime = datetime.combine(date, datetime.min.time()).replace( hour=end_hour, minute=end_minute, second=0, microsecond=0 ) - timedelta(hours=8) + + if template.planning_name == '中夜': + end_datetime = datetime.combine(date, datetime.min.time()).replace( + hour=22, minute=0, second=0, microsecond=0 + ) - timedelta(hours=8) + return start_datetime, end_datetime def float_to_datetime(self, base_date, hour_float): @@ -311,7 +322,7 @@ class HrAttendanceDetail(models.Model): minutes = int((hour_float - hours) * 60) return datetime.combine(base_date, datetime.min.time()) + timedelta(hours=hours, minutes=minutes) - def state_judgment(self, employee, check_in, check_out, start_datetime, end_datetime, current_data): + def state_judgment(self, employee, check_in, check_out, start_datetime, end_datetime, current_data, is_manual): """ 判断打卡状态 :param check_in: 签到时间 @@ -326,6 +337,7 @@ class HrAttendanceDetail(models.Model): is_abnormal = False is_warning = False absenteeism_card = False + is_no_card = False def remove_seconds(dt): """清除datetime对象的秒数和微秒""" @@ -350,10 +362,12 @@ class HrAttendanceDetail(models.Model): employee_list.append(resource_id.employee_id.id) if employee.id not in employee_list: # 判断是否工作日 - if self._process_shift_days(current_data): - return is_early_card, is_late_card, is_abnormal, is_warning, absenteeism_card + if not self._process_shift_days(current_data): + return is_early_card, is_late_card, is_abnormal, is_warning, absenteeism_card, is_no_card is_tianhe_property = employee.company_id.name == "天河物管" + + # 只要是旷工 就不算早退 或者迟到 # 迟到判断 if check_in and start_datetime and check_in > start_datetime: late_delta = (check_in - start_datetime).total_seconds() / 60 @@ -371,12 +385,14 @@ class HrAttendanceDetail(models.Model): # 迟到超过60分钟标记为旷工 if late_delta > 60: absenteeism_card = True + is_late_card = False else: if check_in > start_datetime: is_late_card = True # 迟到超过60分钟标记为旷工 if late_delta > 60: absenteeism_card = True + is_late_card = False # 早退判断 if check_out and end_datetime: early_delta = (end_datetime - check_out).total_seconds() / 60 @@ -386,18 +402,27 @@ class HrAttendanceDetail(models.Model): is_early_card = True if early_delta > 60: absenteeism_card = True + is_early_card = False else: if check_out < end_datetime: is_early_card = True if early_delta > 60: absenteeism_card = True + is_early_card = False # 异常和警告判断 - if is_early_card or is_late_card: + if is_early_card or is_late_card or absenteeism_card: is_abnormal = True is_warning = True - return is_early_card, is_late_card, is_abnormal, is_warning, absenteeism_card + if is_manual == True: + if not check_out or not check_in: + is_no_card = True + absenteeism_card = True + is_warning = True + is_abnormal = True + + return is_early_card, is_late_card, is_abnormal, is_warning, absenteeism_card, is_no_card def _process_shift_days(self, current_data): """ diff --git a/yuthon_hr_attendance/views/hr_attendance_views.xml b/yuthon_hr_attendance/views/hr_attendance_views.xml index 6e5c5a599..940e52a7b 100644 --- a/yuthon_hr_attendance/views/hr_attendance_views.xml +++ b/yuthon_hr_attendance/views/hr_attendance_views.xml @@ -165,11 +165,11 @@ code action = model.update_shift() - - 批量更新员工id + + 批量更新异常 code - action = model.update_id() + action = model.update_abnormal()