from odoo import models, api class MrpProduction(models.Model): _inherit = 'mrp.production' @api.depends('state', 'product_qty', 'qty_producing', 'move_raw_ids.quantity', 'move_raw_ids.product_uom_qty') def _compute_show_produce(self): """ Override to hide produce buttons if proceeding would cause negative stock. """ # First compute standard visibility super()._compute_show_produce() for production in self: # If standard logic says hidden, no need to check further if not production.show_produce and not production.show_produce_all: continue # Determine which action we are validating # If show_produce_all is True, we are producing the full remaining amount # If show_produce (partial) is True, we are producing 'qty_producing' # This logic needs to mirror what happens when the button is clicked. # However, for visibility, we want to know if *current* configured production is possible. # If "Produce All" is available, it means we plan to produce everything remaining. # If "Produce" (partial) is available, we plan to produce `qty_producing`. # Check if any component would go negative potential_negative = False # We need to check stock availability in the source location location = production.location_src_id for move in production.move_raw_ids: if move.state in ('done', 'cancel'): continue # User request: # "if the components qty consumed is 0 then still show produce and produce all button" # "only hide the visibility if components qty consumed will make the stock negative" # If nothing is currently set to be consumed (0), we assume it's safe to proceed # (or the user intends to consume 0/different amount later). # We only block if the *Explicitly Consumed* amount exceeds available stock. if move.quantity == 0: continue # Check availability based on the ACTUAL 'Consumed' quantity qty_to_consume = move.quantity # Check availability product_in_location = move.product_id.with_context(location=location.id) available_qty = product_in_location.qty_available if available_qty - qty_to_consume < 0: potential_negative = True break if potential_negative: production.show_produce = False production.show_produce_all = False # User request: "hide the produce if all components consumed is 0 (does not make sense right to produce without components)" # This should only apply if we are in "Partial Produce" mode (qty_producing > 0), where consumption should have been calculated/entered. # If qty_producing is 0 (Fresh MO), we usually show "Produce All", which will auto-calculate consumption, so we shouldn't hide it. if production.qty_producing > 0: # Check if ALL moves have 0 quantity # We filter out cancelled moves, and maybe we should focus on raw materials. relevant_moves = production.move_raw_ids.filtered(lambda m: m.state not in ('done', 'cancel')) if relevant_moves and all(m.quantity == 0 for m in relevant_moves): production.show_produce = False production.show_produce_all = False