Browse Source

[MIG] base_custom_info: Migration to 12.0

12.0-mig-module_prototyper_last
Alexandre Díaz 5 years ago
parent
commit
136699066b
  1. 112
      base_custom_info/README.rst
  2. 1
      base_custom_info/__init__.py
  3. 9
      base_custom_info/__manifest__.py
  4. 6
      base_custom_info/demo/custom_info_property_defaults.yml
  5. 11
      base_custom_info/demo/defaults.xml
  6. 10
      base_custom_info/migrations/9.0.2.0.0/pre-migrate.py
  7. 1
      base_custom_info/models/__init__.py
  8. 5
      base_custom_info/models/custom_info.py
  9. 12
      base_custom_info/models/custom_info_category.py
  10. 12
      base_custom_info/models/custom_info_option.py
  11. 4
      base_custom_info/models/custom_info_property.py
  12. 5
      base_custom_info/models/custom_info_template.py
  13. 12
      base_custom_info/models/custom_info_value.py
  14. 1
      base_custom_info/models/res_partner.py
  15. 7
      base_custom_info/readme/CONFIGURE.rst
  16. 8
      base_custom_info/readme/CONTRIBUTORS.rst
  17. 117
      base_custom_info/readme/DESCRIPTION.rst
  18. 4
      base_custom_info/readme/DEVELOP.rst
  19. 5
      base_custom_info/readme/INSTALL.rst
  20. 20
      base_custom_info/readme/ROADMAP.rst
  21. 27
      base_custom_info/readme/USAGE.rst
  22. 31
      base_custom_info/security/res_groups.xml
  23. 33
      base_custom_info/security/res_groups_security.xml
  24. 599
      base_custom_info/static/description/index.html
  25. 4
      base_custom_info/views/custom_info_property_view.xml
  26. 2
      base_custom_info/views/custom_info_template_view.xml
  27. 8
      base_custom_info/views/custom_info_value_view.xml
  28. 3
      base_custom_info/wizard/__init__.py
  29. 33
      base_custom_info/wizard/base_config_settings_view.xml
  30. 5
      base_custom_info/wizard/res_config_settings.py
  31. 41
      base_custom_info/wizard/res_config_settings_view.xml

112
base_custom_info/README.rst

