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

177 lines
4.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- 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'})