diff --git a/fusion_plating/fusion_plating_configurator/__manifest__.py b/fusion_plating/fusion_plating_configurator/__manifest__.py
index 5b1adcac..36d5f6fc 100644
--- a/fusion_plating/fusion_plating_configurator/__manifest__.py
+++ b/fusion_plating/fusion_plating_configurator/__manifest__.py
@@ -39,8 +39,6 @@ Provides:
'security/ir.model.access.csv',
'data/fp_configurator_sequence_data.xml',
'data/fp_treatment_data.xml',
- 'wizard/fp_direct_order_wizard_views.xml',
- 'wizard/fp_part_catalog_import_wizard_views.xml',
'views/fp_treatment_views.xml',
'views/fp_part_catalog_views.xml',
'views/fp_coating_config_views.xml',
@@ -50,6 +48,10 @@ Provides:
'views/sale_order_views.xml',
'views/res_partner_views.xml',
'views/fp_configurator_menu.xml',
+ 'views/fp_sale_description_template_views.xml',
+ 'wizard/fp_direct_order_wizard_views.xml',
+ 'wizard/fp_part_catalog_import_wizard_views.xml',
+ 'data/fp_sale_description_template_data.xml',
],
'assets': {
'web.assets_backend': [
diff --git a/fusion_plating/fusion_plating_configurator/data/fp_sale_description_template_data.xml b/fusion_plating/fusion_plating_configurator/data/fp_sale_description_template_data.xml
new file mode 100644
index 00000000..12d68e89
--- /dev/null
+++ b/fusion_plating/fusion_plating_configurator/data/fp_sale_description_template_data.xml
@@ -0,0 +1,69 @@
+
+
+
+
+
+ ENP — Standard (AMS 2404 Class I)
+ standard
+ 10
+ Electroless nickel plating per AMS 2404, Class I, Type II (medium phosphorus, 6–9%). Plate to 0.0005" thickness, heat-treat 4 hours @ 375°F for hydrogen embrittlement relief. Parts to be cleaned, deoxidised and activated prior to plating. All threaded holes & tapped features to remain unplated.
+
+
+
+ ENP — Aerospace (AMS 2404 w/ CoC)
+ aerospace
+ 20
+ Electroless nickel plating per AMS 2404, Class I, Type II, Grade A. Plate to customer-specified thickness. Post-bake 4 hours @ 375°F min. Certificate of Conformance and thickness readings (3 points minimum per lot) required. Traceability to raw material heat lot. Nadcap-accredited process.
+
+
+
+ ENP — Nuclear (CSA N299 / 10CFR50 App B)
+ nuclear
+ 25
+ Electroless nickel plating under CSA N299 / 10CFR50 Appendix B quality program. Full material traceability, dedicated tooling, independent QA inspection. Certificate package includes thickness, adhesion tape test, visual inspection sign-off, and chemistry log for the processing shift.
+
+
+
+ Masking — Threaded & Tapped Features
+ masking
+ 30
+ Selective plating. Mask all threaded holes, tapped features and mating surfaces per customer drawing. Non-plated areas to be free of residue. Remove masking prior to shipment. Any masking residue is cause for rejection.
+
+
+
+ Masking — Selective O.D. / Journals
+ masking
+ 35
+ Plate O.D. and specified journal surfaces only. Mask all bore surfaces, end faces, and sealing surfaces. Maintain ±0.0001" on masked-feature edges. Rack holes to be plugged.
+
+
+
+ Rework — Strip & Replate
+ rework
+ 40
+ Rework of previously-plated parts. Chemically strip existing nickel deposit without attacking the base metal. Dimensional inspection after strip — any parts outside blueprint tolerance to be held for customer disposition. Replate to original spec. New Certificate of Conformance issued for the rework lot.
+
+
+
+ Packaging — Individual Bag + Desiccant
+ packaging
+ 50
+ Each part individually bagged in anti-static poly bag with desiccant pack. Bagged parts packed in cushioned cardboard cartons with corner protection. Outer carton labelled with part number, lot, quantity, and Entech W/O number. Do not ship open-top or mixed part-number cartons.
+
+
+
+ Handling — Delicate / No Tumble
+ other
+ 60
+ Delicate parts — rack plating only, no barrel. No tumbling or vibratory finishing before or after plating. Inspect for handling damage prior to final packaging. Any edge, surface or impact damage is cause for segregation.
+
+
+
diff --git a/fusion_plating/fusion_plating_configurator/models/__init__.py b/fusion_plating/fusion_plating_configurator/models/__init__.py
index 5f70112e..9ee574de 100644
--- a/fusion_plating/fusion_plating_configurator/models/__init__.py
+++ b/fusion_plating/fusion_plating_configurator/models/__init__.py
@@ -9,6 +9,7 @@ from . import fp_coating_config
from . import fp_pricing_complexity_surcharge
from . import fp_pricing_rule
from . import fp_customer_price_list
+from . import fp_sale_description_template
from . import fp_quote_configurator
from . import sale_order
from . import res_partner
diff --git a/fusion_plating/fusion_plating_configurator/models/fp_customer_price_list.py b/fusion_plating/fusion_plating_configurator/models/fp_customer_price_list.py
index a5214278..52c46b36 100644
--- a/fusion_plating/fusion_plating_configurator/models/fp_customer_price_list.py
+++ b/fusion_plating/fusion_plating_configurator/models/fp_customer_price_list.py
@@ -31,8 +31,9 @@ class FpCustomerPriceList(models.Model):
'fp.coating.config', string='Coating', required=True, ondelete='restrict',
tracking=True,
)
- unit_price = fields.Float(
- string='Unit Price', required=True, digits=(12, 4), tracking=True,
+ unit_price = fields.Monetary(
+ string='Unit Price', required=True, currency_field='currency_id',
+ tracking=True,
)
price_uom = fields.Selection(
[('per_part', 'per Part'),
diff --git a/fusion_plating/fusion_plating_configurator/models/fp_sale_description_template.py b/fusion_plating/fusion_plating_configurator/models/fp_sale_description_template.py
new file mode 100644
index 00000000..5fbbbe75
--- /dev/null
+++ b/fusion_plating/fusion_plating_configurator/models/fp_sale_description_template.py
@@ -0,0 +1,62 @@
+# -*- 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 FpSaleDescriptionTemplate(models.Model):
+ """Reusable boilerplate descriptions for sale.order.line items.
+
+ Plating shops run the same customer part over and over with small
+ variations (masking rules, special handling, packaging). Instead of
+ retyping — or half-remembering — the description every time, the
+ estimator picks a named template here, tweaks it, and the tweaked
+ text lands on the SO line as its description.
+ """
+ _name = 'fp.sale.description.template'
+ _description = 'Fusion Plating — Sale Order Line Description Template'
+ _order = 'sequence, name'
+
+ name = fields.Char(
+ string='Template Name', required=True,
+ help='Short name shown in the picker (e.g. "ENP — Standard Aluminium").',
+ )
+ description = fields.Text(
+ string='Description', required=True,
+ help='Boilerplate text. The user can tweak this in the wizard before '
+ 'it lands on the order line.',
+ )
+ sequence = fields.Integer(default=10)
+ coating_config_id = fields.Many2one(
+ 'fp.coating.config', string='Associated Coating',
+ ondelete='set null',
+ help='If set, this template is offered first when this coating is '
+ 'chosen on the order.',
+ )
+ partner_id = fields.Many2one(
+ 'res.partner', string='Customer (optional)',
+ ondelete='set null',
+ help='If set, restrict this template to a specific customer.',
+ )
+ tag = fields.Selection(
+ [('standard', 'Standard'),
+ ('masking', 'Masking / Selective'),
+ ('rework', 'Rework / Strip'),
+ ('aerospace', 'Aerospace'),
+ ('nuclear', 'Nuclear'),
+ ('packaging', 'Special Packaging'),
+ ('other', 'Other')],
+ string='Category', default='standard',
+ )
+ active = fields.Boolean(default=True)
+ usage_count = fields.Integer(
+ string='Used', default=0, readonly=True,
+ help='Bumped each time this template is applied on an order line.',
+ )
+
+ def _register_usage(self):
+ """Called by the wizard when the template is applied."""
+ for rec in self:
+ rec.usage_count = (rec.usage_count or 0) + 1
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 81a87923..083575dc 100644
--- a/fusion_plating/fusion_plating_configurator/security/ir.model.access.csv
+++ b/fusion_plating/fusion_plating_configurator/security/ir.model.access.csv
@@ -24,3 +24,6 @@ access_fp_part_import_wizard_manager,fp.part.catalog.import.wizard.manager,model
access_fp_customer_price_list_operator,fp.customer.price.list.operator,model_fp_customer_price_list,fusion_plating.group_fusion_plating_operator,1,0,0,0
access_fp_customer_price_list_estimator,fp.customer.price.list.estimator,model_fp_customer_price_list,fusion_plating_configurator.group_fp_estimator,1,1,1,0
access_fp_customer_price_list_manager,fp.customer.price.list.manager,model_fp_customer_price_list,fusion_plating.group_fusion_plating_manager,1,1,1,1
+access_fp_sale_desc_template_user,fp.sale.description.template.user,model_fp_sale_description_template,base.group_user,1,0,0,0
+access_fp_sale_desc_template_estimator,fp.sale.description.template.estimator,model_fp_sale_description_template,fusion_plating_configurator.group_fp_estimator,1,1,1,0
+access_fp_sale_desc_template_manager,fp.sale.description.template.manager,model_fp_sale_description_template,fusion_plating.group_fusion_plating_manager,1,1,1,1
diff --git a/fusion_plating/fusion_plating_configurator/views/fp_configurator_menu.xml b/fusion_plating/fusion_plating_configurator/views/fp_configurator_menu.xml
index f152afb2..9339e6d0 100644
--- a/fusion_plating/fusion_plating_configurator/views/fp_configurator_menu.xml
+++ b/fusion_plating/fusion_plating_configurator/views/fp_configurator_menu.xml
@@ -22,17 +22,24 @@
sequence="5"
groups="group_fp_estimator,fusion_plating.group_fusion_plating_supervisor"/>
-
@@ -54,7 +57,11 @@
-
+
+
+
@@ -65,15 +72,35 @@
-
-
+
+ %
+
+
+