@ -1,17 +1,33 @@
.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
:alt: License: LGPL-3
================ ================
Base Custom Info Base Custom Info
================ ================
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
:alt: License: LGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fserver--tools-lightgray.png?logo=github
:target: https://github.com/OCA/server-tools/tree/12.0/base_custom_info
:alt: OCA/server-tools
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/server-tools-12-0/server-tools-12-0-base_custom_info
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
:target: https://runbot.odoo-community.org/runbot/149/12.0
:alt: Try me on Runbot
|badge1| |badge2| |badge3| |badge4| |badge5|
This module allows you to attach custom information to records without the need This module allows you to attach custom information to records without the need
to alter the database structure too much. to alter the database structure too much.
Definitions
===========
This module defines several concepts that you have to understand. This module defines several concepts that you have to understand.
Templates Templates
@ -84,29 +100,6 @@ I.e., the "What weaknesses does he/she have?" *property* has some options:
The *value* will always be one of these. The *value* will always be one of these.
Recursive templates using options
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Oh dear customization lovers! Options can be used to customize the custom
information template!
.. figure:: /base_custom_info/static/description/customizations-everywhere.jpg
:alt: Customizations Everywhere
If you assign an *additional template* to an option, and while using the owner
form you choose that option, you can then press *reload custom information
templates* to make the owner update itself to include all the properties in all
the involved templates. If you do not press the button, anyway the reloading
will be performed when saving the owner record.
.. figure:: /base_custom_info/static/description/templateception.jpg
:alt: Templateception
I.e., if you select the option "Needs videogames" for the property "What
weaknesses does he/she have?" of a smart partner and press *reload custom
information templates*, you will get 2 new properties to fill: "Favourite
videogames genre" and "Favourite videogame".
Value Value
----- -----
@ -150,6 +143,11 @@ So, if you want to apply this to other models, you will have to develop a
little additional addon that depends on this one. If you are a developer, refer little additional addon that depends on this one. If you are a developer, refer
to the *Development* section below. to the *Development* section below.
**Table of contents**
.. contents::
:local:
Installation Installation
============ ============
@ -201,10 +199,6 @@ To manage their values, you need to:
* Go to *Custom Info > Values*. * Go to *Custom Info > Values*.
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot
:target: https://runbot.odoo-community.org/runbot/135/10.0
Development Development
=========== ===========
@ -218,38 +212,68 @@ Known issues / Roadmap
* Custom properties cannot be shared among templates. * Custom properties cannot be shared among templates.
* Required attributes are for now only set in the UI, not in the ORM itself. * Required attributes are for now only set in the UI, not in the ORM itself.
* Support recursive templates using options
.. figure:: https://raw.githubusercontent.com/base_custom_info/static/description/customizations-everywhere.jpg
:alt: Customizations Everywhere
If you assign an *additional template* to an option, and while using the owner
form you choose that option, you can then press *reload custom information
templates* to make the owner update itself to include all the properties in all
the involved templates. If you do not press the button, anyway the reloading
will be performed when saving the owner record.
.. figure:: https://raw.githubusercontent.com/base_custom_info/static/description/templateception.jpg
:alt: Templateception
I.e., if you select the option "Needs videogames" for the property "What
weaknesses does he/she have?" of a smart partner and press *reload custom
information templates*, you will get 2 new properties to fill: "Favourite
videogames genre" and "Favourite videogame".
Bug Tracker Bug Tracker
=========== ===========
Bugs are tracked on `GitHub Issues
<https://github.com/OCA/product-attribute/issues>`_. In case of trouble, please
check there if your issue has already been reported. If you spotted it first,
help us smashing it by providing a detailed and welcomed feedback.
Bugs are tracked on `GitHub Issues <https://github.com/OCA/server-tools/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed
`feedback <https://github.com/OCA/server-tools/issues/new?body=module:%20base_custom_info%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
Credits Credits
======= =======
Authors
~~~~~~~
* Tecnativa
Contributors Contributors
------------
~~~~~~~~~~~~
* `Tecnativa <https://www.tecnativa.com>`__:
* Rafael Blasco <rafael.blasco@tecnativa.com> * Rafael Blasco <rafael.blasco@tecnativa.com>
* Carlos Dauden <carlos.dauden@tecnativa.com> * Carlos Dauden <carlos.dauden@tecnativa.com>
* Sergio Teruel <sergio.teruel@tecnativa.com> * Sergio Teruel <sergio.teruel@tecnativa.com>
* Jairo Llopis <jairo.llopis@tecnativa.com> * Jairo Llopis <jairo.llopis@tecnativa.com>
* Pedro M. Baeza <pedro.baeza@tecnativa.com> * Pedro M. Baeza <pedro.baeza@tecnativa.com>
* Alexandre Díaz <alexandre.diaz@tecnativa.com>
Maintainer
----------
Maintainers
~~~~~~~~~~~
This module is maintained by the OCA.
.. image:: https://odoo-community.org/logo.png .. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association :alt: Odoo Community Association
:target: https://odoo-community.org :target: https://odoo-community.org
This module is maintained by the OCA.
OCA, or the Odoo Community Association, is a nonprofit organization whose OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and mission is to support the collaborative development of Odoo features and
promote its widespread use. promote its widespread use.
To contribute to this module, please visit https://odoo-community.org.
This module is part of the `OCA/server-tools <https://github.com/OCA/server-tools/tree/12.0/base_custom_info>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

1
base_custom_info/__init__.py

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2015 Antiun Ingeniería S.L. - Sergio Teruel # Copyright 2015 Antiun Ingeniería S.L. - Sergio Teruel
# Copyright 2015 Antiun Ingeniería S.L. - Carlos Dauden # Copyright 2015 Antiun Ingeniería S.L. - Carlos Dauden
# License LGPL-3 - See http://www.gnu.org/licenses/lgpl-3.0.html # License LGPL-3 - See http://www.gnu.org/licenses/lgpl-3.0.html

9
base_custom_info/__manifest__.py

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2015 Antiun Ingeniería S.L. - Sergio Teruel # Copyright 2015 Antiun Ingeniería S.L. - Sergio Teruel
# Copyright 2015 Antiun Ingeniería S.L. - Carlos Dauden # Copyright 2015 Antiun Ingeniería S.L. - Carlos Dauden
# Copyright 2015-2016 Jairo Llopis <jairo.llopis@tecnativa.com> # Copyright 2015-2016 Jairo Llopis <jairo.llopis@tecnativa.com>
@ -8,13 +7,13 @@
'name': "Base Custom Info", 'name': "Base Custom Info",
'summary': "Add custom field in models", 'summary': "Add custom field in models",
'category': 'Tools', 'category': 'Tools',
'version': '10.0.1.1.0',
'version': '12.0.1.0.0',
'depends': [ 'depends': [
'base_setup', 'base_setup',
], ],
'data': [ 'data': [
'security/ir.model.access.csv', 'security/ir.model.access.csv',
'security/res_groups.xml',
'security/res_groups_security.xml',
'views/custom_info_category_view.xml', 'views/custom_info_category_view.xml',
'views/custom_info_option_view.xml', 'views/custom_info_option_view.xml',
'views/custom_info_template_view.xml', 'views/custom_info_template_view.xml',
@ -22,15 +21,15 @@
'views/custom_info_value_view.xml', 'views/custom_info_value_view.xml',
'views/menu.xml', 'views/menu.xml',
'views/res_partner_view.xml', 'views/res_partner_view.xml',
'wizard/base_config_settings_view.xml',
'wizard/res_config_settings_view.xml',
], ],
'demo': [ 'demo': [
'demo/custom.info.category.csv', 'demo/custom.info.category.csv',
'demo/custom.info.template.csv', 'demo/custom.info.template.csv',
'demo/custom.info.property.csv', 'demo/custom.info.property.csv',
'demo/custom.info.option.csv', 'demo/custom.info.option.csv',
'demo/custom_info_property_defaults.yml',
'demo/res_groups.xml', 'demo/res_groups.xml',
'demo/defaults.xml',
], ],
"images": [ "images": [
"images/menu.png", "images/menu.png",

6
base_custom_info/demo/custom_info_property_defaults.yml

@ -1,6 +0,0 @@
# Copyright 2016 Jairo Llopis <jairo.llopis@tecnativa.com>
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
- Setting default values after loading custom.info.option.csv
- !record {model: custom.info.property, id: prop_weaknesses}:
default_value: Huge glasses

11
base_custom_info/demo/defaults.xml

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2016 Jairo Llopis <jairo.llopis@tecnativa.com>
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -->
<odoo>
<record id="prop_weaknesses" model="custom.info.property">
<field name="default_value">Huge glasses</field>
</record>
</odoo>

10
base_custom_info/migrations/9.0.2.0.0/pre-migrate.py

@ -1,10 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright 2016 Jairo Llopis <jairo.llopis@tecnativa.com>
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
# pragma: no-cover
def migrate(cr, version):
"""Update database from previous versions, before updating module."""
cr.execute(
"ALTER TABLE custom_info_value RENAME COLUMN value TO value_str")

1
base_custom_info/models/__init__.py

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2015 Antiun Ingeniería S.L. - Sergio Teruel # Copyright 2015 Antiun Ingeniería S.L. - Sergio Teruel
# Copyright 2015 Antiun Ingeniería S.L. - Carlos Dauden # Copyright 2015 Antiun Ingeniería S.L. - Carlos Dauden
# Copyright 2016 Jairo Llopis <jairo.llopis@tecnativa.com> # Copyright 2016 Jairo Llopis <jairo.llopis@tecnativa.com>

5
base_custom_info/models/custom_info.py

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2015 Sergio Teruel <sergio.teruel@tecnativa.com> # Copyright 2015 Sergio Teruel <sergio.teruel@tecnativa.com>
# Copyright 2015 Carlos Dauden <carlos.dauden@tecnativa.com> # Copyright 2015 Carlos Dauden <carlos.dauden@tecnativa.com>
# Copyright 2016 Jairo Llopis <jairo.llopis@tecnativa.com> # Copyright 2016 Jairo Llopis <jairo.llopis@tecnativa.com>
@ -41,7 +40,7 @@ class CustomInfo(models.AbstractModel):
field_onchange.setdefault( field_onchange.setdefault(
u"{}.{}".format(x2many_field, subfield), u"", u"{}.{}".format(x2many_field, subfield), u"",
) )
return super(CustomInfo, self).onchange(
return super().onchange(
values, field_name, field_onchange, values, field_name, field_onchange,
) )
@ -75,7 +74,7 @@ class CustomInfo(models.AbstractModel):
automatically. automatically.
""" """
info_values = self.mapped('custom_info_ids') info_values = self.mapped('custom_info_ids')
res = super(CustomInfo, self).unlink()
res = super().unlink()
if res: if res:
info_values.unlink() info_values.unlink()
return res return res

12
base_custom_info/models/custom_info_category.py

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2016 Jairo Llopis <jairo.llopis@tecnativa.com> # Copyright 2016 Jairo Llopis <jairo.llopis@tecnativa.com>
# License LGPL-3 - See http://www.gnu.org/licenses/lgpl-3.0.html # License LGPL-3 - See http://www.gnu.org/licenses/lgpl-3.0.html
@ -22,13 +21,14 @@ class CustomInfoCategory(models.Model):
@api.multi @api.multi
def check_access_rule(self, operation): def check_access_rule(self, operation):
"""You access a category if you access at least one property.""" """You access a category if you access at least one property."""
last = None
last_error = None
for prop in self.mapped("property_ids"): for prop in self.mapped("property_ids"):
try: try:
prop.check_access_rule(operation) prop.check_access_rule(operation)
return return
except Exception as last:
except Exception as err:
last_error = err
pass pass
if last:
raise last
return super(CustomInfoCategory, self).check_access_rule(operation)
if last_error:
raise last_error
return super().check_access_rule(operation)

12
base_custom_info/models/custom_info_option.py

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2016 Jairo Llopis <jairo.llopis@tecnativa.com> # Copyright 2016 Jairo Llopis <jairo.llopis@tecnativa.com>
# Copyright 2017 Pedro M. Baeza <pedro.baeza@tecnativa.com> # Copyright 2017 Pedro M. Baeza <pedro.baeza@tecnativa.com>
# License LGPL-3 - See http://www.gnu.org/licenses/lgpl-3.0.html # License LGPL-3 - See http://www.gnu.org/licenses/lgpl-3.0.html
@ -33,13 +32,14 @@ class CustomInfoOption(models.Model):
@api.multi @api.multi
def check_access_rule(self, operation): def check_access_rule(self, operation):
"""You access an option if you access at least one property.""" """You access an option if you access at least one property."""
last = None
last_error = None
for prop in self.mapped("property_ids"): for prop in self.mapped("property_ids"):
try: try:
prop.check_access_rule(operation) prop.check_access_rule(operation)
return return
except Exception as last:
except Exception as err:
last_error = err
pass pass
if last:
raise last
return super(CustomInfoOption, self).check_access_rule(operation)
if last_error:
raise last_error
return super().check_access_rule(operation)

4
base_custom_info/models/custom_info_property.py

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2016 Jairo Llopis <jairo.llopis@tecnativa.com> # Copyright 2016 Jairo Llopis <jairo.llopis@tecnativa.com>
# Copyright 2017 Pedro M. Baeza <pedro.baeza@tecnativa.com> # Copyright 2017 Pedro M. Baeza <pedro.baeza@tecnativa.com>
# License LGPL-3 - See http://www.gnu.org/licenses/lgpl-3.0.html # License LGPL-3 - See http://www.gnu.org/licenses/lgpl-3.0.html
@ -25,6 +24,7 @@ class CustomInfoProperty(models.Model):
string="Category", string="Category",
) )
category_sequence = fields.Integer( category_sequence = fields.Integer(
string="Category Sequence",
related="category_id.sequence", related="category_id.sequence",
store=True, store=True,
readonly=True, readonly=True,
@ -81,7 +81,7 @@ class CustomInfoProperty(models.Model):
def check_access_rule(self, operation): def check_access_rule(self, operation):
"""You access a property if you access its template.""" """You access a property if you access its template."""
self.mapped("template_id").check_access_rule(operation) self.mapped("template_id").check_access_rule(operation)
return super(CustomInfoProperty, self).check_access_rule(operation)
return super().check_access_rule(operation)
@api.constrains("default_value", "field_type") @api.constrains("default_value", "field_type")
def _check_default_value(self): def _check_default_value(self):

5
base_custom_info/models/custom_info_template.py

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2016 Jairo Llopis <jairo.llopis@tecnativa.com> # Copyright 2016 Jairo Llopis <jairo.llopis@tecnativa.com>
# Copyright 2017 Pedro M. Baeza <pedro.baeza@tecnativa.com> # Copyright 2017 Pedro M. Baeza <pedro.baeza@tecnativa.com>
# License LGPL-3 - See http://www.gnu.org/licenses/lgpl-3.0.html # License LGPL-3 - See http://www.gnu.org/licenses/lgpl-3.0.html
@ -73,10 +72,10 @@ class CustomInfoTemplate(models.Model):
model = self.env[record.model_id.model or record.model] model = self.env[record.model_id.model or record.model]
model.check_access_rights(operation) model.check_access_rights(operation)
model.check_access_rule(operation) model.check_access_rule(operation)
return super(CustomInfoTemplate, self).check_access_rule(operation)
return super().check_access_rule(operation)
@api.multi @api.multi
def write(self, vals): def write(self, vals):
if 'model_id' in vals: if 'model_id' in vals:
self._check_model_update_allowed(vals['model_id']) self._check_model_update_allowed(vals['model_id'])
return super(CustomInfoTemplate, self).write(vals)
return super().write(vals)

12
base_custom_info/models/custom_info_value.py

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2016 Jairo Llopis <jairo.llopis@tecnativa.com> # Copyright 2016 Jairo Llopis <jairo.llopis@tecnativa.com>
# Copyright 2017 Pedro M. Baeza <pedro.baeza@tecnativa.com> # Copyright 2017 Pedro M. Baeza <pedro.baeza@tecnativa.com>
# License LGPL-3 - See http://www.gnu.org/licenses/lgpl-3.0.html # License LGPL-3 - See http://www.gnu.org/licenses/lgpl-3.0.html
@ -40,6 +39,7 @@ class CustomInfoValue(models.Model):
related="property_id.sequence", store=True, index=True, readonly=True, related="property_id.sequence", store=True, index=True, readonly=True,
) )
category_sequence = fields.Integer( category_sequence = fields.Integer(
string="Category Sequence",
related="property_id.category_id.sequence", store=True, readonly=True, related="property_id.category_id.sequence", store=True, readonly=True,
) )
category_id = fields.Many2one( category_id = fields.Many2one(
@ -75,7 +75,7 @@ class CustomInfoValue(models.Model):
for record in self.filtered('owner_id'): for record in self.filtered('owner_id'):
record.owner_id.check_access_rights(operation) record.owner_id.check_access_rights(operation)
record.owner_id.check_access_rule(operation) record.owner_id.check_access_rule(operation)
return super(CustomInfoValue, self).check_access_rule(operation)
return super().check_access_rule(operation)
@api.model @api.model
def _selection_owner_id(self): def _selection_owner_id(self):
@ -128,8 +128,8 @@ class CustomInfoValue(models.Model):
def _inverse_value(self): def _inverse_value(self):
"""Write the value correctly converted in the typed field.""" """Write the value correctly converted in the typed field."""
for record in self: for record in self:
if (record.field_type == "id" and
record.value == record.value_id.display_name):
if (record.field_type == "id"
and record.value == record.value_id.display_name):
# Avoid another search that can return a different value # Avoid another search that can return a different value
continue continue
record[record.field_name] = self._transform_value( record[record.field_name] = self._transform_value(
@ -178,6 +178,8 @@ class CustomInfoValue(models.Model):
for record in self: for record in self:
if not record.value and record.property_id.default_value: if not record.value and record.property_id.default_value:
record.value = record.property_id.default_value record.value = record.property_id.default_value
if not record.field_type and record.property_id.field_type:
record.field_type = record.property_id.field_type
@api.onchange('value') @api.onchange('value')
def _onchange_value(self): def _onchange_value(self):
@ -238,4 +240,4 @@ class CustomInfoValue(models.Model):
("field_type", "=", fmt), ("field_type", "=", fmt),
("value_" + fmt, operator, _value), ("value_" + fmt, operator, _value),
] ]
return ["|"] * (len(domain) / 3 - 1) + domain
return ["|"] * int(len(domain) / 3 - 1) + domain

1
base_custom_info/models/res_partner.py

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2016 Jairo Llopis <jairo.llopis@tecnativa.com> # Copyright 2016 Jairo Llopis <jairo.llopis@tecnativa.com>
# Copyright 2017 Pedro M. Baeza <pedro.baeza@tecnativa.com> # Copyright 2017 Pedro M. Baeza <pedro.baeza@tecnativa.com>
# License LGPL-3 - See http://www.gnu.org/licenses/lgpl-3.0.html # License LGPL-3 - See http://www.gnu.org/licenses/lgpl-3.0.html

7
base_custom_info/readme/CONFIGURE.rst

@ -0,0 +1,7 @@
To enable the main *Custom Info* menu:
#. Enable *Settings > General Settings > Manage custom information*.
To enable partner's custom info tab:
#. Enable *Settings > General Settings > Edit custom information in partners*.

8
base_custom_info/readme/CONTRIBUTORS.rst

@ -0,0 +1,8 @@
* `Tecnativa <https://www.tecnativa.com>`__:
* Rafael Blasco <rafael.blasco@tecnativa.com>
* Carlos Dauden <carlos.dauden@tecnativa.com>
* Sergio Teruel <sergio.teruel@tecnativa.com>
* Jairo Llopis <jairo.llopis@tecnativa.com>
* Pedro M. Baeza <pedro.baeza@tecnativa.com>
* Alexandre Díaz <alexandre.diaz@tecnativa.com>

