# -*- coding: utf-8 -*- # Copyright 2026 Nexa Systems Inc. # License OPL-1 (Odoo Proprietary License v1.0) # # Adds the Work Order smart button + header action to fp.receiving so # the receiving form mirrors the SO's WO entry point. Button appears # once the receiving is closed and stays until every linked fp.job # reaches state='done'. from odoo import _, fields, models from odoo.exceptions import UserError class FpReceiving(models.Model): _inherit = 'fp.receiving' x_fc_fp_job_count = fields.Integer( string='Work Orders', compute='_compute_fp_job_count', ) x_fc_show_work_order_btn = fields.Boolean( string='Show Work Order Button', compute='_compute_show_work_order_btn', help='True once this receiving is closed and at least one linked ' 'work order is still open (state != done). Hidden again ' 'when every job is done.', ) def _compute_fp_job_count(self): Job = self.env['fp.job'].sudo() for rec in self: if rec.sale_order_id: rec.x_fc_fp_job_count = Job.search_count( [('sale_order_id', '=', rec.sale_order_id.id)] ) else: rec.x_fc_fp_job_count = 0 def _compute_show_work_order_btn(self): Job = self.env['fp.job'].sudo() for rec in self: if rec.state != 'closed' or not rec.sale_order_id: rec.x_fc_show_work_order_btn = False continue jobs = Job.search([('sale_order_id', '=', rec.sale_order_id.id)]) rec.x_fc_show_work_order_btn = bool(jobs) and any( j.state != 'done' for j in jobs ) def action_view_fp_jobs(self): """Open the work order(s) linked to this receiving's sale order.""" self.ensure_one() if not self.sale_order_id: return False jobs = self.env['fp.job'].search([ ('sale_order_id', '=', self.sale_order_id.id), ]) action = { 'type': 'ir.actions.act_window', 'name': _('Work Orders'), 'res_model': 'fp.job', 'view_mode': 'list,form', 'domain': [('sale_order_id', '=', self.sale_order_id.id)], 'context': {'default_sale_order_id': self.sale_order_id.id}, } if len(jobs) == 1: action.update({'view_mode': 'form', 'res_id': jobs.id}) return action # ---- Sticker printing from the Receiving screen (2026-06-04) ---------- # Both stickers loop the SO's boxes (one label per box). Pass a SINGLE # work order: the box loop is sale-order-scoped, so feeding every job # would reprint each box label once per job. One job → exactly one label # per box. Falls back to a single 1/1 label when no boxes exist yet. def _fp_sticker_jobs(self): self.ensure_one() if not self.sale_order_id: return self.env['fp.job'] return self.env['fp.job'].sudo().search( [('sale_order_id', '=', self.sale_order_id.id)], order='id', limit=1) def _fp_print_sticker(self, xmlid): self.ensure_one() jobs = self._fp_sticker_jobs() if not jobs: raise UserError(_( 'No work order exists for this receiving yet — create the ' 'Work Order before printing stickers.')) return self.env.ref(xmlid).report_action(jobs) def action_print_external_sticker(self): """Customer (external) box sticker(s) for this receiving's WO.""" return self._fp_print_sticker( 'fusion_plating_jobs.action_report_fp_job_sticker') def action_print_internal_sticker(self): """Shop (internal) box sticker(s) — same layout, internal notes.""" return self._fp_print_sticker( 'fusion_plating_jobs.action_report_fp_job_sticker_internal')