Skip to content

Commit

Permalink
[MIG]crm_lead_product: Migration to 14.0
Browse files Browse the repository at this point in the history
  • Loading branch information
GuillemCForgeFlow committed Mar 8, 2024
1 parent 9161649 commit 028e705
Show file tree
Hide file tree
Showing 19 changed files with 157 additions and 113 deletions.
32 changes: 15 additions & 17 deletions crm_lead_product/README.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
=================
Lead Line Product
=================
================
CRM Lead Product
================

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Expand All @@ -17,26 +17,26 @@ Lead Line Product
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
:alt: License: LGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fcrm-lightgray.png?logo=github
:target: https://github.com/OCA/crm/tree/13.0/crm_lead_product
:target: https://github.com/OCA/crm/tree/14.0/crm_lead_product
:alt: OCA/crm
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/crm-13-0/crm-13-0-crm_lead_product
:target: https://translation.odoo-community.org/projects/crm-14-0/crm-14-0-crm_lead_product
: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=13.0
:target: https://runboat.odoo-community.org/builds?repo=OCA/crm&target_branch=14.0
:alt: Try me on Runboat

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


This module allows the user to link multiple products, product categories or product templates to a lead or an opportunity
in order to be able to do a product demand forecasting taking into account the leads and opportunities defined in odoo.
Included in the product line there are two computed fields, the planned revenue and expected revenue. On one hand, the
planned revenue is computed as the selling price times the quantity. On the other hand, the expected revenue takes into account
in order to be able to do a product demand forecasting taking into account the leads and opportunities defined in Odoo.

Included in the product line there are two computed fields, the expected revenue and prorated revenue. On one hand, the
expected revenue is computed as the selling price times the quantity. On the other hand, the prorated revenue takes into account
the probability of the opportunity and is computed as the planned revenue times the probability.

The module also includes a reporting section where the user can easily see in a pivot and graph view the relationship
between products, stage of the lead/opportunity and the planned or expected revenue for that product.
between products, stage of the lead/opportunity and the expected or prorated revenue for that product.

**Table of contents**

Expand All @@ -46,24 +46,22 @@ between products, stage of the lead/opportunity and the planned or expected reve
Configuration
=============


To configure this module to be available for the Leads the user needs to activate the Leads option in CRM settings

Usage
=====


* Go to menu **CRM > Lead** and create or edit a Lead adding all the products associated to it.
* Go to menu **CRM > My Pipeline** and create or edit an Opportunity adding all the products associated to it.
* Go to menu **CRM > Reporting > Pipeline by Product** to run the report that relates product to planned and expected revenue per stage
* Go to menu **CRM > Reporting > Pipeline by Product** to run the report that relates product to expected and prorated revenue per stage

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_product%0Aversion:%2013.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
`feedback <https://github.com/OCA/crm/issues/new?body=module:%20crm_lead_product%0Aversion:%2014.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.

Expand All @@ -78,8 +76,8 @@ Authors
Contributors
~~~~~~~~~~~~


* Adria Gil Sorribes <[email protected]>
* Guillem Casassas <[email protected]>

Maintainers
~~~~~~~~~~~
Expand All @@ -94,6 +92,6 @@ 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 <https://github.com/OCA/crm/tree/13.0/crm_lead_product>`_ project on GitHub.
This module is part of the `OCA/crm <https://github.com/OCA/crm/tree/14.0/crm_lead_product>`_ project on GitHub.

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

# Copyright (C) 2017-2024 ForgeFlow S.L. (https://www.forgeflow.com)
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
from . import models
from . import report
11 changes: 5 additions & 6 deletions crm_lead_product/__manifest__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
# Copyright (C) 2017-19 ForgeFlow S.L. (https://www.forgeflow.com).
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl).

