From ff797976681ad3941ac211056c3c0ebe51efaa14 Mon Sep 17 00:00:00 2001 From: ABE-Mark45 Date: Thu, 21 Dec 2023 13:39:43 +0200 Subject: [PATCH] [FIX] mrp: calculate produced quantity based on free subcontractor stock The free to produce quantity was calculated based on the available stock in the warehouse in addition to the subcontracting location. For this reason, `free_to_manufacture_qty` variable was introduced. If it is a non-subcontracting BoM, it will be equal to the free quantity available in warehouse stock. Otherwise, it will contain only the stock in the subcontracting location. task-3632211 Part-of: odoo/odoo#145889 --- addons/mrp/report/mrp_report_bom_structure.py | 8 ++++++-- .../mrp_subcontracting/report/mrp_report_bom_structure.py | 5 +++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/addons/mrp/report/mrp_report_bom_structure.py b/addons/mrp/report/mrp_report_bom_structure.py index 50e19a34d24..0e447b1e480 100644 --- a/addons/mrp/report/mrp_report_bom_structure.py +++ b/addons/mrp/report/mrp_report_bom_structure.py @@ -30,7 +30,7 @@ class ReportBomStructure(models.AbstractModel): if comp['product'].type != 'product' or float_is_zero(comp['base_bom_line_qty'], precision_digits=comp['uom'].rounding): continue components_qty_to_produce[comp['product_id']] += comp['base_bom_line_qty'] - components_qty_available[comp['product_id']] = comp['quantity_available'] + components_qty_available[comp['product_id']] = comp['free_to_manufacture_qty'] producibles = [float_round(components_qty_available[p_id] / qty, precision_digits=0, rounding_method='DOWN') for p_id, qty in components_qty_to_produce.items()] return min(producibles) * bom_data['bom']['product_qty'] if producibles else 0 @@ -241,6 +241,7 @@ class ReportBomStructure(models.AbstractModel): 'quantity': current_quantity, 'quantity_available': quantities_info.get('free_qty', 0), 'quantity_on_hand': quantities_info.get('on_hand_qty', 0), + 'free_to_manufacture_qty': quantities_info.get('free_to_manufacture_qty', 0), 'base_bom_line_qty': bom_line.product_qty if bom_line else False, # bom_line isn't defined only for the top-level product 'name': product.display_name or bom.product_tmpl_id.display_name, 'uom': bom.product_uom_id if bom else product.uom_id, @@ -360,6 +361,7 @@ class ReportBomStructure(models.AbstractModel): 'quantity': line_quantity, 'quantity_available': quantities_info.get('free_qty', 0), 'quantity_on_hand': quantities_info.get('on_hand_qty', 0), + 'free_to_manufacture_qty': quantities_info.get('free_to_manufacture_qty', 0), 'base_bom_line_qty': bom_line.product_qty, 'uom': bom_line.product_uom_id, 'uom_name': bom_line.product_uom_id.name, @@ -381,11 +383,13 @@ class ReportBomStructure(models.AbstractModel): @api.model def _get_quantities_info(self, product, bom_uom, product_info, parent_bom=False, parent_product=False): - return { + quantities_info = { 'free_qty': max(product.uom_id._compute_quantity(product.free_qty, bom_uom), 0) if product.detailed_type == 'product' else 0, 'on_hand_qty': product.uom_id._compute_quantity(product.qty_available, bom_uom) if product.detailed_type == 'product' else 0, 'stock_loc': 'in_stock', } + quantities_info['free_to_manufacture_qty'] = quantities_info['free_qty'] + return quantities_info @api.model def _update_product_info(self, product, bom_key, product_info, warehouse, quantity, bom, parent_bom, parent_product): diff --git a/addons/mrp_subcontracting/report/mrp_report_bom_structure.py b/addons/mrp_subcontracting/report/mrp_report_bom_structure.py index 6072998f322..6d3addf39d6 100644 --- a/addons/mrp_subcontracting/report/mrp_report_bom_structure.py +++ b/addons/mrp_subcontracting/report/mrp_report_bom_structure.py @@ -88,7 +88,7 @@ class ReportBomStructure(models.AbstractModel): @api.model def _get_quantities_info(self, product, bom_uom, product_info, parent_bom=False, parent_product=False): - quantities_info = super()._get_quantities_info(product, bom_uom, product_info, parent_product) + quantities_info = super()._get_quantities_info(product, bom_uom, product_info, parent_bom, parent_product) if parent_product and parent_bom and parent_bom.type == 'subcontract' and product.type == 'product': route_info = product_info.get(parent_product.id, {}).get(parent_bom.id, {}) if route_info and route_info['route_type'] == 'subcontract': @@ -98,7 +98,8 @@ class ReportBomStructure(models.AbstractModel): stock_loc = f"subcontract_{subcontracting_loc.id}" if not product_info[product.id]['consumptions'].get(stock_loc, False): product_info[product.id]['consumptions'][stock_loc] = 0 - quantities_info['free_qty'] += product.uom_id._compute_quantity(subloc_product.free_qty, bom_uom) + quantities_info['free_to_manufacture_qty'] = product.uom_id._compute_quantity(subloc_product.free_qty, bom_uom) + quantities_info['free_qty'] += quantities_info['free_to_manufacture_qty'] quantities_info['on_hand_qty'] += product.uom_id._compute_quantity(subloc_product.qty_available, bom_uom) quantities_info['stock_loc'] = stock_loc