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>
70 lines
3.1 KiB
SQL
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;
|