Panoramica

TIMS (TiLog Information Management System) è un'applicazione web per la gestione di magazzino, ordini e anagrafiche. Funziona come un pannello di visualizzazione e gestione dati connesso al database SQL Server EMS_Premi.

Cosa puoi fare con TIMS

Visualizzare — Tutti i dati di magazzino (movimenti, giacenza, locazioni), anagrafiche (articoli, clienti/fornitori), ordini in ingresso e in uscita, configurazioni di sistema.

Filtrare — Ogni colonna è filtrabile. Filtri testuali, numerici e booleani. Ricerca globale su tutti i campi.

Modificare — I campi contrassegnati come "editabili" nella configurazione possono essere aggiornati direttamente dall'interfaccia (solo utenti livello 50+).

Esportare — Ogni griglia è esportabile in Excel (XLSX), PDF, o condivisibile via WhatsApp. L'export riguarda sempre i dati filtrati/visibili, non l'intero dataset.

Gestire ordini — Le viste ordini in ingresso e in uscita usano il layout master-detail: testata espandibile con righe di dettaglio. Azioni massive come "Chiudi Ordini" disponibili tramite bottoni custom.


Architettura file

Struttura del progetto e ruolo di ogni componente.

File / CartellaRuolo
login.phpPagina di login (3 campi: username, password, codSoc)
index.phpInterfaccia principale (SPA-like): header, sidebar, griglia, modali
config/database.jsonCuore della configurazione: connessione DB, definizione query, campi, regole
config/config.phpConfigurazione PHP (caricamento database.json, funzione log)
includes/Auth.phpClasse autenticazione: login, sessione, controllo livelli, permessi scrittura, caricamento preferenze griglia
includes/Database.phpClasse connessione PDO al SQL Server (singleton). Carica credenziali da C:\inetpub\config_secure\ o da config/db_connection.json
includes/Query.phpClasse per trovare query nella config, eseguire con filtro codSoc, rimuovere colonne NULL
includes/Features.phpFeature flags per codSoc: abilita/disabilita funzionalità specifiche per società. Legge C:\inetpub\config_secure\features_config.php
includes/Encoding.phpConversione encoding Windows-1252 → UTF-8 per risolvere problemi di caratteri speciali con SQL Server collation Latin1_General_CI_AS
api/auth.phpAPI login/logout (POST JSON)
api/data.phpAPI CRUD principale: list, get, update (con filtri, paginazione, ordinamento SQL)
api/menu.phpAPI che restituisce i gruppi e query visibili per il menu sidebar
api/ordini.phpAPI per caricare i dettagli (righe) di ordini master-detail
api/custom_action.phpAPI per eseguire le azioni dei bottoni custom (SQL o API call)
assets/js/app.jsLogica principale frontend: caricamento menu, rendering griglia, filtri, paginazione, editing, heartbeat sessione
assets/js/grid-preferences.jsPersonalizzazione colonne: modal drag-drop per riordinare/nascondere colonne. Salva preferenze in DB (TimsUserGridPreferences)
assets/js/master-detail.jsLogica espansione/compressione righe master-detail, cache dettagli in memoria
assets/js/export.jsLogica export: Excel (SheetJS), PDF (jsPDF), WhatsApp. Legge dati dal DOM.
assets/css/styles.cssStili principali (tema dark completo)
assets/css/filters-fix.cssFix specifici per il layout filtri (label a sinistra, sticky header/footer)
printflow/Modulo stampa template (DDT, etichette, ecc.)
logs/File di log applicazione

Login

TIMS utilizza un sistema di login a 3 campi. Tutti i campi sono obbligatori.

Campi di accesso
CampoDescrizioneNote
UsernameNome utente registrato nella tabella AnUtentiCampo Login
PasswordPassword dell'utenteCampo Password, min 4 caratteri
Codice SocietàIdentifica la società/azienda a cui appartieniCampo codSoc, convertito in MAIUSCOLO
Lockout: Dopo 5 tentativi falliti l'account viene bloccato per 5 minuti. La sessione scade dopo 1 ora di inattività (il timer si resetta ad ogni operazione).
login.php
api/auth.php
Verifica AnUtenti
Sessione PHP
index.php

Interfaccia principale

Dopo il login si accede a index.php, che è un'applicazione single-page con 4 zone principali:

1. Header (barra superiore)

Contiene il toggle sidebar (hamburger), il titolo della pagina/query corrente, le informazioni utente (nome, codSoc, livello), il link a PrintFlow, e il bottone Logout.

2. Sidebar (pannello sinistro)

Mostra i gruppi di query (Magazzino, Anagrafiche, Spedizioni, Configurazione) con le singole query cliccabili. Ha una barra di ricerca in alto per filtrare le voci del menu. La sidebar è collassabile su mobile.

3. Area centrale (griglia dati)

La zona principale dove vengono mostrati i dati della query selezionata. Include: barra azioni (Aggiorna, Nuovo, Esporta, Filtri), pannello filtri (collassabile), tabella dati con header ordinabili, e paginazione in fondo.

4. Modali

Finestre modali per il dettaglio/modifica di un record. Si aprono cliccando su una riga (o sull'icona modifica nelle master-detail). Contengono un form con campi editabili e readonly, e bottoni Annulla/Salva.

Welcome screen: All'apertura, prima di selezionare qualsiasi query, viene mostrata una schermata di benvenuto con il messaggio "Seleziona una query dalla sidebar".


Griglia dati

Il cuore dell'applicazione. Ogni query produce una tabella interattiva.

Caratteristiche

Header colonne cliccabili — Clicca sull'intestazione di una colonna per ordinare i dati (l'ordinamento avviene lato SQL, non lato client, per efficienza con grandi dataset).

Paginazione dinamica con Ellipsis — Di default 50 righe per pagina (configurabile con rows_per_page). Navigazione: bottoni prev/next + numeri di pagina intelligenti che si adattano dinamicamente. Mostra sempre pagina 1, l'ultima pagina, e un range intorno a quella corrente (±2 pagine). Aggiunge ... per indicare gap tra sezioni (es. 1 ... 8 9 [10] 11 12 ... 100). Implementato in assets/js/app.js con funzioni generatePaginationArray() e updatePagination().

Conteggio record — In basso a sinistra viene mostrato il numero totale di record e la pagina corrente.

Dual scrollbar — La tabella ha scrollbar sia in alto che in basso per una navigazione comoda con molte colonne.

Colonne NULL rimosse — Se una colonna ha tutti valori NULL viene nascosta automaticamente (ma i campi editabili sono sempre preservati).


Preferenze griglia

Ogni utente può personalizzare le colonne visibili e il loro ordine per ogni query. Le preferenze vengono salvate nel database e ripristinate automaticamente al prossimo accesso.

Come aprire le preferenze

Nella barra azioni in cima alla griglia è presente il pulsante Preferenze colonne (icona ingranaggio o colonne). Cliccandolo si apre un pannello modal con la lista di tutte le colonne disponibili per la query corrente.

Cosa puoi fare nel modal

Nascondere/mostrare colonne — Usa il toggle accanto al nome di ogni colonna per mostrarla o nasconderla dalla griglia.

Riordinare colonne — Trascina le righe con il handle (icona ≡) per cambiare l'ordine di visualizzazione. Usa la libreria SortableJS per il drag-drop.

Salvare — Clicca Salva per persistere le preferenze. Vengono inviate a api/user_preferences.php e salvate in dbo.TimsUserGridPreferences.

Ripristinare i default — Il pulsante Ripristina default elimina le preferenze salvate e riporta la griglia alla configurazione originale del database.json.

Preferenze per utente + società + query: Le preferenze sono salvate in modo granulare: ogni combinazione di utente, codSoc e query ha le proprie preferenze indipendenti.
Applicazione automatica: Al caricamento di ogni query, il sistema verifica se esistono preferenze salvate e le applica automaticamente prima di renderizzare la griglia.

Sistema filtri

Premendo il bottone Filtri nella barra azioni si apre il pannello filtri. Ogni colonna della query corrente ha il proprio campo di filtro.

