Skip to content

Commit

Permalink
[MIG] hr_holidays_leave_repeated: Migration to 16.0
Browse files Browse the repository at this point in the history
  • Loading branch information
remi-filament committed Dec 26, 2024
1 parent 1cbd60d commit 1d70189
Show file tree
Hide file tree
Showing 11 changed files with 239 additions and 184 deletions.
14 changes: 9 additions & 5 deletions hr_holidays_leave_repeated/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ HR Holidays leave repeated
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fhr--holidays-lightgray.png?logo=github
:target: https://github.com/OCA/hr-holidays/tree/14.0/hr_holidays_leave_repeated
:target: https://github.com/OCA/hr-holidays/tree/16.0/hr_holidays_leave_repeated
:alt: OCA/hr-holidays
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/hr-holidays-14-0/hr-holidays-14-0-hr_holidays_leave_repeated
:target: https://translation.odoo-community.org/projects/hr-holidays-16-0/hr-holidays-16-0-hr_holidays_leave_repeated
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/hr-holidays&target_branch=14.0
:target: https://runboat.odoo-community.org/builds?repo=OCA/hr-holidays&target_branch=16.0
:alt: Try me on Runboat

|badge1| |badge2| |badge3| |badge4| |badge5|
Expand All @@ -48,13 +48,15 @@ Usage
#. Alternatively set the 'Repeat Mode' field to 'End Date', then set 'Repeat Every' and 'Repeat End Date'.
#. Create (save) the leave request. All the periodical leave requests are automatically created.

