diff --git a/project_characterization/README.rst b/project_characterization/README.rst new file mode 100644 index 00000000..f0d48399 --- /dev/null +++ b/project_characterization/README.rst @@ -0,0 +1,36 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +======================== +Project characterization +======================== + +With this module you can characterize a project or an analytic account with: + +* Area +* Team +* Character +* Espace +* Target +* and more... + +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 smash it by providing detailed and welcomed feedback. + +Credits +======= + +Contributors +------------ +* Maite Esnal +* Ana Juaristi +* Xanti Pablo +* Oihane Crucelaegui + +Do not contact contributors directly about support or help with technical issues. diff --git a/project_characterization/__init__.py b/project_characterization/__init__.py new file mode 100644 index 00000000..0f76fd80 --- /dev/null +++ b/project_characterization/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2018 Maite Esnal - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from . import models diff --git a/project_characterization/__manifest__.py b/project_characterization/__manifest__.py new file mode 100644 index 00000000..9b5f2489 --- /dev/null +++ b/project_characterization/__manifest__.py @@ -0,0 +1,28 @@ +# Copyright 2018 Maite Esnal - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +{ + "name": "Project Characterization", + "version": "11.0.6.0.0", + "license": "AGPL-3", + "depends": [ + "project", + "account", + "base_characterization", + "project_funding", + "hr_timesheet", + ], + "author": "AvanzOSC", + "website": "http://www.avanzosc.es", + "category": "Project", + "data": [ + "security/ir.model.access.csv", + "views/account_analytic_view.xml", + "views/project_project_view.xml", + "views/project_task_view.xml", + "views/project_characterization_view.xml", + "views/res_area_view.xml", + "views/res_config_settings_view.xml", + ], + "installable": True, +} diff --git a/project_characterization/i18n/es.po b/project_characterization/i18n/es.po new file mode 100644 index 00000000..7fdec994 --- /dev/null +++ b/project_characterization/i18n/es.po @@ -0,0 +1,300 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * project_characterization +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-04-05 13:49+0000\n" +"PO-Revision-Date: 2023-04-05 13:49+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: project_characterization +#: model:ir.ui.menu,name:project_characterization.res_activity_menu +msgid "Activity" +msgstr "Actividad" + +#. module: project_characterization +#: model:ir.ui.menu,name:project_characterization.res_activity_type_menu +msgid "Activity Type" +msgstr "Tipo de actividad" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_res_config_settings__manual_code +msgid "Add number manually to compose account code" +msgstr "Agregue el número manualmente para redactar el código de cuenta" + +#. module: project_characterization +#: model:ir.model,name:project_characterization.model_account_analytic_account +msgid "Analytic Account" +msgstr "Cuenta analítica" + +#. module: project_characterization +#: model:ir.model,name:project_characterization.model_account_analytic_line +msgid "Analytic Line" +msgstr "Línea Analítica" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_account_analytic_account__res_area_id +#: model:ir.model.fields,field_description:project_characterization.field_project_project__res_area_id +#: model:ir.ui.menu,name:project_characterization.res_area_menu +#: model_terms:ir.ui.view,arch_db:project_characterization.project_project_view_search +msgid "Area" +msgstr "Área" + +#. module: project_characterization +#: model:ir.ui.menu,name:project_characterization.res_area_specialization_menu +msgid "Area Specialization" +msgstr "Área de especialización" + +#. module: project_characterization +#: model:ir.ui.menu,name:project_characterization.res_area_type_menu +msgid "Area Type" +msgstr "Tipo de proyecto" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_account_analytic_account__res_area_type_id +#: model:ir.model.fields,field_description:project_characterization.field_project_project__res_area_type_id +#: model_terms:ir.ui.view,arch_db:project_characterization.project_project_view_search +msgid "Area type" +msgstr "Tipo de área" + +#. module: project_characterization +#: model:ir.model,name:project_characterization.model_res_area_type +msgid "Area types" +msgstr "Tipos" + +#. module: project_characterization +#: model:ir.model,name:project_characterization.model_res_area +#: model_terms:ir.ui.view,arch_db:project_characterization.view_account_analytic_account_search_inh_project_char +msgid "Areas" +msgstr "Áreas" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_account_analytic_account__res_character_id +#: model:ir.model.fields,field_description:project_characterization.field_project_project__res_character_id +#: model:ir.ui.menu,name:project_characterization.res_character_menu +#: model_terms:ir.ui.view,arch_db:project_characterization.project_project_view_search +msgid "Character" +msgstr "Naturaleza" + +#. module: project_characterization +#: model:ir.ui.menu,name:project_characterization.project_characterization_config_menu +#: model_terms:ir.ui.view,arch_db:project_characterization.project_project_view_form +msgid "Characterization" +msgstr "Caracterización" + +#. module: project_characterization +#: model_terms:ir.ui.view,arch_db:project_characterization.view_account_analytic_account_search_inh_project_char +msgid "Characters" +msgstr "Naturaleza" + +#. module: project_characterization +#: model:ir.ui.menu,name:project_characterization.res_committee_menu +msgid "Committee" +msgstr "Comité" + +#. module: project_characterization +#: model:ir.model,name:project_characterization.model_res_config_settings +msgid "Config Settings" +msgstr "Opciones de Configuración" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_project_task_type2__create_uid +msgid "Created by" +msgstr "Creado por" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_project_task_type2__create_date +msgid "Created on" +msgstr "Creado el" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_project_task_type2__description +msgid "Description" +msgstr "Descripción" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_project_task_type2__display_name +msgid "Display Name" +msgstr "Nombre mostrado" + +#. module: project_characterization +#: model_terms:ir.ui.view,arch_db:project_characterization.project_project_view_form +#: model_terms:ir.ui.view,arch_db:project_characterization.project_project_view_search +#: model_terms:ir.ui.view,arch_db:project_characterization.project_project_view_tree +msgid "End Date" +msgstr "Fecha finalización" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_project_project__funding_ids +msgid "Funding Sources" +msgstr "Programas de financiación" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_project_task_type2__id +msgid "ID" +msgstr "" + +#. module: project_characterization +#: model_terms:ir.ui.view,arch_db:project_characterization.project_project_view_form +msgid "Initial Date" +msgstr "Fecha inicial" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_account_analytic_account__justification_deadline +#: model:ir.model.fields,field_description:project_characterization.field_project_project__justification_deadline +msgid "Justification Deadline" +msgstr "Plazo de justificación" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_project_task_type2____last_update +msgid "Last Modified on" +msgstr "Última modificación en" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_project_task_type2__write_uid +msgid "Last Updated by" +msgstr "Última actualización por" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_project_task_type2__write_date +msgid "Last Updated on" +msgstr "Última actualización el" + +#. module: project_characterization +#: model_terms:ir.ui.view,arch_db:project_characterization.project_config_settings_view_form +msgid "Manual Code for Analytic Accounts" +msgstr "Código manual para cuentas analíticas" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_project_task_type2__name +msgid "Name" +msgstr "Nombre" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_account_analytic_account__nonoperative +#: model:ir.model.fields,field_description:project_characterization.field_account_analytic_line__nonoperative +#: model:ir.model.fields,field_description:project_characterization.field_project_project__nonoperative +#: model:ir.model.fields,field_description:project_characterization.field_res_area__nonoperative +#: model_terms:ir.ui.view,arch_db:project_characterization.account_analytic_line_view_search +#: model_terms:ir.ui.view,arch_db:project_characterization.project_project_view_search +#: model_terms:ir.ui.view,arch_db:project_characterization.res_area_operative_view_search +#: model_terms:ir.ui.view,arch_db:project_characterization.view_account_analytic_account_search_inh_project_char +msgid "Non Operative" +msgstr "No operativo" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_account_analytic_account__num_code +#: model:ir.model.fields,field_description:project_characterization.field_project_project__num_code +msgid "Number" +msgstr "Número" + +#. module: project_characterization +#: model_terms:ir.ui.view,arch_db:project_characterization.account_analytic_line_view_search +#: model_terms:ir.ui.view,arch_db:project_characterization.project_project_view_search +#: model_terms:ir.ui.view,arch_db:project_characterization.res_area_operative_view_search +#: model_terms:ir.ui.view,arch_db:project_characterization.view_account_analytic_account_search_inh_project_char +msgid "Operative" +msgstr "Operativo" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_account_analytic_account__op_space_id +#: model:ir.model.fields,field_description:project_characterization.field_project_project__op_space_id +#: model_terms:ir.ui.view,arch_db:project_characterization.project_project_view_search +msgid "Opportunity Space" +msgstr "Espacio de oportunidad" + +#. module: project_characterization +#: model:ir.ui.menu,name:project_characterization.res_opportunity_space_menu +#: model_terms:ir.ui.view,arch_db:project_characterization.view_account_analytic_account_search_inh_project_char +msgid "Opportunity Spaces" +msgstr "Espacios de oportunidad" + +#. module: project_characterization +#: model_terms:ir.ui.view,arch_db:project_characterization.project_task_view_form +msgid "Period" +msgstr "Período" + +#. module: project_characterization +#: model:ir.model,name:project_characterization.model_project_project +msgid "Project" +msgstr "Proyecto" + +#. module: project_characterization +#: model_terms:ir.ui.view,arch_db:project_characterization.project_task_type2_view_form +msgid "Project Task Type" +msgstr "" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_res_area_type__project_ids +msgid "Projects" +msgstr "Proyectos" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_res_area__related_operative_area_ids +msgid "Related Operative Area" +msgstr "Área Operativa Relacionada" + +#. module: project_characterization +#: model_terms:ir.ui.view,arch_db:project_characterization.project_config_settings_view_form +msgid "Select number to compose analytic account code" +msgstr "Seleccione el número para componer el código de la cuenta analítica" + +#. module: project_characterization +#: model:ir.ui.menu,name:project_characterization.res_structure_menu +msgid "Structures" +msgstr "Estructuras" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_account_analytic_account__res_target_id +#: model:ir.model.fields,field_description:project_characterization.field_project_project__res_target_id +#: model:ir.ui.menu,name:project_characterization.res_target_menu +#: model_terms:ir.ui.view,arch_db:project_characterization.project_project_view_search +msgid "Target" +msgstr "Sector Objetivo" + +#. module: project_characterization +#: model_terms:ir.ui.view,arch_db:project_characterization.view_account_analytic_account_search_inh_project_char +msgid "Targets" +msgstr "Objetivos" + +#. module: project_characterization +#: model:ir.model,name:project_characterization.model_project_task +msgid "Task" +msgstr "Tarea" + +#. module: project_characterization +#: model:ir.model,name:project_characterization.model_project_task_type2 +msgid "Task Type" +msgstr "Tipo de tarea" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_account_analytic_account__res_team_id +#: model:ir.model.fields,field_description:project_characterization.field_project_project__res_team_id +#: model:ir.ui.menu,name:project_characterization.res_team_menu +#: model_terms:ir.ui.view,arch_db:project_characterization.project_project_view_search +msgid "Team" +msgstr "Equipo" + +#. module: project_characterization +#: model_terms:ir.ui.view,arch_db:project_characterization.view_account_analytic_account_search_inh_project_char +msgid "Teams" +msgstr "Equipos" + +#. module: project_characterization +#: model:ir.model.fields,help:project_characterization.field_res_config_settings__manual_code +msgid "This will disable automatic number adding to create analytic account code in projects." +msgstr "Esto deshabilitará la adición automática de números para crear un código de cuenta analítico en los proyectos." + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_project_task__type2_id +msgid "Type" +msgstr "Tipo" + diff --git a/project_characterization/i18n/eu_ES.po b/project_characterization/i18n/eu_ES.po new file mode 100644 index 00000000..44c3d1d3 --- /dev/null +++ b/project_characterization/i18n/eu_ES.po @@ -0,0 +1,300 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * project_characterization +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-04-03 14:12+0000\n" +"PO-Revision-Date: 2023-04-03 14:12+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: project_characterization +#: model:ir.ui.menu,name:project_characterization.res_activity_menu +msgid "Activity" +msgstr "Jarduera" + +#. module: project_characterization +#: model:ir.ui.menu,name:project_characterization.res_activity_type_menu +msgid "Activity Type" +msgstr "Jarduera-mota" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_res_config_settings__manual_code +msgid "Add number manually to compose account code" +msgstr "Kontu-koderako zenbakia eskuz gehitzea" + +#. module: project_characterization +#: model:ir.model,name:project_characterization.model_account_analytic_account +msgid "Analytic Account" +msgstr "Kontu analitikoa" + +#. module: project_characterization +#: model:ir.model,name:project_characterization.model_account_analytic_line +msgid "Analytic Line" +msgstr "Lerro analitikoa" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_account_analytic_account__res_area_id +#: model:ir.model.fields,field_description:project_characterization.field_project_project__res_area_id +#: model:ir.ui.menu,name:project_characterization.res_area_menu +#: model_terms:ir.ui.view,arch_db:project_characterization.project_project_view_search +msgid "Area" +msgstr "Arloa" + +#. module: project_characterization +#: model:ir.ui.menu,name:project_characterization.res_area_specialization_menu +msgid "Area Specialization" +msgstr "Espezializazio arloa" + +#. module: project_characterization +#: model:ir.ui.menu,name:project_characterization.res_area_type_menu +msgid "Area Type" +msgstr "Arlo-mota" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_account_analytic_account__res_area_type_id +#: model:ir.model.fields,field_description:project_characterization.field_project_project__res_area_type_id +#: model_terms:ir.ui.view,arch_db:project_characterization.project_project_view_search +msgid "Area type" +msgstr "Arlo-mota" + +#. module: project_characterization +#: model:ir.model,name:project_characterization.model_res_area_type +msgid "Area types" +msgstr "Arlo-motak" + +#. module: project_characterization +#: model:ir.model,name:project_characterization.model_res_area +#: model_terms:ir.ui.view,arch_db:project_characterization.view_account_analytic_account_search_inh_project_char +msgid "Areas" +msgstr "Arloak" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_account_analytic_account__res_character_id +#: model:ir.model.fields,field_description:project_characterization.field_project_project__res_character_id +#: model:ir.ui.menu,name:project_characterization.res_character_menu +#: model_terms:ir.ui.view,arch_db:project_characterization.project_project_view_search +msgid "Character" +msgstr "Natura" + +#. module: project_characterization +#: model:ir.ui.menu,name:project_characterization.project_characterization_config_menu +#: model_terms:ir.ui.view,arch_db:project_characterization.project_project_view_form +msgid "Characterization" +msgstr "Karakterizazioa" + +#. module: project_characterization +#: model_terms:ir.ui.view,arch_db:project_characterization.view_account_analytic_account_search_inh_project_char +msgid "Characters" +msgstr "Natura" + +#. module: project_characterization +#: model:ir.ui.menu,name:project_characterization.res_committee_menu +msgid "Committee" +msgstr "Batzordea" + +#. module: project_characterization +#: model:ir.model,name:project_characterization.model_res_config_settings +msgid "Config Settings" +msgstr "Konfigurazio ezarpenak" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_project_task_type2__create_uid +msgid "Created by" +msgstr "Nork sortua" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_project_task_type2__create_date +msgid "Created on" +msgstr "Noiz sortua" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_project_task_type2__description +msgid "Description" +msgstr "Deskribapena" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_project_task_type2__display_name +msgid "Display Name" +msgstr "Izena erakutsi" + +#. module: project_characterization +#: model_terms:ir.ui.view,arch_db:project_characterization.project_project_view_form +#: model_terms:ir.ui.view,arch_db:project_characterization.project_project_view_search +#: model_terms:ir.ui.view,arch_db:project_characterization.project_project_view_tree +msgid "End Date" +msgstr "Amaiera Data" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_project_project__funding_ids +msgid "Funding Sources" +msgstr "Finantziazio iturriak" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_project_task_type2__id +msgid "ID" +msgstr "" + +#. module: project_characterization +#: model_terms:ir.ui.view,arch_db:project_characterization.project_project_view_form +msgid "Initial Date" +msgstr "Hasiera data" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_account_analytic_account__justification_deadline +#: model:ir.model.fields,field_description:project_characterization.field_project_project__justification_deadline +msgid "Justification Deadline" +msgstr "Azken egunaren justifikazioa" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_project_task_type2____last_update +msgid "Last Modified on" +msgstr "Azken aldaketa" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_project_task_type2__write_uid +msgid "Last Updated by" +msgstr "Azkenengoz eguneratu zuena" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_project_task_type2__write_date +msgid "Last Updated on" +msgstr "Azken eguneraketa noiz" + +#. module: project_characterization +#: model_terms:ir.ui.view,arch_db:project_characterization.project_config_settings_view_form +msgid "Manual Code for Analytic Accounts" +msgstr "Kontu analitikorako eskuzko kodea" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_project_task_type2__name +msgid "Name" +msgstr "Izena" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_account_analytic_account__nonoperative +#: model:ir.model.fields,field_description:project_characterization.field_account_analytic_line__nonoperative +#: model:ir.model.fields,field_description:project_characterization.field_project_project__nonoperative +#: model:ir.model.fields,field_description:project_characterization.field_res_area__nonoperative +#: model_terms:ir.ui.view,arch_db:project_characterization.account_analytic_line_view_search +#: model_terms:ir.ui.view,arch_db:project_characterization.project_project_view_search +#: model_terms:ir.ui.view,arch_db:project_characterization.res_area_operative_view_search +#: model_terms:ir.ui.view,arch_db:project_characterization.view_account_analytic_account_search_inh_project_char +msgid "Non Operative" +msgstr "Ez dabil" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_account_analytic_account__num_code +#: model:ir.model.fields,field_description:project_characterization.field_project_project__num_code +msgid "Number" +msgstr "Zenbakia " + +#. module: project_characterization +#: model_terms:ir.ui.view,arch_db:project_characterization.account_analytic_line_view_search +#: model_terms:ir.ui.view,arch_db:project_characterization.project_project_view_search +#: model_terms:ir.ui.view,arch_db:project_characterization.res_area_operative_view_search +#: model_terms:ir.ui.view,arch_db:project_characterization.view_account_analytic_account_search_inh_project_char +msgid "Operative" +msgstr "Operatiboa" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_account_analytic_account__op_space_id +#: model:ir.model.fields,field_description:project_characterization.field_project_project__op_space_id +#: model_terms:ir.ui.view,arch_db:project_characterization.project_project_view_search +msgid "Opportunity Space" +msgstr "Aukerako espazioa" + +#. module: project_characterization +#: model:ir.ui.menu,name:project_characterization.res_opportunity_space_menu +#: model_terms:ir.ui.view,arch_db:project_characterization.view_account_analytic_account_search_inh_project_char +msgid "Opportunity Spaces" +msgstr "Aukerako espazioak" + +#. module: project_characterization +#: model_terms:ir.ui.view,arch_db:project_characterization.project_task_view_form +msgid "Period" +msgstr "Aldiak" + +#. module: project_characterization +#: model:ir.model,name:project_characterization.model_project_project +msgid "Project" +msgstr "Proiektua" + +#. module: project_characterization +#: model_terms:ir.ui.view,arch_db:project_characterization.project_task_type2_view_form +msgid "Project Task Type" +msgstr "Proiektuko ataza motak" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_res_area_type__project_ids +msgid "Projects" +msgstr "Proiektuak " + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_res_area__related_operative_area_ids +msgid "Related Operative Area" +msgstr "Arlo operatiboak" + +#. module: project_characterization +#: model_terms:ir.ui.view,arch_db:project_characterization.project_config_settings_view_form +msgid "Select number to compose analytic account code" +msgstr "Hautatu zenbaki bat kontu analitikoaren kodea lortzeko" + +#. module: project_characterization +#: model:ir.ui.menu,name:project_characterization.res_structure_menu +msgid "Structures" +msgstr "Egiturak" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_account_analytic_account__res_target_id +#: model:ir.model.fields,field_description:project_characterization.field_project_project__res_target_id +#: model:ir.ui.menu,name:project_characterization.res_target_menu +#: model_terms:ir.ui.view,arch_db:project_characterization.project_project_view_search +msgid "Target" +msgstr "Sektore objektiboa" + +#. module: project_characterization +#: model_terms:ir.ui.view,arch_db:project_characterization.view_account_analytic_account_search_inh_project_char +msgid "Targets" +msgstr "Sektore objektiboak" + +#. module: project_characterization +#: model:ir.model,name:project_characterization.model_project_task +msgid "Task" +msgstr "Zeregina" + +#. module: project_characterization +#: model:ir.model,name:project_characterization.model_project_task_type2 +msgid "Task Type" +msgstr "Ataza mota" + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_account_analytic_account__res_team_id +#: model:ir.model.fields,field_description:project_characterization.field_project_project__res_team_id +#: model:ir.ui.menu,name:project_characterization.res_team_menu +#: model_terms:ir.ui.view,arch_db:project_characterization.project_project_view_search +msgid "Team" +msgstr "Taldea" + +#. module: project_characterization +#: model_terms:ir.ui.view,arch_db:project_characterization.view_account_analytic_account_search_inh_project_char +msgid "Teams" +msgstr "Taldeak" + +#. module: project_characterization +#: model:ir.model.fields,help:project_characterization.field_res_config_settings__manual_code +msgid "This will disable automatic number adding to create analytic account code in projects." +msgstr "Honek zenbakien gehiketa automatikoa desgaituko du proiektuetan kontu analitikoa sortzeko." + +#. module: project_characterization +#: model:ir.model.fields,field_description:project_characterization.field_project_task__type2_id +msgid "Type" +msgstr "Mota" + diff --git a/project_characterization/models/__init__.py b/project_characterization/models/__init__.py new file mode 100644 index 00000000..ddb7a4c3 --- /dev/null +++ b/project_characterization/models/__init__.py @@ -0,0 +1,7 @@ +# Copyright 2018 Maite Esnal - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from . import account_analytic +from . import project_task +from . import project_project +from . import res_config_settings diff --git a/project_characterization/models/account_analytic.py b/project_characterization/models/account_analytic.py new file mode 100644 index 00000000..c537145b --- /dev/null +++ b/project_characterization/models/account_analytic.py @@ -0,0 +1,83 @@ +# Copyright 2018 Maite Esnal - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from odoo import api, fields, models + + +class AccountAnalyticAccount(models.Model): + _inherit = "account.analytic.account" + + res_area_id = fields.Many2one(comodel_name="res.area", string="Area") + op_space_id = fields.Many2one( + comodel_name="res.opportunity.space", string="Opportunity Space" + ) + res_character_id = fields.Many2one(comodel_name="res.character", string="Character") + justification_deadline = fields.Date(string="Justification Deadline") + res_area_type_id = fields.Many2one( + comodel_name="res.area.type", + string="Area type", + domain="[('area_ids', 'in', res_area_id)]", + ) + res_team_id = fields.Many2one(comodel_name="res.team", string="Team") + res_target_id = fields.Many2one(comodel_name="res.target", string="Target") + nonoperative = fields.Boolean( + string="Non Operative", related="res_area_id.nonoperative", store=True + ) + num_code = fields.Char(string="Number", copy=False) + + @api.onchange("res_area_id", "res_area_type_id") + def _onchange_area_type(self): + self.ensure_one() + get_param = self.env["ir.config_parameter"].sudo().get_param + manual_code = ( + get_param("project_characterization.manual_code", "False").lower() == "true" + ) + if not manual_code: + if self.res_area_id and self.res_area_type_id: + try: + count = self.search( + [ + ("res_area_id", "=", self.res_area_id.id), + ("res_area_type_id", "=", self.res_area_type_id.id), + ], + limit=1, + order="num_code DESC", + ) + count = int(count.num_code) + except Exception: + count = self.search_count( + [ + ("res_area_id", "=", self.res_area_id.id), + ("res_area_type_id", "=", self.res_area_type_id.id), + ] + ) + self.num_code = count + 1 + + @api.model + def create(self, values): + if not values.get("code"): + area_id = values.get("res_area_id") + type_id = values.get("res_area_type_id") + num_code = values.get("num_code") + if area_id and type_id: + values.update( + { + "code": "{}.{}.{}".format( + self.env["res.area"].browse(area_id).code or "", + self.env["res.area.type"].browse(type_id).code or "", + num_code or "", + ) + } + ) + return super(AccountAnalyticAccount, self).create(values) + + +class AccountAnalyticLine(models.Model): + _inherit = "account.analytic.line" + + nonoperative = fields.Boolean( + string="Non Operative", + related="account_id.nonoperative", + store=True, + compute_sudo=True, + ) diff --git a/project_characterization/models/project_project.py b/project_characterization/models/project_project.py new file mode 100644 index 00000000..9eea95c1 --- /dev/null +++ b/project_characterization/models/project_project.py @@ -0,0 +1,121 @@ +# Copyright 2018 Xanti Pablo - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from odoo import api, fields, models + + +class ProjectProject(models.Model): + _inherit = "project.project" + + funding_ids = fields.One2many( + comodel_name="funding.source.project", + inverse_name="project_id", + string="Funding Sources", + ) + res_area_id = fields.Many2one( + comodel_name="res.area", + string="Area", + related="analytic_account_id.res_area_id", + readonly=False, + store=True, + ) + op_space_id = fields.Many2one( + comodel_name="res.opportunity.space", + string="Opportunity Space", + related="analytic_account_id.op_space_id", + readonly=False, + store=True, + ) + res_character_id = fields.Many2one( + comodel_name="res.character", + string="Character", + related="analytic_account_id.res_character_id", + readonly=False, + store=True, + ) + justification_deadline = fields.Date( + string="Justification Deadline", + related="analytic_account_id.justification_deadline", + readonly=False, + ) + res_area_type_id = fields.Many2one( + comodel_name="res.area.type", + string="Area type", + related="analytic_account_id.res_area_type_id", + readonly=False, + store=True, + ) + res_team_id = fields.Many2one( + comodel_name="res.team", + string="Team", + related="analytic_account_id.res_team_id", + readonly=False, + store=True, + ) + res_target_id = fields.Many2one( + comodel_name="res.target", + string="Target", + related="analytic_account_id.res_target_id", + readonly=False, + store=True, + ) + nonoperative = fields.Boolean( + string="Non Operative", related="res_area_id.nonoperative", store=True + ) + num_code = fields.Char(string="Number", related="analytic_account_id.num_code", readonly=False,) + + @api.onchange("res_area_id") + def _onchange_area_id(self): + self.ensure_one() + self.nonoperative = self.res_area_id.nonoperative + + @api.onchange("res_area_id", "res_area_type_id") + def _onchange_area_type(self): + self.ensure_one() + get_param = self.env["ir.config_parameter"].sudo().get_param + manual_code = ( + get_param("project_characterization.manual_code", "False").lower() == "true" + ) + if not manual_code: + if self.res_area_id and self.res_area_type_id: + try: + projects = self.search( + [ + ("res_area_id", "=", self.res_area_id.id), + ("res_area_type_id", "=", self.res_area_type_id.id), + ] + ) + count = int( + sorted(projects.mapped("num_code"), key=int, reverse=True)[0] + ) + except Exception: + count = self.search_count( + [ + ("res_area_id", "=", self.res_area_id.id), + ("res_area_type_id", "=", self.res_area_type_id.id), + ] + ) + self.num_code = count + 1 + + +class ResAreaType(models.Model): + _inherit = "res.area.type" + + project_ids = fields.One2many( + comodel_name="project.project", + inverse_name="res_area_type_id", + string="Projects", + ) + + +class ResArea(models.Model): + _inherit = "res.area" + + nonoperative = fields.Boolean(string="Non Operative") + related_operative_area_ids = fields.Many2many( + comodel_name="res.area", + relation="rel_nonop2op_area", + column1="nonop_area_id", + column2="op_area_id", + domain="[('nonoperative', '=', False)]", + ) diff --git a/project_characterization/models/project_task.py b/project_characterization/models/project_task.py new file mode 100644 index 00000000..d5659843 --- /dev/null +++ b/project_characterization/models/project_task.py @@ -0,0 +1,18 @@ +# Copyright 2018 Maite Esnal - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from odoo import fields, models + + +class ProjectTask(models.Model): + _inherit = "project.task" + + type2_id = fields.Many2one(comodel_name="project.task.type2", string="Type") + + +class ProjectTaskType2(models.Model): + _name = "project.task.type2" + _description = "Task Type" + + name = fields.Char(string="Name", required=True) + description = fields.Text(string="Description") diff --git a/project_characterization/models/res_config_settings.py b/project_characterization/models/res_config_settings.py new file mode 100644 index 00000000..d6b84721 --- /dev/null +++ b/project_characterization/models/res_config_settings.py @@ -0,0 +1,35 @@ +# Copyright 2018 Oihane Crucelaegui - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from odoo import api, fields, models + + +class ProjectConfigSettings(models.TransientModel): + _inherit = "res.config.settings" + + manual_code = fields.Boolean( + string="Add number manually to compose account code", + help="This will disable automatic number adding to create analytic " + "account code in projects.", + ) + + @api.model + def get_values(self): + res = super(ProjectConfigSettings, self).get_values() + get_param = self.env["ir.config_parameter"].sudo().get_param + # the value of the parameter is a nonempty string + res.update( + manual_code=get_param( + "project_characterization.manual_code", "False" + ).lower() + == "true", + ) + return res + + @api.multi + def set_values(self): + super(ProjectConfigSettings, self).set_values() + set_param = self.env["ir.config_parameter"].sudo().set_param + # we store the repr of the values, since the value of the parameter is + # a required string + set_param("project_characterization.manual_code", repr(self.manual_code)) diff --git a/project_characterization/security/ir.model.access.csv b/project_characterization/security/ir.model.access.csv new file mode 100644 index 00000000..b5fa8c28 --- /dev/null +++ b/project_characterization/security/ir.model.access.csv @@ -0,0 +1,26 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_project_task_type2_analytic_accounting,access_project_task_type2,model_project_task_type2,analytic.group_analytic_accounting,1,1,1,1 +access_res_target_analytic_accounting,access_res_target,base_characterization.model_res_target,analytic.group_analytic_accounting,1,1,1,1 +access_res_character_analytic_accounting,access_res_character,base_characterization.model_res_character,analytic.group_analytic_accounting,1,1,1,1 +access_res_area_analytic_accounting,access_res_area,base_characterization.model_res_area,analytic.group_analytic_accounting,1,1,1,1 +access_res_area_type_analytic_accounting,access_res_area_type,base_characterization.model_res_area_type,analytic.group_analytic_accounting,1,1,1,1 +access_res_committee_analytic_accounting,access_res_committee,base_characterization.model_res_committee,analytic.group_analytic_accounting,1,1,1,1 +access_res_structure_analytic_accounting,access_res_structure,base_characterization.model_res_structure,analytic.group_analytic_accounting,1,1,1,1 +access_res_opportunity_space_analytic_accounting,access_res_opportunity_space,base_characterization.model_res_opportunity_space,analytic.group_analytic_accounting,1,1,1,1 +access_res_area_specialization_analytic_accounting,access_res_area_specialization,base_characterization.model_res_area_specialization,analytic.group_analytic_accounting,1,1,1,1 +access_res_activity_analytic_accounting,access_res_activity,base_characterization.model_res_activity,analytic.group_analytic_accounting,1,1,1,1 +access_res_activity_type_analytic_accounting,access_res_activity_type,base_characterization.model_res_activity_type,analytic.group_analytic_accounting,1,1,1,1 +access_res_team_analytic_accounting,access_res_team,base_characterization.model_res_team,analytic.group_analytic_accounting,1,1,1,1 +access_project_task_type2_project_manager,access_project_task_type2,model_project_task_type2,project.group_project_manager,1,1,1,1 +access_res_target_project_manager,access_res_target,base_characterization.model_res_target,project.group_project_manager,1,1,1,1 +access_res_character_project_manager,access_res_character,base_characterization.model_res_character,project.group_project_manager,1,1,1,1 +access_res_area_project_manager,access_res_area,base_characterization.model_res_area,project.group_project_manager,1,1,1,1 +access_res_area_type_project_manager,access_res_area_type,base_characterization.model_res_area_type,project.group_project_manager,1,1,1,1 +access_res_committee_project_manager,access_res_committee,base_characterization.model_res_committee,project.group_project_manager,1,1,1,1 +access_res_structure_project_manager,access_res_structure,base_characterization.model_res_structure,project.group_project_manager,1,1,1,1 +access_res_opportunity_space_project_manager,access_res_opportunity_space,base_characterization.model_res_opportunity_space,project.group_project_manager,1,1,1,1 +access_res_area_specialization_project_manager,access_res_area_specialization,base_characterization.model_res_area_specialization,project.group_project_manager,1,1,1,1 +access_res_activity_project_manager,access_res_activity,base_characterization.model_res_activity,project.group_project_manager,1,1,1,1 +access_res_activity_type_project_manager,access_res_activity_type,base_characterization.model_res_activity_type,project.group_project_manager,1,1,1,1 +access_res_team_project_manager,access_res_team,base_characterization.model_res_team,project.group_project_manager,1,1,1,1 +access_project_task_type2,access_project_task_type2,model_project_task_type2,,1,0,0,0 diff --git a/project_characterization/tests/__init__.py b/project_characterization/tests/__init__.py new file mode 100644 index 00000000..084b58a3 --- /dev/null +++ b/project_characterization/tests/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2018 Oihane Crucelaegui - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from . import test_project_characterization diff --git a/project_characterization/tests/test_project_characterization.py b/project_characterization/tests/test_project_characterization.py new file mode 100644 index 00000000..0971222c --- /dev/null +++ b/project_characterization/tests/test_project_characterization.py @@ -0,0 +1,190 @@ +# Copyright 2018 Oihane Crucelaegui - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from odoo.tests import common + + +class TestProjectCharacterization(common.TransactionCase): + def setUp(self): + super(TestProjectCharacterization, self).setUp() + res_partner_model = self.env["res.partner"] + self.project_model = self.env["project.project"] + self.analytic_model = self.env["account.analytic.account"].with_context( + mail_create_nosubscribe=True + ) + area_model = self.env["res.area"] + area_type_model = self.env["res.area.type"] + self.partner = res_partner_model.create( + { + "name": "Test Partner", + } + ) + self.project = self.project_model.create( + { + "name": "Test Project", + } + ) + self.area = area_model.create( + { + "code": "TA", + "name": "Test Area", + "nonoperative": True, + } + ) + self.type = area_type_model.create( + { + "code": "TAT", + "name": "Test Area Type", + } + ) + self.setting = self.env["res.config.settings"].create({}) + + def test_area_nonoperative(self): + self.assertEquals( + self.project.nonoperative, self.project.res_area_id.nonoperative + ) + self.assertFalse(self.project.nonoperative) + self.project.write( + { + "res_area_id": self.area.id, + } + ) + self.project._onchange_area_id() + self.assertEquals( + self.project.nonoperative, self.project.res_area_id.nonoperative + ) + self.assertTrue(self.project.nonoperative) + + def test_create_new_project(self): + self.setting.manual_code = False + self.setting.set_values() + self.assertFalse(self.setting.manual_code) + vals = { + "name": "New Project", + "res_area_id": self.area.id, + "res_area_type_id": self.type.id, + } + new_project = self.project_model.new(vals) + new_project._onchange_area_type() + vals.update({"num_code": new_project.num_code}) + new_project = self.project_model.create(vals) + count = self.project_model.search_count( + [ + ("res_area_id", "=", self.area.id), + ("res_area_type_id", "=", self.type.id), + ] + ) + self.assertEquals( + new_project.code, "{}.{}.{}".format(self.area.code, self.type.code, count) + ) + + def test_create_new_project_char(self): + self.setting.manual_code = False + self.setting.set_values() + self.assertFalse(self.setting.manual_code) + vals = { + "name": "New Project", + "res_area_id": self.area.id, + "res_area_type_id": self.type.id, + } + new_project = self.project_model.new(vals) + new_project._onchange_area_type() + vals.update({"num_code": "{}a".format(new_project.num_code)}) + self.project_model.create(vals) + count = self.project_model.search_count( + [ + ("res_area_id", "=", self.area.id), + ("res_area_type_id", "=", self.type.id), + ] + ) + new_project2 = self.project_model.new(vals) + new_project2._onchange_area_type() + vals.update({"num_code": new_project2.num_code}) + new_project2 = self.project_model.create(vals) + self.assertEquals(new_project2.num_code, str(count + 1)) + + def test_create_new_account(self): + self.setting.manual_code = False + self.setting.set_values() + self.assertFalse(self.setting.manual_code) + vals = { + "name": "New Project", + "res_area_id": self.area.id, + "res_area_type_id": self.type.id, + } + new_account = self.analytic_model.new(vals) + new_account._onchange_area_type() + vals.update({"num_code": new_account.num_code}) + new_account = self.analytic_model.create(vals) + count = self.analytic_model.search_count( + [ + ("res_area_id", "=", self.area.id), + ("res_area_type_id", "=", self.type.id), + ] + ) + self.assertEquals( + new_account.code, "{}.{}.{}".format(self.area.code, self.type.code, count) + ) + + def test_create_new_account_char(self): + self.setting.manual_code = False + self.setting.set_values() + self.assertFalse(self.setting.manual_code) + vals = { + "name": "New Project", + "res_area_id": self.area.id, + "res_area_type_id": self.type.id, + } + new_account = self.analytic_model.new(vals) + new_account._onchange_area_type() + vals.update({"num_code": "{}a".format(new_account.num_code)}) + self.analytic_model.create(vals) + count = self.analytic_model.search_count( + [ + ("res_area_id", "=", self.area.id), + ("res_area_type_id", "=", self.type.id), + ] + ) + new_account2 = self.analytic_model.new(vals) + new_account2._onchange_area_type() + vals.update({"num_code": new_account2.num_code}) + new_account2 = self.analytic_model.create(vals) + self.assertEquals(new_account2.num_code, str(count + 1)) + + def test_create_new_project_manual(self): + self.setting.manual_code = True + self.setting.set_values() + self.assertTrue(self.setting.manual_code) + vals = { + "name": "New Project", + "res_area_id": self.area.id, + "res_area_type_id": self.type.id, + } + new_project = self.project_model.new(vals) + new_project._onchange_area_type() + self.assertFalse(new_project.num_code) + vals.update({"num_code": "10"}) + new_project = self.project_model.create(vals) + self.assertEquals( + new_project.code, + "{}.{}.{}".format(self.area.code, self.type.code, new_project.num_code), + ) + + def test_create_new_account_manual(self): + self.setting.manual_code = True + self.setting.set_values() + self.assertTrue(self.setting.manual_code) + vals = { + "name": "New Project", + "res_area_id": self.area.id, + "res_area_type_id": self.type.id, + } + new_account = self.analytic_model.new(vals) + new_account._onchange_area_type() + self.assertFalse(new_account.num_code) + vals.update({"num_code": "10"}) + new_account = self.analytic_model.create(vals) + self.assertEquals( + new_account.code, + "{}.{}.{}".format(self.area.code, self.type.code, new_account.num_code), + ) diff --git a/project_characterization/views/account_analytic_view.xml b/project_characterization/views/account_analytic_view.xml new file mode 100644 index 00000000..ff50b7c7 --- /dev/null +++ b/project_characterization/views/account_analytic_view.xml @@ -0,0 +1,85 @@ + + + + account.analytic.account.form + account.analytic.account + + + + + + + + + + + + + + + + + + + + + + + account.analytic.account.tree + account.analytic.account + + + + + + + + + + + account.analytic.account.search + account.analytic.account + + + + + + + + + + + + + + + + + + + + + + + + + + account.analytic.line.search + account.analytic.line + + + + + + + + + + diff --git a/project_characterization/views/project_characterization_view.xml b/project_characterization/views/project_characterization_view.xml new file mode 100644 index 00000000..0967e27b --- /dev/null +++ b/project_characterization/views/project_characterization_view.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + diff --git a/project_characterization/views/project_project_view.xml b/project_characterization/views/project_project_view.xml new file mode 100644 index 00000000..d63e1d98 --- /dev/null +++ b/project_characterization/views/project_project_view.xml @@ -0,0 +1,104 @@ + + + + project.project + + + + + + + + + + + + project.project + + + + + + + + + + + project.project.form + project.project + + + + + + + + + + + + + + + + + + + + + + + + + + + + project.project.tree + project.project + + + + + + + + + + + + + + project.project.search + project.project + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/project_characterization/views/project_task_view.xml b/project_characterization/views/project_task_view.xml new file mode 100644 index 00000000..a05152a9 --- /dev/null +++ b/project_characterization/views/project_task_view.xml @@ -0,0 +1,35 @@ + + + + project.task.form + project.task + + + + + + + + + + + + project.task.type2.form + project.task.type2 + +
+ +