117
base_custom_info/readme/DESCRIPTION.rst

@ -0,0 +1,117 @@
This module allows you to attach custom information to records without the need
to alter the database structure too much.
This module defines several concepts that you have to understand.
Templates
---------
A *template* is a collection of *properties* that a record should have.
*Templates* always apply to a given model, and then you can choose among the
current templates for the model you are using when you edit a record of that
model.
I.e., This addon includes a demo template called "Smart partners", that applies
to the model ``res.partner``, so if you edit any partner, you can choose that
template and get its properties autofilled.
Properties
----------
A *property* is the "name" of the field. *Templates* can have any amount of
*properties*, and when you apply a *template* to a record, it automatically
gets all of its *properties* filled, empty (unless they have a *Default
value*), ready to assign *values*.
You can set a property to as *required* to force it have a value, although you
should keep in mind that for yes/no properties, this would mean that only *yes*
can be selected, and for numeric properties, zero would be forbidden.
Also you can set *Minimum* and *Maximum* limits for every *property*, but those
limits are only used when the data type is text (to constrain its length) or
number. To skip this constraint, just set a maximum smaller than the minimum.
*Properties* always belong to a template, and as such, to a model.
*Properties* define the data type (text, number, yes/no...), and when the type
is "Selection", then you can define what *options* are available.
I.e., the "Smart partners" *template* has the following *properties*:
- Name of his/her teacher
- Amount of people that hates him/her for being so smart
- Average note on all subjects
- Does he/she believe he/she is the smartest person on earth?
- What weaknesses does he/she have?
When you set that template to any partner, you will then be able to fill these
*properties* with *values*.
Categories
----------
*Properties* can also belong to a *category*, which allows you to sort them in
a logical way, and makes further development easier.
For example, the ``website_sale_custom_info`` addon uses these to display a
technical datasheet per product in your online shop, sorted and separated by
category.
You are not required to give a *category* to every *property*.
Options
-------
When a *property*'s type is "Selection", then you define the *options*
available, so the *value* must be one of these *options*.
I.e., the "What weaknesses does he/she have?" *property* has some options:
- Loves junk food
- Needs videogames
- Huge glasses
The *value* will always be one of these.
Value
-----
When you assign a *template* to a partner, and then you get the *properties* it
should have, you still have to set a *value* for each property.
*Values* can be of different types (whole numbers, constrained selection,
booleans...), depending on how the *property* was defined. However, there is
always the ``value`` field, that is a text string, and converts automatically
to/from the correct type.
Why would I need this?
~~~~~~~~~~~~~~~~~~~~~~
Imagine you have some partners that are foreign, and that for those partners
you need some extra information that is not needed for others, and you do not
want to fill the partners model with a lot of fields that will be empty most of
the time.
In this case, you could define a *template* called "Foreign partners", which
will be applied to ``res.partner`` objects, and defines some *properties* that
these are expected to have.
Then you could assign that *template* to a partner, and automatically you will
get a subtable of all the properties it should have, with tools to fill their
*values* correctly.
Does this work with any model?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Yes and no.
Yes, because this is a base module that provides the tools to make this work
with any model.
No, because, although the tools are provided, they are only applied to the
``res.partner`` model. This is by design, because different models can have
different needs, and we don't want to depend on every possible model.
So, if you want to apply this to other models, you will have to develop a
little additional addon that depends on this one. If you are a developer, refer
to the *Development* section below.

