From 4751388d29fa3af9483ef9c48ad8c0cbb9c5b205 Mon Sep 17 00:00:00 2001 From: Abdellatif Benzbiria Date: Wed, 5 Nov 2025 14:37:13 +0100 Subject: [PATCH 1/2] [IMP] timeshet_sheet_confirm_reset : fix fr.po module name --- hr_timesheet_groupby_task_origin/__init__.py | 6 ++ .../__manifest__.py | 43 ++++++++++ hr_timesheet_groupby_task_origin/i18n/fr.po | 70 +++++++++++++++ .../models/__init__.py | 6 ++ .../models/hr_timesheet_sheet.py | 42 +++++++++ .../static/description/icon.png | Bin 0 -> 7982 bytes .../tests/__init__.py | 4 + .../tests/test_hr_timesheet_sheet.py | 80 ++++++++++++++++++ .../views/hr_timesheet_sheet_sheet.xml | 23 +++++ timesheet_sheet_confirm_reset/__manifest__.py | 2 +- timesheet_sheet_confirm_reset/i18n/fr.po | 44 +++++----- 11 files changed, 297 insertions(+), 23 deletions(-) create mode 100644 hr_timesheet_groupby_task_origin/__init__.py create mode 100644 hr_timesheet_groupby_task_origin/__manifest__.py create mode 100644 hr_timesheet_groupby_task_origin/i18n/fr.po create mode 100644 hr_timesheet_groupby_task_origin/models/__init__.py create mode 100644 hr_timesheet_groupby_task_origin/models/hr_timesheet_sheet.py create mode 100644 hr_timesheet_groupby_task_origin/static/description/icon.png create mode 100644 hr_timesheet_groupby_task_origin/tests/__init__.py create mode 100644 hr_timesheet_groupby_task_origin/tests/test_hr_timesheet_sheet.py create mode 100644 hr_timesheet_groupby_task_origin/views/hr_timesheet_sheet_sheet.xml diff --git a/hr_timesheet_groupby_task_origin/__init__.py b/hr_timesheet_groupby_task_origin/__init__.py new file mode 100644 index 0000000..7380332 --- /dev/null +++ b/hr_timesheet_groupby_task_origin/__init__.py @@ -0,0 +1,6 @@ +# Copyright Numigi 2025 (tm) and all its contributors +# (https://numigi.com/r/home) +# License LGPL-3.0 or later +# (http://www.gnu.org/licenses/lgpl). + +from . import models # noqa: F401 diff --git a/hr_timesheet_groupby_task_origin/__manifest__.py b/hr_timesheet_groupby_task_origin/__manifest__.py new file mode 100644 index 0000000..70d0cd2 --- /dev/null +++ b/hr_timesheet_groupby_task_origin/__manifest__.py @@ -0,0 +1,43 @@ +# Copyright Numigi 2025 (tm) and all its contributors +# (https://numigi.com/r/home) +# License LGPL-3.0 or later +# (http://www.gnu.org/licenses/lgpl). + +{ + 'name': 'HR Timesheet Group by Task Origin', + 'version': '14.0.1.0.0', + 'category': 'Human Resources', + 'summary': 'Group timesheet lines by origin task instead of current task', + 'description': """ + HR Timesheet Group by Task Origin + ================================= + + This module fixes the inconsistent task grouping behavior between Accounting + and Project applications for analytic lines. + + Issue: + -------- + - In Accounting app, task grouping uses origin_task_id field + - In Project app (Costs/Revenues), task grouping uses task_id field + - This causes inconsistent grouping results between the two apps + + Solution: + --------- + - Modifies the task grouping in Project app's Costs/Revenues view to use + origin_task_id instead of task_id + - Aligns the grouping behavior with Accounting app + - Ensures consistent analytic reporting across applications + """, + 'author': 'Numigi', + 'website': 'https://www.numigi.com', + 'depends': [ + 'hr_timesheet', + 'project' + ], + 'data': [ + 'views/hr_timesheet_views.xml', + ], + 'installable': True, + 'application': False, + 'license': 'LGPL-3', +} diff --git a/hr_timesheet_groupby_task_origin/i18n/fr.po b/hr_timesheet_groupby_task_origin/i18n/fr.po new file mode 100644 index 0000000..9ed334f --- /dev/null +++ b/hr_timesheet_groupby_task_origin/i18n/fr.po @@ -0,0 +1,70 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * timesheet_confirm_reset +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2025-10-21 18:19+0000\n" +"PO-Revision-Date: 2025-10-21 18:19+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: timesheet_confirm_reset +#: model_terms:ir.ui.view,arch_db:timesheet_confirm_reset.view_hr_timesheet_sheet_form_inherit_submit_confirm +msgid "Are you sure you want to submit this timesheet?" +msgstr "Êtes-vous sûr de vouloir soumettre cette feuille de temps ?" + +#. module: timesheet_confirm_reset +#: model:ir.model.fields,field_description:timesheet_confirm_reset.field_hr_timesheet_sheet__display_name +msgid "Display Name" +msgstr "Nom affiché" + +#. module: timesheet_confirm_reset +#: code:addons/timesheet_confirm_reset/models/hr_timesheet_sheet.py:0 +#, python-format +msgid "Error: You cannot reset a timesheet that has already been approved." +msgstr "Erreur : vous ne pouvez pas remettre en brouillon une feuille de temps déjà approuvée." + +#. module: timesheet_confirm_reset +#: model:ir.model.fields,field_description:timesheet_confirm_reset.field_hr_timesheet_sheet__id +msgid "ID" +msgstr "ID" + +#. module: timesheet_confirm_reset +#: model:ir.model.fields,field_description:timesheet_confirm_reset.field_hr_timesheet_sheet____last_update +msgid "Last Modified on" +msgstr "Dernière modification le" + +#. module: timesheet_confirm_reset +#: model_terms:ir.ui.view,arch_db:timesheet_confirm_reset.view_hr_timesheet_sheet_form_inherit_submit_confirm +msgid "Reset to Draft" +msgstr "Remettre en brouillon" + +#. module: timesheet_confirm_reset +#: code:addons/timesheet_confirm_reset/models/hr_timesheet_sheet.py:0 +#, python-format +msgid "The timesheet is already in draft state." +msgstr "La feuille de temps est déjà en état brouillon." + +#. module: timesheet_confirm_reset +#: model:ir.model,name:timesheet_confirm_reset.model_hr_timesheet_sheet +msgid "Timesheet Sheet" +msgstr "Feuille de présence" + +#. module: timesheet_confirm_reset +#: code:addons/timesheet_confirm_reset/models/hr_timesheet_sheet.py:0 +#, python-format +msgid "Timesheet not found." +msgstr "Feuille de temps introuvable." + +#. module: timesheet_confirm_reset +#: code:addons/timesheet_confirm_reset/models/hr_timesheet_sheet.py:0 +#, python-format +msgid "You can only reset your own timesheets." +msgstr "Vous ne pouvez remettre en brouillon que vos propres feuilles de temps." diff --git a/hr_timesheet_groupby_task_origin/models/__init__.py b/hr_timesheet_groupby_task_origin/models/__init__.py new file mode 100644 index 0000000..2817464 --- /dev/null +++ b/hr_timesheet_groupby_task_origin/models/__init__.py @@ -0,0 +1,6 @@ +# Copyright Numigi 2025 (tm) and all its contributors +# (https://numigi.com/r/home) +# License LGPL-3.0 or later +# (http://www.gnu.org/licenses/lgpl). + +from . import hr_timesheet_sheet # noqa: F401 diff --git a/hr_timesheet_groupby_task_origin/models/hr_timesheet_sheet.py b/hr_timesheet_groupby_task_origin/models/hr_timesheet_sheet.py new file mode 100644 index 0000000..8ea3532 --- /dev/null +++ b/hr_timesheet_groupby_task_origin/models/hr_timesheet_sheet.py @@ -0,0 +1,42 @@ +# Copyright Numigi 2025 (tm) and all its contributors +# (https://numigi.com/r/home) +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +from odoo import models, _ +from odoo.exceptions import UserError + + +class HrTimesheetSheet(models.Model): + _inherit = 'hr_timesheet.sheet' + + def action_confirm_reset(self): + """ + Allow the owner (employee's user) to reset a submitted sheet back + to draft, provided it is not approved. Raises errors if the sheet + is already approved or modified concurrently. + """ + self.ensure_one() + current_uid = self.env.uid + if ( + self.user_id.id != current_uid + and not self.env.user.has_group( + 'hr_timesheet.group_hr_timesheet_user' + ) + ): + raise UserError(_('You can only reset your own timesheets.')) + + timesheet_id = self.with_context( + prefetch_fields=False).sudo().browse(self.id) + if not timesheet_id: + raise UserError(_('Timesheet not found.')) + + if timesheet_id.state == 'done': + raise UserError(_( + 'Error: You cannot reset a timesheet that has already ' + 'been approved.' + )) + + if timesheet_id.state in ('draft', False): + raise UserError(_('The timesheet is already in draft state.')) + + timesheet_id.sudo().write({'state': 'draft'}) diff --git a/hr_timesheet_groupby_task_origin/static/description/icon.png b/hr_timesheet_groupby_task_origin/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..92a86b10ed6e2f6a40b286805c8c92c5dc775111 GIT binary patch literal 7982 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 + + + hr.timesheet.sheet.form.inherit.submit.confirm + hr_timesheet.sheet + + + + + Are you sure you want to submit this timesheet? + + + + +