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:
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
- Evita duplicazioni (anagrafiche, utenti, lotti)
- Permette integrazione nativa con moduli TopSeed esistenti: contratti, ispezioni, pagamenti
- UI moderna (Bootstrap 5 / design TopSeed) → migliore UX
- Estensibilità: notifiche email/WA, audit log, multi-azienda
- Single source of truth per l'admin
Rischi
- Dual-running period durante la migrazione → comunicazione puntuale al lab
- Rehash password (SHA→bcrypt) → messaggio reset agli utenti
- Training minimo per chi è abituato alla UI Bootstrap 3
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)
- ✅ Docker Tomcat 7 + MySQL 5.7 sul server aaPanel
- ✅ Nginx reverse-proxy
/germinabilita-old/→ 127.0.0.1:8085 - ✅ App Spring completa (ROOT) deployata
- ✅
germ_old_api.php: 13 endpoint PHP read-only sul DB legacy - ✅ UI tab "Germinabilità OLD" con 9 sotto-tab + iframe app completa
- ✅ Pulsante sync manuale AWS → locale
- ✅ Dossier tecnico completo (questo portale)
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:
- Specie CRUD con matrice mesi×tipologie
- Varietà CRUD (dropdown specie)
- Produttori CRUD (+ modal inline)
- Tipologie seme (admin config)
- Lista + filtri specie/varietà/produttore/stato
- Form crea/modifica lotto
- Bulk "setta esauriti"
- Dettaglio lotto con storico analisi
- 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
- 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
- Specie → categories (con merge fuzzy su
italiano) - Varietà → seeds (tipo OP, legacy=diego)
- Produttori → produttori (match fuzzy Levenshtein; nuovi con legacy_source)
- Tecnici → users (ruolo GENETISTA)
- Utenti Semiorto → users (mapping ruoli, legacy_sha_hash)
- Lotti → lots (risolvi FK varietà+produttore)
- Analisi → test_germinabilita (legacy_id, source='diego', 32 campi)
- Conte → test_germinabilita_conte (16 campi)
- Calendario specie → specie_calendario_analisi (3 campi)
Vedi Migrazione dati per lo pseudo-codice completo.
Fase 4 — Dismissione Semiorto (1 sprint breve, 2 giorni)
- Tutti gli utenti usano TopSeed per nuove analisi
- Semiorto AWS messo in read-only (disabilita scritture via intercept-url)
- Mantieni tab "📜 Germinabilità OLD" per consultazione → 30 giorni di safety net
- Dopo 30 giorni: spegni Tomcat sul server nostro, mantieni solo dump MySQL
- 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:
- Anagrafiche: dal giorno della Fase 1, ogni nuova specie/varietà viene inserita in TopSeed manualmente. Script di sync bidirezionale non vale la complessità.
- 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.
- Comunicazione lab: messaggio unico "da domani tutto in TopSeed, Semiorto read-only" al giorno X.
Success criteria (zero-loss migration)
- □ Tutti i 61.998 record
semiorto_analisiimportati (count identico a legacy) - □ Tutti i 109.204 record
semiorto_conteimportati - □ 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
- Template DOCX certificato (
modello-certificato-{azienda}.docx) — non nel nostro dump - Credenziali SMTP (per reset password via email)
- Conferma comportamento
generaLotto(): è dead code o feature attiva? - Template Scheda Controllo PDF (classe
StampaSchedaControllo— da decompilare se serve replicare) - Lista azioni NON presenti in questa doc: eventuali flussi nascosti o inserimenti manuali via SQL che conosce solo lui