from odoo import models, api class StockMove(models.Model): _inherit = 'stock.move' def _should_bypass_set_qty_producing(self): """ Only bypass if explicitly flagged as manual consumption. We rely on the write() method to set this flag and to block resets. """ # Remove sudo() to allow NewId (virtual records) to access their cache. # If we use sudo(), it might force a DB read which fails for NewId or returns old data. allow_bypass = self.manual_consumption # NewId Fix: If it's a virtual record (NewId) and has quantity, it's "locked" logic-wise # because the user (or auto-fill) has set a value, and we don't want scaling to wipe it. # Real IDs are integers. Virtual IDs (NewId) are not. if not allow_bypass and self.quantity > 0 and not isinstance(self.id, int): allow_bypass = True if allow_bypass: return True return super()._should_bypass_set_qty_producing() def write(self, vals): # 1. Zero-Guard: Block resets to 0 if Locked # We ALLOW positive updates so users can manually set consumption. # We rely on _should_bypass_set_qty_producing (via manual_consumption=True) # to prevent the System from generating Scaling updates. if 'quantity' in vals and vals['quantity'] == 0: locked_moves = self.filtered(lambda m: m.manual_consumption) if locked_moves and len(locked_moves) == len(self): del vals['quantity'] # 2. Arm the Lock if 'quantity' in vals and vals.get('quantity', 0) > 0: vals['manual_consumption'] = True vals['picked'] = True return super().write(vals) @api.model_create_multi def create(self, vals_list): for vals in vals_list: # Look at Consumed (quantity) only. # If we lock on Demand (product_uom_qty), we block the initial auto-fill. consumed = vals.get('quantity', 0) if consumed > 0: # Lock Immediately if created with a specific consumed quantity vals['manual_consumption'] = True vals['picked'] = True return super().create(vals_list)