diff --git a/calendar_public_holiday/README.rst b/calendar_public_holiday/README.rst new file mode 100644 index 00000000..39f5f983 --- /dev/null +++ b/calendar_public_holiday/README.rst @@ -0,0 +1,100 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + +======================== +Calendar Holidays Public +======================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:a209463965237ab34586bc10803aa2d29ef75979c9388634316fb1326a02273d + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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%2Fcalendar-lightgray.png?logo=github + :target: https://github.com/OCA/calendar/tree/19.0/calendar_public_holiday + :alt: OCA/calendar +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/calendar-19-0/calendar-19-0-calendar_public_holiday + :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/calendar&target_branch=19.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module handles public holidays. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +For adding public holidays: + +1. Go to the menu *Calendar > Public Holidays > Public Holidays*. +2. Create your public holidays. + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Michael Telahun Makonnen +* Tecnativa +* Fekete Mihai (Forest and Biomass Services Romania) +* Druidoo +* Camptocamp +* + +Contributors +------------ + +- [Trobz](https://trobz.com): + + - Do Anh Duy <> + +Other credits +------------- + +The creation of this module was financially supported by Camptocamp + +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/calendar `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/calendar_public_holiday/__init__.py b/calendar_public_holiday/__init__.py new file mode 100644 index 00000000..e68a3e61 --- /dev/null +++ b/calendar_public_holiday/__init__.py @@ -0,0 +1,5 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from . import models +from . import wizards +from .hooks import pre_init_hook diff --git a/calendar_public_holiday/__manifest__.py b/calendar_public_holiday/__manifest__.py new file mode 100644 index 00000000..8d6f002f --- /dev/null +++ b/calendar_public_holiday/__manifest__.py @@ -0,0 +1,31 @@ +# Copyright 2015 2011,2013 Michael Telahun Makonnen +# Copyright 2020 InitOS Gmbh +# Copyright 2024 Camptocamp +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +{ + "name": "Calendar Holidays Public", + "summary": """ + Manage Public Holidays + """, + "version": "19.0.1.0.0", + "license": "AGPL-3", + "category": "HR/Calendar", + "author": "Michael Telahun Makonnen, " + "Tecnativa, " + "Fekete Mihai (Forest and Biomass Services Romania), " + "Druidoo, " + "Odoo Community Association (OCA), " + "Camptocamp,", + "website": "https://github.com/OCA/calendar", + "depends": ["calendar"], + "external_dependencies": {"python": ["openupgradelib"]}, + "data": [ + "data/data.xml", + "security/ir.model.access.csv", + "views/calendar_public_holiday_view.xml", + "wizards/calendar_public_holiday_next_year_wizard.xml", + ], + "pre_init_hook": "pre_init_hook", + "installable": True, +} diff --git a/calendar_public_holiday/data/data.xml b/calendar_public_holiday/data/data.xml new file mode 100644 index 00000000..74bcb333 --- /dev/null +++ b/calendar_public_holiday/data/data.xml @@ -0,0 +1,8 @@ + + + + + Public Holidays + + diff --git a/calendar_public_holiday/hooks.py b/calendar_public_holiday/hooks.py new file mode 100644 index 00000000..72f026ed --- /dev/null +++ b/calendar_public_holiday/hooks.py @@ -0,0 +1,55 @@ +# Copyright 2024 Camptocamp +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from openupgradelib import openupgrade + + +def migrate_rename_xmlid_event_type_holiday(env): + if not openupgrade.is_module_installed(env.cr, "hr_holidays_public"): + return + xmlid_renames = [ + ( + "hr_holidays_public.event_type_holiday", + "calendar_public_holiday.event_type_holiday", + ), + ] + openupgrade.rename_xmlids(env.cr, xmlid_renames) + + +def migrate_rename_field_model_hr_holidays_public_line(env): + field_renames = [ + ( + "hr.holidays.public.line", + "hr_holidays_public_line", + "year_id", + "public_holiday_id", + ), + ] + openupgrade.rename_fields(env, field_renames, no_deep=True) + + +def migrate_rename_model_hr_holidays_public_line(env): + if not openupgrade.table_exists(env.cr, "hr_holidays_public_line"): + return + model_renames = [("hr.holidays.public.line", "calendar.public.holiday.line")] + openupgrade.rename_models(env.cr, model_renames) + tables_renames = [("hr_holidays_public_line", "calendar_public_holiday_line")] + openupgrade.rename_tables(env.cr, tables_renames) + + +def migrate_rename_model_hr_holidays_public(env): + if not openupgrade.table_exists(env.cr, "hr_holidays_public"): + return + model_renames = [ + ("hr.holidays.public", "calendar.public.holiday"), + ] + openupgrade.rename_models(env.cr, model_renames) + tables_renames = [("hr_holidays_public", "calendar_public_holiday")] + openupgrade.rename_tables(env.cr, tables_renames) + + +def pre_init_hook(env): + migrate_rename_xmlid_event_type_holiday(env) + migrate_rename_field_model_hr_holidays_public_line(env) + migrate_rename_model_hr_holidays_public_line(env) + migrate_rename_model_hr_holidays_public(env) diff --git a/calendar_public_holiday/i18n/calendar_public_holiday.pot b/calendar_public_holiday/i18n/calendar_public_holiday.pot new file mode 100644 index 00000000..b69d71a0 --- /dev/null +++ b/calendar_public_holiday/i18n/calendar_public_holiday.pot @@ -0,0 +1,244 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * calendar_public_holiday +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: calendar_public_holiday +#: model_terms:ir.ui.view,arch_db:calendar_public_holiday.calendar_public_holiday_next_year_view +msgid "" +"By default, the most recent public holidays\n" +" for each country are used as template to create\n" +" public holidays for the year following the templates.\n" +"

