folder rename

This commit is contained in:
gsinghpal
2026-04-16 20:53:53 -04:00
parent 3f3ddcbab4
commit 7c7ef06057
634 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,64 @@
# Fusion Plating — Nuclear (CSA N299, NQA-1)
Part of the Fusion Plating product family by Nexa Systems Inc.
Nuclear industry pack for plating and metal finishing shops that supply
the Canadian and US nuclear sectors. Layers on top of
`fusion_plating_quality`.
## What's in the box
- **CSA N299 level catalog** — Levels 1 through 4, safety classification,
default records retention (40 / 25 / 15 / 7 years).
- **Nuclear Quality Programs** — per facility, with N299 level, NQA-1
applicability, CNSC supplier status and audit dates.
- **Inspection and Test Plans (ITP)** — hold points, witness points, test
methods, acceptance criteria, customer review workflow.
- **10 CFR Part 21 reports** — 60-day evaluation clock, reportability
determination, customer notification and closure.
- **Nuclear Pedigree Records** — full traceability from raw material heat
number through chemistry, process steps, test results, ship date, and
computed retention-until date.
- **CNSC Licence tracking** — Class II nuclear facility, transport and
export licences with expiry monitoring.
- **Customer spec extension** — nuclear flag, N299 level, NQA-1 flag,
nuclear customer type (OPG, Bruce Power, AECL, Cameco, Candu Energy,
US utility).
- **NCR extension** — nuclear flag and 10 CFR Part 21 evaluation hook.
- **res.company extension** — default nuclear records retention.
## Background
- **CSA N299** — Canadian quality assurance program requirements for
items and services supplied to nuclear power plants. Four levels:
Level 1 (safety-critical) through Level 4 (commercial grade).
- **NQA-1** — US nuclear quality assurance for US facilities.
- **CNSC** — Canadian Nuclear Safety Commission, federal regulator.
- **10 CFR Part 21** — US regulation requiring reporting of defects and
noncompliance that could create a substantial safety hazard.
- **ITP** — Inspection and Test Plan.
- **Nuclear pedigree** — full traceability from raw material to
installed component.
## Canadian nuclear customers (seeded templates)
- **OPG** — Ontario Power Generation (Pickering, Darlington)
- **Bruce Power** — Bruce A and Bruce B
- **AECL / CNL** — Atomic Energy of Canada / Canadian Nuclear
Laboratories (Chalk River)
- **Candu Energy** — SNC-Lavalin Candu Energy (Candu reactor OEM)
## Dependencies
- `fusion_plating_quality`
## Install
1. Drop the module into your Odoo addons path.
2. Update the apps list.
3. Install **Fusion Plating — Nuclear**.
4. Go to **Plating → Nuclear** to start configuring programs and ITPs.
## License
OPL-1 (Odoo Proprietary License v1.0). Copyright 2026 Nexa Systems Inc.

View File

@@ -0,0 +1,6 @@
# -*- coding: utf-8 -*-
# Copyright 2026 Nexa Systems Inc.
# License OPL-1 (Odoo Proprietary License v1.0)
# Part of the Fusion Plating product family.
from . import models

View File

@@ -0,0 +1,108 @@
# -*- coding: utf-8 -*-
# Copyright 2026 Nexa Systems Inc.
# License OPL-1 (Odoo Proprietary License v1.0)
# Part of the Fusion Plating product family.
{
'name': 'Fusion Plating — Nuclear (CSA N299, NQA-1)',
'version': '19.0.1.0.0',
'category': 'Manufacturing/Plating',
'summary': 'Nuclear industry pack: CSA N299 Levels 1-4, NQA-1 awareness, '
'CNSC licence tracking, 10 CFR Part 21 reporting, ITPs, '
'nuclear pedigree traceability, extended retention.',
'description': """
Fusion Plating — Nuclear (CSA N299, NQA-1)
===========================================
Part of the Fusion Plating product family by Nexa Systems Inc.
This industry pack layers nuclear-specific records, workflows and seed
data on top of the Fusion Plating quality module (QMS). It is the
baseline every CSA N299 or 10 CFR Part 21 obligated plating / metal
finishing supplier needs on top of the generic QMS.
Records added
-------------
* CSA N299 Level catalog — Levels 1 through 4 with safety classification
and default records-retention periods (40 / 25 / 15 / 7 years).
* Nuclear Quality Program per facility — tracks N299 level, NQA-1
applicability, CNSC supplier status, last/next audit dates.
* Inspection and Test Plans (ITP) — hold points, witness points, test
methods, acceptance criteria, customer review and approval workflow.
* 10 CFR Part 21 defect evaluation and reporting — 60-day evaluation
clock, reportability determination, customer notification.
* Nuclear Pedigree Records — full traceability from raw material heat
number through chemistry cert, process trail, test results, ship
date, and retention-until date (driven by N299 level).
* CNSC Licence tracking — Class II nuclear facility, transport, export
licences with expiry monitoring.
* Customer Specification extension — nuclear flag, N299 level, NQA-1
flag, nuclear customer type (OPG, Bruce Power, AECL, CNL, Candu
Energy, US utility).
* NCR extension — nuclear job flag and 10 CFR Part 21 evaluation link
so any non-conformance on a nuclear job is captured for reportability.
* res.company extension — default nuclear records retention (40 years
out of the box, configurable per company).
Seed data
---------
* CSA N299 Levels 1 through 4 with real retention periods
* Template customer-spec entries for the major Canadian nuclear
operators: OPG, Bruce Power, AECL/CNL, Candu Energy
Background
----------
CSA N299 is the Canadian Standards Association standard for quality
assurance program requirements for the supply of items and services
for nuclear power plants. It has four levels, with Level 1 being the
most stringent (safety-critical). NQA-1 is the US equivalent for
nuclear facilities in the United States. The CNSC (Canadian Nuclear
Safety Commission) is the federal regulator. 10 CFR Part 21 is the US
regulation requiring reporting of defects and noncompliance that could
create a substantial safety hazard in a nuclear facility.
Dependencies
------------
Depends on fusion_plating_quality, which brings in the core NCR,
customer spec, and facility records this pack extends.
Copyright (c) 2026 Nexa Systems Inc. All rights reserved.
""",
'author': 'Nexa Systems Inc.',
'website': 'https://www.nexasystems.ca',
'maintainer': 'Nexa Systems Inc.',
'support': 'support@nexasystems.ca',
'license': 'OPL-1',
'price': 0.00,
'currency': 'CAD',
'depends': [
'fusion_plating_quality',
],
'data': [
'security/fp_nuclear_security.xml',
'security/ir.model.access.csv',
'data/fp_sequence_data.xml',
'data/fp_n299_level_data.xml',
'data/fp_nuclear_customer_data.xml',
'views/fp_n299_level_views.xml',
'views/fp_nuclear_program_views.xml',
'views/fp_nuclear_itp_views.xml',
'views/fp_10cfr21_report_views.xml',
'views/fp_nuclear_pedigree_views.xml',
'views/fp_cnsc_licence_views.xml',
'views/fp_customer_spec_views.xml',
'views/fp_ncr_views.xml',
'views/fp_menu.xml',
],
'demo': [
'data/fp_demo_nuclear_data.xml',
],
'assets': {
'web.assets_backend': [
'fusion_plating_nuclear/static/src/scss/fusion_plating_nuclear.scss',
],
},
'installable': True,
'application': False,
'auto_install': False,
}

View File