+ +

+ +
+
+
+
+
diff --git a/project_characterization/views/res_area_view.xml b/project_characterization/views/res_area_view.xml new file mode 100644 index 00000000..f771f598 --- /dev/null +++ b/project_characterization/views/res_area_view.xml @@ -0,0 +1,35 @@ + + + + res.area.operative.form + res.area + + + + + + + + + res.area.operative.search + res.area + + + + + + + + + diff --git a/project_characterization/views/res_config_settings_view.xml b/project_characterization/views/res_config_settings_view.xml new file mode 100644 index 00000000..ad2d156a --- /dev/null +++ b/project_characterization/views/res_config_settings_view.xml @@ -0,0 +1,23 @@ + + + + res.config.settings + + +
+
+
+ +
+
+
+
+
+
+
+
diff --git a/project_funding/README.rst b/project_funding/README.rst new file mode 100644 index 00000000..09c5215f --- /dev/null +++ b/project_funding/README.rst @@ -0,0 +1,29 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +=============== +Project Funding +=============== + +You can define how a project is going to be funded. + +Funding line account definition visible by configuration. + +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 smash it by providing detailed and welcomed feedback. + +Credits +======= + +Contributors +------------ +* Ana Juaristi +* Oihane Crucelaegui + +Do not contact contributors directly about support or help with technical issues. diff --git a/project_funding/__init__.py b/project_funding/__init__.py new file mode 100644 index 00000000..288dc48e --- /dev/null +++ b/project_funding/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2018 Oihane Crucelaegui - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from . import models diff --git a/project_funding/__manifest__.py b/project_funding/__manifest__.py new file mode 100644 index 00000000..cd5b86c2 --- /dev/null +++ b/project_funding/__manifest__.py @@ -0,0 +1,24 @@ +# Copyright 2018 Oihane Crucelaegui - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +{ + "name": "Project Funding", + "version": "12.0.1.0.0", + "license": "AGPL-3", + "depends": [ + "project", + "partner_funding_source", + ], + "author": "AvanzOSC", + "website": "http://www.avanzosc.es", + "category": "Project", + "data": [ + "security/project_funding_security.xml", + "security/ir.model.access.csv", + "views/funding_source_project_view.xml", + "views/project_project_view.xml", + "views/project_funding_view.xml", + "views/res_config_settings_view.xml", + ], + "installable": True, +} diff --git a/project_funding/i18n/es.po b/project_funding/i18n/es.po new file mode 100644 index 00000000..efc4e658 --- /dev/null +++ b/project_funding/i18n/es.po @@ -0,0 +1,166 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * project_funding +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-04-03 14:11+0000\n" +"PO-Revision-Date: 2023-04-03 14:11+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: project_funding +#: model:ir.model.fields,field_description:project_funding.field_funding_source_project__active +msgid "Active" +msgstr "Activo" + +#. module: project_funding +#: model_terms:ir.ui.view,arch_db:project_funding.funding_source_project_view_search +msgid "Archived" +msgstr "Archivado" + +#. module: project_funding +#: model:ir.model,name:project_funding.model_res_config_settings +msgid "Config Settings" +msgstr "Opciones de Configuración" + +#. module: project_funding +#: model:ir.model.fields,field_description:project_funding.field_funding_source_project__create_uid +msgid "Created by" +msgstr "Creado por" + +#. module: project_funding +#: model:ir.model.fields,field_description:project_funding.field_funding_source_project__create_date +msgid "Created on" +msgstr "Creado el" + +#. module: project_funding +#: model:ir.model.fields,field_description:project_funding.field_funding_source_project__display_name +msgid "Display Name" +msgstr "Nombre mostrado" + +#. module: project_funding +#: model:ir.model.fields,field_description:project_funding.field_res_config_settings__group_funding_account +msgid "Funding Account Visible" +msgstr "Cuenta contable de financiación visible" + +#. module: project_funding +#: model:ir.model.fields,field_description:project_funding.field_funding_source_project__funding_date +msgid "Funding Date" +msgstr "Fecha de financiación" + +#. module: project_funding +#: model:ir.model.fields,field_description:project_funding.field_funding_source_project__source_id +#: model:ir.ui.menu,name:project_funding.funding_source_config_menu +#: model:ir.ui.menu,name:project_funding.funding_source_menu +msgid "Funding Source" +msgstr "Programa de financiación" + +#. module: project_funding +#: model:ir.model.fields,field_description:project_funding.field_funding_source_project__account_id +msgid "Funding Source Account" +msgstr "Cuenta de fuente de financiación" + +#. module: project_funding +#: model:ir.actions.act_window,name:project_funding.funding_source_project_action +#: model:ir.model,name:project_funding.model_funding_source_project +#: model:ir.ui.menu,name:project_funding.funding_source_project_menu +#: model_terms:ir.ui.view,arch_db:project_funding.funding_source_project_view_tree +msgid "Funding Source Project" +msgstr "Financiación de proyecto" + +#. module: project_funding +#: model:ir.ui.menu,name:project_funding.funding_source_type_menu +msgid "Funding Source Type" +msgstr "Tipo de programa de financiación" + +#. module: project_funding +#: model:ir.model.fields,field_description:project_funding.field_project_project__funding_ids +#: model_terms:ir.ui.view,arch_db:project_funding.project_project_view_form +msgid "Funding Sources" +msgstr "Programas de financiación" + +#. module: project_funding +#: model:ir.model.fields,field_description:project_funding.field_funding_source_project__id +msgid "ID" +msgstr "" + +#. module: project_funding +#: model:ir.model.fields,field_description:project_funding.field_funding_source_project____last_update +msgid "Last Modified on" +msgstr "Última modificación en" + +#. module: project_funding +#: model:ir.model.fields,field_description:project_funding.field_funding_source_project__write_uid +msgid "Last Updated by" +msgstr "Última actualización por" + +#. module: project_funding +#: model:ir.model.fields,field_description:project_funding.field_funding_source_project__write_date +msgid "Last Updated on" +msgstr "Última actualización el" + +#. module: project_funding +#: model:ir.model.fields,field_description:project_funding.field_funding_source_project__percentage +msgid "Percentage (%)" +msgstr "Porcentaje (%)" + +#. module: project_funding +#: code:addons/project_funding/models/funding_source_project.py:38 +#, python-format +msgid "Percentage must be bigger than 0" +msgstr "El porcentaje debe ser mayor que 0" + +#. module: project_funding +#: code:addons/project_funding/models/funding_source_project.py:40 +#, python-format +msgid "Percentage should be less or equal to 100" +msgstr "El porcentaje debe ser menor o igual a 100" + +#. module: project_funding +#: model:ir.model,name:project_funding.model_project_project +#: model:ir.model.fields,field_description:project_funding.field_funding_source_project__project_id +msgid "Project" +msgstr "Proyecto" + +#. module: project_funding +#: model_terms:ir.ui.view,arch_db:project_funding.project_config_settings_view_form +msgid "Project Funding" +msgstr "Financiación de proyecto" + +#. module: project_funding +#: model_terms:ir.ui.view,arch_db:project_funding.funding_source_project_view_search +msgid "Search Funding Source Project" +msgstr "Buscar financiación de proyecto" + +#. module: project_funding +#: model:res.groups,name:project_funding.group_funding_account +msgid "Show Project Funding Account" +msgstr "Mostrar cuenta contable" + +#. module: project_funding +#: model_terms:ir.ui.view,arch_db:project_funding.project_config_settings_view_form +msgid "Show related funding account on project funding." +msgstr "Muestra la cuenta contable asociada a la financiación de proyecto." + +#. module: project_funding +#: model_terms:ir.ui.view,arch_db:project_funding.project_config_settings_view_form +msgid "Specific Settings For Project Funding" +msgstr "Ajustes de la financiación de proyecto" + +#. module: project_funding +#: model:ir.model.fields,field_description:project_funding.field_funding_source_project__year +msgid "Year" +msgstr "Año" + +#. module: project_funding +#: model:ir.model.fields,field_description:project_funding.field_funding_source_project__yearly_amount +msgid "Yearly Amount" +msgstr "Importe anual" + diff --git a/project_funding/models/__init__.py b/project_funding/models/__init__.py new file mode 100644 index 00000000..d9841439 --- /dev/null +++ b/project_funding/models/__init__.py @@ -0,0 +1,6 @@ +# Copyright 2018 Oihane Crucelaegui - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from . import funding_source_project +from . import project_project +from . import res_config_settings diff --git a/project_funding/models/funding_source_project.py b/project_funding/models/funding_source_project.py new file mode 100644 index 00000000..cb7e42ec --- /dev/null +++ b/project_funding/models/funding_source_project.py @@ -0,0 +1,40 @@ +# Copyright 2018 Maite Esnal - AvanzOSC +# Copyright 2018 Oihane Crucelaegui - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from odoo import _, api, fields, models +from odoo.addons import decimal_precision as dp +from odoo.exceptions import ValidationError + + +class FundingSourceProject(models.Model): + _name = "funding.source.project" + _description = "Funding Source Project" + + project_id = fields.Many2one( + comodel_name="project.project", string="Project", required=True + ) + source_id = fields.Many2one( + comodel_name="funding.source", string="Funding Source", required=True + ) + account_id = fields.Many2one( + comodel_name="account.account", string="Funding Source Account" + ) + percentage = fields.Float( + string="Percentage (%)", + digits=dp.get_precision("Discount"), + group_operator="sum", + ) + funding_date = fields.Date(string="Funding Date") + year = fields.Integer(string="Year") + yearly_amount = fields.Float(string="Yearly Amount", digits=0) + active = fields.Boolean(string="Active", default=True) + + @api.multi + @api.constrains("percentage") + def _check_discount(self): + for line in self: + if line.percentage < 0: + raise ValidationError(_("Percentage must be bigger than 0")) + elif line.percentage > 100: + raise ValidationError(_("Percentage should be less or equal to 100")) diff --git a/project_funding/models/project_project.py b/project_funding/models/project_project.py new file mode 100644 index 00000000..5146691f --- /dev/null +++ b/project_funding/models/project_project.py @@ -0,0 +1,26 @@ +# Copyright 2018 Oihane Crucelaegui - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from odoo import api, fields, models + + +class ProjectProject(models.Model): + _inherit = "project.project" + + funding_ids = fields.One2many( + comodel_name="funding.source.project", + inverse_name="project_id", + string="Funding Sources", + copy=True, + context={"active_test": False}, + ) + + @api.multi + def write(self, vals): + res = super(ProjectProject, self).write(vals) if vals else True + if "active" in vals: + # archiving/unarchiving a project does it on its funding, too + self.with_context(active_test=False).mapped("funding_ids").write( + {"active": vals["active"]} + ) + return res diff --git a/project_funding/models/res_config_settings.py b/project_funding/models/res_config_settings.py new file mode 100644 index 00000000..90b8559f --- /dev/null +++ b/project_funding/models/res_config_settings.py @@ -0,0 +1,13 @@ +# Copyright 2018 Oihane Crucelaegui - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from odoo import fields, models + + +class ProjectConfigSettings(models.TransientModel): + _inherit = "res.config.settings" + + group_funding_account = fields.Boolean( + string="Funding Account Visible", + implied_group="project_funding.group_funding_account", + ) diff --git a/project_funding/security/ir.model.access.csv b/project_funding/security/ir.model.access.csv new file mode 100644 index 00000000..3c08ebd6 --- /dev/null +++ b/project_funding/security/ir.model.access.csv @@ -0,0 +1,10 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_funding_source_analytic_accounting,access_funding_source,partner_funding_source.model_funding_source,analytic.group_analytic_accounting,1,1,1,1 +access_funding_source_type_analytic_accounting,access_funding_source_type,partner_funding_source.model_funding_source_type,analytic.group_analytic_accounting,1,1,1,1 +access_funding_source_project_analytic_accounting,access_funding_source_project,model_funding_source_project,analytic.group_analytic_accounting,1,1,1,1 +access_funding_source_project_manager,access_funding_source,partner_funding_source.model_funding_source,project.group_project_manager,1,1,1,1 +access_funding_source_type_project_manager,access_funding_source_type,partner_funding_source.model_funding_source_type,project.group_project_manager,1,1,1,1 +access_funding_source_project_project_manager,access_funding_source_project,model_funding_source_project,project.group_project_manager,1,1,1,1 +access_funding_source,access_funding_source,partner_funding_source.model_funding_source,,1,0,0,0 +access_funding_source_type,access_funding_source_type,partner_funding_source.model_funding_source_type,,1,0,0,0 +access_funding_source_project,access_funding_source_project,model_funding_source_project,,1,0,0,0 diff --git a/project_funding/security/project_funding_security.xml b/project_funding/security/project_funding_security.xml new file mode 100644 index 00000000..78cecb3e --- /dev/null +++ b/project_funding/security/project_funding_security.xml @@ -0,0 +1,7 @@ + + + + Show Project Funding Account + + + diff --git a/project_funding/tests/__init__.py b/project_funding/tests/__init__.py new file mode 100644 index 00000000..12b48bda --- /dev/null +++ b/project_funding/tests/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2018 Oihane Crucelaegui - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from . import test_project_funding diff --git a/project_funding/tests/test_project_funding.py b/project_funding/tests/test_project_funding.py new file mode 100644 index 00000000..c7873aa5 --- /dev/null +++ b/project_funding/tests/test_project_funding.py @@ -0,0 +1,67 @@ +# Copyright 2018 Oihane Crucelaegui - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from odoo.tests import common +from odoo.exceptions import ValidationError + + +class TestProjectCharacterization(common.TransactionCase): + def setUp(self): + super(TestProjectCharacterization, self).setUp() + res_partner_model = self.env["res.partner"] + funding_src_model = self.env["funding.source"] + self.project_model = self.env["project.project"] + self.funding_project_model = self.env["funding.source.project"] + self.partner = res_partner_model.create( + { + "name": "Test Partner", + } + ) + self.funding_src = funding_src_model.create( + { + "name": "Test Funding Source", + } + ) + self.project = self.project_model.create( + { + "name": "Test Project", + } + ) + + def test_funding_src_constraints(self): + funding_project = self.funding_project_model.create( + { + "project_id": self.project.id, + "source_id": self.funding_src.id, + } + ) + with self.assertRaises(ValidationError): + funding_project.write( + { + "percentage": -0.1, + } + ) + with self.assertRaises(ValidationError): + funding_project.write( + { + "percentage": 100.1, + } + ) + funding_project.write( + { + "percentage": 50.0, + } + ) + + def test_project_disable_enable(self): + self.assertTrue(self.project.active) + for funding in self.project.with_context(active_test=False).funding_ids: + self.assertTrue(funding.active) + self.project.toggle_active() + self.assertFalse(self.project.active) + for funding in self.project.with_context(active_test=False).funding_ids: + self.assertFalse(funding.active) + self.project.toggle_active() + self.assertTrue(self.project.active) + for funding in self.project.with_context(active_test=False).funding_ids: + self.assertTrue(funding.active) diff --git a/project_funding/views/funding_source_project_view.xml b/project_funding/views/funding_source_project_view.xml new file mode 100644 index 00000000..5343be86 --- /dev/null +++ b/project_funding/views/funding_source_project_view.xml @@ -0,0 +1,46 @@ + + + + funding.source.project.tree + funding.source.project + + + + + + + + + + + + + + + + funding.source.project.search + funding.source.project + + + + + + + + + + + + Funding Source Project + funding.source.project + tree + { + 'hide_project_id': False, + } + + + + diff --git a/project_funding/views/project_funding_view.xml b/project_funding/views/project_funding_view.xml new file mode 100644 index 00000000..9e140284 --- /dev/null +++ b/project_funding/views/project_funding_view.xml @@ -0,0 +1,15 @@ + + + + + + + diff --git a/project_funding/views/project_project_view.xml b/project_funding/views/project_project_view.xml new file mode 100644 index 00000000..39a8d740 --- /dev/null +++ b/project_funding/views/project_project_view.xml @@ -0,0 +1,17 @@ + + + + project.project + + + + + + + + + + + + diff --git a/project_funding/views/res_config_settings_view.xml b/project_funding/views/res_config_settings_view.xml new file mode 100644 index 00000000..07109941 --- /dev/null +++ b/project_funding/views/res_config_settings_view.xml @@ -0,0 +1,25 @@ + + + + res.config.settings + + + +