4
base_custom_info/readme/DEVELOP.rst

@ -0,0 +1,4 @@
To create a module that supports custom information, just depend on this module
and inherit from the ``custom.info`` model.
See an example in the ``product_custom_info`` addon.

5
base_custom_info/readme/INSTALL.rst

@ -0,0 +1,5 @@
This module serves as a base for other modules that implement this behavior in
concrete models.
This module is a technical dependency and is to be installed in parallel to
other modules.

20
base_custom_info/readme/ROADMAP.rst

@ -0,0 +1,20 @@
* Custom properties cannot be shared among templates.
* Required attributes are for now only set in the UI, not in the ORM itself.
* Support recursive templates using options
.. figure:: /base_custom_info/static/description/customizations-everywhere.jpg
:alt: Customizations Everywhere
If you assign an *additional template* to an option, and while using the owner
form you choose that option, you can then press *reload custom information
templates* to make the owner update itself to include all the properties in all
the involved templates. If you do not press the button, anyway the reloading
will be performed when saving the owner record.
.. figure:: /base_custom_info/static/description/templateception.jpg
:alt: Templateception
I.e., if you select the option "Needs videogames" for the property "What
weaknesses does he/she have?" of a smart partner and press *reload custom
information templates*, you will get 2 new properties to fill: "Favourite
videogames genre" and "Favourite videogame".