@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2026 Nexa Systems Inc. — DEMO DATA (temporary)
Remove this file and its manifest entry before production release.
-->
<odoo noupdate="1">
<!-- ========== NUCLEAR QUALITY PROGRAM ========== -->
<record id="demo_nuclear_program" model="fusion.plating.nuclear.program">
<field name="name">Fusion Plating Main — CSA N299 Level 1 Program</field>
<field name="facility_id" ref="fusion_plating.demo_facility_main"/>
<field name="n299_level_id" ref="fusion_plating_nuclear.n299_l1"/>
<field name="nqa1_applicable" eval="True"/>
<field name="cnsc_licensed_supplier" eval="True"/>
<field name="program_manual_rev">Rev D — 2025-09-15</field>
<field name="last_audit_date" eval="(DateTime.today() - timedelta(days=120)).strftime('%Y-%m-%d')"/>
<field name="next_audit_date" eval="(DateTime.today() + timedelta(days=245)).strftime('%Y-%m-%d')"/>
<field name="state">active</field>
<field name="notes" type="html"><p>Primary nuclear quality program covering OPG and Bruce Power plating work. NQA-1 awareness maintained for potential US utility contracts. Last customer audit by OPG — zero findings.</p></field>
</record>
<!-- ========== NUCLEAR ITPs ========== -->
<record id="demo_nuclear_itp_001" model="fusion.plating.nuclear.itp">
<field name="name">ITP-NUC-2026-001</field>
<field name="customer_id" ref="fusion_plating.demo_partner_aeroparts"/>
<field name="part_number">P/N 9920-A</field>
<field name="drawing_ref">DWG-NUC-9920-A Rev 3</field>
<field name="n299_level_id" ref="fusion_plating_nuclear.n299_l1"/>
<field name="state">approved</field>
<field name="customer_approval_date" eval="(DateTime.today() - timedelta(days=45)).strftime('%Y-%m-%d')"/>
<field name="hold_points" type="html"><p><strong>HP-1:</strong> Pre-plate dimensional verification — customer witness required.<br/><strong>HP-2:</strong> Post-plate thickness measurement — customer hold point, work stops until released.<br/><strong>WP-1:</strong> Bath chemistry verification — customer may witness.</p></field>
<field name="test_methods" type="html"><p>Thickness: XRF per ASTM B568. Adhesion: bend test per ASTM B571. Porosity: ferroxyl test per ASTM B733. Hardness: microhardness per ASTM E384.</p></field>
<field name="acceptance_criteria" type="html"><p>EN deposit 0.0010" +/- 0.0002". Hardness 48-52 HRC after heat treat. Zero porosity on ferroxyl. 100% adhesion on bend test.</p></field>
</record>
<record id="demo_nuclear_itp_002" model="fusion.plating.nuclear.itp">
<field name="name">ITP-NUC-2026-002</field>
<field name="customer_id" ref="fusion_plating.demo_partner_aeroparts"/>
<field name="part_number">P/N 8815-B</field>
<field name="drawing_ref">DWG-NUC-8815-B Rev 1</field>
<field name="n299_level_id" ref="fusion_plating_nuclear.n299_l2"/>
<field name="state">draft</field>
<field name="hold_points" type="html"><p><strong>HP-1:</strong> Pre-plate surface preparation verification.<br/><strong>RP-1:</strong> Post-plate records review by customer QA.</p></field>
<field name="test_methods" type="html"><p>Thickness: magnetic gauge per ASTM B499. Adhesion: tape test per ASTM D3359.</p></field>
</record>
<!-- ========== NUCLEAR PEDIGREE ========== -->
<record id="demo_nuclear_pedigree_001" model="fusion.plating.nuclear.pedigree">
<field name="name">NUC-PED-2026-001</field>
<field name="part_number">P/N 9920-A</field>
<field name="lot_serial">LOT-NUC-44219</field>
<field name="customer_id" ref="fusion_plating.demo_partner_aeroparts"/>
<field name="n299_level_id" ref="fusion_plating_nuclear.n299_l1"/>
<field name="raw_material_cert_refs">CMTR-8821, CMTR-8822</field>
<field name="raw_material_heat_no">HT-20250712-A</field>
<field name="chemistry_cert_refs">CHEM-2026-0091, CHEM-2026-0092</field>
<field name="ship_date" eval="(DateTime.today() - timedelta(days=10)).strftime('%Y-%m-%d')"/>
<field name="locked" eval="True"/>
<field name="test_results" type="html"><p>Thickness: 0.0011" (spec 0.0010" +/- 0.0002") — PASS.<br/>Hardness: 50 HRC (spec 48-52 HRC) — PASS.<br/>Adhesion: No separation on bend test — PASS.<br/>Porosity: No indication on ferroxyl — PASS.</p></field>
</record>
</odoo>

View File

@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2026 Nexa Systems Inc.
License OPL-1 (Odoo Proprietary License v1.0)
Part of the Fusion Plating product family.
Seed data for the four CSA N299 quality levels. Retention values
reflect typical Canadian nuclear practice:
Level 1 — 40 years (safety-critical, often life-of-plant)
Level 2 — 25 years (safety-related)
Level 3 — 15 years (important to safety)
Level 4 — 7 years (commercial grade)
-->
<odoo noupdate="1">
<record id="n299_l1" model="fusion.plating.n299.level">
<field name="name">CSA N299 Level 1 — Safety-critical</field>
<field name="code">N299_L1</field>
<field name="level_number">1</field>
<field name="retention_years">40</field>
<field name="safety_classification">safety_critical</field>
<field name="description">Highest level of the CSA N299 quality assurance program. Applies to safety-critical items whose failure could directly affect nuclear safety. Requires the most rigorous supplier QA program, traceability, and records retention (typically life-of-plant, 40 years or more).</field>
</record>
<record id="n299_l2" model="fusion.plating.n299.level">
<field name="name">CSA N299 Level 2 — Safety-related</field>
<field name="code">N299_L2</field>
<field name="level_number">2</field>
<field name="retention_years">25</field>
<field name="safety_classification">safety_related</field>
<field name="description">Applies to safety-related items that support safety-critical functions. Requires a documented QA program aligned to CSA N299.2, full traceability, and long-term records retention.</field>
</record>
<record id="n299_l3" model="fusion.plating.n299.level">
<field name="name">CSA N299 Level 3 — Important to safety</field>
<field name="code">N299_L3</field>
<field name="level_number">3</field>
<field name="retention_years">15</field>
<field name="safety_classification">important_to_safety</field>
<field name="description">Applies to items important to safety but not themselves safety-critical or safety-related. Requires a documented QA program aligned to CSA N299.3 with moderate records retention.</field>
</record>
<record id="n299_l4" model="fusion.plating.n299.level">
<field name="name">CSA N299 Level 4 — Commercial grade</field>
<field name="code">N299_L4</field>
<field name="level_number">4</field>
<field name="retention_years">7</field>
<field name="safety_classification">commercial_grade</field>
<field name="description">Lowest level of the CSA N299 program. Applies to commercial grade items procured for nuclear use without safety implications. Standard commercial QA records retention applies.</field>
</record>
</odoo>

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2026 Nexa Systems Inc.
License OPL-1 (Odoo Proprietary License v1.0)
Part of the Fusion Plating product family.
Template customer-spec entries for the major Canadian nuclear
operators. Shops can duplicate these to create their own
customer-specific specification records and attach the controlled
documents via the document_url field.
-->
<odoo noupdate="1">
<record id="spec_opg_sqap" model="fusion.plating.customer.spec">
<field name="code">OPG-SQAP</field>
<field name="name">OPG Supplier Quality Assurance Program</field>
<field name="spec_type">customer</field>
<field name="x_fc_is_nuclear">True</field>
<field name="x_fc_nuclear_customer_type">opg</field>
</record>
<record id="spec_bruce_n299" model="fusion.plating.customer.spec">
<field name="code">BRUCE-N299</field>
<field name="name">Bruce Power N299 Supplier Requirements</field>
<field name="spec_type">customer</field>
<field name="x_fc_is_nuclear">True</field>
<field name="x_fc_nuclear_customer_type">bruce_power</field>
</record>
<record id="spec_aecl_n299" model="fusion.plating.customer.spec">
<field name="code">AECL-N299</field>
<field name="name">AECL / CNL N299 Procurement Requirements</field>
<field name="spec_type">customer</field>
<field name="x_fc_is_nuclear">True</field>
<field name="x_fc_nuclear_customer_type">aecl</field>
</record>
<record id="spec_candu_n299" model="fusion.plating.customer.spec">
<field name="code">CANDU-N299</field>
<field name="name">Candu Energy N299 Procurement Requirements</field>
<field name="spec_type">customer</field>
<field name="x_fc_is_nuclear">True</field>
<field name="x_fc_nuclear_customer_type">candu_energy</field>
</record>
</odoo>

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2026 Nexa Systems Inc.
License OPL-1 (Odoo Proprietary License v1.0)
Part of the Fusion Plating product family.
-->
<odoo noupdate="1">
<record id="seq_fp_nuclear_itp" model="ir.sequence">
<field name="name">Fusion Plating: Nuclear ITP</field>
<field name="code">fusion.plating.nuclear.itp</field>
<field name="prefix">ITP/%(year)s/</field>
<field name="padding">3</field>
<field name="company_id" eval="False"/>
</record>
<record id="seq_fp_10cfr21_report" model="ir.sequence">
<field name="name">Fusion Plating: 10 CFR 21 Report</field>
<field name="code">fusion.plating.10cfr21.report</field>
<field name="prefix">10CFR21/%(year)s/</field>
<field name="padding">3</field>
<field name="company_id" eval="False"/>
</record>
</odoo>

View File

@@ -0,0 +1,14 @@
# -*- coding: utf-8 -*-
# Copyright 2026 Nexa Systems Inc.
# License OPL-1 (Odoo Proprietary License v1.0)
# Part of the Fusion Plating product family.
from . import fp_n299_level
from . import fp_nuclear_program
from . import fp_nuclear_itp
from . import fp_10cfr21_report
from . import fp_nuclear_pedigree
from . import fp_cnsc_licence
from . import fp_customer_spec
from . import fp_ncr
from . import res_company

View File

