Files
old-riskletpy/backend/core/tables.py
2025-08-14 14:08:34 +02:00

115 lines
4.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():
impact_labels = [
"Insignificant (1)",
"Significant (2)",
"Severe (3)",
"Material (4)",
"Major (5)"
]
header = ["Likelihood ↓ / Impact →"] + impact_labels
matrix = [
["Almost Certain (5)",
(5, "bg-medium"), (10, "bg-high"), (15, "bg-critical"), (20, "bg-critical"), (25, "bg-critical")
],
["Likely (4)",
(4, "bg-low"), (8, "bg-medium"), (12, "bg-high"), (16, "bg-high"), (20, "bg-critical")
],
["Probable (3)",
(3, "bg-low"), (6, "bg-low"), (9, "bg-medium"), (12, "bg-high"), (15, "bg-high")
],
["Unlikely (2)",
(2, "bg-very-low"), (4, "bg-low"), (6, "bg-medium"), (8, "bg-medium"), (10, "bg-medium")
],
["Rare (1)",
(1, "bg-very-low"), (2, "bg-very-low"), (3, "bg-low"), (4, "bg-low"), (5, "bg-medium")
],
]
table = [header] + matrix
return table
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__subcategory', 'control__function', '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
def get_safeguard_summary_table(risks_with_controls):
from collections import Counter
from backend.core.models import Control
safeguard_counter = Counter()
safeguard_names = {}
for risk in risks_with_controls:
for control in risk.get('controls', []):
control_id = control.get('control')
subc = control.get('control__subcategory') or ''
func = control.get('control__function') or ''
label = f"{subc} - {func}".rstrip(" -")
if control_id:
safeguard_counter[control_id] += 1
safeguard_names[control_id] = label
summary = []
controls = Control.objects.filter(id__in=safeguard_counter.keys())
controls_map = {c.id: c for c in controls}
for control_id, count in safeguard_counter.items():
control = controls_map.get(control_id)
summary.append({
'id': control_id,
'subcategory': control.subcategory if control else '',
'category': control.category if control else '',
'function': control.function if control else '',
'name': safeguard_names.get(control_id, ''),
'count': count,
})
summary.sort(key=lambda x: x['count'], reverse=True)
return summary