nis2-agile/docs/sql/035_migrate_027_to_campaigns.sql
DevEnv nis2-agile aa2db4c6c2 [DOCS] Design modulo questionari fornitori + portale OTP + AI consulente normativo
Pacchetto di design completo (nessun codice applicato, nessuna migrazione eseguita):
- DESIGN aggiornato con 5 review agenti + 3 decisioni utente + pilastro AI consulente (sez. 12-14)
- docs/supplier-portal/template-nis2-base.questions.json: 26 domande GV.SC (Allegato 2 ACN) con nis2_ref/vuln_flag e fonti certe verbatim
- docs/supplier-portal/AI_CONSULENTE_NORMATIVO.md: corpus normativo aggiornato + persona consulente (modello TRPG)
- docs/supplier-portal/UX_MINI_SPEC.md: mini-spec portale fornitore (stati/copy/autosave/mobile/a11y/editor no-code)
- docs/sql/032-035: migrazioni idempotenti proposte (modulo, suppliers, portale auth, migrazione 027->campaigns)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 09:53:07 +02:00

70 lines
3.1 KiB
SQL

-- ============================================================================
-- Migration 035 - Migrazione dati supplier_questionnaires (027) -> campaigns
-- ----------------------------------------------------------------------------
-- PROPOSTA DI DESIGN (NON ancora applicata). Da eseguire PER ULTIMA su host MySQL.
--
-- Travasa le righe di supplier_questionnaires (mig 027) in
-- questionnaire_campaigns (mig 032), preservando i token sq_ gia inviati:
-- token_hash (027) -> access_token_hash (032) [stesso SHA-256]
-- status (027: sent|completed|expired) -> status (032 ENUM esteso)
-- answers/score/risk_level/email/date -> mappatura 1:1
--
-- Idempotente: INSERT ... SELECT con anti-join su access_token_hash (UNIQUE),
-- quindi rilanciabile senza duplicare. template_id resta NULL (legacy).
-- 027 NON viene droppata: resta read-only/deprecata per audit storico.
--
-- DIPENDE da: 032 (questionnaire_campaigns deve esistere) e 027.
-- mysql -h localhost nis2_agile_db -e "source docs/sql/035_migrate_027_to_campaigns.sql"
--
-- Ordine globale: 032 -> 033 -> 034 -> 035.
-- ============================================================================
DELIMITER //
DROP PROCEDURE IF EXISTS _mig035 //
CREATE PROCEDURE _mig035()
BEGIN
IF EXISTS (SELECT 1 FROM information_schema.TABLES
WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='supplier_questionnaires')
AND EXISTS (SELECT 1 FROM information_schema.TABLES
WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='questionnaire_campaigns')
THEN
INSERT INTO questionnaire_campaigns
(organization_id, supplier_id, template_id, template_version,
access_token_hash, status, score, risk_level, answers,
sent_to_email, sent_at, completed_at, expires_at, created_at)
SELECT
sq.organization_id,
sq.supplier_id,
NULL AS template_id,
NULL AS template_version,
sq.token_hash AS access_token_hash,
CASE sq.status
WHEN 'sent' THEN 'sent'
WHEN 'completed' THEN 'completed'
WHEN 'expired' THEN 'expired'
ELSE 'sent'
END AS status,
sq.score,
sq.risk_level,
sq.answers,
sq.sent_to_email,
sq.sent_at,
sq.completed_at,
sq.expires_at,
sq.created_at
FROM supplier_questionnaires sq
LEFT JOIN questionnaire_campaigns qc
ON qc.access_token_hash = sq.token_hash
WHERE qc.id IS NULL; -- anti-join: salta quelle gia migrate (idempotenza)
END IF;
END //
DELIMITER ;
CALL _mig035();
DROP PROCEDURE IF EXISTS _mig035;
-- ROLLBACK (manuale): cancella SOLO le campagne legacy importate (template_id NULL,
-- token corrispondente in supplier_questionnaires). NON tocca le campagne native.
-- DELETE qc FROM questionnaire_campaigns qc
-- JOIN supplier_questionnaires sq ON sq.token_hash = qc.access_token_hash
-- WHERE qc.template_id IS NULL;