[FEAT] Modulo Controlli periodici (control monitoring §9.1/A.8.16) — v1.23.0

Registro controlli ricorrenti (owner/frequenza/metodo/controllo SoA-NIS2 collegato)
+ registro esecuzioni come EVIDENZA (data/esito/note) con avanzamento automatico
della scadenza; da esito non conforme generazione NC o NC+azione correttiva
(riuso non_conformities/capa_actions, nuova source 'monitoring'); report
scheda+storico stampabile; scadenze nel Calendario unico.

mig.057: periodic_controls + periodic_control_executions (FK CASCADE, UNIQUE
(organization_id, code)). PeriodicControlController (slug periodic-controls) +
controlli-periodici.html + CalendarController.srcPeriodicControls.

Fix da flotta di verifica avversariale (9 finding confermati):
- advance(): correzione overflow strtotime '+1 month' (31/01 -> 28/02, no salto
  mese) via DateTimeImmutable con clamp all'ultimo giorno valido (mensile/
  trimestrale/semestrale/annuale); giornaliero/settimanale/custom invariati.
- create(): retry-on-duplicate del codice CTL-NNN con UNIQUE (org_id, code).
- update(): array_key_exists per azzerare owner_role_id / next_due_date.
- delete(): rimossa cleanup morta su review_schedule (il calendario legge diretto).
- CalendarController.srcReviewSchedule: esclude internal_audit/stakeholder_activity
  (gia' con sorgente diretta) -> fix doppia comparsa nel calendario.
- calendario.html: TYPE_META 'periodic_control' (chip filtro + label + colore).

Additivo. Cache-buster ?v= bump (sidebar) + sw cache nis2-shell-v1.23.0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
DevEnv nis2-agile
2026-06-17 09:21:03 +02:00
co-authored by Claude Opus 4.8
parent 0738504fdd
commit 4fdeae7cee
52 changed files with 1043 additions and 169 deletions
+8 -7
View File
@@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<title>Calendario scadenze - NIS2 Agile</title>
<link rel="stylesheet" href="/vendor/bootstrap-italia/dist/css/bootstrap-italia.min.css">
<link rel="stylesheet" href="/css/style.css?v=20260630">
<link rel="stylesheet" href="/css/style.css?v=20260631">
<style>
.cal-intro { background:#eff6ff; border-left:4px solid var(--primary,#2563eb); padding:14px 18px; border-radius:8px; margin-bottom:12px; font-size:.92rem; line-height:1.6; }
.cal-note { font-size:.82rem; color:#3730a3; background:#eef2ff; border:1px solid #c7d2fe; border-radius:8px; padding:10px 12px; margin:0 0 16px; }
@@ -151,12 +151,12 @@
</div>
</div>
<script src="/js/api.js?v=20260630"></script>
<script src="/js/common.js?v=20260630"></script>
<script src="/js/api.js?v=20260631"></script>
<script src="/js/common.js?v=20260631"></script>
<script src="/vendor/bootstrap-italia/dist/js/bootstrap-italia.bundle.min.js"></script>
<script src="/js/common-bi.js?v=20260630"></script>
<script src="/js/i18n.js?v=20260630"></script>
<script src="/js/help.js?v=20260630"></script>
<script src="/js/common-bi.js?v=20260631"></script>
<script src="/js/i18n.js?v=20260631"></script>
<script src="/js/help.js?v=20260631"></script>
<script>
'use strict';
/*
@@ -186,7 +186,8 @@
stakeholder_activity: { label: 'Attivita stakeholder', color: '#0d9488' },
review_schedule: { label: 'Scadenziario revisioni', color: '#4f46e5' },
internal_audit: { label: 'Audit interno', color: '#9333ea' },
management_review_decision: { label: 'Decisione riesame', color: '#0369a1' }
management_review_decision: { label: 'Decisione riesame', color: '#0369a1' },
periodic_control: { label: 'Controllo periodico', color: '#65a30d' }
};
var STATUS_META = {
overdue: { label: 'In ritardo', color: '#dc2626' },