Note for HR Time Off responsibles : creating repeated leaves can only be used when selecting Mode = "By Employee" and that all selected employees should share the same resource calendar, otherwise an error is raised.

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/OCA/hr-holidays/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/OCA/hr-holidays/issues/new?body=module:%20hr_holidays_leave_repeated%0Aversion:%2014.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
`feedback <https://github.com/OCA/hr-holidays/issues/new?body=module:%20hr_holidays_leave_repeated%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

Do not contact contributors directly about support or help with technical issues.

Expand All @@ -64,6 +66,7 @@ Credits
Authors
~~~~~~~

* Le Filament
* Onestein

Contributors
Expand All @@ -72,6 +75,7 @@ Contributors
* Andrea Stirpe <[email protected]>
* Hieu, Vo Minh Bao <[email protected]>
* Italo LOPES <[email protected]>
* Rémi - Le Filament <https://le-filament.com>

Maintainers
~~~~~~~~~~~
Expand All @@ -86,6 +90,6 @@ OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.

This module is part of the `OCA/hr-holidays <https://github.com/OCA/hr-holidays/tree/14.0/hr_holidays_leave_repeated>`_ project on GitHub.
This module is part of the `OCA/hr-holidays <https://github.com/OCA/hr-holidays/tree/16.0/hr_holidays_leave_repeated>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
4 changes: 2 additions & 2 deletions hr_holidays_leave_repeated/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
{
"name": "HR Holidays leave repeated",
"summary": "Define periodical leaves",
"author": "Onestein, Odoo Community Association (OCA)",
"author": "Le Filament, Onestein, Odoo Community Association (OCA)",
"website": "https://github.com/OCA/hr-holidays",
"category": "Human Resources",
"version": "14.0.1.1.0",
"version": "16.0.1.1.0",
"license": "AGPL-3",
"depends": ["hr_holidays"],
"data": ["views/hr_leave_type.xml", "views/hr_leave.xml"],
Expand Down
14 changes: 4 additions & 10 deletions hr_holidays_leave_repeated/i18n/fr.po
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ msgstr "Veuillez définir un nombre de répétitions positif."
#: model:ir.model.fields,field_description:hr_holidays_leave_repeated.field_hr_leave__holiday_type_repeat
#: model:ir.model.fields,field_description:hr_holidays_leave_repeated.field_hr_leave_type__repeat
msgid "Repeat"
msgstr "Répeter"
msgstr "Répéter"

#. module: hr_holidays_leave_repeated
#: model:ir.model.fields,field_description:hr_holidays_leave_repeated.field_hr_leave__repeat_limit
Expand All @@ -84,7 +84,7 @@ msgstr "Répéter # fois"
#. module: hr_holidays_leave_repeated
#: model:ir.model.fields,field_description:hr_holidays_leave_repeated.field_hr_leave__repeat_end_date
msgid "Repeat End Date"
msgstr "Répéter la date de fin"
msgstr "Date de fin de répétition"

#. module: hr_holidays_leave_repeated
#: model:ir.model.fields,field_description:hr_holidays_leave_repeated.field_hr_leave__repeat_every
Expand Down Expand Up @@ -145,15 +145,9 @@ msgstr ""
#. module: hr_holidays_leave_repeated
#: model:ir.model,name:hr_holidays_leave_repeated.model_hr_leave
msgid "Time Off"
msgstr ""
msgstr "Congés"

#. module: hr_holidays_leave_repeated
#: model:ir.model,name:hr_holidays_leave_repeated.model_hr_leave_type
msgid "Time Off Type"
msgstr ""

#~ msgid "Leave"
#~ msgstr "Congé"

#~ msgid "Leave Type"
#~ msgstr "Type de congé"
msgstr "Type de congés"
10 changes: 2 additions & 8 deletions hr_holidays_leave_repeated/i18n/nl.po
Original file line number Diff line number Diff line change
Expand Up @@ -146,15 +146,9 @@ msgstr ""
#. module: hr_holidays_leave_repeated
#: model:ir.model,name:hr_holidays_leave_repeated.model_hr_leave
msgid "Time Off"
msgstr ""
msgstr "Verlof"

#. module: hr_holidays_leave_repeated
#: model:ir.model,name:hr_holidays_leave_repeated.model_hr_leave_type
msgid "Time Off Type"
msgstr ""

#~ msgid "Leave"
#~ msgstr "Verlof"

#~ msgid "Leave Type"
#~ msgstr "Verlofsoort"
msgstr "Verlofsoort"
105 changes: 62 additions & 43 deletions hr_holidays_leave_repeated/models/hr_leave.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Copyright 2016-2019 Onestein (<https://www.onestein.eu>)
# Copyright 2024- Le Filament (https://le-filament.com)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from dateutil.relativedelta import relativedelta
from pytz import utc

from odoo import _, api, fields, models
from odoo.exceptions import UserError, ValidationError
Expand All @@ -26,30 +28,26 @@ class HrLeave(models.Model):
repeat_end_date = fields.Date(default=lambda self: fields.Date.today())

@api.model
def _update_repeated_workday_dates(self, employee, from_dt, to_dt, days):
def _update_repeated_workday_dates(self, resource_calendar, from_dt, to_dt, days):
user = self.env.user
calendar = employee.resource_calendar_id
orig_from_dt = fields.Datetime.context_timestamp(user, from_dt)
orig_to_dt = fields.Datetime.context_timestamp(user, to_dt)
work_hours = calendar.get_work_hours_count(from_dt, to_dt, compute_leaves=False)
from_dt = fields.Datetime.context_timestamp(user, from_dt)
to_dt = fields.Datetime.context_timestamp(user, to_dt)
work_hours = resource_calendar.get_work_hours_count(
from_dt, to_dt, compute_leaves=False
)
while work_hours:
from_dt = from_dt + relativedelta(days=days)
to_dt = to_dt + relativedelta(days=days)

new_work_hours = calendar.get_work_hours_count(
new_work_hours = resource_calendar.get_work_hours_count(
from_dt, to_dt, compute_leaves=True
)
if new_work_hours and work_hours <= new_work_hours:
break

user_from_dt = fields.Datetime.context_timestamp(user, from_dt)
user_to_dt = fields.Datetime.context_timestamp(user, to_dt)
from_dt = from_dt - user_from_dt.tzinfo._utcoffset
from_dt = from_dt + orig_from_dt.tzinfo._utcoffset
to_dt = to_dt - user_to_dt.tzinfo._utcoffset
to_dt = to_dt + orig_to_dt.tzinfo._utcoffset

return from_dt, to_dt
return from_dt.astimezone(utc).replace(tzinfo=None), to_dt.astimezone(
utc
).replace(tzinfo=None)

@api.model
def _get_repeated_vals_dict(self):
Expand Down Expand Up @@ -85,55 +83,76 @@ def _get_repeated_vals_dict(self):
}

@api.model
def _update_repeated_leave_vals(self, vals, employee):
def _update_repeated_leave_vals(self, leave, resource_calendar):
vals_dict = self._get_repeated_vals_dict()
param_dict = vals_dict[vals.get("repeat_every")]
from_dt = fields.Datetime.from_string(vals.get("date_from"))
to_dt = fields.Datetime.from_string(vals.get("date_to"))
end_date = fields.Datetime.from_string(vals.get("repeat_end_date"))
param_dict = vals_dict[leave.repeat_every]
from_dt = fields.Datetime.from_string(leave.date_from)
to_dt = fields.Datetime.from_string(leave.date_to)

if (to_dt - from_dt).days > param_dict["days"]:
raise UserError(param_dict["user_error_msg"])

from_dt, to_dt = self._update_repeated_workday_dates(
employee, from_dt, to_dt, param_dict["days"]
resource_calendar, from_dt, to_dt, param_dict["days"]
)

vals["request_date_from"] = vals["date_from"] = from_dt
vals["request_date_to"] = vals["date_to"] = to_dt
vals["repeat_end_date"] = end_date
return vals
return {
"employee_ids": [(6, 0, leave.employee_ids.ids)],
"date_from": from_dt,
"date_to": to_dt,
"multi_employee": leave.multi_employee,
}

@api.model
def create_repeated_handler(self, vals, employee):
def _check_repeating(count, vals):
repeat_mode = vals.get("repeat_mode", "times")
if repeat_mode == "times" and count < vals.get("repeat_limit", 0):
def create_repeated_handler(self, leave, resource_calendar):
def _check_repeating(count, leave):
repeat_mode = leave.repeat_mode
if repeat_mode == "times" and count < leave.repeat_limit:
return True
repeat_end_date = vals.get("repeat_end_date", fields.Date.today())
if repeat_mode == "date" and vals["date_to"] <= repeat_end_date:
repeat_end_date = leave.repeat_end_date
if repeat_mode == "date" and leave.date_to <= repeat_end_date:
return True

Check warning on line 114 in hr_holidays_leave_repeated/models/hr_leave.py

View check run for this annotation

Codecov / codecov/patch

hr_holidays_leave_repeated/models/hr_leave.py#L114

Added line #L114 was not covered by tests
return False

count = 1
vals = self._update_repeated_leave_vals(vals, employee)
while _check_repeating(count, vals):
self.with_context(skip_create_handler=True).create(vals)
vals = self._update_repeated_leave_vals(leave, resource_calendar)
while _check_repeating(count, leave):
leave = leave.with_context(skip_create_handler=True).copy(vals)
count += 1
vals = self._update_repeated_leave_vals(vals, employee)
vals = self._update_repeated_leave_vals(leave, resource_calendar)

@api.model
def create(self, vals):
res = super().create(vals)
@api.model_create_multi
def create(self, vals_list):
res = super().create(vals_list)
skip_create_handler = self.env.context.get("skip_create_handler")
all_vals_set = vals.get("repeat_every") and vals.get("repeat_mode")
if not skip_create_handler and all_vals_set:
employee = self.env["hr.employee"].browse(vals.get("employee_id"))
if employee.resource_calendar_id:
self.create_repeated_handler(vals, employee)
if skip_create_handler:
return res
for leave in res.filtered(
lambda leave: leave.repeat_every
and leave.repeat_mode
and leave.holiday_type == "employee"
):
employees = leave.employee_ids
resource_calendars = employees.mapped("resource_calendar_id")
if len(resource_calendars) == 1:
self.create_repeated_handler(leave, resource_calendars[0])
elif len(resource_calendars) == 0:
raise ValidationError(
_(
"Please define resource calendar on employee(s) in order "
"to compute repeated leaves."
)
)
else:
raise ValidationError(

Check warning on line 147 in hr_holidays_leave_repeated/models/hr_leave.py

View check run for this annotation

Codecov / codecov/patch

hr_holidays_leave_repeated/models/hr_leave.py#L147

Added line #L147 was not covered by tests
_(
"Creating leaves for multiple employees with different "
"resource calendar is not supported."
)
)
return res

@api.constrains("repeat_limit", "repeat_end_date")
@api.constrains("repeat_mode", "repeat_limit", "repeat_end_date")
def _check_repeat_limit(self):
for record in self:
if record.repeat_mode == "times" and record.repeat_limit < 0:
Expand Down
1 change: 1 addition & 0 deletions hr_holidays_leave_repeated/readme/CONTRIBUTORS.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
* Andrea Stirpe <[email protected]>
* Hieu, Vo Minh Bao <[email protected]>
* Italo LOPES <[email protected]>
* Rémi - Le Filament <https://le-filament.com>
2 changes: 2 additions & 0 deletions hr_holidays_leave_repeated/readme/USAGE.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
#. Set the 'Repeat Mode' field to 'Number of Times'. Set the proper values for 'Repeat Every' and 'Repeat # times'.
#. Alternatively set the 'Repeat Mode' field to 'End Date', then set 'Repeat Every' and 'Repeat End Date'.
#. Create (save) the leave request. All the periodical leave requests are automatically created.

Note for HR Time Off responsibles : creating repeated leaves can only be used when selecting Mode = "By Employee" and that all selected employees should share the same resource calendar, otherwise an error is raised.
Loading

0 comments on commit 1d70189

Please sign in to comment.