From 770a908978b9d1fdbb9fde614692217c9133e654 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: Mon, 17 Nov 2025 10:42:41 +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_base/views/menu.xml | 2 +- yuthon_holiday/models/inherit_hr_leave.py | 78 +------ .../data/attendance_time_data.xml | 103 ++++++--- yuthon_hr_attendance/models/hr_attendance.py | 208 ++++++++++-------- yuthon_wechat/models/wecom_apps.py | 17 +- 5 files changed, 216 insertions(+), 192 deletions(-) diff --git a/yuthon_base/views/menu.xml b/yuthon_base/views/menu.xml index 1f176ca23..319fe26c6 100644 --- a/yuthon_base/views/menu.xml +++ b/yuthon_base/views/menu.xml @@ -15,7 +15,7 @@ action="base.ir_cron_act" sequence="5"/> 12: - hour = float(end_hour) - float(start_hour) - 1 - holiday.number_of_hours = hour - # 9点到12点的情况 - elif start_hour == 9 and end_hour == 12: - holiday.number_of_hours = 4 - # 其他情况按正常计算 - else: - hour = float(end_hour) - float(start_hour) - holiday.number_of_hours = hour - # 非假期且非调休日的情况 - else: - # 如果是周末且不在调休列表中,小时数为0 - if is_weekend: - holiday.number_of_hours = 0 - # 普通工作日按正常逻辑计算 + if holiday.request_hour_from and holiday.request_hour_to: + start_hour = float(holiday.request_hour_from) + end_hour = float(holiday.request_hour_to) + if start_hour < 12 and end_hour > 12: + hour = end_hour - start_hour - 1 + holiday.number_of_hours = hour + elif start_hour == 9 and end_hour == 12: + holiday.number_of_hours = 4 else: - if holiday.request_hour_from and holiday.request_hour_to: - start_hour = float(holiday.request_hour_from) - end_hour = float (holiday.request_hour_to) - if start_hour < 12 and end_hour > 12: - hour = float(end_hour) - float(start_hour) - 1 - holiday.number_of_hours = hour - elif start_hour == 9 and end_hour == 12: - holiday.number_of_hours = 4 - else: - hour = float(end_hour) - float(start_hour) - holiday.number_of_hours = hour - + hour = end_hour - start_hour + holiday.number_of_hours = hour + else: + holiday.number_of_hours = 0 days = (holiday.request_date_to - holiday.request_date_from).days + 1 - current_date = holiday.request_date_from - while current_date <= holiday.request_date_to: - current_date_str = current_date.strftime('%m月%d日') - current_date_str = holiday.remove_leading_zero(current_date_str) - is_weekend = current_date.weekday() in [5, 6] - if current_date_str in holidays_list: - days -= 1 - elif current_date_str in shift_days_list: - if not is_weekend: - days += 1 - else : - if is_weekend: - days -= 1 - current_date += timedelta(days=1) holiday.number_of_days = days def _compute_request_unit_hours(self): diff --git a/yuthon_hr_attendance/data/attendance_time_data.xml b/yuthon_hr_attendance/data/attendance_time_data.xml index c5e693408..d7ddf2cf6 100644 --- a/yuthon_hr_attendance/data/attendance_time_data.xml +++ b/yuthon_hr_attendance/data/attendance_time_data.xml @@ -120,19 +120,6 @@ -1 - - 定时任务:工程部中值夜班值班打卡提醒 - - code - model.gc_night_remind_shift() - - - 1 - days - - -1 - - @@ -200,45 +187,111 @@ -1 - - 定时任务:客服上班提醒 + + 定时任务: 保安部旧晚(旧区府晚班)上班提醒 code - model.card_customer_service_shift_remind_on() + model.ba_card_old_night_up() 1 days - + -1 - - 定时任务:客服下班提醒 + + 定时任务: 保安部旧晚(旧区府晚班)下班提醒 code - model.card_customer_service_shift_remind_out() + model.ba_card_old_night_down() 1 days - + + -1 + + + + 定时任务:保安部旧白(旧区府白班)上班提醒 + + code + model.ba_card_old_white_up() + + + 1 + days + -1 - - 定时任务:客服值班提醒 + + 定时任务:保安部旧白(旧区府白班)下班提醒 code - model.card_customer_service_stand_remind() + model.ba_card_old_white_down() 1 days - + -1 + + 定时任务:工程部旧晚(旧区府晚班)上班打卡提醒 + + code + model.card_old_night_remind_in() + + + 1 + days + + -1 + + + + 定时任务:工程部旧晚(旧区府晚班)下班打卡提醒 + + code + model.card_old_night_remind_out() + + + 1 + days + + -1 + + + + 定时任务:工程部旧白(旧区府白班)上班打卡提醒 + + code + model.card_old_day_remind_in() + + + 1 + days + + -1 + + + + 定时任务:工程部旧白(旧区府白班)下班打卡提醒 + + code + model.card_old_day_remind_out() + + + 1 + days + + -1 + + + diff --git a/yuthon_hr_attendance/models/hr_attendance.py b/yuthon_hr_attendance/models/hr_attendance.py index a9ad0b3a5..20e054af3 100644 --- a/yuthon_hr_attendance/models/hr_attendance.py +++ b/yuthon_hr_attendance/models/hr_attendance.py @@ -160,16 +160,6 @@ class HrAttendance(models.Model): ) current_date += timedelta(days=1) - # @api.model - # def web_read_group(self, domain, fields, groupby, limit=None, offset=0, orderby=False, lazy=True): - # result = super().web_read_group(domain, fields, groupby, limit, offset, orderby, lazy) - # fields_dict = self.fields_get(fields) - # for group in result.get('groups'): - # for field in fields: - # if fields_dict[field].get('type') == 'boolean': - # group[field] = len([r for r in self.search_read(group['__domain'], fields=[field]) if r.get(field)]) - # return result - @api.constrains('check_in', 'check_out') def _check_validity_check_in_check_out(self): """ verifies if check_in is earlier than check_out. """ @@ -212,9 +202,15 @@ class HrAttendance(models.Model): def attendance_abnormal_remind(self): all_employees = self.env['hr.employee'].search([]) current_date = fields.Date.today() + current_dt = fields.Datetime.now() month_start = current_date.replace(day=1) month_end = (month_start + relativedelta(months=1) - relativedelta(days=1)) - current_time = fields.Datetime.now() + start_time = datetime.combine(current_date, datetime.min.time().replace(hour=8, minute=50)) + end_time = datetime.combine(current_date, datetime.min.time().replace(hour=9, minute=10)) + if not (start_time <= current_dt <= end_time): + return + if not self._process_shift_days(current_date): + return for employee in all_employees: domain = [ ('shift_name', '=', '行政班次'), @@ -795,99 +791,121 @@ class HrAttendance(models.Model): else: record.week = False - # 行政异常提醒 - def admin_comment_abnormal(self): - week = (fields.date.today() + timedelta(hours=8)).weekday() - if week < 5: - employee_ids = self.env['hr.employee'].search([('department_id.name', '=', '办公室')]) - menu_id = self.env['ir.ui.menu'].search([('name', '=', '我的异常')]) - for employee_id in employee_ids: - url = f'https://oa.thtzjt.com/web#id={self.id}&cids=2&action={menu_id.action.id}&model=hr.attendance&view_type=from&menu_id={menu_id.id}' - self.sudo().env["wecom.apps"].sync_send_message_textcard(category='att', - user_id=employee_id.wecom_userid, - title="打卡异常提醒", description="异常提醒", - url=url, btntxt="详细信息") + def _is_within_10min_by_float(self, base_float): + base_hour = int(base_float) + base_minute = int((base_float - base_hour) * 60) + today = fields.date.today() + base_datetime = datetime.combine(today, datetime.min.time().replace(hour=base_hour, minute=base_minute)) - # 保安部 - 白班 + # 计算前后10分钟区间 + start_interval = base_datetime - timedelta(minutes=10) + end_interval = base_datetime + timedelta(minutes=10) + current_datetime = datetime.now() + return start_interval <= current_datetime <= end_interval + + # 保安部 - 白班(早班) def ba_card_white_up(self): ba_up_users = self.env['planning.slot'].search( [('role_id.name', '=', '保安部'), ('template_id.planning_name', '=', '早班')]) for user in ba_up_users: - if user.start_datetime.date() == fields.date.today(): - self.card_in_comment(user.resource_id.employee_id,user.template_id.planning_name) + if user.template_id.check_in_start and self._is_within_10min_by_float(user.template_id.check_in_start): + self.card_in_comment(user.resource_id.employee_id, user.template_id.planning_name) def ba_card_white_down(self): ba_up_users = self.env['planning.slot'].search( [('role_id.name', '=', '保安部'), ('template_id.planning_name', '=', '早班')]) for user in ba_up_users: - if user.start_datetime.date() == fields.date.today(): - self.card_out_comment(user.resource_id.employee_id,user.template_id.planning_name) + if user.template_id.check_out_start and self._is_within_10min_by_float(user.template_id.check_out_start): + self.card_out_comment(user.resource_id.employee_id, user.template_id.planning_name) # 保安部 - 中班 def ba_card_mid_up(self): ba_up_users = self.env['planning.slot'].search( [('role_id.name', '=', '保安部'), ('template_id.planning_name', '=', '中班')]) for user in ba_up_users: - if user.start_datetime.date() == fields.date.today(): - self.card_in_comment(user.resource_id.employee_id,user.template_id.planning_name) + if user.template_id.check_in_start and self._is_within_10min_by_float(user.template_id.check_in_start): + self.card_in_comment(user.resource_id.employee_id, user.template_id.planning_name) def ba_card_mid_down(self): ba_up_users = self.env['planning.slot'].search( [('role_id.name', '=', '保安部'), ('template_id.planning_name', '=', '中班')]) for user in ba_up_users: - if user.start_datetime.date() == fields.date.today(): - self.card_out_comment(user.resource_id.employee_id,user.template_id.planning_name) + if user.template_id.check_out_start and self._is_within_10min_by_float(user.template_id.check_out_start): + self.card_out_comment(user.resource_id.employee_id, user.template_id.planning_name) # 保安部 - 夜班 def ba_card_night_up(self): ba_up_users = self.env['planning.slot'].search( [('role_id.name', '=', '保安部'), ('template_id.planning_name', '=', '夜班')]) for user in ba_up_users: - if user.start_datetime.date() == fields.date.today(): - self.card_in_comment(user.resource_id.employee_id,user.template_id.planning_name) + if user.template_id.check_in_start and self._is_within_10min_by_float(user.template_id.check_in_start): + self.card_in_comment(user.resource_id.employee_id, user.template_id.planning_name) def ba_card_night_down(self): ba_up_users = self.env['planning.slot'].search( [('role_id.name', '=', '保安部'), ('template_id.planning_name', '=', '夜班')]) for user in ba_up_users: - if user.end_datetime.date() == fields.date.today(): - self.card_out_comment(user.resource_id.employee_id,user.template_id.planning_name) + if user.template_id.check_out_start and self._is_within_10min_by_float(user.template_id.check_out_start): + self.card_out_comment(user.resource_id.employee_id, user.template_id.planning_name) + + # 保安部 - 旧晚(旧区府晚班) + def ba_card_old_night_up(self): + ba_up_users = self.env['planning.slot'].search( + [('role_id.name', '=', '保安部'), ('template_id.planning_name', '=', '旧晚(旧区府晚班)')]) + for user in ba_up_users: + if user.template_id.check_in_start and self._is_within_10min_by_float(user.template_id.check_in_start): + self.card_in_comment(user.resource_id.employee_id, user.template_id.planning_name) + + def ba_card_old_night_down(self): + ba_up_users = self.env['planning.slot'].search( + [('role_id.name', '=', '保安部'), ('template_id.planning_name', '=', '旧晚(旧区府晚班)')]) + for user in ba_up_users: + if user.template_id.check_out_start and self._is_within_10min_by_float(user.template_id.check_out_start): + self.card_out_comment(user.resource_id.employee_id, user.template_id.planning_name) + + # 保安部 - 旧白(旧区府白班) + def ba_card_old_white_up(self): + ba_up_users = self.env['planning.slot'].search( + [('role_id.name', '=', '保安部'), ('template_id.planning_name', '=', '旧白(旧区府白班)')]) + for user in ba_up_users: + if user.template_id.check_in_start and self._is_within_10min_by_float(user.template_id.check_in_start): + self.card_in_comment(user.resource_id.employee_id, user.template_id.planning_name) + + def ba_card_old_white_down(self): + ba_up_users = self.env['planning.slot'].search( + [('role_id.name', '=', '保安部'), ('template_id.planning_name', '=', '旧白(旧区府白班)')]) + for user in ba_up_users: + if user.template_id.check_out_start and self._is_within_10min_by_float(user.template_id.check_out_start): + self.card_out_comment(user.resource_id.employee_id, user.template_id.planning_name) # 工程部 - 白班 def gc_white_in_remind(self): ba_up_users = self.env['planning.slot'].search( [('role_id.name', '=', '工程部'), ('template_id.planning_name', '=', '白班')]) for user in ba_up_users: - if user.start_datetime.date() == fields.date.today(): - self.card_in_comment(user.resource_id.employee_id,user.template_id.planning_name) - - def gc_white_shift_remind(self): - ba_up_users = self.env['planning.slot'].search( - [('role_id.name', '=', '工程部'), ('template_id.planning_name', '=', '白值')]) - for user in ba_up_users: - if user.start_datetime.date() == fields.date.today(): - self.card_duty_remind(user.resource_id.employee_id) + if user.template_id.check_in_start and self._is_within_10min_by_float(user.template_id.check_in_start): + self.card_in_comment(user.resource_id.employee_id, user.template_id.planning_name) def gc_white_out_remind(self): ba_up_users = self.env['planning.slot'].search( [('role_id.name', '=', '工程部'), ('template_id.planning_name', '=', '白班')]) for user in ba_up_users: - if user.start_datetime.date() == fields.date.today(): - self.card_out_comment(user.resource_id.employee_id,user.template_id.planning_name) + if user.template_id.check_out_start and self._is_within_10min_by_float(user.template_id.check_out_start): + self.card_out_comment(user.resource_id.employee_id, user.template_id.planning_name) # 工程部 - 白值 def gc_white_remind_in(self): ba_up_users = self.env['planning.slot'].search( [('role_id.name', '=', '工程部'), ('template_id.planning_name', '=', '白值')]) for user in ba_up_users: - if user.start_datetime.date() == fields.date.today(): + if user.template_id.check_in_start and self._is_within_10min_by_float(user.template_id.check_in_start): self.card_in_comment(user.resource_id.employee_id, user.template_id.planning_name) def gc_white_remind_out(self): ba_up_users = self.env['planning.slot'].search( [('role_id.name', '=', '工程部'), ('template_id.planning_name', '=', '白值')]) for user in ba_up_users: - if user.start_datetime.date() == fields.date.today(): + if user.template_id.check_out_start and self._is_within_10min_by_float(user.template_id.check_out_start): self.card_out_comment(user.resource_id.employee_id, user.template_id.planning_name) # 工程部-中值夜 @@ -895,91 +913,97 @@ class HrAttendance(models.Model): ba_up_users = self.env['planning.slot'].search( [('role_id.name', '=', '工程部'), ('template_id.planning_name', '=', '中夜')]) for user in ba_up_users: - if user.start_datetime.date() == fields.date.today(): - self.card_in_comment(user.resource_id.employee_id,user.template_id.planning_name) - - def gc_night_remind_shift(self): - ba_up_users = self.env['planning.slot'].search( - [('role_id.name', '=', '工程部'), ('template_id.planning_name', '=', '中夜')]) - for user in ba_up_users: - if user.end_datetime.date() == fields.date.today(): - self.card_duty_remind(user.resource_id.employee_id) + if user.template_id.check_in_start and self._is_within_10min_by_float(user.template_id.check_in_start): + self.card_in_comment(user.resource_id.employee_id, user.template_id.planning_name) def gc_night_remind_out(self): ba_up_users = self.env['planning.slot'].search( [('role_id.name', '=', '工程部'), ('template_id.planning_name', '=', '中夜')]) for user in ba_up_users: - if user.end_datetime.date() == fields.date.today(): - self.card_out_comment(user.resource_id.employee_id,user.template_id.planning_name) + if user.template_id.check_out_start and self._is_within_10min_by_float(user.template_id.check_out_start): + self.card_out_comment(user.resource_id.employee_id, user.template_id.planning_name) + + # 工程部 - 旧晚(旧区府晚班) + def card_old_night_remind_in(self): + ba_up_users = self.env['planning.slot'].search( + [('role_id.name', '=', '工程部'), ('template_id.planning_name', '=', '旧晚(旧区府晚班)')]) + for user in ba_up_users: + if user.template_id.check_in_start and self._is_within_10min_by_float(user.template_id.check_in_start): + self.card_in_comment(user.resource_id.employee_id, user.template_id.planning_name) + + def card_old_night_remind_out(self): + ba_up_users = self.env['planning.slot'].search( + [('role_id.name', '=', '工程部'), ('template_id.planning_name', '=', '旧晚(旧区府晚班)')]) + for user in ba_up_users: + if user.template_id.check_out_start and self._is_within_10min_by_float(user.template_id.check_out_start): + self.card_out_comment(user.resource_id.employee_id, user.template_id.planning_name) + + # 工程部 - 旧白(旧区府白班) + def card_old_day_remind_in(self): + ba_up_users = self.env['planning.slot'].search( + [('role_id.name', '=', '工程部'), ('template_id.planning_name', '=', '旧白(旧区府白班)')]) + for user in ba_up_users: + if user.template_id.check_in_start and self._is_within_10min_by_float(user.template_id.check_in_start): + self.card_in_comment(user.resource_id.employee_id, user.template_id.planning_name) + + def card_old_day_remind_out(self): + ba_up_users = self.env['planning.slot'].search( + [('role_id.name', '=', '工程部'), ('template_id.planning_name', '=', '旧白(旧区府白班)')]) + for user in ba_up_users: + if user.template_id.check_out_start and self._is_within_10min_by_float(user.template_id.check_out_start): + self.card_out_comment(user.resource_id.employee_id, user.template_id.planning_name) # 粮储-白班 def card_lc_remind_in(self): ba_up_users = self.env['planning.slot'].search( [('role_id.name', '=', '联安粮库'), ('template_id.planning_name', '=', '白班')]) for user in ba_up_users: - if user.start_datetime.date() == fields.date.today(): - self.card_in_comment(user.resource_id.employee_id,user.template_id.planning_name) + if user.template_id.check_in_start and self._is_within_10min_by_float(user.template_id.check_in_start): + self.card_in_comment(user.resource_id.employee_id, user.template_id.planning_name) def card_lc_remind_out(self): ba_up_users = self.env['planning.slot'].search( [('role_id.name', '=', '联安粮库'), ('template_id.planning_name', '=', '白班')]) for user in ba_up_users: - if user.start_datetime.date() == fields.date.today(): - self.card_out_comment(user.resource_id.employee_id,user.template_id.planning_name) + if user.template_id.check_out_start and self._is_within_10min_by_float(user.template_id.check_out_start): + self.card_out_comment(user.resource_id.employee_id, user.template_id.planning_name) - # 粮储-值班 + # 粮储-值班(白值) def card_lc_shift_remind_in(self): ba_up_users = self.env['planning.slot'].search( [('role_id.name', '=', '联安粮库'), ('template_id.planning_name', '=', '白值')]) for user in ba_up_users: - if user.start_datetime.date() == fields.date.today(): + if user.template_id.check_in_start and self._is_within_10min_by_float(user.template_id.check_in_start): self.card_in_comment(user.resource_id.employee_id, user.template_id.planning_name) def card_lc_shift_remind(self): ba_up_users = self.env['planning.slot'].search( [('role_id.name', '=', '联安粮库'), ('template_id.planning_name', '=', '白值')]) for user in ba_up_users: - if user.start_datetime.date() == fields.date.today(): + # 值班提醒:基于 template_id.check_in_start(同上班基准) + if user.template_id.check_in_start and self._is_within_10min_by_float(user.template_id.check_in_start): self.card_duty_remind(user.resource_id.employee_id) def card_lc_shift_remind_out(self): - ba_up_users = self.env['planning.slot'].search([('role_id.name', '=', '联安粮库'), ('template_id.planning_name', '=', '白值')]) + ba_up_users = self.env['planning.slot'].search( + [('role_id.name', '=', '联安粮库'), ('template_id.planning_name', '=', '白值')]) for user in ba_up_users: - if user.start_datetime.date() == fields.date.today(): - self.card_out_comment(user.resource_id.employee_id,user.template_id.planning_name) + if user.template_id.check_out_start and self._is_within_10min_by_float(user.template_id.check_out_start): + self.card_out_comment(user.resource_id.employee_id, user.template_id.planning_name) + # 保安计划行政 def card_lc_shift_remind_on_administrative(self): ba_up_users = self.env['planning.slot'].search([('template_id.planning_name', '=', '保安计划行政')]) for user in ba_up_users: - if user.start_datetime.date() == fields.date.today(): + if user.template_id.check_in_start and self._is_within_10min_by_float(user.template_id.check_in_start): self.card_in_comment(user.resource_id.employee_id, user.template_id.planning_name) def card_lc_shift_remind_out_administrative(self): ba_up_users = self.env['planning.slot'].search([('template_id.planning_name', '=', '保安计划行政')]) for user in ba_up_users: - if user.start_datetime.date() == fields.date.today(): + if user.template_id.check_out_start and self._is_within_10min_by_float(user.template_id.check_out_start): self.card_out_comment(user.resource_id.employee_id, user.template_id.planning_name) - # 客服上班消息提醒 - def card_customer_service_shift_remind_on(self): - ba_up_users = self.env['planning.slot'].search([('role_id.name', '=', '客服中心'), ('template_id.planning_name', '=', '白班')]) - for user in ba_up_users: - if user.start_datetime.date() == fields.date.today(): - self.card_in_comment(user.resource_id.employee_id, user.template_id.planning_name) - - # 客服下班消息提醒 - def card_customer_service_shift_remind_out(self): - ba_up_users = self.env['planning.slot'].search([('role_id.name', '=', '客服中心'), ('template_id.planning_name', '=', '白班')]) - for user in ba_up_users: - if user.start_datetime.date() == fields.date.today(): - self.card_out_comment(user.resource_id.employee_id, user.template_id.planning_name) - - # 客服值班消息提醒 - def card_customer_service_stand_remind(self): - ba_up_users = self.env['planning.slot'].search([('role_id.name', '=', '客服中心'), ('template_id.planning_name', '=', '值班')]) - for user in ba_up_users: - if user.start_datetime.date() == fields.date.today(): - self.card_duty_remind(user.resource_id.employee_id) def card_in_comment(self, employee_id, planning_name): data = f"您的班次是{planning_name},还有10分钟上班,记得打卡" diff --git a/yuthon_wechat/models/wecom_apps.py b/yuthon_wechat/models/wecom_apps.py index 5b38c3fbf..7ff697f46 100644 --- a/yuthon_wechat/models/wecom_apps.py +++ b/yuthon_wechat/models/wecom_apps.py @@ -160,14 +160,15 @@ class WeComApps(models.Model): }, } result_data = self.sync_function_api("message_send", "MESSAGE_SEND", data, category) - employee_id = self.env["res.users"].search([("id", "=", user_id)], limit=1).employee_ids - self.env["attendance.message.log"].create({ - "employee_id": employee_id.id, - "content": description, - "notice_type": 'attendance', - 'update_date': fields.Datetime.now() - timedelta(hours=8), - "message_url": url, - }) + if category == 'att': + employee_id = self.env["res.users"].search([("id", "=", user_id)], limit=1).employee_ids + self.env["attendance.message.log"].create({ + "employee_id": employee_id.id, + "content": description, + "notice_type": 'attendance', + 'update_date': fields.Datetime.now() - timedelta(hours=8), + "message_url": url, + }) if result_data.get("errcode", None) == 0: return True, result_data return False, result_data