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