Holger Brunn
10 years ago
17 changed files with 1785 additions and 0 deletions
-
21partner_relations/__init__.py
-
94partner_relations/__openerp__.py
-
268partner_relations/i18n/nl.po
-
277partner_relations/i18n/partner_relations.pot
-
25partner_relations/model/__init__.py
-
238partner_relations/model/res_partner.py
-
330partner_relations/model/res_partner_relation.py
-
88partner_relations/model/res_partner_relation_all.py
-
48partner_relations/model/res_partner_relation_type.py
-
167partner_relations/model/res_partner_relation_type_selection.py
-
7partner_relations/security/ir.model.access.csv
-
BINpartner_relations/static/src/img/icon.png
-
15partner_relations/view/menu.xml
-
96partner_relations/view/res_partner.xml
-
33partner_relations/view/res_partner_relation.xml
-
34partner_relations/view/res_partner_relation_all.xml
-
44partner_relations/view/res_partner_relation_type.xml
@ -0,0 +1,21 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# This module copyright (C) 2013 Therp BV (<http://therp.nl>). |
|||
# |
|||
# This program is free software: you can redistribute it and/or modify |
|||
# it under the terms of the GNU Affero General Public License as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
import model |
@ -0,0 +1,94 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# This module copyright (C) 2013 Therp BV (<http://therp.nl>). |
|||
# |
|||
# This program is free software: you can redistribute it and/or modify |
|||
# it under the terms of the GNU Affero General Public License as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
{ |
|||
"name": "Partner relations", |
|||
"version": "1.1", |
|||
"author": "Therp BV", |
|||
"complexity": "normal", |
|||
"description": """ |
|||
Introduction |
|||
------------ |
|||
|
|||
This addon aims to provide generic means to model relations between partners. |
|||
|
|||
Examples would be 'is sibling of' or 'is friend of', but also 'has contract X |
|||
with' or 'is assistant of'. This way, you can enode your knowledge about your |
|||
partners directly in your partner list. |
|||
|
|||
Usage |
|||
----- |
|||
|
|||
Before being able to use relations, you'll have define some first. Do that in |
|||
Sales / Configuration / Address Book / Partner relations. Here, you need to |
|||
name both sides of the relation: To have an assistant-relation, you would name |
|||
one side 'is assistant of' and the other side 'has assistant'. This relation |
|||
only makes sense between people, so you would choose 'Person' for both partner |
|||
types. For the relation 'is a competitor of', both sides would be companies, |
|||
while the relation 'has worked for' should have persons on the left side and |
|||
companies on the right side. If you leave this field empty, the relation is |
|||
applicable to all types of partners. |
|||
|
|||
If you use categories to further specify the type of partners, you could for |
|||
example enforce that the 'is member of' relation can only have companies with |
|||
label 'Organization' on the left side. |
|||
|
|||
Now open a partner and choose relations as appropriate in the 'Relations' tab. |
|||
|
|||
Searching partners with relations |
|||
--------------------------------- |
|||
|
|||
Searching for relations is integrated transparently into the partner search |
|||
form. To find all assistants in your database, fill in 'is assistant of' and |
|||
autocomplete will propose to search for partners having this relation. Now if |
|||
you want to find Anna's assistant, you fill in 'Anna' and one of the proposals |
|||
is to search for partners having a relation with Anna. This results in Anna's |
|||
assistant(s), as you searched for assistants before. |
|||
|
|||
By default, only active, not expired relations are shown. If you need to find |
|||
partners that had some relation at a certain date, fill in that date in the |
|||
search box and one of the proposals is to search for relations valid at that |
|||
date.""", |
|||
"category": "Customer Relationship Management", |
|||
"depends": [ |
|||
'base', |
|||
'web_m2x_options', |
|||
'web_tree_many2one_clickable', |
|||
], |
|||
"data": [ |
|||
"view/res_partner_relation_all.xml", |
|||
'view/res_partner.xml', |
|||
'view/res_partner_relation.xml', |
|||
'view/res_partner_relation_type.xml', |
|||
'view/menu.xml', |
|||
'security/ir.model.access.csv', |
|||
], |
|||
"js": [ |
|||
], |
|||
"css": [ |
|||
], |
|||
"qweb": [ |
|||
], |
|||
"auto_install": False, |
|||
"installable": True, |
|||
"external_dependencies": { |
|||
'python': [], |
|||
}, |
|||
} |
@ -0,0 +1,268 @@ |
|||
# Translation of OpenERP Server. |
|||
# This file contains the translation of the following modules: |
|||
# * partner_relations |
|||
# |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: OpenERP Server 7.0\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2014-06-19 13:02+0000\n" |
|||
"PO-Revision-Date: 2014-06-19 13:02+0000\n" |
|||
"Last-Translator: <>\n" |
|||
"Language-Team: \n" |
|||
"MIME-Version: 1.0\n" |
|||
"Content-Type: text/plain; charset=UTF-8\n" |
|||
"Content-Transfer-Encoding: \n" |
|||
"Plural-Forms: \n" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation,active:0 |
|||
#: field:res.partner.relation.all,active:0 |
|||
msgid "Active" |
|||
msgstr "Actief" |
|||
|
|||
#. module: partner_relations |
|||
#: model:ir.model,name:partner_relations.model_res_partner_relation_all |
|||
msgid "All (non-inverse + inverse) relations between partners" |
|||
msgstr "Alle (non-inverse + inverse) koppelingen tussen relaties" |
|||
|
|||
#. module: partner_relations |
|||
#: model:ir.model,name:partner_relations.model_res_partner_relation_type_selection |
|||
msgid "All relation types" |
|||
msgstr "Alle relaties" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner,relation_all_ids:0 |
|||
msgid "All relations with current partner" |
|||
msgstr "Alle koppelingen met huidige relatie" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation.all,this_partner_id:0 |
|||
msgid "Current partner" |
|||
msgstr "Huidige relatie" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation.type.selection,partner_category_this:0 |
|||
#: field:res.partner.relation.type.selection,search_partner_category_this:0 |
|||
msgid "Current record's category" |
|||
msgstr "Categorie van huidige record" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation.type.selection,contact_type_this:0 |
|||
msgid "Current record's partner type" |
|||
msgstr "Relatietype van huidige record" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation,date_end:0 |
|||
#: field:res.partner.relation.all,date_end:0 |
|||
msgid "Ending date" |
|||
msgstr "Einddatum" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner,search_relation_id:0 |
|||
msgid "Has relation of type" |
|||
msgstr "Heeft koppeling" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner,search_relation_partner_id:0 |
|||
msgid "Has relation with" |
|||
msgstr "Heeft koppeling met" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation.type,name_inverse:0 |
|||
msgid "Inverse name" |
|||
msgstr "Inverse naam" |
|||
|
|||
#. module: partner_relations |
|||
#: selection:res.partner.relation.all,record_type:0 |
|||
#: selection:res.partner.relation.type.selection,record_type:0 |
|||
msgid "Inverse type" |
|||
msgstr "Inverse type" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation,left_partner_id:0 |
|||
msgid "Left partner" |
|||
msgstr "Linker relatie" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation.type,partner_category_left:0 |
|||
msgid "Left partner category" |
|||
msgstr "Linker relatielabel" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation.type,contact_type_left:0 |
|||
msgid "Left partner type" |
|||
msgstr "Linker relatietype" |
|||
|
|||
#. module: partner_relations |
|||
#: view:res.partner.relation.type:0 |
|||
msgid "Left side of relation" |
|||
msgstr "Linkerkant van de koppeling" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation.type,name:0 |
|||
#: field:res.partner.relation.type.selection,name:0 |
|||
msgid "Name" |
|||
msgstr "Naam" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation.all,other_partner_id:0 |
|||
msgid "Other partner" |
|||
msgstr "Andere relatie" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation.type.selection,partner_category_other:0 |
|||
msgid "Other record's category" |
|||
msgstr "Categorie andere record" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation.type.selection,contact_type_other:0 |
|||
msgid "Other record's partner type" |
|||
msgstr "Type andere record" |
|||
|
|||
#. module: partner_relations |
|||
#: model:ir.model,name:partner_relations.model_res_partner_relation_type |
|||
#: model:ir.model,name:partner_relations.model_res_partner_relation_type_inverse |
|||
msgid "Parter relation type" |
|||
msgstr "Type relatiekoppeling" |
|||
|
|||
#. module: partner_relations |
|||
#: model:ir.model,name:partner_relations.model_res_partner |
|||
#: field:res.partner.relation,partner_id_display:0 |
|||
msgid "Partner" |
|||
msgstr "Relatie" |
|||
|
|||
#. module: partner_relations |
|||
#: model:ir.model,name:partner_relations.model_res_partner_category |
|||
msgid "Partner Categories" |
|||
msgstr "Relatie Categorieën" |
|||
|
|||
#. module: partner_relations |
|||
#: model:ir.model,name:partner_relations.model_res_partner_relation |
|||
#: view:res.partner.relation:0 |
|||
#: view:res.partner.relation.type:0 |
|||
msgid "Partner relation" |
|||
msgstr "Relatiekoppeling" |
|||
|
|||
#. module: partner_relations |
|||
#: model:ir.actions.act_window,name:partner_relations.action_res_partner_relation_type |
|||
#: model:ir.ui.menu,name:partner_relations.menu_res_partner_relation_type |
|||
msgid "Partner relations" |
|||
msgstr "Relatiekoppelingen" |
|||
|
|||
#. module: partner_relations |
|||
#: constraint:res.partner.relation:0 |
|||
msgid "Partners cannot have a relation with themselves." |
|||
msgstr "Relaties kunnen niet aan zichzelf gekoppeld worden." |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation.all,record_type:0 |
|||
#: field:res.partner.relation.type.selection,record_type:0 |
|||
msgid "Record type" |
|||
msgstr "Record type" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation.all,relation_id:0 |
|||
msgid "Relation" |
|||
msgstr "Koppeling" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation,is_relation_expired:0 |
|||
msgid "Relation is expired" |
|||
msgstr "Koppeling is afgelopen" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation,is_relation_future:0 |
|||
msgid "Relation is in the future" |
|||
msgstr "Koppeling is in de toekomst" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation.all,type_id:0 |
|||
msgid "Relation type" |
|||
msgstr "Koppelingstype" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner,search_relation_date:0 |
|||
msgid "Relation valid" |
|||
msgstr "Datum koppeling" |
|||
|
|||
#. module: partner_relations |
|||
#: view:res.partner:0 |
|||
#: field:res.partner,relation_ids:0 |
|||
msgid "Relations" |
|||
msgstr "Koppelingen" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation,right_partner_id:0 |
|||
msgid "Right partner" |
|||
msgstr "Rechter relatie" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation.type,partner_category_right:0 |
|||
msgid "Right partner category" |
|||
msgstr "Rechter relatielabel" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation.type,contact_type_right:0 |
|||
msgid "Right partner type" |
|||
msgstr "Rechter relatietype" |
|||
|
|||
#. module: partner_relations |
|||
#: view:res.partner.relation.type:0 |
|||
msgid "Right side of relation" |
|||
msgstr "Rechterkant van de koppeling" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation,date_start:0 |
|||
#: field:res.partner.relation.all,date_start:0 |
|||
msgid "Starting date" |
|||
msgstr "Begindatum" |
|||
|
|||
#. module: partner_relations |
|||
#: constraint:res.partner.relation:0 |
|||
msgid "The left partner is not applicable for this relation type." |
|||
msgstr "De linker relatie is niet geldig voor dit type koppeling." |
|||
|
|||
#. module: partner_relations |
|||
#: constraint:res.partner.relation:0 |
|||
msgid "The right partner is not applicable for this relation type." |
|||
msgstr "De rechter relatie is niet geldig voor dit type koppeling." |
|||
|
|||
#. module: partner_relations |
|||
#: constraint:res.partner.relation:0 |
|||
msgid "The starting date cannot be after the ending date." |
|||
msgstr "De begindatum mag niet na de einddatum liggen." |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation,type_id:0 |
|||
#: field:res.partner.relation,type_selection_id:0 |
|||
#: selection:res.partner.relation.all,record_type:0 |
|||
#: selection:res.partner.relation.type.selection,record_type:0 |
|||
#: field:res.partner.relation.type.selection,type_id:0 |
|||
msgid "Type" |
|||
msgstr "Type" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.category,only_for_organisation:0 |
|||
msgid "Valid for organisation only" |
|||
msgstr "Alleen geldig voor organisaties" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.category,only_for_person:0 |
|||
msgid "Valid for person only" |
|||
msgstr "Alleen geldig voor personen" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner,search_relation_partner_category_id:0 |
|||
msgid "Has relation with a partner in category" |
|||
msgstr "Heeft koppeling met relatie van de categorie" |
|||
|
|||
#. module: partner_relations |
|||
#: model:ir.actions.act_window,name:partner_relations.action_show_partner_relations |
|||
msgid "Show partner's relations" |
|||
msgstr "Toon relatiekoppelingen" |
|||
|
|||
#. module: partner_relations |
|||
#: constraint:res.partner.relation:0 |
|||
msgid "The same relation can't be created twice." |
|||
msgstr "Dezelfde koppeling kan niet dubbel aan worden gemaakt." |
@ -0,0 +1,277 @@ |
|||
# Translation of OpenERP Server. |
|||
# This file contains the translation of the following modules: |
|||
# * partner_relations |
|||
# |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: OpenERP Server 7.0\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2014-07-01 08:52+0000\n" |
|||
"PO-Revision-Date: 2014-07-01 08:52+0000\n" |
|||
"Last-Translator: <>\n" |
|||
"Language-Team: \n" |
|||
"MIME-Version: 1.0\n" |
|||
"Content-Type: text/plain; charset=UTF-8\n" |
|||
"Content-Transfer-Encoding: \n" |
|||
"Plural-Forms: \n" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation,active:0 |
|||
#: field:res.partner.relation.all,active:0 |
|||
msgid "Active" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: model:ir.model,name:partner_relations.model_res_partner_relation_all |
|||
msgid "All (non-inverse + inverse) relations between partners" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: model:ir.model,name:partner_relations.model_res_partner_relation_type_selection |
|||
msgid "All relation types" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner,relation_all_ids:0 |
|||
msgid "All relations with current partner" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation.all,this_partner_id:0 |
|||
msgid "Current partner" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation.type.selection,partner_category_this:0 |
|||
#: field:res.partner.relation.type.selection,search_partner_category_this:0 |
|||
msgid "Current record's category" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation.type.selection,contact_type_this:0 |
|||
msgid "Current record's partner type" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation,date_end:0 |
|||
#: field:res.partner.relation.all,date_end:0 |
|||
msgid "Ending date" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner,search_relation_id:0 |
|||
msgid "Has relation of type" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner,search_relation_partner_id:0 |
|||
msgid "Has relation with" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner,search_relation_partner_category_id:0 |
|||
msgid "Has relation with a partner in category" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation.type,name_inverse:0 |
|||
msgid "Inverse name" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: selection:res.partner.relation.all,record_type:0 |
|||
#: selection:res.partner.relation.type.selection,record_type:0 |
|||
msgid "Inverse type" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation,left_partner_id:0 |
|||
msgid "Left partner" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation.type,partner_category_left:0 |
|||
msgid "Left partner category" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation.type,contact_type_left:0 |
|||
msgid "Left partner type" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: view:res.partner.relation.type:0 |
|||
msgid "Left side of relation" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation.type,name:0 |
|||
#: field:res.partner.relation.type.selection,name:0 |
|||
msgid "Name" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation.all,other_partner_id:0 |
|||
msgid "Other partner" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation.type.selection,partner_category_other:0 |
|||
msgid "Other record's category" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation.type.selection,contact_type_other:0 |
|||
msgid "Other record's partner type" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: model:ir.model,name:partner_relations.model_res_partner_relation_type |
|||
#: model:ir.model,name:partner_relations.model_res_partner_relation_type_inverse |
|||
msgid "Parter relation type" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: model:ir.model,name:partner_relations.model_res_partner |
|||
#: field:res.partner.relation,partner_id_display:0 |
|||
msgid "Partner" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: model:ir.model,name:partner_relations.model_res_partner_category |
|||
msgid "Partner Categories" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: model:ir.model,name:partner_relations.model_res_partner_relation |
|||
#: view:res.partner.relation:0 |
|||
#: view:res.partner.relation.all:0 |
|||
#: view:res.partner.relation.type:0 |
|||
msgid "Partner relation" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: model:ir.actions.act_window,name:partner_relations.action_res_partner_relation_type |
|||
#: model:ir.ui.menu,name:partner_relations.menu_res_partner_relation_type |
|||
#: view:res.partner.relation.all:0 |
|||
msgid "Partner relations" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: constraint:res.partner.relation:0 |
|||
msgid "Partners cannot have a relation with themselves." |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation.all,record_type:0 |
|||
#: field:res.partner.relation.type.selection,record_type:0 |
|||
msgid "Record type" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation.all,relation_id:0 |
|||
msgid "Relation" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation,is_relation_expired:0 |
|||
msgid "Relation is expired" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation,is_relation_future:0 |
|||
msgid "Relation is in the future" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation.all,type_id:0 |
|||
#: field:res.partner.relation.all,type_selection_id:0 |
|||
msgid "Relation type" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner,search_relation_date:0 |
|||
msgid "Relation valid" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: view:res.partner:0 |
|||
#: field:res.partner,relation_ids:0 |
|||
msgid "Relations" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation,right_partner_id:0 |
|||
msgid "Right partner" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation.type,partner_category_right:0 |
|||
msgid "Right partner category" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation.type,contact_type_right:0 |
|||
msgid "Right partner type" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: view:res.partner.relation.type:0 |
|||
msgid "Right side of relation" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: model:ir.actions.act_window,name:partner_relations.action_show_partner_relations |
|||
msgid "Show partner's relations" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation,date_start:0 |
|||
#: field:res.partner.relation.all,date_start:0 |
|||
msgid "Starting date" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: constraint:res.partner.relation:0 |
|||
msgid "The left partner is not applicable for this relation type." |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: constraint:res.partner.relation:0 |
|||
msgid "The right partner is not applicable for this relation type." |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: sql_constraint:res.partner.relation:0 |
|||
msgid "The same relation can't be created twice." |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: constraint:res.partner.relation:0 |
|||
msgid "The starting date cannot be after the ending date." |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.relation,type_id:0 |
|||
#: field:res.partner.relation,type_selection_id:0 |
|||
#: selection:res.partner.relation.all,record_type:0 |
|||
#: selection:res.partner.relation.type.selection,record_type:0 |
|||
#: field:res.partner.relation.type.selection,type_id:0 |
|||
msgid "Type" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.category,only_for_organisation:0 |
|||
msgid "Valid for organisation only" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: field:res.partner.category,only_for_person:0 |
|||
msgid "Valid for person only" |
|||
msgstr "" |
|||
|
|||
#. module: partner_relations |
|||
#: model:ir.model,name:partner_relations.model_ir_translation |
|||
msgid "ir.translation" |
|||
msgstr "" |
|||
|
@ -0,0 +1,25 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# This module copyright (C) 2013 Therp BV (<http://therp.nl>). |
|||
# |
|||
# This program is free software: you can redistribute it and/or modify |
|||
# it under the terms of the GNU Affero General Public License as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
import res_partner |
|||
import res_partner_relation |
|||
import res_partner_relation_type |
|||
import res_partner_relation_type_selection |
|||
from . import res_partner_relation_all |
@ -0,0 +1,238 @@ |
|||
# -*- coding: utf-8 -*- |
|||
'''Extend res.partner model''' |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# This module copyright (C) 2013 Therp BV (<http://therp.nl>). |
|||
# |
|||
# This program is free software: you can redistribute it and/or modify |
|||
# it under the terms of the GNU Affero General Public License as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
import time |
|||
from openerp.osv import orm, fields |
|||
from openerp.osv.expression import is_leaf |
|||
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT |
|||
|
|||
|
|||
class ResPartner(orm.Model): |
|||
_inherit = 'res.partner' |
|||
|
|||
def _get_relation_ids( |
|||
self, cr, uid, ids, dummy_name, dummy_arg, context=None): |
|||
if context is None: |
|||
context = {} |
|||
|
|||
#TODO: do a permission test on returned ids |
|||
cr.execute( |
|||
'''select id, left_partner_id, right_partner_id |
|||
from res_partner_relation |
|||
where (left_partner_id in %s or right_partner_id in %s)''' + |
|||
' order by ' + self.pool['res.partner.relation']._order, |
|||
(tuple(ids), tuple(ids)) |
|||
) |
|||
result = dict([(i, []) for i in ids]) |
|||
for row in cr.fetchall(): |
|||
if row[1] in result: |
|||
result[row[1]].append(row[0]) |
|||
if row[2] in result: |
|||
result[row[2]].append(row[0]) |
|||
return result |
|||
|
|||
def _set_relation_ids( |
|||
self, cr, uid, ids, dummy_name, field_value, dummy_arg, |
|||
context=None): |
|||
if context is None: |
|||
context = {} |
|||
relation_obj = self.pool.get('res.partner.relation') |
|||
context2 = self._update_context(context, ids) |
|||
for value in field_value: |
|||
if value[0] == 0: |
|||
relation_obj.create(cr, uid, value[2], context=context2) |
|||
if value[0] == 1: |
|||
relation_obj.write( |
|||
cr, uid, value[1], value[2], context=context2) |
|||
if value[0] == 2: |
|||
relation_obj.unlink(cr, uid, value[1], context=context2) |
|||
|
|||
def _search_relation_id( |
|||
self, cr, uid, dummy_obj, name, args, context=None): |
|||
result = [] |
|||
for arg in args: |
|||
if isinstance(arg, tuple) and arg[0] == name: |
|||
if arg[1] != '=': |
|||
continue |
|||
|
|||
type_id, is_inverse = self\ |
|||
.pool['res.partner.relation.type.selection']\ |
|||
.get_type_from_selection_id(cr, uid, arg[2]) |
|||
|
|||
result.extend([ |
|||
'&', |
|||
('relation_all_ids.type_id', '=', type_id), |
|||
('relation_all_ids.record_type', '=', |
|||
'b' if is_inverse else 'a') |
|||
]) |
|||
|
|||
return result |
|||
|
|||
def _search_relation_date(self, cr, uid, obj, name, args, context=None): |
|||
result = [] |
|||
for arg in args: |
|||
if isinstance(arg, tuple) and arg[0] == name: |
|||
#TODO: handle {<,>}{,=} |
|||
if arg[1] != '=': |
|||
continue |
|||
|
|||
result.extend([ |
|||
'&', |
|||
'|', |
|||
('relation_all_ids.date_start', '=', False), |
|||
('relation_all_ids.date_start', '<=', arg[2]), |
|||
'|', |
|||
('relation_all_ids.date_end', '=', False), |
|||
('relation_all_ids.date_end', '>=', arg[2]), |
|||
]) |
|||
|
|||
return result |
|||
|
|||
def _search_related_partner_id( |
|||
self, cr, uid, dummy_obj, name, args, context=None): |
|||
result = [] |
|||
for arg in args: |
|||
if isinstance(arg, tuple) and arg[0] == name: |
|||
result.append( |
|||
( |
|||
'relation_all_ids.other_partner_id', |
|||
arg[1], |
|||
arg[2], |
|||
)) |
|||
|
|||
return result |
|||
|
|||
def _search_related_partner_category_id( |
|||
self, cr, uid, dummy_obj, name, args, context=None): |
|||
result = [] |
|||
for arg in args: |
|||
if isinstance(arg, tuple) and arg[0] == name: |
|||
result.append( |
|||
( |
|||
'relation_all_ids.other_partner_id.category_id', |
|||
arg[1], |
|||
arg[2], |
|||
)) |
|||
|
|||
return result |
|||
|
|||
_columns = { |
|||
'relation_ids': fields.function( |
|||
lambda self, *args, **kwargs: self._get_relation_ids( |
|||
*args, **kwargs), |
|||
fnct_inv=_set_relation_ids, |
|||
type='one2many', obj='res.partner.relation', |
|||
string='Relations', |
|||
selectable=False, |
|||
), |
|||
'relation_all_ids': fields.one2many( |
|||
'res.partner.relation.all', 'this_partner_id', |
|||
string='All relations with current partner', |
|||
auto_join=True, |
|||
selectable=False, |
|||
), |
|||
'search_relation_id': fields.function( |
|||
lambda self, cr, uid, ids, *args: dict([ |
|||
(i, False) for i in ids]), |
|||
fnct_search=_search_relation_id, |
|||
string='Has relation of type', |
|||
type='many2one', obj='res.partner.relation.type.selection' |
|||
), |
|||
'search_relation_partner_id': fields.function( |
|||
lambda self, cr, uid, ids, *args: dict([ |
|||
(i, False) for i in ids]), |
|||
fnct_search=_search_related_partner_id, |
|||
string='Has relation with', |
|||
type='many2one', obj='res.partner' |
|||
), |
|||
'search_relation_date': fields.function( |
|||
lambda self, cr, uid, ids, *args: dict([ |
|||
(i, False) for i in ids]), |
|||
fnct_search=_search_relation_date, |
|||
string='Relation valid', type='date' |
|||
), |
|||
'search_relation_partner_category_id': fields.function( |
|||
lambda self, cr, uid, ids, *args: dict([ |
|||
(i, False) for i in ids]), |
|||
fnct_search=_search_related_partner_category_id, |
|||
string='Has relation with a partner in category', |
|||
type='many2one', obj='res.partner.category' |
|||
), |
|||
} |
|||
|
|||
def copy_data(self, cr, uid, id, default=None, context=None): |
|||
if default is None: |
|||
default = {} |
|||
default.setdefault('relation_ids', []) |
|||
default.setdefault('relation_all_ids', []) |
|||
return super(ResPartner, self).copy_data(cr, uid, id, default=default, |
|||
context=context) |
|||
|
|||
def search(self, cr, uid, args, offset=0, limit=None, order=None, |
|||
context=None, count=False): |
|||
if context is None: |
|||
context = {} |
|||
#inject searching for current relation date if we search for relation |
|||
#properties and no explicit date was given |
|||
date_args = [] |
|||
for arg in args: |
|||
if is_leaf(arg) and arg[0].startswith('search_relation'): |
|||
if arg[0] == 'search_relation_date': |
|||
date_args = [] |
|||
break |
|||
if not date_args: |
|||
date_args = [ |
|||
('search_relation_date', '=', time.strftime( |
|||
DEFAULT_SERVER_DATE_FORMAT))] |
|||
|
|||
#because of auto_join, we have to do the active test by hand |
|||
active_args = [] |
|||
if context.get('active_test', True): |
|||
for arg in args: |
|||
if is_leaf(arg) and\ |
|||
arg[0].startswith('search_relation'): |
|||
active_args = [('relation_all_ids.active', '=', True)] |
|||
break |
|||
|
|||
return super(ResPartner, self).search( |
|||
cr, uid, args + date_args + active_args, offset=offset, |
|||
limit=limit, order=order, context=context, count=count) |
|||
|
|||
def read( |
|||
self, cr, uid, ids, fields=None, context=None, |
|||
load='_classic_read'): |
|||
return super(ResPartner, self).read( |
|||
cr, uid, ids, fields=fields, |
|||
context=self._update_context(context, ids)) |
|||
|
|||
def write(self, cr, uid, ids, vals, context=None): |
|||
return super(ResPartner, self).write( |
|||
cr, uid, ids, vals, context=self._update_context(context, ids)) |
|||
|
|||
def _update_context(self, context, ids): |
|||
if context is None: |
|||
context = {} |
|||
ids = ids if isinstance(ids, list) else [ids] if ids else [] |
|||
result = context.copy() |
|||
result.setdefault('active_id', ids[0] if ids else None) |
|||
result.setdefault('active_ids', ids) |
|||
result.setdefault('active_model', self._name) |
|||
return result |
@ -0,0 +1,330 @@ |
|||
# -*- coding: utf-8 -*- |
|||
'''Define model res.partner.relation''' |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# This module copyright (C) 2013 Therp BV (<http://therp.nl>). |
|||
# |
|||
# This program is free software: you can redistribute it and/or modify |
|||
# it under the terms of the GNU Affero General Public License as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
from openerp.osv.orm import Model |
|||
from openerp.osv import fields |
|||
from openerp.tools.translate import _ |
|||
|
|||
|
|||
class ResPartnerRelation(Model): |
|||
'''Model res.partner.relation is used to describe all links or relations |
|||
between partners in the database. |
|||
|
|||
In many parts of the code we have to know whether the active partner is |
|||
the left partner, or the right partner. If the active partner is the |
|||
right partner we have to show the inverse name. |
|||
|
|||
Because the active partner is crucial for the working of partner |
|||
relationships, we make sure on the res.partner model that the partner id |
|||
is set in the context where needed. |
|||
''' |
|||
_name = 'res.partner.relation' |
|||
_description = 'Partner relation' |
|||
_order = 'active desc, date_start desc, date_end desc' |
|||
|
|||
def _on_right_partner(self, cr, uid, right_partner_id, context=None): |
|||
'''Determine wether functions are called in a situation where the |
|||
active partner is the right partner. Default False! |
|||
''' |
|||
if (context and 'active_ids' in context |
|||
and right_partner_id in context.get('active_ids', [])): |
|||
return True |
|||
return False |
|||
|
|||
def _correct_vals(self, cr, uid, vals, context=None): |
|||
'''Fill type and left and right partner id, according to wether |
|||
we have a normal relation type or an inverse relation type''' |
|||
vals = vals.copy() |
|||
# If type_selection_id ends in 1, it is a reverse relation type |
|||
if 'type_selection_id' in vals: |
|||
prts_model = self.pool['res.partner.relation.type.selection'] |
|||
type_selection_id = vals['type_selection_id'] |
|||
(type_id, is_reverse) = ( |
|||
prts_model.get_type_from_selection_id( |
|||
cr, uid, type_selection_id)) |
|||
vals['type_id'] = type_id |
|||
if context.get('active_id'): |
|||
if is_reverse: |
|||
vals['right_partner_id'] = context['active_id'] |
|||
else: |
|||
vals['left_partner_id'] = context['active_id'] |
|||
if vals.get('partner_id_display'): |
|||
if is_reverse: |
|||
vals['left_partner_id'] = vals['partner_id_display'] |
|||
else: |
|||
vals['right_partner_id'] = vals['partner_id_display'] |
|||
return vals |
|||
|
|||
def _get_computed_fields( |
|||
self, cr, uid, ids, field_names, arg, context=None): |
|||
'''Return a dictionary of dictionaries, with for every partner for |
|||
ids, the computed values.''' |
|||
def get_values(this, dummy_field_names, dummy_arg, context=None): |
|||
'''Get computed values for record''' |
|||
values = {} |
|||
on_right_partner = self._on_right_partner( |
|||
cr, uid, this.right_partner_id.id, context=context) |
|||
# type_selection_id |
|||
values['type_selection_id'] = ( |
|||
((this.type_id.id) * 10) + (on_right_partner and 1 or 0)) |
|||
# partner_id_display |
|||
values['partner_id_display'] = ( |
|||
on_right_partner and this.left_partner_id.id |
|||
or this.right_partner_id.id |
|||
) |
|||
# is_relation_expired |
|||
today = fields.date.context_today(self, cr, uid, context=context) |
|||
values['is_relation_expired'] = ( |
|||
this.date_end and (this.date_end < today)) |
|||
# is_relation_future |
|||
values['is_relation_future'] = this.date_start > today |
|||
return values |
|||
|
|||
return dict([ |
|||
(this.id, get_values(this, field_names, arg, context=context)) |
|||
for this in self.browse(cr, uid, ids, context=context) |
|||
]) |
|||
|
|||
def write(self, cr, uid, ids, vals, context=None): |
|||
'''Override write to correct values, before being stored.''' |
|||
vals = self._correct_vals(cr, uid, vals, context=context) |
|||
return super(ResPartnerRelation, self).write( |
|||
cr, uid, ids, vals, context=context) |
|||
|
|||
def create(self, cr, uid, vals, context=None): |
|||
'''Override create to correct values, before being stored.''' |
|||
vals = self._correct_vals(cr, uid, vals, context=context) |
|||
return super(ResPartnerRelation, self).create( |
|||
cr, uid, vals, context=context) |
|||
|
|||
def on_change_type_selection_id( |
|||
self, cr, uid, dummy_ids, type_selection_id, context=None): |
|||
'''Set domain on partner_id_display, when selection a relation type''' |
|||
result = { |
|||
'domain': {'partner_id_display': []}, |
|||
'value': {'type_id': False} |
|||
} |
|||
if not type_selection_id: |
|||
return result |
|||
prts_model = self.pool['res.partner.relation.type.selection'] |
|||
type_model = self.pool['res.partner.relation.type'] |
|||
(type_id, is_reverse) = ( |
|||
prts_model.get_type_from_selection_id( |
|||
cr, uid, type_selection_id) |
|||
) |
|||
result['value']['type_id'] = type_id |
|||
type_obj = type_model.browse(cr, uid, type_id, context=context) |
|||
partner_domain = [] |
|||
check_contact_type = type_obj.contact_type_right |
|||
check_partner_category = ( |
|||
type_obj.partner_category_right and |
|||
type_obj.partner_category_right.id |
|||
) |
|||
if is_reverse: |
|||
# partner_id_display is left partner |
|||
check_contact_type = type_obj.contact_type_left |
|||
check_partner_category = ( |
|||
type_obj.partner_category_left and |
|||
type_obj.partner_category_left.id |
|||
) |
|||
if check_contact_type == 'c': |
|||
partner_domain.append(('is_company', '=', True)) |
|||
if check_contact_type == 'p': |
|||
partner_domain.append(('is_company', '=', False)) |
|||
if check_partner_category: |
|||
partner_domain.append( |
|||
('category_id', 'child_of', check_partner_category)) |
|||
result['domain']['partner_id_display'] = partner_domain |
|||
return result |
|||
|
|||
_columns = { |
|||
'left_partner_id': fields.many2one( |
|||
'res.partner', string='Left partner', required=True, |
|||
auto_join=True, ondelete='cascade'), |
|||
'right_partner_id': fields.many2one( |
|||
'res.partner', string='Right partner', required=True, |
|||
auto_join=True, ondelete='cascade'), |
|||
'type_id': fields.many2one( |
|||
'res.partner.relation.type', string='Type', required=True, |
|||
auto_join=True), |
|||
'date_start': fields.date('Starting date'), |
|||
'date_end': fields.date('Ending date'), |
|||
'type_selection_id': fields.function( |
|||
_get_computed_fields, |
|||
multi="computed_fields", |
|||
fnct_inv=lambda *args: None, |
|||
type='many2one', obj='res.partner.relation.type.selection', |
|||
string='Type', |
|||
), |
|||
'partner_id_display': fields.function( |
|||
_get_computed_fields, |
|||
multi="computed_fields", |
|||
fnct_inv=lambda *args: None, |
|||
type='many2one', obj='res.partner', |
|||
string='Partner' |
|||
), |
|||
'is_relation_expired': fields.function( |
|||
_get_computed_fields, |
|||
multi="computed_fields", |
|||
type='boolean', |
|||
method=True, |
|||
string='Relation is expired', |
|||
), |
|||
'is_relation_future': fields.function( |
|||
_get_computed_fields, |
|||
multi="computed_fields", |
|||
type='boolean', |
|||
method=True, |
|||
string='Relation is in the future', |
|||
), |
|||
'active': fields.boolean('Active'), |
|||
} |
|||
|
|||
_defaults = { |
|||
'active': True, |
|||
} |
|||
|
|||
def _check_dates(self, cr, uid, ids, context=None): |
|||
'''End date should not be before start date, if noth filled''' |
|||
for line in self.browse(cr, uid, ids, context=context): |
|||
if line.date_start and line.date_end: |
|||
if line.date_start > line.date_end: |
|||
return False |
|||
return True |
|||
|
|||
def _check_partner_type_left(self, cr, uid, ids, context=None): |
|||
'''Check left partner for required company or person''' |
|||
for this in self.browse(cr, uid, ids, context=context): |
|||
ptype = this.type_id.contact_type_left |
|||
company = this.left_partner_id.is_company |
|||
if (ptype == 'c' and not company) or (ptype == 'p' and company): |
|||
return False |
|||
return True |
|||
|
|||
def _check_partner_type_right(self, cr, uid, ids, context=None): |
|||
'''Check right partner for required company or person''' |
|||
for this in self.browse(cr, uid, ids, context=context): |
|||
ptype = this.type_id.contact_type_right |
|||
company = this.right_partner_id.is_company |
|||
if (ptype == 'c' and not company) or (ptype == 'p' and company): |
|||
return False |
|||
return True |
|||
|
|||
def _check_not_with_self(self, cr, uid, ids, context=None): |
|||
'''Not allowed to link partner to same partner''' |
|||
for this in self.browse(cr, uid, ids, context=context): |
|||
if this.left_partner_id == this.right_partner_id: |
|||
return False |
|||
return True |
|||
|
|||
def _check_relation_uniqueness(self, cr, uid, ids, context=None): |
|||
'''Forbid multiple active relations of the same type between the same |
|||
partners''' |
|||
for this in self.browse(cr, uid, ids, context=context): |
|||
if not this.active: |
|||
continue |
|||
if self.search( |
|||
cr, uid, |
|||
[ |
|||
('type_id', '=', this.type_id.id), |
|||
('active', '=', True), |
|||
('id', '!=', this.id), |
|||
('left_partner_id', '=', this.left_partner_id.id), |
|||
('right_partner_id', '=', this.right_partner_id.id), |
|||
], |
|||
context=context): |
|||
return False |
|||
|
|||
return True |
|||
|
|||
_constraints = [ |
|||
( |
|||
_check_dates, |
|||
'The starting date cannot be after the ending date.', |
|||
['date_start', 'date_end'] |
|||
), |
|||
( |
|||
_check_partner_type_left, |
|||
'The left partner is not applicable for this relation type.', |
|||
['left_partner_id', 'type_id'] |
|||
), |
|||
( |
|||
_check_partner_type_right, |
|||
'The right partner is not applicable for this relation type.', |
|||
['right_partner_id', 'type_id'] |
|||
), |
|||
( |
|||
_check_not_with_self, |
|||
'Partners cannot have a relation with themselves.', |
|||
['left_partner_id', 'right_partner_id'] |
|||
), |
|||
( |
|||
_check_relation_uniqueness, |
|||
"The same relation can't be created twice.", |
|||
['left_partner_id', 'right_partner_id', 'active'] |
|||
) |
|||
] |
|||
|
|||
def get_action_related_partners(self, cr, uid, ids, context=None): |
|||
'''return a window action showing a list of partners taking part in the |
|||
relations names by ids. Context key 'partner_relations_show_side' |
|||
determines if we show 'left' side, 'right' side or 'all' (default) |
|||
partners. |
|||
If active_model is res.partner.relation.all, left=this and |
|||
right=other''' |
|||
if context is None: |
|||
context = {} |
|||
|
|||
field_names = {} |
|||
|
|||
if context.get('active_model', self._name) == self._name: |
|||
field_names = { |
|||
'left': ['left'], |
|||
'right': ['right'], |
|||
'all': ['left', 'right'] |
|||
} |
|||
elif context.get('active_model') == 'res.partner.relation.all': |
|||
field_names = { |
|||
'left': ['this'], |
|||
'right': ['other'], |
|||
'all': ['this', 'other'] |
|||
} |
|||
else: |
|||
assert False, 'Unknown active_model!' |
|||
|
|||
partner_ids = [] |
|||
field_names = field_names[ |
|||
context.get('partner_relations_show_side', 'all')] |
|||
field_names = ['%s_partner_id' % n for n in field_names] |
|||
|
|||
for relation in self.pool[context.get('active_model')].read( |
|||
cr, uid, ids, context=context, load='_classic_write'): |
|||
for name in field_names: |
|||
partner_ids.append(relation[name]) |
|||
|
|||
return { |
|||
'name': _('Related partners'), |
|||
'type': 'ir.actions.act_window', |
|||
'res_model': 'res.partner', |
|||
'domain': [('id', 'in', partner_ids)], |
|||
'views': [(False, 'tree'), (False, 'form')], |
|||
'view_type': 'form' |
|||
} |
@ -0,0 +1,88 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# This module copyright (C) 2014 Therp BV (<http://therp.nl>). |
|||
# |
|||
# This program is free software: you can redistribute it and/or modify |
|||
# it under the terms of the GNU Affero General Public License as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
from openerp.osv.orm import Model |
|||
from openerp.osv import fields |
|||
from openerp.tools import drop_view_if_exists |
|||
from res_partner_relation_type_selection import ResPartnerRelationTypeSelection |
|||
|
|||
|
|||
class ResPartnerRelationAll(Model): |
|||
_auto = False |
|||
_log_access = False |
|||
_name = 'res.partner.relation.all' |
|||
_description = 'All (non-inverse + inverse) relations between partners' |
|||
|
|||
def _auto_init(self, cr, context=None): |
|||
drop_view_if_exists(cr, self._table) |
|||
cr.execute( |
|||
'''create or replace view %s as |
|||
select |
|||
id * 10 as id, |
|||
id as relation_id, |
|||
type_id, |
|||
cast('a' as char(1)) as record_type, |
|||
left_partner_id as this_partner_id, |
|||
right_partner_id as other_partner_id, |
|||
date_start, |
|||
date_end, |
|||
active, |
|||
type_id * 10 as type_selection_id |
|||
from res_partner_relation |
|||
union select |
|||
id * 10 + 1, |
|||
id, |
|||
type_id, |
|||
cast('b' as char(1)), |
|||
right_partner_id, |
|||
left_partner_id, |
|||
date_start, |
|||
date_end, |
|||
active, |
|||
type_id * 10 + 1 |
|||
from res_partner_relation''' % self._table) |
|||
|
|||
return super(ResPartnerRelationAll, self)._auto_init( |
|||
cr, context=context) |
|||
|
|||
_columns = { |
|||
'record_type': fields.selection( |
|||
ResPartnerRelationTypeSelection._RECORD_TYPES, 'Record type'), |
|||
'relation_id': fields.many2one( |
|||
'res.partner.relation', 'Relation'), |
|||
'type_id': fields.many2one( |
|||
'res.partner.relation.type', 'Relation type'), |
|||
'type_selection_id': fields.many2one( |
|||
'res.partner.relation.type.selection', 'Relation type'), |
|||
'this_partner_id': fields.many2one('res.partner', 'Current partner'), |
|||
'other_partner_id': fields.many2one('res.partner', 'Other partner'), |
|||
'date_start': fields.date('Starting date'), |
|||
'date_end': fields.date('Ending date'), |
|||
'active': fields.boolean('Active'), |
|||
} |
|||
|
|||
def name_get(self, cr, uid, ids, context=None): |
|||
return dict([ |
|||
(this.id, '%s %s %s' % ( |
|||
this.this_partner_id.name, |
|||
this.type_selection_id.name_get()[0][1], |
|||
this.other_partner_id.name, |
|||
)) |
|||
for this in self.browse(cr, uid, ids, context=context)]) |
@ -0,0 +1,48 @@ |
|||
# -*- coding: utf-8 -*- |
|||
'''Define model res.partner.relation.type''' |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# This module copyright (C) 2013 Therp BV (<http://therp.nl>). |
|||
# |
|||
# This program is free software: you can redistribute it and/or modify |
|||
# it under the terms of the GNU Affero General Public License as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
from openerp.osv.orm import Model |
|||
from openerp.osv import fields |
|||
|
|||
|
|||
class ResPartnerRelationType(Model): |
|||
'''Model that defines relation types that might exist between partners''' |
|||
_name = 'res.partner.relation.type' |
|||
_description = 'Parter relation type' |
|||
_order = 'name' |
|||
|
|||
def _get_partner_types(self, cr, uid, context=None): |
|||
return (('c', 'Company'), ('p', 'Person'),) |
|||
|
|||
_columns = { |
|||
'name': fields.char( |
|||
'Name', size=128, required=True, translate=True), |
|||
'name_inverse': fields.char( |
|||
'Inverse name', size=128, required=True, translate=True), |
|||
'contact_type_left': fields.selection( |
|||
_get_partner_types, 'Left partner type'), |
|||
'contact_type_right': fields.selection( |
|||
_get_partner_types, 'Right partner type'), |
|||
'partner_category_left': fields.many2one( |
|||
'res.partner.category', 'Left partner category'), |
|||
'partner_category_right': fields.many2one( |
|||
'res.partner.category', 'Right partner category'), |
|||
} |
@ -0,0 +1,167 @@ |
|||
# -*- coding: UTF-8 -*- |
|||
''' |
|||
Created on 23 may 2014 |
|||
|
|||
@author: Ronald Portier, Therp |
|||
|
|||
rportier@therp.nl |
|||
http://www.therp.nl |
|||
|
|||
For the model defined here _auto is set to False to prevent creating a |
|||
database file. All i/o operations are overridden to use a sql SELECT that |
|||
takes data from res_partner_connection_type where each type is included in the |
|||
result set twice, so it appears that the connection type and the inverse |
|||
type are separate records.. |
|||
|
|||
The original function _auto_init is still called because this function |
|||
normally (if _auto == True) not only creates the db tables, but it also takes |
|||
care of registering all fields in ir_model_fields. This is needed to make |
|||
the field labels translatable. |
|||
|
|||
example content for last lines of _statement: |
|||
select id, record_type, |
|||
customer_id, customer_name, customer_city, customer_zip, customer_street, |
|||
caller_id, caller_name, caller_phone, caller_fax, caller_email |
|||
from FULL_LIST as ResPartnerRelationTypeSelection where record_type = 'c' |
|||
ORDER BY ResPartnerRelationTypeSelection.customer_name asc, |
|||
ResPartnerRelationTypeSelection.caller_name asc; |
|||
|
|||
''' |
|||
from openerp.osv import fields |
|||
from openerp.osv import orm |
|||
from openerp.tools import drop_view_if_exists |
|||
from openerp.addons.partner_relations.model.res_partner_relation_type\ |
|||
import ResPartnerRelationType |
|||
|
|||
|
|||
class ResPartnerRelationTypeSelection(orm.Model): |
|||
'''Virtual relation types''' |
|||
|
|||
_RECORD_TYPES = [ |
|||
('a', 'Type'), |
|||
('b', 'Inverse type'), |
|||
] |
|||
|
|||
_auto = False # Do not try to create table in _auto_init(..) |
|||
_log_access = False |
|||
|
|||
def get_type_from_selection_id(self, cr, uid, selection_id): |
|||
'''Selection id ic computed from id of underlying type and the |
|||
kind of record. This function does the inverse computation to give |
|||
back the original type id, and about the record type.''' |
|||
type_id = selection_id / 10 |
|||
is_reverse = (selection_id % 10) > 0 |
|||
return (type_id, is_reverse) |
|||
|
|||
def _auto_init(self, cr, context=None): |
|||
drop_view_if_exists(cr, self._table) |
|||
#TODO: we lose field value's translations here. |
|||
#probably we need to patch ir_translation.get_source for that |
|||
#to get res_partner_relation_type's translations |
|||
cr.execute( |
|||
'''create or replace view %s as |
|||
select |
|||
id * 10 as id, |
|||
id as type_id, |
|||
cast('a' as char(1)) as record_type, |
|||
name as name, |
|||
contact_type_left as contact_type_this, |
|||
contact_type_right as contact_type_other, |
|||
partner_category_left as partner_category_this, |
|||
partner_category_right as partner_category_other |
|||
from res_partner_relation_type |
|||
union select |
|||
id * 10 + 1, |
|||
id, |
|||
cast('b' as char(1)), |
|||
name_inverse, |
|||
contact_type_right, |
|||
contact_type_left, |
|||
partner_category_right, |
|||
partner_category_left |
|||
from res_partner_relation_type''' % self._table) |
|||
|
|||
return super(ResPartnerRelationTypeSelection, self)._auto_init( |
|||
cr, context=context) |
|||
|
|||
def _search_partner_category_this(self, cr, uid, obj, field_name, args, |
|||
context=None): |
|||
category_ids = [] |
|||
|
|||
for arg in args: |
|||
if isinstance(arg, tuple) and arg[0] == field_name\ |
|||
and (arg[1] == '=' or arg[1] == 'in'): |
|||
#TODO don't we have an api function to eval that? |
|||
for delta in arg[2]: |
|||
if delta[0] == 6: |
|||
category_ids.extend(delta[2]) |
|||
|
|||
if category_ids: |
|||
return [ |
|||
'|', |
|||
('partner_category_this', '=', False), |
|||
('partner_category_this', 'in', category_ids), |
|||
] |
|||
else: |
|||
return [('partner_category_this', '=', False)] |
|||
|
|||
_name = 'res.partner.relation.type.selection' |
|||
_description = 'All relation types' |
|||
_foreign_keys = [] |
|||
_columns = { |
|||
'record_type': fields.selection(_RECORD_TYPES, 'Record type', size=16), |
|||
'type_id': fields.integer('Type'), |
|||
'name': fields.char('Name', size=64), |
|||
'contact_type_this': fields.selection( |
|||
ResPartnerRelationType._get_partner_types.im_func, |
|||
'Current record\'s partner type'), |
|||
'contact_type_other': fields.selection( |
|||
ResPartnerRelationType._get_partner_types.im_func, |
|||
'Other record\'s partner type'), |
|||
'partner_category_this': fields.many2one( |
|||
'res.partner.category', 'Current record\'s category'), |
|||
'partner_category_other': fields.many2one( |
|||
'res.partner.category', 'Other record\'s category'), |
|||
#search field to handle many2many deltas from the client |
|||
'search_partner_category_this': fields.function( |
|||
lambda self, cr, uid, ids, context=None: dict( |
|||
[(i, False) for i in ids]), |
|||
fnct_search=_search_partner_category_this, |
|||
type='many2many', obj='res.partner.category', |
|||
string='Current record\'s category'), |
|||
} |
|||
_order = 'name asc' |
|||
|
|||
def name_get(self, cr, uid, ids, context=None): |
|||
'translate name using translations from res.partner.relation.type' |
|||
result = super(ResPartnerRelationTypeSelection, self).name_get( |
|||
cr, uid, ids, context=context) |
|||
ir_translation = self.pool['ir.translation'] |
|||
return [ |
|||
(i, ir_translation._get_source( |
|||
cr, uid, |
|||
'res.partner.relation.type,name_inverse' |
|||
if self.get_type_from_selection_id(cr, uid, i)[1] |
|||
else 'res.partner.relation.type,name', |
|||
'model', context.get('lang'), name)) |
|||
for i, name in result] |
|||
|
|||
def name_search(self, cr, uid, name='', args=None, operator='ilike', |
|||
context=None, limit=100): |
|||
'search for translated names in res.partner.relation.type' |
|||
res_partner_relation_type = self.pool['res.partner.relation.type'] |
|||
relation_ids = res_partner_relation_type.search( |
|||
cr, uid, [('name', operator, name)], |
|||
context=context) |
|||
inverse_relation_ids = res_partner_relation_type.search( |
|||
cr, uid, [('name_inverse', operator, name)], |
|||
context=context) |
|||
all_ids = self.search( |
|||
cr, uid, |
|||
[ |
|||
('id', 'in', |
|||
map(lambda x: x * 10, relation_ids) + |
|||
map(lambda x: x * 10 + 1, inverse_relation_ids)), |
|||
] + (args or []), |
|||
context=context, limit=limit) |
|||
return self.name_get(cr, uid, all_ids, context=context) |
@ -0,0 +1,7 @@ |
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink |
|||
read_res_partner_relation,access_res_partner_relation,model_res_partner_relation,,1,0,0,0 |
|||
read_res_partner_relation_all,access_res_partner_relation,model_res_partner_relation_all,,1,0,0,0 |
|||
read_res_partner_relation_type,access_res_partner_relation_type,model_res_partner_relation_type,,1,0,0,0 |
|||
read_res_partner_relation_type_selection,access_res_partner_relation_type,model_res_partner_relation_type_selection,,1,0,0,0 |
|||
crud_res_partner_relation,access_res_partner_relation,model_res_partner_relation,base.group_partner_manager,1,1,1,1 |
|||
crud_res_partner_relation_type,access_res_partner_relation_type,model_res_partner_relation_type,base.group_sale_manager,1,1,1,1 |
After Width: 90 | Height: 90 | Size: 13 KiB |
@ -0,0 +1,15 @@ |
|||
<openerp> |
|||
<data> |
|||
<act_window |
|||
id="action_res_partner_relation_type" |
|||
res_model="res.partner.relation.type" |
|||
view_mode="tree,form" |
|||
name="Partner relations" |
|||
/> |
|||
<menuitem |
|||
id="menu_res_partner_relation_type" |
|||
parent="base.menu_config_address_book" |
|||
action="action_res_partner_relation_type" |
|||
/> |
|||
</data> |
|||
</openerp> |
@ -0,0 +1,96 @@ |
|||
<openerp> |
|||
<data> |
|||
<record id="view_res_partner_filter" model="ir.ui.view"> |
|||
<field name="inherit_id" ref="base.view_res_partner_filter" /> |
|||
<field name="model">res.partner</field> |
|||
<field type="xml" name="arch"> |
|||
<data> |
|||
<field name="parent_id" position="after"> |
|||
<field name="search_relation_partner_id" /> |
|||
<field name="search_relation_id" /> |
|||
<field name="search_relation_date" /> |
|||
<field name="search_relation_partner_category_id" /> |
|||
</field> |
|||
</data> |
|||
</field> |
|||
</record> |
|||
<record id="view_partner_form" model="ir.ui.view"> |
|||
<field name="inherit_id" ref="base.view_partner_form" /> |
|||
<field name="model">res.partner</field> |
|||
<field type="xml" name="arch"> |
|||
<data> |
|||
<xpath expr="//sheet/notebook" position="inside"> |
|||
<page string="Relations"> |
|||
<field |
|||
name="relation_ids" |
|||
context="{ |
|||
'active_model': 'res.partner', |
|||
'active_id': id, 'active_ids': [id], |
|||
'active_test': False, |
|||
}" |
|||
> |
|||
<tree |
|||
editable="top" |
|||
colors="gray:is_relation_expired==True or not active;blue:is_relation_future==True" |
|||
> |
|||
<field |
|||
name="type_selection_id" |
|||
required="True" |
|||
context="{ |
|||
'parent_model': 'res.partner', |
|||
'parent_id': parent.id, |
|||
}" |
|||
domain="[ |
|||
'|', |
|||
('contact_type_this', '=', parent.is_company and 'c' or 'p'), |
|||
('contact_type_this', '=', False), |
|||
('search_partner_category_this', '=', parent.category_id), |
|||
|
|||
] |
|||
" |
|||
options="{'create': false, 'create_edit': false}" |
|||
on_change="on_change_type_selection_id(type_selection_id)" |
|||
/> |
|||
<field name="type_id" invisible="True" /> |
|||
<field |
|||
name="partner_id_display" |
|||
required="True" |
|||
attrs="{ |
|||
'readonly': [('type_selection_id','=',False)], |
|||
}" |
|||
options="{'create': false, 'create_edit': false}" |
|||
widget="many2one_clickable" |
|||
/> |
|||
<field |
|||
name="date_start" |
|||
/> |
|||
<field |
|||
name="date_end" |
|||
/> |
|||
<field |
|||
name="active" |
|||
/> |
|||
<field |
|||
name="is_relation_expired" |
|||
invisible="True" |
|||
/> |
|||
<field |
|||
name="is_relation_future" |
|||
invisible="True" |
|||
/> |
|||
</tree> |
|||
</field> |
|||
</page> |
|||
</xpath> |
|||
</data> |
|||
</field> |
|||
</record> |
|||
|
|||
<act_window id="action_show_partner_relations" |
|||
name="Show partner's relations" |
|||
src_model="res.partner" |
|||
res_model="res.partner.relation.all" |
|||
domain="[('this_partner_id', 'in', active_ids)]" |
|||
key2="client_action_multi" /> |
|||
</data> |
|||
</openerp> |
@ -0,0 +1,33 @@ |
|||
<openerp> |
|||
<data> |
|||
<record id="form_res_partner_relation" model="ir.ui.view"> |
|||
<field name="model">res.partner.relation</field> |
|||
<field type="xml" name="arch"> |
|||
<form version="7.0" string="Partner relation"> |
|||
<sheet> |
|||
<field name="left_partner_id" /> |
|||
<field name="type_id" /> |
|||
<field name="right_partner_id" /> |
|||
</sheet> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
<record id="action_show_right_relation_partners" model="ir.actions.server"> |
|||
<field name="sequence" eval="5"/> |
|||
<field name="state">code</field> |
|||
<field name="type">ir.actions.server</field> |
|||
<field name="model_id" ref="model_res_partner_relation"/> |
|||
<field name="code">action = self.get_action_related_partners(cr, uid, context.get('active_ids', []), dict(context or {}, partner_relations_show_side='right'))</field> |
|||
<field name="condition">True</field> |
|||
<field name="name">Show partners</field> |
|||
</record> |
|||
<record id="action_show_right_relation_partners_value" model="ir.values"> |
|||
<field name="name">Show partners</field> |
|||
<field name="key">action</field> |
|||
<field name="key2">client_action_multi</field> |
|||
<field name="model">res.partner.relation.all</field> |
|||
<field name="value" eval="'ir.actions.server,%d' % ref('partner_relations.action_show_right_relation_partners')" /> |
|||
</record> |
|||
|
|||
</data> |
|||
</openerp> |
@ -0,0 +1,34 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<openerp> |
|||
<data> |
|||
<record id="tree_res_partner_relation_all" model="ir.ui.view"> |
|||
<field name="model">res.partner.relation.all</field> |
|||
<field name="arch" type="xml"> |
|||
<tree string="Partner relations"> |
|||
<field name="this_partner_id" /> |
|||
<field name="type_selection_id" /> |
|||
<field name="other_partner_id" /> |
|||
<field name="date_start" /> |
|||
<field name="date_end" /> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
<record id="form_res_partner_relation_all" model="ir.ui.view"> |
|||
<field name="model">res.partner.relation.all</field> |
|||
<field name="arch" type="xml"> |
|||
<form string="Partner relation"> |
|||
<group> |
|||
<field name="this_partner_id" /> |
|||
<field name="type_selection_id" /> |
|||
<field name="other_partner_id" /> |
|||
</group> |
|||
<group> |
|||
<field name="date_start" /> |
|||
<field name="date_end" /> |
|||
<field name="active" /> |
|||
</group> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
</data> |
|||
</openerp> |
@ -0,0 +1,44 @@ |
|||
<openerp> |
|||
<data> |
|||
<record id="tree_res_partner_relation_type" model="ir.ui.view"> |
|||
<field name="model">res.partner.relation.type</field> |
|||
<field name="type">tree</field> |
|||
<field type="xml" name="arch"> |
|||
<tree version="7.0" string="Partner relation"> |
|||
<field name="name" /> |
|||
<field name="name_inverse" /> |
|||
<field name="contact_type_left" /> |
|||
<field name="contact_type_right" /> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
<record id="form_res_partner_relation_type" model="ir.ui.view"> |
|||
<field name="model">res.partner.relation.type</field> |
|||
<field name="type">form</field> |
|||
<field type="xml" name="arch"> |
|||
<form version="7.0" string="Partner relation"> |
|||
<sheet> |
|||
<group> |
|||
<group |
|||
colspan="2" col="2" |
|||
string="Left side of relation" |
|||
> |
|||
<field name="name" /> |
|||
<field name="contact_type_left" /> |
|||
<field name="partner_category_left" /> |
|||
</group> |
|||
<group |
|||
colspan="2" col="2" |
|||
string="Right side of relation" |
|||
> |
|||
<field name="name_inverse" /> |
|||
<field name="contact_type_right" /> |
|||
<field name="partner_category_right" /> |
|||
</group> |
|||
</group> |
|||
</sheet> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
</data> |
|||
</openerp> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue