Ronald Portier
6 years ago
committed by
Jan Verbeek
19 changed files with 1180 additions and 0 deletions
-
63partner_multi_relation_tabs/README.rst
-
4partner_multi_relation_tabs/__init__.py
-
25partner_multi_relation_tabs/__manifest__.py
-
182partner_multi_relation_tabs/i18n/nl.po
-
181partner_multi_relation_tabs/i18n/partner_multi_relation_tabs.pot
-
8partner_multi_relation_tabs/models/__init__.py
-
158partner_multi_relation_tabs/models/res_partner.py
-
55partner_multi_relation_tabs/models/res_partner_relation_all.py
-
58partner_multi_relation_tabs/models/res_partner_relation_type.py
-
36partner_multi_relation_tabs/models/res_partner_relation_type_selection.py
-
102partner_multi_relation_tabs/models/res_partner_tab.py
-
3partner_multi_relation_tabs/security/ir.model.access.csv
-
BINpartner_multi_relation_tabs/static/description/icon.png
-
4partner_multi_relation_tabs/tests/__init__.py
-
217partner_multi_relation_tabs/tests/test_partner_tabs.py
-
18partner_multi_relation_tabs/views/menu.xml
-
17partner_multi_relation_tabs/views/res_partner_relation_all.xml
-
20partner_multi_relation_tabs/views/res_partner_relation_type.xml
-
29partner_multi_relation_tabs/views/res_partner_tab.xml
@ -0,0 +1,63 @@ |
|||
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg |
|||
:target: http://www.gnu.org/licenses/agpl |
|||
:alt: License: AGPL-3 |
|||
|
|||
======================== |
|||
Partner Relations in tab |
|||
======================== |
|||
|
|||
This module adds the possibility to show certain partner relations in its own |
|||
tab instead of the list of all relations. This can be useful if certain |
|||
relation types are regularly used and should be overseeable at a glace. |
|||
|
|||
|
|||
Usage |
|||
===== |
|||
|
|||
To use this module, you need to: |
|||
|
|||
#. Go to ... |
|||
|
|||
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas |
|||
:alt: Try me on Runbot |
|||
:target: https://runbot.odoo-community.org/runbot/partner-contact/10.0 |
|||
|
|||
|
|||
Bug Tracker |
|||
=========== |
|||
|
|||
Bugs are tracked on `GitHub Issues |
|||
<https://github.com/OCA/partner-contact/issues>`_. In case of trouble, please |
|||
check there if your issue has already been reported. If you spotted it first, |
|||
help us smash it by providing detailed and welcomed feedback. |
|||
|
|||
Credits |
|||
======= |
|||
|
|||
|
|||
Contributors |
|||
------------ |
|||
|
|||
* Holger Brunn <hbrunn@therp.nl> |
|||
* Alexandre Fayolle <alexandre.fayolle@camptocamp.com> |
|||
* Stéphane Bidoul <stephane.bidoul@acsone.eu> |
|||
* Ronald Portier <ronald@therp.nl> |
|||
* George Daramouskas <gdaramouskas@therp.nl> |
|||
|
|||
Do not contact contributors directly about support or help with technical issues. |
|||
|
|||
|
|||
Maintainer |
|||
---------- |
|||
|
|||
.. image:: https://odoo-community.org/logo.png |
|||
:alt: Odoo Community Association |
|||
:target: https://odoo-community.org |
|||
|
|||
This module is maintained by the OCA. |
|||
|
|||
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. |
|||
|
|||
To contribute to this module, please visit https://odoo-community.org. |
@ -0,0 +1,4 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright 2014-2017 Therp BV <https://therp.nl> |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
from . import models |
@ -0,0 +1,25 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright 2014-2018 Therp BV <https://therp.nl> |
|||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). |
|||
{ |
|||
"name": "Show partner relations in own tab", |
|||
"version": "10.0.1.0.0", |
|||
"author": "Therp BV,Odoo Community Association (OCA)", |
|||
"license": "AGPL-3", |
|||
"complexity": "normal", |
|||
"category": "Customer Relationship Management", |
|||
"depends": [ |
|||
'web_tree_many2one_clickable', |
|||
'partner_multi_relation', |
|||
], |
|||
"data": [ |
|||
"views/res_partner_tab.xml", |
|||
"views/res_partner_relation_type.xml", |
|||
"views/res_partner_relation_all.xml", |
|||
'views/menu.xml', |
|||
'security/ir.model.access.csv', |
|||
], |
|||
"auto_install": False, |
|||
"installable": True, |
|||
"application": False, |
|||
} |
@ -0,0 +1,182 @@ |
|||
# Translation of Odoo Server. |
|||
# This file contains the translation of the following modules: |
|||
# * partner_multi_relation_tabs |
|||
# |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: Odoo Server 10.0\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2017-11-01 09:32+0000\n" |
|||
"PO-Revision-Date: 2017-11-01 09:32+0000\n" |
|||
"Last-Translator: Ronald Portier <ronald@therp.nl>, 2017\n" |
|||
"Language-Team: Dutch (https://www.transifex.com/oca/teams/23907/nl/)\n" |
|||
"MIME-Version: 1.0\n" |
|||
"Content-Type: text/plain; charset=UTF-8\n" |
|||
"Content-Transfer-Encoding: \n" |
|||
"Language: nl\n" |
|||
"Plural-Forms: nplurals=2; plural=(n != 1);\n" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: code:addons/partner_multi_relation_tabs/models/res_partner.py:26 |
|||
#, python-format |
|||
msgid "Adding field %s to res.partner nodel." |
|||
msgstr "Veld %s wordt toegevoegd aan res.partner model." |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model,name:partner_multi_relation_tabs.model_res_partner_relation_all |
|||
msgid "All (non-inverse + inverse) relations between partners" |
|||
msgstr "Alle connecties (van beide kanten) tussen relaties" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model,name:partner_multi_relation_tabs.model_res_partner_relation_type_selection |
|||
msgid "All relation types" |
|||
msgstr "Alle connectie types" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model.fields,field_description:partner_multi_relation_tabs.field_res_partner_tab_code |
|||
msgid "Code" |
|||
msgstr "Code" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: code:addons/partner_multi_relation_tabs/models/res_partner_relation_type.py:32 |
|||
#, python-format |
|||
msgid "Contact type left not compatible with left tab" |
|||
msgstr "Linker type contact is niet verenigbaar met linker tab" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: code:addons/partner_multi_relation_tabs/models/res_partner_relation_type.py:52 |
|||
#, python-format |
|||
msgid "Contact type right not compatible with right tab" |
|||
msgstr "Rechter type contact is niet verenigbaar met rechter tab" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model.fields,field_description:partner_multi_relation_tabs.field_res_partner_tab_create_uid |
|||
msgid "Created by" |
|||
msgstr "Aangemaakt door" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model.fields,field_description:partner_multi_relation_tabs.field_res_partner_tab_create_date |
|||
msgid "Created on" |
|||
msgstr "Aangemaakt op" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model.fields,field_description:partner_multi_relation_tabs.field_res_partner_tab_display_name |
|||
msgid "Display Name" |
|||
msgstr "Naam weergave" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model.fields,field_description:partner_multi_relation_tabs.field_res_partner_tab_id |
|||
msgid "ID" |
|||
msgstr "ID" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model.fields,help:partner_multi_relation_tabs.field_res_partner_tab_code |
|||
msgid "Language independent code for tab" |
|||
msgstr "Taal onafhankelijke code voor tab" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model.fields,field_description:partner_multi_relation_tabs.field_res_partner_tab___last_update |
|||
msgid "Last Modified on" |
|||
msgstr "Laatst gewijzigd op" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model.fields,field_description:partner_multi_relation_tabs.field_res_partner_tab_write_uid |
|||
msgid "Last Updated by" |
|||
msgstr "Laatst gewijzigd door" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model.fields,field_description:partner_multi_relation_tabs.field_res_partner_tab_write_date |
|||
msgid "Last Updated on" |
|||
msgstr "Laatst gewijzigd op" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model.fields,field_description:partner_multi_relation_tabs.field_res_partner_tab_name |
|||
msgid "Name" |
|||
msgstr "Naam" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model,name:partner_multi_relation_tabs.model_res_partner |
|||
msgid "Partner" |
|||
msgstr "Relatie" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.actions.act_window,name:partner_multi_relation_tabs.action_res_partner_tab |
|||
#: model:ir.ui.menu,name:partner_multi_relation_tabs.menu_res_partner_tab |
|||
msgid "Relation Tabs" |
|||
msgstr "Connectie tabs" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model,name:partner_multi_relation_tabs.model_res_partner_relation_type |
|||
msgid "Partner Relation Type" |
|||
msgstr "Type connectie" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: code:addons/partner_multi_relation_tabs/models/res_partner_relation_type.py:37 |
|||
#, python-format |
|||
msgid "Partner category left not compatible with left tab" |
|||
msgstr "Categorie van linker partner is niet verenigbaar met linker tab" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: code:addons/partner_multi_relation_tabs/models/res_partner_relation_type.py:57 |
|||
#, python-format |
|||
msgid "Partner category right not compatible with right tab" |
|||
msgstr "Categorie van rechter partner is niet verenigbaar met rechter tab" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model.fields,field_description:partner_multi_relation_tabs.field_res_partner_relation_all_tab_id |
|||
#: model:ir.model.fields,field_description:partner_multi_relation_tabs.field_res_partner_relation_type_selection_tab_id |
|||
msgid "Show relation on tab" |
|||
msgstr "Toon connectie op tab" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model.fields,field_description:partner_multi_relation_tabs.field_res_partner_relation_type_tab_right_id |
|||
msgid "Tab for inverse relation" |
|||
msgstr "Tab voor de omgekeerde relatie" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model.fields,field_description:partner_multi_relation_tabs.field_res_partner_relation_type_tab_left_id |
|||
msgid "Tab for this relation" |
|||
msgstr "Tab voor deze relatie" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model.fields,help:partner_multi_relation_tabs.field_res_partner_relation_type_tab_right_id |
|||
msgid "Tab in which inverse relations will be visible on partner." |
|||
msgstr "Tab waar de omgekeerde connecties zichtbaar zullen zijn op de relatie." |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model.fields,help:partner_multi_relation_tabs.field_res_partner_relation_type_tab_left_id |
|||
msgid "Tab in which these relations will be visible on partner." |
|||
msgstr "Tab waarin deze connecties zichtbaar zullen zijn op de relaties." |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model,name:partner_multi_relation_tabs.model_res_partner_tab |
|||
msgid "Tabs to add to partner" |
|||
msgstr "Tab die aan de relatie wordt toegevoegd" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: code:addons/partner_multi_relation_tabs/models/res_partner.py:39 |
|||
#, python-format |
|||
msgid "Updating field %s in res.partner nodel." |
|||
msgstr "Veld %s op res.partner model wordt bijgewerkt." |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model.fields,field_description:partner_multi_relation_tabs.field_res_partner_tab_partner_category_id |
|||
msgid "Valid for partner category" |
|||
msgstr "Geldig voor relatiecategorie" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model.fields,field_description:partner_multi_relation_tabs.field_res_partner_tab_contact_type |
|||
msgid "Valid for partner type" |
|||
msgstr "Geldig voor type relatie" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model.fields,help:partner_multi_relation_tabs.field_res_partner_tab_name |
|||
msgid "Will provide title for tab in user language" |
|||
msgstr "Wordt gebruikt voor titel van tabblad in de taal van de gebruiker" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: code:addons/partner_multi_relation_tabs/models/res_partner.py:45 |
|||
#, python-format |
|||
msgid "deleting field %s from res.partner nodel." |
|||
msgstr "verwijderen veld % van res.partner model." |
|||
|
@ -0,0 +1,181 @@ |
|||
# Translation of Odoo Server. |
|||
# This file contains the translation of the following modules: |
|||
# * partner_multi_relation_tabs |
|||
# |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: Odoo Server 10.0\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2017-11-01 09:32+0000\n" |
|||
"PO-Revision-Date: 2017-11-01 09:32+0000\n" |
|||
"Last-Translator: <>\n" |
|||
"Language-Team: \n" |
|||
"MIME-Version: 1.0\n" |
|||
"Content-Type: text/plain; charset=UTF-8\n" |
|||
"Content-Transfer-Encoding: \n" |
|||
"Plural-Forms: \n" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: code:addons/partner_multi_relation_tabs/models/res_partner.py:26 |
|||
#, python-format |
|||
msgid "Adding field %s to res.partner nodel." |
|||
msgstr "" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model,name:partner_multi_relation_tabs.model_res_partner_relation_all |
|||
msgid "All (non-inverse + inverse) relations between partners" |
|||
msgstr "" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model,name:partner_multi_relation_tabs.model_res_partner_relation_type_selection |
|||
msgid "All relation types" |
|||
msgstr "" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model.fields,field_description:partner_multi_relation_tabs.field_res_partner_tab_code |
|||
msgid "Code" |
|||
msgstr "" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: code:addons/partner_multi_relation_tabs/models/res_partner_relation_type.py:32 |
|||
#, python-format |
|||
msgid "Contact type left not compatible with left tab" |
|||
msgstr "" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: code:addons/partner_multi_relation_tabs/models/res_partner_relation_type.py:52 |
|||
#, python-format |
|||
msgid "Contact type right not compatible with right tab" |
|||
msgstr "" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model.fields,field_description:partner_multi_relation_tabs.field_res_partner_tab_create_uid |
|||
msgid "Created by" |
|||
msgstr "" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model.fields,field_description:partner_multi_relation_tabs.field_res_partner_tab_create_date |
|||
msgid "Created on" |
|||
msgstr "" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model.fields,field_description:partner_multi_relation_tabs.field_res_partner_tab_display_name |
|||
msgid "Display Name" |
|||
msgstr "" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model.fields,field_description:partner_multi_relation_tabs.field_res_partner_tab_id |
|||
msgid "ID" |
|||
msgstr "" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model.fields,help:partner_multi_relation_tabs.field_res_partner_tab_code |
|||
msgid "Language independent code for tab" |
|||
msgstr "" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model.fields,field_description:partner_multi_relation_tabs.field_res_partner_tab___last_update |
|||
msgid "Last Modified on" |
|||
msgstr "" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model.fields,field_description:partner_multi_relation_tabs.field_res_partner_tab_write_uid |
|||
msgid "Last Updated by" |
|||
msgstr "" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model.fields,field_description:partner_multi_relation_tabs.field_res_partner_tab_write_date |
|||
msgid "Last Updated on" |
|||
msgstr "" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model.fields,field_description:partner_multi_relation_tabs.field_res_partner_tab_name |
|||
msgid "Name" |
|||
msgstr "" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model,name:partner_multi_relation_tabs.model_res_partner |
|||
msgid "Partner" |
|||
msgstr "" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.actions.act_window,name:partner_multi_relation_tabs.action_res_partner_tab |
|||
#: model:ir.ui.menu,name:partner_multi_relation_tabs.menu_res_partner_tab |
|||
msgid "Relation Tabs" |
|||
msgstr "" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model,name:partner_multi_relation_tabs.model_res_partner_relation_type |
|||
msgid "Partner Relation Type" |
|||
msgstr "" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: code:addons/partner_multi_relation_tabs/models/res_partner_relation_type.py:37 |
|||
#, python-format |
|||
msgid "Partner category left not compatible with left tab" |
|||
msgstr "" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: code:addons/partner_multi_relation_tabs/models/res_partner_relation_type.py:57 |
|||
#, python-format |
|||
msgid "Partner category right not compatible with right tab" |
|||
msgstr "" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model.fields,field_description:partner_multi_relation_tabs.field_res_partner_relation_all_tab_id |
|||
#: model:ir.model.fields,field_description:partner_multi_relation_tabs.field_res_partner_relation_type_selection_tab_id |
|||
msgid "Show relation on tab" |
|||
msgstr "" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model.fields,field_description:partner_multi_relation_tabs.field_res_partner_relation_type_tab_right_id |
|||
msgid "Tab for inverse relation" |
|||
msgstr "" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model.fields,field_description:partner_multi_relation_tabs.field_res_partner_relation_type_tab_left_id |
|||
msgid "Tab for this relation" |
|||
msgstr "" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model.fields,help:partner_multi_relation_tabs.field_res_partner_relation_type_tab_right_id |
|||
msgid "Tab in which inverse relations will be visible on partner." |
|||
msgstr "" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model.fields,help:partner_multi_relation_tabs.field_res_partner_relation_type_tab_left_id |
|||
msgid "Tab in which these relations will be visible on partner." |
|||
msgstr "" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model,name:partner_multi_relation_tabs.model_res_partner_tab |
|||
msgid "Tabs to add to partner" |
|||
msgstr "" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: code:addons/partner_multi_relation_tabs/models/res_partner.py:39 |
|||
#, python-format |
|||
msgid "Updating field %s in res.partner nodel." |
|||
msgstr "" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model.fields,field_description:partner_multi_relation_tabs.field_res_partner_tab_partner_category_id |
|||
msgid "Valid for partner category" |
|||
msgstr "" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model.fields,field_description:partner_multi_relation_tabs.field_res_partner_tab_contact_type |
|||
msgid "Valid for partner type" |
|||
msgstr "" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: model:ir.model.fields,help:partner_multi_relation_tabs.field_res_partner_tab_name |
|||
msgid "Will provide title for tab in user language" |
|||
msgstr "" |
|||
|
|||
#. module: partner_multi_relation_tabs |
|||
#: code:addons/partner_multi_relation_tabs/models/res_partner.py:45 |
|||
#, python-format |
|||
msgid "deleting field %s from res.partner nodel." |
|||
msgstr "" |
|||
|
@ -0,0 +1,8 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright 2014-2017 Therp BV <https://therp.nl> |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
from . import res_partner_tab |
|||
from . import res_partner_relation_type |
|||
from . import res_partner_relation_type_selection |
|||
from . import res_partner_relation_all |
|||
from . import res_partner |
@ -0,0 +1,158 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright 2014-2018 Therp BV <https://therp.nl> |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
import logging |
|||
from lxml import etree |
|||
|
|||
from odoo.osv.orm import transfer_modifiers_to_node |
|||
from odoo.osv import expression |
|||
from odoo import _, api, fields, models |
|||
|
|||
|
|||
_logger = logging.getLogger(__name__) |
|||
NAME_PREFIX = 'relation_ids_tab' |
|||
|
|||
|
|||
class ResPartner(models.Model): |
|||
_inherit = 'res.partner' |
|||
|
|||
def _get_tab_fieldname(self, tab): |
|||
"""Create fieldname for tab.""" |
|||
return '%s_%s' % (NAME_PREFIX, tab.id) |
|||
|
|||
@api.model |
|||
def _add_tab_field(self, tab): |
|||
fieldname = self._get_tab_fieldname(tab) |
|||
_logger.info(_( |
|||
"Adding field %s to res.partner model." % fieldname)) |
|||
field = fields.One2many( |
|||
comodel_name='res.partner.relation.all', |
|||
inverse_name='this_partner_id', |
|||
domain=[('tab_id', '=', tab.id)], |
|||
string=tab.name) |
|||
self._add_field(fieldname, field) |
|||
|
|||
@api.model |
|||
def _update_tab_field(self, tab): |
|||
fieldname = self._get_tab_fieldname(tab) |
|||
if fieldname not in self._fields: |
|||
return self._add_tab_field(tab) |
|||
_logger.info(_( |
|||
"Updating field %s in res.partner model." % fieldname)) |
|||
self._fields[fieldname].string = tab.name |
|||
|
|||
@api.model |
|||
def _delete_tab_field(self, fieldname): |
|||
_logger.info(_( |
|||
"deleting field %s from res.partner model." % fieldname)) |
|||
self._pop_field(fieldname) |
|||
|
|||
@api.model |
|||
def _update_tab_fields(self): |
|||
"""Create a field for each tab that might be shown for a partner.""" |
|||
deprecated_tab_fields = [ |
|||
name for name in self._fields |
|||
if name.startswith(NAME_PREFIX)] |
|||
tab_model = self.env['res.partner.tab'] |
|||
for tab in tab_model.search([]): # get all tabs |
|||
fieldname = self._get_tab_fieldname(tab) |
|||
self._add_tab_field(tab) |
|||
if fieldname in deprecated_tab_fields: |
|||
deprecated_tab_fields.remove(fieldname) # not deprecated |
|||
for fieldname in deprecated_tab_fields: |
|||
self._delete_tab_field(fieldname) |
|||
|
|||
def _register_hook(self): |
|||
self._update_tab_fields() |
|||
|
|||
def _create_tab_page(self, fieldname, tab): |
|||
"""Create an xml node containing the tab page to be added view.""" |
|||
# pylint: disable=no-member |
|||
tab_page = etree.Element('page') |
|||
invisible = [('id', '=', False)] # Partner not created yet |
|||
if tab.partner_ids: |
|||
invisible = expression.OR([ |
|||
invisible, |
|||
[('id', 'not in', tab.partner_ids.ids)]]) |
|||
else: |
|||
if tab.contact_type: |
|||
invisible = expression.OR([ |
|||
invisible, |
|||
[('is_company', '=', tab.contact_type != 'c')]]) |
|||
if tab.partner_category_id: |
|||
invisible = expression.OR([ |
|||
invisible, |
|||
[('category_id', '!=', tab.partner_category_id.id)]]) |
|||
attrs = {'invisible': invisible} |
|||
tab_page.set('string', tab.name) |
|||
tab_page.set('attrs', repr(attrs)) |
|||
transfer_modifiers_to_node(attrs, tab_page) |
|||
field = etree.Element( |
|||
'field', |
|||
name=fieldname, |
|||
context='{' |
|||
'"default_this_partner_id": id,' |
|||
'"default_tab_id": %d,' |
|||
'"active_test": False}' % tab.id) |
|||
tree = etree.Element('tree', editable='bottom') |
|||
# Now add fields for the editable tree view in the tab: |
|||
type_field = etree.Element( |
|||
'field', |
|||
name='type_selection_id', |
|||
widget='many2one_clickable') |
|||
type_field.set('domain', repr([('tab_id', '=', tab.id)])) |
|||
type_field.set('options', repr({'no_create': True})) |
|||
tree.append(type_field) |
|||
other_partner_field = etree.Element( |
|||
'field', |
|||
name='other_partner_id', |
|||
widget='many2one_clickable') |
|||
other_partner_field.set('options', repr({'no_create': True})) |
|||
tree.append(other_partner_field) |
|||
tree.append(etree.Element('field', name='date_start')) |
|||
tree.append(etree.Element('field', name='date_end')) |
|||
field.append(tree) |
|||
tab_page.append(field) |
|||
return tab_page |
|||
|
|||
def _add_tab_pages(self, view): |
|||
"""Adds the relevant tabs to the partner's formview.""" |
|||
# pylint: disable=no-member |
|||
last_page_nodes = view.xpath('//page[last()]') |
|||
if not last_page_nodes: |
|||
# Nothing to do if form contains no pages/tabs. |
|||
return [] |
|||
extra_fields = [] |
|||
if not view.xpath('//field[@name="id"]'): |
|||
view.append( |
|||
etree.Element('field', name='id', invisible='True')) |
|||
extra_fields.append('id') |
|||
last_page = last_page_nodes[0] |
|||
tab_model = self.env['res.partner.tab'] |
|||
for tab in tab_model.search([]): # get all tabs |
|||
fieldname = self._get_tab_fieldname(tab) |
|||
self._update_tab_field(tab) |
|||
extra_fields.append(fieldname) |
|||
tab_page = self._create_tab_page(fieldname, tab) |
|||
last_page.addnext(tab_page) |
|||
last_page = tab_page # Keep ordering of tabs |
|||
return extra_fields |
|||
|
|||
@api.model |
|||
def fields_view_get( |
|||
self, view_id=None, view_type='form', toolbar=False, |
|||
submenu=False): |
|||
"""Override to add relation tabs to form.""" |
|||
result = super(ResPartner, self).fields_view_get( |
|||
view_id=view_id, view_type=view_type, toolbar=toolbar, |
|||
submenu=submenu) |
|||
if view_type != 'form' or self.env.context.get('check_view_ids'): |
|||
return result |
|||
view = etree.fromstring(result['arch']) # pylint: disable=no-member |
|||
extra_fields = self._add_tab_pages(view) |
|||
view_model = self.env['ir.ui.view'] |
|||
result['arch'], original_fields = view_model.postprocess_and_fields( |
|||
self._name, view, result['view_id']) |
|||
for fieldname in extra_fields: |
|||
result['fields'][fieldname] = original_fields[fieldname] |
|||
return result |
@ -0,0 +1,55 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright 2014-2017 Therp BV <http://therp.nl> |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
from openerp import api, fields, models |
|||
|
|||
|
|||
class ResPartnerRelationAll(models.AbstractModel): |
|||
"""Abstract model to show each relation from two sides.""" |
|||
_inherit = 'res.partner.relation.all' |
|||
|
|||
tab_id = fields.Many2one( |
|||
comodel_name='res.partner.tab', |
|||
string='Show relation on tab', |
|||
readonly=True, |
|||
) |
|||
|
|||
def _get_additional_view_fields(self): |
|||
"""Add tab_id to view fields.""" |
|||
return ','.join([ |
|||
super(ResPartnerRelationAll, self)._get_additional_view_fields(), |
|||
"CASE" |
|||
" WHEN NOT bas.is_inverse" |
|||
" THEN lefttab.id" |
|||
" ELSE righttab.id" |
|||
" END as tab_id"]) |
|||
|
|||
def _get_additional_tables(self): |
|||
"""Add res_partner_tab table to view.""" |
|||
return ' '.join([ |
|||
super(ResPartnerRelationAll, self)._get_additional_tables(), |
|||
"LEFT OUTER JOIN res_partner_tab lefttab" |
|||
" ON typ.tab_left_id = lefttab.id", |
|||
"LEFT OUTER JOIN res_partner_tab righttab" |
|||
" ON typ.tab_right_id = righttab.id"]) |
|||
|
|||
@api.onchange( |
|||
'this_partner_id', |
|||
'other_partner_id', |
|||
) |
|||
def onchange_partner_id(self): |
|||
"""Add tab if needed to type_selection_id domain. |
|||
|
|||
This method makes sure then when a relation is added to a tab, |
|||
it is with a relation type meant to be placed on that tab. |
|||
""" |
|||
result = super(ResPartnerRelationAll, self).onchange_partner_id() |
|||
if 'default_tab_id' in self.env.context: |
|||
if 'domain' not in result: |
|||
result['domain'] = {} |
|||
if 'type_selection_id' not in result['domain']: |
|||
result['domain']['type_selection_id'] = [] |
|||
selection_domain = result['domain']['type_selection_id'] |
|||
selection_domain.append( |
|||
('tab_id', '=', self.env.context['default_tab_id'])) |
|||
return result |
@ -0,0 +1,58 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright 2014-2017 Therp BV <https://therp.nl> |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
from odoo import _, api, fields, models |
|||
from odoo.exceptions import ValidationError |
|||
|
|||
|
|||
class ResPartnerRelationType(models.Model): |
|||
_inherit = 'res.partner.relation.type' |
|||
|
|||
tab_left_id = fields.Many2one( |
|||
comodel_name='res.partner.tab', |
|||
string='Tab for this relation', |
|||
help="Tab in which these relations will be visible on partner.") |
|||
tab_right_id = fields.Many2one( |
|||
comodel_name='res.partner.tab', |
|||
string='Tab for inverse relation', |
|||
help="Tab in which inverse relations will be visible on partner.") |
|||
|
|||
@api.multi |
|||
@api.constrains( |
|||
'contact_type_left', |
|||
'partner_category_left', |
|||
'tab_left_id') |
|||
def _check_tab_left(self): |
|||
"""Conditions for left partner should be consistent with tab.""" |
|||
for rec in self: |
|||
if not rec.tab_left_id: |
|||
continue |
|||
tab_contact_type = rec.tab_left_id.contact_type |
|||
if tab_contact_type and tab_contact_type != rec.contact_type_left: |
|||
raise ValidationError(_( |
|||
"Contact type left not compatible with left tab")) |
|||
tab_partner_category_id = rec.tab_left_id.partner_category_id |
|||
if tab_partner_category_id and \ |
|||
tab_partner_category_id != rec.partner_category_left: |
|||
raise ValidationError(_( |
|||
"Partner category left not compatible with left tab")) |
|||
|
|||
@api.multi |
|||
@api.constrains( |
|||
'contact_type_right', |
|||
'partner_category_right', |
|||
'tab_right_id') |
|||
def _check_tab_right(self): |
|||
"""Conditions for right partner should be consistent with tab.""" |
|||
for rec in self: |
|||
if not rec.tab_right_id: |
|||
continue |
|||
tab_contact_type = rec.tab_right_id.contact_type |
|||
if tab_contact_type and tab_contact_type != rec.contact_type_right: |
|||
raise ValidationError(_( |
|||
"Contact type right not compatible with right tab")) |
|||
tab_partner_category_id = rec.tab_right_id.partner_category_id |
|||
if tab_partner_category_id and \ |
|||
tab_partner_category_id != rec.partner_category_right: |
|||
raise ValidationError(_( |
|||
"Partner category right not compatible with right tab")) |
@ -0,0 +1,36 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright 2013-2017 Therp BV <http://therp.nl> |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
from openerp import fields, models |
|||
|
|||
|
|||
class ResPartnerRelationTypeSelection(models.Model): |
|||
"""Virtual relation types""" |
|||
_inherit = 'res.partner.relation.type.selection' |
|||
|
|||
tab_id = fields.Many2one( |
|||
comodel_name='res.partner.tab', |
|||
string='Show relation on tab', |
|||
readonly=True, |
|||
) |
|||
|
|||
def _get_additional_view_fields(self): |
|||
"""Add tab_id to fields in view.""" |
|||
return ','.join([ |
|||
super(ResPartnerRelationTypeSelection, self) |
|||
._get_additional_view_fields(), |
|||
"CASE" |
|||
" WHEN NOT bas.is_inverse" |
|||
" THEN lefttab.id" |
|||
" ELSE righttab.id" |
|||
" END as tab_id"]) |
|||
|
|||
def _get_additional_tables(self): |
|||
"""Add two links to res_partner_tab.""" |
|||
return ' '.join([ |
|||
super(ResPartnerRelationTypeSelection, self) |
|||
._get_additional_tables(), |
|||
"LEFT OUTER JOIN res_partner_tab lefttab" |
|||
" ON typ.tab_left_id = lefttab.id", |
|||
"LEFT OUTER JOIN res_partner_tab righttab" |
|||
" ON typ.tab_right_id = righttab.id"]) |
@ -0,0 +1,102 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright 2017-2018 Therp BV <https://therp.nl>. |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
from odoo import _, api, fields, models |
|||
from odoo.exceptions import ValidationError |
|||
|
|||
|
|||
class ResPartnerTab(models.Model): |
|||
"""Model that defines relation types that might exist between partners""" |
|||
_name = 'res.partner.tab' |
|||
_description = 'Tabs to add to partner' |
|||
_order = 'name' |
|||
|
|||
@api.model |
|||
def get_partner_types(self): |
|||
"""Partner types are defined by model res.partner.relation.type.""" |
|||
# pylint: disable=no-self-use |
|||
rprt_model = self.env['res.partner.relation.type'] |
|||
return rprt_model.get_partner_types() |
|||
|
|||
code = fields.Char( |
|||
string='Code', |
|||
required=True, |
|||
help="Language independent code for tab") |
|||
name = fields.Char( |
|||
string='Name', |
|||
required=True, |
|||
translate=True, |
|||
help="Will provide title for tab in user language") |
|||
contact_type = fields.Selection( |
|||
selection='get_partner_types', |
|||
string='Valid for partner type') |
|||
partner_category_id = fields.Many2one( |
|||
comodel_name='res.partner.category', |
|||
string='Valid for partner category') |
|||
partner_ids = fields.Many2many( |
|||
comodel_name='res.partner', |
|||
string="Partners with this tab", |
|||
help="This tab will only show for certain partners.\n" |
|||
"Do not combine this with selection for contact type or" |
|||
" category.") |
|||
|
|||
@api.constrains('contact_type', 'partner_category_id', 'partner_ids') |
|||
def _check_partner_ids(self): |
|||
"""If partner_ids filled, other domain fields should be empty.""" |
|||
if self.partner_ids and \ |
|||
(self.contact_type or self.partner_category_id): |
|||
raise ValidationError(_( |
|||
"You can not both specify partner_ids and other criteria.")) |
|||
|
|||
@api.model |
|||
def create(self, vals): |
|||
new_tab = super(ResPartnerTab, self).create(vals) |
|||
partner_model = self.env['res.partner'] |
|||
partner_model._add_tab_field(new_tab) |
|||
return new_tab |
|||
|
|||
@api.multi |
|||
def update_types(self, vals=None): |
|||
"""Update types on write or unlink. |
|||
|
|||
If we have no vals, assume unlink. |
|||
""" |
|||
if vals: |
|||
contact_type = vals.get('contact_type', False) |
|||
partner_category_id = vals.get('partner_category_id', False) |
|||
type_model = self.env['res.partner.relation.type'] |
|||
for this in self: |
|||
for tab_side in ('left', 'right'): |
|||
side_tab = 'tab_%s_id' % tab_side |
|||
tab_using = type_model.search([(side_tab, '=', this.id)]) |
|||
for relation_type in tab_using: |
|||
type_value = relation_type['contact_type_%s' % tab_side] |
|||
category_value = \ |
|||
relation_type['partner_category_%s' % tab_side] |
|||
if (not vals or |
|||
(contact_type and contact_type != type_value) or |
|||
(partner_category_id and |
|||
partner_category_id != category_value.id)): |
|||
relation_type.write({side_tab: False}) |
|||
|
|||
@api.multi |
|||
def write(self, vals): |
|||
"""Remove tab from types no longer satifying criteria.""" |
|||
if vals.get('contact_type', False) or \ |
|||
vals.get('partner_category_id', False): |
|||
self.update_types(vals) |
|||
result = super(ResPartnerTab, self).write(vals) |
|||
partner_model = self.env['res.partner'] |
|||
for this in self: |
|||
partner_model._update_tab_field(this) |
|||
return result |
|||
|
|||
@api.multi |
|||
def unlink(self): |
|||
"""Unlink should first remove references.""" |
|||
self.update_types() |
|||
partner_model = self.env['res.partner'] |
|||
for this in self: |
|||
fieldname = partner_model._get_tab_fieldname(this) |
|||
partner_model._delete_tab_field(fieldname) |
|||
return super(ResPartnerTab, self).unlink() |
@ -0,0 +1,3 @@ |
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink |
|||
read_res_partner_tab,read_res_partner_tab,model_res_partner_tab,,1,0,0,0 |
|||
crud_res_partner_tab,crud_res_partner_tab,model_res_partner_tab,base.group_partner_manager,1,1,1,1 |
After Width: 90 | Height: 90 | Size: 18 KiB |
@ -0,0 +1,4 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright 2014-2017 Therp BV <https://therp.nl> |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
from . import test_partner_tabs |
@ -0,0 +1,217 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright 2014-2017 Therp BV <https://therp.nl> |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
from lxml import etree |
|||
|
|||
from odoo.exceptions import ValidationError |
|||
from odoo.tests import common |
|||
|
|||
|
|||
class FakeTab(): |
|||
|
|||
def __init__(self, id, name): |
|||
self.id = id |
|||
self.name = name |
|||
|
|||
|
|||
class TestPartnerTabs(common.SingleTransactionCase): |
|||
|
|||
post_install = True |
|||
|
|||
def test_create_tab(self): |
|||
tab_model = self.env['res.partner.tab'] |
|||
partner_model = self.env['res.partner'] |
|||
new_tab = tab_model.create({ |
|||
'code': 'executive', |
|||
'name': 'Executive members', |
|||
'contact_type': 'c'}) |
|||
self.assertTrue(bool(new_tab)) |
|||
# There should now be a field in res_partner for the new tab. |
|||
fieldname = partner_model._get_tab_fieldname(new_tab) |
|||
self.assertTrue(fieldname in partner_model._fields) |
|||
# The form view for partner should now also contain the tab, |
|||
# if the view contains tabs in the first place. |
|||
view_partner_form = self.env.ref('base.view_partner_form') |
|||
view = partner_model.with_context().fields_view_get( |
|||
view_id=view_partner_form.id, view_type='form') |
|||
tree = etree.fromstring(view['arch']) |
|||
field = tree.xpath('//field[@name="id"]') |
|||
self.assertTrue(field, 'Id field does not exist.') |
|||
# And we should have a field for the tab: |
|||
field = tree.xpath('//field[@name="%s"]' % fieldname) |
|||
self.assertTrue( |
|||
field, |
|||
'Tab field %s does not exist in %s.' % |
|||
(fieldname, etree.tostring(tree))) |
|||
# There should be no effect on the tree view: |
|||
view = partner_model.with_context().fields_view_get(view_type='tree') |
|||
tree = etree.fromstring(view['arch']) |
|||
field = tree.xpath('//field[@name="%s"]' % fieldname) |
|||
self.assertFalse( |
|||
field, |
|||
'Tab field %s should not exist in %s.' % |
|||
(fieldname, etree.tostring(tree))) |
|||
|
|||
def test_tab_modifications(self): |
|||
category_model = self.env['res.partner.category'] |
|||
tab_model = self.env['res.partner.tab'] |
|||
type_model = self.env['res.partner.relation.type'] |
|||
category_government = category_model.create({'name': 'Government'}) |
|||
executive_tab = tab_model.create({ |
|||
'code': 'executive', |
|||
'name': 'Executive members'}) |
|||
self.assertTrue(bool(executive_tab)) |
|||
type_has_chairperson = type_model.create({ |
|||
'name': 'has chairperson', |
|||
'name_inverse': 'is chairperson for', |
|||
'contact_type_right': 'p', |
|||
'tab_left_id': executive_tab.id}) |
|||
self.assertTrue(bool(type_has_chairperson)) |
|||
# If we change tab now to be only valid on company partners |
|||
# the tab_left_id field should be cleared from the type: |
|||
executive_tab.write({ |
|||
'contact_type': 'c', |
|||
'partner_category_id': category_government.id}) |
|||
self.assertFalse(type_has_chairperson.tab_left_id.id) |
|||
# Trying to set the tab back on type should be impossible: |
|||
with self.assertRaises(ValidationError): |
|||
type_has_chairperson.write({'tab_left_id': executive_tab.id}) |
|||
# We should be able to change tab, if also changing contact type |
|||
# and category: |
|||
type_has_chairperson.write({ |
|||
'partner_category_left': category_government.id, |
|||
'contact_type_left': 'c', |
|||
'tab_left_id': executive_tab.id}) |
|||
self.assertEqual( |
|||
type_has_chairperson.tab_left_id.id, |
|||
executive_tab.id) |
|||
# Unlinking the tab should reset the tab name on relations: |
|||
executive_tab.unlink() |
|||
self.assertEqual( |
|||
type_has_chairperson.tab_left_id.id, |
|||
False) |
|||
|
|||
def test_relation_type_modifications(self): |
|||
category_model = self.env['res.partner.category'] |
|||
tab_model = self.env['res.partner.tab'] |
|||
type_model = self.env['res.partner.relation.type'] |
|||
category_government = category_model.create({'name': 'Government'}) |
|||
category_positions = category_model.create({'name': 'Positions'}) |
|||
executive_tab = tab_model.create({ |
|||
'code': 'executive', |
|||
'name': 'Executive members', |
|||
'contact_type': 'c', |
|||
'partner_category_id': category_government.id}) |
|||
self.assertTrue(bool(executive_tab)) |
|||
positions_tab = tab_model.create({ |
|||
'code': 'positions', |
|||
'name': 'Positions held', |
|||
'contact_type': 'p', |
|||
'partner_category_id': category_positions.id}) |
|||
self.assertTrue(bool(executive_tab)) |
|||
type_has_chairperson = type_model.create({ |
|||
'name': 'has chairperson', |
|||
'name_inverse': 'is chairperson for', |
|||
'partner_category_left': category_government.id, |
|||
'contact_type_left': 'c', |
|||
'tab_left_id': executive_tab.id, |
|||
'partner_category_right': category_positions.id, |
|||
'contact_type_right': 'p', |
|||
'tab_right_id': positions_tab.id}) |
|||
self.assertTrue(bool(type_has_chairperson)) |
|||
# Trying to clear either category should raise ValidationError: |
|||
with self.assertRaises(ValidationError): |
|||
type_has_chairperson.write({'partner_category_left': False}) |
|||
with self.assertRaises(ValidationError): |
|||
type_has_chairperson.write({'partner_category_right': False}) |
|||
# Trying to clear either contact type should raise ValidationError: |
|||
with self.assertRaises(ValidationError): |
|||
type_has_chairperson.write({'contact_type_left': False}) |
|||
with self.assertRaises(ValidationError): |
|||
type_has_chairperson.write({'contact_type_right': False}) |
|||
|
|||
def test_relations(self): |
|||
"""Test relations shown on tab.""" |
|||
tab_model = self.env['res.partner.tab'] |
|||
type_model = self.env['res.partner.relation.type'] |
|||
partner_model = self.env['res.partner'] |
|||
relation_model = self.env['res.partner.relation'] |
|||
relation_all_model = self.env['res.partner.relation.all'] |
|||
executive_tab = tab_model.create({ |
|||
'code': 'executive', |
|||
'name': 'Executive members'}) |
|||
self.assertTrue(bool(executive_tab)) |
|||
type_has_chairperson = type_model.create({ |
|||
'name': 'has chairperson', |
|||
'name_inverse': 'is chairperson for', |
|||
'contact_type_right': 'p', |
|||
'tab_left_id': executive_tab.id}) |
|||
self.assertTrue(bool(type_has_chairperson)) |
|||
big_company = partner_model.create({ |
|||
'name': 'Big company', |
|||
'is_company': True, |
|||
'ref': 'BIG'}) |
|||
self.assertTrue(bool(big_company)) |
|||
important_person = partner_model.create({ |
|||
'name': 'Bart Simpson', |
|||
'is_company': False, |
|||
'ref': 'BS'}) |
|||
self.assertTrue(bool(important_person)) |
|||
relation_company_chair = relation_model.create({ |
|||
'left_partner_id': big_company.id, |
|||
'type_id': type_has_chairperson.id, |
|||
'right_partner_id': important_person.id}) |
|||
self.assertTrue(bool(relation_company_chair)) |
|||
# Now we should be able to find the relation with the tab_id: |
|||
relation_all_company_chair = relation_all_model.search([ |
|||
('tab_id', '=', executive_tab.id)], limit=1) |
|||
self.assertTrue(bool(relation_all_company_chair)) |
|||
self.assertEqual( |
|||
relation_company_chair.left_partner_id.id, |
|||
relation_all_company_chair.this_partner_id.id) |
|||
# We should find the company on the partner through tab field: |
|||
fieldname = partner_model._get_tab_fieldname(executive_tab) |
|||
self.assertTrue(fieldname in partner_model._fields) |
|||
executive_partners = big_company[fieldname] |
|||
self.assertEqual(len(executive_partners), 1) |
|||
self.assertEqual( |
|||
executive_partners.other_partner_id.id, |
|||
important_person.id) |
|||
# When adding a new relation on a tab, type must be for tab. |
|||
onchange_result = executive_partners.with_context( |
|||
default_tab_id=executive_tab.id |
|||
).onchange_partner_id() |
|||
self.assertTrue(onchange_result) |
|||
self.assertIn('domain', onchange_result) |
|||
self.assertIn('type_selection_id', onchange_result['domain']) |
|||
self.assertEqual( |
|||
onchange_result['domain']['type_selection_id'][-1], |
|||
('tab_id', '=', executive_tab.id)) |
|||
|
|||
def test_update_tabs(self): |
|||
"""Test the function that will create tabs during module loading.""" |
|||
tab_model = self.env['res.partner.tab'] |
|||
partner_model = self.env['res.partner'] |
|||
executive_tab = tab_model.create({ |
|||
'code': 'executive', |
|||
'name': 'Executive members'}) |
|||
self.assertTrue(bool(executive_tab)) |
|||
tabfield_executive_name = partner_model._get_tab_fieldname( |
|||
executive_tab) |
|||
# Create some fake tab fields (should be removed). |
|||
tab_123 = FakeTab(123, 'First tab') |
|||
tab_456 = FakeTab(456, 'Second tab') |
|||
# Add "tab fields" |
|||
partner_model._add_tab_field(tab_123) |
|||
tabfield_123_name = partner_model._get_tab_fieldname(tab_123) |
|||
self.assertEqual( |
|||
partner_model._fields[tabfield_123_name].string, tab_123.name) |
|||
partner_model._add_tab_field(tab_456) |
|||
tabfield_456_name = partner_model._get_tab_fieldname(tab_456) |
|||
self.assertEqual( |
|||
partner_model._fields[tabfield_456_name].string, tab_456.name) |
|||
# Now call hook method |
|||
partner_model._register_hook() |
|||
self.assertFalse(tabfield_123_name in partner_model._fields) |
|||
self.assertFalse(tabfield_456_name in partner_model._fields) |
|||
self.assertTrue(tabfield_executive_name in partner_model._fields) |
@ -0,0 +1,18 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<odoo> |
|||
|
|||
<act_window |
|||
id="action_res_partner_tab" |
|||
res_model="res.partner.tab" |
|||
view_mode="tree,form" |
|||
name="Relation Tabs" |
|||
/> |
|||
|
|||
<menuitem |
|||
id="menu_res_partner_tab" |
|||
parent="sales_team.menu_config_address_book" |
|||
action="action_res_partner_tab" |
|||
sequence="80" |
|||
/> |
|||
|
|||
</odoo> |
@ -0,0 +1,17 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<odoo> |
|||
|
|||
<record id="search_res_partner_relation_all" model="ir.ui.view"> |
|||
<field name="model">res.partner.relation.all</field> |
|||
<field |
|||
name="inherit_id" |
|||
ref="partner_multi_relation.search_res_partner_relation_all" |
|||
/> |
|||
<field name="arch" type="xml"> |
|||
<field name="type_selection_id" position="after"> |
|||
<field name="tab_id"/> |
|||
</field> |
|||
</field> |
|||
</record> |
|||
|
|||
</odoo> |
@ -0,0 +1,20 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<odoo> |
|||
|
|||
<record id="form_res_partner_relation_type" model="ir.ui.view"> |
|||
<field name="model">res.partner.relation.type</field> |
|||
<field |
|||
name="inherit_id" |
|||
ref="partner_multi_relation.form_res_partner_relation_type" |
|||
/> |
|||
<field name="arch" type="xml"> |
|||
<field name="partner_category_left" position="after"> |
|||
<field name="tab_left_id" /> |
|||
</field> |
|||
<field name="partner_category_right" position="after"> |
|||
<field name="tab_right_id" /> |
|||
</field> |
|||
</field> |
|||
</record> |
|||
|
|||
</odoo> |
@ -0,0 +1,29 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<odoo> |
|||
|
|||
<record id="tree_res_partner_tab" model="ir.ui.view"> |
|||
<field name="model">res.partner.tab</field> |
|||
<field type="xml" name="arch"> |
|||
<tree> |
|||
<field name="code" /> |
|||
<field name="name" /> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="form_res_partner_tab" model="ir.ui.view"> |
|||
<field name="model">res.partner.tab</field> |
|||
<field type="xml" name="arch"> |
|||
<form> |
|||
<group> |
|||
<field name="code" /> |
|||
<field name="name" /> |
|||
<field name="contact_type" /> |
|||
<field name="partner_category_id" /> |
|||
<field name="partner_ids" /> |
|||
</group> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
</odoo> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue