From 0d25fe78aa7d5d5a2d6c3115ee8ebf190911e860 Mon Sep 17 00:00:00 2001 From: Carlos Roca Date: Wed, 17 Jun 2026 13:39:18 +0200 Subject: [PATCH] [IMP] sale_order_product_recommendation_product_sold_by_delivery_week: show live per-customer weekly sales in catalog The product catalog showed the globally stored (and cron-refreshed) weekly sales hint from product_sold_by_delivery_week, which did not match the recommendation wizard: the wizard computes the hint live and filtered by the order's customer. When the catalog is opened from a sale order it now displays a new field, weekly_sold_delivered_catalog_shown, computed on the fly and filtered by the order's commercial partner, hiding the base global hint. Outside of a sale order catalog the product lists keep showing the original stored field, and the base module is left untouched. The computation shared by the wizard and the catalog is extracted into a single helper, product.product._weekly_sold_delivered_shown_map(), so the hint is produced in one place and both computes just map their records. --- .../README.rst | 1 + .../__init__.py | 1 + .../__manifest__.py | 5 +- .../models/__init__.py | 1 + .../models/product_product.py | 52 +++++++++++++++++++ .../readme/CONTRIBUTORS.md | 1 + .../static/description/index.html | 1 + .../views/product_views.xml | 25 +++++++++ .../wizard/sale_order_recommendation.py | 14 ++--- 9 files changed, 91 insertions(+), 10 deletions(-) create mode 100644 sale_order_product_recommendation_product_sold_by_delivery_week/models/__init__.py create mode 100644 sale_order_product_recommendation_product_sold_by_delivery_week/models/product_product.py create mode 100644 sale_order_product_recommendation_product_sold_by_delivery_week/views/product_views.xml diff --git a/sale_order_product_recommendation_product_sold_by_delivery_week/README.rst b/sale_order_product_recommendation_product_sold_by_delivery_week/README.rst index a70c26d5f..ce93e0e56 100644 --- a/sale_order_product_recommendation_product_sold_by_delivery_week/README.rst +++ b/sale_order_product_recommendation_product_sold_by_delivery_week/README.rst @@ -67,6 +67,7 @@ Contributors - David Vidal - David Bañón + - Carlos Roca - Jairo Llopis (`Moduon `__) diff --git a/sale_order_product_recommendation_product_sold_by_delivery_week/__init__.py b/sale_order_product_recommendation_product_sold_by_delivery_week/__init__.py index 40272379f..9b4296142 100644 --- a/sale_order_product_recommendation_product_sold_by_delivery_week/__init__.py +++ b/sale_order_product_recommendation_product_sold_by_delivery_week/__init__.py @@ -1 +1,2 @@ +from . import models from . import wizard diff --git a/sale_order_product_recommendation_product_sold_by_delivery_week/__manifest__.py b/sale_order_product_recommendation_product_sold_by_delivery_week/__manifest__.py index 5f3f64c08..357ee8509 100644 --- a/sale_order_product_recommendation_product_sold_by_delivery_week/__manifest__.py +++ b/sale_order_product_recommendation_product_sold_by_delivery_week/__manifest__.py @@ -12,5 +12,8 @@ "license": "AGPL-3", "depends": ["product_sold_by_delivery_week", "sale_order_product_recommendation"], "auto_install": True, - "data": ["wizard/sale_order_recommendation_view.xml"], + "data": [ + "views/product_views.xml", + "wizard/sale_order_recommendation_view.xml", + ], } diff --git a/sale_order_product_recommendation_product_sold_by_delivery_week/models/__init__.py b/sale_order_product_recommendation_product_sold_by_delivery_week/models/__init__.py new file mode 100644 index 000000000..5c74c8c30 --- /dev/null +++ b/sale_order_product_recommendation_product_sold_by_delivery_week/models/__init__.py @@ -0,0 +1 @@ +from . import product_product diff --git a/sale_order_product_recommendation_product_sold_by_delivery_week/models/product_product.py b/sale_order_product_recommendation_product_sold_by_delivery_week/models/product_product.py new file mode 100644 index 000000000..191837f93 --- /dev/null +++ b/sale_order_product_recommendation_product_sold_by_delivery_week/models/product_product.py @@ -0,0 +1,52 @@ +# Copyright 2026 Tecnativa - Carlos Roca +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from odoo import api, fields, models + + +class ProductProduct(models.Model): + _inherit = "product.product" + + weekly_sold_delivered_catalog_shown = fields.Char( + string="Weekly Sold for Catalog", + compute="_compute_weekly_sold_delivered_catalog_shown", + groups="sales_team.group_sale_salesman", + ) + + def _weekly_sold_delivered_shown_map(self, partner): + """Return ``{product: formatted weekly string}`` for ``self`` computed + live and filtered by ``partner`` (its commercial partner). Services are + skipped.""" + products = self.filtered(lambda p: p.type != "service") + if not products or not partner: + return {} + products_weekly = products.with_context( + weekly_partner_id=partner.id, + )._weekly_sold_delivered() + return { + product: self._format_weekly_string(products_weekly.get(product, False)) + for product in products + } + + def _get_catalog_weekly_partner(self): + """Return the partner to filter the weekly sales by when the product + catalog is opened from a sale order, so the hint matches the + recommendation wizard. Empty recordset in any other context.""" + if self.env.context.get("product_catalog_order_model") != "sale.order": + return self.env["res.partner"] + order_id = self.env.context.get("product_catalog_order_id") + if not order_id: + return self.env["res.partner"] + order = self.env["sale.order"].browse(order_id).exists() + return order.partner_id.commercial_partner_id + + @api.depends_context("product_catalog_order_model", "product_catalog_order_id") + def _compute_weekly_sold_delivered_catalog_shown(self): + """Live, customer-filtered weekly sales hint that replaces, in the + product catalog opened from a sale order, the globally stored hint added + by ``product_sold_by_delivery_week``.""" + self.weekly_sold_delivered_catalog_shown = False + weekly_map = self._weekly_sold_delivered_shown_map( + self._get_catalog_weekly_partner() + ) + for product in self: + product.weekly_sold_delivered_catalog_shown = weekly_map.get(product, False) diff --git a/sale_order_product_recommendation_product_sold_by_delivery_week/readme/CONTRIBUTORS.md b/sale_order_product_recommendation_product_sold_by_delivery_week/readme/CONTRIBUTORS.md index d7a94d737..bf8f5aeea 100644 --- a/sale_order_product_recommendation_product_sold_by_delivery_week/readme/CONTRIBUTORS.md +++ b/sale_order_product_recommendation_product_sold_by_delivery_week/readme/CONTRIBUTORS.md @@ -1,4 +1,5 @@ - [Tecnativa](https://www.tecnativa.com): - David Vidal - David Bañón + - Carlos Roca - Jairo Llopis ([Moduon](https://www.moduon.team)) diff --git a/sale_order_product_recommendation_product_sold_by_delivery_week/static/description/index.html b/sale_order_product_recommendation_product_sold_by_delivery_week/static/description/index.html index e0cb47598..446bd3e7f 100644 --- a/sale_order_product_recommendation_product_sold_by_delivery_week/static/description/index.html +++ b/sale_order_product_recommendation_product_sold_by_delivery_week/static/description/index.html @@ -414,6 +414,7 @@

