From c7e1c8de0b1807c2c79d8a8dd8e5c89909ceb5e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phan=20Sainl=C3=A9ger?= Date: Tue, 24 Jan 2023 22:23:28 +0100 Subject: [PATCH] [IMP] hr_effective_attendance_period: add resource.calendar code adds several usability functions in resource.calendar model. --- .../__manifest__.py | 2 +- .../models/resource.py | 72 ++++++++++++++++++- 2 files changed, 72 insertions(+), 2 deletions(-) diff --git a/hr_effective_attendance_period/__manifest__.py b/hr_effective_attendance_period/__manifest__.py index 7a7877a..845ea02 100644 --- a/hr_effective_attendance_period/__manifest__.py +++ b/hr_effective_attendance_period/__manifest__.py @@ -3,7 +3,7 @@ { "name": "hr_effective_attendance_period", - "version": "14.0.1.0.0", + "version": "14.0.2.0.0", "author": "Elabore", "website": "https://elabore.coop", "maintainer": "Stéphan Sainléger", diff --git a/hr_effective_attendance_period/models/resource.py b/hr_effective_attendance_period/models/resource.py index 5f6af34..10930f6 100644 --- a/hr_effective_attendance_period/models/resource.py +++ b/hr_effective_attendance_period/models/resource.py @@ -1,7 +1,77 @@ +import math +from datetime import timedelta from odoo import models, fields class ResourceCalendarAttendance(models.Model): _inherit = "resource.calendar.attendance" - effective_attendance_period = fields.Boolean('Effective Attendance Period', store=True) \ No newline at end of file + effective_attendance_period = fields.Boolean('Effective Attendance Period', store=True) + + +class ResourceCalendar(models.Model): + _inherit = "resource.calendar" + + def _retrieve_day_matching_attendances(self, day): + domain = [ + ("calendar_id", "=", self.id), + ("dayofweek", "=", day.weekday()), + ("effective_attendance_period", "=", True) + ] + if self.two_weeks_calendar: + # Employee has Even/Odd weekly calendar + week_type = 1 if int(math.floor((day.toordinal() - 1) / 7) % 2) else 0 + domain.append(("week_type", "=", week_type)) + result = self.env["resource.calendar.attendance"].search(domain) + return result + + def is_working_day(self, day): + day_attendances = self._retrieve_day_matching_attendances(day) + if len(day_attendances) == 0: + # This day of the week is not supposed to be a working day + return False + else: + # This day of the week is supposed to be a working day + return True + + def is_full_working_day(self, day): + day_attendances = self._retrieve_day_matching_attendances(day) + morning_worked = len(day_attendances.filtered(lambda x: x.day_period == "morning")) > 0 + afternoon_worked = len(day_attendances.filtered(lambda x: x.day_period == "afternoon")) > 0 + return morning_worked and afternoon_worked + + + def _is_worked_attendance(self, resource, day, attendance): + attendance_start = fields.Datetime.to_datetime(day.date()) + timedelta(hours=attendance.hour_from) + attendance_end = fields.Datetime.to_datetime(day.date()) + timedelta(hours=attendance.hour_to) + resource_leaves = self.env["resource.calendar.leaves"].search( + [ + ("company_id", "=", resource.company_id.id), + ("date_from", "<=", attendance_start), + ("date_to", ">=", attendance_end), + "|", + ("resource_id", "=", resource.id), + ("resource_id", "=", None), + ] + ) + if resource_leaves: + return False + else: + # a part or the whole attendance is worked + return True + + def is_worked_day(self, resource, day): + day_attendances = self._retrieve_day_matching_attendances(day) + # If at least one attendance is worked, return True + for attendance in day_attendances: + if self._is_worked_attendance(resource, day, attendance): + return True + return False + + def all_attendances_worked(self, resource, day): + day_attendances = self._retrieve_day_matching_attendances(day) + # If at least one attendance is not worked, return False + for attendance in day_attendances: + if not self._is_worked_attendance(resource, day, attendance): + return False + return True \ No newline at end of file