-
167partner_multi_relation_tabs/README.rst
-
3partner_multi_relation_tabs/__init__.py
-
31partner_multi_relation_tabs/__manifest__.py
-
17partner_multi_relation_tabs/demo/res_partner_category_demo.xml
-
48partner_multi_relation_tabs/demo/res_partner_demo.xml
-
30partner_multi_relation_tabs/demo/res_partner_relation_demo.xml
-
41partner_multi_relation_tabs/demo/res_partner_relation_type_demo.xml
-
34partner_multi_relation_tabs/demo/res_partner_tab_demo.xml
-
266partner_multi_relation_tabs/i18n/da.po
-
276partner_multi_relation_tabs/i18n/nl.po
-
264partner_multi_relation_tabs/i18n/partner_multi_relation_tabs.pot
-
6partner_multi_relation_tabs/models/__init__.py
-
100partner_multi_relation_tabs/models/res_partner.py
-
56partner_multi_relation_tabs/models/res_partner_relation_all.py
-
59partner_multi_relation_tabs/models/res_partner_relation_type.py
-
35partner_multi_relation_tabs/models/res_partner_relation_type_selection.py
-
95partner_multi_relation_tabs/models/res_partner_tab.py
-
5partner_multi_relation_tabs/readme/CONTRIBUTORS.rst
-
9partner_multi_relation_tabs/readme/DESCRIPTION.rst
-
78partner_multi_relation_tabs/readme/USAGE.rst
-
3partner_multi_relation_tabs/security/ir.model.access.csv
-
BINpartner_multi_relation_tabs/static/description/icon.png
-
497partner_multi_relation_tabs/static/description/index.html
-
BINpartner_multi_relation_tabs/static/description/partner_multi_relation_tabs-partner-display.png
-
BINpartner_multi_relation_tabs/static/description/partner_multi_relation_tabs-partner-edit.png
-
BINpartner_multi_relation_tabs/static/description/partner_multi_relation_tabs-relation-search.png
-
BINpartner_multi_relation_tabs/static/description/partner_multi_relation_tabs-relation-type-configuration.png
-
BINpartner_multi_relation_tabs/static/description/partner_multi_relation_tabs-tab-configuration.png
-
2partner_multi_relation_tabs/tablib/__init__.py
-
83partner_multi_relation_tabs/tablib/tab.py
-
4partner_multi_relation_tabs/tests/__init__.py
-
50partner_multi_relation_tabs/tests/common.py
-
157partner_multi_relation_tabs/tests/test_partner_tabs.py
-
39partner_multi_relation_tabs/tests/test_tab.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
-
44partner_multi_relation_tabs/views/res_partner_tab.xml
-
1setup/_metapackage/setup.py
@ -0,0 +1,167 @@ |
|||||
|
================================= |
||||
|
Show partner relations in own tab |
||||
|
================================= |
||||
|
|
||||
|
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
||||
|
!! 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-AGPL--3-blue.png |
||||
|
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html |
||||
|
:alt: License: AGPL-3 |
||||
|
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fpartner--contact-lightgray.png?logo=github |
||||
|
:target: https://github.com/OCA/partner-contact/tree/12.0/partner_multi_relation_tabs |
||||
|
:alt: OCA/partner-contact |
||||
|
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png |
||||
|
:target: https://translation.odoo-community.org/projects/partner-contact-12-0/partner-contact-12-0-partner_multi_relation_tabs |
||||
|
:alt: Translate me on Weblate |
||||
|
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png |
||||
|
:target: https://runbot.odoo-community.org/runbot/134/12.0 |
||||
|
:alt: Try me on Runbot |
||||
|
|
||||
|
|badge1| |badge2| |badge3| |badge4| |badge5| |
||||
|
|
||||
|
This module adds the possibility to show certain partner relations in a |
||||
|
tab on the partner form, in addition to in the list of all relations. |
||||
|
|
||||
|
This can be useful if certain relation types are regularly used and should |
||||
|
be overseeable at a glace. |
||||
|
|
||||
|
For instance you can make a tab named 'board' that will show all the board |
||||
|
members of a company, by showing the relations of types ceo, cto, cfo and |
||||
|
board member. |
||||
|
|
||||
|
**Table of contents** |
||||
|
|
||||
|
.. contents:: |
||||
|
:local: |
||||
|
|
||||
|
Usage |
||||
|
===== |
||||
|
|
||||
|
Relation Type Tabs |
||||
|
~~~~~~~~~~~~~~~~~~ |
||||
|
|
||||
|
Before being able to show certain types of relations on a tab in the partner |
||||
|
form, you will have to define the tab. |
||||
|
|
||||
|
Do that in Contacts / Relations / Relation Tabs. |
||||
|
|
||||
|
.. image:: https://raw.githubusercontent.com/OCA/partner-contact/12.0/partner_multi_relation_tabs/static/description/partner_multi_relation_tabs-tab-configuration.png |
||||
|
|
||||
|
If you specify nothing, the tab will be shown on all partner forms that have |
||||
|
tabs (page elements). Normally you will select to show the tab only on |
||||
|
partners that are companies/organisations, or only for persons. You can also |
||||
|
select a category to further limit for which partners the tab wil be shown. |
||||
|
|
||||
|
The possibility exists to show a tab only on specific partners. For instance |
||||
|
on your own company partner. |
||||
|
|
||||
|
Relation Types |
||||
|
~~~~~~~~~~~~~~ |
||||
|
|
||||
|
In configuring the relation types, you can select which type of relation will |
||||
|
be shown on which tab. It is possible to show multiple types on one tab. |
||||
|
|
||||
|
Do that in Contacts / Relations / Relation Types. |
||||
|
|
||||
|
For example on a 'executive board' tab, you might want to show the CEO of a |
||||
|
company, but also the CFO, the CTO and normal board members. |
||||
|
|
||||
|
You might specify a tab for both the 'left side' of a relation, as for the |
||||
|
'right side' or inverse relation. So a relation 'company has ceo', with |
||||
|
inverse type 'person is ceo of' might specify the 'board' tab for the |
||||
|
company type of the relation, but possibly a 'positions held' tab for the |
||||
|
person side of the relation, so on the partner form of a person you see in |
||||
|
one tab all positions or functions a person has, regardless in which company |
||||
|
or organisation. |
||||
|
|
||||
|
For each side of a relation, the partner contact type and the partner category |
||||
|
must be consistent with those specified for the tab. |
||||
|
|
||||
|
.. image:: https://raw.githubusercontent.com/OCA/partner-contact/12.0/partner_multi_relation_tabs/static/description/partner_multi_relation_tabs-relation-type-configuration.png |
||||
|
|
||||
|
Partner Form |
||||
|
~~~~~~~~~~~~ |
||||
|
|
||||
|
The partner form will contain extra tab pages, for each tab that is |
||||
|
appropiate for that partner. So a company partner does not show the tabs that |
||||
|
are meant for persons and vice versa. Also tabs meant for partners with |
||||
|
a certain category/label will only show if partners have that label. |
||||
|
|
||||
|
When adding relations on a tab, only relation types appropiate for that tab |
||||
|
can be selected. |
||||
|
|
||||
|
Example of adding a relation: |
||||
|
|
||||
|
.. image:: https://raw.githubusercontent.com/OCA/partner-contact/12.0/partner_multi_relation_tabs/static/description/partner_multi_relation_tabs-partner-edit.png |
||||
|
|
||||
|
Example of a filled out board tab: |
||||
|
|
||||
|
.. image:: https://raw.githubusercontent.com/OCA/partner-contact/12.0/partner_multi_relation_tabs/static/description/partner_multi_relation_tabs-partner-display.png |
||||
|
|
||||
|
Deleting tabs |
||||
|
~~~~~~~~~~~~~ |
||||
|
|
||||
|
When a tab is deleted, this will in no way effect the existing relations. |
||||
|
|
||||
|
However the references on the relation types to the deleted tabs will also be |
||||
|
cleared. |
||||
|
|
||||
|
Searching Relations by Tab |
||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
|
|
||||
|
You can search relations with the tab on which they are shown. For instance |
||||
|
to find all board members. |
||||
|
|
||||
|
Do that in Contacts / Relations / Relations. |
||||
|
|
||||
|
.. image:: https://raw.githubusercontent.com/OCA/partner-contact/12.0/partner_multi_relation_tabs/static/description/partner_multi_relation_tabs-relation-search.png |
||||
|
|
||||
|
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 smashing it by providing a detailed and welcomed |
||||
|
`feedback <https://github.com/OCA/partner-contact/issues/new?body=module:%20partner_multi_relation_tabs%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 |
||||
|
======= |
||||
|
|
||||
|
Authors |
||||
|
~~~~~~~ |
||||
|
|
||||
|
* Therp BV |
||||
|
|
||||
|
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> |
||||
|
|
||||
|
Maintainers |
||||
|
~~~~~~~~~~~ |
||||
|
|
||||
|
This module is maintained by the OCA. |
||||
|
|
||||
|
.. image:: https://odoo-community.org/logo.png |
||||
|
:alt: Odoo Community Association |
||||
|
:target: https://odoo-community.org |
||||
|
|
||||
|
OCA, or the Odoo Community Association, is a nonprofit organization whose |
||||
|
mission is to support the collaborative development of Odoo features and |
||||
|
promote its widespread use. |
||||
|
|
||||
|
This module is part of the `OCA/partner-contact <https://github.com/OCA/partner-contact/tree/12.0/partner_multi_relation_tabs>`_ project on GitHub. |
||||
|
|
||||
|
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. |
@ -0,0 +1,3 @@ |
|||||
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). |
||||
|
from . import tablib |
||||
|
from . import models |
@ -0,0 +1,31 @@ |
|||||
|
# 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": "12.0.1.0.0", |
||||
|
"author": "Therp BV,Odoo Community Association (OCA)", |
||||
|
"license": "AGPL-3", |
||||
|
"complexity": "normal", |
||||
|
"category": "Customer Relationship Management", |
||||
|
"depends": [ |
||||
|
'partner_multi_relation', |
||||
|
], |
||||
|
"demo": [ |
||||
|
"demo/res_partner_category_demo.xml", |
||||
|
"demo/res_partner_tab_demo.xml", |
||||
|
"demo/res_partner_demo.xml", |
||||
|
"demo/res_partner_relation_type_demo.xml", |
||||
|
"demo/res_partner_relation_demo.xml", |
||||
|
], |
||||
|
"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,17 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<odoo> |
||||
|
|
||||
|
<!-- Categories --> |
||||
|
<record id="category_government" model="res.partner.category"> |
||||
|
<field name="name">Government</field> |
||||
|
</record> |
||||
|
|
||||
|
<record id="category_functionary" model="res.partner.category"> |
||||
|
<field name="name">Functionary</field> |
||||
|
</record> |
||||
|
|
||||
|
<record id="category_department" model="res.partner.category"> |
||||
|
<field name="name">Department</field> |
||||
|
</record> |
||||
|
|
||||
|
</odoo> |
@ -0,0 +1,48 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<odoo> |
||||
|
|
||||
|
<!-- Partners --> |
||||
|
<record id="partner_big_company" model="res.partner"> |
||||
|
<field name="name">Big company</field> |
||||
|
<field name="is_company">1</field> |
||||
|
<field name="customer" eval="1"/> |
||||
|
<field name="ref">BIG</field> |
||||
|
</record> |
||||
|
|
||||
|
<record id="partner_important_person" model="res.partner"> |
||||
|
<field |
||||
|
name="category_id" |
||||
|
eval="[(6,0,[ref('category_functionary')])]" |
||||
|
/> |
||||
|
<field name="name">Bart Simpson</field> |
||||
|
<field name="is_company">0</field> |
||||
|
<field name="ref">BS</field> |
||||
|
</record> |
||||
|
|
||||
|
<record id="partner_common_person" model="res.partner"> |
||||
|
<field name="name">Homer Simpson</field> |
||||
|
<field name="is_company">0</field> |
||||
|
<field name="ref">HS</field> |
||||
|
</record> |
||||
|
|
||||
|
<record id="partner_programming_department" model="res.partner"> |
||||
|
<field |
||||
|
name="category_id" |
||||
|
eval="[(6,0,[ref('category_department')])]" |
||||
|
/> |
||||
|
<field name="name">Programming</field> |
||||
|
<field name="is_company">1</field> |
||||
|
<field name="ref">HACKDEP</field> |
||||
|
</record> |
||||
|
|
||||
|
<record id="partner_helpdesk_department" model="res.partner"> |
||||
|
<field |
||||
|
name="category_id" |
||||
|
eval="[(6,0,[ref('category_department')])]" |
||||
|
/> |
||||
|
<field name="name">Helpdesk</field> |
||||
|
<field name="is_company">1</field> |
||||
|
<field name="ref">HELPDEP</field> |
||||
|
</record> |
||||
|
|
||||
|
</odoo> |
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<odoo> |
||||
|
|
||||
|
<!-- Company has ceo. --> |
||||
|
<record id="relation_company_ceo" model="res.partner.relation"> |
||||
|
<field name="left_partner_id" ref="partner_big_company" /> |
||||
|
<field name="right_partner_id" ref="partner_important_person" /> |
||||
|
<field name="type_id" ref="relation_type_company_has_ceo" /> |
||||
|
</record> |
||||
|
|
||||
|
<!-- Departments of main organisation. --> |
||||
|
<record id="relation_programming_department" model="res.partner.relation"> |
||||
|
<field name="left_partner_id" ref="base.main_partner" /> |
||||
|
<field name="right_partner_id" ref="partner_programming_department" /> |
||||
|
<field |
||||
|
name="type_id" |
||||
|
ref="relation_type_organisation_has_department" |
||||
|
/> |
||||
|
</record> |
||||
|
|
||||
|
<record id="relation_helpdesk_department" model="res.partner.relation"> |
||||
|
<field name="left_partner_id" ref="base.main_partner" /> |
||||
|
<field name="right_partner_id" ref="partner_helpdesk_department" /> |
||||
|
<field |
||||
|
name="type_id" |
||||
|
ref="relation_type_organisation_has_department" |
||||
|
/> |
||||
|
</record> |
||||
|
|
||||
|
</odoo> |
@ -0,0 +1,41 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<odoo> |
||||
|
|
||||
|
<!-- Company has CEO: organisation to functionary person --> |
||||
|
<record |
||||
|
id="relation_type_company_has_ceo" |
||||
|
model="res.partner.relation.type"> |
||||
|
<field name="name">has ceo</field> |
||||
|
<field name="name_inverse">is ceo of</field> |
||||
|
<field name="contact_type_left">c</field> |
||||
|
<field name="tab_left_id" ref="tab_board" /> |
||||
|
<field name="contact_type_right">p</field> |
||||
|
<field name="partner_category_right" ref="category_functionary"/> |
||||
|
</record> |
||||
|
|
||||
|
<!-- Committee has a chairperson --> |
||||
|
<record |
||||
|
id="relation_type_committee_has_chairperson" |
||||
|
model="res.partner.relation.type"> |
||||
|
<field name="name">has chairperson</field> |
||||
|
<field name="name_inverse">is chairperson of</field> |
||||
|
<field name="contact_type_left">c</field> |
||||
|
<field name="tab_left_id" ref="tab_committee" /> |
||||
|
<field name="contact_type_right">p</field> |
||||
|
<field name="partner_category_left" ref="category_government"/> |
||||
|
<field name="partner_category_right" ref="category_functionary"/> |
||||
|
<field name="tab_right_id" ref="tab_positions" /> |
||||
|
</record> |
||||
|
|
||||
|
<!-- Organisation has department --> |
||||
|
<record |
||||
|
id="relation_type_organisation_has_department" |
||||
|
model="res.partner.relation.type"> |
||||
|
<field name="name">has department</field> |
||||
|
<field name="name_inverse">is department of</field> |
||||
|
<field name="tab_left_id" ref="tab_departments" /> |
||||
|
<field name="contact_type_right">c</field> |
||||
|
<field name="partner_category_right" ref="category_department"/> |
||||
|
</record> |
||||
|
|
||||
|
</odoo> |
@ -0,0 +1,34 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<odoo> |
||||
|
|
||||
|
<record id="tab_committee" model="res.partner.tab"> |
||||
|
<field name="code">committee</field> |
||||
|
<field name="name">Government committee</field> |
||||
|
<field name="contact_type">c</field> |
||||
|
<field name="partner_category_id" ref="category_government" /> |
||||
|
</record> |
||||
|
|
||||
|
<record id="tab_board" model="res.partner.tab"> |
||||
|
<field name="code">board</field> |
||||
|
<field name="name">Company executive board</field> |
||||
|
<field name="contact_type">c</field> |
||||
|
</record> |
||||
|
|
||||
|
<record id="tab_positions" model="res.partner.tab"> |
||||
|
<field name="code">positions</field> |
||||
|
<field name="name">Positions held</field> |
||||
|
<field name="contact_type">p</field> |
||||
|
<field name="partner_category_id" ref="category_functionary" /> |
||||
|
</record> |
||||
|
|
||||
|
<!-- Tab that will only be shown on our own main company partner. --> |
||||
|
<record id="tab_departments" model="res.partner.tab"> |
||||
|
<field name="code">departments</field> |
||||
|
<field name="name">Our departments</field> |
||||
|
<field |
||||
|
name="partner_ids" |
||||
|
eval="[(6,0,[ref('base.main_partner')])]" |
||||
|
/> |
||||
|
</record> |
||||
|
|
||||
|
</odoo> |
@ -0,0 +1,266 @@ |
|||||
|
# Translation of Odoo Server. |
||||
|
# This file contains the translation of the following modules: |
||||
|
# * partner_multi_relation_tabs |
||||
|
# |
||||
|
msgid "" |
||||
|
msgstr "" |
||||
|
"Project-Id-Version: Odoo Server 11.0\n" |
||||
|
"Report-Msgid-Bugs-To: \n" |
||||
|
"PO-Revision-Date: 2019-05-09 07:03+0000\n" |
||||
|
"Last-Translator: Hans Henrik Gabelgaard <hhg@gabelgaard.org>\n" |
||||
|
"Language-Team: none\n" |
||||
|
"Language: da\n" |
||||
|
"MIME-Version: 1.0\n" |
||||
|
"Content-Type: text/plain; charset=UTF-8\n" |
||||
|
"Content-Transfer-Encoding: \n" |
||||
|
"Plural-Forms: nplurals=2; plural=n != 1;\n" |
||||
|
"X-Generator: Weblate 3.5.1\n" |
||||
|
|
||||
|
#. 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 (non-inverse + inverse) relationer mellem partnere" |
||||
|
|
||||
|
#. 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 relationstyper" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:ir.model.fields,field_description:partner_multi_relation_tabs.field_res_partner_tab_code |
||||
|
msgid "Code" |
||||
|
msgstr "Kode" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:res.partner.tab,name:partner_multi_relation_tabs.tab_board |
||||
|
msgid "Company executive board" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:ir.model,name:partner_multi_relation_tabs.model_res_partner |
||||
|
msgid "Contact" |
||||
|
msgstr "Kontakt" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: code:addons/partner_multi_relation_tabs/models/res_partner_relation_type.py:33 |
||||
|
#, python-format |
||||
|
msgid "Contact type left not compatible with left tab" |
||||
|
msgstr "Kontakt type venstre er ikke kompatibel med venstre fane" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: code:addons/partner_multi_relation_tabs/models/res_partner_relation_type.py:53 |
||||
|
#, 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:res.partner.category,name:partner_multi_relation_tabs.category_department |
||||
|
msgid "Department" |
||||
|
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:res.partner.category,name:partner_multi_relation_tabs.category_functionary |
||||
|
msgid "Functionary" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:ir.ui.view,arch_db:partner_multi_relation_tabs.form_res_partner_tab |
||||
|
msgid "General" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:res.partner.category,name:partner_multi_relation_tabs.category_government |
||||
|
msgid "Government" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:res.partner.tab,name:partner_multi_relation_tabs.tab_committee |
||||
|
msgid "Government committee" |
||||
|
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:res.partner.tab,name:partner_multi_relation_tabs.tab_departments |
||||
|
msgid "Our departments" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: code:addons/partner_multi_relation_tabs/tablib/tab.py:56 |
||||
|
#, python-format |
||||
|
msgid "Partner" |
||||
|
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:38 |
||||
|
#, 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:58 |
||||
|
#, 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_tab_partner_ids |
||||
|
msgid "Partners with this tab" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:res.partner.tab,name:partner_multi_relation_tabs.tab_positions |
||||
|
msgid "Positions held" |
||||
|
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.ui.view,arch_db:partner_multi_relation_tabs.form_res_partner_tab |
||||
|
msgid "Select partner type and category for tab" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:ir.ui.view,arch_db:partner_multi_relation_tabs.form_res_partner_tab |
||||
|
msgid "Select specific partners to have this 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 |
||||
|
#: model:ir.model.fields,help:partner_multi_relation_tabs.field_res_partner_tab_partner_ids |
||||
|
msgid "This tab will only show for certain partners.\n" |
||||
|
"Do not combine this with selection for contact type or category." |
||||
|
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_tab.py:49 |
||||
|
#, python-format |
||||
|
msgid "You can not both specify partner_ids and other criteria." |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:res.partner.relation.type,name:partner_multi_relation_tabs.relation_type_company_has_ceo |
||||
|
msgid "has ceo" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:res.partner.relation.type,name:partner_multi_relation_tabs.relation_type_committee_has_chairperson |
||||
|
msgid "has chairperson" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:res.partner.relation.type,name:partner_multi_relation_tabs.relation_type_organisation_has_department |
||||
|
msgid "has department" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:res.partner.relation.type,name_inverse:partner_multi_relation_tabs.relation_type_company_has_ceo |
||||
|
msgid "is ceo of" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:res.partner.relation.type,name_inverse:partner_multi_relation_tabs.relation_type_committee_has_chairperson |
||||
|
msgid "is chairperson of" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:res.partner.relation.type,name_inverse:partner_multi_relation_tabs.relation_type_organisation_has_department |
||||
|
msgid "is department of" |
||||
|
msgstr "" |
@ -0,0 +1,276 @@ |
|||||
|
# 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" |
||||
|
"Language: nl\n" |
||||
|
"MIME-Version: 1.0\n" |
||||
|
"Content-Type: text/plain; charset=UTF-8\n" |
||||
|
"Content-Transfer-Encoding: \n" |
||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n" |
||||
|
|
||||
|
#. 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 |
||||
|
#: model:res.partner.tab,name:partner_multi_relation_tabs.tab_board |
||||
|
msgid "Company executive board" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:ir.model,name:partner_multi_relation_tabs.model_res_partner |
||||
|
msgid "Contact" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: code:addons/partner_multi_relation_tabs/models/res_partner_relation_type.py:33 |
||||
|
#, 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:53 |
||||
|
#, 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:res.partner.category,name:partner_multi_relation_tabs.category_department |
||||
|
msgid "Department" |
||||
|
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 "Naam weergave" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:res.partner.category,name:partner_multi_relation_tabs.category_functionary |
||||
|
msgid "Functionary" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:ir.ui.view,arch_db:partner_multi_relation_tabs.form_res_partner_tab |
||||
|
msgid "General" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:res.partner.category,name:partner_multi_relation_tabs.category_government |
||||
|
msgid "Government" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:res.partner.tab,name:partner_multi_relation_tabs.tab_committee |
||||
|
msgid "Government committee" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. 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:res.partner.tab,name:partner_multi_relation_tabs.tab_departments |
||||
|
msgid "Our departments" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: code:addons/partner_multi_relation_tabs/tablib/tab.py:56 |
||||
|
#, python-format |
||||
|
msgid "Partner" |
||||
|
msgstr "Relatie" |
||||
|
|
||||
|
#. 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:38 |
||||
|
#, 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:58 |
||||
|
#, 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_tab_partner_ids |
||||
|
msgid "Partners with this tab" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:res.partner.tab,name:partner_multi_relation_tabs.tab_positions |
||||
|
msgid "Positions held" |
||||
|
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 "Connectie tabs" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:ir.ui.view,arch_db:partner_multi_relation_tabs.form_res_partner_tab |
||||
|
msgid "Select partner type and category for tab" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:ir.ui.view,arch_db:partner_multi_relation_tabs.form_res_partner_tab |
||||
|
msgid "Select specific partners to have this 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 "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 |
||||
|
#: model:ir.model.fields,help:partner_multi_relation_tabs.field_res_partner_tab_partner_ids |
||||
|
msgid "" |
||||
|
"This tab will only show for certain partners.\n" |
||||
|
"Do not combine this with selection for contact type or category." |
||||
|
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 "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_tab.py:49 |
||||
|
#, python-format |
||||
|
msgid "You can not both specify partner_ids and other criteria." |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:res.partner.relation.type,name:partner_multi_relation_tabs.relation_type_company_has_ceo |
||||
|
msgid "has ceo" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:res.partner.relation.type,name:partner_multi_relation_tabs.relation_type_committee_has_chairperson |
||||
|
msgid "has chairperson" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:res.partner.relation.type,name:partner_multi_relation_tabs.relation_type_organisation_has_department |
||||
|
msgid "has department" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:res.partner.relation.type,name_inverse:partner_multi_relation_tabs.relation_type_company_has_ceo |
||||
|
msgid "is ceo of" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:res.partner.relation.type,name_inverse:partner_multi_relation_tabs.relation_type_committee_has_chairperson |
||||
|
msgid "is chairperson of" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:res.partner.relation.type,name_inverse:partner_multi_relation_tabs.relation_type_organisation_has_department |
||||
|
msgid "is department of" |
||||
|
msgstr "" |
||||
|
|
||||
|
#~ msgid "Adding field %s to res.partner nodel." |
||||
|
#~ msgstr "Veld %s wordt toegevoegd aan res.partner model." |
||||
|
|
||||
|
#~ msgid "Updating field %s in res.partner nodel." |
||||
|
#~ msgstr "Veld %s op res.partner model wordt bijgewerkt." |
||||
|
|
||||
|
#~ msgid "deleting field %s from res.partner nodel." |
||||
|
#~ msgstr "verwijderen veld % van res.partner model." |
@ -0,0 +1,264 @@ |
|||||
|
# Translation of Odoo Server. |
||||
|
# This file contains the translation of the following modules: |
||||
|
# * partner_multi_relation_tabs |
||||
|
# |
||||
|
msgid "" |
||||
|
msgstr "" |
||||
|
"Project-Id-Version: Odoo Server 11.0\n" |
||||
|
"Report-Msgid-Bugs-To: \n" |
||||
|
"Last-Translator: <>\n" |
||||
|
"Language-Team: \n" |
||||
|
"MIME-Version: 1.0\n" |
||||
|
"Content-Type: text/plain; charset=UTF-8\n" |
||||
|
"Content-Transfer-Encoding: \n" |
||||
|
"Plural-Forms: \n" |
||||
|
|
||||
|
#. module: 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 |
||||
|
#: model:res.partner.tab,name:partner_multi_relation_tabs.tab_board |
||||
|
msgid "Company executive board" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:ir.model,name:partner_multi_relation_tabs.model_res_partner |
||||
|
msgid "Contact" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: code:addons/partner_multi_relation_tabs/models/res_partner_relation_type.py:33 |
||||
|
#, 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:53 |
||||
|
#, 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:res.partner.category,name:partner_multi_relation_tabs.category_department |
||||
|
msgid "Department" |
||||
|
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:res.partner.category,name:partner_multi_relation_tabs.category_functionary |
||||
|
msgid "Functionary" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:ir.ui.view,arch_db:partner_multi_relation_tabs.form_res_partner_tab |
||||
|
msgid "General" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:res.partner.category,name:partner_multi_relation_tabs.category_government |
||||
|
msgid "Government" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:res.partner.tab,name:partner_multi_relation_tabs.tab_committee |
||||
|
msgid "Government committee" |
||||
|
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:res.partner.tab,name:partner_multi_relation_tabs.tab_departments |
||||
|
msgid "Our departments" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: code:addons/partner_multi_relation_tabs/tablib/tab.py:56 |
||||
|
#, python-format |
||||
|
msgid "Partner" |
||||
|
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:38 |
||||
|
#, 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:58 |
||||
|
#, 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_tab_partner_ids |
||||
|
msgid "Partners with this tab" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:res.partner.tab,name:partner_multi_relation_tabs.tab_positions |
||||
|
msgid "Positions held" |
||||
|
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.ui.view,arch_db:partner_multi_relation_tabs.form_res_partner_tab |
||||
|
msgid "Select partner type and category for tab" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:ir.ui.view,arch_db:partner_multi_relation_tabs.form_res_partner_tab |
||||
|
msgid "Select specific partners to have this 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 |
||||
|
#: model:ir.model.fields,help:partner_multi_relation_tabs.field_res_partner_tab_partner_ids |
||||
|
msgid "This tab will only show for certain partners.\n" |
||||
|
"Do not combine this with selection for contact type or category." |
||||
|
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_tab.py:49 |
||||
|
#, python-format |
||||
|
msgid "You can not both specify partner_ids and other criteria." |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:res.partner.relation.type,name:partner_multi_relation_tabs.relation_type_company_has_ceo |
||||
|
msgid "has ceo" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:res.partner.relation.type,name:partner_multi_relation_tabs.relation_type_committee_has_chairperson |
||||
|
msgid "has chairperson" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:res.partner.relation.type,name:partner_multi_relation_tabs.relation_type_organisation_has_department |
||||
|
msgid "has department" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:res.partner.relation.type,name_inverse:partner_multi_relation_tabs.relation_type_company_has_ceo |
||||
|
msgid "is ceo of" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:res.partner.relation.type,name_inverse:partner_multi_relation_tabs.relation_type_committee_has_chairperson |
||||
|
msgid "is chairperson of" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: partner_multi_relation_tabs |
||||
|
#: model:res.partner.relation.type,name_inverse:partner_multi_relation_tabs.relation_type_organisation_has_department |
||||
|
msgid "is department of" |
||||
|
msgstr "" |
||||
|
|
@ -0,0 +1,6 @@ |
|||||
|
# 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,100 @@ |
|||||
|
# Copyright 2014-2018 Therp BV <https://therp.nl>. |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
# pylint: disable=no-member |
||||
|
import logging |
||||
|
from lxml import etree |
||||
|
|
||||
|
from odoo import api, fields, models |
||||
|
|
||||
|
|
||||
|
_logger = logging.getLogger(__name__) # pylint: disable=invalid-name |
||||
|
|
||||
|
|
||||
|
class ResPartner(models.Model): |
||||
|
_inherit = 'res.partner' |
||||
|
|
||||
|
@api.multi |
||||
|
def browse(self, arg=None, prefetch=None): |
||||
|
for tab in self._get_tabs(): |
||||
|
fieldname = tab.get_fieldname() |
||||
|
if fieldname not in self._fields: |
||||
|
# Check this for performance reasons. |
||||
|
self.add_field(tab) |
||||
|
return super(ResPartner, self).browse(arg=arg, prefetch=prefetch) |
||||
|
|
||||
|
@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']) |
||||
|
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 |
||||
|
|
||||
|
def _add_tab_pages(self, view): |
||||
|
"""Adds the relevant tabs to the partner's formview.""" |
||||
|
# pylint: disable=no-member |
||||
|
def add_invisible_extra_field(view, extra_fields, fieldname): |
||||
|
"""Add invisible field to view.""" |
||||
|
view.append( |
||||
|
etree.Element('field', name=fieldname, invisible='True')) |
||||
|
extra_fields.append(fieldname) |
||||
|
|
||||
|
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"]'): |
||||
|
add_invisible_extra_field(view, extra_fields, 'id') |
||||
|
last_page = last_page_nodes[0] |
||||
|
for tab in self._get_tabs(): # get all tabs |
||||
|
self.add_field(tab) |
||||
|
add_invisible_extra_field( |
||||
|
view, extra_fields, tab.get_visible_fieldname()) |
||||
|
extra_fields.append(tab.get_fieldname()) |
||||
|
tab_page = tab.create_page() |
||||
|
last_page.addnext(tab_page) |
||||
|
last_page = tab_page # Keep ordering of tabs |
||||
|
return extra_fields |
||||
|
|
||||
|
@api.depends('is_company', 'category_id') |
||||
|
def _compute_tabs_visibility(self): |
||||
|
"""Compute for all tabs wether they should be visible.""" |
||||
|
for tab in self._get_tabs(): # get all tabs |
||||
|
for this in self: |
||||
|
this[tab.get_visible_fieldname()] = \ |
||||
|
tab.compute_visibility(this) |
||||
|
|
||||
|
def _get_tabs(self): |
||||
|
tab_model = self.env['res.partner.tab'] |
||||
|
return tab_model.get_tabs() |
||||
|
|
||||
|
def add_field(self, tab): |
||||
|
"""Add tab field to model. |
||||
|
|
||||
|
Will replace existing field if already present. |
||||
|
""" |
||||
|
# Visible field determines wether first field will be visible. |
||||
|
# This is because domains on many2many no longer work in 9.0 |
||||
|
# and above. |
||||
|
visible_field = fields.Boolean(compute='_compute_tabs_visibility') |
||||
|
self._add_field(tab.get_visible_fieldname(), visible_field) |
||||
|
if visible_field not in self._field_computed: |
||||
|
self._field_computed[visible_field] = [visible_field] |
||||
|
tab_field = fields.One2many( |
||||
|
comodel_name='res.partner.relation.all', |
||||
|
inverse_name='this_partner_id', |
||||
|
domain=[('tab_id', '=', tab.tab_record.id)], |
||||
|
string=tab.tab_record.name) |
||||
|
self._add_field(tab.get_fieldname(), tab_field) |
@ -0,0 +1,56 @@ |
|||||
|
# Copyright 2014-2018 Therp BV <https://therp.nl>. |
||||
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). |
||||
|
from odoo 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.""" |
||||
|
# pylint: disable=no-member |
||||
|
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.""" |
||||
|
# pylint: disable=no-member |
||||
|
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 that when a relation is added to a tab, |
||||
|
it is with a relation type meant to be placed on that tab. |
||||
|
""" |
||||
|
# pylint: disable=no-member |
||||
|
result = super(ResPartnerRelationAll, self).onchange_partner_id() |
||||
|
if 'default_tab_id' in self.env.context: |
||||
|
result['domain'] = result['domain'] if 'domain' in result else {} |
||||
|
result['domain']['type_selection_id'] = \ |
||||
|
result['domain']['type_selection_id'] \ |
||||
|
if 'type_selection_id' in result['domain'] else {} |
||||
|
result['domain']['type_selection_id'].append( |
||||
|
('tab_id', '=', self.env.context['default_tab_id'])) |
||||
|
return result |
@ -0,0 +1,59 @@ |
|||||
|
# Copyright 2014-2017 Therp BV <https://therp.nl> |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
# pylint: disable=no-self-use |
||||
|
from odoo import _, api, fields, models |
||||
|
from odoo.exceptions import ValidationError |
||||
|
|
||||
|
|
||||
|
class ResPartnerRelationType(models.Model): |
||||
|
# pylint: disable=too-few-public-methods |
||||
|
_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,35 @@ |
|||||
|
# Copyright 2013-2018 Therp BV <https://therp.nl>. |
||||
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). |
||||
|
from odoo 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,95 @@ |
|||||
|
# Copyright 2017-2018 Therp BV <https://therp.nl>. |
||||
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). |
||||
|
from odoo import _, api, fields, models |
||||
|
from odoo.exceptions import ValidationError |
||||
|
|
||||
|
from ..tablib import Tab |
||||
|
|
||||
|
|
||||
|
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.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) |
||||
|
return result |
||||
|
|
||||
|
@api.multi |
||||
|
def unlink(self): |
||||
|
"""Unlink should first remove references.""" |
||||
|
self.update_types() |
||||
|
return super(ResPartnerTab, self).unlink() |
||||
|
|
||||
|
@api.model |
||||
|
def get_tabs(self): |
||||
|
"""Convert information on tabs in database to array of objects.""" |
||||
|
tabs = [Tab(tab_record) for tab_record in self.search([])] |
||||
|
return tabs |
@ -0,0 +1,5 @@ |
|||||
|
* 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> |
@ -0,0 +1,9 @@ |
|||||
|
This module adds the possibility to show certain partner relations in a |
||||
|
tab on the partner form, in addition to in the list of all relations. |
||||
|
|
||||
|
This can be useful if certain relation types are regularly used and should |
||||
|
be overseeable at a glace. |
||||
|
|
||||
|
For instance you can make a tab named 'board' that will show all the board |
||||
|
members of a company, by showing the relations of types ceo, cto, cfo and |
||||
|
board member. |
@ -0,0 +1,78 @@ |
|||||
|
Relation Type Tabs |
||||
|
~~~~~~~~~~~~~~~~~~ |
||||
|
|
||||
|
Before being able to show certain types of relations on a tab in the partner |
||||
|
form, you will have to define the tab. |
||||
|
|
||||
|
Do that in Contacts / Relations / Relation Tabs. |
||||
|
|
||||
|
.. image:: ../static/description/partner_multi_relation_tabs-tab-configuration.png |
||||
|
|
||||
|
If you specify nothing, the tab will be shown on all partner forms that have |
||||
|
tabs (page elements). Normally you will select to show the tab only on |
||||
|
partners that are companies/organisations, or only for persons. You can also |
||||
|
select a category to further limit for which partners the tab wil be shown. |
||||
|
|
||||
|
The possibility exists to show a tab only on specific partners. For instance |
||||
|
on your own company partner. |
||||
|
|
||||
|
Relation Types |
||||
|
~~~~~~~~~~~~~~ |
||||
|
|
||||
|
In configuring the relation types, you can select which type of relation will |
||||
|
be shown on which tab. It is possible to show multiple types on one tab. |
||||
|
|
||||
|
Do that in Contacts / Relations / Relation Types. |
||||
|
|
||||
|
For example on a 'executive board' tab, you might want to show the CEO of a |
||||
|
company, but also the CFO, the CTO and normal board members. |
||||
|
|
||||
|
You might specify a tab for both the 'left side' of a relation, as for the |
||||
|
'right side' or inverse relation. So a relation 'company has ceo', with |
||||
|
inverse type 'person is ceo of' might specify the 'board' tab for the |
||||
|
company type of the relation, but possibly a 'positions held' tab for the |
||||
|
person side of the relation, so on the partner form of a person you see in |
||||
|
one tab all positions or functions a person has, regardless in which company |
||||
|
or organisation. |
||||
|
|
||||
|
For each side of a relation, the partner contact type and the partner category |
||||
|
must be consistent with those specified for the tab. |
||||
|
|
||||
|
.. image:: ../static/description/partner_multi_relation_tabs-relation-type-configuration.png |
||||
|
|
||||
|
Partner Form |
||||
|
~~~~~~~~~~~~ |
||||
|
|
||||
|
The partner form will contain extra tab pages, for each tab that is |
||||
|
appropiate for that partner. So a company partner does not show the tabs that |
||||
|
are meant for persons and vice versa. Also tabs meant for partners with |
||||
|
a certain category/label will only show if partners have that label. |
||||
|
|
||||
|
When adding relations on a tab, only relation types appropiate for that tab |
||||
|
can be selected. |
||||
|
|
||||
|
Example of adding a relation: |
||||
|
|
||||
|
.. image:: ../static/description/partner_multi_relation_tabs-partner-edit.png |
||||
|
|
||||
|
Example of a filled out board tab: |
||||
|
|
||||
|
.. image:: ../static/description/partner_multi_relation_tabs-partner-display.png |
||||
|
|
||||
|
Deleting tabs |
||||
|
~~~~~~~~~~~~~ |
||||
|
|
||||
|
When a tab is deleted, this will in no way effect the existing relations. |
||||
|
|
||||
|
However the references on the relation types to the deleted tabs will also be |
||||
|
cleared. |
||||
|
|
||||
|
Searching Relations by Tab |
||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
|
|
||||
|
You can search relations with the tab on which they are shown. For instance |
||||
|
to find all board members. |
||||
|
|
||||
|
Do that in Contacts / Relations / Relations. |
||||
|
|
||||
|
.. image:: ../static/description/partner_multi_relation_tabs-relation-search.png |
@ -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,497 @@ |
|||||
|
<?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>Show partner relations in own tab</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="show-partner-relations-in-own-tab"> |
||||
|
<h1 class="title">Show partner relations in own tab</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/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/partner-contact/tree/12.0/partner_multi_relation_tabs"><img alt="OCA/partner-contact" src="https://img.shields.io/badge/github-OCA%2Fpartner--contact-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/partner-contact-12-0/partner-contact-12-0-partner_multi_relation_tabs"><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/134/12.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p> |
||||
|
<p>This module adds the possibility to show certain partner relations in a |
||||
|
tab on the partner form, in addition to in the list of all relations.</p> |
||||
|
<p>This can be useful if certain relation types are regularly used and should |
||||
|
be overseeable at a glace.</p> |
||||
|
<p>For instance you can make a tab named ‘board’ that will show all the board |
||||
|
members of a company, by showing the relations of types ceo, cto, cfo and |
||||
|
board member.</p> |
||||
|
<p><strong>Table of contents</strong></p> |
||||
|
<div class="contents local topic" id="contents"> |
||||
|
<ul class="simple"> |
||||
|
<li><a class="reference internal" href="#usage" id="id1">Usage</a><ul> |
||||
|
<li><a class="reference internal" href="#relation-type-tabs" id="id2">Relation Type Tabs</a></li> |
||||
|
<li><a class="reference internal" href="#relation-types" id="id3">Relation Types</a></li> |
||||
|
<li><a class="reference internal" href="#partner-form" id="id4">Partner Form</a></li> |
||||
|
<li><a class="reference internal" href="#deleting-tabs" id="id5">Deleting tabs</a></li> |
||||
|
<li><a class="reference internal" href="#searching-relations-by-tab" id="id6">Searching Relations by Tab</a></li> |
||||
|
</ul> |
||||
|
</li> |
||||
|
<li><a class="reference internal" href="#bug-tracker" id="id7">Bug Tracker</a></li> |
||||
|
<li><a class="reference internal" href="#credits" id="id8">Credits</a><ul> |
||||
|
<li><a class="reference internal" href="#authors" id="id9">Authors</a></li> |
||||
|
<li><a class="reference internal" href="#contributors" id="id10">Contributors</a></li> |
||||
|
<li><a class="reference internal" href="#maintainers" id="id11">Maintainers</a></li> |
||||
|
</ul> |
||||
|
</li> |
||||
|
</ul> |
||||
|
</div> |
||||
|
<div class="section" id="usage"> |
||||
|
<h1><a class="toc-backref" href="#id1">Usage</a></h1> |
||||
|
<div class="section" id="relation-type-tabs"> |
||||
|
<h2><a class="toc-backref" href="#id2">Relation Type Tabs</a></h2> |
||||
|
<p>Before being able to show certain types of relations on a tab in the partner |
||||
|
form, you will have to define the tab.</p> |
||||
|
<p>Do that in Contacts / Relations / Relation Tabs.</p> |
||||
|
<img alt="https://raw.githubusercontent.com/OCA/partner-contact/12.0/partner_multi_relation_tabs/static/description/partner_multi_relation_tabs-tab-configuration.png" src="https://raw.githubusercontent.com/OCA/partner-contact/12.0/partner_multi_relation_tabs/static/description/partner_multi_relation_tabs-tab-configuration.png" /> |
||||
|
<p>If you specify nothing, the tab will be shown on all partner forms that have |
||||
|
tabs (page elements). Normally you will select to show the tab only on |
||||
|
partners that are companies/organisations, or only for persons. You can also |
||||
|
select a category to further limit for which partners the tab wil be shown.</p> |
||||
|
<p>The possibility exists to show a tab only on specific partners. For instance |
||||
|
on your own company partner.</p> |
||||
|
</div> |
||||
|
<div class="section" id="relation-types"> |
||||
|
<h2><a class="toc-backref" href="#id3">Relation Types</a></h2> |
||||
|
<p>In configuring the relation types, you can select which type of relation will |
||||
|
be shown on which tab. It is possible to show multiple types on one tab.</p> |
||||
|
<p>Do that in Contacts / Relations / Relation Types.</p> |
||||
|
<p>For example on a ‘executive board’ tab, you might want to show the CEO of a |
||||
|
company, but also the CFO, the CTO and normal board members.</p> |
||||
|
<p>You might specify a tab for both the ‘left side’ of a relation, as for the |
||||
|
‘right side’ or inverse relation. So a relation ‘company has ceo’, with |
||||
|
inverse type ‘person is ceo of’ might specify the ‘board’ tab for the |
||||
|
company type of the relation, but possibly a ‘positions held’ tab for the |
||||
|
person side of the relation, so on the partner form of a person you see in |
||||
|
one tab all positions or functions a person has, regardless in which company |
||||
|
or organisation.</p> |
||||
|
<p>For each side of a relation, the partner contact type and the partner category |
||||
|
must be consistent with those specified for the tab.</p> |
||||
|
<img alt="https://raw.githubusercontent.com/OCA/partner-contact/12.0/partner_multi_relation_tabs/static/description/partner_multi_relation_tabs-relation-type-configuration.png" src="https://raw.githubusercontent.com/OCA/partner-contact/12.0/partner_multi_relation_tabs/static/description/partner_multi_relation_tabs-relation-type-configuration.png" /> |
||||
|
</div> |
||||
|
<div class="section" id="partner-form"> |
||||
|
<h2><a class="toc-backref" href="#id4">Partner Form</a></h2> |
||||
|
<p>The partner form will contain extra tab pages, for each tab that is |
||||
|
appropiate for that partner. So a company partner does not show the tabs that |
||||
|
are meant for persons and vice versa. Also tabs meant for partners with |
||||
|
a certain category/label will only show if partners have that label.</p> |
||||
|
<p>When adding relations on a tab, only relation types appropiate for that tab |
||||
|
can be selected.</p> |
||||
|
<p>Example of adding a relation:</p> |
||||
|
<img alt="https://raw.githubusercontent.com/OCA/partner-contact/12.0/partner_multi_relation_tabs/static/description/partner_multi_relation_tabs-partner-edit.png" src="https://raw.githubusercontent.com/OCA/partner-contact/12.0/partner_multi_relation_tabs/static/description/partner_multi_relation_tabs-partner-edit.png" /> |
||||
|
<p>Example of a filled out board tab:</p> |
||||
|
<img alt="https://raw.githubusercontent.com/OCA/partner-contact/12.0/partner_multi_relation_tabs/static/description/partner_multi_relation_tabs-partner-display.png" src="https://raw.githubusercontent.com/OCA/partner-contact/12.0/partner_multi_relation_tabs/static/description/partner_multi_relation_tabs-partner-display.png" /> |
||||
|
</div> |
||||
|
<div class="section" id="deleting-tabs"> |
||||
|
<h2><a class="toc-backref" href="#id5">Deleting tabs</a></h2> |
||||
|
<p>When a tab is deleted, this will in no way effect the existing relations.</p> |
||||
|
<p>However the references on the relation types to the deleted tabs will also be |
||||
|
cleared.</p> |
||||
|
</div> |
||||
|
<div class="section" id="searching-relations-by-tab"> |
||||
|
<h2><a class="toc-backref" href="#id6">Searching Relations by Tab</a></h2> |
||||
|
<p>You can search relations with the tab on which they are shown. For instance |
||||
|
to find all board members.</p> |
||||
|
<p>Do that in Contacts / Relations / Relations.</p> |
||||
|
<img alt="https://raw.githubusercontent.com/OCA/partner-contact/12.0/partner_multi_relation_tabs/static/description/partner_multi_relation_tabs-relation-search.png" src="https://raw.githubusercontent.com/OCA/partner-contact/12.0/partner_multi_relation_tabs/static/description/partner_multi_relation_tabs-relation-search.png" /> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="section" id="bug-tracker"> |
||||
|
<h1><a class="toc-backref" href="#id7">Bug Tracker</a></h1> |
||||
|
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/partner-contact/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/partner-contact/issues/new?body=module:%20partner_multi_relation_tabs%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"> |
||||
|
<h1><a class="toc-backref" href="#id8">Credits</a></h1> |
||||
|
<div class="section" id="authors"> |
||||
|
<h2><a class="toc-backref" href="#id9">Authors</a></h2> |
||||
|
<ul class="simple"> |
||||
|
<li>Therp BV</li> |
||||
|
</ul> |
||||
|
</div> |
||||
|
<div class="section" id="contributors"> |
||||
|
<h2><a class="toc-backref" href="#id10">Contributors</a></h2> |
||||
|
<ul class="simple"> |
||||
|
<li>Holger Brunn <<a class="reference external" href="mailto:hbrunn@therp.nl">hbrunn@therp.nl</a>></li> |
||||
|
<li>Alexandre Fayolle <<a class="reference external" href="mailto:alexandre.fayolle@camptocamp.com">alexandre.fayolle@camptocamp.com</a>></li> |
||||
|
<li>Stéphane Bidoul <<a class="reference external" href="mailto:stephane.bidoul@acsone.eu">stephane.bidoul@acsone.eu</a>></li> |
||||
|
<li>Ronald Portier <<a class="reference external" href="mailto:ronald@therp.nl">ronald@therp.nl</a>></li> |
||||
|
<li>George Daramouskas <<a class="reference external" href="mailto:gdaramouskas@therp.nl">gdaramouskas@therp.nl</a>></li> |
||||
|
</ul> |
||||
|
</div> |
||||
|
<div class="section" id="maintainers"> |
||||
|
<h2><a class="toc-backref" href="#id11">Maintainers</a></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/partner-contact/tree/12.0/partner_multi_relation_tabs">OCA/partner-contact</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> |
After Width: 815 | Height: 566 | Size: 42 KiB |
After Width: 815 | Height: 566 | Size: 35 KiB |
After Width: 815 | Height: 566 | Size: 23 KiB |
After Width: 815 | Height: 566 | Size: 35 KiB |
After Width: 815 | Height: 566 | Size: 28 KiB |
@ -0,0 +1,2 @@ |
|||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
from .tab import Tab |
@ -0,0 +1,83 @@ |
|||||
|
# Copyright 2014-2018 Therp BV <https://therp.nl>. |
||||
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). |
||||
|
import logging |
||||
|
from lxml import etree |
||||
|
|
||||
|
from odoo import _ |
||||
|
from odoo.osv.orm import transfer_modifiers_to_node |
||||
|
|
||||
|
|
||||
|
_logger = logging.getLogger(__name__) # pylint: disable=invalid-name |
||||
|
|
||||
|
|
||||
|
NAME_PREFIX = 'relation_ids_tab' |
||||
|
|
||||
|
|
||||
|
class Tab(object): |
||||
|
"""Encapsulate the information on a tab in the database.""" |
||||
|
|
||||
|
def __init__(self, tab_record): |
||||
|
"""Create tab from tab_record. |
||||
|
|
||||
|
In this version tab_record can be assumed to be a partner.relation.tab. |
||||
|
""" |
||||
|
self.tab_record = tab_record |
||||
|
self.name = tab_record.code |
||||
|
|
||||
|
def get_fieldname(self): |
||||
|
return '%s_%s' % (NAME_PREFIX, self.tab_record.id) |
||||
|
|
||||
|
def get_visible_fieldname(self): |
||||
|
return '%s_visible' % self.get_fieldname() |
||||
|
|
||||
|
def create_page(self): |
||||
|
tab_page = etree.Element('page') |
||||
|
self._set_page_attrs(tab_page) |
||||
|
field = etree.Element( |
||||
|
'field', |
||||
|
name=self.get_fieldname(), |
||||
|
context='{' |
||||
|
'"default_this_partner_id": id,' |
||||
|
'"default_tab_id": %d,' |
||||
|
'"active_test": False}' % self.tab_record.id) |
||||
|
tab_page.append(field) |
||||
|
tree = etree.Element('tree', editable='bottom') |
||||
|
field.append(tree) |
||||
|
# 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', '=', self.tab_record.id)])) |
||||
|
type_field.set('options', repr({'no_create': True})) |
||||
|
tree.append(type_field) |
||||
|
other_partner_field = etree.Element( |
||||
|
'field', |
||||
|
string=_('Partner'), |
||||
|
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')) |
||||
|
return tab_page |
||||
|
|
||||
|
def _set_page_attrs(self, tab_page): |
||||
|
tab_page.set('string', self.tab_record.name) |
||||
|
attrs = {'invisible': [(self.get_visible_fieldname(), '=', False)]} |
||||
|
tab_page.set('attrs', repr(attrs)) |
||||
|
transfer_modifiers_to_node(attrs, tab_page) |
||||
|
|
||||
|
def compute_visibility(self, partner): |
||||
|
"""Compute visibility, dependent on partner and conditions.""" |
||||
|
tab = self.tab_record |
||||
|
if tab.partner_ids: |
||||
|
return partner in tab.partner_ids |
||||
|
if tab.contact_type: |
||||
|
is_company_tab = tab.contact_type == 'c' |
||||
|
if partner.is_company != is_company_tab: |
||||
|
return False |
||||
|
if tab.partner_category_id: |
||||
|
if tab.partner_category_id not in partner.category_id: |
||||
|
return False |
||||
|
return True |
@ -0,0 +1,4 @@ |
|||||
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). |
||||
|
from . import common |
||||
|
from . import test_partner_tabs |
||||
|
from . import test_tab |
@ -0,0 +1,50 @@ |
|||||
|
# Copyright 2014-2018 Therp BV <https://therp.nl>. |
||||
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). |
||||
|
from odoo.tests import common |
||||
|
|
||||
|
|
||||
|
class TestCommon(common.SingleTransactionCase): |
||||
|
# pylint: disable=too-many-instance-attributes |
||||
|
post_install = True |
||||
|
|
||||
|
def setUp(self): |
||||
|
"""Create common objects for tab tests.""" |
||||
|
# pylint: disable=invalid-name |
||||
|
super(TestCommon, self).setUp() |
||||
|
self.tab_model = self.env['res.partner.tab'] |
||||
|
self.type_model = self.env['res.partner.relation.type'] |
||||
|
self.partner_model = self.env['res.partner'] |
||||
|
self.relation_model = self.env['res.partner.relation'] |
||||
|
# Categories. |
||||
|
self.category_government = self.env.ref( |
||||
|
'partner_multi_relation_tabs.category_government') |
||||
|
self.category_functionary = self.env.ref( |
||||
|
'partner_multi_relation_tabs.category_functionary') |
||||
|
self.category_department = self.env.ref( |
||||
|
'partner_multi_relation_tabs.category_department') |
||||
|
# Tabs. |
||||
|
self.tab_committee = self.env.ref( |
||||
|
'partner_multi_relation_tabs.tab_committee') |
||||
|
self.tab_board = self.env.ref( |
||||
|
'partner_multi_relation_tabs.tab_board') |
||||
|
self.tab_positions = self.env.ref( |
||||
|
'partner_multi_relation_tabs.tab_positions') |
||||
|
self.tab_departments = self.env.ref( |
||||
|
'partner_multi_relation_tabs.tab_departments') |
||||
|
# Types. |
||||
|
self.type_chairperson = self.env.ref( |
||||
|
'partner_multi_relation_tabs' |
||||
|
'.relation_type_committee_has_chairperson') |
||||
|
self.type_ceo = self.env.ref( |
||||
|
'partner_multi_relation_tabs' |
||||
|
'.relation_type_company_has_ceo') |
||||
|
# Partners. |
||||
|
self.partner_big_company = self.env.ref( |
||||
|
'partner_multi_relation_tabs.partner_big_company') |
||||
|
self.partner_important_person = self.env.ref( |
||||
|
'partner_multi_relation_tabs.partner_important_person') |
||||
|
self.partner_common_person = self.env.ref( |
||||
|
'partner_multi_relation_tabs.partner_common_person') |
||||
|
# Relations. |
||||
|
self.relation_company_ceo = self.env.ref( |
||||
|
'partner_multi_relation_tabs.relation_company_ceo') |
@ -0,0 +1,157 @@ |
|||||
|
# Copyright 2014-2018 Therp BV <https://therp.nl>. |
||||
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). |
||||
|
from lxml import etree |
||||
|
|
||||
|
from odoo.exceptions import ValidationError |
||||
|
|
||||
|
from . import common |
||||
|
from ..tablib import Tab |
||||
|
|
||||
|
|
||||
|
class TestPartnerTabs(common.TestCommon): |
||||
|
post_install = True |
||||
|
|
||||
|
def test_create_tab(self): |
||||
|
self.assertTrue(bool(self.tab_board)) |
||||
|
tab_obj = Tab(self.tab_board) |
||||
|
# fields_view_get should force the creation of the new tabs. |
||||
|
view_partner_form = self.env.ref('base.view_partner_form') |
||||
|
view = self.partner_model.with_context().fields_view_get( |
||||
|
view_id=view_partner_form.id, view_type='form') |
||||
|
# The form view for partner should now also contain field 'id'. |
||||
|
tree = etree.fromstring(view['arch']) |
||||
|
field = tree.xpath('//field[@name="id"]') |
||||
|
self.assertTrue(field, 'Id field does not exist.') |
||||
|
# There should now be a field in res_partner for the new tab. |
||||
|
fieldname = tab_obj.get_fieldname() |
||||
|
self.assertTrue(fieldname in self.partner_model._fields) |
||||
|
# 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 = self. 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_view_without_pages(self): |
||||
|
"""Check that _add_tab_pages does not effect view without pages.""" |
||||
|
# pylint: disable=protected-access |
||||
|
view = etree.Element('view') |
||||
|
extra_fields = self.partner_model._add_tab_pages(view) |
||||
|
self.assertFalse(extra_fields) |
||||
|
|
||||
|
def test_tab_modifications(self): |
||||
|
tab_executive = self.tab_model.create({ |
||||
|
'code': 'executive', |
||||
|
'name': 'Executive members'}) |
||||
|
self.assertTrue(bool(tab_executive)) |
||||
|
type_chairperson = self.type_model.create({ |
||||
|
'name': 'has chairperson', |
||||
|
'name_inverse': 'is chairperson for', |
||||
|
'contact_type_left': 'p', # This emulates a user mistake. |
||||
|
'contact_type_right': 'p', |
||||
|
'tab_left_id': tab_executive.id}) |
||||
|
self.assertTrue(bool(type_chairperson)) |
||||
|
# If we change tab now to be only valid on company partners |
||||
|
# the tab_left_id field should be cleared from the type: |
||||
|
tab_executive.write({'contact_type': 'c'}) |
||||
|
self.assertFalse(type_chairperson.tab_left_id.id) |
||||
|
# Trying to set the tab back on type should be impossible: |
||||
|
with self.assertRaises(ValidationError): |
||||
|
type_chairperson.write({'tab_left_id': tab_executive.id}) |
||||
|
# We should be able to change tab, if also changing contact type. |
||||
|
type_chairperson.write({ |
||||
|
'contact_type_left': 'c', |
||||
|
'tab_left_id': tab_executive.id}) |
||||
|
self.assertEqual( |
||||
|
type_chairperson.tab_left_id.id, |
||||
|
tab_executive.id) |
||||
|
# Unlinking the tab should reset the tab_left_id on relation type. |
||||
|
tab_executive.unlink() |
||||
|
self.assertEqual( |
||||
|
type_chairperson.tab_left_id.id, |
||||
|
False) |
||||
|
# It should not be possible to add category or contact type to as |
||||
|
# selection criteria to a tab meant for specific partners. |
||||
|
with self.assertRaises(ValidationError): |
||||
|
self.tab_departments.write({'contact_type': 'c'}) |
||||
|
with self.assertRaises(ValidationError): |
||||
|
self.tab_departments.write({ |
||||
|
'partner_category_id': self.category_government.id}) |
||||
|
|
||||
|
def test_type_modifications(self): |
||||
|
self.assertTrue(bool(self.tab_board)) |
||||
|
self.assertTrue(bool(self.tab_positions)) |
||||
|
self.assertTrue(bool(self.type_chairperson)) |
||||
|
# Trying to clear either category should raise ValidationError: |
||||
|
with self.assertRaises(ValidationError): |
||||
|
self.type_chairperson.write({'partner_category_left': False}) |
||||
|
with self.assertRaises(ValidationError): |
||||
|
self.type_chairperson.write({'partner_category_right': False}) |
||||
|
# Trying to clear either contact type should raise ValidationError: |
||||
|
with self.assertRaises(ValidationError): |
||||
|
self.type_chairperson.write({'contact_type_left': False}) |
||||
|
with self.assertRaises(ValidationError): |
||||
|
self.type_chairperson.write({'contact_type_right': False}) |
||||
|
|
||||
|
def test_relations(self): |
||||
|
"""Test relations shown on tab.""" |
||||
|
relation_all_model = self.env['res.partner.relation.all'] |
||||
|
self.assertTrue(bool(self.tab_board)) |
||||
|
self.assertTrue(bool(self.type_ceo)) |
||||
|
self.assertTrue(bool(self.partner_big_company)) |
||||
|
self.assertTrue(bool(self.partner_important_person)) |
||||
|
self.assertTrue(bool(self.relation_company_ceo)) |
||||
|
# Now we should be able to find the relation with the tab_id: |
||||
|
board_partners = relation_all_model.search([ |
||||
|
('tab_id', '=', self.tab_board.id)]) |
||||
|
self.assertTrue(bool(board_partners)) |
||||
|
self.assertIn( |
||||
|
self.partner_big_company, |
||||
|
[relation.this_partner_id for relation in board_partners]) |
||||
|
# We should find the company on the partner through tab field: |
||||
|
tab_obj = Tab(self.tab_board) |
||||
|
fieldname = tab_obj.get_fieldname() |
||||
|
self.assertTrue(fieldname in self.partner_model._fields) |
||||
|
board_partners = self.partner_big_company[fieldname] |
||||
|
self.assertEqual(len(board_partners), 1) |
||||
|
self.assertEqual( |
||||
|
board_partners.other_partner_id.id, |
||||
|
self.partner_important_person.id) |
||||
|
# When adding a new relation on a tab, type must be for tab. |
||||
|
onchange_result = board_partners.with_context( |
||||
|
default_tab_id=self.tab_board.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', '=', self.tab_board.id)) |
||||
|
|
||||
|
def test_compute_visibility(self): |
||||
|
"""Check the computation of visibility on partners.""" |
||||
|
# pylint: disable=protected-access |
||||
|
main_partner = self.env.ref('base.main_partner') |
||||
|
main_partner._compute_tabs_visibility() |
||||
|
tab_obj = Tab(self.tab_departments) |
||||
|
fieldname = tab_obj.get_fieldname() |
||||
|
visible_fieldname = tab_obj.get_visible_fieldname() |
||||
|
self.assertIn(visible_fieldname, main_partner._fields) |
||||
|
self.assertIn(fieldname, main_partner._fields) |
||||
|
self.assertEqual(main_partner[visible_fieldname], True) |
||||
|
department_relations = main_partner[fieldname] |
||||
|
self.assertTrue(len(department_relations) >= 1) |
||||
|
departments = [ |
||||
|
relation.other_partner_id for relation in department_relations] |
||||
|
for department in departments: |
||||
|
self.assertIn( |
||||
|
self.category_department, department.category_id) |
@ -0,0 +1,39 @@ |
|||||
|
# Copyright 2018 Therp BV <https://therp.nl>. |
||||
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). |
||||
|
from . import common |
||||
|
|
||||
|
from ..tablib import Tab |
||||
|
|
||||
|
|
||||
|
class TestTab(common.TestCommon): |
||||
|
|
||||
|
def test_create_page(self): |
||||
|
self.assertTrue(bool(self.tab_board)) |
||||
|
tab_obj = Tab(self.tab_board) |
||||
|
page = tab_obj.create_page() |
||||
|
# And we should have a field for (amongst others) selection_type_id. |
||||
|
field = page.xpath('//field[@name="type_selection_id"]') |
||||
|
self.assertTrue(field, 'Field selection_type_id not in page.') |
||||
|
|
||||
|
def test_visibility(self): |
||||
|
"""Tab positions should be shown for functionaries, but not others.""" |
||||
|
self.assertTrue(bool(self.tab_positions)) |
||||
|
self.assertTrue(bool(self.partner_important_person)) |
||||
|
self.assertTrue(bool(self.partner_common_person)) |
||||
|
tab_obj = Tab(self.tab_positions) |
||||
|
self.assertTrue( |
||||
|
tab_obj.compute_visibility(self.partner_important_person), |
||||
|
'Positions tab should be visible for functionary.') |
||||
|
self.assertFalse( |
||||
|
tab_obj.compute_visibility(self.partner_common_person), |
||||
|
'Positions tab should not be visible for non-functionary.') |
||||
|
# Tab for departments should only be visible for main partner |
||||
|
self.assertTrue(bool(self.tab_departments)) |
||||
|
self.assertTrue(bool(self.partner_big_company)) |
||||
|
tab_obj = Tab(self.tab_departments) |
||||
|
self.assertTrue( |
||||
|
tab_obj.compute_visibility(self.env.ref('base.main_partner')), |
||||
|
'Department tab should be visible for main partner.') |
||||
|
self.assertFalse( |
||||
|
tab_obj.compute_visibility(self.partner_big_company), |
||||
|
'Department tab should not be visible for other partners.') |
@ -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="partner_multi_relation.menu_res_partner_relation" |
||||
|
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,44 @@ |
|||||
|
<?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 colspan="6" col="4"> |
||||
|
<group |
||||
|
id="tab_group_general" string="General" |
||||
|
colspan="2" col="2" |
||||
|
> |
||||
|
<field name="code" /> |
||||
|
<field name="name" /> |
||||
|
</group> |
||||
|
<group |
||||
|
id="tab_group_target" |
||||
|
string="Select partner type and category for tab" |
||||
|
colspan="2" col="2" |
||||
|
> |
||||
|
<field name="contact_type" /> |
||||
|
<field name="partner_category_id" /> |
||||
|
</group> |
||||
|
<separator |
||||
|
colspan="2" |
||||
|
string="Select specific partners to have this tab" |
||||
|
/> |
||||
|
<field name="partner_ids" colspan="2" nolabel="1"/> |
||||
|
</group> |
||||
|
</form> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
</odoo> |