[FEAT] #384 p.2.2/3 — colonne multi-valore + link attivi bidirezionali Policy<->Misure e Requisiti

Misure e Requisiti: colonna Policy (default) mostra tutte le policy collegate al
requisito come codici Policy.NN cliccabili -> aprono la policy (policies.html?policy=ID).
Policy: colonna Requisito NIS2 mostra tutti i requisiti collegati (codifica MISURA+
REQUISITO, es. 'DE.CM-01 comma 1.') come link -> evidenziano il requisito
(misure-requisiti.html?requisito=ID). Backend: FrameworkController::catalog espone
policies[] per requisito e PolicyController::list espone requisiti[] per policy
(org-scoped, tabella requisito_policy mig.059, try/catch con degrado al dato di default).
Solo lettura/visualizzazione: nessuna modifica dati, nessuna migrazione.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
DevEnv nis2-agile
2026-06-18 19:25:16 +02:00
co-authored by Claude Opus 4.8
parent 02f3e69227
commit cb238e8380
5 changed files with 114 additions and 5 deletions
@@ -52,6 +52,35 @@ class PolicyController extends BaseController
$params
);
// Ticket #384 p.2.2/p.3 — requisiti collegati a ciascuna policy (M:N org-scoped,
// tabella requisito_policy mig.059). Il codice mostrato e' la concatenazione
// MISURA + REQUISITO (spec 2.2). try/catch: degrada al solo nis2_article se assente.
try {
$reqRows = Database::fetchAll(
'SELECT rp.policy_id, q.id AS requisito_id, q.misura_code, q.requisito_code
FROM requisito_policy rp
JOIN cfg_nis2_requisiti q ON q.id = rp.requisito_id
WHERE rp.organization_id = ?
ORDER BY q.misura_code, q.n, q.id',
[$this->getCurrentOrgId()]
);
$reqByPolicy = [];
foreach ($reqRows as $r) {
$reqByPolicy[(int) $r['policy_id']][] = [
'id' => (int) $r['requisito_id'],
'misura_code' => $r['misura_code'],
'requisito_code' => $r['requisito_code'],
'code' => trim(($r['misura_code'] ?? '') . ' ' . ($r['requisito_code'] ?? '')),
];
}
foreach ($policies as &$pol) {
$pol['requisiti'] = $reqByPolicy[(int) $pol['id']] ?? [];
}
unset($pol);
} catch (\Throwable $e) {
error_log('[PolicyController] requisiti per policy (org ' . $this->getCurrentOrgId() . '): ' . $e->getMessage());
}
$this->jsonSuccess($policies);
}