Tipi di filtro
TipoComportamentoEsempio
textCerca il testo contenuto (LIKE %...%)"alfa" trova "Alfa Romeo", "alfa123"
numeric-minValore minimo (>=)Qta >= 10
numeric-maxValore massimo (<=)Qta <= 100
boolVero/Falso (1/0)OrdineChiuso = 1
I filtri vengono applicati lato SQL — Non è un filtro JavaScript lato client. I filtri colonna vengono iniettati nella query SQL prima dell'ORDER BY, garantendo performance anche con milioni di record.
Layout pannello filtri

Le label sono posizionate a sinistra dell'input (non sopra). L'header e il footer del pannello filtri sono sticky: restano visibili durante lo scroll. Il footer contiene il conteggio record, il bottone "Pulisci" (resetta tutti i filtri) e "Applica".

Principio di design: Tutti i campi del database sono filtrabili. Non c'è selezione "intelligente" dei filtri — se un campo è nella query, ha un filtro.

Ordinamento

Clicca su qualsiasi intestazione di colonna per ordinare. Un altro click inverte l'ordine (ASC/DESC).

Ordinamento SQL-side: L'ordinamento NON avviene sui dati già caricati. Viene modificata la clausola ORDER BY della query SQL e rieseguita la chiamata API. Questo è fondamentale per trovare i record più recenti su tabelle molto grandi.

Quando ordini, la SQL originale viene modificata: se contiene già un ORDER BY, viene sostituito; altrimenti viene aggiunto.


Master-Detail (ordini)

Le query di tipo master_detail mostrano una griglia con righe espandibili. Usato per ordini in ingresso e ordini di spedizione.

Come funziona
  1. La griglia mostra le testate (master). Ogni riga ha un pulsante + a sinistra.
  2. Cliccando +, il sistema chiama api/ordini.php?action=get_details&master_id=XXX per caricare le righe di dettaglio.
  3. Le righe di dettaglio appaiono sotto la testata in una sotto-tabella.
  4. I dettagli vengono messi in cache: riaprire la stessa riga non rifa la chiamata API.
  5. Cliccando - la riga si richiude.
Placeholder @masterId: Nella SQL del detail, il placeholder @masterId viene sostituito a runtime con l'ID della testata espansa. Esempio: WHERE idOfOrdiniInTES = @masterId.
Highlight righe

I dettagli possono avere regole di evidenziazione. Per esempio, in ordini_in le righe con daControllare = 1 vengono evidenziate in giallo (stile "warning"). In ordini_out, le righe con ORR_InPrelievo = 1 si evidenziano allo stesso modo.


Modifica record

Solo gli utenti con livello ≥ 50 (SuperUser, Administrator) possono modificare i dati.

