From 54144ac732b6670ffe6b6a9ccb100e021d89e92b Mon Sep 17 00:00:00 2001 From: osi-scampbell Date: Tue, 4 Dec 2018 14:51:49 -0700 Subject: [PATCH 01/32] [ADD] fieldservice_skill --- fieldservice_skill/README.rst | 140 +++++ fieldservice_skill/__init__.py | 4 + fieldservice_skill/__manifest__.py | 29 ++ fieldservice_skill/models/__init__.py | 9 + fieldservice_skill/models/fsm_category.py | 10 + fieldservice_skill/models/fsm_order.py | 19 + fieldservice_skill/models/fsm_person.py | 11 + fieldservice_skill/models/fsm_person_skill.py | 21 + fieldservice_skill/readme/CONFIGURE.rst | 6 + fieldservice_skill/readme/CONTRIBUTORS.rst | 3 + fieldservice_skill/readme/CREDITS.rst | 3 + fieldservice_skill/readme/DESCRIPTION.rst | 12 + fieldservice_skill/readme/INSTALL.rst | 4 + fieldservice_skill/readme/ROADMAP.rst | 2 + fieldservice_skill/readme/USAGE.rst | 8 + .../static/description/icon.png | Bin 0 -> 9455 bytes .../static/description/index.html | 479 ++++++++++++++++++ fieldservice_skill/views/fsm_category.xml | 17 + fieldservice_skill/views/fsm_order.xml | 17 + fieldservice_skill/views/fsm_person.xml | 23 + fieldservice_skill/views/fsm_person_skill.xml | 96 ++++ fieldservice_skill/views/hr_skill.xml | 9 + 22 files changed, 922 insertions(+) create mode 100644 fieldservice_skill/README.rst create mode 100644 fieldservice_skill/__init__.py create mode 100644 fieldservice_skill/__manifest__.py create mode 100644 fieldservice_skill/models/__init__.py create mode 100644 fieldservice_skill/models/fsm_category.py create mode 100644 fieldservice_skill/models/fsm_order.py create mode 100644 fieldservice_skill/models/fsm_person.py create mode 100644 fieldservice_skill/models/fsm_person_skill.py create mode 100644 fieldservice_skill/readme/CONFIGURE.rst create mode 100644 fieldservice_skill/readme/CONTRIBUTORS.rst create mode 100644 fieldservice_skill/readme/CREDITS.rst create mode 100644 fieldservice_skill/readme/DESCRIPTION.rst create mode 100644 fieldservice_skill/readme/INSTALL.rst create mode 100644 fieldservice_skill/readme/ROADMAP.rst create mode 100644 fieldservice_skill/readme/USAGE.rst create mode 100644 fieldservice_skill/static/description/icon.png create mode 100644 fieldservice_skill/static/description/index.html create mode 100644 fieldservice_skill/views/fsm_category.xml create mode 100644 fieldservice_skill/views/fsm_order.xml create mode 100644 fieldservice_skill/views/fsm_person.xml create mode 100644 fieldservice_skill/views/fsm_person_skill.xml create mode 100644 fieldservice_skill/views/hr_skill.xml diff --git a/fieldservice_skill/README.rst b/fieldservice_skill/README.rst new file mode 100644 index 0000000000..54512d4ffe --- /dev/null +++ b/fieldservice_skill/README.rst @@ -0,0 +1,140 @@ +===================== +Field Service - Skill +===================== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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%2Ffield--service-lightgray.png?logo=github + :target: https://github.com/OCA/field-service/tree/11.0/fieldservice_skill + :alt: OCA/field-service +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/field-service-11-0/field-service-11-0-fieldservice_skill + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/264/11.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Odoo Field Service App allows to assign any FS person to any FS order. +For some organizations, they cannot assign any FS person to any order. +They needs to manage the skills of the FS persons and reduce the list of +potential FS persons on an order to avoid wrong assignment and mis-configuration. +The skills of the selectable FS persons on a service order needs to match the +required skills to perform the order. + +This modules allows you to set skills on categories to automatically set those +skills on the order. It also allows you to set the skills to the field service +person with their level. On the order, the list of field service persons is +filtered with the skills and the location so you can only assign the right +person to the order. + +**Table of contents** + +.. contents:: + :local: + +Installation +============ + +To install Field Service and have the mapping features, you need to install GeoEngine. + +Please refer to the installation instructions available at: +https://github.com/OCA/geospatial/tree/11.0/base_geoengine + +Configuration +============= + +To configure this module, you need to: + +* Create or edit your categories to set skills +* Create or edit your persons to set their skills and skill levels +* Create or edit your territories to set their field service persons +* Create or edit your locations to set their territories + +Usage +===== + +To use this module, you need to: + +* Create an order, set the template and the location + + * The categories and skills are set based on the template. + * The field service person is set to the preferred person if skills matches. + * The list of field service persons is filtered with the one serving the + location (using the territory) and having the skills + +Known issues / Roadmap +====================== + +The roadmap of the Field Service application is documented on +`Github `_. + +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 smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Open Source Integrators + +Contributors +~~~~~~~~~~~~ + +* Wolfgang Hall +* Maxime Chambreuil +* Steve Campbell + +Other credits +~~~~~~~~~~~~~ + +The development of this module has been financially supported by: + +* Open Source Integrators + +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. + +.. |maintainer-osi-scampbell| image:: https://github.com/osi-scampbell.png?size=40px + :target: https://github.com/osi-scampbell + :alt: osi-scampbell +.. |maintainer-max3903| image:: https://github.com/max3903.png?size=40px + :target: https://github.com/max3903 + :alt: max3903 + +Current `maintainers `__: + +|maintainer-osi-scampbell| |maintainer-max3903| + +This module is part of the `OCA/field-service `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/fieldservice_skill/__init__.py b/fieldservice_skill/__init__.py new file mode 100644 index 0000000000..631bd4893a --- /dev/null +++ b/fieldservice_skill/__init__.py @@ -0,0 +1,4 @@ +# Copyright (C) 2018 - TODAY, Open Source Integrators +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import models diff --git a/fieldservice_skill/__manifest__.py b/fieldservice_skill/__manifest__.py new file mode 100644 index 0000000000..30ed697973 --- /dev/null +++ b/fieldservice_skill/__manifest__.py @@ -0,0 +1,29 @@ +# Copyright (C) 2018 - TODAY, Open Source Integrators +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + "name": "Field Service - Skill", + "summary": "Manage your FS persons skills", + "version": "11.0.0.0.1", + "category": "Field Service", + "license": "AGPL-3", + "author": "Open Source Integrators, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/field-service", + "depends": [ + "hr_skill", + "fieldservice", + ], + "data": [ + "views/fsm_person.xml", + "views/fsm_category.xml", + "views/fsm_person_skill.xml", + "views/fsm_order.xml", + "views/hr_skill.xml", + ], + "installable": True, + "development_status": "Beta", + "maintainers": [ + "osi-scampbell", + "max3903", + ], +} diff --git a/fieldservice_skill/models/__init__.py b/fieldservice_skill/models/__init__.py new file mode 100644 index 0000000000..6ce13d3d64 --- /dev/null +++ b/fieldservice_skill/models/__init__.py @@ -0,0 +1,9 @@ +# Copyright (C) 2018 - TODAY, Open Source Integrators +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import ( + fsm_person_skill, + fsm_person, + fsm_category, + fsm_order, +) diff --git a/fieldservice_skill/models/fsm_category.py b/fieldservice_skill/models/fsm_category.py new file mode 100644 index 0000000000..e12e69ce32 --- /dev/null +++ b/fieldservice_skill/models/fsm_category.py @@ -0,0 +1,10 @@ +# Copyright (C) 2018 - TODAY, Open Source Integrators +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class FSMCategory(models.Model): + _inherit = 'fsm.category' + + skill_ids = fields.Many2many('hr.skill', string="Required Skills") diff --git a/fieldservice_skill/models/fsm_order.py b/fieldservice_skill/models/fsm_order.py new file mode 100644 index 0000000000..140b3a6b60 --- /dev/null +++ b/fieldservice_skill/models/fsm_order.py @@ -0,0 +1,19 @@ +# Copyright (C) 2018 - TODAY, Open Source Integrators +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields + +from odoo.addons.base_geoengine import geo_model + + +class FSMOrder(geo_model.GeoModel): + _inherit = 'fsm.order' + + skill_ids = fields.Many2many('hr.skill', string="Required Skills") + + @api.onchange('category_ids') + def _onchange_category_ids(self): + skill_ids = [] + for category in self.category_ids: + skill_ids.extend([skill.id for skill in category.skill_ids]) + self.skill_ids = [(6, 0, skill_ids)] diff --git a/fieldservice_skill/models/fsm_person.py b/fieldservice_skill/models/fsm_person.py new file mode 100644 index 0000000000..56e226ef66 --- /dev/null +++ b/fieldservice_skill/models/fsm_person.py @@ -0,0 +1,11 @@ +# Copyright (C) 2018 - TODAY, Open Source Integrators +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class FSMPerson(models.Model): + _inherit = 'fsm.person' + + skill_ids = fields.One2many('fsm.person.skill', 'person_id', + string='Skills') diff --git a/fieldservice_skill/models/fsm_person_skill.py b/fieldservice_skill/models/fsm_person_skill.py new file mode 100644 index 0000000000..a5c0d32ba5 --- /dev/null +++ b/fieldservice_skill/models/fsm_person_skill.py @@ -0,0 +1,21 @@ +# Copyright (C) 2018 - TODAY, Open Source Integrators +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class FSMPersonSkill(models.Model): + _name = 'fsm.person.skill' + _description = 'Field Service Person Skill' + + person_id = fields.Many2one('fsm.person', string="Field Service Person") + skill_id = fields.Many2one('hr.skill', string="Skill", required=True) + level = fields.Selection([('0', 'Junior'), + ('1', 'Intermediate'), + ('2', 'Senior'), + ('3', 'Expert')], string='Level') + + _sql_constraints = [ + ('person_skill_uniq', 'unique(person_id, skill_id)', + "This person already has that skill!"), + ] diff --git a/fieldservice_skill/readme/CONFIGURE.rst b/fieldservice_skill/readme/CONFIGURE.rst new file mode 100644 index 0000000000..da3b6aee62 --- /dev/null +++ b/fieldservice_skill/readme/CONFIGURE.rst @@ -0,0 +1,6 @@ +To configure this module, you need to: + +* Create or edit your categories to set skills +* Create or edit your persons to set their skills and skill levels +* Create or edit your territories to set their field service persons +* Create or edit your locations to set their territories diff --git a/fieldservice_skill/readme/CONTRIBUTORS.rst b/fieldservice_skill/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000000..db6ccc051b --- /dev/null +++ b/fieldservice_skill/readme/CONTRIBUTORS.rst @@ -0,0 +1,3 @@ +* Wolfgang Hall +* Maxime Chambreuil +* Steve Campbell diff --git a/fieldservice_skill/readme/CREDITS.rst b/fieldservice_skill/readme/CREDITS.rst new file mode 100644 index 0000000000..0eff0acf4e --- /dev/null +++ b/fieldservice_skill/readme/CREDITS.rst @@ -0,0 +1,3 @@ +The development of this module has been financially supported by: + +* Open Source Integrators diff --git a/fieldservice_skill/readme/DESCRIPTION.rst b/fieldservice_skill/readme/DESCRIPTION.rst new file mode 100644 index 0000000000..5e82e78e4e --- /dev/null +++ b/fieldservice_skill/readme/DESCRIPTION.rst @@ -0,0 +1,12 @@ +Odoo Field Service App allows to assign any FS person to any FS order. +For some organizations, they cannot assign any FS person to any order. +They needs to manage the skills of the FS persons and reduce the list of +potential FS persons on an order to avoid wrong assignment and mis-configuration. +The skills of the selectable FS persons on a service order needs to match the +required skills to perform the order. + +This modules allows you to set skills on categories to automatically set those +skills on the order. It also allows you to set the skills to the field service +person with their level. On the order, the list of field service persons is +filtered with the skills and the location so you can only assign the right +person to the order. diff --git a/fieldservice_skill/readme/INSTALL.rst b/fieldservice_skill/readme/INSTALL.rst new file mode 100644 index 0000000000..c010f8f6a2 --- /dev/null +++ b/fieldservice_skill/readme/INSTALL.rst @@ -0,0 +1,4 @@ +To install Field Service and have the mapping features, you need to install GeoEngine. + +Please refer to the installation instructions available at: +https://github.com/OCA/geospatial/tree/11.0/base_geoengine diff --git a/fieldservice_skill/readme/ROADMAP.rst b/fieldservice_skill/readme/ROADMAP.rst new file mode 100644 index 0000000000..f607015959 --- /dev/null +++ b/fieldservice_skill/readme/ROADMAP.rst @@ -0,0 +1,2 @@ +The roadmap of the Field Service application is documented on +`Github `_. diff --git a/fieldservice_skill/readme/USAGE.rst b/fieldservice_skill/readme/USAGE.rst new file mode 100644 index 0000000000..7371806917 --- /dev/null +++ b/fieldservice_skill/readme/USAGE.rst @@ -0,0 +1,8 @@ +To use this module, you need to: + +* Create an order, set the template and the location + + * The categories and skills are set based on the template. + * The field service person is set to the preferred person if skills matches. + * The list of field service persons is filtered with the one serving the + location (using the territory) and having the skills diff --git a/fieldservice_skill/static/description/icon.png b/fieldservice_skill/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d GIT binary patch literal 9455 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 z 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 Xviia!U7SGha1wx#SCgwmn*{w2TRX*I literal 0 HcmV?d00001 diff --git a/fieldservice_skill/static/description/index.html b/fieldservice_skill/static/description/index.html new file mode 100644 index 0000000000..aab25d1e7c --- /dev/null +++ b/fieldservice_skill/static/description/index.html @@ -0,0 +1,479 @@ + + + + + + +Field Service - Skill + + + +
+