27
base_custom_info/readme/USAGE.rst

@ -0,0 +1,27 @@
This module defines *Custom Info Templates* that define what properties are
expected for a given record.
To define a template, you need to:
* Go to *Custom Info > Templates*.
* Create one.
* Add some *Properties* to it.
All database records with that template enabled will automatically fill those
properties.
To manage the properties, you need to:
* Go to *Custom Info > Properties*.
To manage the property categories, you need to:
* Go to *Custom Info > Categories*.
Some properties can have a number of options to choose, to manage them:
* Go to *Custom Info > Options*.
To manage their values, you need to:
* Go to *Custom Info > Values*.

31
base_custom_info/security/res_groups.xml

@ -1,31 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2016 Jairo Llopis <jairo.llopis@tecnativa.com>
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -->
<odoo>
<record id="category" model="ir.module.category">
<field name="name">Custom Information</field>
</record>
<record id="group_partner" model="res.groups">
<field name="name">Display in partner form</field>
<field name="category_id" ref="category"/>
<field name="comment">Will be able to edit custom information from partner's form.</field>
</record>
<record id="group_basic" model="res.groups">
<field name="name">Basic management</field>
<field name="category_id" ref="category"/>
<field name="comment">The user will be able to manage basic custom information.</field>
</record>
<record id="group_advanced" model="res.groups">
<field name="name">Advanced management</field>
<field name="category_id" ref="category"/>
<field name="comment">The user will be able to manage advanced custom information.</field>
<field name="implied_ids" eval="[(4, ref('group_basic'))]"/>
<field name="users" eval="[(4, ref('base.user_root'))]"/>
</record>
</odoo>

33
base_custom_info/security/res_groups_security.xml

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2016 Jairo Llopis <jairo.llopis@tecnativa.com>
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -->
<odoo>
<data noupdate="0">
<record id="category" model="ir.module.category">
<field name="name">Custom Information</field>
</record>
<record id="group_partner" model="res.groups">
<field name="name">Display in partner form</field>
<field name="category_id" ref="category"/>
<field name="comment">Will be able to edit custom information from partner's form.</field>
</record>
<record id="group_basic" model="res.groups">
<field name="name">Basic management</field>
<field name="category_id" ref="category"/>
<field name="comment">The user will be able to manage basic custom information.</field>
</record>
<record id="group_advanced" model="res.groups">
<field name="name">Advanced management</field>
<field name="category_id" ref="category"/>
<field name="comment">The user will be able to manage advanced custom information.</field>
<field name="implied_ids" eval="[(4, ref('group_basic'))]"/>
<field name="users" eval="[(4, ref('base.user_root'))]"/>
</record>
</data>
</odoo>

599
base_custom_info/static/description/index.html

