Piano integrazione in TopSeed

Strategia, fasi, deliverable per assorbire Semiorto Report nel gestionale

Approccio scelto: Migrazione completa in TopSeed

Dopo aver valutato 3 scenari possibili (coesistenza / integrazione a 2 UI / migrazione completa), la raccomandazione è la terza:

⭐ Migrazione completa

TopSeed diventa l'unico sistema. Il modulo Germinabilità TopSeed si espande fino a coprire tutto ciò che Semiorto fa oggi. I 62K record storici vengono migrati una tantum. Semiorto viene spento.

Perché questo scenario

Rischi

Architettura target in TopSeed

┌─ TopSeed (stack esistente) ─────────────────────────────────────────┐
│                                                                     │
│  Vanilla HTML/JS frontend                                           │
│   └ germinabilita.html                                              │
│       ├ Tab "🌱 Nuovo modulo" (implementazione nativa — NUOVO)      │
│       │   ├ /germinabilita/cerca                                    │
│       │   ├ /germinabilita/in-corso                                 │
│       │   ├ /germinabilita/da-analizzare                            │
│       │   ├ /germinabilita/analisi/{id}                             │
│       │   ├ /germinabilita/lotti                                    │
│       │   ├ /germinabilita/specie (con matrice mesi)                │
│       │   └ ...                                                     │
│       ├ Tab "📜 Germinabilità OLD" (legacy consultazione)           │
│       │   └ Iframe App completa Spring (solo durante dual-running)  │
│                                                                     │
│  PHP backend (api.php)                                              │
│   └ estensione con endpoint germinabilità:                          │
│       GET/POST/PUT/DELETE entity=test_germinabilita                 │
│       GET/POST/PUT/DELETE entity=test_germinabilita_conte           │
│       GET/POST/PUT/DELETE entity=lots (esteso)                      │
│       ...                                                           │
│   └ germ_report.php: generazione PDF schede + certificati           │
│                                                                     │
│  MySQL topseed_db (esteso)                                          │
│   ├ test_germinabilita (ALTER con 16 nuove colonne)                 │
│   ├ test_germinabilita_conte (NUOVA tabella)                        │
│   ├ specie_calendario_analisi (NUOVA)                               │
│   ├ tipologie_prova (NUOVA lookup)                                  │
│   ├ categories (ALTER con giorni/UR/latino/inglese)                 │
│   ├ seeds (esistente, usata per varietà legacy)                     │
│   ├ produttori (esistente, esteso con codice legacy)                │
│   ├ lots (ALTER con kg, provenienza, dataArrivo, ecc.)              │
│   └ users (ALTER con legacy_sha_hash, legacy_source)                │
└─────────────────────────────────────────────────────────────────────┘

4 Fasi della migrazione

Fase 0 — Setup consultazione (✅ già completata)

Fase 1 — ALTER schema TopSeed (1 sprint, 3-5 giorni)

-- Migrations TopSeed

-- 1.1 Estendere test_germinabilita
ALTER TABLE test_germinabilita
  ADD COLUMN ft VARCHAR(45) NULL,
  ADD COLUMN tipologia_seme_legacy ENUM('NATURA','SELEZIONATO','CALIBRATO',
       'FILM_COATED','PILLOLATO','TRATTATO','MULTISEME','PORTASEME','VIGORIZZATO'),
  ADD COLUMN calibratura VARCHAR(45) NULL,
  ADD COLUMN data_arrivo_laboratorio DATE NULL,
  ADD COLUMN data_inizio DATE NULL,
  ADD COLUMN scostamento ENUM('REGOLARE','IRREGOLARE'),
  ADD COLUMN totale_giorni_prova INT NULL,
  ADD COLUMN rif_numero VARCHAR(45) NULL,
  ADD COLUMN rif_data DATE NULL,
  ADD COLUMN rif_germinabilita INT NULL,
  ADD COLUMN rif_prova_laboratorio VARCHAR(45) NULL,
  ADD COLUMN germinabilita_prova_laboratorio INT NULL,
  ADD COLUMN seme_puro DOUBLE DEFAULT 100,
  ADD COLUMN materiale_inerte DOUBLE DEFAULT 0,
  ADD COLUMN altri_semi DOUBLE NULL,
  ADD COLUMN altri_semi_string VARCHAR(512) NULL,
  ADD COLUMN categoria_analisi ENUM('STANDARD','COMMERCIALE') DEFAULT 'STANDARD',
  ADD COLUMN osservazioni_purezza VARCHAR(512) NULL,
  ADD COLUMN cancella_note VARCHAR(128) NULL,
  ADD COLUMN pillole INT NULL,
  ADD COLUMN replica_analisi INT NULL COMMENT '1/2/3 numero repliche programmate',
  ADD COLUMN legacy_id INT NULL,
  ADD COLUMN source VARCHAR(32) DEFAULT 'topseed' COMMENT 'diego|topseed',
  ADD INDEX idx_legacy_id (legacy_id),
  ADD INDEX idx_source (source),
  ADD INDEX idx_ft (ft);