@@ -0,0 +1,166 @@
# -*- 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 Fp10CFR21Report(models.Model):
"""10 CFR Part 21 — Reporting of Defects and Noncompliance.
10 CFR Part 21 is the US Nuclear Regulatory Commission regulation
that requires suppliers of basic components to nuclear facilities
to evaluate potential defects and noncompliances, and to report
reportable ones to the NRC within 60 days of discovery.
The typical workflow is:
1. discovery — something is observed that might be a defect
2. evaluation — determine whether it rises to the level of a
"substantial safety hazard" (reportable)
3. reportable — yes, it's reportable → file with NRC
or
not_reportable — evaluation closes with a documented basis
4. reported — notice filed with NRC and affected customers
5. closed — corrective action verified, record sealed
The record has a due date that is 60 days after discovery, driven by
the `days_since_discovery` computed field.
"""
_name = 'fusion.plating.10cfr21.report'
_description = 'Fusion Plating — 10 CFR Part 21 Defect Report'
_inherit = ['mail.thread', 'mail.activity.mixin']
_order = 'discovery_date desc, id desc'
name = fields.Char(
string='Reference',
required=True,
copy=False,
readonly=True,
default=lambda self: self._default_name(),
tracking=True,
)
discovery_date = fields.Date(
string='Discovery Date',
required=True,
default=lambda self: fields.Date.context_today(self),
tracking=True,
)
report_date = fields.Date(
string='Report Date',
tracking=True,
help='Date the notification was filed. 10 CFR 21 requires reporting '
'within 60 days of discovery for reportable defects.',
)
days_since_discovery = fields.Integer(
string='Days Since Discovery',
compute='_compute_days_since_discovery',
search='_search_days_since_discovery',
)
part_description = fields.Html(
string='Part / Component',
)
defect_description = fields.Html(
string='Defect Description',
)
customer_ids = fields.Many2many(
'res.partner',
'fp_10cfr21_customer_rel',
'report_id',
'partner_id',
string='Affected Customers',
)
ncr_id = fields.Many2one(
'fusion.plating.ncr',
string='Source NCR',
help='The non-conformance report that triggered the 10 CFR 21 '
'evaluation.',
)
reportable = fields.Boolean(
string='Reportable',
tracking=True,
help='Set after evaluation. True means the defect rises to the '
'level of a substantial safety hazard and must be reported.',
)
corrective_action = fields.Html(
string='Corrective Action',
)
state = fields.Selection(
[
('discovery', 'Discovery'),
('evaluation', 'Evaluation'),
('reportable', 'Reportable'),
('reported', 'Reported'),
('not_reportable', 'Not Reportable'),
('closed', 'Closed'),
],
string='Status',
default='discovery',
required=True,
tracking=True,
)
company_id = fields.Many2one(
'res.company',
string='Company',
default=lambda self: self.env.company,
)
active = fields.Boolean(default=True)
@api.model
def _default_name(self):
seq = self.env['ir.sequence'].next_by_code(
'fusion.plating.10cfr21.report'
)
return seq or '/'
@api.model_create_multi
def create(self, vals_list):
for vals in vals_list:
if not vals.get('name') or vals.get('name') == '/':
vals['name'] = self._default_name()
return super().create(vals_list)
@api.depends('discovery_date')
def _compute_days_since_discovery(self):
today = fields.Date.context_today(self)
for rec in self:
if rec.discovery_date:
rec.days_since_discovery = (today - rec.discovery_date).days
else:
rec.days_since_discovery = 0
def _search_days_since_discovery(self, operator, value):
today = fields.Date.context_today(self)
from datetime import timedelta
target = today - timedelta(days=value)
if operator in ('>=', '>'):
date_op = '<=' if operator == '>=' else '<'
return [('discovery_date', date_op, target)]
if operator in ('<=', '<'):
date_op = '>=' if operator == '<=' else '>'
return [('discovery_date', date_op, target)]
if operator == '=':
return [('discovery_date', '=', target)]
return [('discovery_date', '!=', target)]
def action_start_evaluation(self):
self.write({'state': 'evaluation'})
def action_mark_reportable(self):
self.write({'state': 'reportable', 'reportable': True})
def action_mark_not_reportable(self):
self.write({'state': 'not_reportable', 'reportable': False})
def action_file_report(self):
self.write({
'state': 'reported',
'report_date': fields.Date.context_today(self),
})
def action_close(self):
self.write({'state': 'closed'})
def action_reset_to_discovery(self):
self.write({'state': 'discovery'})

View File

@@ -0,0 +1,99 @@
# -*- 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 FpCnscLicence(models.Model):
"""CNSC Licence record.
The Canadian Nuclear Safety Commission (CNSC) regulates all nuclear
activities in Canada. A plating / finishing supplier that works on
nuclear items may hold — or be listed under — one or more CNSC
licences:
* Class II nuclear facility licence (on-site sources,
irradiators, handling of nuclear substances)
* Transport licence for nuclear substances
* Export licence for controlled nuclear items
This record tracks the licence number, issue and expiry dates, and
any key conditions so the facility can manage renewals and
compliance awareness.
"""
_name = 'fusion.plating.cnsc.licence'
_description = 'Fusion Plating — CNSC Licence'
_inherit = ['mail.thread', 'mail.activity.mixin']
_order = 'expiry_date, name'
name = fields.Char(
string='Title',
required=True,
tracking=True,
)
licence_number = fields.Char(
string='Licence Number',
required=True,
tracking=True,
)
facility_id = fields.Many2one(
'fusion.plating.facility',
string='Facility',
tracking=True,
)
company_id = fields.Many2one(
'res.company',
related='facility_id.company_id',
store=True,
readonly=True,
)
licence_type = fields.Selection(
[
('class_ii_nuclear_facility', 'Class II Nuclear Facility'),
('transport', 'Transport of Nuclear Substances'),
('export', 'Export of Controlled Nuclear Items'),
('other', 'Other'),
],
string='Licence Type',
default='class_ii_nuclear_facility',
required=True,
tracking=True,
)
issue_date = fields.Date(
string='Issue Date',
tracking=True,
)
expiry_date = fields.Date(
string='Expiry Date',
tracking=True,
)
conditions = fields.Html(
string='Licence Conditions',
)
state = fields.Selection(
[
('active', 'Active'),
('expiring', 'Expiring Soon'),
('expired', 'Expired'),
('revoked', 'Revoked'),
],
string='Status',
default='active',
required=True,
tracking=True,
)
attachment_id = fields.Many2one(
'ir.attachment',
string='Licence Document',
)
active = fields.Boolean(default=True)
_sql_constraints = [
(
'fp_cnsc_licence_number_uniq',
'unique(licence_number, company_id)',
'CNSC licence number must be unique per company.',
),
]

View File

@@ -0,0 +1,52 @@
# -*- 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 FpCustomerSpec(models.Model):
"""Extend the quality customer-spec library with nuclear flags.
When a customer spec is flagged `x_fc_is_nuclear`, the system will
surface the N299 level, NQA-1 applicability and nuclear customer
type so that jobs referencing the spec can inherit the correct
retention and traceability rules.
"""
_inherit = 'fusion.plating.customer.spec'
x_fc_is_nuclear = fields.Boolean(
string='Nuclear Spec',
tracking=True,
help='Tick when this specification applies to nuclear work.',
)
x_fc_n299_level_id = fields.Many2one(
'fusion.plating.n299.level',
string='CSA N299 Level',
tracking=True,
)
x_fc_nqa1_applicable = fields.Boolean(
string='NQA-1 Applicable',
tracking=True,
help='Tick when this specification covers work subject to ASME NQA-1.',
)
x_fc_extended_retention_years = fields.Integer(
string='Extended Retention (Years)',
help='Override the default document-retention period for records '
'tied to this specification. Leave 0 to inherit the N299 level '
'default or the company default.',
)
x_fc_nuclear_customer_type = fields.Selection(
[
('opg', 'OPG — Ontario Power Generation'),
('bruce_power', 'Bruce Power'),
('aecl', 'AECL / CNL'),
('cameco', 'Cameco'),
('candu_energy', 'Candu Energy'),
('us_utility', 'US Nuclear Utility'),
('other', 'Other'),
],
string='Nuclear Customer Type',
tracking=True,
)

View File

@@ -0,0 +1,81 @@
# -*- 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 FpN299Level(models.Model):
"""CSA N299 Quality Assurance Level.
CSA N299 is the Canadian Standards Association standard covering
quality assurance program requirements for items and services
supplied to nuclear power plants. It defines four levels of quality
programs keyed to the safety classification of the supplied item:
Level 1 — Safety-critical items (highest)
Level 2 — Safety-related items
Level 3 — Items important to safety
Level 4 — Commercial grade (lowest)
The level drives how long nuclear quality records must be retained
(life-of-plant on the highest levels, commercial norms on the lowest)
and how rigorous the supplier's quality program must be.
"""
_name = 'fusion.plating.n299.level'
_description = 'Fusion Plating — CSA N299 Quality Level'
_order = 'level_number, code'
name = fields.Char(
string='Level',
required=True,
translate=True,
)
code = fields.Char(
string='Code',
required=True,
help='Short identifier, e.g. N299_L1.',
)
level_number = fields.Integer(
string='Level Number',
required=True,
help='1 (highest, safety-critical) to 4 (commercial grade).',
)
description = fields.Text(
string='Description',
translate=True,
)
retention_years = fields.Integer(
string='Retention (Years)',
required=True,
default=40,
help='Default records-retention period for this level. Canadian nuclear '
'quality records are typically retained for 40 years or longer at '
'the highest levels — often "life of plant".',
)
safety_classification = fields.Selection(
[
('safety_critical', 'Safety-critical'),
('safety_related', 'Safety-related'),
('important_to_safety', 'Important to safety'),
('commercial_grade', 'Commercial grade'),
],
string='Safety Classification',
required=True,
default='safety_critical',
)
active = fields.Boolean(default=True)
_sql_constraints = [
(
'fp_n299_level_code_uniq',
'unique(code)',
'N299 level code must be unique.',
),
(
'fp_n299_level_number_uniq',
'unique(level_number)',
'N299 level number must be unique.',
),
]

View File

@@ -0,0 +1,61 @@
# -*- 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 FpNcr(models.Model):
"""Extend the quality NCR with nuclear flags and 10 CFR 21 hook.
When an NCR is opened against a nuclear job, quality needs to
decide within the 10 CFR Part 21 evaluation clock whether the
non-conformance rises to the level of a substantial safety hazard.
The `x_fc_cfr21_report_id` link lets an NCR spawn a 10 CFR 21
record and track the outcome without duplicating the narrative.
"""
_inherit = 'fusion.plating.ncr'
x_fc_is_nuclear = fields.Boolean(
string='Nuclear Job',
tracking=True,
help='Tick when the non-conformance occurred on a nuclear job. '
'This flags the NCR for 10 CFR Part 21 evaluation.',
)
x_fc_n299_level_id = fields.Many2one(
'fusion.plating.n299.level',
string='CSA N299 Level',
tracking=True,
)
x_fc_cfr21_evaluated = fields.Boolean(
string='10 CFR 21 Evaluated',
tracking=True,
)
x_fc_cfr21_report_id = fields.Many2one(
'fusion.plating.10cfr21.report',
string='10 CFR 21 Report',
tracking=True,
)
def action_open_cfr21_report(self):
"""Create or open the linked 10 CFR Part 21 evaluation record."""
self.ensure_one()
if not self.x_fc_cfr21_report_id:
report = self.env['fusion.plating.10cfr21.report'].create({
'discovery_date': fields.Date.context_today(self),
'part_description': self.part_ref or '',
'defect_description': self.description or '',
'ncr_id': self.id,
})
self.write({
'x_fc_cfr21_report_id': report.id,
'x_fc_cfr21_evaluated': True,
})
return {
'name': '10 CFR 21 Report',
'type': 'ir.actions.act_window',
'res_model': 'fusion.plating.10cfr21.report',
'view_mode': 'form',
'res_id': self.x_fc_cfr21_report_id.id,
}

View File

@@ -0,0 +1,126 @@
# -*- 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 FpNuclearItp(models.Model):
"""Inspection and Test Plan (ITP).
For nuclear work, every critical part typically has an approved
Inspection and Test Plan that lists:
* Hold points (customer has to be present before work continues)
* Witness points (customer may be present)
* Review points (customer reviews records after the fact)
* Test methods and acceptance criteria
The ITP is usually prepared by the supplier, reviewed by the
customer, and formally approved before work can start. Once
approved, any deviation needs a change record.
"""
_name = 'fusion.plating.nuclear.itp'
_description = 'Fusion Plating — Nuclear Inspection and Test Plan'
_inherit = ['mail.thread', 'mail.activity.mixin']
_order = 'name desc'
name = fields.Char(
string='Reference',
required=True,
copy=False,
readonly=True,
default=lambda self: self._default_name(),
tracking=True,
)
customer_id = fields.Many2one(
'res.partner',
string='Customer',
required=True,
tracking=True,
)
part_number = fields.Char(
string='Part Number',
tracking=True,
)
drawing_ref = fields.Char(
string='Drawing Ref',
tracking=True,
)
n299_level_id = fields.Many2one(
'fusion.plating.n299.level',
string='CSA N299 Level',
tracking=True,
)
hold_points = fields.Html(
string='Hold / Witness / Review Points',
help='Document the hold, witness and review points the customer has '
'specified for this part.',
)
test_methods = fields.Html(
string='Test Methods',
)
acceptance_criteria = fields.Html(
string='Acceptance Criteria',
)
document_ids = fields.Many2many(
'ir.attachment',
'fp_nuclear_itp_attachment_rel',
'itp_id',
'attachment_id',
string='Attached Documents',
)
state = fields.Selection(
[
('draft', 'Draft'),
('customer_review', 'Customer Review'),
('approved', 'Approved'),
('in_use', 'In Use'),
('superseded', 'Superseded'),
],
string='Status',
default='draft',
required=True,
tracking=True,
)
customer_approval_date = fields.Date(
string='Customer Approval',
tracking=True,
)
company_id = fields.Many2one(
'res.company',
string='Company',
default=lambda self: self.env.company,
)
active = fields.Boolean(default=True)
@api.model
def _default_name(self):
seq = self.env['ir.sequence'].next_by_code('fusion.plating.nuclear.itp')
return seq or '/'
@api.model_create_multi
def create(self, vals_list):
for vals in vals_list:
if not vals.get('name') or vals.get('name') == '/':
vals['name'] = self._default_name()
return super().create(vals_list)
def action_submit_for_review(self):
self.write({'state': 'customer_review'})
def action_approve(self):
self.write({
'state': 'approved',
'customer_approval_date': fields.Date.context_today(self),
})
def action_put_in_use(self):
self.write({'state': 'in_use'})
def action_supersede(self):
self.write({'state': 'superseded'})
def action_reset_to_draft(self):
self.write({'state': 'draft'})

View File

@@ -0,0 +1,122 @@
# -*- coding: utf-8 -*-
# Copyright 2026 Nexa Systems Inc.
# License OPL-1 (Odoo Proprietary License v1.0)
# Part of the Fusion Plating product family.
from dateutil.relativedelta import relativedelta
from odoo import api, fields, models
class FpNuclearPedigree(models.Model):
"""Nuclear Pedigree Traceability Record.
Nuclear pedigree is the unbroken chain of traceability from the raw
material a plated part was made from, through every processing
step, to the finished and shipped component. Nuclear operators use
pedigree records decades after shipment — long after the original
work order has aged out of normal systems — which is why the
retention clock is driven by the N299 level rather than a generic
document-retention rule.
Once the record is locked (typically at ship), the fields above the
chatter are read-only and all downstream edits should go through
the normal change-control process.
"""
_name = 'fusion.plating.nuclear.pedigree'
_description = 'Fusion Plating — Nuclear Pedigree Record'
_inherit = ['mail.thread', 'mail.activity.mixin']
_order = 'ship_date desc, id desc'
name = fields.Char(
string='Job / Lot Ref',
required=True,
tracking=True,
)
part_number = fields.Char(
string='Part Number',
tracking=True,
)
lot_serial = fields.Char(
string='Lot / Serial',
tracking=True,
)
customer_id = fields.Many2one(
'res.partner',
string='Customer',
required=True,
tracking=True,
)
n299_level_id = fields.Many2one(
'fusion.plating.n299.level',
string='CSA N299 Level',
tracking=True,
)
raw_material_cert_refs = fields.Char(
string='Raw Material Cert Refs',
help='Mill test report, CMTR, or material certificate reference(s).',
)
raw_material_heat_no = fields.Char(
string='Raw Material Heat No',
)
process_steps_json = fields.Text(
string='Process Steps',
help='Structured trail of each processing step the part went '
'through (station, operator, timestamp, parameters).',
)
operators_log = fields.Text(
string='Operators Log',
)
chemistry_cert_refs = fields.Char(
string='Chemistry Cert Refs',
)
test_results = fields.Html(
string='Test Results',
)
ship_date = fields.Date(
string='Ship Date',
tracking=True,
)
retention_until_date = fields.Date(
string='Retain Until',
compute='_compute_retention_until_date',
store=True,
help='Ship date plus the retention period of the assigned N299 level.',
)
attachment_ids = fields.Many2many(
'ir.attachment',
'fp_nuclear_pedigree_attachment_rel',
'pedigree_id',
'attachment_id',
string='Supporting Documents',
)
locked = fields.Boolean(
string='Locked',
default=False,
tracking=True,
help='Once the part has shipped, lock the pedigree to prevent '
'modification. Further changes must go through formal '
'change control.',
)
company_id = fields.Many2one(
'res.company',
string='Company',
default=lambda self: self.env.company,
)
active = fields.Boolean(default=True)
@api.depends('ship_date', 'n299_level_id.retention_years')
def _compute_retention_until_date(self):
for rec in self:
if rec.ship_date and rec.n299_level_id and rec.n299_level_id.retention_years:
rec.retention_until_date = rec.ship_date + relativedelta(
years=rec.n299_level_id.retention_years
)
else:
rec.retention_until_date = False
def action_lock(self):
self.write({'locked': True})
def action_unlock(self):
self.write({'locked': False})

View File

@@ -0,0 +1,100 @@
# -*- 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 FpNuclearProgram(models.Model):
"""Nuclear Quality Program per facility.
A facility that supplies the nuclear industry typically runs a
documented quality program aligned to CSA N299 (Canada) and/or
NQA-1 (US), and is listed on one or more nuclear operators'
approved supplier lists. This record tracks the program manual
revision, the target N299 level, supplier certification status, and
the audit cadence (internal, customer, CNSC awareness).
A facility can have more than one nuclear program — e.g. a Level 3
program for OPG work and a separate NQA-1 program for a US utility.
"""
_name = 'fusion.plating.nuclear.program'
_description = 'Fusion Plating — Nuclear Quality Program'
_inherit = ['mail.thread', 'mail.activity.mixin']
_order = 'facility_id, name'
name = fields.Char(
string='Program',
required=True,
tracking=True,
)
facility_id = fields.Many2one(
'fusion.plating.facility',
string='Facility',
required=True,
tracking=True,
)
company_id = fields.Many2one(
'res.company',
related='facility_id.company_id',
store=True,
readonly=True,
)
n299_level_id = fields.Many2one(
'fusion.plating.n299.level',
string='CSA N299 Level',
tracking=True,
)
nqa1_applicable = fields.Boolean(
string='NQA-1 Applicable',
tracking=True,
help='Tick when this program covers work for US nuclear facilities '
'subject to ASME NQA-1.',
)
cnsc_licensed_supplier = fields.Boolean(
string='CNSC Licensed Supplier',
tracking=True,
help='Tick when the facility holds or is listed under a CNSC '
'licence or a CNSC licensee\'s approved supplier programme.',
)
program_manual_rev = fields.Char(
string='Program Manual Rev',
tracking=True,
)
last_audit_date = fields.Date(
string='Last Audit',
tracking=True,
)
next_audit_date = fields.Date(
string='Next Audit',
tracking=True,
)
state = fields.Selection(
[
('draft', 'Draft'),
('active', 'Active'),
('suspended', 'Suspended'),
('withdrawn', 'Withdrawn'),
],
string='Status',
default='draft',
required=True,
tracking=True,
)
notes = fields.Html(
string='Notes',
)
active = fields.Boolean(default=True)
def action_activate(self):
self.write({'state': 'active'})
def action_suspend(self):
self.write({'state': 'suspended'})
def action_withdraw(self):
self.write({'state': 'withdrawn'})
def action_reset_to_draft(self):
self.write({'state': 'draft'})

View File

