From a94f3f4dcb24e08cd4db7fd50ea704e9a065fd83 Mon Sep 17 00:00:00 2001 From: Achraf Date: Mon, 12 Feb 2024 09:12:48 +0000 Subject: [PATCH] [FIX] mrp: Allow users to edit 'MO Overview' report on studio Steps: - Install `mrp` - Install `web_studio` - Open `Inventory` - Click on `Toggle Studio` button - Click on `Reports` tab - Remove default filter - Try to open `MO Overview` report via reports view - Traceback When loading the `MO Overview` report, `_get_report_qweb` is called and builds the context rendering here https://github.com/odoo/enterprise/blob/b7d0d3034d53cdab831f42f8b37a14cf50f3720e/web_studio/controllers/report.py#L549 We therefore call _get_rendering_context with `[0]` in `docids`, which will call `_get_report_values` in `mrp/report/mrp_report_mo_overview`. https://github.com/odoo/odoo/blob/6e8e62db1fa2010c3e6696baacaedf997fd8fa89/addons/mrp/report/mrp_report_mo_overview.py#L29-L30 https://github.com/odoo/odoo/blob/6e8e62db1fa2010c3e6696baacaedf997fd8fa89/addons/mrp/report/mrp_report_mo_overview.py#L53-L54 `_get_report_data` performs a `browse(0)` on `mrp.production`. BaseModels::browse replaces falsy values with empty tuples `()`. https://github.com/odoo/odoo/blob/5d726c933b591468bcef85a4e14b183278a00e5b/odoo/models.py#L5441-L5442 This implies the return of an empty model record. `mrp_report_mo_overview` will therefore use a record containing null values in its operations, for example division, which causes a division by 0 error, or a log10(0) in `_get_uom_precision` because `product_uom.rounding` is 0. https://github.com/odoo/odoo/blob/6e8e62db1fa2010c3e6696baacaedf997fd8fa89/addons/mrp/report/mrp_report_mo_overview.py#L105-L106 This commit corrects these incorrect defaults with fallbacks opw-3725827 closes odoo/odoo#153919 X-original-commit: 1bad2b3b2e285e6e7b8f6e93430b6415c3c65303 Signed-off-by: Achraf Ben Azzouz (abz) --- addons/mrp/report/mrp_report_mo_overview.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/addons/mrp/report/mrp_report_mo_overview.py b/addons/mrp/report/mrp_report_mo_overview.py index d8ef6ac8730..bf76065c940 100644 --- a/addons/mrp/report/mrp_report_mo_overview.py +++ b/addons/mrp/report/mrp_report_mo_overview.py @@ -57,8 +57,8 @@ class ReportMoOverview(models.AbstractModel): doc['show_uom'] = self.env.user.user_has_groups('uom.group_uom') if doc['show_uom']: footer_colspan += 1 - doc['data_mo_unit_cost'] = doc['summary'].get('mo_cost', 0) / doc['summary'].get('quantity', 1) - doc['data_real_unit_cost'] = doc['summary'].get('real_cost', 0) / doc['summary'].get('quantity', 1) + doc['data_mo_unit_cost'] = doc['summary'].get('mo_cost', 0) / (doc['summary'].get('quantity') or 1) + doc['data_real_unit_cost'] = doc['summary'].get('real_cost', 0) / (doc['summary'].get('quantity') or 1) doc['unfolded_ids'] = set(json.loads(data.get('unfoldedIds', '[]'))) doc['footer_colspan'] = footer_colspan doc['get_color'] = get_color @@ -93,8 +93,8 @@ class ReportMoOverview(models.AbstractModel): def _get_report_extra_lines(self, summary, components, operations, production_done=False): currency = summary.get('currency', self.env.company.currency_id) - unit_mo_cost = currency.round(summary.get('mo_cost', 0) / summary.get('quantity', 1)) - unit_real_cost = currency.round(summary.get('real_cost', 0) / summary.get('quantity', 1)) + unit_mo_cost = currency.round(summary.get('mo_cost', 0) / (summary.get('quantity') or 1)) + unit_real_cost = currency.round(summary.get('real_cost', 0) / (summary.get('quantity') or 1)) extras = { 'unit_mo_cost': unit_mo_cost, 'unit_mo_cost_decorator': self._get_comparison_decorator(unit_real_cost, unit_mo_cost, currency.rounding), @@ -175,7 +175,7 @@ class ReportMoOverview(models.AbstractModel): 'formatted_state': self._format_state(production, components), 'quantity': production.product_qty if production.state != 'done' else production.qty_produced, 'uom_name': production.product_uom_id.display_name, - 'uom_precision': self._get_uom_precision(production.product_uom_id.rounding), + 'uom_precision': self._get_uom_precision(production.product_uom_id.rounding or 0.01), 'quantity_free': product.uom_id._compute_quantity(max(product.free_qty, 0), production.product_uom_id) if product.type == 'product' else False, 'quantity_on_hand': product.uom_id._compute_quantity(product.qty_available, production.product_uom_id) if product.type == 'product' else False, 'quantity_reserved': 0.0, @@ -189,6 +189,8 @@ class ReportMoOverview(models.AbstractModel): } def _get_unit_cost(self, move): + if not move: + return 0.0 return move.product_id.uom_id._compute_price(move.product_id.standard_price, move.product_uom) def _format_state(self, record, components=False):