From 9d6044dd49eb5869eb8d37a766bcf142d032b90c Mon Sep 17 00:00:00 2001 From: Suherdy Yacob Date: Thu, 19 Mar 2026 13:19:35 +0700 Subject: [PATCH] fix: Adjust total consumed quantities for microscopic rounding errors by applying the difference to a single move line instead of individual lines. --- models/mrp_production.py | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/models/mrp_production.py b/models/mrp_production.py index 14a74fd..0d4c12e 100644 --- a/models/mrp_production.py +++ b/models/mrp_production.py @@ -157,18 +157,28 @@ class MrpProduction(models.Model): # 2. Fix "Consumed" (move_line_ids.quantity) # If the line is FULLY consumed (e.g. qty_producing == product_qty), - # then move lines should match the ideal quantity. + # then total consumed should match the ideal quantity. + total_done = sum(move.move_line_ids.mapped('quantity')) if production.qty_producing == production.product_qty: - for ml in move.move_line_ids: - if abs(ml.quantity - ideal_qty) > 0.000001: - ml.quantity = ideal_qty + diff = ideal_qty - total_done + # Only auto-fix if it's a microscopic rounding drift (not a user overriding quantity intentionally) + if 0.000001 < abs(diff) < (move.product_uom.rounding * 1.5): + for ml in move.move_line_ids: + # Safely apply the tiny difference to the first line that has enough quantity + if ml.quantity and ml.quantity + diff >= 0: + ml.quantity += diff + break else: - # Otherwise just round to 2 decimals if it's "close enough" to a clean decimal - # but drifted by microscopic dust. - for ml in move.move_line_ids: - clean_done = round(ml.quantity, 2) - if 0.000001 < abs(ml.quantity - clean_done) < (move.product_uom.rounding * 1.5): - ml.quantity = clean_done + # Otherwise just round to 2 decimals if the total drifted by microscopic dust. + # We shouldn't blindly round every single line if they are split in strange ways, + # but we can fix the tiny decimal dust on the first available line. + clean_total = round(total_done, 2) + diff = clean_total - total_done + if 0.000001 < abs(diff) < (move.product_uom.rounding * 1.5): + for ml in move.move_line_ids: + if ml.quantity and ml.quantity + diff >= 0: + ml.quantity += diff + break def _merge_finished_move_lines(self): for production in self: