74 lines
3.7 KiB
Python
74 lines
3.7 KiB
Python
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
|