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,12 @@
# -*- 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_as9100_clause
from . import fp_nadcap_audit
from . import fp_counterfeit_prevention
from . import fp_config_item
from . import fp_risk
from . import fp_customer_spec
from . import fp_fair

View File

@@ -0,0 +1,96 @@
# -*- 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 FpAs9100Clause(models.Model):
"""AS9100 Rev D clause catalog.
A flat catalogue of clauses and sub-clauses from the AS9100 Rev D
standard, plus related standards (ISO 9001:2015, etc.). Used by
customer specifications and audit findings to pin a requirement to
the specific paragraph of the standard it satisfies.
"""
_name = 'fusion.plating.as9100.clause'
_description = 'Fusion Plating — AS9100 Clause'
_order = 'standard, code, id'
_parent_store = True
_rec_name = 'display_name'
name = fields.Char(
string='Name',
required=True,
translate=True,
)
display_name = fields.Char(
compute='_compute_display_name',
store=True,
)
code = fields.Char(
string='Clause Code',
required=True,
help='Clause reference number, e.g. 8.1.2.',
)
parent_id = fields.Many2one(
'fusion.plating.as9100.clause',
string='Parent Clause',
ondelete='cascade',
index=True,
)
parent_path = fields.Char(index=True, unaccent=False)
child_ids = fields.One2many(
'fusion.plating.as9100.clause',
'parent_id',
string='Sub-clauses',
)
description = fields.Html(
string='Description',
translate=True,
)
standard = fields.Selection(
[
('as9100d', 'AS9100 Rev D'),
('iso9001_2015', 'ISO 9001:2015'),
('other', 'Other'),
],
string='Standard',
default='as9100d',
required=True,
)
category = fields.Selection(
[
('leadership', 'Leadership'),
('planning', 'Planning'),
('support', 'Support'),
('operation', 'Operation'),
('performance', 'Performance Evaluation'),
('improvement', 'Improvement'),
],
string='Category',
)
notes = fields.Html(
string='Notes',
translate=True,
)
active = fields.Boolean(default=True)
_sql_constraints = [
(
'fp_as9100_clause_code_std_uniq',
'unique(code, standard)',
'A clause code must be unique per standard.',
),
]
@api.depends('code', 'name')
def _compute_display_name(self):
for rec in self:
parts = []
if rec.code:
parts.append(rec.code)
if rec.name:
parts.append(rec.name)
rec.display_name = ''.join(parts) if parts else ''

View File

@@ -0,0 +1,73 @@
# -*- 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 FpConfigItem(models.Model):
"""Configuration management baseline item.
Tracks a configuration item (product, process, document, tooling,
etc.) under formal configuration management control per AS9100
§8.1.2. Each item has a baseline revision, the current in-use
revision, and a change history log for traceability.
"""
_name = 'fusion.plating.config.item'
_description = 'Fusion Plating — Configuration Management Item'
_inherit = ['mail.thread', 'mail.activity.mixin']
_order = 'name, id'
name = fields.Char(
string='Name',
required=True,
tracking=True,
)
code = fields.Char(
string='Code',
required=True,
tracking=True,
)
baseline_revision = fields.Char(
string='Baseline Revision',
tracking=True,
help='The frozen baseline revision this item starts from.',
)
current_revision = fields.Char(
string='Current Revision',
tracking=True,
help='The revision currently in effect — usually the most '
'recently approved change.',
)
approved_by_id = fields.Many2one(
'res.users',
string='Approved By',
tracking=True,
)
approval_date = fields.Date(
string='Approval Date',
tracking=True,
)
change_history = fields.Html(
string='Change History',
help='Manual log of baseline changes. Use dated entries to keep '
'full traceability for auditors.',
)
notes = fields.Html(
string='Notes',
)
company_id = fields.Many2one(
'res.company',
string='Company',
default=lambda self: self.env.company,
)
active = fields.Boolean(default=True)
_sql_constraints = [
(
'fp_config_item_code_uniq',
'unique(code, company_id)',
'Configuration item codes must be unique per company.',
),
]

