diff --git a/hr_period_create_timesheet/README.rst b/hr_period_create_timesheet/README.rst index c63a67650..5a7ef3147 100644 --- a/hr_period_create_timesheet/README.rst +++ b/hr_period_create_timesheet/README.rst @@ -7,7 +7,7 @@ HR period create timesheet !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:81e2a29a70c3c038721b45c78c57dfdfcf651eebd84c26efe2d52c5ecf5527c7 + !! source digest: sha256:d626a2ca5abdd5fed3b28c537473d94e09d268e03366d33fc2ee161f68e0bddc !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png diff --git a/hr_period_create_timesheet/__init__.py b/hr_period_create_timesheet/__init__.py index aebfda808..e3a185218 100644 --- a/hr_period_create_timesheet/__init__.py +++ b/hr_period_create_timesheet/__init__.py @@ -2,3 +2,4 @@ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). from . import wizards +from . import models diff --git a/hr_period_create_timesheet/__manifest__.py b/hr_period_create_timesheet/__manifest__.py index 36c989770..035f714fe 100644 --- a/hr_period_create_timesheet/__manifest__.py +++ b/hr_period_create_timesheet/__manifest__.py @@ -15,6 +15,7 @@ "security/ir.model.access.csv", "data/ir_cron.xml", "wizards/hr_period_create_timesheet_view.xml", + "views/res_config_settings.xml", ], "installable": True, } diff --git a/hr_period_create_timesheet/models/__init__.py b/hr_period_create_timesheet/models/__init__.py new file mode 100644 index 000000000..0b150f71c --- /dev/null +++ b/hr_period_create_timesheet/models/__init__.py @@ -0,0 +1,2 @@ +from . import res_company +from . import res_config_settings diff --git a/hr_period_create_timesheet/models/res_company.py b/hr_period_create_timesheet/models/res_company.py new file mode 100644 index 000000000..e4ca53e19 --- /dev/null +++ b/hr_period_create_timesheet/models/res_company.py @@ -0,0 +1,11 @@ +from odoo import fields, models + + +class ResCompany(models.Model): + _inherit = "res.company" + + hr_period_create_months_in_advance = fields.Integer( + string="Months to Create Periods in Advance", + default=1, + help="Defines how many months in advance timesheets should be created for HR periods.", + ) diff --git a/hr_period_create_timesheet/models/res_config_settings.py b/hr_period_create_timesheet/models/res_config_settings.py new file mode 100644 index 000000000..a64f7522c --- /dev/null +++ b/hr_period_create_timesheet/models/res_config_settings.py @@ -0,0 +1,12 @@ +from odoo import fields, models + + +class ResConfigSettings(models.TransientModel): + _inherit = "res.config.settings" + + hr_period_create_months_in_advance = fields.Integer( + string="Months to Create Periods in Advance", + related="company_id.hr_period_create_months_in_advance", + readonly=False, + help="Defines how many months in advance timesheets should be created for HR periods.", + ) diff --git a/hr_period_create_timesheet/static/description/index.html b/hr_period_create_timesheet/static/description/index.html index 07589a136..6dbe70564 100644 --- a/hr_period_create_timesheet/static/description/index.html +++ b/hr_period_create_timesheet/static/description/index.html @@ -9,10 +9,11 @@ /* :Author: David Goodger (goodger@python.org) -:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $ +:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $ :Copyright: This stylesheet has been placed in the public domain. Default cascading style sheet for the HTML output of Docutils. +Despite the name, some widely supported CSS2 features are used. See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to customize this style sheet. @@ -275,7 +276,7 @@ margin-left: 2em ; margin-right: 2em } -pre.code .ln { color: grey; } /* line numbers */ +pre.code .ln { color: gray; } /* line numbers */ pre.code, code { background-color: #eeeeee } pre.code .comment, code .comment { color: #5C6576 } pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold } @@ -301,7 +302,7 @@ span.pre { white-space: pre } -span.problematic { +span.problematic, pre.problematic { color: red } span.section-subtitle { @@ -367,7 +368,7 @@

HR period create timesheet

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:81e2a29a70c3c038721b45c78c57dfdfcf651eebd84c26efe2d52c5ecf5527c7 +!! source digest: sha256:d626a2ca5abdd5fed3b28c537473d94e09d268e03366d33fc2ee161f68e0bddc !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

Beta License: AGPL-3 OCA/timesheet Translate me on Weblate Try me on Runboat

This module prepare the timesheets for all the periods created for all @@ -423,7 +424,9 @@

Contributors

Maintainers

This module is maintained by the OCA.

-Odoo Community Association + +Odoo Community Association +

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.

diff --git a/hr_period_create_timesheet/tests/test_hr_period_create_timesheet.py b/hr_period_create_timesheet/tests/test_hr_period_create_timesheet.py index 589ecd42f..67a6efbb0 100644 --- a/hr_period_create_timesheet/tests/test_hr_period_create_timesheet.py +++ b/hr_period_create_timesheet/tests/test_hr_period_create_timesheet.py @@ -28,6 +28,7 @@ def setUp(self): self.dept_1 = self.env.ref("hr.dep_rd") self.dept.write({"parent_id": self.root.id}) self.company_id = self.env.user.company_id + self.company_id.hr_period_create_months_in_advance = 12 self.type = self.create_data_range_type("test_hr_period") self.vals = { diff --git a/hr_period_create_timesheet/views/res_config_settings.xml b/hr_period_create_timesheet/views/res_config_settings.xml new file mode 100644 index 000000000..78b3bf433 --- /dev/null +++ b/hr_period_create_timesheet/views/res_config_settings.xml @@ -0,0 +1,42 @@ + + + res.config.settings.view.form.hr.period + res.config.settings + + + + +

HR Period Settings

+
+
+
+
+
+
+
+
+
+
diff --git a/hr_period_create_timesheet/wizards/hr_period_create_timesheet.py b/hr_period_create_timesheet/wizards/hr_period_create_timesheet.py index 5e524dc03..04a957d06 100644 --- a/hr_period_create_timesheet/wizards/hr_period_create_timesheet.py +++ b/hr_period_create_timesheet/wizards/hr_period_create_timesheet.py @@ -1,6 +1,8 @@ # Copyright 2023 ForgeFlow S.L. # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). +from dateutil.relativedelta import relativedelta + from odoo import _, api, fields, models from odoo.exceptions import ValidationError @@ -93,25 +95,46 @@ def compute(self): def create_timesheets_on_future_periods(self): timesheet_obj = self.env["hr_timesheet.sheet"] today = fields.Date.today() - periods = self.env["hr.period"].search([("date_end", ">=", today)]) + + # Search for employees who have a user and a valid contract employees = self.env["hr.employee"].search( [("user_id", "!=", False), ("contract_id.date_start", "<=", today)] ) - if not periods or not employees: + if not employees: return + # Create a dictionary to store existing timesheets per employee existing_timesheets = {} - timesheet_domain = [ - ("employee_id", "in", employees.ids), - ("date_start", "<=", max(periods.mapped("date_end"))), - ("date_end", ">=", min(periods.mapped("date_start"))), - ] - for timesheet in timesheet_obj.search(timesheet_domain): - key = (timesheet.employee_id.id, timesheet.date_start, timesheet.date_end) - existing_timesheets[key] = timesheet - - for hr_period in periods: - for employee in employees: + for employee in employees: + # Get the company configuration for months in advance + months_in_advance = ( + employee.company_id.hr_period_create_months_in_advance or 1 + ) + advance_date_limit = today + relativedelta(months=months_in_advance) + + # Search for periods within the allowed range for this employee's company + periods = self.env["hr.period"].search( + [("date_end", ">=", today), ("date_end", "<=", advance_date_limit)] + ) + if not periods: + continue + + # Find existing timesheets for this employee + timesheet_domain = [ + ("employee_id", "=", employee.id), + ("date_start", "<=", max(periods.mapped("date_end"))), + ("date_end", ">=", min(periods.mapped("date_start"))), + ] + for timesheet in timesheet_obj.search(timesheet_domain): + key = ( + timesheet.employee_id.id, + timesheet.date_start, + timesheet.date_end, + ) + existing_timesheets[key] = timesheet + + # Create timesheets for missing periods + for hr_period in periods: key = (employee.id, hr_period.date_start, hr_period.date_end) if key not in existing_timesheets: ts_data = self._prepare_timesheet(employee, hr_period)