diff --git a/README.md b/README.md index bbc7b1ff..7e6c03c2 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,8 @@ addon | version | maintainers | summary --- | --- | --- | --- [hr_holidays_leave_auto_approve](hr_holidays_leave_auto_approve/) | 16.0.1.0.0 | | Leave type for auto-validation of Leaves [hr_holidays_natural_period](hr_holidays_natural_period/) | 16.0.1.0.1 | [![victoralmau](https://github.com/victoralmau.png?size=30px)](https://github.com/victoralmau) | Apply natural days in holidays -[hr_holidays_public](hr_holidays_public/) | 16.0.2.0.2 | | Manage Public Holidays -[hr_holidays_public_city](hr_holidays_public_city/) | 16.0.2.0.1 | [![victoralmau](https://github.com/victoralmau.png?size=30px)](https://github.com/victoralmau) | HR Holidays Public City +[hr_holidays_public](hr_holidays_public/) | 16.0.2.0.1 | | Manage Public Holidays +[hr_holidays_public_city](hr_holidays_public_city/) | 16.0.2.0.0 | [![victoralmau](https://github.com/victoralmau.png?size=30px)](https://github.com/victoralmau) | HR Holidays Public City [hr_leave_type_code](hr_leave_type_code/) | 16.0.1.0.0 | | Add a code field to HR Leaves [//]: # (end addons) diff --git a/hr_holidays_public/README.rst b/hr_holidays_public/README.rst index e642cb38..f30b40bb 100644 --- a/hr_holidays_public/README.rst +++ b/hr_holidays_public/README.rst @@ -7,7 +7,7 @@ HR Holidays Public !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:894f5c31a60d73d1c1c32f6ad3145570130ae938fb26150cadb170ef995ab8af + !! source digest: sha256:97a5473be95076d9cf3ac9f5ad936323cbd236f42e5a7ba2854bd41aeff163b8 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png diff --git a/hr_holidays_public/__manifest__.py b/hr_holidays_public/__manifest__.py index e79aebcf..82f2fa83 100644 --- a/hr_holidays_public/__manifest__.py +++ b/hr_holidays_public/__manifest__.py @@ -4,7 +4,7 @@ { "name": "HR Holidays Public", - "version": "16.0.2.0.2", + "version": "16.0.2.0.1", "license": "AGPL-3", "category": "Human Resources", "author": "Michael Telahun Makonnen, " diff --git a/hr_holidays_public/models/hr_leave.py b/hr_holidays_public/models/hr_leave.py index 24d7934f..5b4ba8e7 100644 --- a/hr_holidays_public/models/hr_leave.py +++ b/hr_holidays_public/models/hr_leave.py @@ -55,13 +55,6 @@ def _compute_number_of_hours_display(self): def _get_domain_from_get_unusual_days(self, date_from, date_to=None): domain = [("date", ">=", date_from)] - # Use the employee of the user or the one who has the context - employee_id = self.env.context.get("employee_id", False) - employee = ( - self.env["hr.employee"].browse(employee_id) - if employee_id - else self.env.user.employee_id - ) if date_to: domain.append( ( @@ -70,7 +63,7 @@ def _get_domain_from_get_unusual_days(self, date_from, date_to=None): date_to, ) ) - country_id = employee.address_id.country_id.id + country_id = self.env.user.employee_id.address_id.country_id.id if not country_id: country_id = self.env.company.country_id.id or False if country_id: @@ -81,7 +74,7 @@ def _get_domain_from_get_unusual_days(self, date_from, date_to=None): ("year_id.country_id", "=", country_id), ] ) - state_id = employee.address_id.state_id.id + state_id = self.env.user.employee_id.address_id.state_id.id if not state_id: state_id = self.env.company.state_id.id or False if state_id: diff --git a/hr_holidays_public/static/description/index.html b/hr_holidays_public/static/description/index.html index 274bfc55..c6deb965 100644 --- a/hr_holidays_public/static/description/index.html +++ b/hr_holidays_public/static/description/index.html @@ -8,11 +8,10 @@ /* :Author: David Goodger (goodger@python.org) -:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $ +:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $ :Copyright: This stylesheet has been placed in the public domain. Default cascading style sheet for the HTML output of Docutils. -Despite the name, some widely supported CSS2 features are used. See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to customize this style sheet. @@ -275,7 +274,7 @@ margin-left: 2em ; margin-right: 2em } -pre.code .ln { color: gray; } /* line numbers */ +pre.code .ln { color: grey; } /* line numbers */ pre.code, code { background-color: #eeeeee } pre.code .comment, code .comment { color: #5C6576 } pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold } @@ -301,7 +300,7 @@ span.pre { white-space: pre } -span.problematic, pre.problematic { +span.problematic { color: red } span.section-subtitle { @@ -367,7 +366,7 @@

HR Holidays Public

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:894f5c31a60d73d1c1c32f6ad3145570130ae938fb26150cadb170ef995ab8af +!! source digest: sha256:97a5473be95076d9cf3ac9f5ad936323cbd236f42e5a7ba2854bd41aeff163b8 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

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

This module handles public holidays.

@@ -493,9 +492,7 @@

Contributors

Maintainers

This module is maintained by the OCA.

- -Odoo Community Association - +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.

diff --git a/hr_holidays_public/tests/test_holidays_public.py b/hr_holidays_public/tests/test_holidays_public.py index e985b103..0bbea38a 100644 --- a/hr_holidays_public/tests/test_holidays_public.py +++ b/hr_holidays_public/tests/test_holidays_public.py @@ -19,7 +19,6 @@ def setUpClass(cls): cls.holiday_model_line = cls.env["hr.holidays.public.line"] cls.employee_model = cls.env["hr.employee"] cls.wizard_next_year = cls.env["public.holidays.next.year.wizard"] - cls.leave_model = cls.env["hr.leave"] # Remove possibly existing public holidays that would interfer. cls.holiday_model_line.search([]).unlink() @@ -209,7 +208,8 @@ def assertPublicHolidayIsUnusualDay( self, expected, country_id=None, state_ids=False ): self.assertFalse( - self.leave_model.with_user(self.env.ref("base.user_demo").id) + self.env["hr.leave"] + .with_user(self.env.ref("base.user_demo").id) .get_unusual_days("2019-07-01", date_to="2019-07-31") .get("2019-07-30", False) ) @@ -223,22 +223,12 @@ def assertPublicHolidayIsUnusualDay( } ) self.assertEqual( - self.leave_model.with_user( - self.env.ref("base.user_demo").id - ).get_unusual_days("2019-07-01", date_to="2019-07-31")["2019-07-30"], + self.env["hr.leave"] + .with_user(self.env.ref("base.user_demo").id) + .get_unusual_days("2019-07-01", date_to="2019-07-31")["2019-07-30"], expected, ) - def test_public_holidays_context(self): - self.env.ref("base.user_demo").employee_id.address_id.country_id = False - self.leave_model = self.leave_model.with_context(employee_id=self.employee.id) - self.assertPublicHolidayIsUnusualDay( - True, - country_id=self.env.ref( - "base.user_demo" - ).employee_id.address_id.country_id.id, - ) - def test_get_unusual_days_return_public_holidays_same_country(self): self.env.ref("base.user_demo").employee_id.address_id.state_id = False self.env.company.state_id = False diff --git a/hr_holidays_public_city/README.rst b/hr_holidays_public_city/README.rst index c9e6a65b..67bc6cc7 100644 --- a/hr_holidays_public_city/README.rst +++ b/hr_holidays_public_city/README.rst @@ -7,7 +7,7 @@ HR Holidays Public City !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:f51266f14717ae02cc251ea6be1b8d5d865f7c811e295bf62cefbaa8072a6a81 + !! source digest: sha256:556afea47f505328aa6542aac639bfaffe7cdafcc6c579d7397b34f63b26a0c4 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png diff --git a/hr_holidays_public_city/__manifest__.py b/hr_holidays_public_city/__manifest__.py index 3d205e35..c97de6d2 100644 --- a/hr_holidays_public_city/__manifest__.py +++ b/hr_holidays_public_city/__manifest__.py @@ -3,7 +3,7 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). { "name": "HR Holidays Public City", - "version": "16.0.2.0.1", + "version": "16.0.2.0.0", "category": "Tools", "website": "https://github.com/OCA/hr-holidays", "author": "Tecnativa, Odoo Community Association (OCA)", diff --git a/hr_holidays_public_city/models/hr_leave.py b/hr_holidays_public_city/models/hr_leave.py index a5996ae4..361470ad 100644 --- a/hr_holidays_public_city/models/hr_leave.py +++ b/hr_holidays_public_city/models/hr_leave.py @@ -10,15 +10,8 @@ def _get_domain_from_get_unusual_days(self, date_from, date_to=None): domain = super()._get_domain_from_get_unusual_days( date_from=date_from, date_to=date_to ) - # Use the employee of the user or the one who has the context - employee_id = self.env.context.get("employee_id", False) - employee = ( - self.env["hr.employee"].browse(employee_id) - if employee_id - else self.env.user.employee_id - ) # Add city domain - city_id = employee.address_id.city_id.id + city_id = self.env.user.employee_id.address_id.city_id.id if not city_id: city_id = self.env.company.partner_id.city_id.id or False if city_id: diff --git a/hr_holidays_public_city/static/description/index.html b/hr_holidays_public_city/static/description/index.html index 80d24ee2..76ea0dcc 100644 --- a/hr_holidays_public_city/static/description/index.html +++ b/hr_holidays_public_city/static/description/index.html @@ -8,11 +8,10 @@ /* :Author: David Goodger (goodger@python.org) -:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $ +:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $ :Copyright: This stylesheet has been placed in the public domain. Default cascading style sheet for the HTML output of Docutils. -Despite the name, some widely supported CSS2 features are used. See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to customize this style sheet. @@ -275,7 +274,7 @@ margin-left: 2em ; margin-right: 2em } -pre.code .ln { color: gray; } /* line numbers */ +pre.code .ln { color: grey; } /* line numbers */ pre.code, code { background-color: #eeeeee } pre.code .comment, code .comment { color: #5C6576 } pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold } @@ -301,7 +300,7 @@ span.pre { white-space: pre } -span.problematic, pre.problematic { +span.problematic { color: red } span.section-subtitle { @@ -367,7 +366,7 @@

HR Holidays Public City

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:f51266f14717ae02cc251ea6be1b8d5d865f7c811e295bf62cefbaa8072a6a81 +!! source digest: sha256:556afea47f505328aa6542aac639bfaffe7cdafcc6c579d7397b34f63b26a0c4 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

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

This module adds the cities at the public vacation line level as an extra discriminant.

@@ -412,9 +411,7 @@

Contributors

Maintainers

This module is maintained by the OCA.

- -Odoo Community Association - +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.

diff --git a/hr_holidays_public_city/tests/test_holidays_public.py b/hr_holidays_public_city/tests/test_holidays_public.py index 34b24678..0aa8bcfb 100644 --- a/hr_holidays_public_city/tests/test_holidays_public.py +++ b/hr_holidays_public_city/tests/test_holidays_public.py @@ -29,7 +29,8 @@ def assertPublicHolidayIsUnusualDay( self, expected, country_id=None, state_ids=False, city_ids=False ): self.assertFalse( - self.leave_model.with_user(self.env.ref("base.user_demo").id) + self.env["hr.leave"] + .with_user(self.env.ref("base.user_demo").id) .get_unusual_days("2019-07-01", date_to="2019-07-31") .get("2019-07-30", False) ) @@ -44,29 +45,12 @@ def assertPublicHolidayIsUnusualDay( } ) self.assertEqual( - self.leave_model.with_user( - self.env.ref("base.user_demo").id - ).get_unusual_days("2019-07-01", date_to="2019-07-31")["2019-07-30"], + self.env["hr.leave"] + .with_user(self.env.ref("base.user_demo").id) + .get_unusual_days("2019-07-01", date_to="2019-07-31")["2019-07-30"], expected, ) - def test_public_holidays_context(self): - self.env.ref("base.user_demo").employee_id.address_id.country_id = False - self.env.ref("base.user_demo").employee_id.address_id.state_id = False - self.env.ref("base.user_demo").employee_id.address_id.city_id = False - self.employee.address_id.country_id = self.env.ref("base.us") - self.employee.address_id.state_id = self.env.ref("base.state_us_4") - self.employee.address_id.city_id = self.us_city_a - self.leave_model = self.leave_model.with_context(employee_id=self.employee.id) - self.assertPublicHolidayIsUnusualDay( - True, - country_id=self.env.ref( - "base.user_demo" - ).employee_id.address_id.country_id.id, - state_ids=[(6, 0, [self.employee.address_id.state_id.id])], - city_ids=[(6, 0, [self.employee.address_id.city_id.id])], - ) - def test_get_unusual_days_return_public_holidays_same_state_same_city(self): demo_user_empl_addr = self.env.ref("base.user_demo").employee_id.address_id demo_user_empl_addr.country_id = self.env.ref("base.us") diff --git a/resource_leaves_geographic/README.rst b/resource_leaves_geographic/README.rst new file mode 100644 index 00000000..3d500ce3 --- /dev/null +++ b/resource_leaves_geographic/README.rst @@ -0,0 +1,139 @@ +========================== +Resource Leaves Geographic +========================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:e5409e484959f22489b0c0976ce8231c697b28572e9d29285501c0e20bc49179 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png + :target: https://odoo-community.org/page/development-status + :alt: Alpha +.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png + :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html + :alt: License: LGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fhr--holidays-lightgray.png?logo=github + :target: https://github.com/OCA/hr-holidays/tree/16.0/resource_leaves_geographic + :alt: OCA/hr-holidays +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/hr-holidays-16-0/hr-holidays-16-0-resource_leaves_geographic + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/hr-holidays&target_branch=16.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module extends the functionality of Public Holidays to support +States and allow you to define Local Holidays more easily in the Company +Calendar. + +Shows on Time Off all the holidays (with/without State) in the Public +Holidays section. Public Holidays (without State) always will have grey +background. Local holidays displayed with a grey background in the +calendar view belong to the Employee currently viewing the calendar or +to the single Employee selected from the Employee Form view. + +This module is compatible with Attendances and Contracts (but those +modules are not required). + +.. IMPORTANT:: + This is an alpha version, the data model and design can change at any time without warning. + Only for development or testing purpose, do not use in production. + `More details on development status `_ + +**Table of contents** + +.. contents:: + :local: + +Use Cases / Context +=================== + +This module was developed because in order to differentiate local +Employee holidays, they must be added to their calendars instead of +being able to mark them on the general company calendar. + +This will be useful for you if you want to be able to create holidays by +State in the company calendar and have them automatically applied to all +employees based on their workplace. + +Usage +===== + +To use this module, you need to: + +1. Go to Time Off app > Configuration > Public Holidays +2. Create a Public Holiday without State with name *Local Holiday* +3. Create an *Employee 1* and set his Work Address in the same State + than your *Local Holiday* +4. Create an *Employee 2* and set his Work Address in other State than + your *Local Holiday* +5. Go to Time Off > Overview and check the grey background is only on + *Employee 1* on the days used in *Local Holiday* +6. Create a Time Off for *Employee 1* that involves *Local Holiday* and + check the days used are computed correctly +7. Create a Time Off for *Employee 2* that involves *Local Holiday* and + check the days used are computed correctly (more days than the Time + Off of *Employee 1*) +8. Check both Employee Calendar views from the Employee form to view the + grey background on Local and Public Holidays. + +If you have installed Attendances and Contracts apps, and create +attenances for both employees on the *Local Holiday* you can also check +Extra Hours are computed correctly in both employees. + +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 +------- + +* Moduon + +Contributors +------------ + +- Eduardo de Miguel (`Moduon `__) + +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-Shide| image:: https://github.com/Shide.png?size=40px + :target: https://github.com/Shide + :alt: Shide +.. |maintainer-rafaelbn| image:: https://github.com/rafaelbn.png?size=40px + :target: https://github.com/rafaelbn + :alt: rafaelbn + +Current `maintainers `__: + +|maintainer-Shide| |maintainer-rafaelbn| + +This module is part of the `OCA/hr-holidays `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/resource_leaves_geographic/__init__.py b/resource_leaves_geographic/__init__.py new file mode 100644 index 00000000..0650744f --- /dev/null +++ b/resource_leaves_geographic/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/resource_leaves_geographic/__manifest__.py b/resource_leaves_geographic/__manifest__.py new file mode 100644 index 00000000..8e88da1b --- /dev/null +++ b/resource_leaves_geographic/__manifest__.py @@ -0,0 +1,23 @@ +# Copyright 2024 Moduon Team S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0) + +{ + "name": "Resource Leaves Geographic", + "summary": "Add geographic State to Resource Calendar Leaves", + "version": "16.0.1.0.0", + "development_status": "Alpha", + "category": "Human Resources/Time Off", + "website": "https://github.com/OCA/hr-holidays", + "author": "Moduon, Odoo Community Association (OCA)", + "maintainers": ["Shide", "rafaelbn"], + "license": "LGPL-3", + "application": False, + "installable": True, + "depends": [ + "resource", + "hr_holidays", + ], + "data": [ + "views/resource_calendar_leaves_views.xml", + ], +} diff --git a/resource_leaves_geographic/i18n/es.po b/resource_leaves_geographic/i18n/es.po new file mode 100644 index 00000000..c1b0a707 --- /dev/null +++ b/resource_leaves_geographic/i18n/es.po @@ -0,0 +1,38 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * resource_leaves_geographic +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-31 07:50+0000\n" +"PO-Revision-Date: 2024-07-31 09:52+0200\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: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 3.4.4\n" + +#. module: resource_leaves_geographic +#: model:ir.model,name:resource_leaves_geographic.model_resource_calendar_leaves +msgid "Resource Time Off Detail" +msgstr "Detalle de las ausencias del recurso" + +#. module: resource_leaves_geographic +#: model:ir.model,name:resource_leaves_geographic.model_resource_calendar +msgid "Resource Working Time" +msgstr "Tiempo de Trabajo de Recursos" + +#. module: resource_leaves_geographic +#: model:ir.model.fields,field_description:resource_leaves_geographic.field_resource_calendar_leaves__state_ids +msgid "States" +msgstr "Estados" + +#. module: resource_leaves_geographic +#: model:ir.model.fields,help:resource_leaves_geographic.field_resource_calendar_leaves__state_ids +msgid "States for which this leave is applicable" +msgstr "Estados para los que se aplica esta ausencia" diff --git a/resource_leaves_geographic/i18n/resource_leaves_geographic.pot b/resource_leaves_geographic/i18n/resource_leaves_geographic.pot new file mode 100644 index 00000000..84b74a77 --- /dev/null +++ b/resource_leaves_geographic/i18n/resource_leaves_geographic.pot @@ -0,0 +1,36 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * resource_leaves_geographic +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-31 07:50+0000\n" +"PO-Revision-Date: 2024-07-31 07:50+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: resource_leaves_geographic +#: model:ir.model,name:resource_leaves_geographic.model_resource_calendar_leaves +msgid "Resource Time Off Detail" +msgstr "" + +#. module: resource_leaves_geographic +#: model:ir.model,name:resource_leaves_geographic.model_resource_calendar +msgid "Resource Working Time" +msgstr "" + +#. module: resource_leaves_geographic +#: model:ir.model.fields,field_description:resource_leaves_geographic.field_resource_calendar_leaves__state_ids +msgid "States" +msgstr "" + +#. module: resource_leaves_geographic +#: model:ir.model.fields,help:resource_leaves_geographic.field_resource_calendar_leaves__state_ids +msgid "States for which this leave is applicable" +msgstr "" diff --git a/resource_leaves_geographic/models/__init__.py b/resource_leaves_geographic/models/__init__.py new file mode 100644 index 00000000..0e5f0e25 --- /dev/null +++ b/resource_leaves_geographic/models/__init__.py @@ -0,0 +1,3 @@ +from . import resource_calendar_leaves +from . import resource_calendar +from . import hr_employee diff --git a/resource_leaves_geographic/models/hr_employee.py b/resource_leaves_geographic/models/hr_employee.py new file mode 100644 index 00000000..242e68a6 --- /dev/null +++ b/resource_leaves_geographic/models/hr_employee.py @@ -0,0 +1,51 @@ +# Copyright 2024 Moduon Team S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0) + +from datetime import datetime, time + +from dateutil.rrule import DAILY, rrule +from pytz import UTC + +from odoo import fields, models + + +class HrEmployeePrivate(models.Model): + _inherit = "hr.employee" + + def _get_unusual_days(self, date_from, date_to=None): + """Get the geographical unusual days belongs to employees""" + res = super()._get_unusual_days(date_from, date_to=date_to) + + def dt_combiner(dt, tx): + """Return a datetime object with the date converted to datetime + + :param dt: date string + :param tx: time.min or time.max + """ + return datetime.combine(fields.Date.from_string(dt), tx).replace(tzinfo=UTC) + + calendars = ( + self.mapped("resource_calendar_id") or self.env.company.resource_calendar_id + ) + state_interval_map = calendars._get_general_time_off_intervals_by_state( + domain=[ + ("state_ids", "in", self.mapped("address_id.state_id").ids), + ("date_from", "<=", dt_combiner(date_to, time.max)), + ("date_to", ">=", dt_combiner(date_from, time.min)), + ], + any_calendar=False, + ) + local_leave_days = set() + for state_interval_map in state_interval_map.values(): + for start, end, _rcl in state_interval_map: + local_leave_days.update( + { + fields.Date.to_string(day.date()) + for day in rrule(DAILY, start.date(), until=end.date()) + } + ) + + for day in res.keys(): + if day in local_leave_days: + res[day] = True + return res diff --git a/resource_leaves_geographic/models/resource_calendar.py b/resource_leaves_geographic/models/resource_calendar.py new file mode 100644 index 00000000..d3b19c21 --- /dev/null +++ b/resource_leaves_geographic/models/resource_calendar.py @@ -0,0 +1,84 @@ +# Copyright 2024 Moduon Team S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0) + +from collections import defaultdict + +from odoo import models + +from odoo.addons.resource.models.resource import Intervals, make_aware + + +class ResourceCalendar(models.Model): + _inherit = "resource.calendar" + + def _get_general_time_off_intervals_by_state(self, domain=None, any_calendar=False): + """Get a map of State to Intervals of leaves for the given domain.""" + domain = domain or [] + # Respect the any_calendar option + if not any_calendar: + domain += [("calendar_id", "in", self.ids + [False])] + # Ensure that the leaves are not related to a specific resource + domain += [ + ("resource_id", "=", False), + ] + # Iterate all matching leaves + state_interval_map = defaultdict(Intervals) + for res_cal_leave in self.env["resource.calendar.leaves"].search(domain): + dttf, _f = make_aware(res_cal_leave.date_from) + dttt, _f = make_aware(res_cal_leave.date_to) + # Add the interval to the corresponding State or False if no state + if res_cal_leave.state_ids: + for state in res_cal_leave.state_ids: + state_interval_map[state.id] |= Intervals( + [(dttf, dttt, res_cal_leave)] + ) + else: + state_interval_map[False] |= Intervals([(dttf, dttt, res_cal_leave)]) + return state_interval_map + + def _leave_intervals_batch( + self, start_dt, end_dt, resources=None, domain=None, tz=None, any_calendar=False + ): + # All interval batches (with/out State) + res = super()._leave_intervals_batch( + start_dt, + end_dt, + resources=resources, + domain=domain, + tz=tz, + any_calendar=any_calendar, + ) + # Overwrite the result if resources are specified, but only with + # the global leaves (skipping the local leaves) using the domain + for resource in resources or []: + res.update( + super()._leave_intervals_batch( + start_dt, + end_dt, + resources=resource, + domain=[("state_ids", "=", False)], # Force global leaves + tz=tz, + any_calendar=any_calendar, + ) + ) + # Get Local interval batches by State + state_interval_map = self._get_general_time_off_intervals_by_state( + domain=domain, any_calendar=any_calendar + ) + # Post-process generated intervals + for resource_id in res.keys(): + if not resource_id: + # If no resource is specified, only consider Global leaves + res[resource_id] = state_interval_map[False] + else: + # If resource is specified, add Local Leaves to the result if + # the State of its Work Address has Local leaves + resource_state_id = ( + self.env["hr.employee"] + .sudo() + .search([("resource_id", "=", resource_id)], limit=1) + .address_id.state_id.id + ) + if resource_state_id in state_interval_map: + res[resource_id] |= state_interval_map[resource_state_id] + return res diff --git a/resource_leaves_geographic/models/resource_calendar_leaves.py b/resource_leaves_geographic/models/resource_calendar_leaves.py new file mode 100644 index 00000000..2844d2cc --- /dev/null +++ b/resource_leaves_geographic/models/resource_calendar_leaves.py @@ -0,0 +1,14 @@ +# Copyright 2024 Moduon Team S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0) + +from odoo import fields, models + + +class ResourceCalendarLeaves(models.Model): + _inherit = "resource.calendar.leaves" + + state_ids = fields.Many2many( + comodel_name="res.country.state", + string="States", + help="States for which this leave is applicable", + ) diff --git a/resource_leaves_geographic/readme/CONTEXT.md b/resource_leaves_geographic/readme/CONTEXT.md new file mode 100644 index 00000000..6f20b910 --- /dev/null +++ b/resource_leaves_geographic/readme/CONTEXT.md @@ -0,0 +1,3 @@ +This module was developed because in order to differentiate local Employee holidays, they must be added to their calendars instead of being able to mark them on the general company calendar. + +This will be useful for you if you want to be able to create holidays by State in the company calendar and have them automatically applied to all employees based on their workplace. diff --git a/resource_leaves_geographic/readme/CONTRIBUTORS.md b/resource_leaves_geographic/readme/CONTRIBUTORS.md new file mode 100644 index 00000000..290347f4 --- /dev/null +++ b/resource_leaves_geographic/readme/CONTRIBUTORS.md @@ -0,0 +1 @@ +- Eduardo de Miguel ([Moduon](https://www.moduon.team/)) diff --git a/resource_leaves_geographic/readme/DESCRIPTION.md b/resource_leaves_geographic/readme/DESCRIPTION.md new file mode 100644 index 00000000..e28a2185 --- /dev/null +++ b/resource_leaves_geographic/readme/DESCRIPTION.md @@ -0,0 +1,7 @@ +This module extends the functionality of Public Holidays to support States and allow you to define Local Holidays more easily in the Company Calendar. + +Shows on Time Off all the holidays (with/without State) in the Public Holidays section. +Public Holidays (without State) always will have grey background. +Local holidays displayed with a grey background in the calendar view belong to the Employee currently viewing the calendar or to the single Employee selected from the Employee Form view. + +This module is compatible with Attendances and Contracts (but those modules are not required). diff --git a/resource_leaves_geographic/readme/USAGE.md b/resource_leaves_geographic/readme/USAGE.md new file mode 100644 index 00000000..bc9b6bec --- /dev/null +++ b/resource_leaves_geographic/readme/USAGE.md @@ -0,0 +1,12 @@ +To use this module, you need to: + +1. Go to Time Off app > Configuration > Public Holidays +2. Create a Public Holiday without State with name *Local Holiday* +3. Create an *Employee 1* and set his Work Address in the same State than your *Local Holiday* +4. Create an *Employee 2* and set his Work Address in other State than your *Local Holiday* +5. Go to Time Off > Overview and check the grey background is only on *Employee 1* on the days used in *Local Holiday* +6. Create a Time Off for *Employee 1* that involves *Local Holiday* and check the days used are computed correctly +7. Create a Time Off for *Employee 2* that involves *Local Holiday* and check the days used are computed correctly (more days than the Time Off of *Employee 1*) +8. Check both Employee Calendar views from the Employee form to view the grey background on Local and Public Holidays. + +If you have installed Attendances and Contracts apps, and create attenances for both employees on the *Local Holiday* you can also check Extra Hours are computed correctly in both employees. diff --git a/resource_leaves_geographic/static/description/icon.png b/resource_leaves_geographic/static/description/icon.png new file mode 100644 index 00000000..3a0328b5 Binary files /dev/null and b/resource_leaves_geographic/static/description/icon.png differ diff --git a/resource_leaves_geographic/static/description/index.html b/resource_leaves_geographic/static/description/index.html new file mode 100644 index 00000000..59a75c91 --- /dev/null +++ b/resource_leaves_geographic/static/description/index.html @@ -0,0 +1,475 @@ + + + + + +Resource Leaves Geographic + + + +
+

Resource Leaves Geographic

+ + +

Alpha License: LGPL-3 OCA/hr-holidays Translate me on Weblate Try me on Runboat

+

This module extends the functionality of Public Holidays to support +States and allow you to define Local Holidays more easily in the Company +Calendar.

+

Shows on Time Off all the holidays (with/without State) in the Public +Holidays section. Public Holidays (without State) always will have grey +background. Local holidays displayed with a grey background in the +calendar view belong to the Employee currently viewing the calendar or +to the single Employee selected from the Employee Form view.

+

This module is compatible with Attendances and Contracts (but those +modules are not required).

+
+

Important

+

This is an alpha version, the data model and design can change at any time without warning. +Only for development or testing purpose, do not use in production. +More details on development status

+
+

Table of contents

+ +
+

Use Cases / Context

+

This module was developed because in order to differentiate local +Employee holidays, they must be added to their calendars instead of +being able to mark them on the general company calendar.

+

This will be useful for you if you want to be able to create holidays by +State in the company calendar and have them automatically applied to all +employees based on their workplace.

+
+
+

Usage

+

To use this module, you need to:

+
    +
  1. Go to Time Off app > Configuration > Public Holidays
  2. +
  3. Create a Public Holiday without State with name Local Holiday
  4. +
  5. Create an Employee 1 and set his Work Address in the same State +than your Local Holiday
  6. +
  7. Create an Employee 2 and set his Work Address in other State than +your Local Holiday
  8. +
  9. Go to Time Off > Overview and check the grey background is only on +Employee 1 on the days used in Local Holiday
  10. +
  11. Create a Time Off for Employee 1 that involves Local Holiday and +check the days used are computed correctly
  12. +
  13. Create a Time Off for Employee 2 that involves Local Holiday and +check the days used are computed correctly (more days than the Time +Off of Employee 1)
  14. +
  15. Check both Employee Calendar views from the Employee form to view the +grey background on Local and Public Holidays.
  16. +
+

If you have installed Attendances and Contracts apps, and create +attenances for both employees on the Local Holiday you can also check +Extra Hours are computed correctly in both employees.

+
+
+

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

+
    +
  • Moduon
  • +
+
+
+

Contributors

+
    +
  • Eduardo de Miguel (Moduon)
  • +
+
+
+

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:

+

Shide rafaelbn

+

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

+

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

+
+
+
+ + diff --git a/resource_leaves_geographic/tests/__init__.py b/resource_leaves_geographic/tests/__init__.py new file mode 100644 index 00000000..314fcd3e --- /dev/null +++ b/resource_leaves_geographic/tests/__init__.py @@ -0,0 +1 @@ +from . import test_resource_calendar_leaves diff --git a/resource_leaves_geographic/tests/test_resource_calendar_leaves.py b/resource_leaves_geographic/tests/test_resource_calendar_leaves.py new file mode 100644 index 00000000..7caba496 --- /dev/null +++ b/resource_leaves_geographic/tests/test_resource_calendar_leaves.py @@ -0,0 +1,88 @@ +# Copyright 2024 Moduon Team S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0) + +from odoo.tests.common import TransactionCase + +from odoo.addons.base.tests.common import DISABLED_MAIL_CONTEXT + + +class TestResourceCalendarLeaves(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.env = cls.env(context=dict(cls.env.context, **DISABLED_MAIL_CONTEXT)) + cls.trcl_State = cls.env["res.country.state"].create( + { + "name": "TRCL State", + "code": "TRCL", + "country_id": cls.env.user.company_id.country_id.id, + } + ) + cls.partner = cls.env["res.partner"].create({"name": "TRCL Partner"}) + cls.employee = cls.env["hr.employee"].create( + {"name": "TRCL Employee 1", "address_id": cls.partner.id} + ) + cls.global_leave = cls.env["resource.calendar.leaves"].create( + { + "name": "Global Leave", + "date_from": "2024-07-01 00:00:00", + "date_to": "2024-07-01 23:59:59", + "state_ids": None, + } + ) + cls.local_leave = cls.env["resource.calendar.leaves"].create( + { + "name": "Local Leave", + "date_from": "2024-07-02 00:00:00", + "date_to": "2024-07-02 23:59:59", + "state_ids": [(6, 0, cls.trcl_State.ids)], + } + ) + cls.timeoff_type = cls.env["hr.leave.type"].create( + { + "name": "TRCL Time Off", + "leave_validation_type": "no_validation", + "requires_allocation": "no", + } + ) + + def _create_leave(self): + leave = self.env["hr.leave"].create( + { + "name": "TRCL Leave", + "date_from": "2024-06-28 00:00:00", + "date_to": "2024-07-02 23:59:59", + "employee_id": self.employee.id, + "holiday_status_id": self.timeoff_type.id, + } + ) + if leave.state != "validate": + leave.action_confirm() + self.assertEqual(leave.state, "validate") + return leave + + def test_leave_partner_without_state(self): + leave = self._create_leave() + # Leave does not take in consideration State + self.assertEqual(leave.number_of_days_display, 2.0) + + def test_leave_partner_with_state(self): + self.partner.state_id = self.trcl_State.id + leave = self._create_leave() + # Leave takes in consideration State + self.assertEqual(leave.number_of_days_display, 1.0) + + def test_unusual_days_without_state(self): + unusual_days = self.employee._get_unusual_days( + "2024-07-01", date_to="2024-07-02" + ) + self.assertTrue(unusual_days["2024-07-01"]) + self.assertFalse(unusual_days["2024-07-02"]) + + def test_unusual_days_with_state(self): + self.partner.state_id = self.trcl_State.id + unusual_days = self.employee._get_unusual_days( + "2024-07-01", date_to="2024-07-02" + ) + self.assertTrue(unusual_days["2024-07-01"]) + self.assertTrue(unusual_days["2024-07-02"]) diff --git a/resource_leaves_geographic/views/resource_calendar_leaves_views.xml b/resource_leaves_geographic/views/resource_calendar_leaves_views.xml new file mode 100644 index 00000000..426869fa --- /dev/null +++ b/resource_leaves_geographic/views/resource_calendar_leaves_views.xml @@ -0,0 +1,56 @@ + + + + + resource.calendar.leaves.state.tree + resource.calendar.leaves + + + + + + + + + + resource.calendar.leaves.state.form + resource.calendar.leaves + + + + + + + + + + resource.calendar.leaves.state.calendar + resource.calendar.leaves + + + + + + + + + + resource.calendar.leaves.state.search + resource.calendar.leaves + + + + + + + + diff --git a/setup/resource_leaves_geographic/odoo/addons/resource_leaves_geographic b/setup/resource_leaves_geographic/odoo/addons/resource_leaves_geographic new file mode 120000 index 00000000..b911fd35 --- /dev/null +++ b/setup/resource_leaves_geographic/odoo/addons/resource_leaves_geographic @@ -0,0 +1 @@ +../../../../resource_leaves_geographic \ No newline at end of file diff --git a/setup/resource_leaves_geographic/setup.py b/setup/resource_leaves_geographic/setup.py new file mode 100644 index 00000000..28c57bb6 --- /dev/null +++ b/setup/resource_leaves_geographic/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)