101 lines
3.1 KiB
Python
101 lines
3.1 KiB
Python
from backend.core.models import DocumentRiskControl
|
|
from backend.core.utils import calculate_aggregate_likelihood, calculate_aggregate_weight, map_weight_to_impact_likelihood
|
|
|
|
|
|
def risk_matrix_table():
|
|
likelihood_labels = [
|
|
"Almost Certain (90-100%) (5)",
|
|
"Probable (51-89%) (4)",
|
|
"Possible (25-50%) (3)",
|
|
"Unlikely (11-24%) (2)",
|
|
"Rare (0-10%) (1)"
|
|
]
|
|
|
|
impact_labels = [
|
|
"Insignificant (1)",
|
|
"Significant (2)",
|
|
"Severe (3)",
|
|
"Material (4)",
|
|
"Major (5)"
|
|
]
|
|
|
|
color_mapping = {
|
|
"Very Low": "lightgreen",
|
|
"Low": "green",
|
|
"Medium": "yellow",
|
|
"High": "orange",
|
|
"Critical": "red"
|
|
}
|
|
|
|
def get_label(score):
|
|
if score <= 2:
|
|
return "Very Low"
|
|
elif score <= 4:
|
|
return "Low"
|
|
elif score <= 10:
|
|
return "Medium"
|
|
elif score <= 16:
|
|
return "High"
|
|
else:
|
|
return "Critical"
|
|
|
|
table_matrix_risk = [["Likelihood ↓ / Impact →"] + impact_labels]
|
|
|
|
for likelihood in range(5, 0, -1):
|
|
row = [likelihood_labels[5 - likelihood]]
|
|
for impact in range(1, 6):
|
|
score = likelihood * impact
|
|
label = get_label(score)
|
|
color_class = color_mapping[label]
|
|
row.append((score, label, color_class))
|
|
table_matrix_risk.append(row)
|
|
|
|
return table_matrix_risk
|
|
|
|
def get_risk_table(document):
|
|
risks = (
|
|
DocumentRiskControl.objects
|
|
.filter(document=document)
|
|
.values('risk', 'risk__risk_name')
|
|
.distinct()
|
|
)
|
|
|
|
risks_with_controls = []
|
|
|
|
for risk_entry in risks:
|
|
risk = {
|
|
'id': risk_entry['risk'],
|
|
'name': risk_entry['risk__risk_name']
|
|
}
|
|
|
|
controls = (
|
|
DocumentRiskControl.objects
|
|
.filter(document=document, risk_id=risk['id'])
|
|
.values('control', 'control__name', 'weight', 'likelihood')
|
|
.distinct()
|
|
)
|
|
max_weight = 10*5
|
|
total_weight = calculate_aggregate_weight(controls)
|
|
total_likelihood = calculate_aggregate_likelihood(controls)
|
|
impact, likelihood = map_weight_to_impact_likelihood(total_weight, total_likelihood, max_weight)
|
|
r_impact = round(impact)
|
|
r_likelihood = round(likelihood)
|
|
residua_impact = r_impact - 1 if r_impact > 2 else r_impact
|
|
residual_likelihood = r_likelihood - 1 if r_likelihood > 2 else r_likelihood
|
|
risks_with_controls.append({
|
|
'risk': risk,
|
|
'controls': list(controls),
|
|
'total_weight': total_weight,
|
|
'impact': impact,
|
|
'likelihood': likelihood,
|
|
'r_impact': r_impact,
|
|
'r_likelihood': r_likelihood,
|
|
'risk_score': r_impact * r_likelihood,
|
|
'residual_impact': residua_impact,
|
|
'residual_likelihood': residual_likelihood,
|
|
'residual_risk_score': residua_impact * residual_likelihood,
|
|
})
|
|
risks_with_controls.sort(key=lambda x: x['risk_score'], reverse=True)
|
|
|
|
return risks_with_controls
|