Pagine & UI
Analisi dettagliata di ogni schermata del software — layout, campi, validazioni, azioni
- 1. Login (
accesso/login.jsp) - 2. Recupero password
- 3. Analisi — Lista (In Corso / Da Analizzare / Cancellate)
- 4. Analisi — Cerca
- 5. Analisi — Nuova (selezione lotto)
- 6. Analisi — Form esecuzione e conte (la pagina più importante)
- 7. Lotto — Lista (ricerca + setta esaurito)
- 8. Lotto — Crea / Modifica
- 9. Specie — Lista
- 10. Specie — Crea / Modifica (con matrice mesi × tipologie)
- 11. Varietà — Lista e Update
- 12. Produttore — Lista e Update
- 13. Utenti — Lista (admin)
- 14. Utente — Update (admin)
- 15. I miei dati (self)
- 16. Cambio password
1. Login (/accesso/login)
Form Bootstrap centrato. Campi: j_username, j_password. Submit POST a /j_spring_security_check. Link "Recupera Password".
Se autenticazione fallisce → redirect a /accesso/login?error. Success → redirect sempre a / (configurato always-use-default-target).
2. Recupero password (/accesso/recupera)
Form con solo campo username. Submit POST a /accesso/richiestaRecupero.
Se username esiste e ha email → azzeraPassword() genera password random, invia email, reindirizza al login con messaggio "controlla email". Altrimenti messaggio "Username non esistente" o "Email non settata".
3. Analisi — Lista
Una singola JSP analisi/lista.jsp serve 3 contesti:
/analisis/inCorso→ mostra analisi condata IS NULL/analisis/daAnalizzare→ query complessa (vedi Flussi)/amministrazione/analisis/cancellate→ analisi concancella IS NOT NULL
Colonne tabella
| Colonna | Valore | Note |
|---|---|---|
| FT | ft | link al dettaglio |
| Specie | lotto.varieta.specie.italiano | eagerly loaded |
| Varietà | lotto.varieta.nome | |
| Lotto | lotto.id | codice testuale |
| Produttore | lotto.produttore.nome | |
| Prossima operaz. | (1°) o (2°) + data | calcolata da dataInizio + specie.giorniXConta |
| Azioni | Cancella, Lotto esaurito |
Azione "Lotto esaurito" dalla lista analisi
Click → chiama /analisis/lottoEsaurito/{idLotto} → imposta esaurito=true + dataEsaurito=oggi → redirect a Da Analizzare.
Azione "Cancella"
Apre modal per inserire motivo cancellazione. Submit POST a /analisis/cancella con id + motivo. Il motivo viene salvato in semiorto_analisi.cancella. L'analisi resta in DB ma non appare più nelle liste attive.
4. Analisi — Cerca (/analisis/)
Pagina di ricerca con filtri multipli e tabella risultati. Tutti i campi sono opzionali.
Filtri disponibili
- FT (match "start with")
- Tipologia seme (dropdown da DB)
- Prova (PETRI / TORBA / CONT. ALV)
- Anni (multi-select, default ultimi 3 anni + "In corso")
- Chiusa (sì / no / tutte)
- Specie (dropdown)
- Varietà (dropdown dipendente da specie — AJAX
/varietas/specie/{id}/json) - Lotto (match "anywhere")
- Esaurito (sì / no / tutti)
Logica di esecuzione
Il service analisiService.cerca(bo) crea un oggetto Criteria Hibernate con JOIN su 5 tabelle (analisi, lotto, varieta, specie, produttore, tipologia_seme). Applica solo i filtri valorizzati. Ordina per: specie italiano ASC, varietà nome ASC, data ASC, lotto.id ASC.
All'apertura della pagina, i 3 anni più recenti sono pre-selezionati. L'utente può aggiungerne altri. Valore speciale "In corso" → WHERE data IS NULL.
5. Analisi — Nuova (/analisis/analisi/new)
Pagina di selezione lotto prima di creare l'analisi. Mostra:
- Dropdown Specie
- Lista lotti non analizzati (quelli che non hanno mai avuto un'analisi, o l'ultima è stata chiusa da tempo — logica specifica)
Click su un lotto → redirect a /analisis/lotto/{idLotto}/new che crea l'entity SemiortoAnalisi con:
ftauto-generato (max FT dell'anno + 1, formatoNNN/YY)dataArrivoLaboratorio= oggiid_lotto= lotto selezionato- Tutti gli altri campi NULL
Redirect al form di update con la nuova analisi già popolata.
6. Analisi — Form esecuzione (/analisis/analisi/{id})
La pagina più complessa del software (739 righe JSP). Gestisce tutto il ciclo di vita di una prova di germinabilità.
Struttura a 3 sezioni
- Dati prova (metadati)
- Conte giornaliere (ripetizioni A, B, C, D)
- Chiusura analisi (risultato finale, stampe)
Sezione 1 — Dati prova
| Campo | Tipo UI | Validazione | Note |
|---|---|---|---|
ft | readonly | — | Auto-generato |
| Lotto | readonly (label) | — | Codice + varietà + specie |
| Tipologia seme | dropdown | required | 9 valori |
| Prova | dropdown | required | PETRI / TORBA / CONT. ALV |
| Calibratura | text | — | |
| Categoria | dropdown | required | STANDARD / COMMERCIALE |
| Replica analisi | radio | required | 1 / 2 / 3 |
| Data arrivo lab | datepicker | required | default: oggi |
| Data inizio | datepicker | required | |
| UR % | number | 0-100 | default: specie.ur |
| Totale giorni prova | number | required | default: specie.giorniTConta |
| Seme puro % | number | 0-100, default 100 | |
| Materiale inerte % | number | 0-100, default 0 | |
| Altri semi % | number | 0-100 | |
| Oss. purezza | textarea | max 512 | |
| Osservazioni | textarea | max 512 | |
| Analisi esterna rif | gruppo | — | Numero + Data + Germ% |
| Tecnico | dropdown | required alla chiusura |
Sezione 2 — Conte giornaliere
Tabella dinamica con una riga per ogni ripetizione (lettera A, B, C, D). Due colonne principali: giorni_1 (prima conta parziale) e giorni_2 (conta finale). Per ciascuna, 5 categorie: germinati, duri, freschi, anormali, morti.
┌─ Conte giornaliere ──────────────────────────────────────────────────────────┐ │ │ │ Ripetizione A: ┌─ giorno 5 ─┬─ giorno 10 ─┐ Vigore: [SCARSO|MEDIO|OTTIMO] │ │ │ Germ: [85] │ Germ: [10 ] │ [ Cancella conta ] │ │ │ Duri: [ 2] │ Duri: [ 1 ] │ │ │ │ Fres: [ 1] │ Fres: [ 0 ] │ │ │ │ Anor: [ 1] │ Anor: [ 0 ] │ │ │ │ Mort: [ 0] │ Mort: [ 0 ] │ │ │ └────────────┴─────────────┘ │ │ │ │ Ripetizione B: ... stessa struttura ... │ │ Ripetizione C: ... │ │ Ripetizione D: ... │ │ │ │ [ + Aggiungi Conta ] (nuova lettera auto-incrementata) │ └──────────────────────────────────────────────────────────────────────────────┘
Azioni sul form
Il form supporta 4 azioni distinte tramite campo hidden azione:
Valore azione | Effetto |
|---|---|
AGGIUNGI_CONTA | Aggiunge una nuova riga di conta con lettera sequenziale (A→B→C→D) |
CANCELLA_CONTA | Rimuove una conta esistente. Se era già salvata, ID finisce in conteDaCancellare per delete nel service |
CHIUDI_ANALISI | Valida tutti i campi required, imposta data=oggi, apre sezione 3 (chiusura) |
| (vuoto / default) | Save normale: persiste i dati modificati |
Sezione 3 — Chiusura (modale o sotto-form)
| Campo | Tipo | Note |
|---|---|---|
| Data fine | readonly | Impostata a oggi automaticamente |
| Germinabilità calcolata | readonly | Somma germinati1 + germinati2 (medie) |
| Scostamento | dropdown | REGOLARE / IRREGOLARE — indica se la prova è affidabile |
| Risultato | dropdown | POSITIVO / NEGATIVO (valutazione tecnico) |
| Vigore | dropdown | Auto-calcolato media vigori, modificabile |
Azioni finali
- Salva e chiudi → persiste tutto +
datavalorizzata. L'analisi esce da "In corso" - Stampa Scheda Controllo →
GET /analisis/analisi/{id}/{azienda}/scheda→ PDF - Stampa Certificato →
GET /analisis/analisi/{id}/{azienda}/certificato→ DOCX
7. Lotto — Lista (/lottos/)
Pagina con 2 funzioni:
- Ricerca lotti (filtri: specie, varietà, codice lotto, esaurito)
- Checkbox per selezionare lotti e impostarli come esauriti (bulk action)
La POST /lottos/settaEsaurito legge dai request params tutti i campi lotto_{id}=true e imposta esaurito=true + dataEsaurito=oggi a ciascuno.
8. Lotto — Crea / Modifica (/lottos/lotto/new)
Form semplice. Campi:
| Specie * | dropdown (onChange: carica varietà via AJAX) |
| Varietà * | dropdown dipendente |
| Fornitore * | dropdown. Bottone "+" per aprire modal "Aggiungi Fornitore" inline (POST AJAX a /produttores/produttore/update/json) |
| Kg/Numero * | input numerico (doppio ruolo: quantità in kg o in numero semi) |
| Data arrivo * | datepicker |
| Lotto * | text (codice identificativo lotto, assegnato manualmente) |
Nel servizio LottoServiceImpl.generaLotto() esiste una funzione che genera un codice lotto auto-calcolato: lettera anno (A=2025, B=2026) + codice specie + codice varietà + codice produttore. Es. per un lotto di pomodoro ItalikoEx-Genovese classico da Schiavone Fernando nel 2020: F + POM + IT-EGC + SF = FPOMIT-EGCSF.
Ma il controller non lo richiama mai. Il form chiede il lotto come input libero. Forse era feature prevista ma non finita. Da verificare con Diego, o ignorare.
Gestione duplicati
Se il codice lotto esiste già, il service lancia messaggio "Il lotto esiste già, vuoi creare un lotto con lo stesso nome?" + abilita checkbox forza=true. Al secondo submit, procede con duplicato.
9. Specie — Lista (/species/)
Tabella con tutte le specie. Colonne: Italiano, Inglese, Latino, Codice, Giorni 1ᵃ conta, Giorni totali, UR%, Azioni (Modifica / Elimina).
10. Specie — Crea / Modifica (/species/specie/new o /specie/{id})
Form standard + matrice di configurazione mesi × tipologie seme. Campi base:
- Italiano * / Inglese * / Latino *
- Codice (es. "POM")
- Note
- Giorni 1ª conta * (int, es. 5)
- Giorni fine conta * (int, es. 10)
- UR % * (int, es. 30)
Matrice ripetizione analisi (unica dell'applicazione)
Natura Selez. Calibr. FilmC. Pillol. Trattato ... Gennaio [ ] [ ] [ ] [ ] [ ] [ ] [ ] Febbraio [ ] [X] [ ] [ ] [ ] [ ] [ ] Marzo [ ] [ ] [X] [ ] [ ] [ ] [ ] Aprile [ ] [ ] [ ] [ ] [ ] [ ] [ ] Maggio [X] [ ] [ ] [ ] [ ] [ ] [ ] ← "ogni Maggio riesegui Giugno [ ] [ ] [ ] [ ] [ ] [ ] [ ] analisi su tipologia Natura" ...
Per ogni cella (mese, tipologia) spuntata, viene creato un record in semiorto_map_specie_analisi_ripetizione_tipologia_seme. Questo alimenta il flusso "Da Analizzare" (vedi Flussi).
11. Varietà — Lista e Update
Lista
Filtrabile per specie (dropdown + link dalla pagina specie). Mostra nome, codice, specie, n° lotti.
Update (/varietas/varieta/{id})
Form semplice con: Specie (dropdown), Nome *, Codice.
12. Produttore — Lista e Update
Lista
Tabella con Nome, Codice, Lotti attivi. Click → edit.
Update
Form: Nome * (uppercase automatico), Codice * (uppercase automatico). Validazione duplicati via DuplicateException.
Endpoint AJAX /produttores/produttore/update/json: usato dal form lotto per aggiungere produttore inline nel modal.
13. Utenti — Lista (/amministrazione/utenti)
Solo Amministrazione. Tabella: Username, Nome, Email, Permessi, [Modifica].
14. Utente — Update (/amministrazione/utente/{id})
Form:
- Nome * / Cognome *
- Username * (readonly in modifica, editabile in creazione)
- Email *
- Stato: ATTIVO / NON ATTIVO
- Permessi: checkbox multipli (Amministrazione, Laboratorio, Magazzino)
Bottoni: [Invia] + [Resetta password] (solo su utente esistente). Reset → azzeraPassword() → nuova random + email.
15. I miei dati (/utenti/myself)
Lettura dati propri + cambio password. L'utente vede i propri dati (username, nome, email). Submit POST a /utenti/utente/update.
Se l'utente cambia un suo campo → logout forzato + nuovo login.
16. Cambio password (/utente/cambioPassword)
Pagina forzata quando utente.cambiaPassword=true.
Form: Vecchia password, Nuova password, Conferma. Submit POST a /utenti/myself/cambiaPassword. Dopo salvataggio → logout forzato → re-login con nuova.