Field Service - Skill

+ + +

Beta License: AGPL-3 OCA/field-service Translate me on Weblate Try me on Runbot

+

Odoo Field Service App allows to assign any FS person to any FS order. +For some organizations, they cannot assign any FS person to any order. +They needs to manage the skills of the FS persons and reduce the list of +potential FS persons on an order to avoid wrong assignment and mis-configuration. +The skills of the selectable FS persons on a service order needs to match the +required skills to perform the order.

+

This modules allows you to set skills on categories to automatically set those +skills on the order. It also allows you to set the skills to the field service +person with their level. On the order, the list of field service persons is +filtered with the skills and the location so you can only assign the right +person to the order.

+

Table of contents

+ +
+

Installation

+

To install Field Service and have the mapping features, you need to install GeoEngine.

+

Please refer to the installation instructions available at: +https://github.com/OCA/geospatial/tree/11.0/base_geoengine

+
+
+

Configuration

+

To configure this module, you need to:

+
    +
  • Create or edit your categories to set skills
  • +
  • Create or edit your persons to set their skills and skill levels
  • +
  • Create or edit your territories to set their field service persons
  • +
  • Create or edit your locations to set their territories
  • +
+
+
+

Usage

+

To use this module, you need to:

+
    +
  • Create an order, set the template and the location
      +
    • The categories and skills are set based on the template.
    • +
    • The field service person is set to the preferred person if skills matches.
    • +
    • The list of field service persons is filtered with the one serving the +location (using the territory) and having the skills
    • +
    +
  • +
+
+
+

Known issues / Roadmap

+

The roadmap of the Field Service application is documented on +Github.

+
+
+

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 smashing it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Open Source Integrators
  • +
+
+ +
+

Other credits

+

The development of this module has been financially supported by:

+ +
+
+

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.

+

Current maintainers:

+

osi-scampbell max3903

+

This module is part of the OCA/field-service project on GitHub.

+

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

+
+
+
+ + diff --git a/fieldservice_skill/views/fsm_category.xml b/fieldservice_skill/views/fsm_category.xml new file mode 100644 index 0000000000..22b3ac378b --- /dev/null +++ b/fieldservice_skill/views/fsm_category.xml @@ -0,0 +1,17 @@ + + + + + fsm.category.form + fsm.category + + + + + + + + + + + diff --git a/fieldservice_skill/views/fsm_order.xml b/fieldservice_skill/views/fsm_order.xml new file mode 100644 index 0000000000..a61b52baa3 --- /dev/null +++ b/fieldservice_skill/views/fsm_order.xml @@ -0,0 +1,17 @@ + + + + + fsm.order.form + fsm.order + + + + + + + + + diff --git a/fieldservice_skill/views/fsm_person.xml b/fieldservice_skill/views/fsm_person.xml new file mode 100644 index 0000000000..446260d7c6 --- /dev/null +++ b/fieldservice_skill/views/fsm_person.xml @@ -0,0 +1,23 @@ + + + + + fsm.person.form + fsm.person + + + + + + + + + + + + + + + + + diff --git a/fieldservice_skill/views/fsm_person_skill.xml b/fieldservice_skill/views/fsm_person_skill.xml new file mode 100644 index 0000000000..a4b6f3cf50 --- /dev/null +++ b/fieldservice_skill/views/fsm_person_skill.xml @@ -0,0 +1,96 @@ + + + + + + Skills + fsm.person.skill + + + + + + + + + + + fsm.person.skill.form + fsm.person.skill + +
+ + + + + + + + +
+
+
+ + + Person Skills + fsm.person.skill + + form + tree,form + +

+ Create a person skill. +

+
+
+ + + + + + fsm.person.skill.graph + fsm.person.skill + + + + + + + + + + + fsm.person.skill.pivot + fsm.person.skill + + + + + + + + + + + Person Skills + fsm.person.skill + form + graph,pivot + +

+ Person Skills Report +

