feat: Remove functionality to hide produce buttons on negative stock.

This commit is contained in:
Suherdy Yacob 2026-02-13 14:51:20 +07:00
parent d31ce99419
commit 2c78cd411b
2 changed files with 2 additions and 66 deletions

View File

@ -1,13 +1,11 @@
{ {
'name': 'MO Lock Consumed', 'name': 'MO Lock Consumed',
'version': '1.0', 'version': '1.0',
'summary': 'Lock consumed quantity on MO when manually edited or picked, and hide produce buttons on negative stock.', 'summary': 'Lock consumed quantity on MO when manually edited or picked.',
'description': """ 'description': """
Prevents automatic update of the 'Consumed' quantity on Manufacturing Orders when: Prevents automatic update of the 'Consumed' quantity on Manufacturing Orders when:
1. The component already has a consumed quantity. 1. The component already has a consumed quantity.
2. The component transfer component is already picked. 2. The component transfer component is already picked.
Also hides 'Produce' and 'Produce All' buttons if the operation would result in negative potential stock for components.
""", """,
'category': 'Manufacturing', 'category': 'Manufacturing',
'author': 'Antigravity', 'author': 'Antigravity',

View File

@ -1,66 +1,4 @@
from odoo import models, api, _ from odoo import models
from odoo.tools import float_compare
import logging
_logger = logging.getLogger(__name__)
class MrpProduction(models.Model): class MrpProduction(models.Model):
_inherit = 'mrp.production' _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:
_logger.info("DEBUG MO_LOCK: MO %s state=%s qty_producing=%s product_qty=%s", production.name, production.state, production.qty_producing, production.product_qty)
_logger.info("DEBUG MO_LOCK: Start - show_produce=%s show_produce_all=%s", production.show_produce, production.show_produce_all)
# 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
for move in production.move_raw_ids:
if move.state in ('done', 'cancel'):
continue
# Skip check if product is not storable (Service, etc.)
if not move.product_id.is_storable:
continue
# If the move is already assigned (Ready), we consider it safe to produce.
if move.state == 'assigned':
continue
# Check availability based on the ACTUAL 'Consumed' quantity
# We use forecast_availability as it includes reservations
# Use float_compare to avoid precision issues
if float_compare(move.forecast_availability, move.quantity, precision_rounding=move.product_uom.rounding) < 0:
potential_negative = True
break
if potential_negative:
production.show_produce = False
production.show_produce_all = False
# Relaxed guard: Do not hide if qty_producing > 0 even if consumption is 0.
# This allows users to trigger consumption by clicking the Produce button.
# If they really want to block 0-consumption production, it should be a validation error on click,
# not a hidden button that prevents them from even trying.