diff --git a/fusion-plating/fusion_plating_configurator/models/__init__.py b/fusion-plating/fusion_plating_configurator/models/__init__.py index 9f0c08b4..1942b876 100644 --- a/fusion-plating/fusion_plating_configurator/models/__init__.py +++ b/fusion-plating/fusion_plating_configurator/models/__init__.py @@ -4,3 +4,5 @@ # Part of the Fusion Plating product family. from . import fp_treatment +from . import fp_part_catalog +from . import fp_coating_config diff --git a/fusion-plating/fusion_plating_configurator/models/fp_part_catalog.py b/fusion-plating/fusion_plating_configurator/models/fp_part_catalog.py new file mode 100644 index 00000000..ec62df29 --- /dev/null +++ b/fusion-plating/fusion_plating_configurator/models/fp_part_catalog.py @@ -0,0 +1,65 @@ +# -*- 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 FpPartCatalog(models.Model): + """Customer part library. + + Stores geometry, material, and complexity data for parts that + customers send repeatedly. New orders reference existing catalog + entries for instant re-quoting; one-off parts create new entries. + """ + _name = 'fp.part.catalog' + _description = 'Fusion Plating — Part Catalog' + _inherit = ['mail.thread', 'mail.activity.mixin'] + _order = 'partner_id, part_number, name' + + name = fields.Char(string='Part Name', required=True, tracking=True) + partner_id = fields.Many2one( + 'res.partner', string='Customer', required=True, ondelete='cascade', + tracking=True, domain="[('customer_rank', '>', 0)]", + ) + part_number = fields.Char(string='Part Number', tracking=True, help="Customer's part number (e.g. VS-R392007E01).") + revision = fields.Char(string='Revision', help='Revision letter or number (e.g. Rev: 1B).') + substrate_material = fields.Selection( + [('aluminium', 'Aluminium'), ('steel', 'Steel'), ('stainless', 'Stainless Steel'), + ('copper', 'Copper'), ('titanium', 'Titanium'), ('other', 'Other')], + string='Substrate Material', default='steel', + ) + geometry_source = fields.Selection( + [('3d_model', '3D Model'), ('manual', 'Manual Measurements'), ('pdf_drawing', 'PDF Drawing')], + string='Geometry Source', default='manual', + ) + model_attachment_id = fields.Many2one('ir.attachment', string='3D Model File', help='STEP, STL, or IGES file.') + drawing_attachment_ids = fields.Many2many( + 'ir.attachment', 'fp_part_catalog_drawing_rel', 'part_catalog_id', 'attachment_id', string='PDF Drawings', + ) + surface_area = fields.Float(string='Surface Area', digits=(12, 4)) + surface_area_uom = fields.Selection( + [('sq_in', 'sq in'), ('sq_ft', 'sq ft'), ('sq_cm', 'sq cm'), ('sq_m', 'sq m')], + string='Surface Area UoM', default='sq_in', + ) + weight = fields.Float(string='Weight (kg)', digits=(12, 4)) + dimensions_length = fields.Float(string='Length', digits=(12, 4)) + dimensions_width = fields.Float(string='Width', digits=(12, 4)) + dimensions_height = fields.Float(string='Height', digits=(12, 4)) + complexity = fields.Selection( + [('simple', 'Simple'), ('moderate', 'Moderate'), ('complex', 'Complex'), ('very_complex', 'Very Complex')], + string='Complexity', default='simple', + ) + masking_zones = fields.Integer(string='Masking Zones', help='Number of areas requiring masking.') + masking_description = fields.Text(string='Masking Description', help='e.g. "Mask threaded holes, mask bore ID"') + has_blind_holes = fields.Boolean(string='Has Blind Holes') + has_recesses = fields.Boolean(string='Has Recesses') + has_threads = fields.Boolean(string='Has Threads') + notes = fields.Html(string='Notes') + active = fields.Boolean(string='Active', default=True) + + _sql_constraints = [ + ('fp_part_catalog_partner_partnum_uniq', 'unique(partner_id, part_number)', + 'Part number must be unique per customer.'), + ] diff --git a/fusion-plating/fusion_plating_configurator/security/ir.model.access.csv b/fusion-plating/fusion_plating_configurator/security/ir.model.access.csv index 5a71a42f..a7c63563 100644 --- a/fusion-plating/fusion_plating_configurator/security/ir.model.access.csv +++ b/fusion-plating/fusion_plating_configurator/security/ir.model.access.csv @@ -2,3 +2,9 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_fp_treatment_operator,fp.treatment.operator,model_fp_treatment,fusion_plating.group_fusion_plating_operator,1,0,0,0 access_fp_treatment_supervisor,fp.treatment.supervisor,model_fp_treatment,fusion_plating.group_fusion_plating_supervisor,1,1,0,0 access_fp_treatment_manager,fp.treatment.manager,model_fp_treatment,fusion_plating.group_fusion_plating_manager,1,1,1,1 +access_fp_part_catalog_operator,fp.part.catalog.operator,model_fp_part_catalog,fusion_plating.group_fusion_plating_operator,1,0,0,0 +access_fp_part_catalog_estimator,fp.part.catalog.estimator,model_fp_part_catalog,fusion_plating_configurator.group_fp_estimator,1,1,1,0 +access_fp_part_catalog_manager,fp.part.catalog.manager,model_fp_part_catalog,fusion_plating.group_fusion_plating_manager,1,1,1,1 +access_fp_coating_config_operator,fp.coating.config.operator,model_fp_coating_config,fusion_plating.group_fusion_plating_operator,1,0,0,0 +access_fp_coating_config_estimator,fp.coating.config.estimator,model_fp_coating_config,fusion_plating_configurator.group_fp_estimator,1,1,1,0 +access_fp_coating_config_manager,fp.coating.config.manager,model_fp_coating_config,fusion_plating.group_fusion_plating_manager,1,1,1,1 diff --git a/fusion-plating/fusion_plating_configurator/views/fp_part_catalog_views.xml b/fusion-plating/fusion_plating_configurator/views/fp_part_catalog_views.xml index 85d8c23e..80ac6e2a 100644 --- a/fusion-plating/fusion_plating_configurator/views/fp_part_catalog_views.xml +++ b/fusion-plating/fusion_plating_configurator/views/fp_part_catalog_views.xml @@ -1,2 +1,141 @@ - + + + + + + fp.part.catalog.list + fp.part.catalog + + + + + + + + + + + + + + + + fp.part.catalog.form + fp.part.catalog + +
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+
+
+
+ + + + fp.part.catalog.search + fp.part.catalog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Part Catalog + fp.part.catalog + list,form + + +

+ No parts in the catalog yet +

+

+ Add customer parts with geometry, material, and complexity data + for instant re-quoting on repeat orders. +

+
+
+ +