View File

@@ -0,0 +1,87 @@
# -*- 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 FpCounterfeitPrevention(models.Model):
"""Counterfeit parts prevention incident log.
Records an incident where a suspected or confirmed counterfeit /
fraudulent part, material, or raw stock was detected in the supply
chain. Required by AS9100 §8.1.4 Counterfeit Parts Prevention.
"""
_name = 'fusion.plating.counterfeit.prevention'
_description = 'Fusion Plating — Counterfeit Parts Prevention Log'
_inherit = ['mail.thread', 'mail.activity.mixin']
_order = 'incident_date desc, id desc'
name = fields.Char(
string='Reference',
required=True,
copy=False,
readonly=True,
default=lambda self: self._default_name(),
tracking=True,
)
incident_date = fields.Date(
string='Incident Date',
default=lambda self: fields.Date.context_today(self),
tracking=True,
)
supplier_id = fields.Many2one(
'res.partner',
string='Supplier',
tracking=True,
)
part_number = fields.Char(
string='Part Number',
tracking=True,
)
lot_serial = fields.Char(
string='Lot / Serial',
tracking=True,
)
detection_method = fields.Char(
string='Detection Method',
help='How the counterfeit item was detected (receiving inspection, '
'lab test, certificate discrepancy, etc.).',
)
disposition = fields.Selection(
[
('returned', 'Returned to Supplier'),
('destroyed', 'Destroyed / Quarantined'),
('investigation', 'Under Investigation'),
],
string='Disposition',
default='investigation',
tracking=True,
)
gidep_reported = fields.Boolean(
string='GIDEP Reported',
tracking=True,
help='Reported to the Government Industry Data Exchange Program.',
)
notes = fields.Html(
string='Notes',
)
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.counterfeit.prevention')
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)

View File

@@ -0,0 +1,54 @@
# -*- 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):
"""Aerospace extension to the quality customer-spec model.
Adds the small set of aerospace-specific flags and linkages the
quality module deliberately keeps out of its generic implementation.
"""
_inherit = 'fusion.plating.customer.spec'
x_fc_is_aerospace = fields.Boolean(
string='Aerospace Spec',
tracking=True,
help='Check to mark this specification as aerospace-relevant so '
'it shows up in aerospace filters and dashboards.',
)
x_fc_as9100_clause_ids = fields.Many2many(
'fusion.plating.as9100.clause',
'fp_customer_spec_as9100_clause_rel',
'spec_id',
'clause_id',
string='Related AS9100 Clauses',
help='AS9100 Rev D clauses this specification maps to.',
)
x_fc_nadcap_required = fields.Boolean(
string='Nadcap Required',
tracking=True,
help='This specification can only be satisfied by a Nadcap-accredited '
'supplier.',
)
x_fc_requires_first_article = fields.Boolean(
string='Requires First Article',
tracking=True,
help='Running this specification on a new part number or revision '
'requires a full FAIR on file.',
)
x_fc_pri_file_code = fields.Char(
string='PRI File Code',
tracking=True,
help='Performance Review Institute file code assigned to this '
'specification, when known.',
)
x_fc_customer_approval_required = fields.Boolean(
string='Customer Approval Required',
tracking=True,
help='Each job against this spec requires explicit customer '
'approval before shipping.',
)

View File

