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
104 changes: 104 additions & 0 deletions crm_lead_partner_by_vat/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
.. image:: https://odoo-community.org/readme-banner-image
:target: https://odoo-community.org/get-involved?utm_source=readme
:alt: Odoo Community Association

=======================
CRM Lead Partner by VAT
=======================

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

.. |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_partner_by_vat
: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_partner_by_vat
: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 a lead is matched to a partner, Odoo looks the partner up by email.
This module makes it look up a **company by VAT (TIN)** first, and only
falls back to the native email lookup when the lead has no VAT or no
company carries it.

It builds on ``crm_lead_vat``, which adds the VAT field to leads.

**Table of contents**

.. contents::
:local:

Usage
=====

1. Go to *CRM > Leads* and open a lead that has a TIN set.
2. Press *Convert to Opportunity*.
3. If a company has that TIN, it is proposed in the *Customer* field.
Otherwise the customer is looked up by email, as Odoo does natively.

The proposal can always be changed: the *Customer* field stays editable
and any partner can be picked from it.

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_partner_by_vat%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
-------

* ForgeFlow

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

- Marc Gimeno <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-MarcGForgeFlow| image:: https://github.com/MarcGForgeFlow.png?size=40px
:target: https://github.com/MarcGForgeFlow
:alt: MarcGForgeFlow

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

|maintainer-MarcGForgeFlow|

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

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
3 changes: 3 additions & 0 deletions crm_lead_partner_by_vat/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).

from . import models
16 changes: 16 additions & 0 deletions crm_lead_partner_by_vat/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Copyright 2026 ForgeFlow S.L.
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).

{
"name": "CRM Lead Partner by VAT",
"summary": "Match the lead's partner by VAT (TIN) instead of email",
"version": "19.0.1.0.0",
"category": "Customer Relationship Management",
"website": "https://github.com/OCA/crm",
"author": "ForgeFlow, Odoo Community Association (OCA)",
"maintainers": ["MarcGForgeFlow"],
"license": "AGPL-3",
"application": False,
"installable": True,
"depends": ["crm_lead_vat"],
}
3 changes: 3 additions & 0 deletions crm_lead_partner_by_vat/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).

from . import crm_lead
46 changes: 46 additions & 0 deletions crm_lead_partner_by_vat/models/crm_lead.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Copyright 2026 ForgeFlow S.L.
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).

from odoo import models


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

def _vat_search_variants(self, vat):
"""Return the VAT spellings to look for.

``res.partner.vat`` is free text: neither ``base`` nor ``base_vat``
normalizes it on write, so it is stored exactly as it was typed. The
value as typed is therefore searched alongside the normalized one, and
the case is never altered, so that a partner whose VAT was stored
verbatim is found too.
"""
# Sometimes the VAT is typed with whitespaces or dots.
return (vat.replace(" ", "").replace(".", ""), vat)

def _find_company_by_vat(self):
"""Return the company matching the lead's VAT (TIN), if any.

Exact matches are used on purpose (not ``=ilike``): the VAT is free
text, so wildcard characters must be compared literally, and equality
hits the index on ``res.partner.vat``.
"""
self.ensure_one()
if not self.vat:
return self.env["res.partner"]
return self.env["res.partner"].search(
[
("is_company", "=", True),
("vat", "in", self._vat_search_variants(self.vat)),
],
limit=1,
order="id",
)

def _find_matching_partner(self):
"""Prefer the company matched by the lead's VAT, falling back to the
native email lookup when the lead has no VAT or no company carries it.
"""
self.ensure_one()
return self._find_company_by_vat() or super()._find_matching_partner()
3 changes: 3 additions & 0 deletions crm_lead_partner_by_vat/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[build-system]
requires = ["whool"]
build-backend = "whool.buildapi"
1 change: 1 addition & 0 deletions crm_lead_partner_by_vat/readme/CONTRIBUTORS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Marc Gimeno \<<marc.gimeno@forgeflow.com>\>
5 changes: 5 additions & 0 deletions crm_lead_partner_by_vat/readme/DESCRIPTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
When a lead is matched to a partner, Odoo looks the partner up by email. This
module makes it look up a **company by VAT (TIN)** first, and only falls back
to the native email lookup when the lead has no VAT or no company carries it.

It builds on `crm_lead_vat`, which adds the VAT field to leads.
7 changes: 7 additions & 0 deletions crm_lead_partner_by_vat/readme/USAGE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
1. Go to *CRM \> Leads* and open a lead that has a TIN set.
2. Press *Convert to Opportunity*.
3. If a company has that TIN, it is proposed in the *Customer* field.
Otherwise the customer is looked up by email, as Odoo does natively.

The proposal can always be changed: the *Customer* field stays editable and
any partner can be picked from it.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading