import type { TenantDb } from "./db"; /** * Rest-Risiko-Berechnung (SPEC §4.2): Das Rest-Risiko wird NICHT manuell * gepflegt, sondern ergibt sich aus den verknüpften Maßnahmen. Jede * Verknüpfung trägt eine erwartete Minderung (0,00–4,00) je Dimension — * bewusst dezimal: oft senkt erst die Summe mehrerer Maßnahmen eine * Dimension um einen vollen Punkt. Die Minderungen werden summiert und * von der Brutto-Bewertung abgezogen (Untergrenze 1). Ohne Maßnahmen * gibt es kein Rest-Risiko (null). */ const round2 = (v: number) => Math.round(v * 100) / 100; export async function recomputeResidualRisk(db: TenantDb, riskId: string) { const risk = await db.risk.findUnique({ where: { id: riskId }, include: { riskMeasures: { select: { reductionLikelihood: true, reductionImpact: true } } }, }); if (!risk) return; if (risk.riskMeasures.length === 0) { await db.risk.update({ where: { id: riskId }, data: { residualLikelihood: null, residualImpact: null, residualScore: null }, }); return; } const reductionL = risk.riskMeasures.reduce((s, m) => s + m.reductionLikelihood, 0); const reductionI = risk.riskMeasures.reduce((s, m) => s + m.reductionImpact, 0); const residualLikelihood = round2(Math.max(1, risk.likelihood - reductionL)); const residualImpact = round2(Math.max(1, risk.impact - reductionI)); await db.risk.update({ where: { id: riskId }, data: { residualLikelihood, residualImpact, residualScore: round2(residualLikelihood * residualImpact), }, }); }