+
+
+ + + +
diff --git a/fieldservice_skill/views/hr_skill.xml b/fieldservice_skill/views/hr_skill.xml new file mode 100644 index 0000000000..a679fc9594 --- /dev/null +++ b/fieldservice_skill/views/hr_skill.xml @@ -0,0 +1,9 @@ + + + + + From 9899f5ac66abe2697769107448764479c1d27c94 Mon Sep 17 00:00:00 2001 From: Maxime Chambreuil Date: Thu, 13 Dec 2018 19:48:34 -0600 Subject: [PATCH 02/32] [ADD] Security --- fieldservice_skill/README.rst | 6 +++--- fieldservice_skill/__manifest__.py | 3 ++- .../security/ir.model.access.csv | 3 +++ .../static/description/icon.png | Bin 9455 -> 17808 bytes .../static/description/index.html | 6 +++--- 5 files changed, 11 insertions(+), 7 deletions(-) create mode 100644 fieldservice_skill/security/ir.model.access.csv diff --git a/fieldservice_skill/README.rst b/fieldservice_skill/README.rst index 54512d4ffe..714a40ad16 100644 --- a/fieldservice_skill/README.rst +++ b/fieldservice_skill/README.rst @@ -1,6 +1,6 @@ -===================== -Field Service - Skill -===================== +====================== +Field Service - Skills +====================== .. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! This file is generated by oca-gen-addon-readme !! diff --git a/fieldservice_skill/__manifest__.py b/fieldservice_skill/__manifest__.py index 30ed697973..7915570d04 100644 --- a/fieldservice_skill/__manifest__.py +++ b/fieldservice_skill/__manifest__.py @@ -2,7 +2,7 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). { - "name": "Field Service - Skill", + "name": "Field Service - Skills", "summary": "Manage your FS persons skills", "version": "11.0.0.0.1", "category": "Field Service", @@ -14,6 +14,7 @@ "fieldservice", ], "data": [ + "security/ir.model.access.csv", "views/fsm_person.xml", "views/fsm_category.xml", "views/fsm_person_skill.xml", diff --git a/fieldservice_skill/security/ir.model.access.csv b/fieldservice_skill/security/ir.model.access.csv new file mode 100644 index 0000000000..c1fa458247 --- /dev/null +++ b/fieldservice_skill/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_fsm_person_skill_user,fsm.person.skill.user,model_fsm_person_skill,fieldservice.group_fsm_user,1,0,0,0 +access_fsm_person_skill_dispatcher,fsm.person.skill.dispatcher,model_fsm_person_skill,fieldservice.group_fsm_dispatcher,1,1,1,1 diff --git a/fieldservice_skill/static/description/icon.png b/fieldservice_skill/static/description/icon.png index 3a0328b516c4980e8e44cdb63fd945757ddd132d..955674d8f0b8c47de3ffa9db25cb109fbe4a1091 100644 GIT binary patch literal 17808 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 literal 9455 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 z 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 Xviia!U7SGha1wx#SCgwmn*{w2TRX*I diff --git a/fieldservice_skill/static/description/index.html b/fieldservice_skill/static/description/index.html index aab25d1e7c..df7fb3f94a 100644 --- a/fieldservice_skill/static/description/index.html +++ b/fieldservice_skill/static/description/index.html @@ -4,7 +4,7 @@ -Field Service - Skill +Field Service - Skills -
-

Field Service - Skill

+
+

Field Service - Skills

+ + fsm.template.form + fsm.template + + + + + + + + + From 5d65be2495bb728cdcb91ce9211740e831c378a7 Mon Sep 17 00:00:00 2001 From: osi-scampbell Date: Thu, 24 Jan 2019 11:55:47 -0700 Subject: [PATCH 06/32] [IMP] Smart button --- fieldservice_skill/views/hr_skill.xml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/fieldservice_skill/views/hr_skill.xml b/fieldservice_skill/views/hr_skill.xml index a679fc9594..550f0aac1a 100644 --- a/fieldservice_skill/views/hr_skill.xml +++ b/fieldservice_skill/views/hr_skill.xml @@ -1,9 +1,34 @@ + + + hr.skill.form.button + hr.skill + + + +
+ +
+ +
+
+
+
+ + + True + +
+
+ +
From e82f6b0bf0b4790fac31e27747b634fa8339be66 Mon Sep 17 00:00:00 2001 From: osi-scampbell Date: Thu, 24 Jan 2019 12:53:56 -0700 Subject: [PATCH 07/32] [IMP] Added smartbutton --- fieldservice_skill/views/hr_skill.xml | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/fieldservice_skill/views/hr_skill.xml b/fieldservice_skill/views/hr_skill.xml index 550f0aac1a..f079afa3e5 100644 --- a/fieldservice_skill/views/hr_skill.xml +++ b/fieldservice_skill/views/hr_skill.xml @@ -1,22 +1,17 @@ - hr.skill.form.button hr.skill - -
- -
- -
-
-
+ +
+ +
From 6c9947f20c98621514560d840761daae5cf57f9f Mon Sep 17 00:00:00 2001 From: osi-scampbell Date: Fri, 25 Jan 2019 09:41:05 -0700 Subject: [PATCH 08/32] [IMP] Update to 11.0 --- fieldservice_skill/views/hr_skill.xml | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/fieldservice_skill/views/hr_skill.xml b/fieldservice_skill/views/hr_skill.xml index f079afa3e5..4907c301a0 100644 --- a/fieldservice_skill/views/hr_skill.xml +++ b/fieldservice_skill/views/hr_skill.xml @@ -1,24 +1,5 @@ - - - hr.skill.form.button - hr.skill - - - -
- -
-
- - - True - -
-
Date: Fri, 25 Jan 2019 09:42:18 -0700 Subject: [PATCH 09/32] [IMP] Remove line --- fieldservice_skill/views/hr_skill.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/fieldservice_skill/views/hr_skill.xml b/fieldservice_skill/views/hr_skill.xml index 4907c301a0..a679fc9594 100644 --- a/fieldservice_skill/views/hr_skill.xml +++ b/fieldservice_skill/views/hr_skill.xml @@ -6,5 +6,4 @@ action="hr_skill.open_view_skill_form" parent="fieldservice.menu_fsm_config_person" sequence="80"/> -
From e197b84cdd1e2fa53a4ff1049476d89bc562723e Mon Sep 17 00:00:00 2001 From: osi-scampbell Date: Sat, 26 Jan 2019 20:16:15 -0700 Subject: [PATCH 10/32] [IMP] Instructions to Todo --- fieldservice_skill/models/fsm_order.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fieldservice_skill/models/fsm_order.py b/fieldservice_skill/models/fsm_order.py index a3f1a6464b..e725540c1d 100644 --- a/fieldservice_skill/models/fsm_order.py +++ b/fieldservice_skill/models/fsm_order.py @@ -24,4 +24,4 @@ def _onchange_template_id(self): if self.template_id: self.category_ids = self.template_id.category_ids self.skill_ids = self.template_id.skill_ids - self.description = self.template_id.instructions + self.todo = self.template_id.instructions From 4f234fa13c618a818402444122154a305600fef0 Mon Sep 17 00:00:00 2001 From: Maxime Chambreuil Date: Fri, 1 Feb 2019 19:05:53 -0600 Subject: [PATCH 11/32] [FIX] fieldservice_skill --- fieldservice_skill/README.rst | 22 ++++++++--------- fieldservice_skill/__manifest__.py | 5 ++-- fieldservice_skill/models/fsm_person_skill.py | 5 ++-- fieldservice_skill/readme/CONFIGURE.rst | 4 ++-- fieldservice_skill/readme/DESCRIPTION.rst | 14 +++++------ fieldservice_skill/readme/USAGE.rst | 4 ++-- .../static/description/index.html | 22 ++++++++--------- fieldservice_skill/views/fsm_person.xml | 2 +- fieldservice_skill/views/fsm_person_skill.xml | 24 +++++++++---------- 9 files changed, 51 insertions(+), 51 deletions(-) diff --git a/fieldservice_skill/README.rst b/fieldservice_skill/README.rst index 714a40ad16..ea79572434 100644 --- a/fieldservice_skill/README.rst +++ b/fieldservice_skill/README.rst @@ -25,18 +25,18 @@ Field Service - Skills |badge1| |badge2| |badge3| |badge4| |badge5| -Odoo Field Service App allows to assign any FS person to any FS order. -For some organizations, they cannot assign any FS person to any order. -They needs to manage the skills of the FS persons and reduce the list of -potential FS persons on an order to avoid wrong assignment and mis-configuration. -The skills of the selectable FS persons on a service order needs to match the +Odoo Field Service App allows to assign any FS worker to any FS order. +For some organizations, they cannot assign any FS worker to any order. +They needs to manage the skills of the FS workers and reduce the list of +potential FS workers on an order to avoid wrong assignment and mis-configuration. +The skills of the selectable FS workers on a service order needs to match the required skills to perform the order. This modules allows you to set skills on categories to automatically set those skills on the order. It also allows you to set the skills to the field service -person with their level. On the order, the list of field service persons is +worker with their level. On the order, the list of field service workers is filtered with the skills and the location so you can only assign the right -person to the order. +worker to the order. **Table of contents** @@ -57,8 +57,8 @@ Configuration To configure this module, you need to: * Create or edit your categories to set skills -* Create or edit your persons to set their skills and skill levels -* Create or edit your territories to set their field service persons +* Create or edit your workers to set their skills and skill levels +* Create or edit your territories to set their field service workers * Create or edit your locations to set their territories Usage @@ -69,8 +69,8 @@ To use this module, you need to: * Create an order, set the template and the location * The categories and skills are set based on the template. - * The field service person is set to the preferred person if skills matches. - * The list of field service persons is filtered with the one serving the + * The field service worker is set to the preferred worker if skills matches. + * The list of field service workers is filtered with the one serving the location (using the territory) and having the skills Known issues / Roadmap diff --git a/fieldservice_skill/__manifest__.py b/fieldservice_skill/__manifest__.py index a142b365b1..db6b8cf191 100644 --- a/fieldservice_skill/__manifest__.py +++ b/fieldservice_skill/__manifest__.py @@ -3,8 +3,8 @@ { "name": "Field Service - Skills", - "summary": "Manage your FS persons skills", - "version": "11.0.0.1.0", + "summary": "Manage your FS workers skills", + "version": "11.0.0.2.0", "category": "Field Service", "license": "AGPL-3", "author": "Open Source Integrators, Odoo Community Association (OCA)", @@ -22,7 +22,6 @@ "views/hr_skill.xml", "views/fsm_template.xml" ], - "installable": True, "development_status": "Beta", "maintainers": [ "osi-scampbell", diff --git a/fieldservice_skill/models/fsm_person_skill.py b/fieldservice_skill/models/fsm_person_skill.py index 0e537a015a..be54c842ed 100644 --- a/fieldservice_skill/models/fsm_person_skill.py +++ b/fieldservice_skill/models/fsm_person_skill.py @@ -6,14 +6,15 @@ class FSMPersonSkill(models.Model): _name = 'fsm.person.skill' - _description = 'Field Service Person Skill' + _description = 'Field Service Worker Skill' LEVEL = [('0', 'Junior'), ('1', 'Intermediate'), ('2', 'Senior'), ('3', 'Expert')] - person_id = fields.Many2one('fsm.person', string="Field Service Person") + person_id = fields.Many2one('fsm.person', string="Field Service Worker", + required=True) skill_id = fields.Many2one('hr.skill', string="Skill", required=True) level = fields.Selection(LEVEL, string='Level', default=LEVEL[0][0]) diff --git a/fieldservice_skill/readme/CONFIGURE.rst b/fieldservice_skill/readme/CONFIGURE.rst index da3b6aee62..30e5a22dd4 100644 --- a/fieldservice_skill/readme/CONFIGURE.rst +++ b/fieldservice_skill/readme/CONFIGURE.rst @@ -1,6 +1,6 @@ To configure this module, you need to: * Create or edit your categories to set skills -* Create or edit your persons to set their skills and skill levels -* Create or edit your territories to set their field service persons +* Create or edit your workers to set their skills and skill levels +* Create or edit your territories to set their field service workers * Create or edit your locations to set their territories diff --git a/fieldservice_skill/readme/DESCRIPTION.rst b/fieldservice_skill/readme/DESCRIPTION.rst index 5e82e78e4e..cb08056e8d 100644 --- a/fieldservice_skill/readme/DESCRIPTION.rst +++ b/fieldservice_skill/readme/DESCRIPTION.rst @@ -1,12 +1,12 @@ -Odoo Field Service App allows to assign any FS person to any FS order. -For some organizations, they cannot assign any FS person to any order. -They needs to manage the skills of the FS persons and reduce the list of -potential FS persons on an order to avoid wrong assignment and mis-configuration. -The skills of the selectable FS persons on a service order needs to match the +Odoo Field Service App allows to assign any FS worker to any FS order. +For some organizations, they cannot assign any FS worker to any order. +They needs to manage the skills of the FS workers and reduce the list of +potential FS workers on an order to avoid wrong assignment and mis-configuration. +The skills of the selectable FS workers on a service order needs to match the required skills to perform the order. This modules allows you to set skills on categories to automatically set those skills on the order. It also allows you to set the skills to the field service -person with their level. On the order, the list of field service persons is +worker with their level. On the order, the list of field service workers is filtered with the skills and the location so you can only assign the right -person to the order. +worker to the order. diff --git a/fieldservice_skill/readme/USAGE.rst b/fieldservice_skill/readme/USAGE.rst index 7371806917..271c3da109 100644 --- a/fieldservice_skill/readme/USAGE.rst +++ b/fieldservice_skill/readme/USAGE.rst @@ -3,6 +3,6 @@ To use this module, you need to: * Create an order, set the template and the location * The categories and skills are set based on the template. - * The field service person is set to the preferred person if skills matches. - * The list of field service persons is filtered with the one serving the + * The field service worker is set to the preferred worker if skills matches. + * The list of field service workers is filtered with the one serving the location (using the territory) and having the skills diff --git a/fieldservice_skill/static/description/index.html b/fieldservice_skill/static/description/index.html index df7fb3f94a..6a28bb169d 100644 --- a/fieldservice_skill/static/description/index.html +++ b/fieldservice_skill/static/description/index.html @@ -368,17 +368,17 @@

Field Service - Skills

!! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

Beta License: AGPL-3 OCA/field-service Translate me on Weblate Try me on Runbot

-

Odoo Field Service App allows to assign any FS person to any FS order. -For some organizations, they cannot assign any FS person to any order. -They needs to manage the skills of the FS persons and reduce the list of -potential FS persons on an order to avoid wrong assignment and mis-configuration. -The skills of the selectable FS persons on a service order needs to match the +

Odoo Field Service App allows to assign any FS worker to any FS order. +For some organizations, they cannot assign any FS worker to any order. +They needs to manage the skills of the FS workers and reduce the list of +potential FS workers on an order to avoid wrong assignment and mis-configuration. +The skills of the selectable FS workers on a service order needs to match the required skills to perform the order.

This modules allows you to set skills on categories to automatically set those skills on the order. It also allows you to set the skills to the field service -person with their level. On the order, the list of field service persons is +worker with their level. On the order, the list of field service workers is filtered with the skills and the location so you can only assign the right -person to the order.

+worker to the order.

Table of contents

    @@ -407,8 +407,8 @@

    Configuration

    To configure this module, you need to:

    • Create or edit your categories to set skills
    • -
    • Create or edit your persons to set their skills and skill levels
    • -
    • Create or edit your territories to set their field service persons
    • +
    • Create or edit your workers to set their skills and skill levels
    • +
    • Create or edit your territories to set their field service workers
    • Create or edit your locations to set their territories
@@ -418,8 +418,8 @@

Usage

  • Create an order, set the template and the location
    • The categories and skills are set based on the template.
    • -
    • The field service person is set to the preferred person if skills matches.
    • -
    • The list of field service persons is filtered with the one serving the +
    • The field service worker is set to the preferred worker if skills matches.
    • +
    • The list of field service workers is filtered with the one serving the location (using the territory) and having the skills
  • diff --git a/fieldservice_skill/views/fsm_person.xml b/fieldservice_skill/views/fsm_person.xml index 0f72acbd4c..3c40120592 100644 --- a/fieldservice_skill/views/fsm_person.xml +++ b/fieldservice_skill/views/fsm_person.xml @@ -1,6 +1,6 @@ - + fsm.person.form fsm.person diff --git a/fieldservice_skill/views/fsm_person_skill.xml b/fieldservice_skill/views/fsm_person_skill.xml index a4b6f3cf50..68b69d47ff 100644 --- a/fieldservice_skill/views/fsm_person_skill.xml +++ b/fieldservice_skill/views/fsm_person_skill.xml @@ -6,7 +6,7 @@ Skills fsm.person.skill - + @@ -18,34 +18,34 @@ fsm.person.skill.form fsm.person.skill -
    + + - - +
    - Person Skills + Worker Skills fsm.person.skill form tree,form

    - Create a person skill. + Create a worker skill.

    @@ -55,7 +55,7 @@ fsm.person.skill.graph fsm.person.skill - + @@ -67,7 +67,7 @@ fsm.person.skill.pivot fsm.person.skill - + @@ -76,19 +76,19 @@ - Person Skills + Worker Skills fsm.person.skill form graph,pivot

    - Person Skills Report + Worker Skills Report

    From d88b61b52b22fe2d385711eec7cbbc7700474a72 Mon Sep 17 00:00:00 2001 From: Maxime Chambreuil Date: Fri, 8 Feb 2019 00:11:23 -0600 Subject: [PATCH 12/32] [FIX] fieldservice_skill - Call super --- fieldservice_skill/models/fsm_order.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fieldservice_skill/models/fsm_order.py b/fieldservice_skill/models/fsm_order.py index e725540c1d..e0eb3bdc88 100644 --- a/fieldservice_skill/models/fsm_order.py +++ b/fieldservice_skill/models/fsm_order.py @@ -22,6 +22,5 @@ def _onchange_category_ids(self): @api.onchange('template_id') def _onchange_template_id(self): if self.template_id: - self.category_ids = self.template_id.category_ids + super(FSMOrder, self)._onchange_template_id() self.skill_ids = self.template_id.skill_ids - self.todo = self.template_id.instructions From af139a9d7c51273c7672b3017bd0ec999773c545 Mon Sep 17 00:00:00 2001 From: scampbell Date: Fri, 8 Mar 2019 13:20:47 -0800 Subject: [PATCH 13/32] [IMP] FSM Skill Bug Fix --- fieldservice_skill/views/fsm_person.xml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/fieldservice_skill/views/fsm_person.xml b/fieldservice_skill/views/fsm_person.xml index 3c40120592..b3ff064371 100644 --- a/fieldservice_skill/views/fsm_person.xml +++ b/fieldservice_skill/views/fsm_person.xml @@ -18,4 +18,15 @@
    + + + fsm.person.form + fsm.person + + + + + + +
    From 1ce4f9c5b6de864a7f27d89ab50b40696f36dbe1 Mon Sep 17 00:00:00 2001 From: Maxime Chambreuil Date: Sat, 16 Mar 2019 14:43:19 -0600 Subject: [PATCH 14/32] [FIX] fieldservice_skill: duplicate record --- fieldservice_skill/views/fsm_person.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fieldservice_skill/views/fsm_person.xml b/fieldservice_skill/views/fsm_person.xml index b3ff064371..71a65889cb 100644 --- a/fieldservice_skill/views/fsm_person.xml +++ b/fieldservice_skill/views/fsm_person.xml @@ -19,8 +19,8 @@ - - fsm.person.form + + fsm.person.search fsm.person From 429db78df0b7eab72ea7fbe3ead0fe3d7732ddca Mon Sep 17 00:00:00 2001 From: Murtuza Saleh Date: Thu, 4 Apr 2019 18:16:00 +0530 Subject: [PATCH 15/32] [MIG][WIP][12.0] fieldservice_skill --- fieldservice_skill/README.rst | 13 +++++++------ fieldservice_skill/__manifest__.py | 3 ++- fieldservice_skill/models/fsm_order.py | 6 ++---- fieldservice_skill/models/fsm_person_skill.py | 1 + fieldservice_skill/readme/CONTRIBUTORS.rst | 1 + fieldservice_skill/readme/INSTALL.rst | 2 +- fieldservice_skill/static/description/index.html | 11 ++++++----- fieldservice_skill/views/fsm_person_skill.xml | 14 ++++++++------ 8 files changed, 28 insertions(+), 23 deletions(-) diff --git a/fieldservice_skill/README.rst b/fieldservice_skill/README.rst index ea79572434..1da54e52ff 100644 --- a/fieldservice_skill/README.rst +++ b/fieldservice_skill/README.rst @@ -14,13 +14,13 @@ Field Service - Skills :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Ffield--service-lightgray.png?logo=github - :target: https://github.com/OCA/field-service/tree/11.0/fieldservice_skill + :target: https://github.com/OCA/field-service/tree/12.0/fieldservice_skill :alt: OCA/field-service .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/field-service-11-0/field-service-11-0-fieldservice_skill + :target: https://translation.odoo-community.org/projects/field-service-12-0/field-service-12-0-fieldservice_skill :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png - :target: https://runbot.odoo-community.org/runbot/264/11.0 + :target: https://runbot.odoo-community.org/runbot/264/12.0 :alt: Try me on Runbot |badge1| |badge2| |badge3| |badge4| |badge5| @@ -49,7 +49,7 @@ Installation To install Field Service and have the mapping features, you need to install GeoEngine. Please refer to the installation instructions available at: -https://github.com/OCA/geospatial/tree/11.0/base_geoengine +https://github.com/OCA/geospatial/tree/12.0/base_geoengine Configuration ============= @@ -85,7 +85,7 @@ 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 smashing it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -103,6 +103,7 @@ Contributors * Wolfgang Hall * Maxime Chambreuil * Steve Campbell +* Serpent Consulting Services Pvt. Ltd. Other credits ~~~~~~~~~~~~~ @@ -135,6 +136,6 @@ Current `maintainers `__: |maintainer-osi-scampbell| |maintainer-max3903| -This module is part of the `OCA/field-service `_ project on GitHub. +This module is part of the `OCA/field-service `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/fieldservice_skill/__manifest__.py b/fieldservice_skill/__manifest__.py index db6b8cf191..3653d9974e 100644 --- a/fieldservice_skill/__manifest__.py +++ b/fieldservice_skill/__manifest__.py @@ -4,7 +4,7 @@ { "name": "Field Service - Skills", "summary": "Manage your FS workers skills", - "version": "11.0.0.2.0", + "version": "12.0.1.0.0", "category": "Field Service", "license": "AGPL-3", "author": "Open Source Integrators, Odoo Community Association (OCA)", @@ -27,4 +27,5 @@ "osi-scampbell", "max3903", ], + 'installable': True, } diff --git a/fieldservice_skill/models/fsm_order.py b/fieldservice_skill/models/fsm_order.py index e0eb3bdc88..ffef817ba0 100644 --- a/fieldservice_skill/models/fsm_order.py +++ b/fieldservice_skill/models/fsm_order.py @@ -1,12 +1,10 @@ # Copyright (C) 2018 - TODAY, Open Source Integrators # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import api, fields +from odoo import api, fields, models -from odoo.addons.base_geoengine import geo_model - -class FSMOrder(geo_model.GeoModel): +class FSMOrder(models.Model): _inherit = 'fsm.order' skill_ids = fields.Many2many('hr.skill', string="Required Skills") diff --git a/fieldservice_skill/models/fsm_person_skill.py b/fieldservice_skill/models/fsm_person_skill.py index be54c842ed..886c8c47fe 100644 --- a/fieldservice_skill/models/fsm_person_skill.py +++ b/fieldservice_skill/models/fsm_person_skill.py @@ -6,6 +6,7 @@ class FSMPersonSkill(models.Model): _name = 'fsm.person.skill' + _rec_name = 'skill_id' _description = 'Field Service Worker Skill' LEVEL = [('0', 'Junior'), diff --git a/fieldservice_skill/readme/CONTRIBUTORS.rst b/fieldservice_skill/readme/CONTRIBUTORS.rst index db6ccc051b..c72bec9f3b 100644 --- a/fieldservice_skill/readme/CONTRIBUTORS.rst +++ b/fieldservice_skill/readme/CONTRIBUTORS.rst @@ -1,3 +1,4 @@ * Wolfgang Hall * Maxime Chambreuil * Steve Campbell +* Serpent Consulting Services Pvt. Ltd. diff --git a/fieldservice_skill/readme/INSTALL.rst b/fieldservice_skill/readme/INSTALL.rst index c010f8f6a2..8571f65376 100644 --- a/fieldservice_skill/readme/INSTALL.rst +++ b/fieldservice_skill/readme/INSTALL.rst @@ -1,4 +1,4 @@ To install Field Service and have the mapping features, you need to install GeoEngine. Please refer to the installation instructions available at: -https://github.com/OCA/geospatial/tree/11.0/base_geoengine +https://github.com/OCA/geospatial/tree/12.0/base_geoengine diff --git a/fieldservice_skill/static/description/index.html b/fieldservice_skill/static/description/index.html index 6a28bb169d..7360967242 100644 --- a/fieldservice_skill/static/description/index.html +++ b/fieldservice_skill/static/description/index.html @@ -3,7 +3,7 @@ - + Field Service - Skills - - -
    -

    Field Service - Skills

    - - -

    Beta License: AGPL-3 OCA/field-service Translate me on Weblate Try me on Runbot

    -

    Odoo Field Service App allows to assign any FS worker to any FS order. -For some organizations, they cannot assign any FS worker to any order. -They needs to manage the skills of the FS workers and reduce the list of -potential FS workers on an order to avoid wrong assignment and mis-configuration. -The skills of the selectable FS workers on a service order needs to match the -required skills to perform the order.

    -

    This modules allows you to set skills on categories to automatically set those -skills on the order. It also allows you to set the skills to the field service -worker with their level. On the order, the list of field service workers is -filtered with the skills and the location so you can only assign the right -worker to the order.

    -

    Table of contents

    - -
    -

    Installation

    -

    To install Field Service and have the mapping features, you need to install GeoEngine.

    -

    Please refer to the installation instructions available at: -https://github.com/OCA/geospatial/tree/12.0/base_geoengine

    -
    -
    -

    Configuration

    -

    To configure this module, you need to:

    -
      -
    • Create or edit your categories to set skills
    • -
    • Create or edit your workers to set their skills and skill levels
    • -
    • Create or edit your territories to set their field service workers
    • -
    • Create or edit your locations to set their territories
    • -
    -
    -
    -

    Usage

    -

    To use this module, you need to:

    -
      -
    • Create an order, set the template and the location
        -
      • The categories and skills are set based on the template.
      • -
      • The field service worker is set to the preferred worker if skills matches.
      • -
      • The list of field service workers is filtered with the one serving the -location (using the territory) and having the skills
      • -
      -
    • -
    -
    -
    -

    Known issues / Roadmap

    -

    The roadmap of the Field Service application is documented on -Github.

    -
    -
    -

    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 smashing it by providing a detailed and welcomed -feedback.

    -

    Do not contact contributors directly about support or help with technical issues.

    -
    -
    -

    Credits

    -
    -

    Authors

    -
      -
    • Open Source Integrators
    • -
    -
    -
    -

    Contributors

    - -
    -
    -

    Other credits

    -

    The development of this module has been financially supported by:

    - -
    -
    -

    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.

    -

    Current maintainers:

    -

    osi-scampbell max3903

    -

    This module is part of the OCA/field-service project on GitHub.

    -

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

    -
    -
    -
    - +

    + Beta + License: AGPL-3 + OCA/field-service + Translate me on Weblate + Try me on Runbot +

    +

    + Odoo Field Service App allows to assign any FS worker to any FS order. For some + organizations, they cannot assign any FS worker to any order. They needs to + manage the skills of the FS workers and reduce the list of potential FS workers + on an order to avoid wrong assignment and mis-configuration. The skills of the + selectable FS workers on a service order needs to match the required skills to + perform the order. +

    +

    + This modules allows you to set skills on categories to automatically set those + skills on the order. It also allows you to set the skills to the field service + worker with their level. On the order, the list of field service workers is + filtered with the skills and the location so you can only assign the right + worker to the order. +

    +

    Table of contents

    +
    + +
    +
    +

    Installation

    +

    + To install Field Service and have the mapping features, you need to install + GeoEngine. +

    +

    + Please refer to the installation instructions available at: + https://github.com/OCA/geospatial/tree/12.0/base_geoengine +

    +
    +
    +

    Configuration

    +

    To configure this module, you need to:

    +
      +
    • Create or edit your categories to set skills
    • +
    • Create or edit your workers to set their skills and skill levels
    • +
    • Create or edit your territories to set their field service workers
    • +
    • Create or edit your locations to set their territories
    • +
    +
    +
    +

    Usage

    +

    To use this module, you need to:

    +
      +
    • + Create an order, set the template and the location +
        +
      • The categories and skills are set based on the template.
      • +
      • + The field service worker is set to the preferred worker if skills + matches. +
      • +
      • + The list of field service workers is filtered with the one serving the + location (using the territory) and having the skills +
      • +
      +
    • +
    +
    +
    +

    Known issues / Roadmap

    +

    + The roadmap of the Field Service application is documented on + Github. +

    +
    +
    +

    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 smashing it by providing a detailed + and welcomed + feedback. +

    +

    + Do not contact contributors directly about support or help with technical + issues. +

    +
    +
    +

    Credits

    +
    +

    Authors

    +
      +
    • Open Source Integrators
    • +
    +
    +
    +

    Contributors

    + +
    +
    +

    Other credits

    +

    The development of this module has been financially supported by:

    + +
    +
    +

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

    +

    + Current + maintainers: +

    +

    + osi-scampbell + max3903 +

    +

    + This module is part of the + OCA/field-service + project on GitHub. +

    +

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

    +
    +
    +
+ diff --git a/fieldservice_skill/views/fsm_category.xml b/fieldservice_skill/views/fsm_category.xml index 22b3ac378b..3dfabd30eb 100644 --- a/fieldservice_skill/views/fsm_category.xml +++ b/fieldservice_skill/views/fsm_category.xml @@ -1,17 +1,16 @@ - + fsm.category.form fsm.category - + - + - diff --git a/fieldservice_skill/views/fsm_order.xml b/fieldservice_skill/views/fsm_order.xml index 62dd81b2fa..b2cd361626 100644 --- a/fieldservice_skill/views/fsm_order.xml +++ b/fieldservice_skill/views/fsm_order.xml @@ -1,17 +1,18 @@ - + fsm.order.form fsm.order - + - + - diff --git a/fieldservice_skill/views/fsm_person.xml b/fieldservice_skill/views/fsm_person.xml index 71a65889cb..0cb157a57d 100644 --- a/fieldservice_skill/views/fsm_person.xml +++ b/fieldservice_skill/views/fsm_person.xml @@ -1,31 +1,30 @@ - + fsm.person.form fsm.person - + - - + + - fsm.person.search fsm.person - + - + diff --git a/fieldservice_skill/views/fsm_person_skill.xml b/fieldservice_skill/views/fsm_person_skill.xml index 7597530657..283c929167 100644 --- a/fieldservice_skill/views/fsm_person_skill.xml +++ b/fieldservice_skill/views/fsm_person_skill.xml @@ -1,19 +1,17 @@ - + - Skills fsm.person.skill - - - + + + - fsm.person.skill.form fsm.person.skill @@ -22,21 +20,20 @@ - - - + + + - + - Worker Skills fsm.person.skill - + form tree,form @@ -45,38 +42,36 @@

- - - + fsm.person.skill.graph fsm.person.skill - - - + + + - fsm.person.skill.pivot fsm.person.skill - - - + + + - Worker Skills fsm.person.skill @@ -88,11 +83,11 @@

- - - +
diff --git a/fieldservice_skill/views/fsm_template.xml b/fieldservice_skill/views/fsm_template.xml index 0b281538ee..6f574cbe3f 100644 --- a/fieldservice_skill/views/fsm_template.xml +++ b/fieldservice_skill/views/fsm_template.xml @@ -1,17 +1,18 @@ - + fsm.template.form fsm.template - + - + - diff --git a/fieldservice_skill/views/hr_skill.xml b/fieldservice_skill/views/hr_skill.xml index a679fc9594..66c2367c8f 100644 --- a/fieldservice_skill/views/hr_skill.xml +++ b/fieldservice_skill/views/hr_skill.xml @@ -1,9 +1,10 @@ - + - - + From 6ae0b9238f701c273e9cb5986905f1dd0266116d Mon Sep 17 00:00:00 2001 From: brian10048 Date: Tue, 21 Jul 2020 00:17:07 -0400 Subject: [PATCH 28/32] [MIG] fieldservice_skill: Migration to 13.0 --- fieldservice_skill/__manifest__.py | 4 ++-- fieldservice_skill/models/fsm_category.py | 2 +- fieldservice_skill/models/fsm_order.py | 2 +- fieldservice_skill/models/fsm_person.py | 2 +- fieldservice_skill/models/fsm_person_skill.py | 2 +- fieldservice_skill/models/fsm_template.py | 2 +- fieldservice_skill/readme/CONTRIBUTORS.rst | 1 + fieldservice_skill/readme/INSTALL.rst | 2 +- fieldservice_skill/views/fsm_person_skill.xml | 2 -- fieldservice_skill/views/hr_skill.xml | 2 +- setup/fieldservice_skill/odoo/addons/fieldservice_skill | 1 + setup/fieldservice_skill/setup.py | 6 ++++++ 12 files changed, 17 insertions(+), 11 deletions(-) create mode 120000 setup/fieldservice_skill/odoo/addons/fieldservice_skill create mode 100644 setup/fieldservice_skill/setup.py diff --git a/fieldservice_skill/__manifest__.py b/fieldservice_skill/__manifest__.py index 7b4455c8eb..77e3094528 100644 --- a/fieldservice_skill/__manifest__.py +++ b/fieldservice_skill/__manifest__.py @@ -4,12 +4,12 @@ { "name": "Field Service - Skills", "summary": "Manage your Field Service workers skills", - "version": "12.0.1.0.0", + "version": "13.0.1.0.0", "category": "Field Service", "license": "AGPL-3", "author": "Open Source Integrators, Odoo Community Association (OCA)", "website": "https://github.com/OCA/field-service", - "depends": ["hr_skill", "fieldservice"], + "depends": ["hr_skills", "fieldservice"], "data": [ "security/ir.model.access.csv", "views/fsm_person.xml", diff --git a/fieldservice_skill/models/fsm_category.py b/fieldservice_skill/models/fsm_category.py index e29aea3696..2308982978 100644 --- a/fieldservice_skill/models/fsm_category.py +++ b/fieldservice_skill/models/fsm_category.py @@ -1,4 +1,4 @@ -# Copyright (C) 2018 - TODAY, Open Source Integrators +# Copyright (C) 2018, Open Source Integrators # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo import fields, models diff --git a/fieldservice_skill/models/fsm_order.py b/fieldservice_skill/models/fsm_order.py index 093066eab4..11063a4b00 100644 --- a/fieldservice_skill/models/fsm_order.py +++ b/fieldservice_skill/models/fsm_order.py @@ -1,4 +1,4 @@ -# Copyright (C) 2018 - TODAY, Open Source Integrators +# Copyright (C) 2018, Open Source Integrators # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo import api, fields, models diff --git a/fieldservice_skill/models/fsm_person.py b/fieldservice_skill/models/fsm_person.py index e74a89badf..c3080556e0 100644 --- a/fieldservice_skill/models/fsm_person.py +++ b/fieldservice_skill/models/fsm_person.py @@ -1,4 +1,4 @@ -# Copyright (C) 2018 - TODAY, Open Source Integrators +# Copyright (C) 2018, Open Source Integrators # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo import fields, models diff --git a/fieldservice_skill/models/fsm_person_skill.py b/fieldservice_skill/models/fsm_person_skill.py index 8bbfdd7581..c4bbc9a688 100644 --- a/fieldservice_skill/models/fsm_person_skill.py +++ b/fieldservice_skill/models/fsm_person_skill.py @@ -1,4 +1,4 @@ -# Copyright (C) 2018 - TODAY, Open Source Integrators +# Copyright (C) 2018, Open Source Integrators # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo import fields, models diff --git a/fieldservice_skill/models/fsm_template.py b/fieldservice_skill/models/fsm_template.py index 449fd517bf..d8b8707ed0 100644 --- a/fieldservice_skill/models/fsm_template.py +++ b/fieldservice_skill/models/fsm_template.py @@ -1,4 +1,4 @@ -# Copyright (C) 2018 - TODAY, Open Source Integrators +# Copyright (C) 2018, Open Source Integrators # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo import fields, models diff --git a/fieldservice_skill/readme/CONTRIBUTORS.rst b/fieldservice_skill/readme/CONTRIBUTORS.rst index c72bec9f3b..45d16a07ab 100644 --- a/fieldservice_skill/readme/CONTRIBUTORS.rst +++ b/fieldservice_skill/readme/CONTRIBUTORS.rst @@ -2,3 +2,4 @@ * Maxime Chambreuil * Steve Campbell * Serpent Consulting Services Pvt. Ltd. +* Brian McMaster diff --git a/fieldservice_skill/readme/INSTALL.rst b/fieldservice_skill/readme/INSTALL.rst index 8571f65376..e5355c4b0f 100644 --- a/fieldservice_skill/readme/INSTALL.rst +++ b/fieldservice_skill/readme/INSTALL.rst @@ -1,4 +1,4 @@ To install Field Service and have the mapping features, you need to install GeoEngine. Please refer to the installation instructions available at: -https://github.com/OCA/geospatial/tree/12.0/base_geoengine +https://github.com/OCA/geospatial/tree/13.0/base_geoengine diff --git a/fieldservice_skill/views/fsm_person_skill.xml b/fieldservice_skill/views/fsm_person_skill.xml index 283c929167..584c68a624 100644 --- a/fieldservice_skill/views/fsm_person_skill.xml +++ b/fieldservice_skill/views/fsm_person_skill.xml @@ -34,7 +34,6 @@ Worker Skills fsm.person.skill - form tree,form

@@ -75,7 +74,6 @@ Worker Skills fsm.person.skill - form graph,pivot

diff --git a/fieldservice_skill/views/hr_skill.xml b/fieldservice_skill/views/hr_skill.xml index 66c2367c8f..a8f57911d3 100644 --- a/fieldservice_skill/views/hr_skill.xml +++ b/fieldservice_skill/views/hr_skill.xml @@ -3,7 +3,7 @@ diff --git a/setup/fieldservice_skill/odoo/addons/fieldservice_skill b/setup/fieldservice_skill/odoo/addons/fieldservice_skill new file mode 120000 index 0000000000..2a9978ec32 --- /dev/null +++ b/setup/fieldservice_skill/odoo/addons/fieldservice_skill @@ -0,0 +1 @@ +../../../../fieldservice_skill \ No newline at end of file diff --git a/setup/fieldservice_skill/setup.py b/setup/fieldservice_skill/setup.py new file mode 100644 index 0000000000..28c57bb640 --- /dev/null +++ b/setup/fieldservice_skill/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) From 0a2a0803bb6678bac121c615e7250c3a6394894a Mon Sep 17 00:00:00 2001 From: Brian McMaster Date: Thu, 15 Oct 2020 12:32:24 -0400 Subject: [PATCH 29/32] [IMP] fieldservice_skill: Add back the color field --- fieldservice_skill/models/__init__.py | 1 + fieldservice_skill/models/hr_skill.py | 10 ++++++++++ fieldservice_skill/views/hr_skill.xml | 11 ++++++++++- 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 fieldservice_skill/models/hr_skill.py diff --git a/fieldservice_skill/models/__init__.py b/fieldservice_skill/models/__init__.py index d10774c085..729a9f51c3 100644 --- a/fieldservice_skill/models/__init__.py +++ b/fieldservice_skill/models/__init__.py @@ -6,3 +6,4 @@ from . import fsm_category from . import fsm_order from . import fsm_template +from . import hr_skill diff --git a/fieldservice_skill/models/hr_skill.py b/fieldservice_skill/models/hr_skill.py new file mode 100644 index 0000000000..6f9bfe6ab6 --- /dev/null +++ b/fieldservice_skill/models/hr_skill.py @@ -0,0 +1,10 @@ +# Copyright (C) 2020, Brian McMaster +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class HRSkill(models.Model): + _inherit = "hr.skill" + + color = fields.Integer(string="Color Index", default=10,) diff --git a/fieldservice_skill/views/hr_skill.xml b/fieldservice_skill/views/hr_skill.xml index a8f57911d3..83f42c8308 100644 --- a/fieldservice_skill/views/hr_skill.xml +++ b/fieldservice_skill/views/hr_skill.xml @@ -1,5 +1,14 @@ - + + hr.skill.fsm.form + hr.skill + + + + + + + Date: Thu, 15 Oct 2020 13:35:45 -0400 Subject: [PATCH 30/32] [IMP] fieldservice_skill: Filter order workers --- fieldservice_skill/models/fsm_order.py | 30 ++++++++++++++++++++++++++ fieldservice_skill/views/fsm_order.xml | 6 ++++++ 2 files changed, 36 insertions(+) diff --git a/fieldservice_skill/models/fsm_order.py b/fieldservice_skill/models/fsm_order.py index 11063a4b00..ee1662b9d1 100644 --- a/fieldservice_skill/models/fsm_order.py +++ b/fieldservice_skill/models/fsm_order.py @@ -1,13 +1,23 @@ # Copyright (C) 2018, Open Source Integrators +# Copyright (C) 2020, Brian McMaster # 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 FSMOrder(models.Model): _inherit = "fsm.order" skill_ids = fields.Many2many("hr.skill", string="Required Skills") + skill_worker_ids = fields.Many2many( + "fsm.person", + "fsm_order_skill_workers_rel", + compute="_compute_skill_workers", + help="Available workers based on skill requirements", + ) @api.onchange("category_ids") def _onchange_category_ids(self): @@ -22,3 +32,23 @@ def _onchange_template_id(self): if self.template_id: super(FSMOrder, self)._onchange_template_id() self.skill_ids = self.template_id.skill_ids + + @api.depends("skill_ids") + @api.onchange("skill_ids") + def _compute_skill_workers(self): + worker_ids = [] + req_skills = self.skill_ids.ids + if not self.skill_ids: + worker_ids = self.env["fsm.person"].search([]).ids + else: + FPS = self.env["fsm.person.skill"] + potential_workers = FPS.search( + [("skill_id", "in", self.skill_ids.ids)] + ).mapped("person_id") + for w in potential_workers: + worker_skills = FPS.search([("person_id", "=", w.id)]).mapped( + "skill_id" + ) + if set(worker_skills.ids) >= set(req_skills): + worker_ids.append(w.id) + self.skill_worker_ids = [(6, 0, worker_ids)] diff --git a/fieldservice_skill/views/fsm_order.xml b/fieldservice_skill/views/fsm_order.xml index b2cd361626..a7615b7214 100644 --- a/fieldservice_skill/views/fsm_order.xml +++ b/fieldservice_skill/views/fsm_order.xml @@ -12,6 +12,12 @@ widget="many2many_tags" options="{'color_field': 'color'}" /> + + + + + [("id", "in", skill_worker_ids)] + From cef004cf255c045f01815bb67e1db3d280e91d10 Mon Sep 17 00:00:00 2001 From: Brian McMaster Date: Thu, 29 Oct 2020 17:07:51 -0400 Subject: [PATCH 31/32] [IMP] fieldservice_skill: Skill views Adapted FSM Person Skills to mimic Odoo v13 behavior of Employee Skills. - Skill progress level instead of priority - Updated views on FSM Person form --- fieldservice_skill/models/fsm_person_skill.py | 28 ++++++++-- fieldservice_skill/views/fsm_person.xml | 26 +++++++--- fieldservice_skill/views/fsm_person_skill.xml | 52 ++++++------------- 3 files changed, 60 insertions(+), 46 deletions(-) diff --git a/fieldservice_skill/models/fsm_person_skill.py b/fieldservice_skill/models/fsm_person_skill.py index c4bbc9a688..7070480a7f 100644 --- a/fieldservice_skill/models/fsm_person_skill.py +++ b/fieldservice_skill/models/fsm_person_skill.py @@ -1,7 +1,9 @@ # Copyright (C) 2018, Open Source Integrators +# Copyright (C) 2020, Brian McMaster # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import fields, models +from odoo import _, api, fields, models +from odoo.exceptions import ValidationError class FSMPersonSkill(models.Model): @@ -9,13 +11,13 @@ class FSMPersonSkill(models.Model): _rec_name = "skill_id" _description = "Field Service Worker Skill" - LEVEL = [("0", "Junior"), ("1", "Intermediate"), ("2", "Senior"), ("3", "Expert")] - person_id = fields.Many2one( "fsm.person", string="Field Service Worker", required=True ) skill_id = fields.Many2one("hr.skill", string="Skill", required=True) - level = fields.Selection(LEVEL, string="Level", default=LEVEL[0][0]) + skill_level_id = fields.Many2one("hr.skill.level", required=True) + skill_type_id = fields.Many2one("hr.skill.type", required=True) + level_progress = fields.Integer(related="skill_level_id.level_progress", store=True) _sql_constraints = [ ( @@ -24,3 +26,21 @@ class FSMPersonSkill(models.Model): "This person already has that skill!", ), ] + + @api.constrains("skill_id", "skill_type_id") + def _check_skill_type(self): + for record in self: + if record.skill_id not in record.skill_type_id.skill_ids: + raise ValidationError( + _("The skill %s and skill type %s doesn't match") + % (record.skill_id.name, record.skill_type_id.name) + ) + + @api.constrains("skill_type_id", "skill_level_id") + def _check_skill_level(self): + for record in self: + if record.skill_level_id not in record.skill_type_id.skill_level_ids: + raise ValidationError( + _("The skill level %s is not valid for skill type: %s ") + % (record.skill_level_id.name, record.skill_type_id.name) + ) diff --git a/fieldservice_skill/views/fsm_person.xml b/fieldservice_skill/views/fsm_person.xml index 0cb157a57d..1154cf3dc8 100644 --- a/fieldservice_skill/views/fsm_person.xml +++ b/fieldservice_skill/views/fsm_person.xml @@ -8,12 +8,26 @@ - - - - - - +

+
+ + + + + + + + + +
+
diff --git a/fieldservice_skill/views/fsm_person_skill.xml b/fieldservice_skill/views/fsm_person_skill.xml index 584c68a624..af07cc6131 100644 --- a/fieldservice_skill/views/fsm_person_skill.xml +++ b/fieldservice_skill/views/fsm_person_skill.xml @@ -1,53 +1,33 @@ - - Skills - fsm.person.skill - - - - - - - - fsm.person.skill.form fsm.person.skill -
+ - - - + + + + + + -
- - Worker Skills - fsm.person.skill - - tree,form - -

- Create a worker skill. -

-
-
- fsm.person.skill.graph @@ -56,7 +36,7 @@ - +
@@ -67,7 +47,7 @@ - + From fd662ddfee92802f40c84c3914dc1fb574ab9589 Mon Sep 17 00:00:00 2001 From: brian10048 Date: Mon, 26 Oct 2020 21:23:07 -0400 Subject: [PATCH 32/32] [IMP] fieldservice_skill: Add Test --- fieldservice_skill/tests/__init__.py | 4 + fieldservice_skill/tests/test_fsm_skill.py | 173 +++++++++++++++++++++ 2 files changed, 177 insertions(+) create mode 100644 fieldservice_skill/tests/__init__.py create mode 100644 fieldservice_skill/tests/test_fsm_skill.py diff --git a/fieldservice_skill/tests/__init__.py b/fieldservice_skill/tests/__init__.py new file mode 100644 index 0000000000..b45a5c28be --- /dev/null +++ b/fieldservice_skill/tests/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2020, Brian McMaster +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) + +from . import test_fsm_skill diff --git a/fieldservice_skill/tests/test_fsm_skill.py b/fieldservice_skill/tests/test_fsm_skill.py new file mode 100644 index 0000000000..4c58d8c4e0 --- /dev/null +++ b/fieldservice_skill/tests/test_fsm_skill.py @@ -0,0 +1,173 @@ +# Copyright 2020, Brian McMaster +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) + +from odoo.tests import SavepointCase + + +class TestFSMSkill(SavepointCase): + @classmethod + def setUpClass(cls): + super(TestFSMSkill, cls).setUpClass() + + cls.skill = cls.env["hr.skill"] + cls.skill_level = cls.env["hr.skill.level"] + cls.skill_type = cls.env["hr.skill.type"] + cls.fsm_person = cls.env["fsm.person"] + cls.fsm_person_skill = cls.env["fsm.person.skill"] + cls.fsm_order = cls.env["fsm.order"] + cls.fsm_location = cls.env["fsm.location"] + cls.fsm_template = cls.env["fsm.template"] + cls.fsm_category = cls.env["fsm.category"] + + cls.skill_type_01 = cls.skill_type.create({"name": "Field Service Skills"}) + + # Create some great skills + cls.skill_01 = cls.skill.create( + {"name": "Nunchuck Skills", "skill_type_id": cls.skill_type_01.id} + ) + cls.skill_02 = cls.skill.create( + {"name": "Bow Hunting Skills", "skill_type_id": cls.skill_type_01.id} + ) + cls.skill_03 = cls.skill.create( + {"name": "Computer Hacking Skills", "skill_type_id": cls.skill_type_01.id} + ) + cls.skill_04 = cls.skill.create( + {"name": "Sweet Bike Owning Skills", "skill_type_id": cls.skill_type_01.id} + ) + cls.skill_05 = cls.skill.create( + { + "name": "Hooking Up with Chicks Skills", + "skill_type_id": cls.skill_type_01.id, + } + ) + cls.skill_06 = cls.skill.create( + {"name": "Moustache Growing Skills", "skill_type_id": cls.skill_type_01.id} + ) + + cls.skill_level_100 = cls.skill_level.create( + { + "name": "Great", + "skill_type_id": cls.skill_type_01.id, + "level_progress": 100, + } + ) + + # Create some great workers with their own great skills + # Our first worker, Napoleon, has nunchuck skills and bow hunting + # skills, which he learned while in Alaska hunting wolverines with his + # uncle. + cls.person_01 = cls.fsm_person.create({"name": "Napoleon"}) + cls.person_01_skill_01 = cls.fsm_person_skill.create( + { + "person_id": cls.person_01.id, + "skill_id": cls.skill_01.id, + "skill_level_id": cls.skill_level_100.id, + "skill_type_id": cls.skill_type_01.id, + } + ) + cls.person_01_skill_02 = cls.fsm_person_skill.create( + { + "person_id": cls.person_01.id, + "skill_id": cls.skill_02.id, + "skill_level_id": cls.skill_level_100.id, + "skill_type_id": cls.skill_type_01.id, + } + ) + + # Our second worker, Pedro, has a lot of really good skills which he + # learned from his cousins that have all the sweet hookups + cls.person_02 = cls.fsm_person.create({"name": "Pedro"}) + cls.person_02_skill_04 = cls.fsm_person_skill.create( + { + "person_id": cls.person_02.id, + "skill_id": cls.skill_04.id, + "skill_level_id": cls.skill_level_100.id, + "skill_type_id": cls.skill_type_01.id, + } + ) + cls.person_02_skill_05 = cls.fsm_person_skill.create( + { + "person_id": cls.person_02.id, + "skill_id": cls.skill_05.id, + "skill_level_id": cls.skill_level_100.id, + "skill_type_id": cls.skill_type_01.id, + } + ) + cls.person_02_skill_06 = cls.fsm_person_skill.create( + { + "person_id": cls.person_02.id, + "skill_id": cls.skill_06.id, + "skill_level_id": cls.skill_level_100.id, + "skill_type_id": cls.skill_type_01.id, + } + ) + + # Create a location for an order + cls.location_01 = cls.fsm_location.create( + { + "name": "Summer's House", + "owner_id": cls.env["res.partner"] + .create({"name": "Summer's Parents"}) + .id, + } + ) + + # Create a category that requires great skills + cls.category_01_skills = [cls.skill_04.id, cls.skill_05.id, cls.skill_06.id] + cls.category_01 = cls.fsm_category.create( + {"name": "Sales", "skill_ids": [(6, 0, cls.category_01_skills)]} + ) + + # Create a template that requires great skills + cls.template_01_skills = [cls.skill_01.id, cls.skill_02.id] + cls.template_01 = cls.fsm_template.create( + {"name": "Template Name", "skill_ids": [(6, 0, cls.template_01_skills)]} + ) + + # Create an order that requires no skills + cls.order_no_skills = cls.fsm_order.create({"location_id": cls.location_01.id}) + + # Create an order with a category + cls.order_category_skills = cls.fsm_order.create( + { + "location_id": cls.location_01.id, + "category_ids": [(6, 0, [cls.category_01.id])], + } + ) + + # Create an order with a template + cls.order_template_skills = cls.fsm_order.create( + {"location_id": cls.location_01.id, "template_id": cls.template_01.id} + ) + + def test_fsm_skills(self): + + # Validate the order without skills can be done by all workers + self.assertEqual( + self.order_no_skills.skill_worker_ids.ids, + self.fsm_person.search([]).ids, + "FSM Order without skills should allow all workers", + ) + + # Trigger the category onchange and validate skill_ids get set + self.order_category_skills._onchange_category_ids() + self.assertEqual( + self.order_category_skills.skill_ids.ids, + self.category_01_skills, + "The order should have skills based on the category", + ) + + # Trigger the template onchange and validate skill_ids get set + self.order_template_skills._onchange_template_id() + self.assertEqual( + self.order_template_skills.skill_ids.ids, + self.template_01_skills, + "The order should have skills based on the template", + ) + + # Validate the skilled order can be done by Pedro who has the skills + self.assertEqual( + self.order_category_skills.skill_worker_ids, + self.person_02, + "FSM Order should only allow workers with all skills required", + )