@@ -0,0 +1,26 @@
# -*- 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 ResCompany(models.Model):
"""Extend company with a default nuclear records retention policy.
Nuclear quality records typically have to be retained for 40 years
or longer — far beyond the standard document-retention rule of a
commercial shop. This field sets the company-wide default used
when a pedigree record has no N299 level linked or when a higher
authority needs to be applied.
"""
_inherit = 'res.company'
x_fc_nuclear_retention_years = fields.Integer(
string='Nuclear Retention (Years)',
default=40,
help='Default records-retention period for nuclear quality records, '
'applied when no N299 level or spec override is set. Typical '
'Canadian nuclear practice is 40 years or life-of-plant.',
)

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2026 Nexa Systems Inc.
License OPL-1 (Odoo Proprietary License v1.0)
Part of the Fusion Plating product family.
-->
<odoo>
<!--
This module reuses the core groups from fusion_plating:
fusion_plating.group_fusion_plating_operator
fusion_plating.group_fusion_plating_supervisor
fusion_plating.group_fusion_plating_manager
fusion_plating.group_fusion_plating_admin
No new res.groups records are introduced here. All access control
is expressed in security/ir.model.access.csv via those existing
groups so a single user role works across the core, the QMS and
the nuclear pack.
-->
</odoo>

View File

@@ -0,0 +1,19 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_fp_n299_level_operator,fp.n299.level.operator,model_fusion_plating_n299_level,fusion_plating.group_fusion_plating_operator,1,0,0,0
access_fp_n299_level_supervisor,fp.n299.level.supervisor,model_fusion_plating_n299_level,fusion_plating.group_fusion_plating_supervisor,1,0,0,0
access_fp_n299_level_manager,fp.n299.level.manager,model_fusion_plating_n299_level,fusion_plating.group_fusion_plating_manager,1,1,1,1
access_fp_nuclear_program_operator,fp.nuclear.program.operator,model_fusion_plating_nuclear_program,fusion_plating.group_fusion_plating_operator,1,0,0,0
access_fp_nuclear_program_supervisor,fp.nuclear.program.supervisor,model_fusion_plating_nuclear_program,fusion_plating.group_fusion_plating_supervisor,1,1,0,0
access_fp_nuclear_program_manager,fp.nuclear.program.manager,model_fusion_plating_nuclear_program,fusion_plating.group_fusion_plating_manager,1,1,1,1
access_fp_nuclear_itp_operator,fp.nuclear.itp.operator,model_fusion_plating_nuclear_itp,fusion_plating.group_fusion_plating_operator,1,0,0,0
access_fp_nuclear_itp_supervisor,fp.nuclear.itp.supervisor,model_fusion_plating_nuclear_itp,fusion_plating.group_fusion_plating_supervisor,1,1,1,0
access_fp_nuclear_itp_manager,fp.nuclear.itp.manager,model_fusion_plating_nuclear_itp,fusion_plating.group_fusion_plating_manager,1,1,1,1
access_fp_10cfr21_report_operator,fp.10cfr21.report.operator,model_fusion_plating_10cfr21_report,fusion_plating.group_fusion_plating_operator,1,0,0,0
access_fp_10cfr21_report_supervisor,fp.10cfr21.report.supervisor,model_fusion_plating_10cfr21_report,fusion_plating.group_fusion_plating_supervisor,1,1,1,0
access_fp_10cfr21_report_manager,fp.10cfr21.report.manager,model_fusion_plating_10cfr21_report,fusion_plating.group_fusion_plating_manager,1,1,1,1
access_fp_nuclear_pedigree_operator,fp.nuclear.pedigree.operator,model_fusion_plating_nuclear_pedigree,fusion_plating.group_fusion_plating_operator,1,0,0,0
access_fp_nuclear_pedigree_supervisor,fp.nuclear.pedigree.supervisor,model_fusion_plating_nuclear_pedigree,fusion_plating.group_fusion_plating_supervisor,1,1,1,0
access_fp_nuclear_pedigree_manager,fp.nuclear.pedigree.manager,model_fusion_plating_nuclear_pedigree,fusion_plating.group_fusion_plating_manager,1,1,1,1
access_fp_cnsc_licence_operator,fp.cnsc.licence.operator,model_fusion_plating_cnsc_licence,fusion_plating.group_fusion_plating_operator,1,0,0,0
access_fp_cnsc_licence_supervisor,fp.cnsc.licence.supervisor,model_fusion_plating_cnsc_licence,fusion_plating.group_fusion_plating_supervisor,1,0,0,0
access_fp_cnsc_licence_manager,fp.cnsc.licence.manager,model_fusion_plating_cnsc_licence,fusion_plating.group_fusion_plating_manager,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_fp_n299_level_operator fp.n299.level.operator model_fusion_plating_n299_level fusion_plating.group_fusion_plating_operator 1 0 0 0
3 access_fp_n299_level_supervisor fp.n299.level.supervisor model_fusion_plating_n299_level fusion_plating.group_fusion_plating_supervisor 1 0 0 0
4 access_fp_n299_level_manager fp.n299.level.manager model_fusion_plating_n299_level fusion_plating.group_fusion_plating_manager 1 1 1 1
5 access_fp_nuclear_program_operator fp.nuclear.program.operator model_fusion_plating_nuclear_program fusion_plating.group_fusion_plating_operator 1 0 0 0
6 access_fp_nuclear_program_supervisor fp.nuclear.program.supervisor model_fusion_plating_nuclear_program fusion_plating.group_fusion_plating_supervisor 1 1 0 0
7 access_fp_nuclear_program_manager fp.nuclear.program.manager model_fusion_plating_nuclear_program fusion_plating.group_fusion_plating_manager 1 1 1 1
8 access_fp_nuclear_itp_operator fp.nuclear.itp.operator model_fusion_plating_nuclear_itp fusion_plating.group_fusion_plating_operator 1 0 0 0
9 access_fp_nuclear_itp_supervisor fp.nuclear.itp.supervisor model_fusion_plating_nuclear_itp fusion_plating.group_fusion_plating_supervisor 1 1 1 0
10 access_fp_nuclear_itp_manager fp.nuclear.itp.manager model_fusion_plating_nuclear_itp fusion_plating.group_fusion_plating_manager 1 1 1 1
11 access_fp_10cfr21_report_operator fp.10cfr21.report.operator model_fusion_plating_10cfr21_report fusion_plating.group_fusion_plating_operator 1 0 0 0
12 access_fp_10cfr21_report_supervisor fp.10cfr21.report.supervisor model_fusion_plating_10cfr21_report fusion_plating.group_fusion_plating_supervisor 1 1 1 0
13 access_fp_10cfr21_report_manager fp.10cfr21.report.manager model_fusion_plating_10cfr21_report fusion_plating.group_fusion_plating_manager 1 1 1 1
14 access_fp_nuclear_pedigree_operator fp.nuclear.pedigree.operator model_fusion_plating_nuclear_pedigree fusion_plating.group_fusion_plating_operator 1 0 0 0
15 access_fp_nuclear_pedigree_supervisor fp.nuclear.pedigree.supervisor model_fusion_plating_nuclear_pedigree fusion_plating.group_fusion_plating_supervisor 1 1 1 0
16 access_fp_nuclear_pedigree_manager fp.nuclear.pedigree.manager model_fusion_plating_nuclear_pedigree fusion_plating.group_fusion_plating_manager 1 1 1 1
17 access_fp_cnsc_licence_operator fp.cnsc.licence.operator model_fusion_plating_cnsc_licence fusion_plating.group_fusion_plating_operator 1 0 0 0
18 access_fp_cnsc_licence_supervisor fp.cnsc.licence.supervisor model_fusion_plating_cnsc_licence fusion_plating.group_fusion_plating_supervisor 1 0 0 0
19 access_fp_cnsc_licence_manager fp.cnsc.licence.manager model_fusion_plating_cnsc_licence fusion_plating.group_fusion_plating_manager 1 1 1 1

View File

