From be29d1b2357f84b5a113c01d546cb0cd63f94f27 Mon Sep 17 00:00:00 2001 From: "Pedro M. Baeza" Date: Mon, 13 Feb 2017 02:07:14 +0100 Subject: [PATCH] [IMP] base_custom_info: Make backend UI work # Conflicts: # base_custom_info/i18n/es.po --- base_custom_info/README.rst | 23 +- base_custom_info/__manifest__.py | 4 +- .../demo/custom.info.category.csv | 2 +- base_custom_info/i18n/es.po | 577 ++++++++++++++++-- .../customizations-everywhere.jpg | Bin .../templateception.jpg | Bin base_custom_info/models/custom_info.py | 122 ++-- base_custom_info/models/custom_info_option.py | 3 +- .../models/custom_info_property.py | 14 +- .../models/custom_info_template.py | 71 ++- base_custom_info/models/custom_info_value.py | 169 ++--- base_custom_info/models/res_partner.py | 9 +- base_custom_info/static/description/icon.png | Bin 5289 -> 4075 bytes base_custom_info/static/description/icon.svg | 60 +- base_custom_info/tests/test_partner.py | 25 - .../views/custom_info_category_view.xml | 83 ++- .../views/custom_info_option_view.xml | 113 ++-- .../views/custom_info_property_view.xml | 169 ++--- .../views/custom_info_template_view.xml | 124 ++-- .../views/custom_info_value_view.xml | 185 +++--- base_custom_info/views/menu.xml | 72 +-- base_custom_info/views/res_partner_view.xml | 52 +- 22 files changed, 1152 insertions(+), 725 deletions(-) rename base_custom_info/{static/description => images}/customizations-everywhere.jpg (100%) rename base_custom_info/{static/description => images}/templateception.jpg (100%) diff --git a/base_custom_info/README.rst b/base_custom_info/README.rst index 8271d9f6e..2871256ed 100644 --- a/base_custom_info/README.rst +++ b/base_custom_info/README.rst @@ -217,19 +217,7 @@ Known issues / Roadmap ====================== * Custom properties cannot be shared among templates. -* You get an error if you press *Save & New* when setting property values in - partner form. -* You have to press *reload custom information templates*, when the optimal - thing would be the reloading taking place whenever needed: when you change - the template, or when you choose an option that has an additional template. - However, `currently it is impossible for a x2many field to update itself - `_, and it is - needed to skip some checks when you are saving a record after filling the - templates, which has to be done by `changing the context, something also not - possible currently at onchange time - `_. So there are some technical - limitations that do not let us reach the ideal UX for this addon. So, in - short, press the button when you see it and be happy. +* Required attributes are for now only set in the UI, not in the ORM itself. Bug Tracker =========== @@ -245,10 +233,11 @@ Credits Contributors ------------ -* Rafael Blasco -* Carlos Dauden -* Sergio Teruel -* Jairo Llopis +* Rafael Blasco +* Carlos Dauden +* Sergio Teruel +* Jairo Llopis +* Pedro M. Baeza Maintainer ---------- diff --git a/base_custom_info/__manifest__.py b/base_custom_info/__manifest__.py index 7c9a5c70f..5afe440f9 100644 --- a/base_custom_info/__manifest__.py +++ b/base_custom_info/__manifest__.py @@ -38,9 +38,7 @@ "images/templates.png", "images/values.png", ], - 'author': 'Antiun Ingeniería S.L., ' - 'Incaser Informatica S.L., ' - 'Tecnativa, ' + 'author': 'Tecnativa, ' 'Odoo Community Association (OCA)', 'website': 'https://www.tecnativa.com', 'license': 'AGPL-3', diff --git a/base_custom_info/demo/custom.info.category.csv b/base_custom_info/demo/custom.info.category.csv index 35104e4ef..4c64ccb09 100644 --- a/base_custom_info/demo/custom.info.category.csv +++ b/base_custom_info/demo/custom.info.category.csv @@ -1,3 +1,3 @@ id,name,sequence -cat_statics,Statics,50 +cat_statics,Statistics,50 cat_gaming,Gaming,100 diff --git a/base_custom_info/i18n/es.po b/base_custom_info/i18n/es.po index adab6ff19..3587f3576 100644 --- a/base_custom_info/i18n/es.po +++ b/base_custom_info/i18n/es.po @@ -1,27 +1,61 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: -# * base_custom_info -# -# Translators: -# OCA Transbot , 2016 +# * base_custom_info +# msgid "" msgstr "" "Project-Id-Version: Odoo Server 9.0c\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-09-10 02:52+0000\n" -"PO-Revision-Date: 2016-09-10 02:52+0000\n" -"Last-Translator: OCA Transbot , 2016\n" -"Language-Team: Spanish (https://www.transifex.com/oca/teams/23907/es/)\n" +"POT-Creation-Date: 2017-02-13 00:39+0000\n" +"PO-Revision-Date: 2017-02-13 00:39+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" -"Language: es\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"Plural-Forms: \n" #. module: base_custom_info -#: model:ir.model,name:base_custom_info.model_custom_info_model_link -msgid "A model that gets its ``ir.model`` computed" -msgstr "" +#: model:ir.ui.view,arch_db:base_custom_info.custom_info_value_form +msgid "Warning!\n" +" You might see no changes in parent form until you save it." +msgstr "¡Aviso!\n" +" Puede no ver cambios en el formulario padre hasta que guarde." + +#. module: base_custom_info +#: model:ir.model.fields,help:base_custom_info.field_base_config_settings_group_custom_info_partner +msgid "Add a tab in the partners form to edit custom information" +msgstr "Añade una pestaña en el formulario de empresas para editar su inf. personalizada." + +#. module: base_custom_info +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_option_template_id +msgid "Additional template" +msgstr "Plantilla adicional" + +#. module: base_custom_info +#: model:ir.model.fields,help:base_custom_info.field_custom_info_option_template_id +msgid "Additional template to be applied to the owner if this option is chosen." +msgstr "Plantilla adicional a ser aplicada al propietario si esta opción se escoge." + +#. module: base_custom_info +#: model:ir.ui.menu,name:base_custom_info.menu_advanced +msgid "Advanced" +msgstr "Avanzado" + +#. module: base_custom_info +#: model:res.groups,name:base_custom_info.group_advanced +msgid "Advanced management" +msgstr "Gestión avanzada" + +#. module: base_custom_info +#: model:ir.model.fields,help:base_custom_info.field_base_config_settings_group_custom_info_manager +msgid "Allow all employees to manage custom information" +msgstr "Permitir a todos los empleados gestionar inf. personalizada." + +#. module: base_custom_info +#: model:custom.info.property,name:base_custom_info.prop_haters +msgid "Amount of people that hates him/her for being so smart" +msgstr "Cantidad de gente que lo odia por ser tan listo" #. module: base_custom_info #: sql_constraint:custom.info.value:0 @@ -38,12 +72,58 @@ msgstr "Ya existe otra propiedad con ese nombre en esa plantilla." msgid "Another template with that name exists for that model." msgstr "Ya existe otra plantilla con ese nombre para ese modelo." +#. module: base_custom_info +#: model:ir.model,name:base_custom_info.model_custom_info_option +msgid "Available options for a custom property" +msgstr "Opciones disponibles para una propiedad personalizada" + +#. module: base_custom_info +#: model:custom.info.property,name:base_custom_info.prop_avg_note +msgid "Average note on all subjects" +msgstr "Nota media en todas las materias" + +#. module: base_custom_info +#: model:ir.ui.menu,name:base_custom_info.menu_basic +msgid "Basic" +msgstr "Básico" + +#. module: base_custom_info +#: model:res.groups,name:base_custom_info.group_basic +msgid "Basic management" +msgstr "Gestión básica" + +#. module: base_custom_info +#: model:custom.info.option,name:base_custom_info.opt_cars +msgid "Cars" +msgstr "Coches" + +#. module: base_custom_info +#: model:ir.actions.act_window,name:base_custom_info.custom_info_category_action +#: model:ir.ui.menu,name:base_custom_info.menu_category +msgid "Categories" +msgstr "Categorías" + +#. module: base_custom_info +#: model:ir.model,name:base_custom_info.model_custom_info_category +msgid "Categorize custom info properties" +msgstr "Categorizar las propiedades de inf. personalizada" + +#. module: base_custom_info +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_property_category_id +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_value_category_id +#: model:ir.ui.view,arch_db:base_custom_info.custom_info_property_search +#: model:ir.ui.view,arch_db:base_custom_info.custom_info_value_search +msgid "Category" +msgstr "Categoría" + #. module: base_custom_info #: model:ir.actions.act_window,help:base_custom_info.custom_info_template_action msgid "Click to define a new custom info template." -msgstr "" +msgstr "Pulse para definir una nueva plantilla de inf. personalizada." #. module: base_custom_info +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_category_create_uid +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_option_create_uid #: model:ir.model.fields,field_description:base_custom_info.field_custom_info_property_create_uid #: model:ir.model.fields,field_description:base_custom_info.field_custom_info_template_create_uid #: model:ir.model.fields,field_description:base_custom_info.field_custom_info_value_create_uid @@ -51,66 +131,115 @@ msgid "Created by" msgstr "Creado por" #. module: base_custom_info +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_category_create_date +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_option_create_date #: model:ir.model.fields,field_description:base_custom_info.field_custom_info_property_create_date #: model:ir.model.fields,field_description:base_custom_info.field_custom_info_template_create_date #: model:ir.model.fields,field_description:base_custom_info.field_custom_info_value_create_date msgid "Created on" -msgstr "Creado el" +msgstr "Creado en" #. module: base_custom_info #: model:ir.ui.menu,name:base_custom_info.menu_base_custom_info msgid "Custom Info" -msgstr "Información personalizada" +msgstr "Inf. personalizada" + +#. module: base_custom_info +#: model:ir.ui.view,arch_db:base_custom_info.custom_info_category_tree +msgid "Custom Info Categories" +msgstr "Categorías de inf. personalizada" #. module: base_custom_info -#: model:ir.ui.view,arch_db:base_custom_info.base_custom_info_template_form +#: model:ir.ui.view,arch_db:base_custom_info.custom_info_option_tree +msgid "Custom Info Options" +msgstr "Opciones de inf. personalizada" + +#. module: base_custom_info +#: model:ir.ui.view,arch_db:base_custom_info.custom_info_property_tree +msgid "Custom Info Properties" +msgstr "Propiedades de inf. personalizada" + +#. module: base_custom_info +#: model:ir.ui.view,arch_db:base_custom_info.custom_info_template_form msgid "Custom Info Template" -msgstr "Plantilla de información personalizada" +msgstr "Plantilla de inf. personalizada" #. module: base_custom_info -#: model:ir.ui.view,arch_db:base_custom_info.base_custom_info_template_line_form +#: model:ir.ui.view,arch_db:base_custom_info.custom_info_category_form +#: model:ir.ui.view,arch_db:base_custom_info.custom_info_option_form +#: model:ir.ui.view,arch_db:base_custom_info.custom_info_property_form msgid "Custom Info Template Properties" -msgstr "Propiedades de la plantilla de información personalizada" +msgstr "Propiedades de la plantilla de inf. personalizada" #. module: base_custom_info -#: model:ir.ui.view,arch_db:base_custom_info.base_custom_info_template_line_tree -#: model:ir.ui.view,arch_db:base_custom_info.base_custom_info_template_tree +#: model:ir.ui.view,arch_db:base_custom_info.custom_info_template_tree msgid "Custom Info Templates" -msgstr "Plantillas de información personalizada" +msgstr "Plantillas de inf. personalizada" + +#. module: base_custom_info +#: model:ir.module.category,name:base_custom_info.category +#: model:ir.ui.view,arch_db:base_custom_info.view_general_configuration +#: model:ir.ui.view,arch_db:base_custom_info.view_partner_form +msgid "Custom Information" +msgstr "Inf. personalizada" #. module: base_custom_info #: model:ir.model.fields,field_description:base_custom_info.field_custom_info_custom_info_template_id +#: model:ir.model.fields,field_description:base_custom_info.field_res_partner_custom_info_template_id msgid "Custom Information Template" -msgstr "Plantilla de información personalizada" +msgstr "Plantilla de inf. personalizada" #. module: base_custom_info #: model:ir.model.fields,field_description:base_custom_info.field_custom_info_custom_info_ids +#: model:ir.model.fields,field_description:base_custom_info.field_res_partner_custom_info_ids msgid "Custom Properties" msgstr "Propiedades personalizadas" #. module: base_custom_info -#: model:ir.ui.view,arch_db:base_custom_info.base_custom_info_value_tree +#: model:ir.ui.view,arch_db:base_custom_info.custom_info_value_tree msgid "Custom Property Values" msgstr "Valores de las propiedades personalizadas" #. module: base_custom_info #: model:ir.model,name:base_custom_info.model_custom_info_property msgid "Custom information property" -msgstr "Propiedad de información personalizada" +msgstr "Propiedad de inf. personalizada" #. module: base_custom_info #: model:ir.model,name:base_custom_info.model_custom_info_template msgid "Custom information template" -msgstr "Plantilla de información personalizada" +msgstr "Plantilla de inf. personalizada" #. module: base_custom_info #: model:ir.model,name:base_custom_info.model_custom_info_value msgid "Custom information value" -msgstr "Valor de información personalizada" +msgstr "Valor de inf. personalizada" + +#. module: base_custom_info +#: selection:custom.info.property,field_type:0 +msgid "Decimal number" +msgstr "Número decimal" + +#. module: base_custom_info +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_value_value_float +msgid "Decimal number value" +msgstr "Valor del número decimal" + +#. module: base_custom_info +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_property_default_value +msgid "Default value" +msgstr "Valor por defecto" + +#. module: base_custom_info +#: code:addons/base_custom_info/models/custom_info_property.py:101 +#, python-format +msgid "Default value %s cannot be converted to type %s." +msgstr "El valor por defecto %s no se puede convertir al tipo %s." #. module: base_custom_info +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_category_display_name #: model:ir.model.fields,field_description:base_custom_info.field_custom_info_display_name -#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_model_link_display_name +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_option_display_name #: model:ir.model.fields,field_description:base_custom_info.field_custom_info_property_display_name #: model:ir.model.fields,field_description:base_custom_info.field_custom_info_template_display_name #: model:ir.model.fields,field_description:base_custom_info.field_custom_info_value_display_name @@ -118,29 +247,110 @@ msgid "Display Name" msgstr "Nombre mostrado" #. module: base_custom_info +#: model:res.groups,name:base_custom_info.group_partner +msgid "Display in partner form" +msgstr "Mostrar en el formulario de empresas" + +#. module: base_custom_info +#: model:custom.info.property,name:base_custom_info.prop_smartypants +msgid "Does he/she believe he/she is the smartest person on earth?" +msgstr "¿Se cree la persona más lista de la Tierra?" + +#. module: base_custom_info +#: model:ir.model.fields,field_description:base_custom_info.field_base_config_settings_group_custom_info_partner +msgid "Edit custom information in partners" +msgstr "Editar inf. personalizada en empresas" + +#. module: base_custom_info +#: model:custom.info.property,name:base_custom_info.prop_fav_game +msgid "Favourite videogame" +msgstr "Videojuego favorito" + +#. module: base_custom_info +#: model:custom.info.property,name:base_custom_info.prop_fav_genre +msgid "Favourite videogames genre" +msgstr "Género de videojuegos favorito" + +#. module: base_custom_info +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_value_field_name +msgid "Field name" +msgstr "Nombre del campo" + +#. module: base_custom_info +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_property_field_type +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_value_field_type +msgid "Field type" +msgstr "Tipo del campo" + +#. module: base_custom_info +#: model:ir.model.fields,help:base_custom_info.field_custom_info_property_maximum +msgid "For numeric fields, it means the maximum possible value; for text fields, it means the maximum possible length. If it is smaller than the minimum, then this check is skipped" +msgstr "Para campos numéricos, significa el valor máximo permitido; para campos de texto, significa la longitud máxima permitida. Si es menor que el mínimo, entonces esta comprobación se omite." + +#. module: base_custom_info +#: model:ir.model.fields,help:base_custom_info.field_custom_info_property_minimum +msgid "For numeric fields, it means the minimum possible value; for text fields, it means the minimum possible length. If it is bigger than the maximum, then this check is skipped" +msgstr "Para campos numéricos, significa el valor mínimo permitido; para campos de texto, significa la longitud mínima permitida. Si es mayor que el máximo, entonces esta comprobación se omite." + +#. module: base_custom_info +#: model:custom.info.template,name:base_custom_info.tpl_gamer +msgid "Gamers" +msgstr "Jugadores" + +#. module: base_custom_info +#: model:custom.info.category,name:base_custom_info.cat_gaming +msgid "Gaming" +msgstr "Juego" + +#. module: base_custom_info +#: model:custom.info.option,name:base_custom_info.opt_graphical_adventure +msgid "Graphical adventure" +msgstr "Aventura gráfica" + +#. module: base_custom_info +#: model:ir.ui.view,arch_db:base_custom_info.custom_info_property_search +#: model:ir.ui.view,arch_db:base_custom_info.custom_info_template_search +#: model:ir.ui.view,arch_db:base_custom_info.custom_info_value_search +msgid "Group By" +msgstr "Agrupar por" + +#. module: base_custom_info +#: model:custom.info.option,name:base_custom_info.opt_glasses +#: model:custom.info.property,default_value:base_custom_info.prop_weaknesses +msgid "Huge glasses" +msgstr "Gafas gigantes" + +#. module: base_custom_info +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_category_id #: model:ir.model.fields,field_description:base_custom_info.field_custom_info_id -#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_model_link_id +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_option_id #: model:ir.model.fields,field_description:base_custom_info.field_custom_info_property_id #: model:ir.model.fields,field_description:base_custom_info.field_custom_info_template_id #: model:ir.model.fields,field_description:base_custom_info.field_custom_info_value_id msgid "ID" -msgstr "ID" +msgstr "ID (identificación)" #. module: base_custom_info -#: model:ir.ui.view,arch_db:base_custom_info.base_custom_info_template_form -msgid "Info Lines" -msgstr "Líneas de información" +#: code:addons/base_custom_info/models/custom_info_property.py:111 +#, python-format +msgid "If you require a Yes/No field, you can only set Yes." +msgstr "Si requiere un campo Sí/No, sólo podrá escoger Sí." + +#. module: base_custom_info +#: code:addons/base_custom_info/models/custom_info_property.py:114 +#, python-format +msgid "If you require a numeric field, you cannot set it to zero." +msgstr "Si requiere un campo numérico, no podrá ponerlo a cero." #. module: base_custom_info #: model:ir.model,name:base_custom_info.model_custom_info msgid "Inheritable abstract model to add custom info in any model" -msgstr "" -"Modelo abstracto que se puede heredar para añadir información personalizada " -"a cualquier modelo" +msgstr "Modelo abstracto que se puede heredar para añadir inf. personalizada a cualquier modelo" #. module: base_custom_info #: model:ir.model.fields,field_description:base_custom_info.field_custom_info___last_update -#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_model_link___last_update +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_category___last_update +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_option___last_update #: model:ir.model.fields,field_description:base_custom_info.field_custom_info_property___last_update #: model:ir.model.fields,field_description:base_custom_info.field_custom_info_template___last_update #: model:ir.model.fields,field_description:base_custom_info.field_custom_info_value___last_update @@ -148,30 +358,65 @@ msgid "Last Modified on" msgstr "Última modificación en" #. module: base_custom_info +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_category_write_uid +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_option_write_uid #: model:ir.model.fields,field_description:base_custom_info.field_custom_info_property_write_uid #: model:ir.model.fields,field_description:base_custom_info.field_custom_info_template_write_uid #: model:ir.model.fields,field_description:base_custom_info.field_custom_info_value_write_uid msgid "Last Updated by" -msgstr "Última actualización por" +msgstr "Última actualización de" #. module: base_custom_info +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_category_write_date +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_option_write_date #: model:ir.model.fields,field_description:base_custom_info.field_custom_info_property_write_date #: model:ir.model.fields,field_description:base_custom_info.field_custom_info_template_write_date #: model:ir.model.fields,field_description:base_custom_info.field_custom_info_value_write_date msgid "Last Updated on" -msgstr "Última actualización el" +msgstr "Última actualización en" + +#. module: base_custom_info +#: code:addons/base_custom_info/models/custom_info_value.py:152 +#, python-format +msgid "Length for %(prop)s is %(val)s, but it should be between %(min)d and %(max)d." +msgstr "La longitud de %(prop)s es %(val)s, pero debería estar entre %(min)d y %(max)d." + +#. module: base_custom_info +#: model:custom.info.option,name:base_custom_info.opt_food +msgid "Loves junk food" +msgstr "Le encanta la comida basura" + +#. module: base_custom_info +#: model:ir.model.fields,field_description:base_custom_info.field_base_config_settings_group_custom_info_manager +msgid "Manage custom information" +msgstr "Gestionar inf. personalizada" + +#. module: base_custom_info +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_property_maximum +msgid "Maximum" +msgstr "Máximo" + +#. module: base_custom_info +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_property_minimum +msgid "Minimum" +msgstr "Mínimo" #. module: base_custom_info -#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_model_link_model -#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_model_link_model_id -#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_template_model #: model:ir.model.fields,field_description:base_custom_info.field_custom_info_template_model_id -#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_value_model -#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_value_model_id +#: model:ir.ui.view,arch_db:base_custom_info.custom_info_template_search msgid "Model" msgstr "Modelo" #. module: base_custom_info +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_property_model +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_template_model +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_value_model +msgid "Model technical name" +msgstr "Nombre técnico del modelo" + +#. module: base_custom_info +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_category_name +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_option_name #: model:ir.model.fields,field_description:base_custom_info.field_custom_info_property_name #: model:ir.model.fields,field_description:base_custom_info.field_custom_info_template_name #: model:ir.model.fields,field_description:base_custom_info.field_custom_info_value_name @@ -179,14 +424,69 @@ msgid "Name" msgstr "Nombre" #. module: base_custom_info -#: model:ir.actions.act_window,name:base_custom_info.custom_info_template_line_action -#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_template_info_ids -#: model:ir.ui.menu,name:base_custom_info.menu_base_custom_info_template_line +#: model:custom.info.property,name:base_custom_info.prop_teacher +msgid "Name of his/her teacher" +msgstr "Nombre de su profesor" + +#. module: base_custom_info +#: model:custom.info.option,name:base_custom_info.opt_videogames +msgid "Needs videogames" +msgstr "Necesita videojuegos" + +#. module: base_custom_info +#: code:addons/base_custom_info/models/custom_info_value.py:123 +#: code:addons/base_custom_info/models/custom_info_value.py:215 +#, python-format +msgid "No" +msgstr "No" + +#. module: base_custom_info +#: model:ir.actions.act_window,name:base_custom_info.custom_info_option_action +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_property_option_ids +#: model:ir.ui.menu,name:base_custom_info.menu_option +#: model:ir.ui.view,arch_db:base_custom_info.custom_info_property_form +msgid "Options" +msgstr "Opciones" + +#. module: base_custom_info +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_value_owner_id +#: model:ir.ui.view,arch_db:base_custom_info.custom_info_value_search +msgid "Owner" +msgstr "Propietario" + +#. module: base_custom_info +#: model:ir.model,name:base_custom_info.model_res_partner +msgid "Partner" +msgstr "Empresa" + +#. module: base_custom_info +#: model:custom.info.option,name:base_custom_info.opt_platforms +msgid "Platforms" +msgstr "Plataformas" + +#. module: base_custom_info +#: model:ir.actions.act_window,name:base_custom_info.custom_info_property_action +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_category_property_ids +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_option_property_ids +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_template_property_ids +#: model:ir.ui.menu,name:base_custom_info.menu_property +#: model:ir.ui.view,arch_db:base_custom_info.custom_info_template_form msgid "Properties" msgstr "Propiedades" +#. module: base_custom_info +#: model:ir.model.fields,help:base_custom_info.field_custom_info_category_property_ids +msgid "Properties in this category." +msgstr "Propiedades en esta categoría." + +#. module: base_custom_info +#: model:ir.model.fields,help:base_custom_info.field_custom_info_option_property_ids +msgid "Properties where this option is enabled." +msgstr "Propiedades en las que esta opción está disponible." + #. module: base_custom_info #: model:ir.model.fields,field_description:base_custom_info.field_custom_info_value_property_id +#: model:ir.ui.view,arch_db:base_custom_info.custom_info_value_search msgid "Property" msgstr "Propiedad" @@ -195,13 +495,79 @@ msgstr "Propiedad" msgid "Property Values" msgstr "Valor de la propiedad" +#. module: base_custom_info +#: model:custom.info.option,name:base_custom_info.opt_rpg +msgid "RPG" +msgstr "RPG" + +#. module: base_custom_info +#: model:ir.model.fields,help:base_custom_info.field_custom_info_value_owner_id +msgid "Record that owns this custom value." +msgstr "Registro que posee este valor personalizado." + +#. module: base_custom_info +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_property_required +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_value_required +msgid "Required" +msgstr "Requerido" + #. module: base_custom_info #: model:ir.model.fields,field_description:base_custom_info.field_custom_info_value_res_id msgid "Resource ID" -msgstr "ID del recurso" +msgstr "ID del Recurso" + +#. module: base_custom_info +#: model:ir.ui.view,arch_db:base_custom_info.custom_info_property_form +msgid "Select one of the existing options or create a new one clicking on 'Add an item'" +msgstr "Seleccione una de la opciones existentes o cree una nueva pulsando en 'Añadir un elemento'" + +#. module: base_custom_info +#: selection:custom.info.property,field_type:0 +msgid "Selection" +msgstr "Selección" + +#. module: base_custom_info +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_value_value_id +msgid "Selection value" +msgstr "Valor de selección" + +#. module: base_custom_info +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_category_sequence +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_property_category_sequence +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_property_sequence +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_value_category_sequence +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_value_property_sequence +msgid "Sequence" +msgstr "Secuencia" + +#. module: base_custom_info +#: model:custom.info.option,name:base_custom_info.opt_shooter +msgid "Shooter" +msgstr "Shooter" + +#. module: base_custom_info +#: model:custom.info.template,name:base_custom_info.tpl_smart +msgid "Smart partners" +msgstr "Gente lista" + +#. module: base_custom_info +#: model:custom.info.category,name:base_custom_info.cat_statics +msgid "Statics" +msgstr "Statics" + +#. module: base_custom_info +#: model:custom.info.option,name:base_custom_info.opt_strategy +msgid "Strategy" +msgstr "Estrategia" + +#. module: base_custom_info +#: model:ir.model.fields,help:base_custom_info.field_custom_info_value_field_name +msgid "Technical name of the field where the value is stored." +msgstr "Nombre técnico del campo donde se guarda este valor" #. module: base_custom_info #: model:ir.model.fields,field_description:base_custom_info.field_custom_info_property_template_id +#: model:ir.ui.view,arch_db:base_custom_info.custom_info_property_search msgid "Template" msgstr "Plantilla" @@ -211,20 +577,125 @@ msgstr "Plantilla" msgid "Templates" msgstr "Plantillas" +#. module: base_custom_info +#: selection:custom.info.property,field_type:0 +msgid "Text" +msgstr "Texto" + +#. module: base_custom_info +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_value_value_str +msgid "Text value" +msgstr "Valor de texto" + +#. module: base_custom_info +#: model:res.groups,comment:base_custom_info.group_advanced +msgid "The user will be able to manage advanced custom information." +msgstr "El usuario tendrá acceso a una gestión avanzada de la inf. personalizada." + +#. module: base_custom_info +#: model:res.groups,comment:base_custom_info.group_basic +msgid "The user will be able to manage basic custom information." +msgstr "El usuario tendrá acceso a una gestión básica de la inf. personalizada." + +#. module: base_custom_info +#: model:ir.model.fields,help:base_custom_info.field_custom_info_property_field_type +#: model:ir.model.fields,help:base_custom_info.field_custom_info_value_field_type +msgid "Type of information that can be stored in the property." +msgstr "Tipo de información que se puede almacenar en esta propiedad." + #. module: base_custom_info #: model:ir.model.fields,field_description:base_custom_info.field_custom_info_value_value msgid "Value" msgstr "Valor" +#. module: base_custom_info +#: code:addons/base_custom_info/models/custom_info_value.py:158 +#, python-format +msgid "Value for %(prop)s is %(val)s, but it should be between %(min)d and %(max)d." +msgstr "El valor de %(prop)s es %(val)s, pero debería estar entre %(min)d y %(max)d." + +#. module: base_custom_info +#: code:addons/base_custom_info/models/custom_info_value.py:162 +#, python-format +msgid "Value for %(prop)s is %(val)s, but it should be between %(min)f and %(max)f." +msgstr "El valor de %(prop)s es %(val)s, pero debería estar entre %(min)f y %(max)f." + +#. module: base_custom_info +#: model:ir.model.fields,help:base_custom_info.field_custom_info_value_value +msgid "Value, always converted to/from the typed field." +msgstr "Valor, siempre convertido del/al campo tipado." + #. module: base_custom_info #: model:ir.actions.act_window,name:base_custom_info.custom_info_value_action +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_option_value_ids #: model:ir.ui.menu,name:base_custom_info.menu_base_custom_info_value msgid "Values" msgstr "Valores" +#. module: base_custom_info +#: model:ir.model.fields,help:base_custom_info.field_custom_info_option_value_ids +msgid "Values that have set this option." +msgstr "Valores que han escogido esta opción." + +#. module: base_custom_info +#: model:custom.info.property,name:base_custom_info.prop_weaknesses +msgid "What weaknesses does he/she have?" +msgstr "¿Qué debilidades tiene?" + +#. module: base_custom_info +#: model:ir.model.fields,help:base_custom_info.field_custom_info_property_option_ids +msgid "When the field type is 'selection', choose the available options here." +msgstr "Cuando el tipo de campo es 'selección', escoja las opciones disponibles aquí." + +#. module: base_custom_info +#: selection:custom.info.property,field_type:0 +msgid "Whole number" +msgstr "Número entero" + +#. module: base_custom_info +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_value_value_int +msgid "Whole number value" +msgstr "Valor del número entero" + +#. module: base_custom_info +#: model:res.groups,comment:base_custom_info.group_partner +msgid "Will be able to edit custom information from partner's form." +msgstr "Podrá editar inf. personalizada en el formulario de empresa." + +#. module: base_custom_info +#: model:ir.model.fields,help:base_custom_info.field_custom_info_property_default_value +msgid "Will be applied by default to all custom values of this property. This is a char field, so you have to enter some value that can be converted to the field type you choose." +msgstr "Se aplicará por defecto a todos los valores personalizados de esta propiedad. Este campo es de texto, así que tiene que introducir un valor que se pueda convertir al tipo de campo que ha escogido." + +#. module: base_custom_info +#: code:addons/base_custom_info/models/custom_info_value.py:123 +#, python-format +msgid "Yes" +msgstr "Sí" + +#. module: base_custom_info +#: selection:custom.info.property,field_type:0 +msgid "Yes/No" +msgstr "Sí/No" + +#. module: base_custom_info +#: model:ir.model.fields,field_description:base_custom_info.field_custom_info_value_value_bool +msgid "Yes/No value" +msgstr "Valor sí/no" + +#. module: base_custom_info +#: code:addons/base_custom_info/models/custom_info_template.py:66 +#, python-format +msgid "You cannot change the model because it is in use." +msgstr "No puede cambiar el modelo porque ya se está usando." + #. module: base_custom_info #: model:ir.actions.act_window,help:base_custom_info.custom_info_template_action -msgid "" -"You must define a custom info template for each\n" -" product properties group." -msgstr "" +msgid "You must define a custom info template for each properties group." +msgstr "Debe definir una plantilla de inf. personalizada por cada grupo de propiedades." + +#. module: base_custom_info +#: model:ir.model,name:base_custom_info.model_base_config_settings +msgid "base.config.settings" +msgstr "base.config.settings" + diff --git a/base_custom_info/static/description/customizations-everywhere.jpg b/base_custom_info/images/customizations-everywhere.jpg similarity index 100% rename from base_custom_info/static/description/customizations-everywhere.jpg rename to base_custom_info/images/customizations-everywhere.jpg diff --git a/base_custom_info/static/description/templateception.jpg b/base_custom_info/images/templateception.jpg similarity index 100% rename from base_custom_info/static/description/templateception.jpg rename to base_custom_info/images/templateception.jpg diff --git a/base_custom_info/models/custom_info.py b/base_custom_info/models/custom_info.py index 45c70e963..96617453a 100644 --- a/base_custom_info/models/custom_info.py +++ b/base_custom_info/models/custom_info.py @@ -1,14 +1,15 @@ # -*- coding: utf-8 -*- -# © 2015 Antiun Ingeniería S.L. - Sergio Teruel -# © 2015 Antiun Ingeniería S.L. - Carlos Dauden -# © 2016 Jairo Llopis +# Copyright 2015 Sergio Teruel +# Copyright 2015 Carlos Dauden +# Copyright 2016 Jairo Llopis +# Copyright 2017 Pedro M. Baeza # License LGPL-3 - See http://www.gnu.org/licenses/lgpl-3.0.html from openerp import api, fields, models class CustomInfo(models.AbstractModel): - """Models that inherit this one will get custom information for free! + """Models that inherit from this one will get custom information for free! They will probably want to declare a default model in the context of the :attr:`custom_info_template_id` field. @@ -21,54 +22,64 @@ class CustomInfo(models.AbstractModel): custom_info_template_id = fields.Many2one( comodel_name='custom.info.template', domain=lambda self: [("model", "=", self._name)], - string='Custom Information Template') + string='Custom Information Template', + ) custom_info_ids = fields.One2many( - comodel_name='custom.info.value', - inverse_name='res_id', + comodel_name='custom.info.value', inverse_name='res_id', domain=lambda self: [("model", "=", self._name)], - context={"embed": True}, - auto_join=True, - string='Custom Properties') - dirty_templates = fields.Boolean( - compute="_compute_dirty_templates", + auto_join=True, string='Custom Properties', ) - # HACK https://github.com/odoo/odoo/pull/11042 - @api.model - def create(self, vals): - res = super(CustomInfo, self).create(vals) - if not self.env.context.get("filling_templates"): - res.filtered( - "dirty_templates").action_custom_info_templates_fill() - return res - - # HACK https://github.com/odoo/odoo/pull/11042 + # HACK: Until https://github.com/odoo/odoo/pull/10557 is merged + # https://github.com/OCA/server-tools/pull/492#issuecomment-237594285 @api.multi - def write(self, vals): - res = super(CustomInfo, self).write(vals) - if not self.env.context.get("filling_templates"): - self.filtered( - "dirty_templates").action_custom_info_templates_fill() - return res + def onchange(self, values, field_name, field_onchange): # pragma: no cover + x2many_field = 'custom_info_ids' + if x2many_field in field_onchange: + subfields = getattr(self, x2many_field)._fields.keys() + for subfield in subfields: + field_onchange.setdefault( + "{}.{}".format(x2many_field, subfield), u"", + ) + return super(CustomInfo, self).onchange( + values, field_name, field_onchange, + ) + + @api.onchange('custom_info_template_id') + def _onchange_custom_info_template_id(self): + tmpls = self.all_custom_info_templates() + props_good = tmpls.mapped("property_ids") + props_enabled = self.mapped("custom_info_ids.property_id") + to_add = props_good - props_enabled + to_remove = props_enabled - props_good + values = self.custom_info_ids + values = values.filtered(lambda r: r.property_id not in to_remove) + for prop in to_add.sorted(): + newvalue = self.custom_info_ids.new({ + "property_id": prop.id, + "res_id": self.id, + "value": prop.default_value, + }) + # HACK https://github.com/odoo/odoo/issues/13076 + newvalue._inverse_value() + newvalue._compute_value() + values += newvalue + self.custom_info_ids = values + # Default values implied new templates? Then this is recursive + if self.all_custom_info_templates() != tmpls: + self._onchange_custom_info_template_id() @api.multi def unlink(self): + """Remove linked custom info this way, as can't be handled + automatically. + """ info_values = self.mapped('custom_info_ids') res = super(CustomInfo, self).unlink() if res: info_values.unlink() return res - @api.one - @api.depends("custom_info_template_id", - "custom_info_ids.value_id.template_id") - def _compute_dirty_templates(self): - """Know if you need to reload the templates.""" - expected_properties = self.all_custom_info_templates().mapped( - "property_ids") - actual_properties = self.mapped("custom_info_ids.property_id") - self.dirty_templates = expected_properties != actual_properties - @api.multi @api.returns("custom.info.value") def get_custom_info_value(self, properties): @@ -84,38 +95,3 @@ class CustomInfo(models.AbstractModel): """Get all custom info templates involved in these owners.""" return (self.mapped("custom_info_template_id") | self.mapped("custom_info_ids.value_id.template_id")) - - @api.multi - def action_custom_info_templates_fill(self): - """Fill values with enabled custom info templates.""" - recursive_owners = self - for owner in self.with_context(filling_templates=True): - values = owner.custom_info_ids - tpls = owner.all_custom_info_templates() - props_good = tpls.mapped("property_ids") - props_enabled = owner.mapped("custom_info_ids.property_id") - to_add = props_good - props_enabled - to_rm = props_enabled - props_good - # Remove remaining properties - # HACK https://github.com/odoo/odoo/pull/13480 - values.filtered(lambda r: r.property_id in to_rm).unlink() - values = values.exists() - # Add new properties - for prop in to_add: - newvalue = values.new({ - "property_id": prop.id, - "res_id": owner.id, - }) - newvalue._onchange_property_set_default_value() - # HACK https://github.com/odoo/odoo/issues/13076 - newvalue._inverse_value() - newvalue._compute_value() - values |= newvalue - owner.custom_info_ids = values - # Default values implied new templates? Then this is recursive - if owner.all_custom_info_templates() == tpls: - recursive_owners -= owner - # Changes happened under a different environment; update own - self.invalidate_cache() - if recursive_owners: - return recursive_owners.action_custom_info_templates_fill() diff --git a/base_custom_info/models/custom_info_option.py b/base_custom_info/models/custom_info_option.py index 6e20d94bd..a8ad2e95e 100644 --- a/base_custom_info/models/custom_info_option.py +++ b/base_custom_info/models/custom_info_option.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- -# © 2016 Jairo Llopis +# Copyright 2016 Jairo Llopis +# Copyright 2017 Pedro M. Baeza # License LGPL-3 - See http://www.gnu.org/licenses/lgpl-3.0.html from openerp import api, fields, models diff --git a/base_custom_info/models/custom_info_property.py b/base_custom_info/models/custom_info_property.py index 67917cff3..a05b4d8a2 100644 --- a/base_custom_info/models/custom_info_property.py +++ b/base_custom_info/models/custom_info_property.py @@ -1,6 +1,8 @@ # -*- coding: utf-8 -*- -# © 2016 Jairo Llopis +# Copyright 2016 Jairo Llopis +# Copyright 2017 Pedro M. Baeza # License LGPL-3 - See http://www.gnu.org/licenses/lgpl-3.0.html + from openerp import _, api, fields, models from openerp.exceptions import UserError, ValidationError @@ -28,13 +30,11 @@ class CustomInfoProperty(models.Model): readonly=True, ) template_id = fields.Many2one( - comodel_name='custom.info.template', - string='Template', - required=True) + comodel_name='custom.info.template', string='Template', + required=True, ondelete="cascade", + ) model = fields.Char( - related="template_id.model", - readonly=True, - auto_join=True, + related="template_id.model", readonly=True, auto_join=True, ) info_value_ids = fields.One2many( comodel_name="custom.info.value", diff --git a/base_custom_info/models/custom_info_template.py b/base_custom_info/models/custom_info_template.py index 16e814e0e..57ece627f 100644 --- a/base_custom_info/models/custom_info_template.py +++ b/base_custom_info/models/custom_info_template.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- -# © 2016 Jairo Llopis +# Copyright 2016 Jairo Llopis +# Copyright 2017 Pedro M. Baeza # License LGPL-3 - See http://www.gnu.org/licenses/lgpl-3.0.html from openerp import _, api, fields, models @@ -13,57 +14,63 @@ class CustomInfoTemplate(models.Model): _order = "model_id, name" _sql_constraints = [ ("name_model", - "UNIQUE (name, model)", + "UNIQUE (name, model_id)", "Another template with that name exists for that model."), ] name = fields.Char(required=True, translate=True) model = fields.Char( - index=True, - readonly=True, - required=True) + string="Model technical name", inverse="_inverse_model", + compute="_compute_model", search="_search_model" + ) model_id = fields.Many2one( - 'ir.model', - 'Model', - compute="_compute_model_id", - store=True, - ondelete="cascade", + comodel_name='ir.model', string='Model', ondelete="restrict", + required=True, auto_join=True, ) property_ids = fields.One2many( - 'custom.info.property', - 'template_id', - 'Properties', - oldname="info_ids", - context={"embed": True}, + comodel_name='custom.info.property', inverse_name='template_id', + string='Properties', oldname="info_ids", ) @api.multi - @api.depends("model") - def _compute_model_id(self): - """Get a related model from its name, for better UI.""" - for s in self: - s.model_id = self.env["ir.model"].search([("model", "=", s.model)]) + @api.depends("model_id") + def _compute_model(self): + for r in self: + r.model = r.model_id.model + + @api.multi + def _inverse_model(self): + for r in self: + r.model_id = self.env["ir.model"].search([("model", "=", r.model)]) + + @api.model + def _search_model(self, operator, value): + models = self.env['ir.model'].search([('model', operator, value)]) + return [('model_id', 'in', models.ids)] + + @api.onchange('model') + def _onchange_model(self): + self._inverse_model() @api.multi - @api.constrains("model") + @api.constrains("model_id") def _check_model(self): - """Ensure model exists.""" - for s in self: - if s.model not in self.env: - raise ValidationError(_("Model does not exist.")) - # Avoid error when updating base module and a submodule extends a - # model that falls out of this one's dependency graph + """Avoid error when updating base module and a submodule extends a + model that falls out of this one's dependency graph. + """ + for record in self: with self.env.norecompute(): - oldmodels = set(s.mapped("property_ids.info_value_ids.model")) - if oldmodels and {s.model} != oldmodels: + oldmodels = record.mapped("property_ids.info_value_ids.model") + if oldmodels and record.model not in oldmodels: raise ValidationError( - _("You cannot change the model because it is in use.")) + _("You cannot change the model because it is in use.") + ) @api.multi def check_access_rule(self, operation): """You access a template if you access its model.""" - for s in self: - model = self.env[s.model] + for record in self: + model = self.env[record.model_id.model or record.model] model.check_access_rights(operation) model.check_access_rule(operation) return super(CustomInfoTemplate, self).check_access_rule(operation) diff --git a/base_custom_info/models/custom_info_value.py b/base_custom_info/models/custom_info_value.py index a7cd143a8..b09d4c993 100644 --- a/base_custom_info/models/custom_info_value.py +++ b/base_custom_info/models/custom_info_value.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- -# © 2016 Jairo Llopis +# Copyright 2016 Jairo Llopis +# Copyright 2017 Pedro M. Baeza # License LGPL-3 - See http://www.gnu.org/licenses/lgpl-3.0.html from openerp import _, api, fields, models, SUPERUSER_ID from openerp.exceptions import ValidationError @@ -19,117 +20,63 @@ class CustomInfoValue(models.Model): ] model = fields.Char( - related="property_id.model", - index=True, - readonly=True, - auto_join=True, - store=True, + related="property_id.model", index=True, readonly=True, + auto_join=True, store=True, ) owner_id = fields.Reference( - selection="_selection_owner_id", - string="Owner", - compute="_compute_owner_id", - inverse="_inverse_owner_id", + selection="_selection_owner_id", string="Owner", + compute="_compute_owner_id", inverse="_inverse_owner_id", help="Record that owns this custom value.", ) res_id = fields.Integer( - "Resource ID", - required=True, - index=True, - store=True, + string="Resource ID", required=True, index=True, store=True, ondelete="cascade", ) property_id = fields.Many2one( - comodel_name='custom.info.property', - required=True, - string='Property') - property_sequence = fields.Integer( - related="property_id.sequence", - store=True, - index=True, + comodel_name='custom.info.property', required=True, string='Property', readonly=True, ) + property_sequence = fields.Integer( + related="property_id.sequence", store=True, index=True, readonly=True, + ) category_sequence = fields.Integer( - related="property_id.category_id.sequence", - store=True, - readonly=True, + related="property_id.category_id.sequence", store=True, readonly=True, ) category_id = fields.Many2one( - related="property_id.category_id", - store=True, - readonly=True, + related="property_id.category_id", store=True, readonly=True, ) name = fields.Char(related='property_id.name', readonly=True) - field_type = fields.Selection(related="property_id.field_type") + field_type = fields.Selection( + related="property_id.field_type", readonly=True, + ) field_name = fields.Char( compute="_compute_field_name", help="Technical name of the field where the value is stored.", ) - required = fields.Boolean(related="property_id.required") + required = fields.Boolean(related="property_id.required", readonly=True) value = fields.Char( - compute="_compute_value", - inverse="_inverse_value", + compute="_compute_value", inverse="_inverse_value", search="_search_value", help="Value, always converted to/from the typed field.", ) - value_str = fields.Char( - string="Text value", - translate=True, - index=True, - ) - value_int = fields.Integer( - string="Whole number value", - index=True, - ) - value_float = fields.Float( - string="Decimal number value", - index=True, - ) - value_bool = fields.Boolean( - string="Yes/No value", - index=True, - ) + value_str = fields.Char(string="Text value", translate=True, index=True) + value_int = fields.Integer(string="Whole number value", index=True) + value_float = fields.Float(string="Decimal number value", index=True) + value_bool = fields.Boolean(string="Yes/No value", index=True) value_id = fields.Many2one( - comodel_name="custom.info.option", - string="Selection value", - ondelete="cascade", - domain="[('property_ids', 'in', [property_id])]", + comodel_name="custom.info.option", string="Selection value", + ondelete="cascade", domain="[('property_ids', 'in', [property_id])]", ) @api.multi def check_access_rule(self, operation): - """You access a value if you access its property and owner record.""" - if self.env.uid == SUPERUSER_ID: - return - for s in self: - s.property_id.check_access_rule(operation) - s.owner_id.check_access_rights(operation) - s.owner_id.check_access_rule(operation) + """You access a value if you access its owner record.""" + if self.env.uid != SUPERUSER_ID: + for record in self.filtered('owner_id'): + record.owner_id.check_access_rights(operation) + record.owner_id.check_access_rule(operation) return super(CustomInfoValue, self).check_access_rule(operation) - @api.model - def create(self, vals): - """Skip constrains in 1st lap. Update owner templates.""" - # HACK https://github.com/odoo/odoo/pull/13439 - if "value" in vals: - self.env.context.skip_required = True - result = super(CustomInfoValue, self).create(vals) - # HACK https://github.com/odoo/odoo/pull/11042 - if not self.env.context.get("filling_templates"): - result.owner_id.exists().filtered("dirty_templates") \ - .action_custom_info_templates_fill() - return result - - # HACK https://github.com/odoo/odoo/pull/11042 - @api.multi - def write(self, vals): - """Update owner templates.""" - result = super(CustomInfoValue, self).write(vals) - if not self.env.context.get("filling_templates"): - self.mapped("owner_id").exists().filtered("dirty_templates") \ - .action_custom_info_templates_fill() - return result - @api.model def _selection_owner_id(self): """You can choose among models linked to a template.""" @@ -154,15 +101,15 @@ class CustomInfoValue(models.Model): @api.depends("res_id", "model") def _compute_owner_id(self): """Get the id from the linked record.""" - for s in self: - s.owner_id = "{},{}".format(s.model, s.res_id) + for record in self: + record.owner_id = "{},{}".format(record.model, record.res_id) @api.multi def _inverse_owner_id(self): """Store the owner according to the model and ID.""" - for s in self: - s.model = s.owner_id._name - s.res_id = s.owner_id.id + for record in self.filtered('owner_id'): + record.model = record.owner_id._name + record.res_id = record.owner_id.id @api.multi @api.depends("property_id.field_type", "field_name", "value_str", @@ -171,7 +118,7 @@ class CustomInfoValue(models.Model): """Get the value as a string, from the original field.""" for s in self: if s.field_type == "id": - s.value = ", ".join(s.value_id.mapped("display_name")) + s.value = s.value_id.display_name elif s.field_type == "bool": s.value = _("Yes") if s.value_bool else _("No") else: @@ -180,33 +127,19 @@ class CustomInfoValue(models.Model): @api.multi def _inverse_value(self): """Write the value correctly converted in the typed field.""" - for s in self: - s[s.field_name] = self._transform_value( - s.value, s.field_type, s.property_id) - - @api.one - @api.constrains("required", "field_name", "value_str", "value_int", - "value_float", "value_bool", "value_id") - def _check_required(self): - """Ensure required fields are filled""" - # HACK https://github.com/odoo/odoo/pull/13439 - try: - del self.env.context.skip_required - except AttributeError: - if (not self.env.context.get("filling_templates") and - self.required and not self[self.field_name]): - raise ValidationError( - _("Property %s is required.") % - self.property_id.display_name) + for record in self: + if (record.field_type == "id" and + record.value == record.value_id.display_name): + # Avoid another search that can return a different value + continue + record[record.field_name] = self._transform_value( + record.value, record.field_type, record.property_id, + ) @api.one - @api.constrains("property_id", "field_type", "field_name", - "value_str", "value_int", "value_float") + @api.constrains("property_id", "value_str", "value_int", "value_float") def _check_min_max_limits(self): """Ensure value falls inside the property's stablished limits.""" - # Skip constraint while filling the partner template - if self.env.context.get("filling_templates"): - return minimum, maximum = self.property_id.minimum, self.property_id.maximum if minimum <= maximum: value = self[self.field_name] @@ -246,6 +179,12 @@ class CustomInfoValue(models.Model): if not record.value and record.property_id.default_value: record.value = record.property_id.default_value + @api.onchange('value') + def _onchange_value(self): + """Inverse function is not launched after writing, so we need to + trigger it right now.""" + self._inverse_value() + @api.model def _transform_value(self, value, format_, properties=None): """Transforms a text value to the expected format. @@ -266,10 +205,10 @@ class CustomInfoValue(models.Model): if not value: value = False elif format_ == "id" and properties: - value = self.env["custom.info.option"].search( - [("property_ids", "in", properties.ids), - ("name", "=ilike", value)]) - value.ensure_one() + value = self.env["custom.info.option"].search([ + ("property_ids", "in", properties.ids), + ("name", "ilike", u"%{}%".format(value)), + ], limit=1) elif format_ == "bool": value = value.strip().lower() not in { "0", "false", "", "no", "off", _("No").lower()} diff --git a/base_custom_info/models/res_partner.py b/base_custom_info/models/res_partner.py index cc431bfbf..1f0a562b6 100644 --- a/base_custom_info/models/res_partner.py +++ b/base_custom_info/models/res_partner.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- # Copyright 2016 Jairo Llopis +# Copyright 2017 Pedro M. Baeza # License LGPL-3 - See http://www.gnu.org/licenses/lgpl-3.0.html from openerp import fields, models @@ -14,9 +15,5 @@ class ResPartner(models.Model): _name = "res.partner" _inherit = [_name, "custom.info"] - custom_info_template_id = fields.Many2one( - context={"default_model": _name}, - ) - custom_info_ids = fields.One2many( - context={"default_model": _name}, - ) + custom_info_template_id = fields.Many2one(context={"default_model": _name}) + custom_info_ids = fields.One2many(context={"default_model": _name}) diff --git a/base_custom_info/static/description/icon.png b/base_custom_info/static/description/icon.png index 896696e43b57a353305958c411a62b42430697d3..cc64c001a82d7f7128de843860f8f57b1f39aef6 100644 GIT binary patch delta 4054 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 literal 5289 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 r>88k + + + inkscape:export-xdpi="192" + inkscape:export-ydpi="192"> + id="metadata8"> image/svg+xml - + + id="defs6" /> + + + transform="matrix(0.3061173,0,0,0.3061173,-1.0360053,-1.0457906)" + style="fill:#ffffff;stroke:none"> + d="m 63.145923,117.98015 9.436965,0 0,-9.43697 -9.436965,0 m 4.718483,61.34028 c -20.808512,0 -37.747871,-16.93935 -37.747871,-37.74786 0,-20.80852 16.939359,-37.747875 37.747871,-37.747875 20.808514,0 37.747864,16.939355 37.747864,37.747875 0,20.80851 -16.93935,37.74786 -37.747864,37.74786 m 0,-84.932702 A 47.18484,47.18484 0 0 0 20.679568,132.1356 47.18484,47.18484 0 0 0 67.864406,179.32044 47.18484,47.18484 0 0 0 115.04924,132.1356 47.18484,47.18484 0 0 0 67.864406,84.950758 m -4.718483,70.777262 9.436965,0 0,-28.31091 -9.436965,0 0,28.31091 z" + style="fill:#ffffff;stroke:none" /> diff --git a/base_custom_info/tests/test_partner.py b/base_custom_info/tests/test_partner.py index 9105586e7..21cfafb3a 100644 --- a/base_custom_info/tests/test_partner.py +++ b/base_custom_info/tests/test_partner.py @@ -162,28 +162,3 @@ class PartnerCase(TransactionCase): self.env.ref("base_custom_info.prop_avg_note")) with self.assertRaises(ValidationError): val.value = "11" - - def test_dirty_templates_setting_tpl(self): - """If you set a template, it gets dirty.""" - with self.env.do_in_onchange(): - self.assertFalse(self.agrolait.dirty_templates) - self.agrolait.custom_info_template_id = self.tpl - self.assertTrue(self.agrolait.dirty_templates) - - def test_dirty_templates_removing_tpl(self): - """If you remove a template, it gets dirty.""" - self.agrolait.custom_info_template_id = self.tpl - with self.env.do_in_onchange(): - self.assertFalse(self.agrolait.dirty_templates) - self.agrolait.custom_info_template_id = False - self.assertTrue(self.agrolait.dirty_templates) - - def test_dirty_templates_choosing_option(self): - """If you choose an option with an extra template, it gets dirty.""" - self.agrolait.custom_info_template_id = self.tpl - with self.env.do_in_onchange(): - self.assertFalse(self.agrolait.dirty_templates) - val = self.agrolait.get_custom_info_value( - self.env.ref("base_custom_info.prop_weaknesses")) - val.value_id = self.env.ref("base_custom_info.opt_videogames") - self.assertTrue(self.agrolait.dirty_templates) diff --git a/base_custom_info/views/custom_info_category_view.xml b/base_custom_info/views/custom_info_category_view.xml index d9b5a7355..3c601d9bb 100644 --- a/base_custom_info/views/custom_info_category_view.xml +++ b/base_custom_info/views/custom_info_category_view.xml @@ -3,51 +3,48 @@ License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). --> - - Custom Info Category Tree - custom.info.category - - - - - - - - + + custom.info.category + + + + + + + + - - Custom Info Category Form - custom.info.category - -
- - - - - - - -
-
-
+ + custom.info.category + +
+ + + + + + + +
+
+
- - Custom Info Category Search - custom.info.category - - - - - - - + + custom.info.category + + + + + + + - - Categories - ir.actions.act_window - custom.info.category - tree,form - form - + + Categories + ir.actions.act_window + custom.info.category + tree,form + form +
diff --git a/base_custom_info/views/custom_info_option_view.xml b/base_custom_info/views/custom_info_option_view.xml index 3ac65804c..ca204523f 100644 --- a/base_custom_info/views/custom_info_option_view.xml +++ b/base_custom_info/views/custom_info_option_view.xml @@ -1,54 +1,79 @@ - - Custom Info Option Tree - custom.info.option - - - - - - - - + + custom.info.option + + + + + + + + + - - Custom Info Option Form - custom.info.option - -
- - - - - - - - -
-
-
+ + custom.info.option + + primary + + + + + + + + + - - Custom Info Option Search - custom.info.option - - - - - - - + + custom.info.option + + +
+ + + + + + + +
+
+
- - Options - ir.actions.act_window - custom.info.option - tree,form - form - + + custom.info.option + + primary + + + + + + + + + + custom.info.option + + + + + + + + + + Options + ir.actions.act_window + custom.info.option + tree,form + form +
diff --git a/base_custom_info/views/custom_info_property_view.xml b/base_custom_info/views/custom_info_property_view.xml index 71a14f6a4..39d446f6d 100644 --- a/base_custom_info/views/custom_info_property_view.xml +++ b/base_custom_info/views/custom_info_property_view.xml @@ -1,84 +1,105 @@ - - Custom Info Property Tree - custom.info.property - - - - - - - - - - - - + + custom.info.property + + + + + + + + + + + + - - Custom Info Property Form - custom.info.property - -
- - - - - - - - - - - - - - - - -
-
-
+ + custom.info.property + + primary + + + + + + + + + custom.info.property + + +
+ + + + + + + + + + + + + + + +
+
+
- - Custom Info Property Search - custom.info.property - - - - - - - - - - - - - - - + + custom.info.property + + primary + + + + + + + + + custom.info.property + + + + + + + + + + + + + + + - - Properties - ir.actions.act_window - custom.info.property - tree,form - form - + + Properties + ir.actions.act_window + custom.info.property + tree,form + form +
diff --git a/base_custom_info/views/custom_info_template_view.xml b/base_custom_info/views/custom_info_template_view.xml index d8500fe96..4805471b4 100644 --- a/base_custom_info/views/custom_info_template_view.xml +++ b/base_custom_info/views/custom_info_template_view.xml @@ -1,72 +1,72 @@ - - Custom Info Template Tree - custom.info.template - - - - - - - - - + + custom.info.template + + + + + + + + + - - Custom Info Template Form - custom.info.template - -
- - - - - - - - - - -
-
-
+ + custom.info.template + +
+ + + + + + + + + + +
+
+
- - Custom Info Template Search - custom.info.template - - - - - - - - - - - + + custom.info.template + + + + + + + + + + + - - Templates - ir.actions.act_window - custom.info.template - tree,form - form - - - -

