[FIX]l10n_fr_hr_holidays:fix bug in part-time employee duleaves duration calculation
This commit is contained in:
@@ -175,9 +175,14 @@ class HrLeave(models.Model):
|
||||
#@overwrite
|
||||
def _get_number_of_days_batch(self, date_from, date_to, employee_ids):
|
||||
"""
|
||||
Returns a dict with the number of legal leave days for each employee,
|
||||
based on the company's calendar. In France, part-time employees accrue and take leave on company working days,
|
||||
not only on their own working days. Handles half-day requests and rounds according to French rules.
|
||||
Returns a dict with the number of legal leave days for each employee.
|
||||
In France, part-time employees' leave is counted in company working days
|
||||
(jours ouvrables) from the first day of absence to the return day
|
||||
(exclusive). The absence period is determined by the employee's calendar,
|
||||
but the day count uses the company's calendar. Public holidays and other
|
||||
global leaves registered on the company calendar are excluded.
|
||||
For half-day requests, the first day counts as 0.5 if the employee
|
||||
works the other half of that day (returns same day), or 1 otherwise.
|
||||
"""
|
||||
employee = self.env['hr.employee'].browse(employee_ids)
|
||||
# Force the company in the domain, as we are likely in a compute_sudo context
|
||||
@@ -188,12 +193,55 @@ class HrLeave(models.Model):
|
||||
calendar = self._get_calendar()
|
||||
result = employee._get_work_days_data_batch(date_from, date_to, calendar=calendar, domain=domain)
|
||||
for employee_id in result:
|
||||
# For non-French context: a half-day leave always counts as 0.5 day
|
||||
if self.request_unit_half and result[employee_id]['hours'] > 0 and not self._l10n_fr_leave_applies():
|
||||
if self._l10n_fr_leave_applies():
|
||||
company_calendar = calendar
|
||||
employee_calendar = self.resource_calendar_id
|
||||
first_day = date_from.date()
|
||||
last_date = date_to.date()
|
||||
|
||||
# _get_fr_date_from_to returns date_to with different semantics:
|
||||
# - AM half-day, employee doesn't work PM: date_to = return day
|
||||
# (must be excluded from the count)
|
||||
# - AM half-day, employee works PM: date_to = same day (leave day)
|
||||
# - General case (full-day, PM half-day): date_to = last leave day
|
||||
# (day before the return, must be included)
|
||||
# Only the first case has date_to as the return day. It is
|
||||
# detected by: AM half-day, date_to strictly after date_from.
|
||||
if (self.request_unit_half and self.request_date_from_period == 'am'
|
||||
and last_date > first_day):
|
||||
last_date -= relativedelta(days=1)
|
||||
|
||||
# Get the set of dates where the company actually works between
|
||||
# first_day and last_date, excluding public holidays (global leaves).
|
||||
# Don't pass the company_id-filtered domain here: the leave is
|
||||
# already matched by calendar_id in _leave_intervals_batch, and
|
||||
# the company_id filter would exclude holidays created on the
|
||||
# french company when self.env.company is the main company.
|
||||
working_dates = company_calendar._get_working_dates(first_day, last_date)
|
||||
|
||||
if self.request_unit_half:
|
||||
# Check if the employee works the other half of the first day
|
||||
dayofweek = str(first_day.weekday())
|
||||
other_period = 'afternoon' if self.request_date_from_period == 'am' else 'morning'
|
||||
other_half = employee_calendar.attendance_ids.filtered(
|
||||
lambda a: a.dayofweek == dayofweek and a.day_period == other_period
|
||||
)
|
||||
first_day_count = 0.5 if (other_half and first_day in working_dates) else (1.0 if first_day in working_dates else 0.0)
|
||||
days_count = first_day_count
|
||||
current_date = first_day + relativedelta(days=1)
|
||||
else:
|
||||
days_count = 0
|
||||
current_date = first_day
|
||||
|
||||
while current_date <= last_date:
|
||||
if current_date in working_dates:
|
||||
days_count += 1
|
||||
current_date += relativedelta(days=1)
|
||||
|
||||
result[employee_id]['days'] = float(days_count)
|
||||
elif self.request_unit_half and result[employee_id]['hours'] > 0:
|
||||
# Non-French context: a half-day leave always counts as 0.5 day
|
||||
result[employee_id]['days'] = 0.5
|
||||
# For French context: round the number of days to the nearest half-day (legal rule)
|
||||
elif self.request_unit_half and result[employee_id]['hours'] > 0 and self._l10n_fr_leave_applies():
|
||||
result[employee_id]['days'] = self._round_to_nearest_half(result[employee_id]['days'])
|
||||
return result
|
||||
|
||||
def _round_to_nearest_half(self, x):
|
||||
|
||||
Reference in New Issue
Block a user