diff --git a/hr_timesheet_overtime_rate/README.rst b/hr_timesheet_overtime_rate/README.rst
index f0a57bf..ccb27d5 100644
--- a/hr_timesheet_overtime_rate/README.rst
+++ b/hr_timesheet_overtime_rate/README.rst
@@ -39,13 +39,6 @@ At time of writing (2024-06-28), the way a rate is computed for a date is by
looking _exclusively_ at the corresponding day of the week. This should be more
robust.
-Because ``unit_amount`` is computed from ``hours_worked``, this module is not
-compatible with ``hr_timesheet_begin_end``. To make this module subsequently
-compatible with ``hr_timesheet_begin_end``, ``hours_worked`` must be computed
-from ``time_stop`` and ``time_start``, and ``unit_amount`` must use this
-module's computation method instead of ``hr_timesheet_begin_end``'s. The
-compatibility layer should go into its own module.
-
Furthermore, the summary view of timesheet sheets are set read-only in this
module. Because of programming complexities, it is not easy to change this view
to use ``hours_worked`` instead of ``unit_amount``.
diff --git a/hr_timesheet_overtime_rate/readme/ROADMAP.rst b/hr_timesheet_overtime_rate/readme/ROADMAP.rst
index 5885dc0..d84795b 100644
--- a/hr_timesheet_overtime_rate/readme/ROADMAP.rst
+++ b/hr_timesheet_overtime_rate/readme/ROADMAP.rst
@@ -5,13 +5,6 @@ At time of writing (2024-06-28), the way a rate is computed for a date is by
looking _exclusively_ at the corresponding day of the week. This should be more
robust.
-Because ``unit_amount`` is computed from ``hours_worked``, this module is not
-compatible with ``hr_timesheet_begin_end``. To make this module subsequently
-compatible with ``hr_timesheet_begin_end``, ``hours_worked`` must be computed
-from ``time_stop`` and ``time_start``, and ``unit_amount`` must use this
-module's computation method instead of ``hr_timesheet_begin_end``'s. The
-compatibility layer should go into its own module.
-
Furthermore, the summary view of timesheet sheets are set read-only in this
module. Because of programming complexities, it is not easy to change this view
to use ``hours_worked`` instead of ``unit_amount``.
diff --git a/hr_timesheet_overtime_rate/static/description/index.html b/hr_timesheet_overtime_rate/static/description/index.html
index bc923ac..31b5bbd 100644
--- a/hr_timesheet_overtime_rate/static/description/index.html
+++ b/hr_timesheet_overtime_rate/static/description/index.html
@@ -390,12 +390,6 @@
At time of writing (2024-06-28), the way a rate is computed for a date is by
looking _exclusively_ at the corresponding day of the week. This should be more
robust.
-Because unit_amount is computed from hours_worked, this module is not
-compatible with hr_timesheet_begin_end. To make this module subsequently
-compatible with hr_timesheet_begin_end, hours_worked must be computed
-from time_stop and time_start, and unit_amount must use this
-module’s computation method instead of hr_timesheet_begin_end’s. The
-compatibility layer should go into its own module.
Furthermore, the summary view of timesheet sheets are set read-only in this
module. Because of programming complexities, it is not easy to change this view
to use hours_worked instead of unit_amount.
diff --git a/hr_timesheet_overtime_rate_begin_end/README.rst b/hr_timesheet_overtime_rate_begin_end/README.rst
new file mode 100644
index 0000000..286154b
--- /dev/null
+++ b/hr_timesheet_overtime_rate_begin_end/README.rst
@@ -0,0 +1,70 @@
+===========================================================
+Timesheet - Overtime rate and begin/end hours compatibility
+===========================================================
+
+..
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ !! This file is generated by oca-gen-addon-readme !!
+ !! changes will be overwritten. !!
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ !! source digest: sha256:5ab790e671629b45c0297eceb50037e97ab4827da3d637687db534dd0dd0dde0
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
+ :target: https://odoo-community.org/page/development-status
+ :alt: Beta
+.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
+ :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
+ :alt: License: AGPL-3
+.. |badge3| image:: https://img.shields.io/badge/github-coopiteasy%2Fcie--timesheet-lightgray.png?logo=github
+ :target: https://github.com/coopiteasy/cie-timesheet/tree/16.0/hr_timesheet_overtime_rate_begin_end
+ :alt: coopiteasy/cie-timesheet
+
+|badge1| |badge2| |badge3|
+
+Make ``hr_timesheet_overtime_rate`` and ``hr_timesheet_begin_end`` compatible.
+
+**Table of contents**
+
+.. contents::
+ :local:
+
+Bug Tracker
+===========
+
+Bugs are tracked on `GitHub 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 `_.
+
+Do not contact contributors directly about support or help with technical issues.
+
+Credits
+=======
+
+Authors
+~~~~~~~
+
+* Coop IT Easy SC
+
+Contributors
+~~~~~~~~~~~~
+
+* `Coop IT Easy SC `_:
+
+ * Carmen Bianca BAKKER
+
+Maintainers
+~~~~~~~~~~~
+
+.. |maintainer-carmenbianca| image:: https://github.com/carmenbianca.png?size=40px
+ :target: https://github.com/carmenbianca
+ :alt: carmenbianca
+
+Current maintainer:
+
+|maintainer-carmenbianca|
+
+This module is part of the `coopiteasy/cie-timesheet `_ project on GitHub.
+
+You are welcome to contribute.
diff --git a/hr_timesheet_overtime_rate_begin_end/__init__.py b/hr_timesheet_overtime_rate_begin_end/__init__.py
new file mode 100644
index 0000000..3eb7887
--- /dev/null
+++ b/hr_timesheet_overtime_rate_begin_end/__init__.py
@@ -0,0 +1,5 @@
+# SPDX-FileCopyrightText: 2024 Coop IT Easy SC
+#
+# SPDX-License-Identifier: AGPL-3.0-or-later
+
+from . import models
diff --git a/hr_timesheet_overtime_rate_begin_end/__manifest__.py b/hr_timesheet_overtime_rate_begin_end/__manifest__.py
new file mode 100644
index 0000000..5d67310
--- /dev/null
+++ b/hr_timesheet_overtime_rate_begin_end/__manifest__.py
@@ -0,0 +1,20 @@
+# SPDX-FileCopyrightText: 2024 Coop IT Easy SC
+#
+# SPDX-License-Identifier: AGPL-3.0-or-later
+
+{
+ "name": "Timesheet - Overtime rate and begin/end hours compatibility",
+ "summary": "Make ``hr_timesheet_overtime_rate`` and ``hr_timesheet_begin_end`` compatible.",
+ "version": "16.0.1.0.0",
+ "category": "Human Resources",
+ "website": "https://github.com/coopiteasy/cie-timesheet",
+ "author": "Coop IT Easy SC",
+ "maintainers": ["carmenbianca"],
+ "license": "AGPL-3",
+ "application": False,
+ "depends": [
+ "hr_timesheet_overtime_rate",
+ "hr_timesheet_begin_end",
+ ],
+ "auto_install": True,
+}
diff --git a/hr_timesheet_overtime_rate_begin_end/models/__init__.py b/hr_timesheet_overtime_rate_begin_end/models/__init__.py
new file mode 100644
index 0000000..84f4adc
--- /dev/null
+++ b/hr_timesheet_overtime_rate_begin_end/models/__init__.py
@@ -0,0 +1,5 @@
+# SPDX-FileCopyrightText: 2024 Coop IT Easy SC
+#
+# SPDX-License-Identifier: AGPL-3.0-or-later
+
+from . import account_analytic_line
diff --git a/hr_timesheet_overtime_rate_begin_end/models/account_analytic_line.py b/hr_timesheet_overtime_rate_begin_end/models/account_analytic_line.py
new file mode 100644
index 0000000..67d2b96
--- /dev/null
+++ b/hr_timesheet_overtime_rate_begin_end/models/account_analytic_line.py
@@ -0,0 +1,37 @@
+# SPDX-FileCopyrightText: 2024 Coop IT Easy SC
+#
+# SPDX-License-Identifier: AGPL-3.0-or-later
+
+from odoo import api, fields, models
+
+
+class AnalyticLine(models.Model):
+ _inherit = "account.analytic.line"
+
+ hours_worked = fields.Float(
+ store=True,
+ readonly=True,
+ compute="_compute_hours_worked",
+ )
+ unit_amount = fields.Float(
+ # Make sure unit_amount is computed from hours worked, NOT directly from
+ # time_start and time_stop.
+ compute="_compute_unit_amount_from_hours",
+ )
+
+ @api.depends("time_start", "time_stop")
+ def _compute_hours_worked(self):
+ for line in self:
+ line.hours_worked = self._hours_from_start_stop(
+ line.time_start, line.time_stop
+ )
+
+ # Add date to constrains.
+ @api.constrains("time_start", "time_stop", "unit_amount", "date")
+ def _check_time_start_stop(self):
+ return super()._check_time_start_stop()
+
+ def unit_amount_from_start_stop(self):
+ result = super().unit_amount_from_start_stop()
+ result *= self.get_overtime_rate()
+ return result
diff --git a/hr_timesheet_overtime_rate_begin_end/readme/CONTRIBUTORS.rst b/hr_timesheet_overtime_rate_begin_end/readme/CONTRIBUTORS.rst
new file mode 100644
index 0000000..f1ac675
--- /dev/null
+++ b/hr_timesheet_overtime_rate_begin_end/readme/CONTRIBUTORS.rst
@@ -0,0 +1,3 @@
+* `Coop IT Easy SC `_:
+
+ * Carmen Bianca BAKKER
diff --git a/hr_timesheet_overtime_rate_begin_end/readme/DESCRIPTION.rst b/hr_timesheet_overtime_rate_begin_end/readme/DESCRIPTION.rst
new file mode 100644
index 0000000..3ae044d
--- /dev/null
+++ b/hr_timesheet_overtime_rate_begin_end/readme/DESCRIPTION.rst
@@ -0,0 +1 @@
+Make ``hr_timesheet_overtime_rate`` and ``hr_timesheet_begin_end`` compatible.
diff --git a/hr_timesheet_overtime_rate_begin_end/static/description/index.html b/hr_timesheet_overtime_rate_begin_end/static/description/index.html
new file mode 100644
index 0000000..e5fc9bb
--- /dev/null
+++ b/hr_timesheet_overtime_rate_begin_end/static/description/index.html
@@ -0,0 +1,420 @@
+
+
+
+
+
+Timesheet - Overtime rate and begin/end hours compatibility
+
+
+
+
+
Timesheet - Overtime rate and begin/end hours compatibility
+
+
+
+
Make hr_timesheet_overtime_rate and hr_timesheet_begin_end compatible.
+
Table of contents
+
+
+
+
Bugs are tracked on GitHub 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.
+
Do not contact contributors directly about support or help with technical issues.
+
+
+
+
+
+
+
+
Current maintainer:
+
+
This module is part of the coopiteasy/cie-timesheet project on GitHub.
+
You are welcome to contribute.
+
+
+
+
+
diff --git a/hr_timesheet_overtime_rate_begin_end/tests/__init__.py b/hr_timesheet_overtime_rate_begin_end/tests/__init__.py
new file mode 100644
index 0000000..926bcd5
--- /dev/null
+++ b/hr_timesheet_overtime_rate_begin_end/tests/__init__.py
@@ -0,0 +1,5 @@
+# SPDX-FileCopyrightText: 2024 Coop IT Easy SC
+#
+# SPDX-License-Identifier: AGPL-3.0-or-later
+
+from . import test_analytic_line
diff --git a/hr_timesheet_overtime_rate_begin_end/tests/test_analytic_line.py b/hr_timesheet_overtime_rate_begin_end/tests/test_analytic_line.py
new file mode 100644
index 0000000..a736509
--- /dev/null
+++ b/hr_timesheet_overtime_rate_begin_end/tests/test_analytic_line.py
@@ -0,0 +1,78 @@
+# SPDX-FileCopyrightText: 2024 Coop IT Easy SC
+#
+# SPDX-License-Identifier: AGPL-3.0-or-later
+
+from odoo.tests.common import TransactionCase
+
+
+class TestAnalyticLine(TransactionCase):
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass()
+ cls.project = cls.env.ref("project.project_project_1")
+ cls.employee = cls.env.ref("hr.employee_qdp")
+ # I'm not sure what this record does in this context.
+ cls.overtime = cls.env["resource.overtime"].create({"name": "test"})
+ cls.rate = cls.env["resource.overtime.rate"].create(
+ {
+ "name": "test",
+ "dayofweek": "0", # Monday
+ "rate": 2.0,
+ "overtime_id": cls.overtime.id,
+ }
+ )
+
+ def base_line(self):
+ return {
+ "name": "test",
+ "date": "2024-01-01", # Monday
+ "time_start": 10.0,
+ "time_stop": 12.0,
+ "project_id": self.project.id,
+ "employee_id": self.employee.id,
+ }
+
+ def test_rate_applied(self):
+ line = self.base_line()
+ line_record = self.env["account.analytic.line"].create(line)
+ self.assertEqual(line_record.unit_amount, 4.0)
+
+ def test_rate_applied_after_edit(self):
+ line = self.base_line()
+ del line["time_start"]
+ del line["time_stop"]
+ line_record = self.env["account.analytic.line"].create(line)
+ line_record.write({"time_start": 10.0, "time_stop": 12.0})
+ self.assertEqual(line_record.unit_amount, 4.0)
+
+ def test_rate_not_double_applied(self):
+ line = self.base_line()
+ del line["time_start"]
+ del line["time_stop"]
+
+ # Emulating a transient record before it is actually created.
+ line_new = self.env["account.analytic.line"].new(line)
+ line_new.time_start = 10.0
+ line_new.time_stop = 12.0
+ self.assertEqual(line_new.unit_amount, 4.0)
+
+ # Prepare the transient data for writing to a new record.
+ #
+ # Annoyingly, the value for unit_amount is not in _cache, so we have to
+ # add it here.
+ #
+ # Ideally I would emulate this with a Form(), but the necessary fields
+ # are not available in a form. This is the closest emulation.
+ vals = line_new._convert_to_write(line_new._cache)
+ vals.setdefault("unit_amount", line_new.unit_amount)
+ line_record = self.env["account.analytic.line"].create(vals)
+
+ # The rate was already applied on the transient record. Don't also apply
+ # it on creation.
+ self.assertEqual(line_record.unit_amount, 4.0)
+
+ def test_rate_changes_on_date(self):
+ line = self.base_line()
+ line_record = self.env["account.analytic.line"].create(line)
+ line_record.date = "2024-01-02"
+ self.assertEqual(line_record.unit_amount, line_record.hours_worked)
diff --git a/setup/hr_timesheet_overtime_rate_begin_end/odoo/addons/hr_timesheet_overtime_begin_end b/setup/hr_timesheet_overtime_rate_begin_end/odoo/addons/hr_timesheet_overtime_begin_end
new file mode 120000
index 0000000..58ec292
--- /dev/null
+++ b/setup/hr_timesheet_overtime_rate_begin_end/odoo/addons/hr_timesheet_overtime_begin_end
@@ -0,0 +1 @@
+../../../../hr_timesheet_overtime_begin_end
\ No newline at end of file
diff --git a/setup/hr_timesheet_overtime_rate_begin_end/odoo/addons/hr_timesheet_overtime_rate_begin_end b/setup/hr_timesheet_overtime_rate_begin_end/odoo/addons/hr_timesheet_overtime_rate_begin_end
new file mode 120000
index 0000000..348076d
--- /dev/null
+++ b/setup/hr_timesheet_overtime_rate_begin_end/odoo/addons/hr_timesheet_overtime_rate_begin_end
@@ -0,0 +1 @@
+../../../../hr_timesheet_overtime_rate_begin_end
\ No newline at end of file
diff --git a/setup/hr_timesheet_overtime_rate_begin_end/setup.py b/setup/hr_timesheet_overtime_rate_begin_end/setup.py
new file mode 100644
index 0000000..28c57bb
--- /dev/null
+++ b/setup/hr_timesheet_overtime_rate_begin_end/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+ setup_requires=['setuptools-odoo'],
+ odoo_addon=True,
+)