From 97f83ceb0ac8c70c1f9da587d504ca6f984b62ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=B9=8F=E5=AE=87?= Date: Thu, 7 May 2026 10:18:39 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=96=E6=B6=88=E8=8A=82=E5=81=87=E6=97=A5?= =?UTF-8?q?=E6=8F=90=E9=86=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yuthon_salary/models/yuthon_meal_expenses.py | 70 ++++++++++++++++++-- 1 file changed, 65 insertions(+), 5 deletions(-) diff --git a/yuthon_salary/models/yuthon_meal_expenses.py b/yuthon_salary/models/yuthon_meal_expenses.py index 76b4f004a..c88de870e 100644 --- a/yuthon_salary/models/yuthon_meal_expenses.py +++ b/yuthon_salary/models/yuthon_meal_expenses.py @@ -1,5 +1,5 @@ from odoo import api, fields, models -from datetime import datetime +from datetime import datetime, timedelta import calendar @@ -90,6 +90,54 @@ class YuthonMealExpenses(models.Model): current_month = datetime.now().month return str(current_month) + def _remove_leading_zero(self, date_str): + """去掉日期字符串的前导零,如 '01月01日' -> '1月1日'""" + month, day = date_str.split('月') + day = day.replace('日', '') + return f"{int(month)}月{int(day)}日" + + def _is_chinese_workday(self, check_date=None): + """判断给定日期是否为中国工作日(考虑法定节假日和调休)""" + if check_date is None: + check_date = datetime.now() + + # 获取当年行政考勤工作日的节假日数据 + current_year = check_date.year + query_start = datetime(current_year, 1, 1, 0, 0, 0) - timedelta(hours=8) + query_end = datetime(current_year, 12, 31, 23, 59, 59) - timedelta(hours=8) + + calendar_leaves = self.env['resource.calendar.leaves'].sudo().search([ + ("calendar_id.name", "=", "行政考勤工作日"), + ("date_from", ">=", query_start), + ("date_from", "<=", query_end) + ]) + + holidays_list = [] + shift_days_list = [] + + for leave in calendar_leaves: + if leave.holidays: + holidays_list.extend(leave.holidays.split(',')) + if leave.alternate_rest_day: + holidays_list.extend(leave.alternate_rest_day.split(',')) + if leave.shift_replacement_day: + shift_days_list.extend(leave.shift_replacement_day.split(',')) + + holidays_list = [self._remove_leading_zero(d) for d in holidays_list] + shift_days_list = [self._remove_leading_zero(d) for d in shift_days_list] + + date_str = self._remove_leading_zero(check_date.strftime('%m月%d日')) + + if date_str in shift_days_list: + # 调休补班日,强制算工作日 + return True + if date_str in holidays_list: + # 法定节假日或调休休息日,算非工作日 + return False + + # 没有特殊安排的,按周末判断 + return check_date.weekday() < 5 + def send_meal(self): return { 'type': 'ir.actions.act_window', @@ -112,6 +160,18 @@ class YuthonMealExpenses(models.Model): def cron_send_meal_reminder(self): """定时任务:给状态为已发送且缴费状态为待缴的记录发送缴费提醒""" + # 节假日不发送 + if not self._is_chinese_workday(): + self.env['ir.logging'].sudo().create({ + 'name': '餐费缴费提醒', + 'type': 'server', + 'message': f'今天{datetime.now().strftime("%Y-%m-%d")}是节假日或周末,跳过发送餐费缴费提醒', + 'path': __name__, + 'func': 'cron_send_meal_reminder', + 'line': 0, + }) + return True + # 找出所有 已发送 且 仍然 待缴 的餐费记录 meals = self.sudo().search([ ('meal_state', '=', 'done'), @@ -253,15 +313,15 @@ class YuthonMealExpenses(models.Model): """定时任务:每月第一个工作日发送餐费缴费提醒""" from datetime import datetime, timedelta import calendar - - # 检查是否是工作日 + + # 检查是否是中国工作日(含法定节假日和调休判断) today = datetime.now() - if today.weekday() >= 5: # 0-4是工作日,5-6是周末 + if not self._is_chinese_workday(today): # 记录日志 self.env['ir.logging'].sudo().create({ 'name': '餐费缴费提醒', 'type': 'server', - 'message': f'今天{today.strftime("%Y-%m-%d")}是周末,跳过发送餐费缴费提醒', + 'message': f'今天{today.strftime("%Y-%m-%d")}是节假日或周末,跳过发送餐费缴费提醒', 'path': __name__, 'func': 'cron_send_monthly_meal_reminder', 'line': 0,