Project Funding

+
+
+
+ +
+
+
+
+
+
+
+
+
diff --git a/project_goal/README.rst b/project_goal/README.rst new file mode 100644 index 00000000..f2dc5c9f --- /dev/null +++ b/project_goal/README.rst @@ -0,0 +1,28 @@ +.. image:: https://img.shields.io/badge/license-AGPL--3-blue.png + :target: https://www.gnu.org/licenses/agpl + :alt: License: AGPL-3 + +============ +Project Goal +============ + +You will be able to define a list of goals for a project. + +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 smash it by providing detailed and welcomed feedback. + +Credits +======= + +Contributors +------------ + +* Gontzal Gomez +* Ana Juaristi + +Do not contact contributors directly about support or help with technical issues. diff --git a/project_goal/__init__.py b/project_goal/__init__.py new file mode 100644 index 00000000..94f64b4d --- /dev/null +++ b/project_goal/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2018 Gontzal Gomez - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from . import models diff --git a/project_goal/__manifest__.py b/project_goal/__manifest__.py new file mode 100644 index 00000000..af75d4ec --- /dev/null +++ b/project_goal/__manifest__.py @@ -0,0 +1,21 @@ +# Copyright 2018 Gontzal Gomez - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +{ + "name": "Project Goal", + "version": "12.0.1.0.0", + "license": "AGPL-3", + "depends": [ + "project", + ], + "author": "AvanzOSC", + "website": "http://www.avanzosc.es", + "category": "Project", + "data": [ + "security/ir.model.access.csv", + "views/project_goal_view.xml", + "views/project_project_view.xml", + "data/project_goal_data.xml", + ], + "installable": True, +} diff --git a/project_goal/data/project_goal_data.xml b/project_goal/data/project_goal_data.xml new file mode 100644 index 00000000..e2cc6a13 --- /dev/null +++ b/project_goal/data/project_goal_data.xml @@ -0,0 +1,15 @@ + + + + Customer + + + Technical + + + Internal + + diff --git a/project_goal/i18n/es.po b/project_goal/i18n/es.po new file mode 100644 index 00000000..73a61165 --- /dev/null +++ b/project_goal/i18n/es.po @@ -0,0 +1,187 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * project_goal +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-04-03 11:01+0000\n" +"PO-Revision-Date: 2023-04-03 11:01+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: project_goal +#: model:ir.model.fields,field_description:project_goal.field_project_goal__acceptance_range +msgid "Acceptance range" +msgstr "Rango de aceptación" + +#. module: project_goal +#: model:ir.model.fields,field_description:project_goal.field_project_goal__active +msgid "Active" +msgstr "Activo" + +#. module: project_goal +#: model_terms:ir.ui.view,arch_db:project_goal.project_goal_view_search +msgid "Archived" +msgstr "Archivado" + +#. module: project_goal +#: model:ir.model.fields,field_description:project_goal.field_project_goal__compliance +msgid "Compliance Degree" +msgstr "Grado de cumplimiento" + +#. module: project_goal +#: model:ir.model.fields,field_description:project_goal.field_project_goal__create_uid +#: model:ir.model.fields,field_description:project_goal.field_project_goal_goal__create_uid +#: model:ir.model.fields,field_description:project_goal.field_project_goal_type__create_uid +msgid "Created by" +msgstr "Creado por" + +#. module: project_goal +#: model:ir.model.fields,field_description:project_goal.field_project_goal__create_date +#: model:ir.model.fields,field_description:project_goal.field_project_goal_goal__create_date +#: model:ir.model.fields,field_description:project_goal.field_project_goal_type__create_date +msgid "Created on" +msgstr "Creado el" + +#. module: project_goal +#: model:project.goal.type,name:project_goal.gtype1 +msgid "Customer" +msgstr "Cliente" + +#. module: project_goal +#: model:ir.model.fields,field_description:project_goal.field_project_goal_goal__description +msgid "Description" +msgstr "Descripción" + +#. module: project_goal +#: model:ir.model.fields,field_description:project_goal.field_project_goal__display_name +#: model:ir.model.fields,field_description:project_goal.field_project_goal_goal__display_name +#: model:ir.model.fields,field_description:project_goal.field_project_goal_type__display_name +msgid "Display Name" +msgstr "Nombre mostrado" + +#. module: project_goal +#: model:ir.model.fields,field_description:project_goal.field_project_goal__goal_id +msgid "Goal" +msgstr "Objetivo" + +#. module: project_goal +#: model:ir.model.fields,field_description:project_goal.field_project_goal_goal__default_goal +msgid "Goal By Default" +msgstr "Objetivo por defecto" + +#. module: project_goal +#: model:ir.model.fields,field_description:project_goal.field_project_goal__name +msgid "Goal Description" +msgstr "Descripción del objetivo" + +#. module: project_goal +#: model:ir.model,name:project_goal.model_project_goal_type +#: model:ir.model.fields,field_description:project_goal.field_project_goal_goal__type_id +msgid "Goal Type" +msgstr "Tipo de objetivo" + +#. module: project_goal +#: model:ir.model.fields,field_description:project_goal.field_project_project__goal_ids +#: model_terms:ir.ui.view,arch_db:project_goal.project_project_plan_view_form +msgid "Goals" +msgstr "Objetivos" + +#. module: project_goal +#: model:ir.model,name:project_goal.model_project_goal +msgid "Goals of Projects" +msgstr "Objetivos de proyectos" + +#. module: project_goal +#: model:ir.model.fields,field_description:project_goal.field_project_goal__id +#: model:ir.model.fields,field_description:project_goal.field_project_goal_goal__id +#: model:ir.model.fields,field_description:project_goal.field_project_goal_type__id +msgid "ID" +msgstr "ID" + +#. module: project_goal +#: model:project.goal.type,name:project_goal.gtype3 +msgid "Internal" +msgstr "Interno" + +#. module: project_goal +#: model:ir.model.fields,field_description:project_goal.field_project_goal____last_update +#: model:ir.model.fields,field_description:project_goal.field_project_goal_goal____last_update +#: model:ir.model.fields,field_description:project_goal.field_project_goal_type____last_update +msgid "Last Modified on" +msgstr "Última modificación en" + +#. module: project_goal +#: model:ir.model.fields,field_description:project_goal.field_project_goal__write_uid +#: model:ir.model.fields,field_description:project_goal.field_project_goal_goal__write_uid +#: model:ir.model.fields,field_description:project_goal.field_project_goal_type__write_uid +msgid "Last Updated by" +msgstr "Última actualización de" + +#. module: project_goal +#: model:ir.model.fields,field_description:project_goal.field_project_goal__write_date +#: model:ir.model.fields,field_description:project_goal.field_project_goal_goal__write_date +#: model:ir.model.fields,field_description:project_goal.field_project_goal_type__write_date +msgid "Last Updated on" +msgstr "Última actualización en" + +#. module: project_goal +#: model:ir.model.fields,field_description:project_goal.field_project_goal_goal__name +#: model:ir.model.fields,field_description:project_goal.field_project_goal_type__name +msgid "Name" +msgstr "Nombre" + +#. module: project_goal +#: model:ir.actions.act_window,name:project_goal.project_goal_goal_action +#: model:ir.model,name:project_goal.model_project_goal_goal +#: model:ir.ui.menu,name:project_goal.project_goal_goal_menu +msgid "Predefined Project Goals" +msgstr "Objetivos predefinidos" + +#. module: project_goal +#: model:ir.model,name:project_goal.model_project_project +#: model:ir.model.fields,field_description:project_goal.field_project_goal__project_id +#: model_terms:ir.ui.view,arch_db:project_goal.project_goal_view_search +msgid "Project" +msgstr "Proyecto" + +#. module: project_goal +#: model:ir.actions.act_window,name:project_goal.project_goal_action +#: model:ir.ui.menu,name:project_goal.project_goal_configuration_menu +#: model:ir.ui.menu,name:project_goal.project_goal_menu +msgid "Project Goals" +msgstr "Objetivos de proyecto" + +#. module: project_goal +#: model:ir.model.fields,field_description:project_goal.field_project_goal__remark +msgid "Remarks" +msgstr "Observaciones" + +#. module: project_goal +#: model:ir.model.fields,field_description:project_goal.field_project_goal__sequence +msgid "Sequence" +msgstr "Secuencia" + +#. module: project_goal +#: model:project.goal.type,name:project_goal.gtype2 +msgid "Technical" +msgstr "Técnico" + +#. module: project_goal +#: model:ir.model.fields,field_description:project_goal.field_project_goal__type_id +#: model_terms:ir.ui.view,arch_db:project_goal.project_goal_view_search +msgid "Type" +msgstr "Tipo" + +#. module: project_goal +#: model:ir.actions.act_window,name:project_goal.project_goal_type_action +#: model:ir.ui.menu,name:project_goal.project_goal_type_menu +msgid "Types of Goal" +msgstr "Tipos de objetivo" + diff --git a/project_goal/models/__init__.py b/project_goal/models/__init__.py new file mode 100644 index 00000000..31059c0d --- /dev/null +++ b/project_goal/models/__init__.py @@ -0,0 +1,7 @@ +# Copyright 2018 Gontzal Gomez - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from . import project_goal +from . import project_goal_goal +from . import project_goal_type +from . import project_project diff --git a/project_goal/models/project_goal.py b/project_goal/models/project_goal.py new file mode 100644 index 00000000..a73c5c76 --- /dev/null +++ b/project_goal/models/project_goal.py @@ -0,0 +1,40 @@ +# Copyright 2018 Gontzal Gomez - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from odoo import api, fields, models + + +class ProjectGoal(models.Model): + _name = "project.goal" + _description = "Goals of Projects" + _order = "project_id,sequence" + + project_id = fields.Many2one( + name="Project", + comodel_name="project.project", + required=True, + ondelete="cascade", + ) + sequence = fields.Integer(string="Sequence") + goal_id = fields.Many2one( + string="Goal", + comodel_name="project.goal.goal", + domain="['|',('type_id','=',type_id),('type_id','=',False)]", + ) + name = fields.Text(string="Goal Description") + type_id = fields.Many2one( + string="Type", comodel_name="project.goal.type", required=True + ) + acceptance_range = fields.Text(string="Acceptance range") + compliance = fields.Char(string="Compliance Degree") + remark = fields.Char(string="Remarks") + active = fields.Boolean(string="Active", default=True) + + @api.onchange("goal_id") + def onchange_goal_id(self): + self.name = self.goal_id.description + + @api.onchange("type_id") + def onchange_type_id(self): + if self.goal_id.type_id.id not in (self.type_id.id, False): + self.goal_id = False diff --git a/project_goal/models/project_goal_goal.py b/project_goal/models/project_goal_goal.py new file mode 100644 index 00000000..ed3637a7 --- /dev/null +++ b/project_goal/models/project_goal_goal.py @@ -0,0 +1,14 @@ +# Copyright 2019 Oihane Crucelaegui - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from odoo import fields, models + + +class ProjectGoalGoal(models.Model): + _name = "project.goal.goal" + _description = "Predefined Project Goals" + + name = fields.Char(string="Name", required=True) + description = fields.Text(string="Description") + type_id = fields.Many2one(string="Goal Type", comodel_name="project.goal.type") + default_goal = fields.Boolean(string="Goal By Default") diff --git a/project_goal/models/project_goal_type.py b/project_goal/models/project_goal_type.py new file mode 100644 index 00000000..10f08103 --- /dev/null +++ b/project_goal/models/project_goal_type.py @@ -0,0 +1,11 @@ +# Copyright 2018 Gontzal Gomez - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from odoo import fields, models + + +class ProjectGoalType(models.Model): + _name = "project.goal.type" + _description = "Goal Type" + + name = fields.Char(string="Name", translate=True) diff --git a/project_goal/models/project_project.py b/project_goal/models/project_project.py new file mode 100644 index 00000000..02d745ac --- /dev/null +++ b/project_goal/models/project_project.py @@ -0,0 +1,54 @@ +# Copyright 2018 Gontzal Gomez - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from odoo import api, fields, models + + +class ProjectProject(models.Model): + _inherit = "project.project" + + goal_ids = fields.One2many( + comodel_name="project.goal", + inverse_name="project_id", + string="Goals", + copy=True, + context={"active_test": False}, + ) + + @api.model + def default_get(self, fields): + res = super(ProjectProject, self).default_get(fields) + default_goals = self.env["project.goal.goal"].search( + [ + ("default_goal", "=", True), + ("type_id", "!=", False), + ] + ) + res.update( + { + "goal_ids": [ + ( + 0, + 0, + { + "type_id": x.type_id.id, + "goal_id": x.id, + "name": x.description, + "active": True, + }, + ) + for x in default_goals + ], + } + ) + return res + + @api.multi + def write(self, vals): + res = super(ProjectProject, self).write(vals) if vals else True + if "active" in vals: + # archiving/unarchiving a project does it on its goals, too + self.with_context(active_test=False).mapped("goal_ids").write( + {"active": vals["active"]} + ) + return res diff --git a/project_goal/security/ir.model.access.csv b/project_goal/security/ir.model.access.csv new file mode 100644 index 00000000..11fb4112 --- /dev/null +++ b/project_goal/security/ir.model.access.csv @@ -0,0 +1,10 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_project_goal,access_project_goal,model_project_goal,,1,0,0,0 +access_project_goal_goal,access_project_goal_goal,model_project_goal_goal,,1,0,0,0 +access_project_goal_type,access_project_goal_type,model_project_goal_type,,1,0,0,0 +access_project_goal_user,access_project_goal user,model_project_goal,project.group_project_user,1,1,1,0 +access_project_goal_goal_user,access_project_goal_goal user,model_project_goal_goal,project.group_project_user,1,1,1,0 +access_project_goal_type_user,access_project_goal_type user,model_project_goal_type,project.group_project_user,1,1,1,0 +access_project_goal_manager,access_project_goal manager,model_project_goal,project.group_project_manager,1,1,1,1 +access_project_goal_goal_manager,access_project_goal_goal manager,model_project_goal_goal,project.group_project_manager,1,1,1,1 +access_project_goal_type_manager,access_project_goal_type manager,model_project_goal_type,project.group_project_manager,1,1,1,1 diff --git a/project_goal/tests/__init__.py b/project_goal/tests/__init__.py new file mode 100644 index 00000000..03c88221 --- /dev/null +++ b/project_goal/tests/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2018 Oihane Crucelaegui - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from . import test_project_goal diff --git a/project_goal/tests/test_project_goal.py b/project_goal/tests/test_project_goal.py new file mode 100644 index 00000000..df731d10 --- /dev/null +++ b/project_goal/tests/test_project_goal.py @@ -0,0 +1,61 @@ +# Copyright 2018 Oihane Crucelaegui - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from odoo.tests import common, tagged + + +@tagged("post_install", "-at_install") +class TestProjectGoal(common.SavepointCase): + @classmethod + def setUpClass(cls): + super(TestProjectGoal, cls).setUpClass() + goal_type = cls.env.ref("project_goal.gtype1") + cls.goal_type2 = cls.env.ref("project_goal.gtype2") + cls.goal = cls.env["project.goal.goal"].create( + { + "name": "New Goal", + "description": "Goal Description", + "type_id": goal_type.id, + } + ) + cls.project = cls.env["project.project"].create( + { + "name": "New Project", + "goal_ids": [ + (0, 0, {"name": "Goal 1", "type_id": goal_type.id}), + (0, 0, {"name": "Goal 2", "type_id": goal_type.id}), + ], + } + ) + + def test_project_disable_enable(self): + self.assertTrue(self.project.active) + for goal in self.project.with_context(active_test=False).goal_ids: + self.assertTrue(goal.active) + self.project.toggle_active() + self.assertFalse(self.project.active) + for goal in self.project.with_context(active_test=False).goal_ids: + self.assertFalse(goal.active) + self.project.toggle_active() + self.assertTrue(self.project.active) + for goal in self.project.with_context(active_test=False).goal_ids: + self.assertTrue(goal.active) + + def test_project_goal_onchanges(self): + for goal in self.project.with_context(active_test=False).goal_ids: + self.assertFalse(goal.goal_id) + self.assertNotEquals(goal.name, self.goal.description) + goal.write( + { + "goal_id": self.goal.id, + } + ) + goal.onchange_goal_id() + self.assertEquals(goal.name, self.goal.description) + goal.write( + { + "type_id": self.goal_type2.id, + } + ) + goal.onchange_type_id() + self.assertFalse(goal.goal_id) diff --git a/project_goal/views/project_goal_view.xml b/project_goal/views/project_goal_view.xml new file mode 100644 index 00000000..ceb6d057 --- /dev/null +++ b/project_goal/views/project_goal_view.xml @@ -0,0 +1,104 @@ + + + + project.goal + +
+ + + + + + + + + + + +
+
+
+ + + project.goal + + + + + + + + + + + + + + + + + project.goal.type + + + + + + + + + project.goal.goal + + + + + + + + + + + project.goal.goal + +
+ + + + + + + + + + + + +
+
+
+ + + project.goal + + + + + + + + + + + + + + + + + + + +
diff --git a/project_goal/views/project_project_view.xml b/project_goal/views/project_project_view.xml new file mode 100644 index 00000000..a4e7f193 --- /dev/null +++ b/project_goal/views/project_project_view.xml @@ -0,0 +1,54 @@ + + + + + project.plan.form.view + project.project + + + + + + + + + + + + + + Project Goals + project.goal + tree + { + 'hide_project_id': False, + } + + + + + Predefined Project Goals + project.goal.goal + tree,form + + + + Types of Goal + project.goal.type + tree + + + + + + +