\n" +" Normally, you should not need to input anything in\n" +" optional fields and only need to click on the button\n" +" \"Create\"." +msgstr "" + +#. module: calendar_public_holiday +#: model:ir.model,name:calendar_public_holiday.model_calendar_public_holiday +msgid "Calendar Public Holiday" +msgstr "" + +#. module: calendar_public_holiday +#: model:ir.model,name:calendar_public_holiday.model_calendar_public_holiday_line +msgid "Calendar Public Holiday Line" +msgstr "" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday__year +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_line__public_holiday_id +msgid "Calendar Year" +msgstr "" + +#. module: calendar_public_holiday +#: model_terms:ir.ui.view,arch_db:calendar_public_holiday.calendar_public_holiday_next_year_view +msgid "Cancel" +msgstr "" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday__country_id +msgid "Country" +msgstr "" + +#. module: calendar_public_holiday +#: model_terms:ir.ui.view,arch_db:calendar_public_holiday.calendar_public_holiday_next_year_view +msgid "Create" +msgstr "" + +#. module: calendar_public_holiday +#: model:ir.actions.act_window,name:calendar_public_holiday.action_create_next_year_public_holidays +#: model:ir.ui.menu,name:calendar_public_holiday.menu_create_next_year_public_holidays +#: model_terms:ir.ui.view,arch_db:calendar_public_holiday.calendar_public_holiday_next_year_view +msgid "Create Next Year Public Holidays" +msgstr "" + +#. module: calendar_public_holiday +#: model:ir.model,name:calendar_public_holiday.model_calendar_public_holiday_next_year +msgid "Create Public Holiday From Existing Ones" +msgstr "" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday__create_uid +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_line__create_uid +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_next_year__create_uid +msgid "Created by" +msgstr "" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday__create_date +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_line__create_date +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_next_year__create_date +msgid "Created on" +msgstr "" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_line__date +msgid "Date" +msgstr "" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_line__variable_date +msgid "Date may change" +msgstr "" + +#. module: calendar_public_holiday +#. odoo-python +#: code:addons/calendar_public_holiday/models/calendar_public_holiday_line.py:0 +msgid "" +"Dates of holidays should be the same year as the calendar year they are " +"being assigned to" +msgstr "" + +#. module: calendar_public_holiday +#: model_terms:ir.ui.view,arch_db:calendar_public_holiday.calendar_public_holiday_next_year_view +msgid "Defaults" +msgstr "" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday__display_name +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_line__display_name +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_next_year__display_name +msgid "Display Name" +msgstr "" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday__line_ids +msgid "Holiday Dates" +msgstr "" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday__id +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_line__id +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_next_year__id +msgid "ID" +msgstr "" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday__write_uid +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_line__write_uid +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_next_year__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday__write_date +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_line__write_date +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_next_year__write_date +msgid "Last Updated on" +msgstr "" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_line__meeting_id +msgid "Meeting" +msgstr "" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_line__name +msgid "Name" +msgstr "" + +#. module: calendar_public_holiday +#. odoo-python +#: code:addons/calendar_public_holiday/wizards/calendar_public_holiday_next_year_wizard.py:0 +msgid "New public holidays" +msgstr "" + +#. module: calendar_public_holiday +#. odoo-python +#: code:addons/calendar_public_holiday/wizards/calendar_public_holiday_next_year_wizard.py:0 +msgid "" +"No Public Holidays found as template. Please create the first Public " +"Holidays manually." +msgstr "" + +#. module: calendar_public_holiday +#: model_terms:ir.ui.view,arch_db:calendar_public_holiday.calendar_public_holiday_next_year_view +msgid "Optional" +msgstr "" + +#. module: calendar_public_holiday +#: model:ir.actions.act_window,name:calendar_public_holiday.open_calendar_public_holiday_view +#: model:ir.ui.menu,name:calendar_public_holiday.menu_calendar_public_holiday +#: model:ir.ui.menu,name:calendar_public_holiday.menu_calendar_public_holiday_view +#: model_terms:ir.ui.view,arch_db:calendar_public_holiday.view_calendar_public_holiday_form +msgid "Public Holidays" +msgstr "" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_line__state_ids +msgid "Related States" +msgstr "" + +#. module: calendar_public_holiday +#: model:ir.model.fields,help:calendar_public_holiday.field_calendar_public_holiday_next_year__public_holiday_ids +msgid "" +"Select the public holidays to use as template. If not set, latest public " +"holidays of each country will be used. Only the last templates of each " +"country for each year will be taken into account (If you select templates " +"from 2012 and 2015, only the templates from 2015 will be taken into account." +msgstr "" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_next_year__public_holiday_ids +msgid "Templates" +msgstr "" + +#. module: calendar_public_holiday +#: model_terms:ir.ui.view,arch_db:calendar_public_holiday.calendar_public_holiday_next_year_view +msgid "" +"The below optional fields are here only to handle\n" +" special situations like \"2011 was a special year with\n" +" an additional public holiday for the 150th\n" +" anniversary of the Italian unification, so you want to\n" +" replicate the 2010 Italian holidays to 2012.\"" +msgstr "" + +#. module: calendar_public_holiday +#: model_terms:ir.ui.view,arch_db:calendar_public_holiday.calendar_public_holiday_next_year_view +msgid "" +"Use this wizard to create public holidays based on the\n" +" existing ones.
\n" +" Only the last templates of each country\n" +" will be taken into account (If you select templates\n" +" from 2012 and 2015 of the same country; '\n" +" only the templates from 2015 will be taken into\n" +" account)." +msgstr "" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_next_year__year +msgid "Year" +msgstr "" + +#. module: calendar_public_holiday +#: model:ir.model.fields,help:calendar_public_holiday.field_calendar_public_holiday_next_year__year +msgid "" +"Year for which you want to create the public holidays. By default, the year " +"following the template." +msgstr "" + +#. module: calendar_public_holiday +#. odoo-python +#: code:addons/calendar_public_holiday/models/calendar_public_holiday.py:0 +msgid "You can't create duplicate public holiday per year and/or country" +msgstr "" + +#. module: calendar_public_holiday +#. odoo-python +#: code:addons/calendar_public_holiday/wizards/calendar_public_holiday_next_year_wizard.py:0 +msgid "" +"You cannot use as template the public holidays of a year that includes " +"public holidays on 29th of February (2016, 2020...), please select a " +"template from another year." +msgstr "" diff --git a/calendar_public_holiday/i18n/es.po b/calendar_public_holiday/i18n/es.po new file mode 100644 index 00000000..50264a80 --- /dev/null +++ b/calendar_public_holiday/i18n/es.po @@ -0,0 +1,268 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * calendar_public_holiday +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2025-08-07 11:26+0000\n" +"Last-Translator: Miquel Romera \n" +"Language-Team: none\n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 5.10.4\n" + +#. module: calendar_public_holiday +#: model_terms:ir.ui.view,arch_db:calendar_public_holiday.calendar_public_holiday_next_year_view +msgid "" +"By default, the most recent public holidays\n" +" for each country are used as template to create\n" +" public holidays for the year following the templates.\n" +"

\n" +" Normally, you should not need to input anything in\n" +" optional fields and only need to click on the button\n" +" \"Create\"." +msgstr "" +"Por defecto, los días festivos más recientes\n" +"de cada país se utilizan como plantilla para crear\n" +"los días festivos del año siguiente a las plantillas.\n" +"br/>
\n" +"Normalmente, no es necesario introducir nada en\n" +"los campos opcionales, solo hay que hacer clic en el botón\n" +"\"Crear\"." + +#. module: calendar_public_holiday +#: model:ir.model,name:calendar_public_holiday.model_calendar_public_holiday +msgid "Calendar Public Holiday" +msgstr "Calendario de días festivos" + +#. module: calendar_public_holiday +#: model:ir.model,name:calendar_public_holiday.model_calendar_public_holiday_line +msgid "Calendar Public Holiday Line" +msgstr "Línea de días festivos del calendario" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday__year +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_line__public_holiday_id +msgid "Calendar Year" +msgstr "Año de calendario" + +#. module: calendar_public_holiday +#: model_terms:ir.ui.view,arch_db:calendar_public_holiday.calendar_public_holiday_next_year_view +msgid "Cancel" +msgstr "Cancelar" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday__country_id +msgid "Country" +msgstr "País" + +#. module: calendar_public_holiday +#: model_terms:ir.ui.view,arch_db:calendar_public_holiday.calendar_public_holiday_next_year_view +msgid "Create" +msgstr "Crear" + +#. module: calendar_public_holiday +#: model:ir.actions.act_window,name:calendar_public_holiday.action_create_next_year_public_holidays +#: model:ir.ui.menu,name:calendar_public_holiday.menu_create_next_year_public_holidays +#: model_terms:ir.ui.view,arch_db:calendar_public_holiday.calendar_public_holiday_next_year_view +msgid "Create Next Year Public Holidays" +msgstr "Crear días festivos del próximo año" + +#. module: calendar_public_holiday +#: model:ir.model,name:calendar_public_holiday.model_calendar_public_holiday_next_year +msgid "Create Public Holiday From Existing Ones" +msgstr "Crear un día festivo a partir de los ya existentes" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday__create_uid +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_line__create_uid +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_next_year__create_uid +msgid "Created by" +msgstr "Creado por" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday__create_date +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_line__create_date +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_next_year__create_date +msgid "Created on" +msgstr "Creado en" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_line__date +msgid "Date" +msgstr "Fecha" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_line__variable_date +msgid "Date may change" +msgstr "La fecha puede cambiar" + +#. module: calendar_public_holiday +#. odoo-python +#: code:addons/calendar_public_holiday/models/calendar_public_holiday_line.py:0 +msgid "" +"Dates of holidays should be the same year as the calendar year they are " +"being assigned to" +msgstr "" +"Las fechas de los días festivos deben corresponder al mismo año que el año " +"natural al que se asignan" + +#. module: calendar_public_holiday +#: model_terms:ir.ui.view,arch_db:calendar_public_holiday.calendar_public_holiday_next_year_view +msgid "Defaults" +msgstr "Valores predeterminados" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday__display_name +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_line__display_name +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_next_year__display_name +msgid "Display Name" +msgstr "Nombre mostrado" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday__line_ids +msgid "Holiday Dates" +msgstr "Días festivos" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday__id +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_line__id +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_next_year__id +msgid "ID" +msgstr "ID" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday__write_uid +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_line__write_uid +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_next_year__write_uid +msgid "Last Updated by" +msgstr "Última actualización de" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday__write_date +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_line__write_date +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_next_year__write_date +msgid "Last Updated on" +msgstr "Última actualización en" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_line__meeting_id +msgid "Meeting" +msgstr "Reunión" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_line__name +msgid "Name" +msgstr "Nombre" + +#. module: calendar_public_holiday +#. odoo-python +#: code:addons/calendar_public_holiday/wizards/calendar_public_holiday_next_year_wizard.py:0 +msgid "New public holidays" +msgstr "Nuevos días festivos" + +#. module: calendar_public_holiday +#. odoo-python +#: code:addons/calendar_public_holiday/wizards/calendar_public_holiday_next_year_wizard.py:0 +msgid "" +"No Public Holidays found as template. Please create the first Public " +"Holidays manually." +msgstr "" +"No se han encontrado días festivos como plantilla. Por favor, cree los " +"primeros días festivos manualmente." + +#. module: calendar_public_holiday +#: model_terms:ir.ui.view,arch_db:calendar_public_holiday.calendar_public_holiday_next_year_view +msgid "Optional" +msgstr "Opcional" + +#. module: calendar_public_holiday +#: model:ir.actions.act_window,name:calendar_public_holiday.open_calendar_public_holiday_view +#: model:ir.ui.menu,name:calendar_public_holiday.menu_calendar_public_holiday +#: model:ir.ui.menu,name:calendar_public_holiday.menu_calendar_public_holiday_view +#: model_terms:ir.ui.view,arch_db:calendar_public_holiday.view_calendar_public_holiday_form +msgid "Public Holidays" +msgstr "Días festivos" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_line__state_ids +msgid "Related States" +msgstr "Provincia relacionada" + +#. module: calendar_public_holiday +#: model:ir.model.fields,help:calendar_public_holiday.field_calendar_public_holiday_next_year__public_holiday_ids +msgid "" +"Select the public holidays to use as template. If not set, latest public " +"holidays of each country will be used. Only the last templates of each " +"country for each year will be taken into account (If you select templates " +"from 2012 and 2015, only the templates from 2015 will be taken into account." +msgstr "" +"Seleccione los días festivos que desea utilizar como plantilla. Si no se " +"establece nada, se utilizarán los últimos días festivos de cada país. Solo " +"se tendrán en cuenta las últimas plantillas de cada país para cada año (si " +"selecciona plantillas de 2012 y 2015, solo se tendrán en cuenta las " +"plantillas de 2015)." + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_next_year__public_holiday_ids +msgid "Templates" +msgstr "Plantillas" + +#. module: calendar_public_holiday +#: model_terms:ir.ui.view,arch_db:calendar_public_holiday.calendar_public_holiday_next_year_view +msgid "" +"The below optional fields are here only to handle\n" +" special situations like \"2011 was a special year with\n" +" an additional public holiday for the 150th\n" +" anniversary of the Italian unification, so you want to\n" +" replicate the 2010 Italian holidays to 2012.\"" +msgstr "" + +#. module: calendar_public_holiday +#: model_terms:ir.ui.view,arch_db:calendar_public_holiday.calendar_public_holiday_next_year_view +msgid "" +"Use this wizard to create public holidays based on the\n" +" existing ones.
\n" +" Only the last templates of each country\n" +" will be taken into account (If you select templates\n" +" from 2012 and 2015 of the same country; '\n" +" only the templates from 2015 will be taken into\n" +" account)." +msgstr "" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_next_year__year +msgid "Year" +msgstr "Año" + +#. module: calendar_public_holiday +#: model:ir.model.fields,help:calendar_public_holiday.field_calendar_public_holiday_next_year__year +msgid "" +"Year for which you want to create the public holidays. By default, the year " +"following the template." +msgstr "" +"Año para el que desea crear los días festivos. Por defecto, el año siguiente " +"a la plantilla." + +#. module: calendar_public_holiday +#. odoo-python +#: code:addons/calendar_public_holiday/models/calendar_public_holiday.py:0 +msgid "You can't create duplicate public holiday per year and/or country" +msgstr "No se pueden crear días festivos duplicados por año y/o país" + +#. module: calendar_public_holiday +#. odoo-python +#: code:addons/calendar_public_holiday/wizards/calendar_public_holiday_next_year_wizard.py:0 +msgid "" +"You cannot use as template the public holidays of a year that includes " +"public holidays on 29th of February (2016, 2020...), please select a " +"template from another year." +msgstr "" +"No puede utilizar como plantilla los días festivos de un año que incluya " +"días festivos el 29 de febrero (2016, 2020...), por favor seleccione una " +"plantilla de otro año." diff --git a/calendar_public_holiday/i18n/it.po b/calendar_public_holiday/i18n/it.po new file mode 100644 index 00000000..25c8a894 --- /dev/null +++ b/calendar_public_holiday/i18n/it.po @@ -0,0 +1,287 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * calendar_public_holiday +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2025-02-15 10:06+0000\n" +"Last-Translator: mymage \n" +"Language-Team: none\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 5.6.2\n" + +#. module: calendar_public_holiday +#: model_terms:ir.ui.view,arch_db:calendar_public_holiday.calendar_public_holiday_next_year_view +msgid "" +"By default, the most recent public holidays\n" +" for each country are used as template to create\n" +" public holidays for the year following the templates.\n" +"

\n" +" Normally, you should not need to input anything in\n" +" optional fields and only need to click on the button\n" +" \"Create\"." +msgstr "" +"Per impostazione predefinita, i giorni festivi più recenti\n" +" per ogni paese sono usati come modello per " +"creare\n" +" le festività per l'anno seguendo i modelli.\n" +"

\n" +" Normalmente, non dovrebbe essere necessario " +"inserire nulla\n" +" nei campi facoltativi ed è solo necessario fare " +"clic sul pulsante\n" +" \"Crea\"." + +#. module: calendar_public_holiday +#: model:ir.model,name:calendar_public_holiday.model_calendar_public_holiday +msgid "Calendar Public Holiday" +msgstr "Calendario giorni festivi" + +#. module: calendar_public_holiday +#: model:ir.model,name:calendar_public_holiday.model_calendar_public_holiday_line +msgid "Calendar Public Holiday Line" +msgstr "Riga giorno festivo calendario" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday__year +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_line__public_holiday_id +msgid "Calendar Year" +msgstr "Anno del calendario" + +#. module: calendar_public_holiday +#: model_terms:ir.ui.view,arch_db:calendar_public_holiday.calendar_public_holiday_next_year_view +msgid "Cancel" +msgstr "Annulla" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday__country_id +msgid "Country" +msgstr "Nazione" + +#. module: calendar_public_holiday +#: model_terms:ir.ui.view,arch_db:calendar_public_holiday.calendar_public_holiday_next_year_view +msgid "Create" +msgstr "Crea" + +#. module: calendar_public_holiday +#: model:ir.actions.act_window,name:calendar_public_holiday.action_create_next_year_public_holidays +#: model:ir.ui.menu,name:calendar_public_holiday.menu_create_next_year_public_holidays +#: model_terms:ir.ui.view,arch_db:calendar_public_holiday.calendar_public_holiday_next_year_view +msgid "Create Next Year Public Holidays" +msgstr "Crea giorni festivi del prossimo anno" + +#. module: calendar_public_holiday +#: model:ir.model,name:calendar_public_holiday.model_calendar_public_holiday_next_year +msgid "Create Public Holiday From Existing Ones" +msgstr "Crea giorni festivi da quelle esistenti" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday__create_uid +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_line__create_uid +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_next_year__create_uid +msgid "Created by" +msgstr "Creato da" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday__create_date +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_line__create_date +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_next_year__create_date +msgid "Created on" +msgstr "Creato il" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_line__date +msgid "Date" +msgstr "Data" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_line__variable_date +msgid "Date may change" +msgstr "Data variabile" + +#. module: calendar_public_holiday +#. odoo-python +#: code:addons/calendar_public_holiday/models/calendar_public_holiday_line.py:0 +msgid "" +"Dates of holidays should be the same year as the calendar year they are " +"being assigned to" +msgstr "" +"Le date delle vacanze dovrebbero coincidere con l'anno solare a cui sono " +"state assegnate" + +#. module: calendar_public_holiday +#: model_terms:ir.ui.view,arch_db:calendar_public_holiday.calendar_public_holiday_next_year_view +msgid "Defaults" +msgstr "Predefiniti" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday__display_name +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_line__display_name +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_next_year__display_name +msgid "Display Name" +msgstr "Nome visualizzato" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday__line_ids +msgid "Holiday Dates" +msgstr "Date festività" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday__id +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_line__id +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_next_year__id +msgid "ID" +msgstr "ID" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday__write_uid +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_line__write_uid +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_next_year__write_uid +msgid "Last Updated by" +msgstr "Ultimo aggiornamento di" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday__write_date +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_line__write_date +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_next_year__write_date +msgid "Last Updated on" +msgstr "Ultimo aggiornamento il" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_line__meeting_id +msgid "Meeting" +msgstr "Riunione" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_line__name +msgid "Name" +msgstr "Nome" + +#. module: calendar_public_holiday +#. odoo-python +#: code:addons/calendar_public_holiday/wizards/calendar_public_holiday_next_year_wizard.py:0 +msgid "New public holidays" +msgstr "Nuovi giorni festivi" + +#. module: calendar_public_holiday +#. odoo-python +#: code:addons/calendar_public_holiday/wizards/calendar_public_holiday_next_year_wizard.py:0 +msgid "" +"No Public Holidays found as template. Please create the first Public " +"Holidays manually." +msgstr "" +"Nessun giorno festivo trovato come modello. Si prega di creare i primi " +"giorni festivi manualmente." + +#. module: calendar_public_holiday +#: model_terms:ir.ui.view,arch_db:calendar_public_holiday.calendar_public_holiday_next_year_view +msgid "Optional" +msgstr "Opzionale" + +#. module: calendar_public_holiday +#: model:ir.actions.act_window,name:calendar_public_holiday.open_calendar_public_holiday_view +#: model:ir.ui.menu,name:calendar_public_holiday.menu_calendar_public_holiday +#: model:ir.ui.menu,name:calendar_public_holiday.menu_calendar_public_holiday_view +#: model_terms:ir.ui.view,arch_db:calendar_public_holiday.view_calendar_public_holiday_form +msgid "Public Holidays" +msgstr "Giorni festivi" + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_line__state_ids +msgid "Related States" +msgstr "Nazioni correlate" + +#. module: calendar_public_holiday +#: model:ir.model.fields,help:calendar_public_holiday.field_calendar_public_holiday_next_year__public_holiday_ids +msgid "" +"Select the public holidays to use as template. If not set, latest public " +"holidays of each country will be used. Only the last templates of each " +"country for each year will be taken into account (If you select templates " +"from 2012 and 2015, only the templates from 2015 will be taken into account." +msgstr "" +"Seleziona i giorni festivi da utilizzare come modello. In caso contrario, " +"verranno utilizzati gli ultimi giorni festivi di ciascun paese. Verranno " +"presi in considerazione solo gli ultimi modelli di ciascun paese per ogni " +"anno (se si selezionano modelli del 2012 e del 2015, verranno presi in " +"considerazione solo i modelli del 2015." + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_next_year__public_holiday_ids +msgid "Templates" +msgstr "Modelli" + +#. module: calendar_public_holiday +#: model_terms:ir.ui.view,arch_db:calendar_public_holiday.calendar_public_holiday_next_year_view +msgid "" +"The below optional fields are here only to handle\n" +" special situations like \"2011 was a special year with\n" +" an additional public holiday for the 150th\n" +" anniversary of the Italian unification, so you want to\n" +" replicate the 2010 Italian holidays to 2012.\"" +msgstr "" +"I campi facoltativi seguenti sono qui solo per gestire\n" +" situazioni particolari come \"Il 2011 è stato " +"un anno speciale con\n" +" un giorno festivo aggiuntivo per il 150°\n" +" anniversario dell'Unità d'Italia, quindi vuoi\n" +" replicare le festività italiane dal 2010 al " +"2012.\"" + +#. module: calendar_public_holiday +#: model_terms:ir.ui.view,arch_db:calendar_public_holiday.calendar_public_holiday_next_year_view +msgid "" +"Use this wizard to create public holidays based on the\n" +" existing ones.
\n" +" Only the last templates of each country\n" +" will be taken into account (If you select templates\n" +" from 2012 and 2015 of the same country; '\n" +" only the templates from 2015 will be taken into\n" +" account)." +msgstr "" +"Utilizzare questa procedura guidata per creare giorni festivi basati su\n" +" quelli esistenti.
\n" +" Solo gli ultimi modelli di ogni paese\n" +" verranno presi in considerazione (se si selezionano " +"i modelli\n" +" dal 2012 al 2015 dello stesso Paese; '\n" +" verranno presi in considerazione solo i modelli del " +"2015\n" +" )." + +#. module: calendar_public_holiday +#: model:ir.model.fields,field_description:calendar_public_holiday.field_calendar_public_holiday_next_year__year +msgid "Year" +msgstr "Anno" + +#. module: calendar_public_holiday +#: model:ir.model.fields,help:calendar_public_holiday.field_calendar_public_holiday_next_year__year +msgid "" +"Year for which you want to create the public holidays. By default, the year " +"following the template." +msgstr "" +"Anno per il quale si desidera creare i giorni festivi. Per impostazione " +"predefinita, l'anno successivo al modello." + +#. module: calendar_public_holiday +#. odoo-python +#: code:addons/calendar_public_holiday/models/calendar_public_holiday.py:0 +msgid "You can't create duplicate public holiday per year and/or country" +msgstr "Non è possibile creare giorni festivi duplicati per anno e/o nazione" + +#. module: calendar_public_holiday +#. odoo-python +#: code:addons/calendar_public_holiday/wizards/calendar_public_holiday_next_year_wizard.py:0 +msgid "" +"You cannot use as template the public holidays of a year that includes " +"public holidays on 29th of February (2016, 2020...), please select a " +"template from another year." +msgstr "" +"Non si possono utilizzare come modello i giorni festivi di un anno che " +"presenta giorni festivi il 29 febbraio (2016, 2020...), seleziona un modello " +"di un altro anno." diff --git a/calendar_public_holiday/models/__init__.py b/calendar_public_holiday/models/__init__.py new file mode 100644 index 00000000..a3e864da --- /dev/null +++ b/calendar_public_holiday/models/__init__.py @@ -0,0 +1,4 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from . import calendar_public_holiday +from . import calendar_public_holiday_line diff --git a/calendar_public_holiday/models/calendar_public_holiday.py b/calendar_public_holiday/models/calendar_public_holiday.py new file mode 100644 index 00000000..cadaef73 --- /dev/null +++ b/calendar_public_holiday/models/calendar_public_holiday.py @@ -0,0 +1,126 @@ +# Copyright 2015 2011,2013 Michael Telahun Makonnen +# Copyright 2020 InitOS Gmbh +# Copyright 2024 Camptocamp +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import datetime + +from odoo import api, fields, models +from odoo.exceptions import ValidationError + + +class ResourceCalendarPublicHoliday(models.Model): + _name = "calendar.public.holiday" + _description = "Calendar Public Holiday" + _rec_name = "year" + _order = "year desc" + + year = fields.Integer( + "Calendar Year", + required=True, + default=lambda self: fields.Date.context_today(self).year, + ) + line_ids = fields.One2many( + "calendar.public.holiday.line", + "public_holiday_id", + "Holiday Dates", + ) + country_id = fields.Many2one("res.country", "Country") + + @api.constrains("year", "country_id") + def _check_year(self): + for line in self: + line._check_year_one() + + def _check_year_one(self): + if self.search_count( + [ + ("year", "=", self.year), + ("country_id", "=", self.country_id.id), + ("id", "!=", self.id), + ] + ): + raise ValidationError( + self.env._( + "You can't create duplicate public holiday per year and/or country" + ) + ) + return True + + @api.depends("country_id") + def _compute_display_name(self): + for line in self: + if line.country_id: + line.display_name = f"{line.year} ({line.country_id.name})" + else: + line.display_name = line.year + + def _get_domain_states_filter(self, pholidays, start_dt, end_dt, partner_id=None): + partner = self.env["res.partner"].browse(partner_id) + states_filter = [ + ("public_holiday_id", "in", pholidays.ids), + ("date", ">=", start_dt), + ("date", "<=", end_dt), + ] + if partner and partner.state_id: + states_filter.extend( + [ + "|", + ("state_ids", "in", partner.state_id.ids), + ("state_ids", "=", False), + ] + ) + else: + states_filter.append(("state_ids", "=", False)) + return states_filter + + @api.model + def get_holidays_list(self, year=None, start_dt=None, end_dt=None, partner_id=None): + """Returns recordset of calendar.public.holiday.line + for the specified year and employee + :param year: year as string (optional if start_dt and end_dt defined) + :param start_dt: start_dt as date + :param end_dt: end_dt as date + :param partner_id: ID of the partner + :return: recordset of calendar.public.holiday.line + """ + partner = self.env["res.partner"].browse(partner_id) + if not start_dt and not end_dt: + start_dt = datetime.date(year, 1, 1) + end_dt = datetime.date(year, 12, 31) + years = list(range(start_dt.year, end_dt.year + 1)) + holidays_filter = [("year", "in", years)] + if partner: + if partner.country_id: + holidays_filter.append( + ("country_id", "in", (False, partner.country_id.id)) + ) + else: + holidays_filter.append(("country_id", "=", False)) + public_holidays = self.search(holidays_filter) + public_holiday_line = self.env["calendar.public.holiday.line"] + if not public_holidays: + return public_holiday_line + states_filter = self._get_domain_states_filter( + public_holidays, start_dt, end_dt, partner_id=partner.id + ) + return public_holiday_line.search(states_filter) + + @api.model + def is_public_holiday(self, selected_date, partner_id=None): + """ + Returns True if selected_date is a public holiday for the employee + :param selected_date: datetime object + :param partner_id: ID of the partner + :return: bool + """ + partner = self.env["res.partner"].browse(partner_id) + partner_id = partner.id if partner else None + holidays_lines = self.get_holidays_list( + year=selected_date.year, partner_id=partner_id + ) + if holidays_lines: + hol_date = holidays_lines.filtered(lambda r: r.date == selected_date) + if hol_date: + return True + return False diff --git a/calendar_public_holiday/models/calendar_public_holiday_line.py b/calendar_public_holiday/models/calendar_public_holiday_line.py new file mode 100644 index 00000000..69a05444 --- /dev/null +++ b/calendar_public_holiday/models/calendar_public_holiday_line.py @@ -0,0 +1,125 @@ +# Copyright 2015 2011,2013 Michael Telahun Makonnen +# Copyright 2020 InitOS Gmbh +# Copyright 2024 Camptocamp +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import SUPERUSER_ID, api, fields, models +from odoo.exceptions import ValidationError + + +class CalendarHolidaysPublicLine(models.Model): + _name = "calendar.public.holiday.line" + _description = "Calendar Public Holiday Line" + _order = "date, name desc" + + name = fields.Char(required=True) + date = fields.Date(required=True) + public_holiday_id = fields.Many2one( + "calendar.public.holiday", + "Calendar Year", + required=True, + ondelete="cascade", + ) + variable_date = fields.Boolean("Date may change", default=True) + state_ids = fields.Many2many( + "res.country.state", + "public_holiday_state_rel", + "public_holiday_line_id", + "state_id", + "Related States", + ) + meeting_id = fields.Many2one( + "calendar.event", + string="Meeting", + copy=False, + ) + + @api.constrains("date", "state_ids") + def _check_date_state(self): + for line in self: + line._check_date_state_one() + + def _get_domain_check_date_state_one_state_ids(self): + return [ + ("date", "=", self.date), + ("public_holiday_id", "=", self.public_holiday_id.id), + ("state_ids", "!=", False), + ("id", "!=", self.id), + ] + + def _get_domain_check_date_state_one(self): + return [ + ("date", "=", self.date), + ("public_holiday_id", "=", self.public_holiday_id.id), + ("state_ids", "=", False), + ] + + def _check_date_state_one(self): + if self.date.year != self.public_holiday_id.year: + raise ValidationError( + self.env._( + "Dates of holidays should be the same year as the calendar" + " year they are being assigned to" + ) + ) + if self.state_ids: + domain = self._get_domain_check_date_state_one_state_ids() + holidays = self.search(domain) + for holiday in holidays: + if self.state_ids & holiday.state_ids: + raise ValidationError( + self.env._( + "You can't create duplicate public holiday per date %s " + "and one of the country states.", + self.date, + ) + ) + domain = self._get_domain_check_date_state_one() + if self.search_count(domain) > 1: + raise ValidationError( + self.env._( + "You can't create duplicate public holiday per date %s.", + self.date, + ) + ) + return True + + def _prepare_holidays_meeting_values(self): + self.ensure_one() + categ_id = self.env.ref("calendar_public_holiday.event_type_holiday", False) + meeting_values = { + "name": ( + f"{self.name} ({self.public_holiday_id.country_id.name})" + if self.public_holiday_id.country_id + else self.name + ), + "description": ", ".join(self.state_ids.mapped("name")), + "start": self.date, + "stop": self.date, + "allday": True, + "user_id": SUPERUSER_ID, + "privacy": "confidential", + "show_as": "busy", + } + if categ_id: + meeting_values.update({"categ_ids": [(6, 0, categ_id.ids)]}) + return meeting_values + + @api.constrains("date", "name", "public_holiday_id", "state_ids") + def _update_calendar_event(self): + for rec in self: + if rec.meeting_id: + rec.meeting_id.write(rec._prepare_holidays_meeting_values()) + + @api.model_create_multi + def create(self, vals_list): + res = super().create(vals_list) + for record in res: + record.meeting_id = self.env["calendar.event"].create( + record._prepare_holidays_meeting_values() + ) + return res + + def unlink(self): + self.mapped("meeting_id").unlink() + return super().unlink() diff --git a/calendar_public_holiday/pyproject.toml b/calendar_public_holiday/pyproject.toml new file mode 100644 index 00000000..4231d0cc --- /dev/null +++ b/calendar_public_holiday/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/calendar_public_holiday/readme/CONTRIBUTORS.md b/calendar_public_holiday/readme/CONTRIBUTORS.md new file mode 100644 index 00000000..d9381e9b --- /dev/null +++ b/calendar_public_holiday/readme/CONTRIBUTORS.md @@ -0,0 +1,3 @@ +- \[Trobz\](): + + - Do Anh Duy \<\<\>\> diff --git a/calendar_public_holiday/readme/CREDITS.md b/calendar_public_holiday/readme/CREDITS.md new file mode 100644 index 00000000..35e239a0 --- /dev/null +++ b/calendar_public_holiday/readme/CREDITS.md @@ -0,0 +1 @@ +The creation of this module was financially supported by Camptocamp diff --git a/calendar_public_holiday/readme/DESCRIPTION.md b/calendar_public_holiday/readme/DESCRIPTION.md new file mode 100644 index 00000000..2a7afcc9 --- /dev/null +++ b/calendar_public_holiday/readme/DESCRIPTION.md @@ -0,0 +1 @@ +This module handles public holidays. diff --git a/calendar_public_holiday/readme/USAGE.md b/calendar_public_holiday/readme/USAGE.md new file mode 100644 index 00000000..185826a2 --- /dev/null +++ b/calendar_public_holiday/readme/USAGE.md @@ -0,0 +1,4 @@ +For adding public holidays: + +1. Go to the menu *Calendar \> Public Holidays \> Public Holidays*. +2. Create your public holidays. diff --git a/calendar_public_holiday/security/ir.model.access.csv b/calendar_public_holiday/security/ir.model.access.csv new file mode 100644 index 00000000..26d7f805 --- /dev/null +++ b/calendar_public_holiday/security/ir.model.access.csv @@ -0,0 +1,6 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_calendar_public_holiday_user,access_calendar_public_holiday,model_calendar_public_holiday,base.group_user,1,0,0,0 +access_calendar_public_holiday_manager,access_calendar_public_holiday,model_calendar_public_holiday,base.group_system,1,1,1,1 +access_calendar_public_holiday_line_user,access_calendar_public_holiday_line,model_calendar_public_holiday_line,base.group_user,1,0,0,0 +access_calendar_public_holiday_line_manager,access_calendar_public_holiday_line,model_calendar_public_holiday_line,base.group_system,1,1,1,1 +access_calendar_public_holiday_manager_next_year,access_calendar_public_holiday_next_year,model_calendar_public_holiday_next_year,base.group_system,1,1,1,1 diff --git a/calendar_public_holiday/static/description/icon.png b/calendar_public_holiday/static/description/icon.png new file mode 100644 index 00000000..3a0328b5 Binary files /dev/null and b/calendar_public_holiday/static/description/icon.png differ diff --git a/calendar_public_holiday/static/description/index.html b/calendar_public_holiday/static/description/index.html new file mode 100644 index 00000000..3a4e6108 --- /dev/null +++ b/calendar_public_holiday/static/description/index.html @@ -0,0 +1,451 @@ + + + + + +README.rst + + + +
+ + + +Odoo Community Association + +
+

Calendar Holidays Public

+ +

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

+

This module handles public holidays.

+

Table of contents

+ +
+

Usage

+

For adding public holidays:

+
    +
  1. Go to the menu Calendar > Public Holidays > Public Holidays.
  2. +
  3. Create your public holidays.
  4. +
+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • Michael Telahun Makonnen
  • +
  • Tecnativa
  • +
  • Fekete Mihai (Forest and Biomass Services Romania)
  • +
  • Druidoo
  • +
  • Camptocamp
  • +
  • +
+
+
+

Contributors

+ +
+
+

Other credits

+

The creation of this module was financially supported by Camptocamp

+
+
+

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

+

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

+
+
+
+
+ + diff --git a/calendar_public_holiday/tests/__init__.py b/calendar_public_holiday/tests/__init__.py new file mode 100644 index 00000000..e052af02 --- /dev/null +++ b/calendar_public_holiday/tests/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from . import test_calendar_public_holiday diff --git a/calendar_public_holiday/tests/test_calendar_public_holiday.py b/calendar_public_holiday/tests/test_calendar_public_holiday.py new file mode 100644 index 00000000..0bd83ffb --- /dev/null +++ b/calendar_public_holiday/tests/test_calendar_public_holiday.py @@ -0,0 +1,249 @@ +# Copyright 2015 iDT LABS (http://www.@idtlabs.sl) +# Copyright 2017-2018 Tecnativa - Pedro M. Baeza +# Copyright 2018 Brainbean Apps +# Copyright 2020 InitOS Gmbh +# Copyright 2024 Camptocamp +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from datetime import date + +from odoo.exceptions import UserError, ValidationError + +from odoo.addons.base.tests.common import BaseCommon + + +class TestCalendarPublicHoliday(BaseCommon): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.holiday_model = cls.env["calendar.public.holiday"] + cls.holiday_line_model = cls.env["calendar.public.holiday.line"] + cls.calendar_event = cls.env["calendar.event"] + cls.wizard_next_year = cls.env["calendar.public.holiday.next.year"] + + # Remove possibly existing public holidays that would interfer. + cls.holiday_line_model.search([]).unlink() + cls.holiday_model.search([]).unlink() + cls.calendar_event.search([]).unlink() + + cls.country_1 = cls.env["res.country"].create( + { + "name": "Country 1", + "code": "XX", + } + ) + cls.country_2 = cls.env["res.country"].create( + { + "name": "Country 2", + "code": "YY", + } + ) + cls.country_3 = cls.env["res.country"].create( + { + "name": "Country 3", + "code": "ZZ", + } + ) + cls.res_partner = cls.env["res.partner"].create( + {"name": "Partner 1", "country_id": cls.country_1.id} + ) + cls.holiday_1 = cls.holiday_model.create( + { + "year": 2024, + "country_id": cls.country_1.id, + "line_ids": [ + ( + 0, + 0, + { + "name": "Christmas Day for Country 1", + "date": "2024-12-25", + }, + ) + ], + } + ) + cls.holiday_2 = cls.holiday_model.create( + { + "year": 2024, + "country_id": cls.country_2.id, + "line_ids": [ + ( + 0, + 0, + { + "name": "Christmas Day for Country 2", + "date": "2024-12-25", + }, + ) + ], + } + ) + cls.holiday_3 = cls.holiday_model.create({"year": 2025}) + ls_dates = ["2025-01-02", "2025-01-05", "2025-01-07"] + for i in range(len(ls_dates)): + cls.holiday_line_model.create( + { + "name": f"Public Holiday Line {i + 1}", + "date": ls_dates[i], + "public_holiday_id": cls.holiday_3.id, + } + ) + + def test_display_name(self): + holiday_1_display_name = self.holiday_1.display_name + expect_display_name = ( + f"{self.holiday_1.year} ({self.holiday_1.country_id.name})" + ) + self.assertEqual(holiday_1_display_name, expect_display_name) + + # without country + holiday_3_display_name = self.holiday_3.display_name + expect_display_name = f"{self.holiday_3.year}" + self.assertEqual(holiday_3_display_name, expect_display_name) + + def test_duplicate_year_country_fail(self): + # ensures that duplicate year cannot be created for the same country + with self.assertRaises(ValidationError): + # same year with country = False + self.holiday_model.create({"year": 2025}) + with self.assertRaises(ValidationError): + # same country with holiday_1 + self.holiday_model.create({"year": 2024, "country_id": self.country_1.id}) + + def test_duplicate_date_state_fail(self): + # ensures that duplicate date cannot be created for the same country + # state or with state null + holiday_4 = self.holiday_model.create( + {"year": 2024, "country_id": self.country_3.id} + ) + holiday_4_line = self.holiday_line_model.create( + { + "name": "holiday x", + "date": "2024-12-25", + "public_holiday_id": holiday_4.id, + } + ) + with self.assertRaises(ValidationError): + self.holiday_line_model.create( + { + "name": "holiday x", + "date": "2024-12-25", + "public_holiday_id": holiday_4.id, + } + ) + holiday_4_line.state_ids = [(6, 0, [self.country_3.id])] + with self.assertRaises(ValidationError): + self.holiday_line_model.create( + { + "name": "holiday x", + "date": "2024-12-25", + "public_holiday_id": holiday_4.id, + "state_ids": [(6, 0, [self.country_3.id])], + } + ) + + def test_holiday_in_country(self): + # ensures that correct holidays are identified for a country + self.assertTrue( + self.holiday_model.is_public_holiday( + date(2024, 12, 25), partner_id=self.res_partner.id + ) + ) + self.assertFalse( + self.holiday_model.is_public_holiday( + date(2024, 12, 23), partner_id=self.res_partner.id + ) + ) + + def test_holiday_line_same_year_with_parent(self): + # ensures that line year and holiday year are the same + with self.assertRaises(ValidationError): + self.holiday_model.create( + { + "year": 2026, + "line_ids": [ + ( + 0, + 0, + { + "name": "Line with not the same year", + "date": "2027-12-25", + }, + ) + ], + } + ) + + def test_list_holidays_in_list_country_specific(self): + # ensures that correct holidays are identified for a country + lines = self.holiday_model.get_holidays_list( + 2024, partner_id=self.res_partner.id + ) + res = lines.filtered(lambda r: r.date == date(2024, 12, 25)) + self.assertEqual(len(res), 1) + self.assertEqual(len(lines), 1) + + def test_list_holidays_in_list(self): + # ensures that correct holidays are identified for a country + lines = self.holiday_model.get_holidays_list(2025) + res = lines.filtered(lambda r: r.date == date(2025, 1, 2)) + self.assertEqual(len(res), 1) + self.assertEqual(len(lines), 3) + + def test_create_year_2026_public_holidays(self): + # holiday_1 and holiday_2 have the same line in 2024 but different country + ph_start_ids = self.holiday_model.search([("year", "=", 2024)]) + vals = {"public_holiday_ids": ph_start_ids, "year": 2026} + wizard = self.wizard_next_year.new(values=vals) + wizard.create_public_holidays() + lines = self.holiday_model.get_holidays_list(2026) + self.assertEqual(len(lines), 2) + res = lines.filtered( + lambda r: r.public_holiday_id.country_id.id == self.country_1.id + ) + self.assertEqual(len(res), 1) + + def test_create_year_2027_public_holidays(self): + # holiday_3 have 3 line in year 2025 + ph_start_ids = self.holiday_model.search([("year", "=", 2025)]) + wizard = self.wizard_next_year.new( + values={ + "public_holiday_ids": ph_start_ids, + "year": 2027, + } + ) + wizard.create_public_holidays() + lines = self.holiday_model.get_holidays_list(2027) + self.assertEqual(len(lines), 3) + + def test_february_29th(self): + # Ensures that users get a UserError (not a nasty Exception) when + # trying to create public holidays from year including 29th of + # February + holiday_tw_2024 = self.holiday_model.create( + {"year": 2024, "country_id": self.country_3.id} + ) + self.holiday_line_model.create( + { + "name": "Peace Memorial Holiday", + "date": "2024-02-29", + "public_holiday_id": holiday_tw_2024.id, + } + ) + vals = {"public_holiday_ids": holiday_tw_2024} + wz_create_ph = self.wizard_next_year.new(values=vals) + + with self.assertRaises(UserError): + wz_create_ph.create_public_holidays() + + def test_calendar_event_created(self): + holiday_1_line = self.holiday_1.line_ids[0] + meeting_id = holiday_1_line.meeting_id + self.assertTrue(meeting_id) + holiday_1_line.unlink() + self.assertFalse(meeting_id.exists()) + all_lines = self.holiday_line_model.search([]) + categ_id = self.env.ref("calendar_public_holiday.event_type_holiday", False) + all_meetings = self.calendar_event.search([("categ_ids", "in", categ_id.id)]) + self.assertEqual(len(all_lines), len(all_meetings)) diff --git a/calendar_public_holiday/views/calendar_public_holiday_view.xml b/calendar_public_holiday/views/calendar_public_holiday_view.xml new file mode 100644 index 00000000..b6186c50 --- /dev/null +++ b/calendar_public_holiday/views/calendar_public_holiday_view.xml @@ -0,0 +1,66 @@ + + + + + calendar.public.holiday.list + calendar.public.holiday + + + + + + + + + calendar.public.holiday.form + calendar.public.holiday + +
+ + + + + + + + + + + + + + + + + + + +
+
+ + Public Holidays + calendar.public.holiday + list,form + + + +
diff --git a/calendar_public_holiday/wizards/__init__.py b/calendar_public_holiday/wizards/__init__.py new file mode 100644 index 00000000..5c75b1aa --- /dev/null +++ b/calendar_public_holiday/wizards/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from . import calendar_public_holiday_next_year_wizard diff --git a/calendar_public_holiday/wizards/calendar_public_holiday_next_year_wizard.py b/calendar_public_holiday/wizards/calendar_public_holiday_next_year_wizard.py new file mode 100644 index 00000000..e701a32d --- /dev/null +++ b/calendar_public_holiday/wizards/calendar_public_holiday_next_year_wizard.py @@ -0,0 +1,83 @@ +# Copyright 2016 Trobz +# Copyright 2024 Camptocamp +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +import logging + +from odoo import fields, models +from odoo.exceptions import UserError + +_logger = logging.getLogger(__name__) + + +class CalendarPublicHolidayNextYear(models.TransientModel): + _name = "calendar.public.holiday.next.year" + _description = "Create Public Holiday From Existing Ones" + + public_holiday_ids = fields.Many2many( + comodel_name="calendar.public.holiday", + string="Templates", + help="Select the public holidays to use as template. " + "If not set, latest public holidays of each country will be used. " + "Only the last templates of each country for each year will " + "be taken into account (If you select templates from 2012 and 2015, " + "only the templates from 2015 will be taken into account.", + ) + year = fields.Integer( + help="Year for which you want to create the public holidays. " + "By default, the year following the template." + ) + + def create_public_holidays(self): + self.ensure_one() + last_ph_dict = {} + ph_env = self.env["calendar.public.holiday"] + # Avoid empty-domain search without limit for performance (lint rule W8163) + pholidays = self.public_holiday_ids or ph_env.search([("id", "!=", 0)]) + if not pholidays: + raise UserError( + self.env._( + "No Public Holidays found as template. " + "Please create the first Public Holidays manually." + ) + ) + for ph in pholidays: + last_ph_country = last_ph_dict.get(ph.country_id, False) + if last_ph_country: + if last_ph_country.year < ph.year: + last_ph_dict[ph.country_id] = ph + else: + last_ph_dict[ph.country_id] = ph + new_ph_ids = [] + for last_ph in last_ph_dict.values(): + new_year = self.year or last_ph.year + 1 + new_ph_vals = {"year": new_year} + new_ph = last_ph.copy(new_ph_vals) + new_ph_ids.append(new_ph.id) + for last_ph_line in last_ph.line_ids: + feb_29 = last_ph_line.date.month == 2 and last_ph_line.date.day == 29 + if feb_29: + # Handling this rare case would mean quite a lot of + # complexity because previous or next day might also be a + # public holiday. + raise UserError( + self.env._( + "You cannot use as template the public holidays " + "of a year that " + "includes public holidays on 29th of February " + "(2016, 2020...), please select a template from " + "another year." + ) + ) + new_date = last_ph_line.date.replace(year=new_year) + new_ph_line_vals = {"date": new_date, "public_holiday_id": new_ph.id} + last_ph_line.copy(new_ph_line_vals) + domain = [["id", "in", new_ph_ids]] + action = { + "type": "ir.actions.act_window", + "name": self.env._("New public holidays"), + "view_mode": "list,form", + "res_model": ph_env._name, + "domain": domain, + } + return action diff --git a/calendar_public_holiday/wizards/calendar_public_holiday_next_year_wizard.xml b/calendar_public_holiday/wizards/calendar_public_holiday_next_year_wizard.xml new file mode 100644 index 00000000..6c11ebed --- /dev/null +++ b/calendar_public_holiday/wizards/calendar_public_holiday_next_year_wizard.xml @@ -0,0 +1,71 @@ + + + + + Create Next Year Public Holidays + calendar.public.holiday.next.year + +
+ +
+ Use this wizard to create public holidays based on the + existing ones.
+ Only the last templates of each country + will be taken into account (If you select templates + from 2012 and 2015 of the same country; ' + only the templates from 2015 will be taken into + account). +
+ + +
+ By default, the most recent public holidays + for each country are used as template to create + public holidays for the year following the templates. +

+ Normally, you should not need to input anything in + optional fields and only need to click on the button + "Create". +
+
+ +
+ The below optional fields are here only to handle + special situations like "2011 was a special year with + an additional public holiday for the 150th + anniversary of the Italian unification, so you want to + replicate the 2010 Italian holidays to 2012." +
+ + + + +
+
+
+
+
+
+
+
+ + Create Next Year Public Holidays + calendar.public.holiday.next.year + form + new + + +
diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..180fc497 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +# generated from manifests external_dependencies +openupgradelib