From b20d4769e74c742a60fcf119fae79b802c87cffa Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Tue, 10 Sep 2024 17:48:04 +0200 Subject: [PATCH] [IMP] hr_attendance_validation: improve reporting storing compute value for analysis purpose * store existing fields to be used in pivot view * add new field to report compensatory leaves taken --- hr_attendance_validation/README.rst | 9 ++- .../data/hr_leave_type.xml | 6 ++ hr_attendance_validation/i18n/es.po | 22 +++++ hr_attendance_validation/i18n/fr.po | 23 ++++++ .../i18n/hr_attendance_validation.pot | 22 +++++ hr_attendance_validation/i18n/it.po | 22 +++++ .../models/hr_attendance_validation_sheet.py | 81 +++++++++++++------ .../models/hr_leave_type.py | 3 + .../models/res_config_settings.py | 1 + hr_attendance_validation/readme/CONFIGURE.rst | 9 ++- .../static/description/index.html | 21 ++--- .../tests/test_hr_attendance_validation.py | 3 + .../views/hr_attendance_validation.xml | 59 ++++++++++++-- .../views/hr_leave_type.xml | 1 + 14 files changed, 239 insertions(+), 43 deletions(-) create mode 100644 hr_attendance_validation/data/hr_leave_type.xml diff --git a/hr_attendance_validation/README.rst b/hr_attendance_validation/README.rst index ff830afb..45dcdf4a 100644 --- a/hr_attendance_validation/README.rst +++ b/hr_attendance_validation/README.rst @@ -64,9 +64,14 @@ Configuration ============= * Ensure employee weeks are properly set +* Set `is_compensatory` on leave types to: + * reduce domain to select leave type in hr configuration + * to dispatch taken leaves on validation sheet * Set the leave type to use by generating compensatory - hours from attendance review (to be done in hr attendance configuration) -* You can ignore some leaves in validation sheet by ticking the "Ignored in attendance validation" + hours from attendance review (to be done in hr attendance configuration). + We use to create a new type `hr.leave.type` manually each years. +* You can ignore some leaves in validation sheet by ticking the + "Ignored in attendance validation" on holidays `hr.leave.type`` (for instance it can be useful if you manage employee remote days using hr.leave in such case you want to ignore those lines) * once all leaves and attendances has been recorded you can generate leave reviews diff --git a/hr_attendance_validation/data/hr_leave_type.xml b/hr_attendance_validation/data/hr_leave_type.xml new file mode 100644 index 00000000..bf2a1b88 --- /dev/null +++ b/hr_attendance_validation/data/hr_leave_type.xml @@ -0,0 +1,6 @@ + + + + True + + diff --git a/hr_attendance_validation/i18n/es.po b/hr_attendance_validation/i18n/es.po index 48fc9e95..68687b5b 100644 --- a/hr_attendance_validation/i18n/es.po +++ b/hr_attendance_validation/i18n/es.po @@ -141,6 +141,11 @@ msgstr "" "No se puede crear una nueva asistencia para el empleado %s. La asistencia " "para el día de la comprobación en %s ya ha sido revisada y validada." +#. module: hr_attendance_validation +#: model:ir.model.fields,field_description:hr_attendance_validation.field_hr_attendance_validation_sheet__compensatory_leave_hours +msgid "Compensatory Leaves (hours)" +msgstr "" + #. module: hr_attendance_validation #: model:ir.model.fields,field_description:hr_attendance_validation.field_hr_attendance_validation_sheet__compensatory_hour msgid "Compensatory hour" @@ -198,6 +203,11 @@ msgstr "" "Calcular el número de líneas de presencia no marcadas como horas " "extraordinarias" +#. module: hr_attendance_validation +#: model:ir.model.fields,help:hr_attendance_validation.field_hr_attendance_validation_sheet__compensatory_leave_hours +msgid "Compute number of compensatory leaves taken (in hours)" +msgstr "" + #. module: hr_attendance_validation #: model:ir.model.fields,help:hr_attendance_validation.field_hr_attendance_validation_sheet__leave_hours msgid "Compute number of leaves in hours" @@ -291,11 +301,23 @@ msgstr "Horas de la Semana en Curso" msgid "ID" msgstr "ID (identificador)" +#. module: hr_attendance_validation +#: model:ir.model.fields,help:hr_attendance_validation.field_hr_leave_type__is_compensatory +msgid "" +"If check, taken leaves are displayed in hr attendance validation analysis " +"report." +msgstr "" + #. module: hr_attendance_validation #: model:ir.model.fields,field_description:hr_attendance_validation.field_hr_leave_type__ignored_in_attendance_validation msgid "Ignored In Attendance Validation" msgstr "" +#. module: hr_attendance_validation +#: model:ir.model.fields,field_description:hr_attendance_validation.field_hr_leave_type__is_compensatory +msgid "Is Compensatory" +msgstr "" + #. module: hr_attendance_validation #: model:ir.model.fields,field_description:hr_attendance_validation.field_hr_attendance__is_overtime_due msgid "Is overtime due" diff --git a/hr_attendance_validation/i18n/fr.po b/hr_attendance_validation/i18n/fr.po index d1041214..dde7cd84 100644 --- a/hr_attendance_validation/i18n/fr.po +++ b/hr_attendance_validation/i18n/fr.po @@ -139,6 +139,11 @@ msgstr "" "Ne peut pas créer cette ligne de présence (%s, %s) elle est sur une semaine " "déjà validée par le responsable." +#. module: hr_attendance_validation +#: model:ir.model.fields,field_description:hr_attendance_validation.field_hr_attendance_validation_sheet__compensatory_leave_hours +msgid "Compensatory Leaves (hours)" +msgstr "Congés compensatoire pris (heures)" + #. module: hr_attendance_validation #: model:ir.model.fields,field_description:hr_attendance_validation.field_hr_attendance_validation_sheet__compensatory_hour msgid "Compensatory hour" @@ -193,6 +198,11 @@ msgstr "" msgid "Compute number of attendance lines not marked as overtime" msgstr "Nombre d'heure sur plage horaire de travail." +#. module: hr_attendance_validation +#: model:ir.model.fields,help:hr_attendance_validation.field_hr_attendance_validation_sheet__compensatory_leave_hours +msgid "Compute number of compensatory leaves taken (in hours)" +msgstr "Nombre d'heures compensatoires prisent sur la période (en heures)" + #. module: hr_attendance_validation #: model:ir.model.fields,help:hr_attendance_validation.field_hr_attendance_validation_sheet__leave_hours msgid "Compute number of leaves in hours" @@ -287,11 +297,24 @@ msgstr "Heures effectuées cette semaine" msgid "ID" msgstr "" +#. module: hr_attendance_validation +#: model:ir.model.fields,help:hr_attendance_validation.field_hr_leave_type__is_compensatory +msgid "" +"If check, taken leaves are displayed in hr attendance validation analysis " +"report." +msgstr "" +"Si sélectionné, pris en compte dans le total d'heures compensatoire pris." + #. module: hr_attendance_validation #: model:ir.model.fields,field_description:hr_attendance_validation.field_hr_leave_type__ignored_in_attendance_validation msgid "Ignored In Attendance Validation" msgstr "Ignoré dans les feuilles de revue de présences" +#. module: hr_attendance_validation +#: model:ir.model.fields,field_description:hr_attendance_validation.field_hr_leave_type__is_compensatory +msgid "Is Compensatory" +msgstr "Est un type de congés compensatoire" + #. module: hr_attendance_validation #: model:ir.model.fields,field_description:hr_attendance_validation.field_hr_attendance__is_overtime_due msgid "Is overtime due" diff --git a/hr_attendance_validation/i18n/hr_attendance_validation.pot b/hr_attendance_validation/i18n/hr_attendance_validation.pot index 0a688185..c5561bc6 100644 --- a/hr_attendance_validation/i18n/hr_attendance_validation.pot +++ b/hr_attendance_validation/i18n/hr_attendance_validation.pot @@ -125,6 +125,11 @@ msgid "" "check in %s has already been reviewed and validated." msgstr "" +#. module: hr_attendance_validation +#: model:ir.model.fields,field_description:hr_attendance_validation.field_hr_attendance_validation_sheet__compensatory_leave_hours +msgid "Compensatory Leaves (hours)" +msgstr "" + #. module: hr_attendance_validation #: model:ir.model.fields,field_description:hr_attendance_validation.field_hr_attendance_validation_sheet__compensatory_hour msgid "Compensatory hour" @@ -175,6 +180,11 @@ msgstr "" msgid "Compute number of attendance lines not marked as overtime" msgstr "" +#. module: hr_attendance_validation +#: model:ir.model.fields,help:hr_attendance_validation.field_hr_attendance_validation_sheet__compensatory_leave_hours +msgid "Compute number of compensatory leaves taken (in hours)" +msgstr "" + #. module: hr_attendance_validation #: model:ir.model.fields,help:hr_attendance_validation.field_hr_attendance_validation_sheet__leave_hours msgid "Compute number of leaves in hours" @@ -266,11 +276,23 @@ msgstr "" msgid "ID" msgstr "" +#. module: hr_attendance_validation +#: model:ir.model.fields,help:hr_attendance_validation.field_hr_leave_type__is_compensatory +msgid "" +"If check, taken leaves are displayed in hr attendance validation analysis " +"report." +msgstr "" + #. module: hr_attendance_validation #: model:ir.model.fields,field_description:hr_attendance_validation.field_hr_leave_type__ignored_in_attendance_validation msgid "Ignored In Attendance Validation" msgstr "" +#. module: hr_attendance_validation +#: model:ir.model.fields,field_description:hr_attendance_validation.field_hr_leave_type__is_compensatory +msgid "Is Compensatory" +msgstr "" + #. module: hr_attendance_validation #: model:ir.model.fields,field_description:hr_attendance_validation.field_hr_attendance__is_overtime_due msgid "Is overtime due" diff --git a/hr_attendance_validation/i18n/it.po b/hr_attendance_validation/i18n/it.po index 30aec518..f51eebef 100644 --- a/hr_attendance_validation/i18n/it.po +++ b/hr_attendance_validation/i18n/it.po @@ -140,6 +140,11 @@ msgstr "" "Non si può creare una nuova presenza per il dipendente %s. La presenza per " "il giorno di check-in %s è già stata visionata e validata." +#. module: hr_attendance_validation +#: model:ir.model.fields,field_description:hr_attendance_validation.field_hr_attendance_validation_sheet__compensatory_leave_hours +msgid "Compensatory Leaves (hours)" +msgstr "" + #. module: hr_attendance_validation #: model:ir.model.fields,field_description:hr_attendance_validation.field_hr_attendance_validation_sheet__compensatory_hour msgid "Compensatory hour" @@ -194,6 +199,11 @@ msgstr "" msgid "Compute number of attendance lines not marked as overtime" msgstr "Calcola numero di righe presenza non marcate come straordinario" +#. module: hr_attendance_validation +#: model:ir.model.fields,help:hr_attendance_validation.field_hr_attendance_validation_sheet__compensatory_leave_hours +msgid "Compute number of compensatory leaves taken (in hours)" +msgstr "" + #. module: hr_attendance_validation #: model:ir.model.fields,help:hr_attendance_validation.field_hr_attendance_validation_sheet__leave_hours msgid "Compute number of leaves in hours" @@ -287,11 +297,23 @@ msgstr "Ore settimana corrente" msgid "ID" msgstr "ID" +#. module: hr_attendance_validation +#: model:ir.model.fields,help:hr_attendance_validation.field_hr_leave_type__is_compensatory +msgid "" +"If check, taken leaves are displayed in hr attendance validation analysis " +"report." +msgstr "" + #. module: hr_attendance_validation #: model:ir.model.fields,field_description:hr_attendance_validation.field_hr_leave_type__ignored_in_attendance_validation msgid "Ignored In Attendance Validation" msgstr "" +#. module: hr_attendance_validation +#: model:ir.model.fields,field_description:hr_attendance_validation.field_hr_leave_type__is_compensatory +msgid "Is Compensatory" +msgstr "" + #. module: hr_attendance_validation #: model:ir.model.fields,field_description:hr_attendance_validation.field_hr_attendance__is_overtime_due msgid "Is overtime due" diff --git a/hr_attendance_validation/models/hr_attendance_validation_sheet.py b/hr_attendance_validation/models/hr_attendance_validation_sheet.py index 40085e20..c13bea9c 100644 --- a/hr_attendance_validation/models/hr_attendance_validation_sheet.py +++ b/hr_attendance_validation/models/hr_attendance_validation_sheet.py @@ -96,26 +96,38 @@ def name_get(self): leave_hours = fields.Float( "Leaves (hours)", compute="_compute_leaves", + store=True, help="Compute number of leaves in hours", ) + compensatory_leave_hours = fields.Float( + "Compensatory Leaves (hours)", + compute="_compute_leaves", + store=True, + help="Compute number of compensatory leaves taken (in hours)", + ) + attendance_hours = fields.Float( "Attendance (hours)", compute="_compute_attendances_hours", + store=True, help="Compute number of attendance lines not marked as overtime", ) attendance_total_hours = fields.Float( "Total Attendance (hours)", compute="_compute_attendances_hours", + store=True, help="Validated attendances. Sum attendance and due overtime lines.", ) overtime_due_hours = fields.Float( "Overtime due (hours)", compute="_compute_attendances_hours", + store=True, help="Compute number of attendance lines marked as overtime which are marked as due", ) overtime_not_due_hours = fields.Float( "Overtime not due (hours)", compute="_compute_attendances_hours", + store=True, help="Compute number of attendance lines marked as overtime which are not due", ) compensatory_hour = fields.Float( @@ -138,33 +150,51 @@ def _onchange_recompute_lines(self): self.ensure_one() self.require_regeneration = True - @api.depends("leave_ids") - def _compute_leaves(self): - for record in self: - leave_hours = 0 - for leave in record.leave_ids: - if leave.request_unit_half or leave.request_unit_hours: - # we assume time off is recorded by hours - leave_hours += leave.number_of_hours_display - else: - # As far leaves can be record on multiple weeks - # intersect calendar attendance and leaves date - # to compute theoretical leave time - current_date = max(leave.request_date_from, record.date_from) - date_to = min( - leave.request_date_to or leave.request_date_from, record.date_to + def _compute_leaves_fields(self): + self.ensure_one() + + leave_hours = 0 + compensatory_leave_hours = 0 + for leave in self.leave_ids: + if leave.request_unit_half or leave.request_unit_hours: + # we assume time off is recorded by hours + leave_hours += leave.number_of_hours_display + if leave.holiday_status_id.is_compensatory: + compensatory_leave_hours += leave.number_of_hours_display + else: + # As far leaves can be record on multiple weeks + # intersect calendar attendance and leaves date + # to compute theoretical leave time + current_date = max(leave.request_date_from, self.date_from) + date_to = min( + leave.request_date_to or leave.request_date_from, self.date_to + ) + while current_date <= date_to: + current_date_leave_hours = sum( + self.calendar_id.attendance_ids.filtered( + lambda att: int(att.dayofweek) == current_date.weekday() + ).mapped(lambda att: att.hour_to - att.hour_from) ) - while current_date <= date_to: - leave_hours += sum( - record.calendar_id.attendance_ids.filtered( - lambda att: int(att.dayofweek) == current_date.weekday() - ).mapped(lambda att: att.hour_to - att.hour_from) - ) - current_date += timedelta(days=1) + leave_hours += current_date_leave_hours + if leave.holiday_status_id.is_compensatory: + compensatory_leave_hours += current_date_leave_hours + current_date += timedelta(days=1) + return leave_hours, compensatory_leave_hours - record.leave_hours = leave_hours + @api.depends("leave_ids", "leave_ids.holiday_status_id.is_compensatory") + def _compute_leaves(self): + for record in self: + ( + record.leave_hours, + record.compensatory_leave_hours, + ) = record._compute_leaves_fields() - @api.depends("attendance_ids", "attendance_ids.is_overtime") + @api.depends( + "attendance_ids", + "attendance_ids.is_overtime", + "attendance_ids.is_overtime_due", + "attendance_due_ids", + ) def _compute_attendances_hours(self): for record in self: record.attendance_hours = sum( @@ -186,6 +216,9 @@ def _compute_attendances_hours(self): record.attendance_due_ids.mapped("worked_hours") ) + @api.depends( + "attendance_ids", "attendance_ids.is_overtime", "attendance_ids.is_overtime_due" + ) def _compute_attendance_due_ids(self): for record in self: record.attendance_due_ids = record.attendance_ids.filtered( diff --git a/hr_attendance_validation/models/hr_leave_type.py b/hr_attendance_validation/models/hr_leave_type.py index ca426b43..401b8643 100644 --- a/hr_attendance_validation/models/hr_leave_type.py +++ b/hr_attendance_validation/models/hr_leave_type.py @@ -7,3 +7,6 @@ class HrLeaveType(models.Model): _inherit = "hr.leave.type" ignored_in_attendance_validation = fields.Boolean() + is_compensatory = fields.Boolean( + help="If check, taken leaves are displayed in hr attendance validation analysis report." + ) diff --git a/hr_attendance_validation/models/res_config_settings.py b/hr_attendance_validation/models/res_config_settings.py index febcbe72..3676dec7 100644 --- a/hr_attendance_validation/models/res_config_settings.py +++ b/hr_attendance_validation/models/res_config_settings.py @@ -9,6 +9,7 @@ class ResConfigSettings(models.TransientModel): "Overtime compensatory leave type", config_parameter="hr_attendance_validation.leave_type_id", required=True, + domain=[("is_compensatory", "=", "True")], default=lambda self: self.env.ref("hr_holidays.holiday_status_comp"), help="Compensatory leave type used while validate weekly attendance sheet.", ) diff --git a/hr_attendance_validation/readme/CONFIGURE.rst b/hr_attendance_validation/readme/CONFIGURE.rst index a21b9b10..2e4584c3 100644 --- a/hr_attendance_validation/readme/CONFIGURE.rst +++ b/hr_attendance_validation/readme/CONFIGURE.rst @@ -1,7 +1,12 @@ * Ensure employee weeks are properly set +* Set `is_compensatory` on leave types to: + * reduce domain to select leave type in hr configuration + * to dispatch taken leaves on validation sheet * Set the leave type to use by generating compensatory - hours from attendance review (to be done in hr attendance configuration) -* You can ignore some leaves in validation sheet by ticking the "Ignored in attendance validation" + hours from attendance review (to be done in hr attendance configuration). + We use to create a new type `hr.leave.type` manually each years. +* You can ignore some leaves in validation sheet by ticking the + "Ignored in attendance validation" on holidays `hr.leave.type`` (for instance it can be useful if you manage employee remote days using hr.leave in such case you want to ignore those lines) * once all leaves and attendances has been recorded you can generate leave reviews diff --git a/hr_attendance_validation/static/description/index.html b/hr_attendance_validation/static/description/index.html index f72a5a6a..271933fd 100644 --- a/hr_attendance_validation/static/description/index.html +++ b/hr_attendance_validation/static/description/index.html @@ -8,11 +8,10 @@ /* :Author: David Goodger (goodger@python.org) -:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $ +:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z 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 +274,7 @@ margin-left: 2em ; margin-right: 2em } -pre.code .ln { color: gray; } /* line numbers */ +pre.code .ln { color: grey; } /* 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 +300,7 @@ span.pre { white-space: pre } -span.problematic, pre.problematic { +span.problematic { color: red } span.section-subtitle { @@ -412,10 +411,16 @@

Configuration