From dc37979e7b0a2a77bedc0f29e5b772d341a53ca0 Mon Sep 17 00:00:00 2001 From: Dossogne Bertrand Date: Thu, 11 May 2023 12:10:47 +0000 Subject: [PATCH] [IMP] hr_holidays: display correct calendar attendances Before this commit, the attendance and non-working days were always based to the current calendar of the user's employee. This is not accurate since we can see other's calendars and contract changes can lead to calendar changes (from full-time to part-time,...). This commit base that view on the viewed employee contracts so that even a contract change is correctly viewed. task-3060722 closes odoo/odoo#121153 Related: odoo/enterprise#42125 Signed-off-by: Kevin Baptiste --- addons/hr_contract/models/hr_employee.py | 28 ++++++++++++++++++- addons/hr_holidays/models/hr_leave.py | 4 ++- .../src/views/calendar/calendar_model.js | 16 +++++++++++ 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/addons/hr_contract/models/hr_employee.py b/addons/hr_contract/models/hr_employee.py index e98d02100fc..afe73bb6012 100644 --- a/addons/hr_contract/models/hr_employee.py +++ b/addons/hr_contract/models/hr_employee.py @@ -1,7 +1,9 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from datetime import date +from pytz import UTC +from datetime import date, datetime, time + from odoo import api, fields, models from odoo.osv import expression @@ -28,6 +30,7 @@ class Employee(models.Model): def _get_first_contract_date(self, no_gap=True): self.ensure_one() + def remove_gap(contracts): # We do not consider a gap of more than 4 days to be a same occupation # contracts are considered to be ordered correctly @@ -94,6 +97,29 @@ class Employee(models.Model): """ return self.search(['|', ('active', '=', True), ('active', '=', False)])._get_contracts(date_from, date_to, states=states) + def _get_unusual_days(self, date_from, date_to=None): + employee_contracts = self.env['hr.contract'].search([ + ('state', '!=', 'cancel'), + ('employee_id', '=', self.id), + ('date_start', '<=', date_to), + '|', + ('date_end', '=', False), + ('date_end', '>=', date_from), + ]) + if not employee_contracts: + return super()._get_unusual_days(date_from, date_to) + unusual_days = {} + date_from_date = datetime.strptime(date_from, '%Y-%m-%d %H:%M:%S').date() + date_to_date = datetime.strptime(date_to, '%Y-%m-%d %H:%M:%S').date() if date_to else None + for contract in employee_contracts: + tmp_date_from = max(date_from_date, contract.date_start) + tmp_date_to = min(date_to_date, contract.date_end) if contract.date_end else date_to_date + unusual_days.update(contract.resource_calendar_id._get_unusual_days( + datetime.combine(fields.Date.from_string(tmp_date_from), time.min).replace(tzinfo=UTC), + datetime.combine(fields.Date.from_string(tmp_date_to), time.max).replace(tzinfo=UTC) + )) + return unusual_days + def write(self, vals): res = super().write(vals) if vals.get('contract_id'): diff --git a/addons/hr_holidays/models/hr_leave.py b/addons/hr_holidays/models/hr_leave.py index c2b10cf5122..b63cdb3386a 100644 --- a/addons/hr_holidays/models/hr_leave.py +++ b/addons/hr_holidays/models/hr_leave.py @@ -1694,7 +1694,9 @@ class HolidaysRequest(models.Model): @api.model def get_unusual_days(self, date_from, date_to=None): - return self.env.user.employee_id.sudo(False)._get_unusual_days(date_from, date_to) + employee_id = self.env.context.get('employee_id', False) + employee = self.env['hr.employee'].browse(employee_id) if employee_id else self.env.user.employee_id + return employee.sudo(False)._get_unusual_days(date_from, date_to) def _get_start_or_end_from_attendance(self, hour, date, employee): hour = float_to_time(float(hour)) diff --git a/addons/hr_holidays/static/src/views/calendar/calendar_model.js b/addons/hr_holidays/static/src/views/calendar/calendar_model.js index fdc8d84ba20..a3c3c138920 100644 --- a/addons/hr_holidays/static/src/views/calendar/calendar_model.js +++ b/addons/hr_holidays/static/src/views/calendar/calendar_model.js @@ -45,9 +45,25 @@ export class TimeOffCalendarModel extends CalendarModel { async updateData(data) { await super.updateData(data); + data.stressDays = await this.fetchStressDays(data); } + /** + * @override + */ + fetchUnusualDays(data) { + return this.orm.call(this.meta.resModel, "get_unusual_days", [ + serializeDateTime(data.range.start), + serializeDateTime(data.range.end), + ], + { + context: { + 'employee_id': this.employeeId, + } + }); + } + async fetchStressDays(data) { return this.orm.call("hr.employee", "get_stress_days", [ this.employeeId,