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 = [ "Certain (90-100%)", "Almost Certain (80-89%)", "Very Probable (70-79%)", "Probable (60-69%)", "Highly Likely (50-59%)", "Likely (40-49%)", "Occasional (30-39%)", "Possible (20-29%)", "Unlikely (10-19%)", "Rare (0-9%)" ] impact_labels = [ "Insignificant", "Minor", "Moderate", "Major", "Severe", "Catastrophic", "Critical", "Extreme", "Disastrous", "Unrecoverable" ] color_mapping = { "Very Low": "green", "Low": "lightgreen", "Medium": "yellow", "High": "orange", "Critical": "red" } table_matrix_risk = [["Impact ↓ / Likelihood →"] + impact_labels] for likelihood_index, likelihood_label in enumerate(likelihood_labels, start=1): reversed_index = 11 - likelihood_index row = [likelihood_label] for impact_index in range(1, 11): score = reversed_index * impact_index if score <= 20: label = "Very Low" elif score <= 40: label = "Low" elif score <= 60: label = "Medium" elif score <= 80: label = "High" else: label = "Critical" 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*10 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