From 7cbf4f25df5bdb2f5025565561e9f35335f331ce Mon Sep 17 00:00:00 2001 From: gsinghpal Date: Wed, 3 Jun 2026 22:23:42 -0400 Subject: [PATCH] feat(fusion_plating_certificates): add fp.certificate.part child model + ACL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds the fp.certificate.part model (one row per part on a combined CoC), the part_line_ids O2M on fp.certificate, and ACL rows for all three plating roles. No views yet — Task 2. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../models/__init__.py | 1 + .../models/fp_certificate.py | 4 ++ .../models/fp_certificate_part.py | 38 +++++++++++++++++++ .../security/ir.model.access.csv | 3 ++ 4 files changed, 46 insertions(+) create mode 100644 fusion_plating/fusion_plating_certificates/models/fp_certificate_part.py diff --git a/fusion_plating/fusion_plating_certificates/models/__init__.py b/fusion_plating/fusion_plating_certificates/models/__init__.py index 999c44d1..7b1d321f 100644 --- a/fusion_plating/fusion_plating_certificates/models/__init__.py +++ b/fusion_plating/fusion_plating_certificates/models/__init__.py @@ -5,6 +5,7 @@ from . import fp_thickness_reading from . import fp_certificate +from . import fp_certificate_part from . import res_config_settings from . import res_partner from . import fp_delivery diff --git a/fusion_plating/fusion_plating_certificates/models/fp_certificate.py b/fusion_plating/fusion_plating_certificates/models/fp_certificate.py index 4da83ead..c425d30c 100644 --- a/fusion_plating/fusion_plating_certificates/models/fp_certificate.py +++ b/fusion_plating/fusion_plating_certificates/models/fp_certificate.py @@ -87,6 +87,10 @@ class FpCertificate(models.Model): thickness_reading_ids = fields.One2many( 'fp.thickness.reading', 'certificate_id', string='Thickness Readings', ) + part_line_ids = fields.One2many( + 'fp.certificate.part', 'certificate_id', string='Parts', + help='One row per part covered by this certificate. Populated at ' + 'cert creation from the work order\'s sale-order lines.') # ----- Inline Fischerscope PDF upload (cert-local) ---------------------- # The merge pipeline normally pulls the Fischerscope/XDAL PDF from the diff --git a/fusion_plating/fusion_plating_certificates/models/fp_certificate_part.py b/fusion_plating/fusion_plating_certificates/models/fp_certificate_part.py new file mode 100644 index 00000000..aeb6266e --- /dev/null +++ b/fusion_plating/fusion_plating_certificates/models/fp_certificate_part.py @@ -0,0 +1,38 @@ +# -*- 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 fields, models + + +class FpCertificatePart(models.Model): + """One row per part on a combined Certificate of Conformance. + + A work order can cover several parts that share the same plating + process; the combined CoC lists each with its own identity, spec, + and quantities. Fields are snapshots taken at cert-creation time. + """ + _name = 'fp.certificate.part' + _description = 'Certificate Part Line' + _order = 'certificate_id, sequence, id' + _rec_name = 'part_number' + + certificate_id = fields.Many2one( + 'fp.certificate', string='Certificate', + required=True, ondelete='cascade', index=True,) + sequence = fields.Integer(default=10) + sale_order_line_id = fields.Many2one( + 'sale.order.line', string='Source SO Line', + help='The order line this part row was built from (traceability).',) + part_catalog_id = fields.Many2one('fp.part.catalog', string='Part') + part_number = fields.Char(string='Part Number') # snapshot + part_name = fields.Char(string='Part Name') # snapshot + description = fields.Char(string='Description') # customer-facing snapshot + serial = fields.Char(string='Serial Number(s)') # comma-joined snapshot + customer_spec_id = fields.Many2one( + 'fusion.plating.customer.spec', string='Customer Spec',) + spec_reference = fields.Char(string='Spec Reference') # snapshot 'CODE Rev X' + # Per-part; the parent fp.certificate keeps cert-level legacy totals. + quantity_shipped = fields.Integer(string='Qty Shipped') + nc_quantity = fields.Integer(string='NC Qty') diff --git a/fusion_plating/fusion_plating_certificates/security/ir.model.access.csv b/fusion_plating/fusion_plating_certificates/security/ir.model.access.csv index f2e0b841..af9bb085 100644 --- a/fusion_plating/fusion_plating_certificates/security/ir.model.access.csv +++ b/fusion_plating/fusion_plating_certificates/security/ir.model.access.csv @@ -11,3 +11,6 @@ access_fp_thickness_upload_wiz_sup,fp.thickness.upload.wiz.supervisor,model_fp_t access_fp_thickness_upload_wiz_mgr,fp.thickness.upload.wiz.manager,model_fp_thickness_upload_wizard,fusion_plating.group_fp_manager,1,1,1,1 access_fp_thickness_upload_wiz_line_sup,fp.thickness.upload.wiz.line.supervisor,model_fp_thickness_upload_wizard_line,fusion_plating.group_fp_shop_manager_v2,1,1,1,1 access_fp_thickness_upload_wiz_line_mgr,fp.thickness.upload.wiz.line.manager,model_fp_thickness_upload_wizard_line,fusion_plating.group_fp_manager,1,1,1,1 +access_fp_certificate_part_operator,fp.certificate.part.operator,model_fp_certificate_part,fusion_plating.group_fp_technician,1,1,0,0 +access_fp_certificate_part_supervisor,fp.certificate.part.supervisor,model_fp_certificate_part,fusion_plating.group_fp_shop_manager_v2,1,1,1,0 +access_fp_certificate_part_manager,fp.certificate.part.manager,model_fp_certificate_part,fusion_plating.group_fp_manager,1,1,1,1