Skip to content

Commit

Permalink
[FIX] hr_holidays_natural_period: Define the correct number of days i…
Browse files Browse the repository at this point in the history
…n some use cases.

Example use case:
- Calendar Monday 16:00-21:00
- Calendar Tuesday-Friday: 09:00-14:00
- Absence from Monday to Sunday in natural day
- Number of days: 7

TT55243
  • Loading branch information
victoralmau committed Feb 27, 2025
1 parent bf3846d commit 2119995
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 3 deletions.
43 changes: 42 additions & 1 deletion hr_holidays_natural_period/models/hr_leave.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,27 @@
# Copyright 2020-2024 Tecnativa - Víctor Martínez
# Copyright 2020-2025 Tecnativa - Víctor Martínez
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from odoo import api, models

from odoo.addons.hr_holidays.models.hr_leave import DummyAttendance


class HrLeave(models.Model):
_inherit = "hr.leave"

def _compute_date_from_to(self):
"""Call the compute with the corresponding context to be used later in the
_get_attendances() method.
"""
for holiday in self:
holiday = holiday.with_context(
natural_period=bool(
holiday.holiday_status_id.request_unit == "natural_day"
)
)
super(HrLeave, holiday)._compute_date_from_to()
return

def _get_number_of_days(self, date_from, date_to, employee_id):
instance = self.with_context(
natural_period=bool(self.holiday_status_id.request_unit == "natural_day")
Expand All @@ -15,6 +30,32 @@ def _get_number_of_days(self, date_from, date_to, employee_id):
date_from, date_to, employee_id
)

def _get_attendances(self, employee, request_date_from, request_date_to):
"""Overwrite the attendance_to obtained if the leave is natural day,
specifically we define hour_to with the value of attendance_from.hour_from.
Example use case:
attendance_from.hour_from=20:00
attendance_to.hour_to=14:00
This would cause the number of days to be displayed to be incorrect, so "force"
hour_to=20:00 so that the value is correct.
"""
(attendance_from, attendance_to) = super()._get_attendances(
employee, request_date_from, request_date_to
)
if (
self.env.context.get("natural_period")
and attendance_to.hour_to < attendance_from.hour_from
):
attendance_to = DummyAttendance(
attendance_to.hour_from,
attendance_from.hour_from,
attendance_to.dayofweek,
attendance_to.day_period,
attendance_to.week_type,
)
return (attendance_from, attendance_to)

@api.model_create_multi
def create(self, vals_list):
"""Only in UX an incorrect value is set, recalculate.
Expand Down
51 changes: 49 additions & 2 deletions hr_holidays_natural_period/tests/test_hr_leave.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2020-2023 Tecnativa - Víctor Martínez
# Copyright 2020-2025 Tecnativa - Víctor Martínez
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from freezegun import freeze_time

Expand Down Expand Up @@ -77,7 +77,7 @@ def _create_hr_leave(self, leave_type, date_from, date_to):
return leave_form.save()

@users("test-user")
def test_hr_leave_natural_day(self):
def test_hr_leave_natural_day_01(self):
leave_allocation = self._create_leave_allocation(self.leave_type, 5)
leave_allocation.action_confirm()
leave_allocation.sudo().action_validate()
Expand All @@ -92,6 +92,53 @@ def test_hr_leave_natural_day(self):
self.assertEqual(leave.number_of_days, 4.0)
self.assertEqual(leave.number_of_days_display, 4.0)

@users("test-user")
def test_hr_leave_natural_day_02(self):
attendances = [
(0, 16, 21),
(1, 9, 14),
(2, 9, 14),
(3, 9, 14),
(4, 9, 14),
]
calendar = (
self.env["resource.calendar"]
.sudo()
.create(
{
"name": "Test calendar",
"tz": "Europe/Brussels",
"attendance_ids": [
(
0,
0,
{
"name": index,
"dayofweek": str(att[0]),
"hour_from": att[1],
"hour_to": att[2],
},
)
for index, att in enumerate(attendances)
],
}
)
)
self.employee.resource_calendar_id = calendar
leave_allocation = self._create_leave_allocation(self.leave_type, 7)
leave_allocation.action_confirm()
leave_allocation.sudo().action_validate()
res_leave_type = self.env["hr.leave.type"].get_days_all_request()[0][1]
self.assertEqual(res_leave_type["remaining_leaves"], "7")
self.assertEqual(res_leave_type["virtual_remaining_leaves"], "7")
self.assertEqual(res_leave_type["max_leaves"], "7")
self.assertEqual(res_leave_type["leaves_taken"], "0")
self.assertEqual(res_leave_type["virtual_leaves_taken"], "0")
self.assertEqual(res_leave_type["request_unit"], "natural_day")
leave = self._create_hr_leave(self.leave_type, "2023-01-02", "2023-01-08")
self.assertEqual(leave.number_of_days, 7.0)
self.assertEqual(leave.number_of_days_display, 7.0)

@users("test-user")
def test_hr_leave_day(self):
leave_allocation = self._create_leave_allocation(self.leave_type_day, 5)
Expand Down

0 comments on commit 2119995

Please sign in to comment.