@@ -0,0 +1,54 @@
# -*- 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 FpFair(models.Model):
"""Aerospace extension to the quality FAIR model.
Adds the AS9102 form 1/2/3 attachment slots and the customer-approval
signature block that aerospace customers routinely require on top of
the generic first-article report.
"""
_inherit = 'fusion.plating.fair'
x_fc_as9102_form1 = fields.Binary(
string='AS9102 Form 1 (Part Accountability)',
help='Scanned / generated copy of AS9102 Form 1 — part '
'accountability header.',
)
x_fc_as9102_form1_filename = fields.Char(string='Form 1 Filename')
x_fc_as9102_form2 = fields.Binary(
string='AS9102 Form 2 (Product Accountability)',
help='Scanned / generated copy of AS9102 Form 2 — product '
'accountability, raw material / process / inspection records.',
)
x_fc_as9102_form2_filename = fields.Char(string='Form 2 Filename')
x_fc_as9102_form3 = fields.Binary(
string='AS9102 Form 3 (Characteristic Accountability)',
help='Scanned / generated copy of AS9102 Form 3 — characteristic '
'accountability, verification, and compatibility evaluation.',
)
x_fc_as9102_form3_filename = fields.Char(string='Form 3 Filename')
x_fc_drawing_revision = fields.Char(
string='Drawing Revision',
tracking=True,
help='Customer drawing revision this FAIR is against — must match '
'the revision shipped to the customer.',
)
x_fc_customer_approval_id = fields.Many2one(
'res.users',
string='Customer Approver',
tracking=True,
help='User who recorded the customer-side approval of this FAIR.',
)
x_fc_customer_approval_date = fields.Date(
string='Customer Approval Date',
tracking=True,
)

View File

@@ -0,0 +1,132 @@
# -*- 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 FpNadcapAudit(models.Model):
"""Nadcap AC7108 chemical-processing audit record.
Tracks a single Nadcap audit against AC7108 (base checklist) and its
slash sheets. This is deliberately kept separate from the generic
fusion.plating.audit model in the quality module because Nadcap has
its own accreditation lifecycle, PRI-assigned auditors, and
merit/NCR tracking that don't map cleanly to the generic audit flow.
"""
_name = 'fusion.plating.nadcap.audit'
_description = 'Fusion Plating — Nadcap AC7108 Audit'
_inherit = ['mail.thread', 'mail.activity.mixin']
_order = 'audit_date desc, id desc'
name = fields.Char(
string='Reference',
required=True,
copy=False,
readonly=True,
default=lambda self: self._default_name(),
tracking=True,
)
audit_date = fields.Date(
string='Audit Date',
tracking=True,
)
auditor_name = fields.Char(
string='Auditor',
tracking=True,
help='Name of the individual auditor performing the assessment.',
)
pri_auditor = fields.Boolean(
string='PRI-Assigned Auditor',
tracking=True,
help='Checked when the auditor was assigned by the Performance '
'Review Institute rather than a self-nomination.',
)
checklist = fields.Selection(
[
('ac7108_base', 'AC7108 — Base Checklist'),
('ac7108_10_electroless', 'AC7108/10 — Electroless Nickel'),
('ac7108_11_brush', 'AC7108/11 — Brush Plating'),
('ac7108_12_chrome', 'AC7108/12 — Chromium Plating'),
('ac7108_13_anodize', 'AC7108/13 — Anodize'),
('ac7108_14_conv', 'AC7108/14 — Conversion Coating'),
],
string='Checklist',
default='ac7108_base',
required=True,
tracking=True,
)
result = fields.Selection(
[
('accredited', 'Accredited'),
('conditional', 'Conditional'),
('failed', 'Failed'),
],
string='Result',
tracking=True,
)
merit_count = fields.Integer(
string='Merits',
help='Count of merit-worthy observations recorded during the '
'audit (positive findings).',
)
ncr_count = fields.Integer(
string='NCRs',
help='Non-conformance reports raised during the audit.',
)
audit_report_attachment = fields.Many2one(
'ir.attachment',
string='Audit Report',
help='Final audit report PDF.',
)
accreditation_start = fields.Date(
string='Accreditation Start',
tracking=True,
)
accreditation_end = fields.Date(
string='Accreditation End',
tracking=True,
)
state = fields.Selection(
[
('scheduled', 'Scheduled'),
('in_progress', 'In Progress'),
('report_issued', 'Report Issued'),
('closed', 'Closed'),
],
string='Status',
default='scheduled',
required=True,
tracking=True,
)
notes = fields.Html(
string='Notes',
)
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.nadcap.audit')
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_start(self):
self.write({'state': 'in_progress'})
def action_issue_report(self):
self.write({'state': 'report_issued'})
def action_close(self):
self.write({'state': 'closed'})

