# -*- coding: utf-8 -*- # Copyright 2026 Nexa Systems Inc. # License OPL-1 (Odoo Proprietary License v1.0) # Part of the Fusion Plating product family. from odoo import api, fields, models class SaleOrder(models.Model): _inherit = 'sale.order' x_fc_receiving_ids = fields.One2many( 'fp.receiving', 'sale_order_id', string='Receiving Records', ) x_fc_receiving_count = fields.Integer( string='Receiving Count', compute='_compute_receiving_count', ) @api.depends('x_fc_receiving_ids') def _compute_receiving_count(self): for rec in self: rec.x_fc_receiving_count = len(rec.x_fc_receiving_ids) def action_confirm(self): """Override to auto-create receiving record on SO confirmation. Per-line metadata (part catalog, part number) is sourced from ``sale.order.line.x_fc_part_catalog_id`` — NOT from the SO header. The header field exists too but is rarely populated; the line carries the authoritative part link in the configurator flow. Each receiving line prefills ``received_qty`` to ``expected_qty`` so the racking crew only types when the count is off (mirrors the header behaviour in fp_receiving.py:create). """ res = super().action_confirm() for order in self: if order.x_fc_receiving_ids: continue total_qty = sum(order.order_line.mapped('product_uom_qty')) line_vals = [] for line in order.order_line: part = ( line.x_fc_part_catalog_id if 'x_fc_part_catalog_id' in line._fields else False ) expected = int(line.product_uom_qty or 0) line_vals.append((0, 0, { 'part_catalog_id': part.id if part else False, 'part_number': (part.part_number if part else '') or '', 'description': line.name or '', 'expected_qty': expected, 'received_qty': expected, })) self.env['fp.receiving'].create({ 'sale_order_id': order.id, 'expected_qty': int(total_qty), 'line_ids': line_vals, }) return res def action_view_receiving(self): """Smart button action to view receiving records.""" self.ensure_one() if self.x_fc_receiving_count == 1: return { 'type': 'ir.actions.act_window', 'res_model': 'fp.receiving', 'res_id': self.x_fc_receiving_ids[0].id, 'view_mode': 'form', 'target': 'current', } return { 'type': 'ir.actions.act_window', 'res_model': 'fp.receiving', 'view_mode': 'list,form', 'domain': [('sale_order_id', '=', self.id)], 'target': 'current', }