- Click to define a new custom info template. -

- You must define a custom info template for each properties group. -

- - + + Templates + ir.actions.act_window + custom.info.template + tree,form + form + + + +

+ Click to define a new custom info template. +

+

+ You must define a custom info template for each properties group. +

+
+
diff --git a/base_custom_info/views/custom_info_value_view.xml b/base_custom_info/views/custom_info_value_view.xml index 519721095..41355c7fa 100644 --- a/base_custom_info/views/custom_info_value_view.xml +++ b/base_custom_info/views/custom_info_value_view.xml @@ -1,93 +1,112 @@ - - Custom Info Value Tree - custom.info.value - - - - - - - - - + + custom.info.value + + + + + + + + + + - - Custom Info Value Form - custom.info.value - -
- - - - - - - - - - - - - - - -
- Warning! - You might see no changes in parent form until you save it. -
-
-
-
-
+ + custom.info.value + + primary + + + + bottom + + + + + + + - - Custom Info Value Search - custom.info.value - - - - - - - - - - - - - - - + + custom.info.value + +
+ + + + + + + + + + + + + + + +
+ Warning! + You might see no changes in parent form until you save it. +
+
+
+
+
+ + + custom.info.value + + + + + + + + + + + + + + + - - Values - ir.actions.act_window - custom.info.value - tree,form - form - + + Values + ir.actions.act_window + custom.info.value + tree,form + form +
diff --git a/base_custom_info/views/menu.xml b/base_custom_info/views/menu.xml index f69e82584..233a32947 100644 --- a/base_custom_info/views/menu.xml +++ b/base_custom_info/views/menu.xml @@ -1,41 +1,45 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/base_custom_info/views/res_partner_view.xml b/base_custom_info/views/res_partner_view.xml index f32978c82..4a8c17c9f 100644 --- a/base_custom_info/views/res_partner_view.xml +++ b/base_custom_info/views/res_partner_view.xml @@ -1,38 +1,32 @@ - - Custom info in partners form - res.partner - - - - - + + res.partner + + + + - - + + + + - -