Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 119 additions & 0 deletions crm_lead_to_opportunity_contact/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
.. image:: https://odoo-community.org/readme-banner-image
:target: https://odoo-community.org/get-involved?utm_source=readme
:alt: Odoo Community Association

=================================
CRM Lead to opportunity - Contact
=================================

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:4ed7fe64c973da857fdc999167004b63b97c43d00c2e48e4561aa75a4f73bc0e
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |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/license-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%2Fcrm-lightgray.png?logo=github
:target: https://github.com/OCA/crm/tree/19.0/crm_lead_to_opportunity_contact
:alt: OCA/crm
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/crm-19-0/crm-19-0-crm_lead_to_opportunity_contact
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/crm&target_branch=19.0
:alt: Try me on Runboat

|badge1| |badge2| |badge3| |badge4| |badge5|

When converting a lead to an opportunity, the native wizard can already
attach the lead's contact to an existing company: pick **Create a new
customer** and fill the **Company** field.

That field is only editable when the lead carries **no company name**,
though. As soon as the lead has one — which is the usual case for leads
coming from a website form or an import — the native wizard leaves no
way to do it:

- **Create a new customer** creates a *second* company out of the lead's
company name, even when that company already exists;
- **Link to an existing customer** links the company, and the lead's
contact is never created.

This module fills that gap. It adds a sub-question under **Link to an
existing customer**, shown when the lead has a contact name and the
selected customer is a company, to decide what to do with that contact:

- **Create a new contact** on the existing company
- **Link to an existing contact** of that company
- **Do not add a contact** (keep the native behaviour: link the company,
and leave the lead's contact aside)

If a contact of the company already matches the lead's email, it is
pre-selected, so that no duplicate is created. When the lead has no
contact name, or the selected customer is a person, the native behaviour
is kept.

|Screenshot lead to opportunity wizard|

.. |Screenshot lead to opportunity wizard| image:: https://raw.githubusercontent.com/OCA/crm/19.0/crm_lead_to_opportunity_contact/static/description/crm_lead_to_opportunity_contact-sshot.png

**Table of contents**

.. contents::
:local:

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/OCA/crm/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/OCA/crm/issues/new?body=module:%20crm_lead_to_opportunity_contact%0Aversion:%2019.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
-------

* Akretion

Contributors
------------

- Alexis de Lattre <alexis.delattre@akretion.com>
- Marc Gimeno Morales <marc.gimeno@forgeflow.com>

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.

.. |maintainer-alexis-via| image:: https://github.com/alexis-via.png?size=40px
:target: https://github.com/alexis-via
:alt: alexis-via

Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:

|maintainer-alexis-via|

This module is part of the `OCA/crm <https://github.com/OCA/crm/tree/19.0/crm_lead_to_opportunity_contact>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
2 changes: 2 additions & 0 deletions crm_lead_to_opportunity_contact/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import models
from . import wizards
20 changes: 20 additions & 0 deletions crm_lead_to_opportunity_contact/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Copyright 2023 Akretion France (http://www.akretion.com/)
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# Copyright 2026 ForgeFlow S.L.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

{
"name": "CRM Lead to opportunity - Contact",
"version": "19.0.1.0.0",
"category": "CRM",
"license": "AGPL-3",
"summary": "Lead to opportunity: create or link a contact on an existing customer",
"author": "Akretion,Odoo Community Association (OCA)",
"maintainers": ["alexis-via"],
"website": "https://github.com/OCA/crm",
"depends": ["crm"],
"data": [
"wizards/crm_lead_to_opportunity_view.xml",
],
"installable": True,
}
1 change: 1 addition & 0 deletions crm_lead_to_opportunity_contact/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import crm_lead
41 changes: 41 additions & 0 deletions crm_lead_to_opportunity_contact/models/crm_lead.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Copyright 2023 Akretion France (http://www.akretion.com/)
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# Copyright 2026 ForgeFlow S.L.
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from odoo import models


class CrmLead(models.Model):
_inherit = "crm.lead"

def _find_contact_in_company(self, company):
"""Return a contact of ``company`` matching the lead's email, if any.

Matching is done by email, which is the key Odoo itself uses to look up
partners, and the oldest one wins for the very same reason: it is
considered the most relevant.

As in ``MailThread._partner_find_from_emails()``, the normalized email
is the key, unless it is wrong and cannot be normalized, in which case
the raw input is compared instead. That keeps this lookup consistent
with the one filling the customer, which goes through that tool.
"""
self.ensure_one()
email = self.email_normalized or self.email_from
if not company or not email:
return self.env["res.partner"]
email_domain = (
[("email_normalized", "=", email)]
if self.email_normalized
else [("email", "=", email)]
)
return self.env["res.partner"].search(
[
("parent_id", "=", company.id),
("is_company", "=", False),
]
+ email_domain,
limit=1,
order="id",
)
3 changes: 3 additions & 0 deletions crm_lead_to_opportunity_contact/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[build-system]
requires = ["whool"]
build-backend = "whool.buildapi"
2 changes: 2 additions & 0 deletions crm_lead_to_opportunity_contact/readme/CONTRIBUTORS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Alexis de Lattre \<alexis.delattre@akretion.com\>
- Marc Gimeno Morales \<marc.gimeno@forgeflow.com\>
28 changes: 28 additions & 0 deletions crm_lead_to_opportunity_contact/readme/DESCRIPTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
When converting a lead to an opportunity, the native wizard can already attach
the lead's contact to an existing company: pick **Create a new customer** and
fill the **Company** field.

That field is only editable when the lead carries **no company name**, though.
As soon as the lead has one — which is the usual case for leads coming from a
website form or an import — the native wizard leaves no way to do it:

- **Create a new customer** creates a *second* company out of the lead's company
name, even when that company already exists;
- **Link to an existing customer** links the company, and the lead's contact is
never created.

This module fills that gap. It adds a sub-question under **Link to an existing
customer**, shown when the lead has a contact name and the selected customer is
a company, to decide what to do with that contact:

- **Create a new contact** on the existing company
- **Link to an existing contact** of that company
- **Do not add a contact** (keep the native behaviour: link the company, and
leave the lead's contact aside)

If a contact of the company already matches the lead's email, it is
pre-selected, so that no duplicate is created. When the lead has no contact
name, or the selected customer is a person, the native behaviour is kept.

![Screenshot lead to opportunity
wizard](../static/description/crm_lead_to_opportunity_contact-sshot.png)
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading