Skip to content

Commit 4fb406a

Browse files
committed
[ADD] new module partner_multi_relation_contact
1 parent 0b499c9 commit 4fb406a

25 files changed

+1247
-0
lines changed
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
========================
2+
Partner Relation Contact
3+
========================
4+
5+
..
6+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
7+
!! This file is generated by oca-gen-addon-readme !!
8+
!! changes will be overwritten. !!
9+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
10+
!! source digest: sha256:f5bedfce28db3d0081c34e3c73d93c3be293d8248a5143c99f135b8537f54ad1
11+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
12+
13+
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
14+
:target: https://odoo-community.org/page/development-status
15+
:alt: Beta
16+
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
17+
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
18+
:alt: License: AGPL-3
19+
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fpartner--contact-lightgray.png?logo=github
20+
:target: https://github.com/OCA/partner-contact/tree/16.0/partner_multi_relation_contact
21+
:alt: OCA/partner-contact
22+
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
23+
:target: https://translation.odoo-community.org/projects/partner-contact-16-0/partner-contact-16-0-partner_multi_relation_contact
24+
:alt: Translate me on Weblate
25+
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
26+
:target: https://runboat.odoo-community.org/builds?repo=OCA/partner-contact&target_branch=16.0
27+
:alt: Try me on Runboat
28+
29+
|badge1| |badge2| |badge3| |badge4| |badge5|
30+
31+
This module gives the posibility to set contact information on a relation.
32+
33+
Sometimes the email address, the phone number or the physical address to
34+
use with a contact can depend on the role, or relation, for which we want
35+
to approach a contact, or function.
36+
37+
For instance a company can have a company email info@example.company.com. A
38+
lawyer with the email address somelawyer@legalcompany.com is working for that
39+
company. So we have a relation 'Example company is represented by lawyer some lawyer'.
40+
But for this relation an email has been created 'legaldepartment@example.company.com'.
41+
42+
Similar examples can be given for phone or physical address.
43+
44+
**Table of contents**
45+
46+
.. contents::
47+
:local:
48+
49+
Usage
50+
=====
51+
52+
Relation Type
53+
~~~~~~~~~~~~~
54+
55+
You can specify that a relation type can have a separate contact attached to it. You can
56+
specify that the separate address can have an email, a phone and/or a physical address.
57+
58+
You can also specify a priority to use for which contact, left or right, to use for email,
59+
phone or physical address, if not specified on the attached contact (or if there is no
60+
attached contact).
61+
62+
Relation
63+
~~~~~~~~
64+
65+
You can specify a special contact for relation types that allow this. Depending
66+
on the type you can enter email, phone and or physical address.
67+
68+
Bug Tracker
69+
===========
70+
71+
Bugs are tracked on `GitHub Issues <https://github.com/OCA/partner-contact/issues>`_.
72+
In case of trouble, please check there if your issue has already been reported.
73+
If you spotted it first, help us to smash it by providing a detailed and welcomed
74+
`feedback <https://github.com/OCA/partner-contact/issues/new?body=module:%20partner_multi_relation_contact%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
75+
76+
Do not contact contributors directly about support or help with technical issues.
77+
78+
Credits
79+
=======
80+
81+
Authors
82+
~~~~~~~
83+
84+
* Therp BV
85+
86+
Contributors
87+
~~~~~~~~~~~~
88+
89+
* `Therp BV <https://therp.nl>`_:
90+
91+
* Ronald Portier <ronald@therp.nl>
92+
93+
Maintainers
94+
~~~~~~~~~~~
95+
96+
This module is maintained by the OCA.
97+
98+
.. image:: https://odoo-community.org/logo.png
99+
:alt: Odoo Community Association
100+
:target: https://odoo-community.org
101+
102+
OCA, or the Odoo Community Association, is a nonprofit organization whose
103+
mission is to support the collaborative development of Odoo features and
104+
promote its widespread use.
105+
106+
.. |maintainer-NL66278| image:: https://github.com/NL66278.png?size=40px
107+
:target: https://github.com/NL66278
108+
:alt: NL66278
109+
110+
Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:
111+
112+
|maintainer-NL66278|
113+
114+
This module is part of the `OCA/partner-contact <https://github.com/OCA/partner-contact/tree/16.0/partner_multi_relation_contact>`_ project on GitHub.
115+
116+
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
2+
from . import models
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Copyright 2026 Therp BV <http://therp.nl>.
2+
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
3+
{
4+
"name": "Partner Relation Contact",
5+
"version": "16.0.1.0.0",
6+
"author": "Therp BV,Odoo Community Association (OCA)",
7+
"website": "https://github.com/OCA/partner-contact",
8+
"maintainers": ["NL66278"],
9+
"complexity": "normal",
10+
"category": "Customer Relationship Management",
11+
"license": "AGPL-3",
12+
"depends": ["partner_multi_relation"],
13+
"demo": [
14+
"demo/res_partner_relation_type_demo.xml",
15+
"demo/res_partner_demo.xml",
16+
"demo/res_partner_demo.xml", # Must be after type and partner
17+
"demo/res_partner_02_demo.xml", # Create contact address for relation
18+
],
19+
"data": [
20+
"views/res_partner_views.xml",
21+
"views/res_partner_relation_views.xml",
22+
"views/res_partner_relation_type_views.xml",
23+
],
24+
"auto_install": False,
25+
"installable": True,
26+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<odoo>
3+
4+
<record id="res_partner_demo_contact" model="res.partner">
5+
<field name="relation_id" ref="demo_relation_company_lawyer" />
6+
<field name="type">other</field>
7+
<field name="parent_id" ref="res_partner_demo_lawyer" />
8+
<field name="name">Joe Clever is head lawyer for Big Company</field>
9+
<field name="is_company">0</field>
10+
<field name="email">joeclever@legalcompany.example.com</field>
11+
<field name="phone">+31 06 6461 7838</field>
12+
</record>
13+
14+
</odoo>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<odoo>
3+
4+
<record id="res_partner_demo_lawyer" model="res.partner">
5+
<field name="name">Joe Clever</field>
6+
<field name="is_company">0</field>
7+
<field name="city">Hilversum</field>
8+
<field name="zip">1222 EE</field>
9+
<field name="country_id" ref="base.nl" />
10+
<field name="email">joeclever@legalcompany.example.com</field>
11+
<field name="phone">+31 06 6461 0401</field>
12+
<field name="street">Buisweg</field>
13+
</record>
14+
15+
</odoo>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<odoo>
3+
4+
<record id="demo_relation_company_lawyer" model="res.partner.relation">
5+
<field
6+
name="left_partner_id"
7+
ref="partner_multi_relation.res_partner_pmr_great"
8+
/>
9+
<field name="right_partner_id" ref="res_partner_demo_lawyer" />
10+
<field name="type_id" ref="rel_type_lawyer" />
11+
</record>
12+
13+
</odoo>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<odoo>
3+
<record id="rel_type_lawyer" model="res.partner.relation.type">
4+
<field name="name">Has lawyer</field>
5+
<field name="name_inverse">Is lawyer for</field>
6+
<field name="contact_type_left">c</field>
7+
<field name="contact_type_right">p</field>
8+
<field name="allow_email">True</field>
9+
<field name="allow_phone">True</field>
10+
<field name="set_contact_parent">True</field>
11+
</record>
12+
</odoo>
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
2+
from . import res_partner
3+
from . import res_partner_relation_type
4+
from . import res_partner_relation
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# Copyright 2026 Therp BV <https://therp.nl>.
2+
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
3+
4+
from odoo import _, api, exceptions, fields, models
5+
6+
7+
class ResPartner(models.Model):
8+
"""Enable searching partner via email"""
9+
10+
_inherit = "res.partner"
11+
12+
relation_id = fields.Many2one(
13+
comodel_name="res.partner.relation",
14+
readonly=True,
15+
help="Relation for which this contact address has been created",
16+
)
17+
allow_contact_partner = fields.Boolean(
18+
related="relation_id.type_id.allow_contact_partner",
19+
)
20+
allow_address = fields.Boolean(
21+
related="relation_id.type_id.allow_address",
22+
)
23+
allow_email = fields.Boolean(
24+
related="relation_id.type_id.allow_email",
25+
)
26+
allow_phone = fields.Boolean(
27+
related="relation_id.type_id.allow_phone",
28+
)
29+
search_relation_email = fields.Many2one(
30+
comodel_name="res.partner.relation",
31+
compute=lambda self: self.update({"search_relation_email": None}),
32+
search="_search_relation_email",
33+
string="Has relation email",
34+
)
35+
search_relation_phone = fields.Many2one(
36+
comodel_name="res.partner.relation",
37+
compute=lambda self: self.update({"search_relation_phone": None}),
38+
search="_search_relation_phone",
39+
string="Has relation phone",
40+
)
41+
42+
@api.model_create_multi
43+
def create(self, vals_list):
44+
result = super().create(vals_list)
45+
for record in result:
46+
if record.relation_id:
47+
record.relation_id.contact_partner_id = record
48+
return result
49+
50+
@api.model
51+
def _search_relation_email(self, operator, value):
52+
"""Search partners based on their relation email."""
53+
SUPPORTED_OPERATORS = (
54+
"=",
55+
"!=",
56+
"like",
57+
"not like",
58+
"ilike",
59+
"not ilike",
60+
"in",
61+
"not in",
62+
)
63+
if operator not in SUPPORTED_OPERATORS:
64+
raise exceptions.ValidationError(
65+
_('Unsupported search operator "%s"') % operator
66+
)
67+
return [
68+
"|",
69+
("relation_left_ids.contact_partner_id.email", operator, value),
70+
("relation_right_ids.contact_partner_id.email", operator, value),
71+
]
72+
73+
@api.model
74+
def _search_relation_phone(self, operator, value):
75+
"""Search partners based on their relation phone."""
76+
SUPPORTED_OPERATORS = (
77+
"=",
78+
"!=",
79+
"like",
80+
"not like",
81+
"ilike",
82+
"not ilike",
83+
"in",
84+
"not in",
85+
)
86+
if operator not in SUPPORTED_OPERATORS:
87+
raise exceptions.ValidationError(
88+
_('Unsupported search operator "%s"') % operator
89+
)
90+
return [
91+
"|",
92+
("relation_left_ids.contact_partner_id.phone", operator, value),
93+
("relation_right_ids.contact_partner_id.phone", operator, value),
94+
]

0 commit comments

Comments
 (0)