From 0b461f0751adb5cf8d4ccafea73be159a5846006 Mon Sep 17 00:00:00 2001 From: juan Date: Wed, 30 Sep 2026 17:52:15 +0200 Subject: [PATCH 1/2] [ADD]hr_shift_area module --- hr_shift_area/README.rst | 121 +++++ hr_shift_area/__init__.py | 1 + hr_shift_area/__manifest__.py | 23 + hr_shift_area/i18n/es.po | 130 +++++ hr_shift_area/models/__init__.py | 4 + hr_shift_area/models/hr_employee.py | 12 + hr_shift_area/models/shift_area.py | 10 + hr_shift_area/models/shift_planning.py | 25 + hr_shift_area/models/shift_template.py | 13 + hr_shift_area/pyproject.toml | 3 + hr_shift_area/readme/CONFIGURE.md | 16 + hr_shift_area/readme/CONTRIBUTORS.md | 1 + hr_shift_area/readme/CREDITS.md | 1 + hr_shift_area/readme/DESCRIPTION.md | 2 + hr_shift_area/readme/USAGE.md | 6 + hr_shift_area/security/ir.model.access.csv | 3 + hr_shift_area/static/description/icon.png | Bin 0 -> 5002 bytes hr_shift_area/static/description/icon.svg | 104 ++++ hr_shift_area/static/description/index.html | 471 +++++++++++++++++++ hr_shift_area/tests/__init__.py | 1 + hr_shift_area/tests/test_hr_shift_area.py | 67 +++ hr_shift_area/views/hr_employee_views.xml | 30 ++ hr_shift_area/views/shift_area_views.xml | 36 ++ hr_shift_area/views/shift_planning_views.xml | 34 ++ hr_shift_area/views/shift_template_views.xml | 21 + 25 files changed, 1135 insertions(+) create mode 100644 hr_shift_area/README.rst create mode 100644 hr_shift_area/__init__.py create mode 100644 hr_shift_area/__manifest__.py create mode 100644 hr_shift_area/i18n/es.po create mode 100644 hr_shift_area/models/__init__.py create mode 100644 hr_shift_area/models/hr_employee.py create mode 100644 hr_shift_area/models/shift_area.py create mode 100644 hr_shift_area/models/shift_planning.py create mode 100644 hr_shift_area/models/shift_template.py create mode 100644 hr_shift_area/pyproject.toml create mode 100644 hr_shift_area/readme/CONFIGURE.md create mode 100644 hr_shift_area/readme/CONTRIBUTORS.md create mode 100644 hr_shift_area/readme/CREDITS.md create mode 100644 hr_shift_area/readme/DESCRIPTION.md create mode 100644 hr_shift_area/readme/USAGE.md create mode 100644 hr_shift_area/security/ir.model.access.csv create mode 100644 hr_shift_area/static/description/icon.png create mode 100644 hr_shift_area/static/description/icon.svg create mode 100644 hr_shift_area/static/description/index.html create mode 100644 hr_shift_area/tests/__init__.py create mode 100644 hr_shift_area/tests/test_hr_shift_area.py create mode 100644 hr_shift_area/views/hr_employee_views.xml create mode 100644 hr_shift_area/views/shift_area_views.xml create mode 100644 hr_shift_area/views/shift_planning_views.xml create mode 100644 hr_shift_area/views/shift_template_views.xml diff --git a/hr_shift_area/README.rst b/hr_shift_area/README.rst new file mode 100644 index 0000000..04a2395 --- /dev/null +++ b/hr_shift_area/README.rst @@ -0,0 +1,121 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + +============= +HR Shift Area +============= + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:03f941175be758297a8a3db3031797b3715c83786c317cfd63cae66a45d584e5 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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%2Fshift--planning-lightgray.png?logo=github + :target: https://github.com/OCA/shift-planning/tree/16.0/hr_shift_area + :alt: OCA/shift-planning +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/shift-planning-16-0/shift-planning-16-0-hr_shift_area + :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/shift-planning&target_branch=16.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Classifies shift templates and employees into areas, so shift plannings +can target the areas that need shifts generated. + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +In order to configure shift areas you'll need to be in the **Shift +Manager** security group. + +Creating areas +-------------- + +Go to *Shifts > Areas* and create a new one, giving it a descriptive +name. + +Assigning areas to shift templates +---------------------------------- + +Go to *Shifts > Shifts* and set the **Area** field on each template. + +Assigning areas to employees +---------------------------- + +Go to *Employees > Employees* and, in the *Work information* tab, set +the **Areas** field for each employee that should be considered when +generating shifts for those areas. + +Usage +===== + +When creating a shift planning, set the **Areas** field to the areas +this planning is meant to cover. + +Each shift template can be linked to an area (*Shifts > Shifts*, field +**Area**). The area of the template assigned to a shift line is shown +(read-only) on the line's form view, and can be used as a filter in the +*Shifts > Shifts* calendar view. + +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 +------- + +* CreuBlanca + +Contributors +------------ + +- `CreuBlanca `__ + +Other credits +------------- + +`Sun Moon icon `__ by Lucide + +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/shift-planning `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/hr_shift_area/__init__.py b/hr_shift_area/__init__.py new file mode 100644 index 0000000..0650744 --- /dev/null +++ b/hr_shift_area/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/hr_shift_area/__manifest__.py b/hr_shift_area/__manifest__.py new file mode 100644 index 0000000..41965e5 --- /dev/null +++ b/hr_shift_area/__manifest__.py @@ -0,0 +1,23 @@ +# Copyright 2026 Creu Blanca +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +{ + "name": "HR Shift Area", + "summary": "Defines shift areas used to classify shift templates", + "version": "16.0.1.0.0", + "category": "CB", + "website": "https://github.com/OCA/shift-planning", + "author": "CreuBlanca, Odoo Community Association (OCA)", + "license": "AGPL-3", + "installable": True, + "application": False, + "depends": [ + "hr_shift", + ], + "data": [ + "security/ir.model.access.csv", + "views/shift_area_views.xml", + "views/shift_template_views.xml", + "views/shift_planning_views.xml", + "views/hr_employee_views.xml", + ], +} diff --git a/hr_shift_area/i18n/es.po b/hr_shift_area/i18n/es.po new file mode 100644 index 0000000..5e8ab7d --- /dev/null +++ b/hr_shift_area/i18n/es.po @@ -0,0 +1,130 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * hr_shift_area +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2026-09-08 15:34+0000\n" +"PO-Revision-Date: 2026-09-08 15:34+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: hr_shift_area +#: model:ir.model.fields,field_description:hr_shift_area.field_hr_shift_planning_line__template_area_id +#: model:ir.model.fields,field_description:hr_shift_area.field_hr_shift_template__area +#: model_terms:ir.ui.view,arch_db:hr_shift_area.shift_planning_line_calendar +msgid "Area" +msgstr "Área" + +#. module: hr_shift_area +#: model:ir.model.fields,help:hr_shift_area.field_hr_shift_planning_line__template_area_id +#: model:ir.model.fields,help:hr_shift_area.field_hr_shift_template__area +msgid "" +"Area (work center, department and location) this shift template is assigned " +"to." +msgstr "" +"Área (centro de trabajo, departamento y ubicación) a la que está asignada " +"esta plantilla de turno." + +#. module: hr_shift_area +#: model:ir.model.fields,field_description:hr_shift_area.field_hr_employee__area_ids +#: model:ir.model.fields,field_description:hr_shift_area.field_hr_shift_planning__area_ids +#: model:ir.ui.menu,name:hr_shift_area.shift_area_menu +msgid "Areas" +msgstr "Áreas" + +#. module: hr_shift_area +#: model:ir.model.fields,field_description:hr_shift_area.field_hr_shift_area__create_uid +msgid "Created by" +msgstr "Creado por" + +#. module: hr_shift_area +#: model:ir.model.fields,field_description:hr_shift_area.field_hr_shift_area__create_date +msgid "Created on" +msgstr "Creado el" + +#. module: hr_shift_area +#: model:ir.model.fields,field_description:hr_shift_area.field_hr_shift_area__display_name +msgid "Display Name" +msgstr "Nombre mostrado" + +#. module: hr_shift_area +#: model:ir.model,name:hr_shift_area.model_hr_employee +msgid "Employee" +msgstr "Empleado" + +#. module: hr_shift_area +#: model:ir.ui.menu,name:hr_shift_area.hr_employee_shift_planning_menu +msgid "Employees" +msgstr "Empleados" + +#. module: hr_shift_area +#: model:ir.model.fields,field_description:hr_shift_area.field_hr_shift_area__id +msgid "ID" +msgstr "" + +#. module: hr_shift_area +#: model:ir.model.fields,field_description:hr_shift_area.field_hr_shift_area____last_update +msgid "Last Modified on" +msgstr "Última modificación el" + +#. module: hr_shift_area +#: model:ir.model.fields,field_description:hr_shift_area.field_hr_shift_area__write_uid +msgid "Last Updated by" +msgstr "Última actualización por" + +#. module: hr_shift_area +#: model:ir.model.fields,field_description:hr_shift_area.field_hr_shift_area__write_date +msgid "Last Updated on" +msgstr "Última actualización el" + +#. module: hr_shift_area +#: model:ir.model.fields,field_description:hr_shift_area.field_hr_shift_area__name +msgid "Name" +msgstr "Nombre" + +#. module: hr_shift_area +#: model:ir.model,name:hr_shift_area.model_hr_shift_area +msgid "Shift Area" +msgstr "Área de turno" + +#. module: hr_shift_area +#: model:ir.actions.act_window,name:hr_shift_area.shift_area_action +msgid "Shift Areas" +msgstr "Áreas de turno" + +#. module: hr_shift_area +#: model:ir.actions.act_window,name:hr_shift_area.hr_employee_shift_planning_action +msgid "Shift Planning Employees" +msgstr "Empleados de planificación de turnos" + +#. module: hr_shift_area +#: model:ir.model,name:hr_shift_area.model_hr_shift_planning_line +msgid "Shift of the day for the employee" +msgstr "Turno del día para el empleado" + +#. module: hr_shift_area +#: model:ir.model,name:hr_shift_area.model_hr_shift_planning +msgid "Shift plannings" +msgstr "Planificaciones de turnos" + +#. module: hr_shift_area +#: model:ir.model,name:hr_shift_area.model_hr_shift_template +msgid "Shifts" +msgstr "Turnos" + +#. module: hr_shift_area +#: model:ir.model.fields,help:hr_shift_area.field_hr_shift_planning__area_ids +msgid "" +"Shifts will be generated for employees assigned to these areas, using the " +"shift templates that belong to them." +msgstr "" +"Se generarán turnos para los empleados asignados a estas áreas, usando las " +"plantillas de turno que les pertenecen." diff --git a/hr_shift_area/models/__init__.py b/hr_shift_area/models/__init__.py new file mode 100644 index 0000000..00ea695 --- /dev/null +++ b/hr_shift_area/models/__init__.py @@ -0,0 +1,4 @@ +from . import shift_area +from . import shift_template +from . import shift_planning +from . import hr_employee diff --git a/hr_shift_area/models/hr_employee.py b/hr_shift_area/models/hr_employee.py new file mode 100644 index 0000000..e4eb967 --- /dev/null +++ b/hr_shift_area/models/hr_employee.py @@ -0,0 +1,12 @@ +# Copyright 2026 Creu Blanca +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from odoo import fields, models + + +class HrEmployee(models.Model): + _inherit = "hr.employee" + + area_ids = fields.Many2many( + comodel_name="hr.shift.area", + string="Areas", + ) diff --git a/hr_shift_area/models/shift_area.py b/hr_shift_area/models/shift_area.py new file mode 100644 index 0000000..45d4224 --- /dev/null +++ b/hr_shift_area/models/shift_area.py @@ -0,0 +1,10 @@ +# Copyright 2026 Creu Blanca +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from odoo import fields, models + + +class ShiftArea(models.Model): + _name = "hr.shift.area" + _description = "Shift Area" + + name = fields.Char(required=True) diff --git a/hr_shift_area/models/shift_planning.py b/hr_shift_area/models/shift_planning.py new file mode 100644 index 0000000..3fd83df --- /dev/null +++ b/hr_shift_area/models/shift_planning.py @@ -0,0 +1,25 @@ +# Copyright 2026 Creu Blanca +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from odoo import fields, models + + +class ShiftPlanning(models.Model): + _inherit = "hr.shift.planning" + + area_ids = fields.Many2many( + comodel_name="hr.shift.area", + string="Areas", + help="Shifts will be generated for employees assigned to these areas," + " using the shift templates that belong to them.", + ) + + +class ShiftPlanningLine(models.Model): + _inherit = "hr.shift.planning.line" + + template_area_id = fields.Many2one( + comodel_name="hr.shift.area", + related="template_id.area", + string="Area", + store=True, + ) diff --git a/hr_shift_area/models/shift_template.py b/hr_shift_area/models/shift_template.py new file mode 100644 index 0000000..4301111 --- /dev/null +++ b/hr_shift_area/models/shift_template.py @@ -0,0 +1,13 @@ +# Copyright 2026 Creu Blanca +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from odoo import fields, models + + +class ShiftTemplate(models.Model): + _inherit = "hr.shift.template" + + area = fields.Many2one( + comodel_name="hr.shift.area", + help="Area (work center, department and location) this shift " + "template is assigned to.", + ) diff --git a/hr_shift_area/pyproject.toml b/hr_shift_area/pyproject.toml new file mode 100644 index 0000000..4231d0c --- /dev/null +++ b/hr_shift_area/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/hr_shift_area/readme/CONFIGURE.md b/hr_shift_area/readme/CONFIGURE.md new file mode 100644 index 0000000..3056aeb --- /dev/null +++ b/hr_shift_area/readme/CONFIGURE.md @@ -0,0 +1,16 @@ +In order to configure shift areas you'll need to be in the _**Shift Manager**_ security +group. + +## Creating areas + +Go to _Shifts > Areas_ and create a new one, giving it a descriptive name. + +## Assigning areas to shift templates + +Go to _Shifts > Shifts_ and set the _**Area**_ field on each template. + +## Assigning areas to employees + +Go to _Employees > Employees_ and, in the _Work information_ tab, set the _**Areas**_ +field for each employee that should be considered when generating shifts for those +areas. diff --git a/hr_shift_area/readme/CONTRIBUTORS.md b/hr_shift_area/readme/CONTRIBUTORS.md new file mode 100644 index 0000000..b0880dc --- /dev/null +++ b/hr_shift_area/readme/CONTRIBUTORS.md @@ -0,0 +1 @@ +- [CreuBlanca](https://creublanca.es) diff --git a/hr_shift_area/readme/CREDITS.md b/hr_shift_area/readme/CREDITS.md new file mode 100644 index 0000000..62e7118 --- /dev/null +++ b/hr_shift_area/readme/CREDITS.md @@ -0,0 +1 @@ +[Sun Moon icon](https://lucide.dev/icons/sun-moon) by Lucide diff --git a/hr_shift_area/readme/DESCRIPTION.md b/hr_shift_area/readme/DESCRIPTION.md new file mode 100644 index 0000000..e6f747f --- /dev/null +++ b/hr_shift_area/readme/DESCRIPTION.md @@ -0,0 +1,2 @@ +Classifies shift templates and employees into areas, so shift plannings can target the +areas that need shifts generated. diff --git a/hr_shift_area/readme/USAGE.md b/hr_shift_area/readme/USAGE.md new file mode 100644 index 0000000..7447ad5 --- /dev/null +++ b/hr_shift_area/readme/USAGE.md @@ -0,0 +1,6 @@ +When creating a shift planning, set the _**Areas**_ field to the areas this planning is +meant to cover. + +Each shift template can be linked to an area (_Shifts > Shifts_, field _**Area**_). The +area of the template assigned to a shift line is shown (read-only) on the line's form +view, and can be used as a filter in the _Shifts > Shifts_ calendar view. diff --git a/hr_shift_area/security/ir.model.access.csv b/hr_shift_area/security/ir.model.access.csv new file mode 100644 index 0000000..fcbd6db --- /dev/null +++ b/hr_shift_area/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_hr_shift_area_user,hr.shift.area user,model_hr_shift_area,base.group_user,1,0,0,0 +access_hr_shift_area_manager,hr.shift.area manager,model_hr_shift_area,hr_shift.group_shift_manager,1,1,1,1 diff --git a/hr_shift_area/static/description/icon.png b/hr_shift_area/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..168d28641de7b6c52205445ca89970c695de1cdd GIT binary patch literal 5002 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 literal 0 HcmV?d00001 diff --git a/hr_shift_area/static/description/icon.svg b/hr_shift_area/static/description/icon.svg new file mode 100644 index 0000000..9d26f65 --- /dev/null +++ b/hr_shift_area/static/description/icon.svg @@ -0,0 +1,104 @@ + + diff --git a/hr_shift_area/static/description/index.html b/hr_shift_area/static/description/index.html new file mode 100644 index 0000000..42aafb2 --- /dev/null +++ b/hr_shift_area/static/description/index.html @@ -0,0 +1,471 @@ + + + + + +HR Shift Area + + + +
+ + + +Odoo Community Association + +
+