View File

@@ -0,0 +1,176 @@
# -*- 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 FpRisk(models.Model):
"""Risk register entry.
Implements the operational risk management requirement from AS9100
Rev D §8.1.1. Each risk gets scored on a 15 likelihood and 15
impact scale; the multiplicative score drives the level classification
(low / medium / high / critical) used for escalation and reporting.
"""
_name = 'fusion.plating.risk'
_description = 'Fusion Plating — Risk Register Entry'
_inherit = ['mail.thread', 'mail.activity.mixin']
_order = 'risk_score desc, id desc'
name = fields.Char(
string='Reference',
required=True,
copy=False,
readonly=True,
default=lambda self: self._default_name(),
tracking=True,
)
title = fields.Char(
string='Title',
required=True,
tracking=True,
)
description = fields.Html(
string='Description',
)
category = fields.Selection(
[
('operational', 'Operational'),
('supply_chain', 'Supply Chain'),
('quality', 'Quality'),
('safety', 'Safety'),
('environmental', 'Environmental'),
('financial', 'Financial'),
('customer', 'Customer'),
('regulatory', 'Regulatory'),
],
string='Category',
default='operational',
required=True,
tracking=True,
)
likelihood = fields.Selection(
[
('1', '1 — Very Low'),
('2', '2 — Low'),
('3', '3 — Medium'),
('4', '4 — High'),
('5', '5 — Very High'),
],
string='Likelihood',
default='3',
required=True,
tracking=True,
)
impact = fields.Selection(
[
('1', '1 — Very Low'),
('2', '2 — Low'),
('3', '3 — Medium'),
('4', '4 — High'),
('5', '5 — Very High'),
],
string='Impact',
default='3',
required=True,
tracking=True,
)
risk_score = fields.Integer(
string='Score',
compute='_compute_risk_score',
store=True,
help='Likelihood × Impact (125).',
)
risk_level = fields.Selection(
[
('low', 'Low'),
('medium', 'Medium'),
('high', 'High'),
('critical', 'Critical'),
],
string='Level',
compute='_compute_risk_level',
store=True,
tracking=True,
)
mitigation_plan = fields.Html(
string='Mitigation Plan',
)
owner_id = fields.Many2one(
'res.users',
string='Owner',
default=lambda self: self.env.user,
tracking=True,
)
review_date = fields.Date(
string='Next Review',
tracking=True,
)
state = fields.Selection(
[
('identified', 'Identified'),
('assessed', 'Assessed'),
('treated', 'Treated'),
('monitored', 'Monitored'),
('closed', 'Closed'),
],
string='Status',
default='identified',
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.risk')
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('likelihood', 'impact')
def _compute_risk_score(self):
for rec in self:
try:
likely = int(rec.likelihood or 0)
impact = int(rec.impact or 0)
except (TypeError, ValueError):
likely, impact = 0, 0
rec.risk_score = likely * impact
@api.depends('risk_score')
def _compute_risk_level(self):
for rec in self:
score = rec.risk_score or 0
if score >= 20:
rec.risk_level = 'critical'
elif score >= 12:
rec.risk_level = 'high'
elif score >= 6:
rec.risk_level = 'medium'
else:
rec.risk_level = 'low'
def action_assess(self):
self.write({'state': 'assessed'})
def action_treat(self):
self.write({'state': 'treated'})
def action_monitor(self):
self.write({'state': 'monitored'})
def action_close(self):
self.write({'state': 'closed'})