@@ -0,0 +1,71 @@
// =============================================================================
// Fusion Plating — Nuclear (CSA N299, NQA-1) backend styles
// Copyright 2026 Nexa Systems Inc.
// License OPL-1 (Odoo Proprietary License v1.0)
//
// THEME AWARENESS
// ---------------
// This file NEVER hardcodes backgrounds or text colours. All surface and
// semantic colours come from Odoo / Bootstrap CSS custom properties so the
// component renders correctly in BOTH light and dark mode without any
// duplication or media-query overrides.
//
// background: var(--bs-body-bg) // main surface
// surface: var(--o-view-background-color) // view canvas
// foreground: var(--bs-body-color) // main text
// muted text: var(--bs-secondary-color)
// border: var(--bs-border-color)
// primary: var(--o-action) // Odoo action / brand
// success: var(--bs-success)
// warning: var(--bs-warning)
// danger: var(--bs-danger)
// info: var(--bs-info)
//
// Semantic status tints use `color-mix()` against the Bootstrap theme tokens
// so a danger badge is darker on light mode and brighter on dark mode
// automatically — one rule, two looks.
//
// We never target `.o_dark`, `html.dark`, or `@media (prefers-color-scheme)`.
// =============================================================================
// -----------------------------------------------------------------------------
// Local helper — semantic tint mixin
// -----------------------------------------------------------------------------
@mixin fp-nuclear-tint($color-var, $amount: 12%) {
background-color: color-mix(in srgb, var(#{$color-var}) #{$amount}, transparent);
color: var(#{$color-var});
border: 1px solid color-mix(in srgb, var(#{$color-var}) 35%, transparent);
}
// -----------------------------------------------------------------------------
// N299 level pill — used anywhere a level is displayed inline
// -----------------------------------------------------------------------------
.o_fp_nuclear_level {
display: inline-block;
padding: 2px 8px;
font-size: 0.72rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.03em;
border-radius: 999px;
@include fp-nuclear-tint(--bs-info);
&[data-level="1"] { @include fp-nuclear-tint(--bs-danger); }
&[data-level="2"] { @include fp-nuclear-tint(--bs-warning); }
&[data-level="3"] { @include fp-nuclear-tint(--bs-info); }
&[data-level="4"] { @include fp-nuclear-tint(--bs-secondary-color); }
}
// -----------------------------------------------------------------------------
// Locked pedigree — visual cue that the record is frozen
// -----------------------------------------------------------------------------
.o_fp_nuclear_locked {
// When a pedigree is locked the title picks up a subtle danger tint so
// the reader knows at a glance that further changes need change control.
// The Odoo ribbon widget handles the overt "Locked" indicator; this
// just reinforces it on the title line.
color: color-mix(in srgb, var(--bs-body-color) 85%, var(--bs-danger));
}

View File

@@ -0,0 +1,121 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2026 Nexa Systems Inc.
License OPL-1 (Odoo Proprietary License v1.0)
Part of the Fusion Plating product family.
-->
<odoo>
<record id="view_fp_10cfr21_report_list" model="ir.ui.view">
<field name="name">fp.10cfr21.report.list</field>
<field name="model">fusion.plating.10cfr21.report</field>
<field name="arch" type="xml">
<list string="10 CFR Part 21 Reports"
decoration-danger="days_since_discovery &gt;= 45 and state in ('discovery','evaluation')"
decoration-warning="days_since_discovery &gt;= 30 and days_since_discovery &lt; 45 and state in ('discovery','evaluation')"
decoration-muted="state in ('closed','not_reportable')">
<field name="name"/>
<field name="discovery_date"/>
<field name="days_since_discovery"/>
<field name="ncr_id"/>
<field name="reportable" widget="boolean_toggle"/>
<field name="report_date"/>
<field name="state" widget="badge"
decoration-info="state == 'evaluation'"
decoration-warning="state == 'reportable'"
decoration-success="state == 'reported'"
decoration-muted="state in ('closed','not_reportable')"/>
</list>
</field>
</record>
<record id="view_fp_10cfr21_report_form" model="ir.ui.view">
<field name="name">fp.10cfr21.report.form</field>
<field name="model">fusion.plating.10cfr21.report</field>
<field name="arch" type="xml">
<form string="10 CFR Part 21 Report">
<header>
<button name="action_start_evaluation" string="Start Evaluation" type="object"
class="oe_highlight" invisible="state != 'discovery'"/>
<button name="action_mark_reportable" string="Mark Reportable" type="object"
class="oe_highlight" invisible="state != 'evaluation'"/>
<button name="action_mark_not_reportable" string="Mark Not Reportable" type="object"
invisible="state != 'evaluation'"/>
<button name="action_file_report" string="File Report" type="object"
class="oe_highlight" invisible="state != 'reportable'"/>
<button name="action_close" string="Close" type="object"
invisible="state not in ('reported','not_reportable')"/>
<button name="action_reset_to_discovery" string="Reset" type="object"
invisible="state == 'discovery'"/>
<field name="state" widget="statusbar"
statusbar_visible="discovery,evaluation,reportable,reported,closed"/>
</header>
<sheet>
<div class="oe_title">
<label for="name"/>
<h1><field name="name" readonly="1"/></h1>
</div>
<group>
<group>
<field name="discovery_date"/>
<field name="days_since_discovery"/>
<field name="report_date"/>
</group>
<group>
<field name="ncr_id"/>
<field name="reportable"/>
</group>
</group>
<notebook>
<page string="Part / Component">
<field name="part_description"/>
</page>
<page string="Defect Description">
<field name="defect_description"/>
</page>
<page string="Affected Customers">
<field name="customer_ids" widget="many2many_tags"/>
</page>
<page string="Corrective Action">
<field name="corrective_action"/>
</page>
</notebook>
</sheet>
<chatter/>
</form>
</field>
</record>
<record id="view_fp_10cfr21_report_search" model="ir.ui.view">
<field name="name">fp.10cfr21.report.search</field>
<field name="model">fusion.plating.10cfr21.report</field>
<field name="arch" type="xml">
<search string="10 CFR 21 Reports">
<field name="name"/>
<field name="ncr_id"/>
<separator/>
<filter string="Open Evaluation" name="open_eval"
domain="[('state','in',['discovery','evaluation'])]"/>
<filter string="Reportable" name="reportable_f"
domain="[('state','in',['reportable','reported'])]"/>
<filter string="Not Reportable" name="not_reportable_f"
domain="[('state','=','not_reportable')]"/>
<filter string="Overdue (&gt;= 45 days)" name="overdue"
domain="[('days_since_discovery','&gt;=',45),('state','in',['discovery','evaluation'])]"/>
<separator/>
<filter string="Archived" name="inactive" domain="[('active','=',False)]"/>
<group>
<filter string="Status" name="group_state" context="{'group_by':'state'}"/>
</group>
</search>
</field>
</record>
<record id="action_fp_10cfr21_report" model="ir.actions.act_window">
<field name="name">10 CFR Part 21 Reports</field>
<field name="res_model">fusion.plating.10cfr21.report</field>
<field name="view_mode">list,form</field>
<field name="search_view_id" ref="view_fp_10cfr21_report_search"/>
</record>
</odoo>

View File

@@ -0,0 +1,96 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2026 Nexa Systems Inc.
License OPL-1 (Odoo Proprietary License v1.0)
Part of the Fusion Plating product family.
-->
<odoo>
<record id="view_fp_cnsc_licence_list" model="ir.ui.view">
<field name="name">fp.cnsc.licence.list</field>
<field name="model">fusion.plating.cnsc.licence</field>
<field name="arch" type="xml">
<list string="CNSC Licences"
decoration-danger="state == 'expired'"
decoration-warning="state == 'expiring'"
decoration-muted="state == 'revoked'">
<field name="licence_number"/>
<field name="name"/>
<field name="facility_id"/>
<field name="licence_type"/>
<field name="issue_date"/>
<field name="expiry_date"/>
<field name="state" widget="badge"
decoration-success="state == 'active'"
decoration-warning="state == 'expiring'"
decoration-danger="state == 'expired'"
decoration-muted="state == 'revoked'"/>
</list>
</field>
</record>
<record id="view_fp_cnsc_licence_form" model="ir.ui.view">
<field name="name">fp.cnsc.licence.form</field>
<field name="model">fusion.plating.cnsc.licence</field>
<field name="arch" type="xml">
<form string="CNSC Licence">
<sheet>
<div class="oe_title">
<label for="name"/>
<h1><field name="name"/></h1>
</div>
<group>
<group>
<field name="licence_number"/>
<field name="licence_type"/>
<field name="facility_id"/>
<field name="state"/>
</group>
<group>
<field name="issue_date"/>
<field name="expiry_date"/>
<field name="attachment_id"/>
</group>
</group>
<notebook>
<page string="Licence Conditions">
<field name="conditions"/>
</page>
</notebook>
</sheet>
<chatter/>
</form>
</field>
</record>
<record id="view_fp_cnsc_licence_search" model="ir.ui.view">
<field name="name">fp.cnsc.licence.search</field>
<field name="model">fusion.plating.cnsc.licence</field>
<field name="arch" type="xml">
<search string="CNSC Licences">
<field name="licence_number"/>
<field name="name"/>
<field name="facility_id"/>
<separator/>
<filter string="Active" name="active_f" domain="[('state','=','active')]"/>
<filter string="Expiring" name="expiring" domain="[('state','=','expiring')]"/>
<filter string="Expired" name="expired" domain="[('state','=','expired')]"/>
<separator/>
<filter string="Archived" name="inactive" domain="[('active','=',False)]"/>
<group>
<filter string="Type" name="group_type" context="{'group_by':'licence_type'}"/>
<filter string="Facility" name="group_facility" context="{'group_by':'facility_id'}"/>
<filter string="Status" name="group_state" context="{'group_by':'state'}"/>
</group>
</search>
</field>
</record>
<record id="action_fp_cnsc_licence" model="ir.actions.act_window">
<field name="name">CNSC Licences</field>
<field name="res_model">fusion.plating.cnsc.licence</field>
<field name="view_mode">list,form</field>
<field name="search_view_id" ref="view_fp_cnsc_licence_search"/>
</record>
</odoo>

View File

@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2026 Nexa Systems Inc.
License OPL-1 (Odoo Proprietary License v1.0)
Part of the Fusion Plating product family.
-->
<odoo>
<!-- Inherit the quality customer-spec form to surface nuclear fields. -->
<record id="view_fp_customer_spec_form_nuclear" model="ir.ui.view">
<field name="name">fp.customer.spec.form.nuclear</field>
<field name="model">fusion.plating.customer.spec</field>
<field name="inherit_id" ref="fusion_plating_quality.view_fp_customer_spec_form"/>
<field name="arch" type="xml">
<xpath expr="//notebook" position="inside">
<page string="Nuclear">
<group>
<group>
<field name="x_fc_is_nuclear"/>
<field name="x_fc_n299_level_id"
invisible="not x_fc_is_nuclear"/>
<field name="x_fc_nuclear_customer_type"
invisible="not x_fc_is_nuclear"/>
</group>
<group>
<field name="x_fc_nqa1_applicable"
invisible="not x_fc_is_nuclear"/>
<field name="x_fc_extended_retention_years"
invisible="not x_fc_is_nuclear"/>
</group>
</group>
</page>
</xpath>
</field>
</record>
<!-- Inherit the quality customer-spec list to show the nuclear flag. -->
<record id="view_fp_customer_spec_list_nuclear" model="ir.ui.view">
<field name="name">fp.customer.spec.list.nuclear</field>
<field name="model">fusion.plating.customer.spec</field>
<field name="inherit_id" ref="fusion_plating_quality.view_fp_customer_spec_list"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='spec_type']" position="after">
<field name="x_fc_is_nuclear" optional="show" string="Nuclear"/>
<field name="x_fc_n299_level_id" optional="hide"/>
</xpath>
</field>
</record>
<!-- Inherit the quality customer-spec search to add nuclear filters. -->
<record id="view_fp_customer_spec_search_nuclear" model="ir.ui.view">
<field name="name">fp.customer.spec.search.nuclear</field>
<field name="model">fusion.plating.customer.spec</field>
<field name="inherit_id" ref="fusion_plating_quality.view_fp_customer_spec_search"/>
<field name="arch" type="xml">
<xpath expr="//filter[@name='internal']" position="after">
<separator/>
<filter string="Nuclear" name="nuclear" domain="[('x_fc_is_nuclear','=',True)]"/>
<filter string="NQA-1" name="nqa1" domain="[('x_fc_nqa1_applicable','=',True)]"/>
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2026 Nexa Systems Inc.
License OPL-1 (Odoo Proprietary License v1.0)
Part of the Fusion Plating product family.
-->
<odoo>
<!-- ===== NUCLEAR (top-level submenu under the Plating app) ===== -->
<menuitem id="menu_fp_nuclear"
name="Nuclear"
parent="fusion_plating.menu_fp_root"
sequence="65"
groups="fusion_plating.group_fusion_plating_operator"/>
<menuitem id="menu_fp_nuclear_program"
name="N299 Programs"
parent="menu_fp_nuclear"
action="action_fp_nuclear_program"
sequence="10"/>
<menuitem id="menu_fp_nuclear_itp"
name="Inspection &amp; Test Plans"
parent="menu_fp_nuclear"
action="action_fp_nuclear_itp"
sequence="20"/>
<menuitem id="menu_fp_nuclear_10cfr21"
name="10 CFR 21 Reports"
parent="menu_fp_nuclear"
action="action_fp_10cfr21_report"
sequence="30"/>
<menuitem id="menu_fp_nuclear_pedigree"
name="Pedigree Records"
parent="menu_fp_nuclear"
action="action_fp_nuclear_pedigree"
sequence="40"/>
<menuitem id="menu_fp_nuclear_cnsc_licence"
name="CNSC Licences"
parent="menu_fp_nuclear"
action="action_fp_cnsc_licence"
sequence="50"/>
<!-- ===== CONFIGURATION ENTRIES (under the existing Configuration submenu) ===== -->
<menuitem id="menu_fp_config_n299_level"
name="N299 Levels"
parent="fusion_plating.menu_fp_config"
action="action_fp_n299_level"
sequence="200"/>
</odoo>

View File

@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2026 Nexa Systems Inc.
License OPL-1 (Odoo Proprietary License v1.0)
Part of the Fusion Plating product family.
-->
<odoo>
<record id="view_fp_n299_level_list" model="ir.ui.view">
<field name="name">fp.n299.level.list</field>
<field name="model">fusion.plating.n299.level</field>
<field name="arch" type="xml">
<list string="CSA N299 Levels" default_order="level_number">
<field name="level_number"/>
<field name="code"/>
<field name="name"/>
<field name="safety_classification" widget="badge"
decoration-danger="safety_classification == 'safety_critical'"
decoration-warning="safety_classification == 'safety_related'"
decoration-info="safety_classification == 'important_to_safety'"
decoration-muted="safety_classification == 'commercial_grade'"/>
<field name="retention_years"/>
</list>
</field>
</record>
<record id="view_fp_n299_level_form" model="ir.ui.view">
<field name="name">fp.n299.level.form</field>
<field name="model">fusion.plating.n299.level</field>
<field name="arch" type="xml">
<form string="CSA N299 Level">
<sheet>
<div class="oe_title">
<label for="name"/>
<h1><field name="name"/></h1>
</div>
<group>
<group>
<field name="code"/>
<field name="level_number"/>
<field name="safety_classification"/>
</group>
<group>
<field name="retention_years"/>
<field name="active"/>
</group>
</group>
<group string="Description">
<field name="description" nolabel="1"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="view_fp_n299_level_search" model="ir.ui.view">
<field name="name">fp.n299.level.search</field>
<field name="model">fusion.plating.n299.level</field>
<field name="arch" type="xml">
<search string="CSA N299 Levels">
<field name="code"/>
<field name="name"/>
<filter string="Archived" name="inactive" domain="[('active','=',False)]"/>
<group>
<filter string="Safety Classification" name="group_safety"
context="{'group_by':'safety_classification'}"/>
</group>
</search>
</field>
</record>
<record id="action_fp_n299_level" model="ir.actions.act_window">
<field name="name">CSA N299 Levels</field>
<field name="res_model">fusion.plating.n299.level</field>
<field name="view_mode">list,form</field>
<field name="search_view_id" ref="view_fp_n299_level_search"/>
</record>
</odoo>

View File

@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2026 Nexa Systems Inc.
License OPL-1 (Odoo Proprietary License v1.0)
Part of the Fusion Plating product family.
-->
<odoo>
<!-- Inherit the quality NCR form to surface nuclear fields and the 10 CFR 21 button. -->
<record id="view_fp_ncr_form_nuclear" model="ir.ui.view">
<field name="name">fp.ncr.form.nuclear</field>
<field name="model">fusion.plating.ncr</field>
<field name="inherit_id" ref="fusion_plating_quality.view_fp_ncr_form"/>
<field name="arch" type="xml">
<xpath expr="//header" position="inside">
<button name="action_open_cfr21_report"
string="10 CFR 21 Evaluation"
type="object"
invisible="not x_fc_is_nuclear"/>
</xpath>
<xpath expr="//notebook" position="inside">
<page string="Nuclear">
<group>
<group>
<field name="x_fc_is_nuclear"/>
<field name="x_fc_n299_level_id"
invisible="not x_fc_is_nuclear"/>
</group>
<group>
<field name="x_fc_cfr21_evaluated"
invisible="not x_fc_is_nuclear"/>
<field name="x_fc_cfr21_report_id"
invisible="not x_fc_is_nuclear"
readonly="1"/>
</group>
</group>
</page>
</xpath>
</field>
</record>
<!-- Inherit the quality NCR list to surface the nuclear flag. -->
<record id="view_fp_ncr_list_nuclear" model="ir.ui.view">
<field name="name">fp.ncr.list.nuclear</field>
<field name="model">fusion.plating.ncr</field>
<field name="inherit_id" ref="fusion_plating_quality.view_fp_ncr_list"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='severity']" position="after">
<field name="x_fc_is_nuclear" optional="show" string="Nuclear"/>
</xpath>
</field>
</record>
<!-- Inherit the quality NCR search to add nuclear filters. -->
<record id="view_fp_ncr_search_nuclear" model="ir.ui.view">
<field name="name">fp.ncr.search.nuclear</field>
<field name="model">fusion.plating.ncr</field>
<field name="inherit_id" ref="fusion_plating_quality.view_fp_ncr_search"/>
<field name="arch" type="xml">
<xpath expr="//filter[@name='customer_src']" position="after">
<separator/>
<filter string="Nuclear" name="nuclear_ncr"
domain="[('x_fc_is_nuclear','=',True)]"/>
<filter string="10 CFR 21 Pending"
name="cfr21_pending"
domain="[('x_fc_is_nuclear','=',True),('x_fc_cfr21_evaluated','=',False)]"/>
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,118 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2026 Nexa Systems Inc.
License OPL-1 (Odoo Proprietary License v1.0)
Part of the Fusion Plating product family.
-->
<odoo>
<record id="view_fp_nuclear_itp_list" model="ir.ui.view">
<field name="name">fp.nuclear.itp.list</field>
<field name="model">fusion.plating.nuclear.itp</field>
<field name="arch" type="xml">
<list string="Nuclear Inspection and Test Plans"
decoration-muted="state == 'superseded'"
decoration-success="state == 'in_use'"
decoration-info="state == 'approved'">
<field name="name"/>
<field name="customer_id"/>
<field name="part_number"/>
<field name="drawing_ref"/>
<field name="n299_level_id"/>
<field name="customer_approval_date"/>
<field name="state" widget="badge"
decoration-info="state == 'customer_review'"
decoration-success="state in ('approved','in_use')"
decoration-muted="state == 'superseded'"/>
</list>
</field>
</record>
<record id="view_fp_nuclear_itp_form" model="ir.ui.view">
<field name="name">fp.nuclear.itp.form</field>
<field name="model">fusion.plating.nuclear.itp</field>
<field name="arch" type="xml">
<form string="Inspection and Test Plan">
<header>
<button name="action_submit_for_review" string="Submit for Review" type="object"
class="oe_highlight" invisible="state != 'draft'"/>
<button name="action_approve" string="Mark Approved" type="object"
class="oe_highlight" invisible="state != 'customer_review'"/>
<button name="action_put_in_use" string="Put in Use" type="object"
invisible="state != 'approved'"/>
<button name="action_supersede" string="Supersede" type="object"
invisible="state not in ('approved','in_use')"/>
<button name="action_reset_to_draft" string="Reset to Draft" type="object"
invisible="state == 'draft'"/>
<field name="state" widget="statusbar"
statusbar_visible="draft,customer_review,approved,in_use,superseded"/>
</header>
<sheet>
<div class="oe_title">
<label for="name"/>
<h1><field name="name" readonly="1"/></h1>
</div>
<group>
<group>
<field name="customer_id"/>
<field name="part_number"/>
<field name="drawing_ref"/>
</group>
<group>
<field name="n299_level_id"/>
<field name="customer_approval_date"/>
</group>
</group>
<notebook>
<page string="Hold / Witness / Review Points">
<field name="hold_points"/>
</page>
<page string="Test Methods">
<field name="test_methods"/>
</page>
<page string="Acceptance Criteria">
<field name="acceptance_criteria"/>
</page>
<page string="Documents">
<field name="document_ids" widget="many2many_binary"/>
</page>
</notebook>
</sheet>
<chatter/>
</form>
</field>
</record>
<record id="view_fp_nuclear_itp_search" model="ir.ui.view">
<field name="name">fp.nuclear.itp.search</field>
<field name="model">fusion.plating.nuclear.itp</field>
<field name="arch" type="xml">
<search string="ITPs">
<field name="name"/>
<field name="customer_id"/>
<field name="part_number"/>
<field name="drawing_ref"/>
<separator/>
<filter string="Draft" name="draft" domain="[('state','=','draft')]"/>
<filter string="Customer Review" name="review" domain="[('state','=','customer_review')]"/>
<filter string="Approved" name="approved" domain="[('state','=','approved')]"/>
<filter string="In Use" name="in_use" domain="[('state','=','in_use')]"/>
<separator/>
<filter string="Archived" name="inactive" domain="[('active','=',False)]"/>
<group>
<filter string="Customer" name="group_customer" context="{'group_by':'customer_id'}"/>
<filter string="N299 Level" name="group_level" context="{'group_by':'n299_level_id'}"/>
<filter string="Status" name="group_state" context="{'group_by':'state'}"/>
</group>
</search>
</field>
</record>
<record id="action_fp_nuclear_itp" model="ir.actions.act_window">
<field name="name">Inspection and Test Plans</field>
<field name="res_model">fusion.plating.nuclear.itp</field>
<field name="view_mode">list,form</field>
<field name="search_view_id" ref="view_fp_nuclear_itp_search"/>
</record>
</odoo>

View File

@@ -0,0 +1,119 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2026 Nexa Systems Inc.
License OPL-1 (Odoo Proprietary License v1.0)
Part of the Fusion Plating product family.
-->
<odoo>
<record id="view_fp_nuclear_pedigree_list" model="ir.ui.view">
<field name="name">fp.nuclear.pedigree.list</field>
<field name="model">fusion.plating.nuclear.pedigree</field>
<field name="arch" type="xml">
<list string="Nuclear Pedigree Records"
decoration-muted="locked">
<field name="name"/>
<field name="part_number"/>
<field name="lot_serial"/>
<field name="customer_id"/>
<field name="n299_level_id"/>
<field name="raw_material_heat_no"/>
<field name="ship_date"/>
<field name="retention_until_date"/>
<field name="locked" widget="boolean_toggle"/>
</list>
</field>
</record>
<record id="view_fp_nuclear_pedigree_form" model="ir.ui.view">
<field name="name">fp.nuclear.pedigree.form</field>
<field name="model">fusion.plating.nuclear.pedigree</field>
<field name="arch" type="xml">
<form string="Nuclear Pedigree Record">
<header>
<button name="action_lock" string="Lock" type="object"
class="oe_highlight" invisible="locked"/>
<button name="action_unlock" string="Unlock" type="object"
invisible="not locked"
groups="fusion_plating.group_fusion_plating_manager"
confirm="Unlocking a pedigree record bypasses change control. Continue?"/>
</header>
<sheet>
<widget name="web_ribbon" title="Locked" bg_color="text-bg-danger"
invisible="not locked"/>
<div class="oe_title">
<label for="name"/>
<h1>
<field name="name" readonly="locked"
class="o_fp_nuclear_locked"/>
</h1>
</div>
<group>
<group>
<field name="part_number" readonly="locked"/>
<field name="lot_serial" readonly="locked"/>
<field name="customer_id" readonly="locked"/>
<field name="n299_level_id" readonly="locked"
class="o_fp_nuclear_level"/>
</group>
<group>
<field name="raw_material_heat_no" readonly="locked"/>
<field name="raw_material_cert_refs" readonly="locked"/>
<field name="chemistry_cert_refs" readonly="locked"/>
<field name="ship_date" readonly="locked"/>
<field name="retention_until_date" readonly="1"/>
</group>
</group>
<notebook>
<page string="Process Steps">
<field name="process_steps_json" readonly="locked"
placeholder="Station, operator, timestamp, parameters..."/>
</page>
<page string="Operators Log">
<field name="operators_log" readonly="locked"/>
</page>
<page string="Test Results">
<field name="test_results" readonly="locked"/>
</page>
<page string="Supporting Documents">
<field name="attachment_ids" widget="many2many_binary"
readonly="locked"/>
</page>
</notebook>
</sheet>
<chatter/>
</form>
</field>
</record>
<record id="view_fp_nuclear_pedigree_search" model="ir.ui.view">
<field name="name">fp.nuclear.pedigree.search</field>
<field name="model">fusion.plating.nuclear.pedigree</field>
<field name="arch" type="xml">
<search string="Pedigree Records">
<field name="name"/>
<field name="part_number"/>
<field name="lot_serial"/>
<field name="customer_id"/>
<field name="raw_material_heat_no"/>
<separator/>
<filter string="Locked" name="locked_f" domain="[('locked','=',True)]"/>
<filter string="Open" name="open_f" domain="[('locked','=',False)]"/>
<separator/>
<filter string="Archived" name="inactive" domain="[('active','=',False)]"/>
<group>
<filter string="Customer" name="group_customer" context="{'group_by':'customer_id'}"/>
<filter string="N299 Level" name="group_level" context="{'group_by':'n299_level_id'}"/>
</group>
</search>
</field>
</record>
<record id="action_fp_nuclear_pedigree" model="ir.actions.act_window">
<field name="name">Nuclear Pedigree Records</field>
<field name="res_model">fusion.plating.nuclear.pedigree</field>
<field name="view_mode">list,form</field>
<field name="search_view_id" ref="view_fp_nuclear_pedigree_search"/>
</record>
</odoo>

View File

@@ -0,0 +1,110 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2026 Nexa Systems Inc.
License OPL-1 (Odoo Proprietary License v1.0)
Part of the Fusion Plating product family.
-->
<odoo>
<record id="view_fp_nuclear_program_list" model="ir.ui.view">
<field name="name">fp.nuclear.program.list</field>
<field name="model">fusion.plating.nuclear.program</field>
<field name="arch" type="xml">
<list string="Nuclear Quality Programs"
decoration-muted="state == 'withdrawn'"
decoration-warning="state == 'suspended'"
decoration-success="state == 'active'">
<field name="name"/>
<field name="facility_id"/>
<field name="n299_level_id"/>
<field name="nqa1_applicable" widget="boolean_toggle"/>
<field name="cnsc_licensed_supplier" widget="boolean_toggle"/>
<field name="program_manual_rev"/>
<field name="last_audit_date"/>
<field name="next_audit_date"/>
<field name="state" widget="badge"
decoration-success="state == 'active'"
decoration-warning="state == 'suspended'"
decoration-muted="state == 'withdrawn'"/>
</list>
</field>
</record>
<record id="view_fp_nuclear_program_form" model="ir.ui.view">
<field name="name">fp.nuclear.program.form</field>
<field name="model">fusion.plating.nuclear.program</field>
<field name="arch" type="xml">
<form string="Nuclear Quality Program">
<header>
<button name="action_activate" string="Activate" type="object"
class="oe_highlight" invisible="state == 'active'"/>
<button name="action_suspend" string="Suspend" type="object"
invisible="state != 'active'"/>
<button name="action_withdraw" string="Withdraw" type="object"
invisible="state == 'withdrawn'"/>
<button name="action_reset_to_draft" string="Reset to Draft" type="object"
invisible="state == 'draft'"/>
<field name="state" widget="statusbar"
statusbar_visible="draft,active,suspended,withdrawn"/>
</header>
<sheet>
<div class="oe_title">
<label for="name"/>
<h1><field name="name"/></h1>
</div>
<group>
<group>
<field name="facility_id"/>
<field name="n299_level_id"/>
<field name="program_manual_rev"/>
</group>
<group>
<field name="nqa1_applicable"/>
<field name="cnsc_licensed_supplier"/>
<field name="last_audit_date"/>
<field name="next_audit_date"/>
</group>
</group>
<notebook>
<page string="Notes">
<field name="notes"/>
</page>
</notebook>
</sheet>
<chatter/>
</form>
</field>
</record>
<record id="view_fp_nuclear_program_search" model="ir.ui.view">
<field name="name">fp.nuclear.program.search</field>
<field name="model">fusion.plating.nuclear.program</field>
<field name="arch" type="xml">
<search string="Nuclear Programs">
<field name="name"/>
<field name="facility_id"/>
<field name="n299_level_id"/>
<separator/>
<filter string="Active" name="active_state" domain="[('state','=','active')]"/>
<filter string="Suspended" name="suspended" domain="[('state','=','suspended')]"/>
<filter string="NQA-1" name="nqa1" domain="[('nqa1_applicable','=',True)]"/>
<filter string="CNSC Supplier" name="cnsc" domain="[('cnsc_licensed_supplier','=',True)]"/>
<separator/>
<filter string="Archived" name="inactive" domain="[('active','=',False)]"/>
<group>
<filter string="Facility" name="group_facility" context="{'group_by':'facility_id'}"/>
<filter string="N299 Level" name="group_level" context="{'group_by':'n299_level_id'}"/>
<filter string="Status" name="group_state" context="{'group_by':'state'}"/>
</group>
</search>
</field>
</record>
<record id="action_fp_nuclear_program" model="ir.actions.act_window">
<field name="name">Nuclear Quality Programs</field>
<field name="res_model">fusion.plating.nuclear.program</field>
<field name="view_mode">list,form</field>
<field name="search_view_id" ref="view_fp_nuclear_program_search"/>
</record>
</odoo>