-- 1.2 Nuova tabella conte giornaliere (1:N)
CREATE TABLE test_germinabilita_conte (
  id INT AUTO_INCREMENT PRIMARY KEY,
  analisi_id INT NOT NULL,
  lettera CHAR(1) NOT NULL DEFAULT 'A',
  giorni_1 INT, germinati_1 INT, duri_1 INT, freschi_1 INT, anormali_1 INT, morti_1 INT,
  giorni_2 INT, germinati_2 INT, duri_2 INT, freschi_2 INT, anormali_2 INT, morti_2 INT,
  vigore_1 ENUM('SCARSO','MEDIO','OTTIMO'),
  vigore_2 ENUM('SCARSO','MEDIO','OTTIMO'),
  FOREIGN KEY (analisi_id) REFERENCES test_germinabilita(id) ON DELETE CASCADE,
  INDEX idx_analisi (analisi_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- 1.3 Tipologie prova lookup
CREATE TABLE tipologie_prova (
  id INT AUTO_INCREMENT PRIMARY KEY,
  codice VARCHAR(30) UNIQUE,
  nome VARCHAR(60),
  ordinamento INT DEFAULT 0
) ENGINE=InnoDB;
INSERT INTO tipologie_prova (codice, nome, ordinamento) VALUES
 ('PETRI','PETRI',1),('TORBA','TORBA',2),('CONT_ALV','CONTENITORI ALVEOLATI',3);

-- 1.4 Tipologie seme lookup
CREATE TABLE tipologie_seme (
  id INT AUTO_INCREMENT PRIMARY KEY,
  codice VARCHAR(30) UNIQUE,
  nome VARCHAR(60),
  ordinamento INT DEFAULT 0
) ENGINE=InnoDB;
INSERT INTO tipologie_seme (codice, nome, ordinamento) VALUES
 ('NATURA','Natura',1),('SELEZIONATO','Selezionato',2),
 ('CALIBRATO','Calibrato',3),('FILM_COATED','Film coated',4),
 ('PILLOLATO','Pillolato',5),('TRATTATO','Trattato',6),
 ('MULTISEME','Multiseme',7),('PORTASEME','Portaseme',0),
 ('VIGORIZZATO','Vigorizzato',9);

-- 1.5 Calendario analisi per specie
CREATE TABLE specie_calendario_analisi (
  id INT AUTO_INCREMENT PRIMARY KEY,
  categoria_id INT NOT NULL,           -- → categories (ex semiorto_specie)
  mese INT NOT NULL,                   -- 1-12
  tipologia_seme_id INT NOT NULL,
  UNIQUE KEY uq (categoria_id, mese, tipologia_seme_id),
  INDEX idx_categoria (categoria_id),
  INDEX idx_mese (mese)
) ENGINE=InnoDB;

-- 1.6 Estendere categories
ALTER TABLE categories
  ADD COLUMN italiano VARCHAR(60) NULL,
  ADD COLUMN inglese VARCHAR(60) NULL,
  ADD COLUMN latino VARCHAR(60) NULL,
  ADD COLUMN codice_specie VARCHAR(10) NULL,
  ADD COLUMN giorni_1_conta INT NULL,
  ADD COLUMN giorni_tot_conta INT NULL,
  ADD COLUMN ur_target INT NULL,
  ADD COLUMN note_specie VARCHAR(512) NULL,
  ADD COLUMN legacy_source VARCHAR(32) NULL,
  ADD COLUMN legacy_id INT NULL;

-- 1.7 Estendere lots
ALTER TABLE lots
  ADD COLUMN kg DOUBLE NULL,
  ADD COLUMN provenienza VARCHAR(60) NULL,
  ADD COLUMN data_arrivo DATE NULL,
  ADD COLUMN data_prossima_analisi DATE NULL,
  ADD COLUMN data_esaurito DATE NULL,
  ADD COLUMN esaurito TINYINT(1) DEFAULT 0,
  ADD COLUMN legacy_id INT NULL,
  ADD COLUMN legacy_source VARCHAR(32) NULL;

-- 1.8 Estendere users
ALTER TABLE users
  ADD COLUMN legacy_sha_hash VARCHAR(255) NULL,
  ADD COLUMN legacy_source VARCHAR(32) NULL,
  ADD COLUMN legacy_id INT NULL,
  ADD COLUMN cambia_password TINYINT(1) DEFAULT 0;

-- 1.9 Estendere produttori
ALTER TABLE produttori
  ADD COLUMN codice VARCHAR(45) NULL,
  ADD COLUMN legacy_id INT NULL,
  ADD COLUMN legacy_source VARCHAR(32) NULL;

Test di compatibilità: ALTER non-breaking. Nessun campo rimosso. Dati TopSeed esistenti non toccati.

Fase 2 — UI nuovo modulo Germinabilità (2-3 sprint)

Estendere germinabilita.html tab "🌱 Nuovo modulo" con tutte le sotto-pagine operative:

Sezione Anagrafiche
  • Specie CRUD con matrice mesi×tipologie
  • Varietà CRUD (dropdown specie)
  • Produttori CRUD (+ modal inline)
  • Tipologie seme (admin config)
Sezione Lotti
  • Lista + filtri specie/varietà/produttore/stato
  • Form crea/modifica lotto
  • Bulk "setta esauriti"
  • Dettaglio lotto con storico analisi
Sezione Analisi (workflow principale)
  • Lista "In Corso" con badge prossima conta
  • Lista "Da Analizzare" (mese corrente)
  • Form "Nuova" (seleziona lotto → crea)
  • Form esecuzione analisi (core, replica della JSP 739 righe)
  • Aggiungi / Cancella conte A/B/C/D
  • Chiudi analisi con risultato
  • Stampa scheda PDF + certificato PDF/DOCX
Sezione Amministrazione
  • Lista analisi cancellate + ripristino
  • Gestione utenti (già esistente in TopSeed)
  • Audit log (bonus: non c'era in Semiorto)

Fase 3 — Migrazione dati storici (1 sprint, 2-3 giorni)

Script migrate_semiorto_to_topseed.php. Transazione unica con rollback automatico se qualcosa fallisce.

Ordine di esecuzione

  1. Specie → categories (con merge fuzzy su italiano)
  2. Varietà → seeds (tipo OP, legacy=diego)
  3. Produttori → produttori (match fuzzy Levenshtein; nuovi con legacy_source)
  4. Tecnici → users (ruolo GENETISTA)
  5. Utenti Semiorto → users (mapping ruoli, legacy_sha_hash)
  6. Lotti → lots (risolvi FK varietà+produttore)
  7. Analisi → test_germinabilita (legacy_id, source='diego', 32 campi)
  8. Conte → test_germinabilita_conte (16 campi)
  9. Calendario specie → specie_calendario_analisi (3 campi)

Vedi Migrazione dati per lo pseudo-codice completo.

Fase 4 — Dismissione Semiorto (1 sprint breve, 2 giorni)

  1. Tutti gli utenti usano TopSeed per nuove analisi
  2. Semiorto AWS messo in read-only (disabilita scritture via intercept-url)
  3. Mantieni tab "📜 Germinabilità OLD" per consultazione → 30 giorni di safety net
  4. Dopo 30 giorni: spegni Tomcat sul server nostro, mantieni solo dump MySQL
  5. Cartella germinabilita/ in repo → archivio con README

Timeline totale

Settimana     Attività                                          Deliverable
─────────────────────────────────────────────────────────────────────────────
Ora           Fase 0 ✅ completa                                Consultazione live
Week 1        Fase 1: ALTER schema + test                       Migration files
Week 2-3      Fase 2a: UI anagrafiche + lotti                   Form funzionanti
Week 4-5      Fase 2b: UI analisi + workflow                    Feature parity
Week 6        Fase 2c: Stampe PDF + testing                     Stampe validate
Week 7        Fase 3: migrazione dati + validation              62K record importati
Week 8        Fase 4: switch utenti + observability            Sistema live
Week 9-12     Safety net (Semiorto read-only + monitoraggio)   Spegnimento finale

Dual-running strategy

Durante la Fase 2 e 3, entrambi i sistemi sono attivi. Come gestire:

  1. Anagrafiche: dal giorno della Fase 1, ogni nuova specie/varietà viene inserita in TopSeed manualmente. Script di sync bidirezionale non vale la complessità.
  2. Lotti & analisi: in Fase 2 si può continuare su Semiorto. In Fase 3, prima del "taglio", si fa import completo. Dopo il taglio, solo TopSeed.
  3. Comunicazione lab: messaggio unico "da domani tutto in TopSeed, Semiorto read-only" al giorno X.

Success criteria (zero-loss migration)

✅ Checklist finale
  • □ Tutti i 61.998 record semiorto_analisi importati (count identico a legacy)
  • □ Tutti i 109.204 record semiorto_conte importati
  • □ Tutti i 11.138 lotti importati
  • □ Tutte le 1.332 varietà importate
  • □ Tutte le 160 specie merge con TopSeed existing
  • □ Tutti i 331 produttori match / importati
  • □ Spot check 50 analisi random: campi identici
  • □ Spot check 100 calcoli germinabilità: valore identico (tolleranza ≤1%)
  • □ 5 utenti Semiorto attivi in TopSeed
  • □ Login funziona (SHA legacy rigenera bcrypt)
  • □ 3 certificati DOCX prodotti e validati visivamente
  • □ Workflow "Da Analizzare" produce gli stessi lotti legacy
  • □ Training 1h con Ana (utente solo-Laboratorio)
  • □ Rollback plan testato

Input richiesti da Diego

📬 Da chiedere
  1. Template DOCX certificato (modello-certificato-{azienda}.docx) — non nel nostro dump
  2. Credenziali SMTP (per reset password via email)
  3. Conferma comportamento generaLotto(): è dead code o feature attiva?
  4. Template Scheda Controllo PDF (classe StampaSchedaControllo — da decompilare se serve replicare)
  5. Lista azioni NON presenti in questa doc: eventuali flussi nascosti o inserimenti manuali via SQL che conosce solo lui