diff --git a/README.md b/README.md index d9b93dcc98d..a0495b84d6f 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,7 @@ addon | version | maintainers | summary [hr_employee_service_contract](hr_employee_service_contract/) | 16.0.1.0.0 | | Employee service information & duration based on employee's contracts [hr_employee_ssn](hr_employee_ssn/) | 16.0.1.0.0 | | View/edit employee's SSN & SIN fields [hr_holidays_team_manager](hr_holidays_team_manager/) | 16.0.1.0.0 | | HR Holidays Team Manager +[hr_job_category](hr_job_category/) | 16.0.1.0.0 | | Adds tags to employee through contract and job position [hr_personal_equipment_request](hr_personal_equipment_request/) | 16.0.1.0.0 | | This addon allows to manage employee personal equipment [hr_personal_equipment_request_tier_validation](hr_personal_equipment_request_tier_validation/) | 16.0.1.0.0 | | Enables tier validation from hr.personal.equipment.request [hr_personal_equipment_stock](hr_personal_equipment_stock/) | 16.0.1.0.0 | | This addon allows to integrate hr_personal_equipment_request with stock diff --git a/hr_employee_service/tests/test_hr_employee_service.py b/hr_employee_service/tests/test_hr_employee_service.py index bdb0f61a2bf..8b02b36d545 100644 --- a/hr_employee_service/tests/test_hr_employee_service.py +++ b/hr_employee_service/tests/test_hr_employee_service.py @@ -2,9 +2,9 @@ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). from datetime import date +from unittest.mock import patch from dateutil.relativedelta import relativedelta -from mock import patch from odoo import fields from odoo.tests import common diff --git a/hr_job_category/README.rst b/hr_job_category/README.rst new file mode 100644 index 00000000000..d4461a62d4c --- /dev/null +++ b/hr_job_category/README.rst @@ -0,0 +1,107 @@ +========================== +HR Job Employee Categories +========================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:ee02668b98fd586cba7bceb632c9a7ad745fa65c7799e2544587ad1805b1ccd2 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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-OCA%2Fhr-lightgray.png?logo=github + :target: https://github.com/OCA/hr/tree/16.0/hr_job_category + :alt: OCA/hr +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/hr-16-0/hr-16-0-hr_job_category + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/hr&target_branch=16.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module was written to extend the functionality of jobs +to support tagging employees based on their job positions. +For example, all Supervisors could be attached to the Supervisors category. +Define which categories a job belongs to in the configuration for the job. +When an employee is assigned a particular job the categories attached to that +job will be attached to the employee record as well. + +**Table of contents** + +.. contents:: + :local: + +Installation +============ + +To install this module, you need to: + +* clone the branch 11.0 of the repository https://github.com/OCA/hr +* add the path to this repository in your configuration (addons-path) +* update the module list +* search for "HR Job Employee Categories" in your addons +* install the module + +Usage +===== + +Just like on Employee form, you can select Tags on every Job form view. +Once a contract is defined for an employee, the tags assigned to the job +position selected are copied to the employee. + +Note: If the job position is changed on the same contract, the tags from +old job position will be removed from employee. + +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 +~~~~~~~ + +* Michael Telahun Makonnen +* Savoir-faire Linux +* Fekete Mihai (FBSR) + +Contributors +~~~~~~~~~~~~ + +* Michael Telahun Makonnen +* Savoir-faire Linux +* Fekete Mihai +* Nikul Chaudhary + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +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. + +This module is part of the `OCA/hr `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/hr_job_category/__init__.py b/hr_job_category/__init__.py new file mode 100644 index 00000000000..69f7babdfb1 --- /dev/null +++ b/hr_job_category/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import models diff --git a/hr_job_category/__manifest__.py b/hr_job_category/__manifest__.py new file mode 100644 index 00000000000..eed3065d2b5 --- /dev/null +++ b/hr_job_category/__manifest__.py @@ -0,0 +1,18 @@ +# Copyright 2013 Michael Telahun Makonnen +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + "name": "HR Job Employee Categories", + "version": "16.0.1.0.0", + "category": "Generic Modules/Human Resources", + "summary": "Adds tags to employee through contract and job position", + "author": "Michael Telahun Makonnen , " + "Savoir-faire Linux, " + "Fekete Mihai (FBSR), " + "Odoo Community Association (OCA)", + "website": "https://github.com/OCA/hr", + "license": "AGPL-3", + "depends": ["hr_contract"], + "data": ["views/hr_view.xml"], + "installable": True, +} diff --git a/hr_job_category/i18n/de.po b/hr_job_category/i18n/de.po new file mode 100644 index 00000000000..4fd53c878ef --- /dev/null +++ b/hr_job_category/i18n/de.po @@ -0,0 +1,43 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * hr_job_category +# +# Translators: +# Rudolf Schnapka , 2016 +# Thomas A. Jaeger, 2015 +# Thomas A. Jaeger, 2015 +msgid "" +msgstr "" +"Project-Id-Version: hr (8.0)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-11-30 05:19+0000\n" +"PO-Revision-Date: 2022-05-11 13:05+0000\n" +"Last-Translator: Maria Sparenberg \n" +"Language-Team: German (http://www.transifex.com/oca/OCA-hr-8-0/language/" +"de/)\n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.3.2\n" + +#. module: hr_job_category +#: model:ir.model.fields,field_description:hr_job_category.field_hr_job__category_ids +msgid "Associated Tags" +msgstr "Assoziierte Stichwörter" + +#. module: hr_job_category +#: model:ir.model,name:hr_job_category.model_hr_contract +msgid "Contract" +msgstr "Vertrag" + +#. module: hr_job_category +#: model:ir.model,name:hr_job_category.model_hr_job +msgid "Job Position" +msgstr "Job-Position" + +#. module: hr_job_category +#: model_terms:ir.ui.view,arch_db:hr_job_category.view_job_form +msgid "e.g. Part Time" +msgstr "z. B. Teilzeit" diff --git a/hr_job_category/i18n/es.po b/hr_job_category/i18n/es.po new file mode 100644 index 00000000000..34968c54c47 --- /dev/null +++ b/hr_job_category/i18n/es.po @@ -0,0 +1,41 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * hr_job_category +# +# Translators: +# Antonio Trueba, 2016 +msgid "" +msgstr "" +"Project-Id-Version: hr (8.0)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-11-30 05:19+0000\n" +"PO-Revision-Date: 2016-02-10 16:53+0000\n" +"Last-Translator: Antonio Trueba\n" +"Language-Team: Spanish (http://www.transifex.com/oca/OCA-hr-8-0/language/" +"es/)\n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: hr_job_category +#: model:ir.model.fields,field_description:hr_job_category.field_hr_job__category_ids +msgid "Associated Tags" +msgstr "Etiquetas asociadas" + +#. module: hr_job_category +#: model:ir.model,name:hr_job_category.model_hr_contract +#, fuzzy +msgid "Contract" +msgstr "Contrato" + +#. module: hr_job_category +#: model:ir.model,name:hr_job_category.model_hr_job +msgid "Job Position" +msgstr "" + +#. module: hr_job_category +#: model_terms:ir.ui.view,arch_db:hr_job_category.view_job_form +msgid "e.g. Part Time" +msgstr "p.e., Tiempo parcial" diff --git a/hr_job_category/i18n/fi.po b/hr_job_category/i18n/fi.po new file mode 100644 index 00000000000..188c211149e --- /dev/null +++ b/hr_job_category/i18n/fi.po @@ -0,0 +1,40 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * hr_job_category +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: hr (8.0)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-04-14 04:15+0000\n" +"PO-Revision-Date: 2016-04-04 11:09+0000\n" +"Last-Translator: Jarmo Kortetjärvi \n" +"Language-Team: Finnish (http://www.transifex.com/oca/OCA-hr-8-0/language/" +"fi/)\n" +"Language: fi\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: hr_job_category +#: model:ir.model.fields,field_description:hr_job_category.field_hr_job__category_ids +msgid "Associated Tags" +msgstr "" + +#. module: hr_job_category +#: model:ir.model,name:hr_job_category.model_hr_contract +#, fuzzy +msgid "Contract" +msgstr "Sopimus" + +#. module: hr_job_category +#: model:ir.model,name:hr_job_category.model_hr_job +msgid "Job Position" +msgstr "" + +#. module: hr_job_category +#: model_terms:ir.ui.view,arch_db:hr_job_category.view_job_form +msgid "e.g. Part Time" +msgstr "" diff --git a/hr_job_category/i18n/fr.po b/hr_job_category/i18n/fr.po new file mode 100644 index 00000000000..b512237ac75 --- /dev/null +++ b/hr_job_category/i18n/fr.po @@ -0,0 +1,40 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * hr_job_category +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: hr (8.0)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-08-18 13:10+0000\n" +"PO-Revision-Date: 2015-07-27 23:44+0000\n" +"Last-Translator: <>\n" +"Language-Team: French (http://www.transifex.com/oca/OCA-hr-8-0/language/" +"fr/)\n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#. module: hr_job_category +#: model:ir.model.fields,field_description:hr_job_category.field_hr_job__category_ids +msgid "Associated Tags" +msgstr "" + +#. module: hr_job_category +#: model:ir.model,name:hr_job_category.model_hr_contract +#, fuzzy +msgid "Contract" +msgstr "Contrat" + +#. module: hr_job_category +#: model:ir.model,name:hr_job_category.model_hr_job +msgid "Job Position" +msgstr "Poste" + +#. module: hr_job_category +#: model_terms:ir.ui.view,arch_db:hr_job_category.view_job_form +msgid "e.g. Part Time" +msgstr "p.e. À temps partiel" diff --git a/hr_job_category/i18n/hr_job_category.pot b/hr_job_category/i18n/hr_job_category.pot new file mode 100644 index 00000000000..fc7693bcb3c --- /dev/null +++ b/hr_job_category/i18n/hr_job_category.pot @@ -0,0 +1,34 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * hr_job_category +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \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: hr_job_category +#: model:ir.model.fields,field_description:hr_job_category.field_hr_job__category_ids +msgid "Associated Tags" +msgstr "" + +#. module: hr_job_category +#: model:ir.model,name:hr_job_category.model_hr_contract +msgid "Contract" +msgstr "" + +#. module: hr_job_category +#: model:ir.model,name:hr_job_category.model_hr_job +msgid "Job Position" +msgstr "" + +#. module: hr_job_category +#: model_terms:ir.ui.view,arch_db:hr_job_category.view_job_form +msgid "e.g. Part Time" +msgstr "" diff --git a/hr_job_category/i18n/it.po b/hr_job_category/i18n/it.po new file mode 100644 index 00000000000..9e25f5d7b63 --- /dev/null +++ b/hr_job_category/i18n/it.po @@ -0,0 +1,44 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * hr_job_category +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: hr (8.0)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-03-12 12:02+0000\n" +"PO-Revision-Date: 2023-05-17 14:34+0000\n" +"Last-Translator: mymage \n" +"Language-Team: Italian (http://www.transifex.com/oca/OCA-hr-8-0/language/" +"it/)\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.14.1\n" + +#. module: hr_job_category +#: model:ir.model.fields,field_description:hr_job_category.field_hr_job__category_ids +msgid "Associated Tags" +msgstr "Etichette associate" + +#. module: hr_job_category +#: model:ir.model,name:hr_job_category.model_hr_contract +#, fuzzy +msgid "Contract" +msgstr "Contratto" + +#. module: hr_job_category +#: model:ir.model,name:hr_job_category.model_hr_job +msgid "Job Position" +msgstr "Posizione lavorativa" + +#. module: hr_job_category +#: model_terms:ir.ui.view,arch_db:hr_job_category.view_job_form +msgid "e.g. Part Time" +msgstr "es. Part Time" + +#~ msgid "Employee Contract" +#~ msgstr "Contratto dipendente" diff --git a/hr_job_category/i18n/pt_BR.po b/hr_job_category/i18n/pt_BR.po new file mode 100644 index 00000000000..0367e0f352c --- /dev/null +++ b/hr_job_category/i18n/pt_BR.po @@ -0,0 +1,44 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * hr_job_category +# +# Translators: +# danimaribeiro , 2016 +msgid "" +msgstr "" +"Project-Id-Version: hr (8.0)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-03-11 01:48+0000\n" +"PO-Revision-Date: 2022-09-26 16:07+0000\n" +"Last-Translator: Douglas Custódio \n" +"Language-Team: Portuguese (Brazil) (http://www.transifex.com/oca/OCA-hr-8-0/" +"language/pt_BR/)\n" +"Language: pt_BR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.3.2\n" + +#. module: hr_job_category +#: model:ir.model.fields,field_description:hr_job_category.field_hr_job__category_ids +msgid "Associated Tags" +msgstr "Etiquetas Associadas" + +#. module: hr_job_category +#: model:ir.model,name:hr_job_category.model_hr_contract +msgid "Contract" +msgstr "Contrato" + +#. module: hr_job_category +#: model:ir.model,name:hr_job_category.model_hr_job +msgid "Job Position" +msgstr "Cargo" + +#. module: hr_job_category +#: model_terms:ir.ui.view,arch_db:hr_job_category.view_job_form +msgid "e.g. Part Time" +msgstr "ex. Meio período" + +#~ msgid "Display Name" +#~ msgstr "Nome de Exibição" diff --git a/hr_job_category/i18n/ro.po b/hr_job_category/i18n/ro.po new file mode 100644 index 00000000000..2b2f986815d --- /dev/null +++ b/hr_job_category/i18n/ro.po @@ -0,0 +1,41 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * hr_job_category +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: hr (8.0)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-08-18 13:10+0000\n" +"PO-Revision-Date: 2015-07-27 23:44+0000\n" +"Last-Translator: <>\n" +"Language-Team: Romanian (http://www.transifex.com/oca/OCA-hr-8-0/language/" +"ro/)\n" +"Language: ro\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?" +"2:1));\n" + +#. module: hr_job_category +#: model:ir.model.fields,field_description:hr_job_category.field_hr_job__category_ids +msgid "Associated Tags" +msgstr "" + +#. module: hr_job_category +#: model:ir.model,name:hr_job_category.model_hr_contract +#, fuzzy +msgid "Contract" +msgstr "Contract" + +#. module: hr_job_category +#: model:ir.model,name:hr_job_category.model_hr_job +msgid "Job Position" +msgstr "Funcție" + +#. module: hr_job_category +#: model_terms:ir.ui.view,arch_db:hr_job_category.view_job_form +msgid "e.g. Part Time" +msgstr "" diff --git a/hr_job_category/i18n/sl.po b/hr_job_category/i18n/sl.po new file mode 100644 index 00000000000..42057c95ee4 --- /dev/null +++ b/hr_job_category/i18n/sl.po @@ -0,0 +1,43 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * hr_job_category +# +# Translators: +# Matjaž Mozetič , 2015 +msgid "" +msgstr "" +"Project-Id-Version: hr (8.0)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-08-18 13:10+0000\n" +"PO-Revision-Date: 2020-08-11 14:59+0000\n" +"Last-Translator: Matjaz Mozetic \n" +"Language-Team: Slovenian (http://www.transifex.com/oca/OCA-hr-8-0/language/" +"sl/)\n" +"Language: sl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || " +"n%100==4 ? 2 : 3;\n" +"X-Generator: Weblate 3.10\n" + +#. module: hr_job_category +#: model:ir.model.fields,field_description:hr_job_category.field_hr_job__category_ids +msgid "Associated Tags" +msgstr "Povezane oznake" + +#. module: hr_job_category +#: model:ir.model,name:hr_job_category.model_hr_contract +#, fuzzy +msgid "Contract" +msgstr "Pogodba o zaposlitvi" + +#. module: hr_job_category +#: model:ir.model,name:hr_job_category.model_hr_job +msgid "Job Position" +msgstr "Delovno mesto" + +#. module: hr_job_category +#: model_terms:ir.ui.view,arch_db:hr_job_category.view_job_form +msgid "e.g. Part Time" +msgstr "npr. Občasno" diff --git a/hr_job_category/models/__init__.py b/hr_job_category/models/__init__.py new file mode 100644 index 00000000000..0cabad10f7d --- /dev/null +++ b/hr_job_category/models/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import hr diff --git a/hr_job_category/models/hr.py b/hr_job_category/models/hr.py new file mode 100644 index 00000000000..18f32a2c9e7 --- /dev/null +++ b/hr_job_category/models/hr.py @@ -0,0 +1,87 @@ +# Copyright 2013 Michael Telahun Makonnen +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import logging + +from odoo import api, fields, models + +_logger = logging.getLogger(__name__) + + +class HRJob(models.Model): + _inherit = "hr.job" + + category_ids = fields.Many2many( + "hr.employee.category", + "job_category_rel", + "job_id", + "category_id", + string="Associated Tags", + ) + + +class HRContract(models.Model): + _inherit = "hr.contract" + + def _remove_tags(self, employee_id=None, job_id=None): + # TODO write tags only once + if not employee_id or not job_id: + return + employee = self.env["hr.employee"].browse(employee_id) + empl_tags = employee.category_ids + job = self.env["hr.job"].browse(job_id) + _logger.debug( + "Removing employee tags if tag exists on contract " "job: %s", empl_tags + ) + for tag in job.category_ids: + if tag in empl_tags: + employee.write({"category_ids": [(3, tag.id)]}) + + def _tag_employees(self, employee_id=None, job_id=None): + if not employee_id or not job_id: + return + employee = self.env["hr.employee"].browse(employee_id) + empl_tags = employee.category_ids + job = self.env["hr.job"].browse(job_id) + for tag in job.category_ids: + if tag not in empl_tags: + _logger.debug( + "Adding employee tag if job tag doesn't " "exists: %s", tag.name + ) + employee.write({"category_ids": [(4, tag.id)]}) + + @api.model + def create(self, vals): + res = super().create(vals) + if "job_id" in vals: + res._tag_employees(vals.get("job_id")) + return res + + def write(self, vals): + prev_data = self.read(["job_id"]) + + res = super().write(vals) + + # Go through each record and delete tags associated with the previous + # job, then add the tags of the new job. + # + for contract in self: + for data in prev_data: + if ( + data.get("id") == contract.id + and data["job_id"] + and data["job_id"][0] != contract.job_id.id + ): + self._remove_tags(contract.employee_id.id, data["job_id"][0]) + self._tag_employees(contract.employee_id.id, contract.job_id.id) + return res + + def unlink(self): + prev_data = self.read(["job_id"]) + # Go through each record and delete tags associated with the previous + # job, then add the tags of the new job. + # + for contract in self: + for data in prev_data: + self._remove_tags(contract.employee_id.id, data["job_id"][0]) + return super(HRContract, self).unlink() diff --git a/hr_job_category/readme/CONTRIBUTORS.rst b/hr_job_category/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000000..e35de9243ce --- /dev/null +++ b/hr_job_category/readme/CONTRIBUTORS.rst @@ -0,0 +1,4 @@ +* Michael Telahun Makonnen +* Savoir-faire Linux +* Fekete Mihai +* Nikul Chaudhary diff --git a/hr_job_category/readme/DESCRIPTION.rst b/hr_job_category/readme/DESCRIPTION.rst new file mode 100644 index 00000000000..883af419076 --- /dev/null +++ b/hr_job_category/readme/DESCRIPTION.rst @@ -0,0 +1,6 @@ +This module was written to extend the functionality of jobs +to support tagging employees based on their job positions. +For example, all Supervisors could be attached to the Supervisors category. +Define which categories a job belongs to in the configuration for the job. +When an employee is assigned a particular job the categories attached to that +job will be attached to the employee record as well. diff --git a/hr_job_category/readme/INSTALL.rst b/hr_job_category/readme/INSTALL.rst new file mode 100644 index 00000000000..de0bc623691 --- /dev/null +++ b/hr_job_category/readme/INSTALL.rst @@ -0,0 +1,7 @@ +To install this module, you need to: + +* clone the branch 11.0 of the repository https://github.com/OCA/hr +* add the path to this repository in your configuration (addons-path) +* update the module list +* search for "HR Job Employee Categories" in your addons +* install the module diff --git a/hr_job_category/readme/USAGE.rst b/hr_job_category/readme/USAGE.rst new file mode 100644 index 00000000000..bdd3d7f054c --- /dev/null +++ b/hr_job_category/readme/USAGE.rst @@ -0,0 +1,6 @@ +Just like on Employee form, you can select Tags on every Job form view. +Once a contract is defined for an employee, the tags assigned to the job +position selected are copied to the employee. + +Note: If the job position is changed on the same contract, the tags from +old job position will be removed from employee. diff --git a/hr_job_category/static/description/icon.png b/hr_job_category/static/description/icon.png new file mode 100644 index 00000000000..297dc71c85c Binary files /dev/null and b/hr_job_category/static/description/icon.png differ diff --git a/hr_job_category/static/description/index.html b/hr_job_category/static/description/index.html new file mode 100644 index 00000000000..cdfc31877c9 --- /dev/null +++ b/hr_job_category/static/description/index.html @@ -0,0 +1,454 @@ + + + + + +HR Job Employee Categories + + + +
+

HR Job Employee Categories

+ + +

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

+

This module was written to extend the functionality of jobs +to support tagging employees based on their job positions. +For example, all Supervisors could be attached to the Supervisors category. +Define which categories a job belongs to in the configuration for the job. +When an employee is assigned a particular job the categories attached to that +job will be attached to the employee record as well.

+

Table of contents

+ +
+

Installation

+

To install this module, you need to:

+
    +
  • clone the branch 11.0 of the repository https://github.com/OCA/hr
  • +
  • add the path to this repository in your configuration (addons-path)
  • +
  • update the module list
  • +
  • search for “HR Job Employee Categories” in your addons
  • +
  • install the module
  • +
+
+
+

Usage

+

Just like on Employee form, you can select Tags on every Job form view. +Once a contract is defined for an employee, the tags assigned to the job +position selected are copied to the employee.

+

Note: If the job position is changed on the same contract, the tags from +old job position will be removed from employee.

+
+
+

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

+ +
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+ +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.

+

This module is part of the OCA/hr project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/hr_job_category/tests/__init__.py b/hr_job_category/tests/__init__.py new file mode 100644 index 00000000000..95196a8de46 --- /dev/null +++ b/hr_job_category/tests/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import test_hr_job_categories diff --git a/hr_job_category/tests/test_hr_job_categories.py b/hr_job_category/tests/test_hr_job_categories.py new file mode 100644 index 00000000000..4289fc5c603 --- /dev/null +++ b/hr_job_category/tests/test_hr_job_categories.py @@ -0,0 +1,144 @@ +# Copyright 2014 Savoir-faire Linux +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo.tests import common + + +class TestHrJobCategories(common.TransactionCase): + def setUp(self): + super(TestHrJobCategories, self).setUp() + self.employee_model = self.env["hr.employee"] + self.employee_categ_model = self.env["hr.employee.category"] + self.user_model = self.env["res.users"] + self.job_model = self.env["hr.job"] + self.contract_model = self.env["hr.contract"] + + # Create a employee + self.employee_id_1 = self.employee_model.create({"name": "Employee 1"}) + self.employee_id_2 = self.employee_model.create({"name": "Employee 2"}) + + # Create two employee categories for job positions + self.categ_id = self.employee_categ_model.create({"name": "Category 1"}) + self.categ_2_id = self.employee_categ_model.create({"name": "Category 2"}) + + # Create an employee category to be used out of job positions + self.categ_3_id = self.employee_categ_model.create({"name": "Category 3"}) + + # Create two jobs + self.job_id = self.job_model.create( + {"name": "Job 1", "category_ids": [(6, 0, [self.categ_id.id])]} + ) + + self.job_2_id = self.job_model.create( + {"name": "Job 2", "category_ids": [(6, 0, [self.categ_2_id.id])]} + ) + + # Create one contract + self.contract_id = self.contract_model.create( + {"name": "Contract 1", "employee_id": self.employee_id_1.id, "wage": 50000} + ) + + def test_write_computes_with_normal_args(self): + """ + Test that write method on hr_contract computes without error + when the required data is given in parameter + + Check if the job categories are written to the employee. + """ + # Check if job categories are written to the employee + self.contract_id.write({"job_id": self.job_id.id}) + self.contract_id.refresh() + self.assertTrue(self.employee_id_1.category_ids) + self.assertTrue( + all( + x in self.employee_id_1.category_ids.ids + for x in self.job_id.category_ids.ids + ) + ) + + self.contract_id.write({"job_id": False}) + self.assertFalse(self.employee_id_1.category_ids) + + # Check if job2 categories are written to the employee + self.contract_id.write({"job_id": self.job_2_id.id}) + self.contract_id.flush() + self.assertTrue( + all( + x in self.employee_id_1.category_ids.ids + for x in self.job_2_id.category_ids.ids + ) + ) + self.contract_id.write({"employee_id": self.employee_id_2.id}) + self.contract_id.write({"job_id": self.job_2_id.id}) + # We need to force the job, as it is modified by a compute + self.employee_id_1.refresh() + self.employee_id_2.refresh() + # self.assertFalse(self.employee_id_1.category_ids) + self.job_2_id.refresh() + self.assertTrue( + all( + x in self.employee_id_2.category_ids.ids + for x in self.job_2_id.category_ids.ids + ) + ) + + self.contract_id.unlink() + self.assertFalse(self.employee_id_2.category_ids) + + def test_add_new_tags_with_already_present_tags(self): + """ + When a tag is manually added, adding new tags from a contract shouldn't remove + them + """ + self.employee_id_1.write({"category_ids": self.categ_3_id}) + # We have added manually a tag + self.assertEqual(len(self.employee_id_1.category_ids.ids), 1) + self.assertEqual(self.employee_id_1.category_ids.ids[0], self.categ_3_id.id) + # We are now adding contract with 1 job category + # The employee should now have two tags + self.contract_id.write({"job_id": self.job_id.id}) + self.contract_id.refresh() + self.assertEqual(len(self.employee_id_1.category_ids.ids), 2) + self.assertIn(self.categ_3_id.id, self.employee_id_1.category_ids.ids) + self.assertIn( + self.job_id.category_ids.ids[0], self.employee_id_1.category_ids.ids + ) + + def test_remove_tags_from_previous_job(self): + """Changing the job position removes previous tags and add the new ones""" + self.employee_id_1.write({"category_ids": self.categ_3_id}) + self.contract_id.write({"job_id": self.job_id.id}) + self.contract_id.refresh() + + # We have two tags (from job and the manual added one) + self.assertEqual(len(self.employee_id_1.category_ids.ids), 2) + + # We change the contract of the employe + # We should now have the tag + self.contract_id.write({"job_id": self.job_2_id.id}) + self.contract_id.flush() + + self.assertEqual(len(self.employee_id_1.category_ids.ids), 2) + self.assertIn(self.categ_3_id.id, self.employee_id_1.category_ids.ids) + self.assertNotIn( + self.job_id.category_ids.ids[0], self.employee_id_1.category_ids.ids + ) + self.assertIn( + self.job_2_id.category_ids.ids[0], self.employee_id_1.category_ids.ids + ) + + def test_unlink_contract(self): + """When we unlink a contract, it should remove only the tags related to it""" + self.employee_id_1.write({"category_ids": self.categ_3_id}) + self.contract_id.write({"job_id": self.job_id.id}) + self.contract_id.refresh() + + # We have two tags (from job and the manual added one) + self.assertEqual(len(self.employee_id_1.category_ids.ids), 2) + + self.contract_id.unlink() + self.assertEqual(len(self.employee_id_1.category_ids.ids), 1) + self.assertIn(self.categ_3_id.id, self.employee_id_1.category_ids.ids) + self.assertNotIn( + self.job_id.category_ids.ids[0], self.employee_id_1.category_ids.ids + ) diff --git a/hr_job_category/views/hr_view.xml b/hr_job_category/views/hr_view.xml new file mode 100644 index 00000000000..cebc0e2e75b --- /dev/null +++ b/hr_job_category/views/hr_view.xml @@ -0,0 +1,19 @@ + + + + hr.job.category + hr.job + + + + + + + diff --git a/setup/_metapackage/VERSION.txt b/setup/_metapackage/VERSION.txt index 1c9ef3bd9bd..fcfd8379c04 100644 --- a/setup/_metapackage/VERSION.txt +++ b/setup/_metapackage/VERSION.txt @@ -1 +1 @@ -16.0.20250214.1 \ No newline at end of file +16.0.20250217.0 \ No newline at end of file diff --git a/setup/_metapackage/setup.py b/setup/_metapackage/setup.py index bdeffae1900..2f5bafa09c3 100644 --- a/setup/_metapackage/setup.py +++ b/setup/_metapackage/setup.py @@ -34,6 +34,7 @@ 'odoo-addon-hr_employee_service_contract>=16.0dev,<16.1dev', 'odoo-addon-hr_employee_ssn>=16.0dev,<16.1dev', 'odoo-addon-hr_holidays_team_manager>=16.0dev,<16.1dev', + 'odoo-addon-hr_job_category>=16.0dev,<16.1dev', 'odoo-addon-hr_personal_equipment_request>=16.0dev,<16.1dev', 'odoo-addon-hr_personal_equipment_request_tier_validation>=16.0dev,<16.1dev', 'odoo-addon-hr_personal_equipment_stock>=16.0dev,<16.1dev', diff --git a/setup/hr_job_category/odoo/addons/hr_job_category b/setup/hr_job_category/odoo/addons/hr_job_category new file mode 120000 index 00000000000..541c8f9bc70 --- /dev/null +++ b/setup/hr_job_category/odoo/addons/hr_job_category @@ -0,0 +1 @@ +../../../../hr_job_category \ No newline at end of file diff --git a/setup/hr_job_category/setup.py b/setup/hr_job_category/setup.py new file mode 100644 index 00000000000..28c57bb6403 --- /dev/null +++ b/setup/hr_job_category/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) diff --git a/test-requirements.txt b/test-requirements.txt deleted file mode 100644 index 932a8957f78..00000000000 --- a/test-requirements.txt +++ /dev/null @@ -1 +0,0 @@ -mock