Contributors

  • Tecnativa:
    • David Vidal
    • David Bañón
    • +
    • Carlos Roca
  • Jairo Llopis (Moduon)
  • diff --git a/sale_order_product_recommendation_product_sold_by_delivery_week/views/product_views.xml b/sale_order_product_recommendation_product_sold_by_delivery_week/views/product_views.xml new file mode 100644 index 000000000..34798401a --- /dev/null +++ b/sale_order_product_recommendation_product_sold_by_delivery_week/views/product_views.xml @@ -0,0 +1,25 @@ + + + + + product.product + + + + + + + + 1 + + + + diff --git a/sale_order_product_recommendation_product_sold_by_delivery_week/wizard/sale_order_recommendation.py b/sale_order_product_recommendation_product_sold_by_delivery_week/wizard/sale_order_recommendation.py index a2bf8b5e0..2c92d8b9f 100644 --- a/sale_order_product_recommendation_product_sold_by_delivery_week/wizard/sale_order_recommendation.py +++ b/sale_order_product_recommendation_product_sold_by_delivery_week/wizard/sale_order_recommendation.py @@ -17,14 +17,10 @@ class SaleOrderRecommendationLine(models.TransientModel): @api.depends("product_id") def _compute_weekly_sold_delivered_shown(self): """Compute dinamically in the view""" - _format_weekly_string = self.env["product.product"]._format_weekly_string self.weekly_sold_delivered_shown = False - products = self.mapped("product_id").filtered(lambda x: x.type != "service") common_partner = self.wizard_id.order_id.partner_id.commercial_partner_id - products_weekly = products.with_context( - weekly_partner_id=common_partner.id, - )._weekly_sold_delivered() - for line in self.filtered(lambda x: x.product_id.type != "service"): - line.weekly_sold_delivered_shown = _format_weekly_string( - products_weekly.get(line.product_id, False) - ) + weekly_map = self.mapped("product_id")._weekly_sold_delivered_shown_map( + common_partner + ) + for line in self: + line.weekly_sold_delivered_shown = weekly_map.get(line.product_id, False)