Flusso di modifica
  1. Clicca su una riga nella griglia (o sull'icona 🔧 nelle master-detail) per aprire la modale dettaglio.
  2. La modale mostra tutti i campi del record. I campi readonly sono grigi e non modificabili. I campi editabili sono interattivi.
  3. I campi required sono contrassegnati e devono avere un valore per poter salvare.
  4. Clicca Salva — il sistema invia un POST a api/data.php?action=update con solo i campi editabili modificati.
  5. Il backend filtra i campi ricevuti rispetto a editable_fields della config (sicurezza lato server). Costruisce una query UPDATE sulla tabella, usando la primary_key.
Senza primary_key non c'è UPDATE: Se una query nel database.json non ha primary_key definita, i record sono solo visualizzabili. Nessun bottone Salva apparirà.
Chiave composita: Alcune query (es. progressivi) hanno primary_key come array: ["codSoc", "NomeProgr"]. Il sistema gestisce automaticamente la costruzione della WHERE con tutti i campi chiave.

Bottoni custom

Alcune query (attualmente solo ordini_in) hanno pulsanti personalizzati nella barra azioni. Servono per operazioni massive o specifiche.

Chiudi Ordini selezione multipla

Seleziona una o più testate ordine tramite checkbox → clicca "Chiudi Ordini" → conferma il messaggio → il sistema esegue un UPDATE SQL che imposta OrdineChiuso = 1 e registra la data di chiusura. Dopo l'azione, la griglia si aggiorna automaticamente.

Stampa DDT selezione singola nascosto

Seleziona una sola testata → chiama l'endpoint PrintFlow che genera il DDT. Il risultato è un download diretto. Attualmente disabilitato (visible: false).

Tipi di azione: action_type: "sql" esegue una query SQL tramite api/custom_action.php. action_type: "api_call" restituisce endpoint e parametri al frontend, che fa la chiamata direttamente (utile per download).

Sistema di export

Il dropdown "Esporta" nella barra azioni offre 3 formati. Tutti leggono i dati direttamente dal DOM (la tabella visibile), quindi l'export riguarda sempre e solo i dati filtrati.

Formati disponibili
FormatoLibreriaComportamento
Excel (XLSX) SheetJS Genera un file .xlsx con i dati filtrati. Per master-detail: due fogli separati (testate + righe).
PDF jsPDF + AutoTable Genera un PDF con tabella formattata. Orientamento auto (landscape se molte colonne).
WhatsApp SheetJS + Web Share API Genera un file XLSX e apre il dialog di condivisione del dispositivo (WhatsApp, email, ecc.).
Principio di export: Si esporta sempre ciò che si vede. Se hai un filtro attivo che mostra 30 record su 5000, l'export conterrà solo quei 30 record.

Livelli utente e permessi

LivelloRuoloVede queryModifica datiBottoni custom
100 Administrator Tutte Tutti
90 Administrator Tutte (incl. Configurazione, Locazioni) Tutti
50 SuperUser Query con min_level ≤ 50 Quelli con min_level ≤ 50
10 StandardUser Query con min_level ≤ 10 No Quelli con min_level ≤ 10 (es. Stampa DDT)
Controllo a due livelli: Il livello viene verificato sia dal frontend (nasconde voci menu / bottoni) che dal backend (api/data.php e api/custom_action.php rifiutano le richieste se il livello non è sufficiente).

Il bottone Nuovo e il bottone Salva nella modale appaiono solo se l'utente ha livello ≥ 50 (verificato in PHP nel rendering di index.php).


Filtro società (codSoc)

Il filtro società è un meccanismo di sicurezza fondamentale. Ogni utente è associato a un codSoc e può vedere solo i dati della propria società.

Come funziona

Quando l'utente carica una query, il backend aggiunge automaticamente AND codSoc = @userCodSoc alla WHERE della SQL. L'utente non può mai vedere dati di un'altra società.

La classe Query.php ha il metodo executeWithCodSoc() che gestisce l'iniezione del filtro, tenendo conto della struttura della query (JOIN, subquery, posizione della WHERE).

Eccezione: skip_codsoc_filter — Le tabelle che non hanno il campo codSoc devono avere "skip_codsoc_filter": true nel database.json. Attualmente: locazioni (AnLocazioni) e bordereau (OrBordereau).

Gestione sessione

TIMS implementa un sistema di sessioni per-tab indipendenti usando token univoci invece dei tradizionali cookie PHP. Questo permette lo stesso utente di avere sessioni separate in tab diverse del browser.

Token sessione per-tab

Come funziona: Al login, il server genera un tabToken univoco di 48 caratteri esadecimali. Questo token identifica la sessione per quella specifica tab/finestra.

Trasmissione del token: Il token viene passato al frontend e deve essere incluso in ogni richiesta API tramite:

X-Tab-Token (header HTTP preferito)

_tab_token (parametro GET come fallback per pagine di stampa)

Sessioni indipendenti: Ogni tab mantiene la sua sessione in memoria sul server. Lo stesso utente loggato da browser diversi o tab diversi avrà sessioni completamente separate, con login_time indipendenti.

Timeout e validazione

Timeout: 3600 secondi (1 ora). Il timer si resetta ad ogni chiamata API autenticata (il metodo isAuthenticated() aggiorna il login_time).

Validazione: Il backend estrae il tabToken dal header X-Tab-Token, lo passa a session_id($tabToken), e verifica che la sessione sia ancora attiva e non scaduta.

Sessione scaduta: Se una chiamata API ritorna HTTP 401 ("Autenticazione richiesta"), il frontend mostra un modal di errore e redirige a login.php dopo qualche secondo.

Heartbeat di sessione

L'applicazione esegue periodicamente un ping a api/ping.php (con X-Tab-Token header) per verificare se la sessione è ancora attiva senza rinnovarla. Questo permette di mostrare l'avviso di scadenza prima che avvenga una chiamata reale, evitando la perdita di dati in fase di editing.

ping.php controlla il timestamp della sessione senza aggiornarlo. Se la sessione è scaduta risponde HTTP 401, innescando il redirect al login.

Nota tecnica: Cookie PHP è DISABILITATO completamente (session.use_cookies = 0) in config.php. La comunicazione avviene unicamente tramite header HTTP e parametri URL.
Configurazione legacy nel database.json: Il file config/database.json contiene una sezione "session" con impostazioni di cookie (secure, sameSite, name: "db_session_id") che sono NON UTILIZZATE perché i cookie sono disabilitati in config.php. Queste configurazioni sono legacy e non influenzano il comportamento attuale.

Stampe e PrintFlow

Le stampe in TIMS avvengono in due modi: attraverso bottoni custom nelle griglie (che aprono l'HTML in nuova tab), oppure tramite il modulo PrintFlow accessibile dall'header.

Stampe da griglia (bottoni custom)

I bottoni di stampa nelle griglie chiamano direttamente endpoint PHP che generano HTML stampabile. Si aprono in una nuova scheda del browser.

Nota auth: i file di stampa accettano l'autenticazione sia tramite sessione PHP (normale) che tramite parametri GET _user e _codsoc come fallback, per compatibilità con link diretti o apertura in nuova tab senza sessione attiva.

Ordinamenti Liste di Prelievo

Le stampe LdP (api/print_ldp.php e api/print_ldp_Multi.php) supportano 3 modalità di ordinamento tramite il parametro sort:

Valore sortOrdinamento
seqSequenza di prelievo standard
xcorsiaPer corsia: Corsia → Posizione → Piano → SeqPrelievo
xarticoloPer articolo: codArticolo → SeqPrelievo

Gli articoli senza locazione (Out-Of-Stock) appaiono sempre in cima quando il parametro noLocFirst è attivo.

PrintFlow (modulo stampe)

PrintFlow è un modulo standalone accessibile dal bottone nell'header. Si apre in una pagina separata (printing.php) e permette di cercare e stampare documenti senza dover navigare le griglie.

Funzionalità disponibili: ricerca per locazione (dropdown cascata), ricerca lista di prelievo per numero lista o numero ordine, stampa con scelta di ordinamento.

Usa api/printing_ajax.php per i dropdown e le ricerche dinamiche.

Per il bottone custom "Stampa DDT" (attualmente nascosto, visible=false) chiama l'endpoint printflow/api/generate.php. Per la documentazione completa di PrintFlow consultare la cartella Docs/.


Sezione: Magazzino

Contiene 3 query di sola lettura per consultare lo stato del magazzino.

Movimenti tutti gli utenti

Mostra lo storico di tutti i movimenti di carico/scarico. Ogni riga è un movimento con articolo, quantità, causale, DDT, lotto e scadenza. I dati arrivano dalla tabella StMovimenti con JOIN su AnArticoli per mostrare codice e descrizione articolo. Ordinati per ID decrescente (più recenti in cima).

Uso tipico: Cercare un movimento specifico filtrando per codArticolo, Lotto, DDT o NumeroOrdine.

Locazioni solo admin (90+)

Anagrafica delle posizioni fisiche del magazzino: magazzino fisico/logico, corsia, posizione, piano, alias. Mostra anche le proprietà (picking/scorta, prelevabile, multi-articolo, dimensioni, peso max). Usa la tabella AnLocazioni, che non ha codSoc.

Uso tipico: Consultare la struttura del magazzino, verificare caratteristiche di una locazione.

Giacenza tutti gli utenti

Stato attuale dello stock: mostra gli articoli in magazzino con quantità > 0, posizionati per locazione. Usa la vista vStockArticoliPosizioni. Include lotto, scadenza, pallet, quantità impegnata e posizione completa.

Uso tipico: Verificare la disponibilità di un articolo, controllare dove è posizionato, vedere le scadenze.


Sezione: Anagrafiche

Articoli tutti gli utenti 1 campo editabile

Lista completa degli articoli attivi (Cancellato = 0). Mostra codice, descrizioni, quantità confezionamento/pezzo, pesi, gestione lotto/scadenza, unità misura. L'unico campo modificabile è descrizione1 (descrizione aggiuntiva).

Uso tipico: Cercare un articolo per codice o descrizione, consultare le caratteristiche, aggiornare la descrizione aggiuntiva.

Clienti & Fornitori tutti gli utenti CRUD completo

Elenco clienti, fornitori e vettori dalla tabella AnCliForn. Mostra codice cliente, codice fornitore, ragione sociale, indirizzo, contatti e provincia. Per gli utenti livello ≥ 50 sono disponibili la creazione e la modifica dei record.

Regole di inserimento (insert rules):

RagioneSociale è obbligatoria

• Almeno uno tra Cli, Forn, Vett deve essere impostato a 1 (il soggetto deve avere almeno un ruolo)

• Se Cli = 1 allora codCli diventa obbligatorio

• Se Forn = 1 o Vett = 1 allora codForn diventa obbligatorio

• I codici codCli e codForn devono essere unici per tipo (controllo duplicati automatico)

• Alcuni campi (codSoc, utenteCreazione, utenteUltModifica) vengono popolati automaticamente dal sistema

Uso tipico: Cercare un cliente o fornitore per ragione sociale o codice; aggiungere nuovi soggetti; aggiornare i dati anagrafici.


Sezione: Spedizioni

Ordini In Ingresso master-detail editabile

Gestione ordini fornitori. La testata mostra: ordine fornitore, progressivo arrivo, date, note (ordine/logistica/DDT/trasporto), DDT, stato chiusura, esito invio, ragione sociale e codice fornitore.

Espandendo una riga, il dettaglio mostra le righe dell'ordine: articolo, lotto atteso, scadenza attesa, quantità attesa/caricata, stato completamento, campi extra, flag "da controllare".

Azioni disponibili:

Modifica testata/righe — Clic sulla riga per aprire la modale.

Chiudi Ordine — Selezione multipla, imposta OrdineChiuso=1 (level ≥ 50). Handler: chiudiOrdineIn() in assets/js/chiudi-ordine-in.js. API: api/chiudi_ordine_in.php.

Stampa Etichette IN — Selezione singola, apre modale split-pallet per configurare etichette × quantità per riga ordine (level ≥ 10). Handler: stampaEtichetteIn() in assets/js/etichette-in.js. API: api/etichette_in.php, api/print_etichette_in.php.

Stampa DDT — Selezione singola, genera DDT via PrintFlow. API: api/print_ordini_in.php (attualmente nascosto: visible=false).

Missioni (LdP) master-detail tutti gli utenti

Liste di prelievo con dettaglio articoli e locazioni. Tabelle: OrListaPCOTes (master) + OrListaPCORig (detail). Sola lettura.

Master — Mostra: numero lista, data lista, numero ordine collegato, bolla, data bolla, stato InPrelievo.

Detail — Mostra: articolo, descrizione, lotto, pallet, quantità da prelevare/prelevata/out-of-stock, locazione fisica e logica (corsia, posizione, piano).

Stampa LdP — Bottone custom per stampa lista di prelievo (level ≥ 10). API: api/print_ldp.php, api/print_ldp_Multi.php. Disponibile anche con api/printing_ajax.php per stampa automatica.

Bordereau master-detail CRUD completo level ≥ 50 per azioni

Gestione bordereau spedizioni dalla tabella OrBordereau (non ha filtro codSoc). Operazioni disponibili:

Visualizza — Lista tutti i bordereau con paginazione, filtri dinamici (tutti gli utenti)

Crea — Seleziona vettore e ordini di uscita, genera codice univoco da progressivo AnProgr, collega ordini (level ≥ 50)

Chiudi — Imposta dataChiusura e utenteUltModifica (level ≥ 50, solo se dataChiusura IS NULL)

Cancella — Cancellazione logica (Cancellato=1) + scollega automaticamente ordini (level ≥ 50, solo se non chiuso)

Bottoni custom stampa (dropdown):

Stampa Lista di Carico — Genera la distinta di carico del bordereau selezionato (formato A4, colli deduplicati, totale peso). API: api/print_bordereau.php

Bordereau per Vettore — Genera il documento bordereau con firma da consegnare al vettore (UDS per riga, totali deduplicati). API: api/print_bordereau_vettore.php

API Backend: api/bordereau.php con azioni: create, close, delete, get_vettori, get_available_orders

Handler JavaScript: assets/js/chiudi-bordereau.js — chiusura con verifica preliminare · assets/js/app.js (deleteBordereau) — cancellazione con transazione atomica

Ordini di Spedizione master-detail editabile

Gestione ordini clienti/spedizioni. La testata mostra: numero ordine, date, bolla, destinazione completa (rag. soc., indirizzo, località, CAP, provincia, nazione), note, contrassegno, fattura, ragione sociale cliente, anno, stato prelievo.

Il dettaglio mostra le righe: numero riga, riserve pallet/posizione, lotto, scadenza, matricola, pallet, varianti (1-8), quantità ordinata/prelevata, note riga.

Le righe con ORR_InPrelievo = 1 sono evidenziate in giallo.


Sezione: Configurazione

Accessibile solo ad Administrator (livello 90+).

Opzioni solo admin

Tabella AnOpzioni. Opzioni di configurazione del sistema: chiave-valore per società e utente. Sola lettura in TIMS.

Utenti solo admin 1 campo editabile

Tabella AnUtenti. Lista utenti del sistema con login, tipo, token, menu di riferimento. L'unico campo modificabile è Abilitato (per attivare/disattivare un utente).

Progressivi solo admin 3 campi editabili

Tabella AnProgr (TOP 200). Gestione contatori/progressivi per numerazione automatica. Campi editabili: Progr (valore attuale), Abilitato, Prefisso. Ha chiave primaria composita [codSoc, NomeProgr].


Endpoint API

Riepilogo di tutte le API disponibili nel backend.

EndpointMetodoFunzione
api/auth.phpPOSTLogin (action: login) e Logout (action: logout)
api/data.php?action=configGETOttiene gruppi, query e ui_settings
api/data.php?action=list&queryId=xxxGETLista dati con filtri, paginazione, ordinamento
api/data.php?action=updatePOSTAggiorna record (solo campi editabili)
api/ping.phpGETHeartbeat: verifica sessione attiva senza rinnovarla (risponde 401 se scaduta)
api/menu.phpGETStruttura menu (gruppi + query)
api/user_preferences.phpGET/POST/DELETEGestione preferenze griglia utente (visibilità e ordine colonne per query)
api/ordini.php?action=get_detailsGETRighe dettaglio di una testata master-detail
api/custom_action.phpPOSTEsegue azioni bottoni custom (SQL o api_call)
api/bordereau.php?action=createPOSTCrea nuovo bordereau con ordini collegati (richiede level ≥ 50)
api/bordereau.php?action=closePOSTChiude bordereau: imposta dataChiusura (richiede level ≥ 50)
api/bordereau.php?action=deletePOSTCancella logicamente bordereau e scollega ordini (richiede level ≥ 50)
api/bordereau.php?action=get_vettoriGETLista vettori disponibili per creazione bordereau
api/bordereau.php?action=get_available_ordersGETLista ordini di uscita da collegare al bordereau
api/chiudi_ordine_in.phpPOSTChiusura ordini in ingresso multi-step: validazione → dialogo delta → UPDATE OrdineChiuso=1 (level ≥ 50)
api/etichette_in.phpPOSTGenera etichette per ordini in ingresso: action=load (carica righe) / action=generate (riserva pallet su AnProgr)
api/print_etichette_in.phpGETStampa etichette IN in formato HTML per stampa diretta
api/print_ordini_in.phpGETGenera DDT per ordini in ingresso (attualmente nascosto: visible=false)
api/print_ldp.phpGETStampa Lista di Prelievo singola (parametro sort: seq/xcorsia/xarticolo)
api/print_ldp_Multi.phpGETStampa multipla Liste di Prelievo (parametro ids=id1,id2,...)
api/print_bordereau.phpGETStampa Distinta di Carico bordereau (A4, colli deduplicati, totale peso)
api/print_bordereau_vettore.phpGETStampa Bordereau per Vettore con firma (UDS per riga, totali deduplicati)
api/print_plist_berlin.phpGETStampa Packing List stile Berlin Packaging (usa view roviews.vImpPackingList)
api/print_etichette.phpGETStampa etichette generiche
api/printing_ajax.phpPOSTAJAX per modulo Printing: dropdown cascata, ricerca locazioni, ricerca LdP
File JSHandlerFunzione
assets/js/app.jsLogica principale: menu, griglia, filtri, paginazione ellipsis, editing, heartbeat sessione
assets/js/grid-preferences.jsModal drag-drop preferenze colonne (SortableJS): visibilità + ordine, persistenza in TimsUserGridPreferences
assets/js/export.jsSistema export lato client: Excel (SheetJS), PDF (jsPDF), WhatsApp
assets/js/master-detail.jsGestione apertura/chiusura righe dettaglio master-detail, cache in memoria
assets/js/chiudi-bordereau.jschiudiBordereauChiusura bordereau con verifica dataChiusura IS NULL
assets/js/chiudi-ordine-in.jschiudiOrdineInChiusura ordini in ingresso multi-step: validazione → dialogo delta quantità → conferma UPDATE
assets/js/etichette-in.jsstampaEtichetteInModale split-pallet: configurazione N etichette × quantità per riga ordine, riserva ID pallet su AnProgr
Sicurezza JSON: Tutti gli endpoint API hanno error_reporting(0) e ob_start()/ob_clean() per evitare che warning PHP corrompano l'output JSON. Questo è fondamentale su IIS.

Troubleshooting

JSON corrotto nelle risposte API

Sintomo: La pagina non carica dati, errori "JSON parse" nella console.

Causa: PHP sta stampando warning o errori prima del JSON.

Soluzione: Verificare che error_reporting(0) e ini_set('display_errors', 0) siano presenti all'inizio di ogni file API. Usare ob_start() e ob_clean() prima dell'output JSON.

Colonne ambigue nei JOIN

Sintomo: Errore SQL "Ambiguous column name" quando si aggiunge il filtro codSoc.

Causa: Il campo codSoc esiste in più tabelle del JOIN.

Soluzione: Nella SQL, prefissare sempre codSoc con il nome tabella (es. OfOrdiniInTES.codSoc). Il metodo addCodSocFilter in Query.php cerca di determinare la tabella giusta, ma è meglio essere espliciti.

Alias GETDATE() in SQL Server

Sintomo: Errori SQL quando si usa GETDATE() senza alias.

Causa: SQL Server richiede un alias per le colonne calcolate.

Soluzione: Usare sempre GETDATE() AS nomeAlias nelle SELECT.

Funzioni multibyte non disponibili

Sintomo: Errori con mb_strtolower, mb_substr su IIS.

Causa: L'estensione mbstring potrebbe non essere attiva su IIS.

Soluzione: Non usare funzioni mb_* nel codice. Il sistema è stato adattato per usare solo funzioni string standard di PHP.

Sessione scaduta improvvisamente

Sintomo: Redirect a login dopo poco tempo.

Causa: Il timeout è 3600 secondi. Se il browser non fa chiamate API per un'ora, la sessione scade.

Soluzione: Il timeout si resetta ad ogni operazione. Se il problema persiste, verificare la configurazione PHP di session.gc_maxlifetime su IIS.

La query non mostra i record più recenti

Sintomo: I nuovi record non appaiono in cima alla lista.

Causa: La SQL potrebbe non avere un ORDER BY DESC.

Soluzione: Aggiungere ORDER BY Id DESC (o campo data) alla SQL nel database.json. L'ordinamento avviene a livello SQL, non lato client.