# Copyright (C) 2017-2024 ForgeFlow S.L. (https://www.forgeflow.com)
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
{
"name": "Lead Line Product",
"version": "13.0.1.0.1",
"name": "CRM Lead Product",
"version": "14.0.1.0.0",
"category": "Customer Relationship Management",
"license": "LGPL-3",
"summary": "Adds a lead line in the lead/opportunity model " "in odoo",
"summary": "Adds a lead line in the lead/opportunity model in odoo",
"author": "ForgeFlow, Odoo Community Association (OCA)",
"website": "https://github.com/OCA/crm",
"depends": ["crm", "product"],
Expand Down
59 changes: 59 additions & 0 deletions crm_lead_product/migrations/14.0.1.0.0/pre-migration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Copyright (C) 2017-2024 ForgeFlow S.L. (https://www.forgeflow.com)
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
from openupgradelib import openupgrade


@openupgrade.migrate()
def migrate(env, version):
if openupgrade.column_exists(
env.cr, "crm_lead_line", "expected_revenue"
) and not openupgrade.column_exists(env.cr, "crm_lead_line", "prorated_revenue"):
env.cr.execute(
"""
ALTER TABLE crm_lead_line
ADD COLUMN prorated_revenue NUMERIC;
COMMENT ON COLUMN crm_lead_line.prorated_revenue
IS 'Prorated Revenue';
"""
)
# PostgreSQL already automatically truncates from `double_precision` type to
# `numeric` type, this is needed as we are converting from Float Odoo field
# to Monetary Odoo field
env.cr.execute(
"""
UPDATE crm_lead_line
SET prorated_revenue = expected_revenue;
"""
)
env.cr.execute(
"""
ALTER TABLE crm_lead_line
DROP COLUMN expected_revenue;
"""
)
if openupgrade.column_exists(
env.cr, "crm_lead_line", "planned_revenue"
) and not openupgrade.column_exists(env.cr, "crm_lead_line", "expected_revenue"):
env.cr.execute(
"""
ALTER TABLE crm_lead_line
ADD COLUMN expected_revenue NUMERIC;
COMMENT ON COLUMN crm_lead_line.expected_revenue
IS 'Expected Revenue';
"""
)
# PostgreSQL already automatically truncates from `double_precision` type to
# `numeric` type, this is needed as we are converting from Float Odoo field
# to Monetary Odoo field
env.cr.execute(
"""
UPDATE crm_lead_line
SET expected_revenue = planned_revenue;
"""
)
env.cr.execute(
"""
ALTER TABLE crm_lead_line
DROP COLUMN planned_revenue;
"""
)
4 changes: 2 additions & 2 deletions crm_lead_product/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl).

# Copyright (C) 2017-2024 ForgeFlow S.L. (https://www.forgeflow.com)
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
from . import crm_lead_line
from . import crm_lead
21 changes: 8 additions & 13 deletions crm_lead_product/models/crm_lead.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Copyright (C) 2017-19 ForgeFlow S.L. (https://www.forgeflow.com)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
# Copyright (C) 2017-2024 ForgeFlow S.L. (https://www.forgeflow.com)
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)

from odoo import api, fields, models

Expand All @@ -13,20 +13,15 @@ class CrmLead(models.Model):

@api.onchange("lead_line_ids")
def _onchange_lead_line_ids(self):
planned_revenue = 0
expected_revenue = 0
for lead_line in self.lead_line_ids:
if lead_line.planned_revenue != 0:
planned_revenue += lead_line.planned_revenue
self.planned_revenue = planned_revenue
expected_revenue += lead_line.expected_revenue
self.expected_revenue = expected_revenue

def _convert_opportunity_data(self, customer, team_id=False):
res = super(CrmLead, self)._convert_opportunity_data(customer, team_id)

# Update planned_revenue
planned_revenue = 0
expected_revenue = 0
for lead_line in self.lead_line_ids:
planned_revenue += lead_line.planned_revenue

res["planned_revenue"] = planned_revenue

expected_revenue += lead_line.expected_revenue
res["expected_revenue"] = expected_revenue
return res
49 changes: 23 additions & 26 deletions crm_lead_product/models/crm_lead_line.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Copyright (C) 2017-19 ForgeFlow S.L. (https://www.forgeflow.com)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
# Copyright (C) 2017-2024 ForgeFlow S.L. (https://www.forgeflow.com)
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)

from odoo import api, fields, models

Expand All @@ -9,16 +9,16 @@ class CrmLeadLine(models.Model):
_description = "Line in CRM Lead"

@api.depends("price_unit", "product_qty")
def _compute_planned_revenue(self):
def _compute_expected_revenue(self):
for rec in self:
rec.planned_revenue = rec.product_qty * rec.price_unit
rec.expected_revenue = rec.product_qty * rec.price_unit

@api.depends("lead_id.probability", "planned_revenue")
def _compute_expected_revenue(self):
@api.depends("lead_id.probability", "expected_revenue")
def _compute_prorated_revenue(self):
for rec in self:
if rec.lead_id and rec.lead_id.type != "lead":
rec.expected_revenue = (
rec.planned_revenue * rec.lead_id.probability * (1 / 100)
rec.prorated_revenue = (
rec.expected_revenue * rec.lead_id.probability * (1 / 100)
)

lead_id = fields.Many2one("crm.lead", string="Lead")
Expand All @@ -32,16 +32,24 @@ def _compute_expected_revenue(self):
)
product_qty = fields.Integer(string="Product Quantity", default=1, required=True)
uom_id = fields.Many2one("uom.uom", string="Unit of Measure", readonly=True)
price_unit = fields.Float(string="Price Unit")
planned_revenue = fields.Float(
compute="_compute_planned_revenue",
string="Planned revenue",
compute_sudo=True,
store=True,
price_unit = fields.Float(string="Price Unit", digits="Product Price")
company_currency = fields.Many2one(
"res.currency",
string="Currency",
related="lead_id.company_currency",
readonly=True,
)
expected_revenue = fields.Float(
expected_revenue = fields.Monetary(
compute="_compute_expected_revenue",
string="Expected revenue",
currency_field="company_currency",
compute_sudo=True,
store=True,
)
prorated_revenue = fields.Monetary(
compute="_compute_prorated_revenue",
string="Prorated revenue",
currency_field="company_currency",
compute_sudo=True,
store=True,
)
Expand All @@ -51,7 +59,6 @@ def _onchange_product_id(self):
domain = {}
if not self.lead_id:
return

Check warning on line 61 in crm_lead_product/models/crm_lead_line.py

View check run for this annotation

Codecov / codecov/patch

crm_lead_product/models/crm_lead_line.py#L61

Added line #L61 was not covered by tests

if not self.product_id:
self.price_unit = 0.0
domain["uom_id"] = []
Expand All @@ -62,22 +69,18 @@ def _onchange_product_id(self):
self.category_id = product.categ_id.id
self.product_tmpl_id = product.product_tmpl_id.id
self.price_unit = product.list_price

if product.name:
self.name = product.name

if (
not self.uom_id
or product.uom_id.category_id.id != self.uom_id.category_id.id
):
self.uom_id = product.uom_id.id
domain["uom_id"] = [("category_id", "=", product.uom_id.category_id.id)]

if self.uom_id and self.uom_id.id != product.uom_id.id:
self.price_unit = product.uom_id._compute_price(

Check warning on line 81 in crm_lead_product/models/crm_lead_line.py

View check run for this annotation

Codecov / codecov/patch

crm_lead_product/models/crm_lead_line.py#L81

Added line #L81 was not covered by tests
self.price_unit, self.uom_id
)

return {"domain": domain}

@api.onchange("category_id")
Expand All @@ -89,15 +92,13 @@ def _onchange_category_id(self):
categ_id = self.category_id
if categ_id.name and not self.name:
self.name = categ_id.name

Check warning on line 94 in crm_lead_product/models/crm_lead_line.py

View check run for this annotation

Codecov / codecov/patch

crm_lead_product/models/crm_lead_line.py#L94

Added line #L94 was not covered by tests

# Check if there are already defined product and product template
# and remove them if categories do not match
if self.product_id and self.product_id.categ_id != categ_id:
self.product_id = None
self.name = categ_id.name
if self.product_tmpl_id and self.product_tmpl_id.categ_id != categ_id:
self.product_tmpl_id = None

return {"domain": domain}

@api.onchange("product_tmpl_id")
Expand All @@ -110,26 +111,22 @@ def _onchange_product_tmpl_id(self):
if product_tmpl.name and not self.name:
self.name = product_tmpl.name

Check warning on line 112 in crm_lead_product/models/crm_lead_line.py

View check run for this annotation

Codecov / codecov/patch

crm_lead_product/models/crm_lead_line.py#L112

Added line #L112 was not covered by tests
self.category_id = product_tmpl.categ_id

if self.product_id:
# Check if there are already defined product and remove
# if it does not match
if self.product_id.product_tmpl_id != product_tmpl:
self.product_id = None
self.name = product_tmpl.name

Check warning on line 119 in crm_lead_product/models/crm_lead_line.py

View check run for this annotation

Codecov / codecov/patch

crm_lead_product/models/crm_lead_line.py#L118-L119

Added lines #L118 - L119 were not covered by tests

return {"domain": domain}

@api.onchange("uom_id")
def _onchange_uom_id(self):
result = {}
if not self.uom_id:
self.price_unit = 0.0

if self.product_id and self.uom_id:
price_unit = self.product_id.list_price
self.price_unit = self.product_id.uom_id._compute_price(

Check warning on line 129 in crm_lead_product/models/crm_lead_line.py

View check run for this annotation

Codecov / codecov/patch

crm_lead_product/models/crm_lead_line.py#L128-L129

Added lines #L128 - L129 were not covered by tests
price_unit, self.uom_id
)

return result
1 change: 0 additions & 1 deletion crm_lead_product/readme/CONFIGURE.rst
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@

To configure this module to be available for the Leads the user needs to activate the Leads option in CRM settings
2 changes: 1 addition & 1 deletion crm_lead_product/readme/CONTRIBUTORS.rst
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@

* Adria Gil Sorribes <[email protected]>
* Guillem Casassas <[email protected]>
10 changes: 5 additions & 5 deletions crm_lead_product/readme/DESCRIPTION.rst
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@

This module allows the user to link multiple products, product categories or product templates to a lead or an opportunity
in order to be able to do a product demand forecasting taking into account the leads and opportunities defined in odoo.
Included in the product line there are two computed fields, the planned revenue and expected revenue. On one hand, the
planned revenue is computed as the selling price times the quantity. On the other hand, the expected revenue takes into account
in order to be able to do a product demand forecasting taking into account the leads and opportunities defined in Odoo.

Included in the product line there are two computed fields, the expected revenue and prorated revenue. On one hand, the
expected revenue is computed as the selling price times the quantity. On the other hand, the prorated revenue takes into account
the probability of the opportunity and is computed as the planned revenue times the probability.

The module also includes a reporting section where the user can easily see in a pivot and graph view the relationship
between products, stage of the lead/opportunity and the planned or expected revenue for that product.
between products, stage of the lead/opportunity and the expected or prorated revenue for that product.
3 changes: 1 addition & 2 deletions crm_lead_product/readme/USAGE.rst
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

* Go to menu **CRM > Lead** and create or edit a Lead adding all the products associated to it.
* Go to menu **CRM > My Pipeline** and create or edit an Opportunity adding all the products associated to it.
* Go to menu **CRM > Reporting > Pipeline by Product** to run the report that relates product to planned and expected revenue per stage
* Go to menu **CRM > Reporting > Pipeline by Product** to run the report that relates product to expected and prorated revenue per stage
4 changes: 2 additions & 2 deletions crm_lead_product/report/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

# Copyright (C) 2017-2024 ForgeFlow S.L. (https://www.forgeflow.com)
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
from . import crm_product_report
Loading

0 comments on commit 028e705

Please sign in to comment.