@ -0,0 +1,599 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.15.1: http://docutils.sourceforge.net/" />
<title>Base Custom Info</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: grey; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="base-custom-info">
<h1 class="title">Base Custom Info</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/lgpl-3.0-standalone.html"><img alt="License: LGPL-3" src="https://img.shields.io/badge/licence-LGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/server-tools/tree/12.0/base_custom_info"><img alt="OCA/server-tools" src="https://img.shields.io/badge/github-OCA%2Fserver--tools-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/server-tools-12-0/server-tools-12-0-base_custom_info"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/149/12.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
<p>This module allows you to attach custom information to records without the need
to alter the database structure too much.</p>
<p>This module defines several concepts that you have to understand.</p>
<div class="section" id="templates">
<h1>Templates</h1>
<p>A <em>template</em> is a collection of <em>properties</em> that a record should have.
<em>Templates</em> always apply to a given model, and then you can choose among the
current templates for the model you are using when you edit a record of that
model.</p>
<p>I.e., This addon includes a demo template called “Smart partners”, that applies
to the model <tt class="docutils literal">res.partner</tt>, so if you edit any partner, you can choose that
template and get its properties autofilled.</p>
</div>
<div class="section" id="properties">
<h1>Properties</h1>
<p>A <em>property</em> is the “name” of the field. <em>Templates</em> can have any amount of
<em>properties</em>, and when you apply a <em>template</em> to a record, it automatically
gets all of its <em>properties</em> filled, empty (unless they have a <em>Default
value</em>), ready to assign <em>values</em>.</p>
<p>You can set a property to as <em>required</em> to force it have a value, although you
should keep in mind that for yes/no properties, this would mean that only <em>yes</em>
can be selected, and for numeric properties, zero would be forbidden.</p>
<p>Also you can set <em>Minimum</em> and <em>Maximum</em> limits for every <em>property</em>, but those
limits are only used when the data type is text (to constrain its length) or
number. To skip this constraint, just set a maximum smaller than the minimum.</p>
<p><em>Properties</em> always belong to a template, and as such, to a model.</p>
<p><em>Properties</em> define the data type (text, number, yes/no…), and when the type
is “Selection”, then you can define what <em>options</em> are available.</p>
<p>I.e., the “Smart partners” <em>template</em> has the following <em>properties</em>:</p>
<ul class="simple">
<li>Name of his/her teacher</li>
<li>Amount of people that hates him/her for being so smart</li>
<li>Average note on all subjects</li>
<li>Does he/she believe he/she is the smartest person on earth?</li>
<li>What weaknesses does he/she have?</li>
</ul>
<p>When you set that template to any partner, you will then be able to fill these
<em>properties</em> with <em>values</em>.</p>
</div>
<div class="section" id="categories">
<h1>Categories</h1>
<p><em>Properties</em> can also belong to a <em>category</em>, which allows you to sort them in
a logical way, and makes further development easier.</p>
<p>For example, the <tt class="docutils literal">website_sale_custom_info</tt> addon uses these to display a
technical datasheet per product in your online shop, sorted and separated by
category.</p>
<p>You are not required to give a <em>category</em> to every <em>property</em>.</p>
</div>
<div class="section" id="options">
<h1>Options</h1>
<p>When a <em>property</em>’s type is “Selection”, then you define the <em>options</em>
available, so the <em>value</em> must be one of these <em>options</em>.</p>
<p>I.e., the “What weaknesses does he/she have?” <em>property</em> has some options:</p>
<ul class="simple">
<li>Loves junk food</li>
<li>Needs videogames</li>
<li>Huge glasses</li>
</ul>
<p>The <em>value</em> will always be one of these.</p>
</div>
<div class="section" id="value">
<h1>Value</h1>
<p>When you assign a <em>template</em> to a partner, and then you get the <em>properties</em> it
should have, you still have to set a <em>value</em> for each property.</p>
<p><em>Values</em> can be of different types (whole numbers, constrained selection,
booleans…), depending on how the <em>property</em> was defined. However, there is
always the <tt class="docutils literal">value</tt> field, that is a text string, and converts automatically
to/from the correct type.</p>
<div class="section" id="why-would-i-need-this">
<h2>Why would I need this?</h2>
<p>Imagine you have some partners that are foreign, and that for those partners
you need some extra information that is not needed for others, and you do not
want to fill the partners model with a lot of fields that will be empty most of
the time.</p>
<p>In this case, you could define a <em>template</em> called “Foreign partners”, which
will be applied to <tt class="docutils literal">res.partner</tt> objects, and defines some <em>properties</em> that
these are expected to have.</p>
<p>Then you could assign that <em>template</em> to a partner, and automatically you will
get a subtable of all the properties it should have, with tools to fill their
<em>values</em> correctly.</p>
</div>
<div class="section" id="does-this-work-with-any-model">
<h2>Does this work with any model?</h2>
<p>Yes and no.</p>
<p>Yes, because this is a base module that provides the tools to make this work
with any model.</p>
<p>No, because, although the tools are provided, they are only applied to the
<tt class="docutils literal">res.partner</tt> model. This is by design, because different models can have
different needs, and we don’t want to depend on every possible model.</p>
<p>So, if you want to apply this to other models, you will have to develop a
little additional addon that depends on this one. If you are a developer, refer
to the <em>Development</em> section below.</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#installation" id="id1">Installation</a></li>
<li><a class="reference internal" href="#configuration" id="id2">Configuration</a></li>
<li><a class="reference internal" href="#usage" id="id3">Usage</a></li>
<li><a class="reference internal" href="#development" id="id4">Development</a></li>
<li><a class="reference internal" href="#known-issues-roadmap" id="id5">Known issues / Roadmap</a></li>
<li><a class="reference internal" href="#bug-tracker" id="id6">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="id7">Credits</a></li>
</ul>
</div>
<div class="section" id="installation">
<h3><a class="toc-backref" href="#id1">Installation</a></h3>
<p>This module serves as a base for other modules that implement this behavior in
concrete models.</p>
<p>This module is a technical dependency and is to be installed in parallel to
other modules.</p>
</div>
<div class="section" id="configuration">
<h3><a class="toc-backref" href="#id2">Configuration</a></h3>
<p>To enable the main <em>Custom Info</em> menu:</p>
<ol class="arabic simple">
<li>Enable <em>Settings &gt; General Settings &gt; Manage custom information</em>.</li>
</ol>
<p>To enable partner’s custom info tab:</p>
<ol class="arabic simple">
<li>Enable <em>Settings &gt; General Settings &gt; Edit custom information in partners</em>.</li>
</ol>
</div>
<div class="section" id="usage">
<h3><a class="toc-backref" href="#id3">Usage</a></h3>
<p>This module defines <em>Custom Info Templates</em> that define what properties are
expected for a given record.</p>
<p>To define a template, you need to:</p>
<ul class="simple">
<li>Go to <em>Custom Info &gt; Templates</em>.</li>
<li>Create one.</li>
<li>Add some <em>Properties</em> to it.</li>
</ul>
<p>All database records with that template enabled will automatically fill those
properties.</p>
<p>To manage the properties, you need to:</p>
<ul class="simple">
<li>Go to <em>Custom Info &gt; Properties</em>.</li>
</ul>
<p>To manage the property categories, you need to:</p>
<ul class="simple">
<li>Go to <em>Custom Info &gt; Categories</em>.</li>
</ul>
<p>Some properties can have a number of options to choose, to manage them:</p>
<ul class="simple">
<li>Go to <em>Custom Info &gt; Options</em>.</li>
</ul>
<p>To manage their values, you need to:</p>
<ul class="simple">
<li>Go to <em>Custom Info &gt; Values</em>.</li>
</ul>
</div>
<div class="section" id="development">
<h3><a class="toc-backref" href="#id4">Development</a></h3>
<p>To create a module that supports custom information, just depend on this module
and inherit from the <tt class="docutils literal">custom.info</tt> model.</p>
<p>See an example in the <tt class="docutils literal">product_custom_info</tt> addon.</p>
</div>
<div class="section" id="known-issues-roadmap">
<h3><a class="toc-backref" href="#id5">Known issues / Roadmap</a></h3>
<ul>
<li><p class="first">Custom properties cannot be shared among templates.</p>
</li>
<li><p class="first">Required attributes are for now only set in the UI, not in the ORM itself.</p>
</li>
<li><p class="first">Support recursive templates using options</p>
<div class="figure">
<img alt="Customizations Everywhere" src="https://raw.githubusercontent.com/base_custom_info/static/description/customizations-everywhere.jpg" />
</div>
<p>If you assign an <em>additional template</em> to an option, and while using the owner
form you choose that option, you can then press <em>reload custom information
templates</em> to make the owner update itself to include all the properties in all
the involved templates. If you do not press the button, anyway the reloading
will be performed when saving the owner record.</p>
<div class="figure">
<img alt="Templateception" src="https://raw.githubusercontent.com/base_custom_info/static/description/templateception.jpg" />
</div>
<p>I.e., if you select the option “Needs videogames” for the property “What
weaknesses does he/she have?” of a smart partner and press <em>reload custom
information templates</em>, you will get 2 new properties to fill: “Favourite
videogames genre” and “Favourite videogame”.</p>
</li>
</ul>
</div>
<div class="section" id="bug-tracker">
<h3><a class="toc-backref" href="#id6">Bug Tracker</a></h3>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/server-tools/issues">GitHub Issues</a>.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/OCA/server-tools/issues/new?body=module:%20base_custom_info%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h3><a class="toc-backref" href="#id7">Credits</a></h3>
</div>
</div>
<div class="section" id="authors">
<h2>Authors</h2>
<ul class="simple">
<li>Tecnativa</li>
</ul>
</div>
<div class="section" id="contributors">
<h2>Contributors</h2>
<ul class="simple">
<li><a class="reference external" href="https://www.tecnativa.com">Tecnativa</a>:<ul>
<li>Rafael Blasco &lt;<a class="reference external" href="mailto:rafael.blasco&#64;tecnativa.com">rafael.blasco&#64;tecnativa.com</a>&gt;</li>
<li>Carlos Dauden &lt;<a class="reference external" href="mailto:carlos.dauden&#64;tecnativa.com">carlos.dauden&#64;tecnativa.com</a>&gt;</li>
<li>Sergio Teruel &lt;<a class="reference external" href="mailto:sergio.teruel&#64;tecnativa.com">sergio.teruel&#64;tecnativa.com</a>&gt;</li>
<li>Jairo Llopis &lt;<a class="reference external" href="mailto:jairo.llopis&#64;tecnativa.com">jairo.llopis&#64;tecnativa.com</a>&gt;</li>
<li>Pedro M. Baeza &lt;<a class="reference external" href="mailto:pedro.baeza&#64;tecnativa.com">pedro.baeza&#64;tecnativa.com</a>&gt;</li>
<li>Alexandre Díaz &lt;<a class="reference external" href="mailto:alexandre.diaz&#64;tecnativa.com">alexandre.diaz&#64;tecnativa.com</a>&gt;</li>
</ul>
</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2>Maintainers</h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.</p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/server-tools/tree/12.0/base_custom_info">OCA/server-tools</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>
</div>
</body>
</html>

4
base_custom_info/views/custom_info_property_view.xml

@ -50,7 +50,7 @@
/> />
</group> </group>
<group name="Options" col="1" attrs="{'invisible': [('field_type', '!=', 'id')]}"> <group name="Options" col="1" attrs="{'invisible': [('field_type', '!=', 'id')]}">
<label string="Select one of the existing options or create a new one clicking on 'Add an item'"/>
<label for="option_ids" string="Select one of the existing options or create a new one clicking on 'Add an item'"/>
<field name="option_ids" <field name="option_ids"
nolabel="1" nolabel="1"
context="{'form_view_ref': 'base_custom_info.custom_info_option_form', 'tree_view_ref': 'base_custom_info.custom_info_option_tree'}" context="{'form_view_ref': 'base_custom_info.custom_info_option_form', 'tree_view_ref': 'base_custom_info.custom_info_option_tree'}"
@ -85,9 +85,11 @@
<group expand="0" string="Group By"> <group expand="0" string="Group By">
<filter <filter
string="Template" string="Template"
name="template"
context="{'group_by': 'template_id'}"/> context="{'group_by': 'template_id'}"/>
<filter <filter
string="Category" string="Category"
name="category"
context="{'group_by': 'category_id'}"/> context="{'group_by': 'category_id'}"/>
</group> </group>
</search> </search>

2
base_custom_info/views/custom_info_template_view.xml

