Files
MartinandClaude Fable 5 668e587881 Iteration 4 (Maßnahmen) + Risikoanalyse nachgeschärft
Risikoanalyse:
- Risiko direkt aus dem Asset-Popup erstellbar ("+ Risiko erstellen"
  → Anlege-Popup mit vorverknüpftem Asset)
- Brutto-/Rest-Risiko detailliert: Eintrittswahrscheinlichkeit und
  Schaden als beschriftete Werte (X × Y = Score-Pille)
- Rest-Risiko wird NICHT mehr manuell erfasst, sondern automatisch aus
  den verknüpften Maßnahmen berechnet (Minderung je Dimension, Summe,
  Untergrenze 1; src/server/risk-calc.ts); Neuberechnung bei jeder
  Änderung an Bewertung oder Maßnahmen-Verknüpfungen
- Risikoregister unterhalb der Heatmap in voller Breite

Maßnahmen-Modul (SPEC §4.4):
- Measure/RiskMeasure-Schema mit RLS, laufende Nummer (M-001),
  Status/Priorität/Owner/Fälligkeit
- Kanban-Board mit Drag-and-Drop (dnd-kit): Karten zwischen Offen /
  In Umsetzung / Erledigt verschieben aktualisiert den Status per
  Server-Action inkl. Audit-Log; überfällige Karten rot markiert
- Maßnahmen-Popups (Detail read-only / Bearbeiten / Anlegen) nach
  App-Muster; Detail zeigt verknüpfte Risiken mit Minderung
- Im Risiko-Bearbeiten: bestehende Maßnahme verknüpfen ODER neue
  Maßnahme direkt anlegen & verknüpfen (jeweils mit Minderung
  Wahrscheinlichkeit/Schaden); "Notwendige Maßnahmen" im Risiko-Detail
  jetzt echt
- Seed: 4 Beispiel-Maßnahmen, Rest-Risiken daraus berechnet

Verifiziert im Browser: DnD-Statuswechsel (beide Richtungen, Audit-
Einträge), Rest-Risiko-Berechnung (R-001: 4×5=20 → 2×4=8), Risiko-
Anlage aus dem Asset inkl. automatischer Verknüpfung.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 16:07:59 +02:00

60 lines
2.0 KiB
SQL

-- CreateEnum
CREATE TYPE "MeasureStatus" AS ENUM ('OPEN', 'IN_PROGRESS', 'DONE');
-- CreateEnum
CREATE TYPE "MeasurePriority" AS ENUM ('LOW', 'MEDIUM', 'HIGH');
-- CreateTable
CREATE TABLE "measures" (
"id" TEXT NOT NULL,
"tenant_id" TEXT NOT NULL,
"ref_no" INTEGER NOT NULL,
"title" TEXT NOT NULL,
"description" TEXT,
"status" "MeasureStatus" NOT NULL DEFAULT 'OPEN',
"priority" "MeasurePriority" NOT NULL DEFAULT 'MEDIUM',
"owner_id" TEXT,
"due_date" TIMESTAMP(3),
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3) NOT NULL,
"created_by" TEXT,
CONSTRAINT "measures_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "risk_measures" (
"id" TEXT NOT NULL,
"tenant_id" TEXT NOT NULL,
"risk_id" TEXT NOT NULL,
"measure_id" TEXT NOT NULL,
"reduction_likelihood" INTEGER NOT NULL DEFAULT 0,
"reduction_impact" INTEGER NOT NULL DEFAULT 0,
CONSTRAINT "risk_measures_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE INDEX "measures_tenant_id_idx" ON "measures"("tenant_id");
-- CreateIndex
CREATE INDEX "measures_tenant_id_status_idx" ON "measures"("tenant_id", "status");
-- CreateIndex
CREATE UNIQUE INDEX "measures_tenant_id_ref_no_key" ON "measures"("tenant_id", "ref_no");
-- CreateIndex
CREATE INDEX "risk_measures_tenant_id_idx" ON "risk_measures"("tenant_id");
-- CreateIndex
CREATE UNIQUE INDEX "risk_measures_risk_id_measure_id_key" ON "risk_measures"("risk_id", "measure_id");
-- AddForeignKey
ALTER TABLE "measures" ADD CONSTRAINT "measures_owner_id_fkey" FOREIGN KEY ("owner_id") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "risk_measures" ADD CONSTRAINT "risk_measures_risk_id_fkey" FOREIGN KEY ("risk_id") REFERENCES "risks"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "risk_measures" ADD CONSTRAINT "risk_measures_measure_id_fkey" FOREIGN KEY ("measure_id") REFERENCES "measures"("id") ON DELETE CASCADE ON UPDATE CASCADE;