Files
Odoo-Modules/fusion-plating/fusion_plating_nuclear/models/fp_10cfr21_report.py
gsinghpal be611876ad changes
2026-04-12 09:09:50 -04:00

167 lines
5.5 KiB
Python

# -*- 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'})