@ -45,7 +45,7 @@
<field name="model_id"/> <field name="model_id"/>
<field name="property_ids"/> <field name="property_ids"/>
<group expand="0" string="Group By"> <group expand="0" string="Group By">
<filter string="Model" context="{'group_by': 'model_id'}"/>
<filter string="Model" name="model" context="{'group_by': 'model_id'}"/>
</group> </group>
</search> </search>
</field> </field>

8
base_custom_info/views/custom_info_value_view.xml

@ -8,7 +8,7 @@
<field name="model">custom.info.value</field> <field name="model">custom.info.value</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="Custom Property Values" create="0" delete="0"> <tree string="Custom Property Values" create="0" delete="0">
<field name="owner_id" invisible="context.get('embed')"/>
<field name="owner_id" />
<field name="property_id"/> <field name="property_id"/>
<field name="category_id"/> <field name="category_id"/>
<field name="required" invisible="1"/> <field name="required" invisible="1"/>
@ -28,6 +28,7 @@
<tree position="attributes"> <tree position="attributes">
<attribute name="editable">bottom</attribute> <attribute name="editable">bottom</attribute>
</tree> </tree>
<field name="owner_id" position="replace" />
<field name="value" position="after"> <field name="value" position="after">
<field name="field_type" invisible="1"/> <field name="field_type" invisible="1"/>
<field name="value_id" <field name="value_id"
@ -68,7 +69,7 @@
attrs="{'invisible': [('field_type', '!=', 'id')], 'required': [('required', '=', True), ('field_type', '=', 'id')]}" attrs="{'invisible': [('field_type', '!=', 'id')], 'required': [('required', '=', True), ('field_type', '=', 'id')]}"
/> />
</group> </group>
<div class="alert alert-warning" invisible="not context.get('embed')">
<div class="alert alert-warning" role="alert" invisible="not context.get('embed')">
<strong>Warning!</strong> <strong>Warning!</strong>
You might see no changes in parent form until you save it. You might see no changes in parent form until you save it.
</div> </div>
@ -89,12 +90,15 @@
<group expand="0" string="Group By"> <group expand="0" string="Group By">
<filter <filter
string="Owner" string="Owner"
name="owner"
context="{'group_by': ['model' , 'res_id']}"/> context="{'group_by': ['model' , 'res_id']}"/>
<filter <filter
string="Category" string="Category"
name="category"
context="{'group_by': 'category_id'}"/> context="{'group_by': 'category_id'}"/>
<filter <filter
string="Property" string="Property"
name="property"
context="{'group_by': 'property_id'}"/> context="{'group_by': 'property_id'}"/>
</group> </group>
</search> </search>

3
base_custom_info/wizard/__init__.py

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright 2015 Antiun Ingeniería S.L. - Sergio Teruel # Copyright 2015 Antiun Ingeniería S.L. - Sergio Teruel
# Copyright 2015 Antiun Ingeniería S.L. - Carlos Dauden # Copyright 2015 Antiun Ingeniería S.L. - Carlos Dauden
# License LGPL-3 - See http://www.gnu.org/licenses/lgpl-3.0.html # License LGPL-3 - See http://www.gnu.org/licenses/lgpl-3.0.html
from . import base_config_settings
from . import res_config_settings

33
base_custom_info/wizard/base_config_settings_view.xml

@ -1,33 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2016 Jairo Llopis <jairo.llopis@tecnativa.com>
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -->
<odoo>
<record id="view_general_configuration" model="ir.ui.view">
<field name="name">Allow to enable partners custom info</field>
<field name="model">base.config.settings</field>
<field name="inherit_id" ref="base_setup.view_general_configuration"/>
<field name="arch" type="xml">
<xpath expr="//group[@name='authentication']" position="after">
<group name="custom_info">
<group>
<label for="id" string="Custom Information"/>
<div>
<div>
<field name="group_custom_info_partner"
class="oe_inline"/>
<label for="group_custom_info_partner"/>
</div>
<div>
<field name="group_custom_info_manager"
class="oe_inline"/>
<label for="group_custom_info_manager"/>
</div>
</div>
</group>
</group>
</xpath>
</field>
</record>
</odoo>

5
base_custom_info/wizard/base_config_settings.py → base_custom_info/wizard/res_config_settings.py

@ -1,12 +1,11 @@
# -*- coding: utf-8 -*-
# Copyright 2016 Jairo Llopis <jairo.llopis@tecnativa.com> # Copyright 2016 Jairo Llopis <jairo.llopis@tecnativa.com>
# License LGPL-3 - See http://www.gnu.org/licenses/lgpl-3.0.html # License LGPL-3 - See http://www.gnu.org/licenses/lgpl-3.0.html
from odoo import fields, models from odoo import fields, models
class BaseConfigSettings(models.TransientModel):
_inherit = "base.config.settings"
class ResConfigSettings(models.TransientModel):
_inherit = "res.config.settings"
group_custom_info_manager = fields.Boolean( group_custom_info_manager = fields.Boolean(
string="Manage custom information", string="Manage custom information",

41
base_custom_info/wizard/res_config_settings_view.xml

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2016 Jairo Llopis <jairo.llopis@tecnativa.com>
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -->
<odoo>
<record id="res_config_settings_view_form" model="ir.ui.view">
<field name="name">Allow to enable custom information</field>
<field name="model">res.config.settings</field>
<field name="inherit_id" ref="base_setup.res_config_settings_view_form"/>
<field name="arch" type="xml">
<xpath expr="//div[hasclass('app_settings_block')][@data-key='general_settings']" position="inside">
<h2>Custom Information</h2>
<div class="row mt16 o_settings_container" name="base_information">
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="group_custom_info_partner" />
</div>
<div class="o_setting_right_pane">
<label for="group_custom_info_partner"/>
<div class="text-muted">
Allow all employees to manage custom information
</div>
</div>
</div>
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="group_custom_info_manager" />
</div>
<div class="o_setting_right_pane">
<label for="group_custom_info_manager"/>
<div class="text-muted">
Add a tab in the partners form to edit custom information
</div>
</div>
</div>
</div>
</xpath>
</field>
</record>
</odoo>
Loading…
Cancel
Save