56 lines
2.0 KiB
Python
56 lines
2.0 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Copyright 2026 Nexa Systems Inc.
|
|
# License OPL-1 (Odoo Proprietary License v1.0)
|
|
# Part of the Fusion Plating product family.
|
|
|
|
import logging
|
|
|
|
from odoo import models, _
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
class MrpProduction(models.Model):
|
|
_inherit = 'mrp.production'
|
|
|
|
def action_confirm(self):
|
|
"""Soft gate: warn if parts haven't been received yet.
|
|
|
|
Checks the linked sale order's receiving status. If parts
|
|
are not yet received, logs a warning. This is informational
|
|
only -- it does not block confirmation. The gate is soft
|
|
because handshake deals and urgent jobs need flexibility.
|
|
"""
|
|
for production in self:
|
|
so = production._get_source_sale_order()
|
|
if so and so.x_fc_receiving_status in ('not_received', False):
|
|
_logger.warning(
|
|
'MO %s: parts not yet received for SO %s (receiving status: %s). '
|
|
'Proceeding with confirmation.',
|
|
production.name, so.name, so.x_fc_receiving_status,
|
|
)
|
|
production.message_post(
|
|
body=_(
|
|
'Warning: Parts not yet received for sale order '
|
|
'<a href="/odoo/sale-order/%s">%s</a>. '
|
|
'Manufacturing confirmed without receiving verification.'
|
|
) % (so.id, so.name),
|
|
)
|
|
return super().action_confirm()
|
|
|
|
def _get_source_sale_order(self):
|
|
"""Find the sale order linked to this MO via origin field."""
|
|
self.ensure_one()
|
|
if not self.origin:
|
|
return False
|
|
# origin may contain SO name like "S00001" or configurator ref "CFG-00001"
|
|
so = self.env['sale.order'].search(
|
|
[('name', '=', self.origin)], limit=1,
|
|
)
|
|
if not so:
|
|
# Try matching by origin containing the SO name
|
|
so = self.env['sale.order'].search(
|
|
[('name', 'ilike', self.origin)], limit=1,
|
|
)
|
|
return so or False
|