115 lines
4.1 KiB
Python
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 |