如何在Python Odoo中计算排除节假日的员工总工时
Odoo中计算排除节假日的员工总工时实现方案
问题分析
你当前的代码仅计算了起止日期的原始时间差,未排除周末和节假日,且日期处理存在冗余(Odoo的date字段无需转字符串再解析)。以下是完整的修正方案,包含工作日过滤、节假日排除逻辑。
解决步骤
- 规范日期处理:直接使用Odoo返回的
date对象,无需字符串转换 - 过滤周末:遍历日期区间,排除周六(weekday=5)和周日(weekday=6)
- 排除节假日:关联Odoo内置的
resource.calendar.leaves模型(或员工关联的资源日历假期),过滤掉区间内的节假日 - 计算有效工时:有效工作日数量 × 每日8小时
修改后的完整代码
from datetime import timedelta from dateutil.rrule import rrule, DAILY from odoo import api, models, fields class YourModelName(models.Model): _inherit = 'your.model.name' # 替换为你的实际模型名 start_date = fields.Date(string="开始日期") date_deadline = fields.Date(string="截止日期") total_hours = fields.Float(string="总工时", compute="_compute_hours", store=True) @api.depends("start_date", "date_deadline") def _compute_hours(self): for record in self: total_hours = 0.0 if record.start_date and record.date_deadline: start_dt = fields.Datetime.from_string(record.start_date) end_dt = fields.Datetime.from_string(record.date_deadline) # 生成起止区间内的所有日期(含首尾) all_days = rrule(DAILY, dtstart=start_dt, until=end_dt) # 过滤周末:仅保留周一至周五 work_days = [day for day in all_days if day.weekday() < 5] # 获取区间内的节假日(关联资源日历假期,可根据实际业务调整) # 这里默认使用员工关联的资源日历,若为全局节假日可调整查询条件 holiday_days = self.env['resource.calendar.leaves'].search([ ('date_from', '<=', end_dt.date()), ('date_to', '>=', start_dt.date()), ('resource_id', '=', record.employee_id.resource_id.id if record.employee_id else False), ('time_type', '=', 'leave') ]) # 提取节假日日期集合 holiday_set = set() for holiday in holiday_days: holiday_start = fields.Date.from_string(holiday.date_from) holiday_end = fields.Date.from_string(holiday.date_to) current_date = holiday_start while current_date <= holiday_end: holiday_set.add(current_date) current_date += timedelta(days=1) # 计算有效工作日:工作日 - 节假日 valid_days = [day for day in work_days if day.date() not in holiday_set] total_hours = len(valid_days) * 8 # 每日8小时 record.total_hours = total_hours
关键说明
- 资源日历配置:确保员工的
resource_id关联了正确的资源日历,且已在日历中添加节假日(路径:设置 > 人力资源 > 资源日历) - 自定义节假日模型:若你的业务使用独立的节假日模型,只需替换
resource.calendar.leaves的查询逻辑为你的模型查询 - 边界处理:自动处理起止日期相同、区间跨月/跨年等场景,若起止日期为同一天且是有效工作日,将返回8小时
内容的提问来源于stack exchange,提问作者Nahid Jawad Angon
相关产品推荐
相关产品推荐

