diff --git a/crm_lead_partner_interest_group/README.rst b/crm_lead_partner_interest_group/README.rst new file mode 100644 index 00000000000..a375a8b4042 --- /dev/null +++ b/crm_lead_partner_interest_group/README.rst @@ -0,0 +1,97 @@ +.. 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 Interest Group +=============================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:16ff04f11093f59c59a325d926c3ca46c1b575194b663a21736ef34ea331f032 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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_interest_group + :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_interest_group + :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| + +This module adds the Interest Groups field (provided by +``partner_interest_group``) to CRM leads and opportunities. + +When a partner is generated from a lead (using the standard +lead-to-partner conversion or marking the lead as won), the interest +groups stored on the lead are automatically propagated to the new +partner. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +1. Open a lead or opportunity. +2. Fill the *Interest Groups* field with one or more interest groups. +3. Convert the lead to an opportunity (or directly mark it as won) so + that a new partner is created. The interest groups defined on the + lead are copied over to the newly created partner. + +Bug Tracker +=========== + +Bugs are tracked on `GitHub 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 `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* ForgeFlow + +Contributors +------------ + +- `ForgeFlow `__: + + - Jordi Ballester Alomar + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/crm `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/crm_lead_partner_interest_group/__init__.py b/crm_lead_partner_interest_group/__init__.py new file mode 100644 index 00000000000..0650744f6bc --- /dev/null +++ b/crm_lead_partner_interest_group/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/crm_lead_partner_interest_group/__manifest__.py b/crm_lead_partner_interest_group/__manifest__.py new file mode 100644 index 00000000000..647f052acce --- /dev/null +++ b/crm_lead_partner_interest_group/__manifest__.py @@ -0,0 +1,21 @@ +# Copyright 2026 ForgeFlow S.L. (https://www.forgeflow.com) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +{ + "name": "CRM Lead Partner Interest Group", + "summary": "Manage interest groups on CRM leads and propagate them to the " + "partner created from the lead.", + "version": "19.0.1.0.0", + "category": "Customer Relationship Management", + "author": "ForgeFlow, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/crm", + "license": "AGPL-3", + "depends": [ + "crm", + "partner_interest_group", + ], + "data": [ + "views/crm_lead_views.xml", + ], + "installable": True, +} diff --git a/crm_lead_partner_interest_group/models/__init__.py b/crm_lead_partner_interest_group/models/__init__.py new file mode 100644 index 00000000000..e66f0d6cf4e --- /dev/null +++ b/crm_lead_partner_interest_group/models/__init__.py @@ -0,0 +1 @@ +from . import crm_lead diff --git a/crm_lead_partner_interest_group/models/crm_lead.py b/crm_lead_partner_interest_group/models/crm_lead.py new file mode 100644 index 00000000000..e295a28b7f4 --- /dev/null +++ b/crm_lead_partner_interest_group/models/crm_lead.py @@ -0,0 +1,21 @@ +# Copyright 2026 ForgeFlow S.L. (https://www.forgeflow.com) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class CrmLead(models.Model): + _inherit = "crm.lead" + + interest_group_ids = fields.Many2many( + comodel_name="res.partner.interest.group", + string="Interest Groups", + ) + + def _prepare_customer_values(self, partner_name, is_company=False, parent_id=False): + values = super()._prepare_customer_values( + partner_name, is_company=is_company, parent_id=parent_id + ) + if self.interest_group_ids and not is_company: + values["interest_group_ids"] = [(6, 0, self.interest_group_ids.ids)] + return values diff --git a/crm_lead_partner_interest_group/pyproject.toml b/crm_lead_partner_interest_group/pyproject.toml new file mode 100644 index 00000000000..4231d0cccb3 --- /dev/null +++ b/crm_lead_partner_interest_group/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/crm_lead_partner_interest_group/readme/CONTRIBUTORS.md b/crm_lead_partner_interest_group/readme/CONTRIBUTORS.md new file mode 100644 index 00000000000..4cbeb5866f2 --- /dev/null +++ b/crm_lead_partner_interest_group/readme/CONTRIBUTORS.md @@ -0,0 +1,2 @@ +- [ForgeFlow](https://www.forgeflow.com): + - Jordi Ballester Alomar diff --git a/crm_lead_partner_interest_group/readme/DESCRIPTION.md b/crm_lead_partner_interest_group/readme/DESCRIPTION.md new file mode 100644 index 00000000000..ead56182eab --- /dev/null +++ b/crm_lead_partner_interest_group/readme/DESCRIPTION.md @@ -0,0 +1,6 @@ +This module adds the Interest Groups field (provided by +`partner_interest_group`) to CRM leads and opportunities. + +When a partner is generated from a lead (using the standard lead-to-partner +conversion or marking the lead as won), the interest groups stored on the +lead are automatically propagated to the new partner. diff --git a/crm_lead_partner_interest_group/readme/USAGE.md b/crm_lead_partner_interest_group/readme/USAGE.md new file mode 100644 index 00000000000..a2517b3099b --- /dev/null +++ b/crm_lead_partner_interest_group/readme/USAGE.md @@ -0,0 +1,5 @@ +1. Open a lead or opportunity. +2. Fill the *Interest Groups* field with one or more interest groups. +3. Convert the lead to an opportunity (or directly mark it as won) so that + a new partner is created. The interest groups defined on the lead are + copied over to the newly created partner. diff --git a/crm_lead_partner_interest_group/static/description/index.html b/crm_lead_partner_interest_group/static/description/index.html new file mode 100644 index 00000000000..e5adb14cce1 --- /dev/null +++ b/crm_lead_partner_interest_group/static/description/index.html @@ -0,0 +1,448 @@ + + + + + +README.rst + + + +
+ + + +Odoo Community Association + +
+

CRM Lead Partner Interest Group

+ +

Beta License: AGPL-3 OCA/crm Translate me on Weblate Try me on Runboat

+

This module adds the Interest Groups field (provided by +partner_interest_group) to CRM leads and opportunities.

+

When a partner is generated from a lead (using the standard +lead-to-partner conversion or marking the lead as won), the interest +groups stored on the lead are automatically propagated to the new +partner.

+

Table of contents

+ +
+

Usage

+
    +
  1. Open a lead or opportunity.
  2. +
  3. Fill the Interest Groups field with one or more interest groups.
  4. +
  5. Convert the lead to an opportunity (or directly mark it as won) so +that a new partner is created. The interest groups defined on the +lead are copied over to the newly created partner.
  6. +
+
+
+

Bug Tracker

+

Bugs are tracked on GitHub 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.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • ForgeFlow
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/crm project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+
+ + diff --git a/crm_lead_partner_interest_group/tests/__init__.py b/crm_lead_partner_interest_group/tests/__init__.py new file mode 100644 index 00000000000..87ff46ea9c8 --- /dev/null +++ b/crm_lead_partner_interest_group/tests/__init__.py @@ -0,0 +1 @@ +from . import test_crm_lead_partner_interest_group diff --git a/crm_lead_partner_interest_group/tests/test_crm_lead_partner_interest_group.py b/crm_lead_partner_interest_group/tests/test_crm_lead_partner_interest_group.py new file mode 100644 index 00000000000..9bb3f1dc1aa --- /dev/null +++ b/crm_lead_partner_interest_group/tests/test_crm_lead_partner_interest_group.py @@ -0,0 +1,74 @@ +# Copyright 2026 ForgeFlow S.L. (https://www.forgeflow.com) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo.tests import Form, TransactionCase + + +class TestCrmLeadPartnerInterestGroup(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + InterestGroup = cls.env["res.partner.interest.group"] + cls.group_a = InterestGroup.create({"name": "Group A"}) + cls.group_b = InterestGroup.create({"name": "Group B"}) + + def _new_lead_form(self): + return Form(self.env["crm.lead"]) + + def test_lead_interest_group_field(self): + lead_form = self._new_lead_form() + lead_form.name = "Lead with interests" + lead_form.contact_name = "Test Contact" + lead_form.email_from = "test.contact@example.com" + lead_form.interest_group_ids.add(self.group_a) + lead_form.interest_group_ids.add(self.group_b) + lead = lead_form.save() + self.assertEqual(lead.interest_group_ids, self.group_a + self.group_b) + + def test_create_partner_from_lead_propagates_interest_groups(self): + lead = self.env["crm.lead"].create( + { + "name": "Lead generating partner", + "contact_name": "John Doe", + "email_from": "john.doe@example.com", + "interest_group_ids": [(6, 0, (self.group_a + self.group_b).ids)], + } + ) + self.assertFalse(lead.partner_id) + lead._handle_partner_assignment() + self.assertTrue(lead.partner_id) + self.assertEqual( + lead.partner_id.interest_group_ids, + self.group_a + self.group_b, + ) + + def test_create_partner_from_lead_without_interest_groups(self): + lead = self.env["crm.lead"].create( + { + "name": "Lead without interests", + "contact_name": "Jane Doe", + "email_from": "jane.doe@example.com", + } + ) + lead._handle_partner_assignment() + self.assertTrue(lead.partner_id) + self.assertFalse(lead.partner_id.interest_group_ids) + + def test_partner_creation_with_company(self): + lead = self.env["crm.lead"].create( + { + "name": "Lead with company", + "contact_name": "Foo Contact", + "partner_name": "ACME Inc.", + "email_from": "contact@acme.example.com", + "interest_group_ids": [(6, 0, self.group_a.ids)], + } + ) + lead._handle_partner_assignment() + partner = lead.partner_id + self.assertTrue(partner) + self.assertEqual(partner.interest_group_ids, self.group_a) + # The parent company partner should NOT carry interest groups, + # as those belong to the individual contact only. + self.assertTrue(partner.parent_id) + self.assertFalse(partner.parent_id.interest_group_ids) diff --git a/crm_lead_partner_interest_group/views/crm_lead_views.xml b/crm_lead_partner_interest_group/views/crm_lead_views.xml new file mode 100644 index 00000000000..c7d07f60c30 --- /dev/null +++ b/crm_lead_partner_interest_group/views/crm_lead_views.xml @@ -0,0 +1,56 @@ + + + + + crm.lead.form.interest.group + crm.lead + + + + + + + + + + + + + crm.lead.search.lead.interest.group + crm.lead + + + + + + + + + + crm.lead.search.opportunity.interest.group + crm.lead + + + + + + + +