diff --git a/hr_job_category/README.rst b/hr_job_category/README.rst new file mode 100644 index 00000000000..3bef31c7067 --- /dev/null +++ b/hr_job_category/README.rst @@ -0,0 +1,104 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + +========================== +HR Job Employee Categories +========================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:334f4006060852202ff2e1e565df3cdada501648421bb866aa531c156da54661 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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/license-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/19.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-19-0/hr-19-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=19.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: + +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 +- Italo LOPES +- `Heliconia Solutions Pvt. Ltd. `__ + + - Bhavesh Heliconia + +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..f6fda77e00e --- /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": "19.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"], + "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..f1535579e15 --- /dev/null +++ b/hr_job_category/i18n/es.po @@ -0,0 +1,45 @@ +# 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: 2023-10-09 07:38+0000\n" +"Last-Translator: Ivorra78 \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" +"X-Generator: Weblate 4.17\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 "Puesto de trabajo" + +#. 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" + +#~ msgid "Employee Contract" +#~ msgstr "Contrato de empleado" 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..3e8f79a7b87 --- /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 18.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..4c26236c5fe --- /dev/null +++ b/hr_job_category/i18n/it.po @@ -0,0 +1,43 @@ +# 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: 2024-08-14 17:58+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 5.6.2\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 +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..8753c0bba0e --- /dev/null +++ b/hr_job_category/models/hr.py @@ -0,0 +1,95 @@ +# 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 HRVersion(models.Model): + _inherit = "hr.version" + + def _remove_tags(self, job_id): + if isinstance(job_id, int): + job = self.env["hr.job"].browse(job_id) + else: + job = job_id + for employee in self.mapped("employee_id"): + _logger.debug( + "Removing employee tags if tags exist on contract job: %s", + employee.category_ids, + ) + tags_to_remove = [ + (3, tag.id) for tag in job.category_ids & employee.category_ids + ] + if tags_to_remove: + employee.write({"category_ids": tags_to_remove}) + + def _tag_employees(self, job_id): + if isinstance(job_id, int): + job = self.env["hr.job"].browse(job_id) + else: + job = job_id + _logger.debug( + "Adding employee tags if job tags doesn't exist: %s", job.category_ids + ) + for employee in self.mapped("employee_id"): + tags_to_add = [ + (4, tag.id) for tag in job.category_ids - employee.category_ids + ] + if tags_to_add: + employee.write({"category_ids": tags_to_add}) + + @api.model_create_multi + def create(self, vals_list): + res = super().create(vals_list) + for record, vals in zip(res, vals_list, strict=False): + if "job_id" in vals: + record._tag_employees(vals.get("job_id")) + return res + + def write(self, vals): + prev_data = { + res["id"]: res["job_id"][0] + for res in self.read(["job_id"]) + if res["job_id"] + } + for record in self: + if ( + "employee_id" in vals + and record.employee_id + and record.employee_id.id != vals.get("employee_id") + ): + record._remove_tags(record.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. + # + if "job_id" in vals: + for contract in self: + job_id = prev_data.get(contract.id) + if job_id: + contract._remove_tags(job_id) + self._tag_employees(contract.job_id) + return res + + def unlink(self): + # Go through each record and delete tags associated with the previous job + for contract in self: + if contract.job_id: + contract._remove_tags(contract.job_id) + return super().unlink() diff --git a/hr_job_category/pyproject.toml b/hr_job_category/pyproject.toml new file mode 100644 index 00000000000..4231d0cccb3 --- /dev/null +++ b/hr_job_category/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/hr_job_category/readme/CONTRIBUTORS.md b/hr_job_category/readme/CONTRIBUTORS.md new file mode 100644 index 00000000000..cd0027a30f8 --- /dev/null +++ b/hr_job_category/readme/CONTRIBUTORS.md @@ -0,0 +1,7 @@ +- Michael Telahun Makonnen \<\> +- Savoir-faire Linux +- Fekete Mihai \<\> +- Nikul Chaudhary \<\> +- Italo LOPES \<\> +- [Heliconia Solutions Pvt. Ltd.](https://www.heliconia.io) + - Bhavesh Heliconia diff --git a/hr_job_category/readme/DESCRIPTION.md b/hr_job_category/readme/DESCRIPTION.md new file mode 100644 index 00000000000..280466d6bcc --- /dev/null +++ b/hr_job_category/readme/DESCRIPTION.md @@ -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/USAGE.md b/hr_job_category/readme/USAGE.md new file mode 100644 index 00000000000..bdd3d7f054c --- /dev/null +++ b/hr_job_category/readme/USAGE.md @@ -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..9fe12d818c0 --- /dev/null +++ b/hr_job_category/static/description/index.html @@ -0,0 +1,453 @@ + + + + + +README.rst + + + +
+ + + +Odoo Community Association + +
+

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

+ +
+

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..88bdebc2494 --- /dev/null +++ b/hr_job_category/tests/test_hr_job_categories.py @@ -0,0 +1,141 @@ +# Copyright 2014 Savoir-faire Linux +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from odoo import Command + +from odoo.addons.base.tests.common import BaseCommon + + +class TestHrJobCategories(BaseCommon): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.employee_model = cls.env["hr.employee"] + cls.employee_categ_model = cls.env["hr.employee.category"] + cls.user_model = cls.env["res.users"] + cls.job_model = cls.env["hr.job"] + cls.contract_model = cls.env["hr.version"] + + # Create a employee + cls.employee_id_1 = cls.employee_model.create({"name": "Employee 1"}) + cls.employee_id_2 = cls.employee_model.create({"name": "Employee 2"}) + + # Create two employee categories for job positions + cls.categ_id = cls.employee_categ_model.create({"name": "Category 1"}) + cls.categ_2_id = cls.employee_categ_model.create({"name": "Category 2"}) + + # Create an employee category to be used out of job positions + cls.categ_3_id = cls.employee_categ_model.create({"name": "Category 3"}) + + # Create two jobs + cls.job_id = cls.job_model.create( + {"name": "Job 1", "category_ids": [Command.set([cls.categ_id.id])]} + ) + + cls.job_2_id = cls.job_model.create( + {"name": "Job 2", "category_ids": [Command.set([cls.categ_2_id.id])]} + ) + + # Create one contract + cls.contract_id = cls.contract_model.create( + { + "name": "Contract 1", + "employee_id": cls.employee_id_1.id, + "wage": 50000, + "date_version": "2023-01-01", + } + ) + + 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.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.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}) + self.assertFalse(self.employee_id_1.category_ids) + 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.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}) + + # 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.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}) + + # 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 + + + + + + +