diff --git a/hr_holidays_auto_extend/README.rst b/hr_holidays_auto_extend/README.rst
new file mode 100644
index 00000000..f8dd328c
--- /dev/null
+++ b/hr_holidays_auto_extend/README.rst
@@ -0,0 +1,9 @@
+.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
+ :target: https://www.gnu.org/licenses/agpl-3.0-standalone.html
+ :alt: License: AGPL-3
+
+=======================
+Hr Holidays Auto Extend
+=======================
+
+Allow to extend some kind of holidays
diff --git a/hr_holidays_auto_extend/__init__.py b/hr_holidays_auto_extend/__init__.py
new file mode 100644
index 00000000..0650744f
--- /dev/null
+++ b/hr_holidays_auto_extend/__init__.py
@@ -0,0 +1 @@
+from . import models
diff --git a/hr_holidays_auto_extend/__manifest__.py b/hr_holidays_auto_extend/__manifest__.py
new file mode 100644
index 00000000..58595971
--- /dev/null
+++ b/hr_holidays_auto_extend/__manifest__.py
@@ -0,0 +1,21 @@
+# Copyright 2023 CreuBlanca
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+
+{
+ "name": "Hr Holidays Auto Extend",
+ "summary": """
+ Allow to extend some kind of holidays""",
+ "version": "14.0.1.0.0",
+ "license": "AGPL-3",
+ "author": "CreuBlanca,Odoo Community Association (OCA)",
+ "website": "https://github.com/OCA/hr-holidays",
+ "depends": [
+ "hr_holidays",
+ ],
+ "data": [
+ "views/hr_leave.xml",
+ "views/hr_leave_type.xml",
+ "data/cron.xml",
+ ],
+ "demo": [],
+}
diff --git a/hr_holidays_auto_extend/data/cron.xml b/hr_holidays_auto_extend/data/cron.xml
new file mode 100644
index 00000000..42a4e3f9
--- /dev/null
+++ b/hr_holidays_auto_extend/data/cron.xml
@@ -0,0 +1,13 @@
+
+
+
+ Holidays: Auto extend
+
+ 1
+ days
+ -1
+
+ code
+ model._cron_auto_extend()
+
+
diff --git a/hr_holidays_auto_extend/models/__init__.py b/hr_holidays_auto_extend/models/__init__.py
new file mode 100644
index 00000000..7c444ff5
--- /dev/null
+++ b/hr_holidays_auto_extend/models/__init__.py
@@ -0,0 +1,2 @@
+from . import hr_leave_type
+from . import hr_leave
diff --git a/hr_holidays_auto_extend/models/hr_leave.py b/hr_holidays_auto_extend/models/hr_leave.py
new file mode 100644
index 00000000..7a302309
--- /dev/null
+++ b/hr_holidays_auto_extend/models/hr_leave.py
@@ -0,0 +1,65 @@
+# Copyright 2023 CreuBlanca
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+
+from datetime import timedelta
+
+from odoo import api, fields, models
+
+
+class HrLeave(models.Model):
+ _inherit = "hr.leave"
+
+ auto_extend_type = fields.Boolean(
+ related="holiday_status_id.auto_extend", string="Auto extend type"
+ )
+ auto_extend = fields.Boolean(
+ compute="_compute_auto_extend", store=True, readonly=False
+ )
+ auto_extend_period = fields.Integer(
+ compute="_compute_auto_extend", store=True, readonly=False
+ )
+
+ def _check_date_state(self):
+ if not self.env.context.get("__no_check_state_date"):
+ super()._check_date_state()
+
+ def _get_number_of_days(self, date_from, date_to, employee_id):
+ """Returns a float equals to the timedelta between two dates given as string.
+ We need to modify in order to add the compute_leaves = False
+ """
+ if not self.env.context.get("__no_check_state_date") or not employee_id:
+ return super()._get_number_of_days(date_from, date_to, employee_id)
+ employee = self.env["hr.employee"].browse(employee_id)
+ return employee._get_work_days_data_batch(
+ date_from, date_to, compute_leaves=False
+ )[employee.id]
+
+ @api.depends("holiday_status_id")
+ def _compute_auto_extend(self):
+ for record in self:
+ record.auto_extend = record.holiday_status_id.auto_extend
+ record.auto_extend_period = record.holiday_status_id.auto_extend_period
+
+ def _cron_auto_extend_domain(self):
+ return [
+ ("request_date_to", "<=", fields.Date.today()),
+ ("auto_extend", "=", True),
+ ("auto_extend_period", ">", 0),
+ ("state", "=", "validate"),
+ ]
+
+ def _cron_auto_extend(self):
+ leaves = self.search(self._cron_auto_extend_domain())
+ for leave in leaves.with_context(__no_check_state_date=True):
+ vals = {
+ "request_date_to": leave.request_date_to
+ + timedelta(days=leave.auto_extend_period)
+ }
+ vals.update(
+ leave.onchange(vals, ["request_date_to"], leave._onchange_spec())[
+ "value"
+ ]
+ )
+ leave.write(vals)
+ leave._remove_resource_leave()
+ leave._create_resource_leave()
diff --git a/hr_holidays_auto_extend/models/hr_leave_type.py b/hr_holidays_auto_extend/models/hr_leave_type.py
new file mode 100644
index 00000000..0fed4e25
--- /dev/null
+++ b/hr_holidays_auto_extend/models/hr_leave_type.py
@@ -0,0 +1,11 @@
+# Copyright 2023 CreuBlanca
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+
+from odoo import fields, models
+
+
+class HrLeaveType(models.Model):
+ _inherit = "hr.leave.type"
+
+ auto_extend = fields.Boolean()
+ auto_extend_period = fields.Integer(default=7)
diff --git a/hr_holidays_auto_extend/readme/CONTRIBUTORS.rst b/hr_holidays_auto_extend/readme/CONTRIBUTORS.rst
new file mode 100644
index 00000000..e084beee
--- /dev/null
+++ b/hr_holidays_auto_extend/readme/CONTRIBUTORS.rst
@@ -0,0 +1,2 @@
+* Enric Tobella
+*
diff --git a/hr_holidays_auto_extend/readme/DESCRIPTION.rst b/hr_holidays_auto_extend/readme/DESCRIPTION.rst
new file mode 100644
index 00000000..2d631369
--- /dev/null
+++ b/hr_holidays_auto_extend/readme/DESCRIPTION.rst
@@ -0,0 +1,3 @@
+With this module, we will be able to extend automatically a leave when the period is reached.
+
+This might be necessary for leaves without a clear return date for the employee.
diff --git a/hr_holidays_auto_extend/readme/USAGE.rst b/hr_holidays_auto_extend/readme/USAGE.rst
new file mode 100644
index 00000000..b4d00c1e
--- /dev/null
+++ b/hr_holidays_auto_extend/readme/USAGE.rst
@@ -0,0 +1,4 @@
+* Access leave types and mark it as "Auto extendable"
+* When the manager approves the leave, the "Auto extendable" check will be marked
+* When we decide that the leave is no longer extendable, we can uncheck it.
+*
diff --git a/hr_holidays_auto_extend/static/description/icon.png b/hr_holidays_auto_extend/static/description/icon.png
new file mode 100644
index 00000000..3a0328b5
Binary files /dev/null and b/hr_holidays_auto_extend/static/description/icon.png differ
diff --git a/hr_holidays_auto_extend/tests/__init__.py b/hr_holidays_auto_extend/tests/__init__.py
new file mode 100644
index 00000000..18ea4c09
--- /dev/null
+++ b/hr_holidays_auto_extend/tests/__init__.py
@@ -0,0 +1 @@
+from . import test_extend
diff --git a/hr_holidays_auto_extend/tests/test_extend.py b/hr_holidays_auto_extend/tests/test_extend.py
new file mode 100644
index 00000000..d177eb24
--- /dev/null
+++ b/hr_holidays_auto_extend/tests/test_extend.py
@@ -0,0 +1,45 @@
+# Copyright 2023 CreuBlanca
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+
+from datetime import timedelta
+
+from odoo import fields
+
+from odoo.addons.hr_holidays.tests.common import TestHrHolidaysCommon
+
+
+class TestExtend(TestHrHolidaysCommon):
+ def test_time_type(self):
+ leave_type = self.env["hr.leave.type"].create(
+ {
+ "name": "Paid Time Off",
+ "time_type": "leave",
+ "auto_extend": True,
+ "allocation_type": "no",
+ "validity_start": False,
+ }
+ )
+ date_to = fields.Date.today() - timedelta(days=2)
+ leave_1 = self.env["hr.leave"].create(
+ {
+ "name": "Doctor Appointment",
+ "employee_id": self.employee_hruser_id,
+ "holiday_status_id": leave_type.id,
+ "request_date_from": (fields.Date.today() - timedelta(days=5)),
+ "request_date_to": date_to,
+ "number_of_days": 1,
+ }
+ )
+ self.assertEqual(leave_1.request_date_to, date_to)
+ self.env["hr.leave"]._cron_auto_extend()
+ self.assertEqual(leave_1.request_date_to, date_to)
+ leave_1.action_approve()
+ self.assertEqual(leave_1.request_date_to, date_to)
+ self.assertEqual(
+ self.env["resource.calendar.leaves"]
+ .search([("holiday_id", "=", leave_1.id)])
+ .time_type,
+ "leave",
+ )
+ self.env["hr.leave"]._cron_auto_extend()
+ self.assertEqual(leave_1.request_date_to, date_to + timedelta(days=7))
diff --git a/hr_holidays_auto_extend/views/hr_leave.xml b/hr_holidays_auto_extend/views/hr_leave.xml
new file mode 100644
index 00000000..01eb3068
--- /dev/null
+++ b/hr_holidays_auto_extend/views/hr_leave.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+ hr.leave.form (in hr_holidays_auto_extend)
+ hr.leave
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/hr_holidays_auto_extend/views/hr_leave_type.xml b/hr_holidays_auto_extend/views/hr_leave_type.xml
new file mode 100644
index 00000000..a2678d60
--- /dev/null
+++ b/hr_holidays_auto_extend/views/hr_leave_type.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+ hr.leave.type.form (in hr_holidays_auto_extend)
+ hr.leave.type
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/setup/hr_holidays_auto_extend/odoo/addons/hr_holidays_auto_extend b/setup/hr_holidays_auto_extend/odoo/addons/hr_holidays_auto_extend
new file mode 120000
index 00000000..b8c1a9c0
--- /dev/null
+++ b/setup/hr_holidays_auto_extend/odoo/addons/hr_holidays_auto_extend
@@ -0,0 +1 @@
+../../../../hr_holidays_auto_extend
\ No newline at end of file
diff --git a/setup/hr_holidays_auto_extend/setup.py b/setup/hr_holidays_auto_extend/setup.py
new file mode 100644
index 00000000..28c57bb6
--- /dev/null
+++ b/setup/hr_holidays_auto_extend/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+ setup_requires=['setuptools-odoo'],
+ odoo_addon=True,
+)