HR Shift Area

+ +

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

+

Classifies shift templates and employees into areas, so shift plannings +can target the areas that need shifts generated.

+

Table of contents

+ +
+

Configuration

+

In order to configure shift areas you’ll need to be in the Shift +Manager security group.

+
+

Creating areas

+

Go to Shifts > Areas and create a new one, giving it a descriptive +name.

+
+
+

Assigning areas to shift templates

+

Go to Shifts > Shifts and set the Area field on each template.

+
+
+

Assigning areas to employees

+

Go to Employees > Employees and, in the Work information tab, set +the Areas field for each employee that should be considered when +generating shifts for those areas.

+
+
+
+

Usage

+

When creating a shift planning, set the Areas field to the areas +this planning is meant to cover.

+

Each shift template can be linked to an area (Shifts > Shifts, field +Area). The area of the template assigned to a shift line is shown +(read-only) on the line’s form view, and can be used as a filter in the +Shifts > Shifts calendar view.

+
+
+

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

+
    +
  • CreuBlanca
  • +
+
+ + +
+

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/shift-planning project on GitHub.

+

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

+
+
+
+
+ + diff --git a/hr_shift_area/tests/__init__.py b/hr_shift_area/tests/__init__.py new file mode 100644 index 0000000..e557751 --- /dev/null +++ b/hr_shift_area/tests/__init__.py @@ -0,0 +1 @@ +from . import test_hr_shift_area diff --git a/hr_shift_area/tests/test_hr_shift_area.py b/hr_shift_area/tests/test_hr_shift_area.py new file mode 100644 index 0000000..e0356fe --- /dev/null +++ b/hr_shift_area/tests/test_hr_shift_area.py @@ -0,0 +1,67 @@ +# Copyright 2026 Creu Blanca +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from odoo.tests.common import TransactionCase + + +class TestHrShiftArea(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + # Creating hr.employee records from scratch requires going through + # this instance's own onboarding flow (mandatory partner_id, + # practitioner requirement, ...), so reuse existing employees + # instead of creating new ones. + cls.employee_a, cls.employee_b = cls.env["hr.employee"].search([], limit=2) + cls.area_a = cls.env["hr.shift.area"].create({"name": "Test Area A"}) + cls.area_b = cls.env["hr.shift.area"].create({"name": "Test Area B"}) + cls.template = cls.env["hr.shift.template"].create( + {"name": "Test Template", "area": cls.area_a.id} + ) + + def test_template_area(self): + self.assertEqual(self.template.area, self.area_a) + + def test_employee_area_ids(self): + self.employee_a.area_ids = [(6, 0, [self.area_a.id, self.area_b.id])] + self.assertEqual(self.employee_a.area_ids, self.area_a + self.area_b) + + def test_planning_area_ids(self): + plan = self.env["hr.shift.planning"].create( + { + "year": 2099, + "week_number": 50, + "area_ids": [(6, 0, [self.area_a.id])], + } + ) + self.assertEqual(plan.area_ids, self.area_a) + + def test_planning_line_template_area_id_mirrors_template(self): + plan = self.env["hr.shift.planning"].create({"year": 2099, "week_number": 51}) + shift = self.env["hr.shift.planning.shift"].create( + {"planning_id": plan.id, "employee_id": self.employee_a.id} + ) + line = self.env["hr.shift.planning.line"].create( + {"shift_id": shift.id, "day_number": "0"} + ) + self.assertFalse(line.template_area_id) + line.template_id = self.template.id + self.assertEqual(line.template_area_id, self.area_a) + + def test_planning_line_template_area_id_updates_when_template_changes(self): + other_template = self.env["hr.shift.template"].create( + {"name": "Other Template", "area": self.area_b.id} + ) + plan = self.env["hr.shift.planning"].create({"year": 2099, "week_number": 52}) + shift = self.env["hr.shift.planning.shift"].create( + {"planning_id": plan.id, "employee_id": self.employee_b.id} + ) + line = self.env["hr.shift.planning.line"].create( + { + "shift_id": shift.id, + "day_number": "0", + "template_id": self.template.id, + } + ) + self.assertEqual(line.template_area_id, self.area_a) + line.template_id = other_template.id + self.assertEqual(line.template_area_id, self.area_b) diff --git a/hr_shift_area/views/hr_employee_views.xml b/hr_shift_area/views/hr_employee_views.xml new file mode 100644 index 0000000..2f79e3c --- /dev/null +++ b/hr_shift_area/views/hr_employee_views.xml @@ -0,0 +1,30 @@ + + + + hr.employee + + + + + + + + + + + + Shift Planning Employees + hr.employee + tree + + [('shift_planning', '=', True)] + + + diff --git a/hr_shift_area/views/shift_area_views.xml b/hr_shift_area/views/shift_area_views.xml new file mode 100644 index 0000000..a152f33 --- /dev/null +++ b/hr_shift_area/views/shift_area_views.xml @@ -0,0 +1,36 @@ + + + + hr.shift.area + +
+ + + + + +
+
+
+ + hr.shift.area + + + + + + + + Shift Areas + hr.shift.area + tree,form + + +
diff --git a/hr_shift_area/views/shift_planning_views.xml b/hr_shift_area/views/shift_planning_views.xml new file mode 100644 index 0000000..9606dfb --- /dev/null +++ b/hr_shift_area/views/shift_planning_views.xml @@ -0,0 +1,34 @@ + + + + hr.shift.planning + + + + + + + + + hr.shift.planning.line + + + + + + + + + hr.shift.planning.line + + + + + + + + diff --git a/hr_shift_area/views/shift_template_views.xml b/hr_shift_area/views/shift_template_views.xml new file mode 100644 index 0000000..730d249 --- /dev/null +++ b/hr_shift_area/views/shift_template_views.xml @@ -0,0 +1,21 @@ + + + + hr.shift.template + + + + + + + + + hr.shift.template + + + + + + + + From d2ca5e4d4be0bf3a2d78ec2fa47a22af0753be47 Mon Sep 17 00:00:00 2001 From: juan Date: Thu, 1 Oct 2026 17:46:03 +0200 Subject: [PATCH 2/2] [16.0][ADD] hr_shift_area: declare hr_shift test dependency hr_shift (OCA/shift-planning#53) is not yet merged into this branch, so it's installed from its own branch just for running tests. --- setup/hr_shift_area/odoo/addons/hr_shift_area | 1 + setup/hr_shift_area/setup.py | 6 ++++++ test-requirements.txt | 1 + 3 files changed, 8 insertions(+) create mode 120000 setup/hr_shift_area/odoo/addons/hr_shift_area create mode 100644 setup/hr_shift_area/setup.py create mode 100644 test-requirements.txt diff --git a/setup/hr_shift_area/odoo/addons/hr_shift_area b/setup/hr_shift_area/odoo/addons/hr_shift_area new file mode 120000 index 0000000..8dd91de --- /dev/null +++ b/setup/hr_shift_area/odoo/addons/hr_shift_area @@ -0,0 +1 @@ +../../../../hr_shift_area \ No newline at end of file diff --git a/setup/hr_shift_area/setup.py b/setup/hr_shift_area/setup.py new file mode 100644 index 0000000..28c57bb --- /dev/null +++ b/setup/hr_shift_area/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) diff --git a/test-requirements.txt b/test-requirements.txt new file mode 100644 index 0000000..fe7f1fd --- /dev/null +++ b/test-requirements.txt @@ -0,0 +1 @@ +odoo-addon-hr_shift @ git+https://github.com/tegin/shift-planning.git@16.0-mig-hr_shift#subdirectory=hr_shift