Magazzino
Giacenze, movimenti, lotti FIFO/FEFO, alert scorte, inventario fisico, analisi ABC e riordino
Riferimenti normativi
- DPR 441/97 — Presunzione di cessione e acquisto: I beni nei locali dell'impresa si presumono acquistati, prodotti o ceduti. Il registro carico/scarico documenta la movimentazione e giustifica le giacenze.
- Art. 2214 Codice Civile — Scritture contabili obbligatorie: L'imprenditore deve tenere le scritture richieste dalla natura dell'impresa, incluso il registro di magazzino.
- Art. 2217 Codice Civile — Inventario: L'inventario deve essere redatto ogni anno con indicazione e valutazione delle rimanenze di magazzino.
- Art. 92 TUIR (DPR 917/86) — Valutazione rimanenze: Metodi ammessi: costo specifico, FIFO, LIFO o costo medio ponderato. Il sistema supporta tutti e tre nella dashboard.
- OIC 13 — Rimanenze: Valutazione al minore tra costo di acquisto/produzione e valore di realizzo desumibile dal mercato.
- DPR 633/72 art. 53 — Beni in deposito: Per beni in conto lavorazione, deposito o visione va tenuto registro apposito.
- D.Lgs. 193/2007 — Tracciabilità alimentare e farmaceutica: Obbligo di tracciabilità del lotto per prodotti alimentari e farmaceutici.
- Reg. UE 178/2002 art. 18 — General Food Law: Tracciabilità in tutte le fasi di produzione, trasformazione e distribuzione.
- D.Lgs. 219/2006 — Codice dei medicinali: Gestione lotti con data scadenza obbligatoria. FEFO garantisce dispensazione corretta.
Note operative e permessi configurabili
🗒️ Pannello Note: ogni scheda di movimento di magazzino, magazzino o ubicazione ha un pannello "post-it"
giallo floating ancorato all'entità corrente. Si apre minimizzato come fascia
centrata sulla topbar (sulla barra blu del modale per i documenti); cliccando
la fascia o la freccia expand_more si espande al centro del viewport
(ridimensionabile via handle in basso a destra). La fascia minimizzata è trascinabile
e la sua posizione viene memorizzata in localStorage per ciascun record (es. ogni
documento ha la sua posizione independente). Per scrivere una nota: testo nel box giallino
+ bottone + Aggiungi (o Cmd/Ctrl + Invio). Modifica/elimina riservate
all'autore o agli amministratori. Cestino note con ripristino disponibile
dal toggle delete_outline nell'header del pannello espanso (solo ADMIN/SUPERADMIN).
Tutti i CRUD (create/update/delete/restore) sono tracciati in audit_log
(consultabile da Amministrazione Sistema → Audit Log).
🔒 Permessi configurabili: alcune azioni di questa scheda (creazione, modifica, cancellazione, esportazione, stampa) possono essere bloccate per il ruolo del tuo workspace. Quando un bottone è bloccato, appare con icona "lucchetto" e tooltip "Permesso disabilitato dal Super Amministratore". La configurazione si fa in Amministrazione di Sistema » Permessi per Ruolo (solo SUPERADMIN).
Il modulo Magazzino gestisce l'intero ciclo delle scorte. L'header mostra 4 KPI chip (articoli, valore stock, sotto scorta, in esaurimento), selettore magazzino, ricerca e scanner barcode.
10 Tab
| Tab | Contenuto |
|---|---|
| Giacenze | Quantità per articolo: totale, disponibile, riservata, scorta min, costo medio, valore |
| Movimenti | Registro cronologico carico/scarico con 12 tipi |
| Lotti | Lotti con quantità residua, scadenza, fornitore |
| Alert | Sotto scorta + lotti in scadenza 30gg |
| Dashboard | KPI avanzati, valorizzazione FIFO/LIFO/Costo Medio, top 10 |
| ABC | Classificazione Pareto: A (80%), B (95%), C |
| Rotazione | Indice rotazione, copertura gg, stato (obsoleto/lento/normale/veloce) |
| Riordino | ROP automatico, quantità da ordinare |
| Trasferimenti | Movimenti tra magazzini |
| Storico Prezzi | Cronologia costi unitari per articolo |
Il sistema supporta più magazzini indipendenti. Il selettore nell'header permette di cambiare.
- Premere “Gestione Magazzini” nel footer.
- Dialog con elenco magazzini. Compilare: codice, nome, tipo, indirizzo, CAP, provincia. Flag Default per il principale.
- Modificare: clic su un magazzino, editare, salvare. Eliminare: solo se vuoto.
| Colonna | Descrizione |
|---|---|
| Codice / Descrizione | Articolo dal catalogo |
| Tipo | Farmaco, Integratore, Articolo, ecc. |
| Quantità | Giacenza totale |
| Disponibile | Totale − riservata |
| Riservata | Impegnata in documenti non spediti |
| U.M. | Unità di misura |
| Ubicazione | Corridoio-Scaffale-Ripiano-Cella |
| Scorta min. | Soglia alert sotto scorta |
| Costo medio / Valore | Costo medio ponderato × giacenza |
| Stato | OK (verde), Sotto scorta (rosso), In esaurimento (arancione) |
Filtri: ricerca testo, ubicazione, tipo voce, paginazione 50/pagina. Azioni riga: scheda catalogo, soglie, etichetta.
Registro cronologico. Colonne: data, tipo, articolo, segno (+/−), quantità, costo unit., valore, lotto, ubicazione, documento, giacenza post.
12 tipi di movimento
| Tipo | Segno | Descrizione |
|---|---|---|
| CARICO_ACQUISTO | + | Merce da fornitore |
| CARICO_RESO | + | Reso da cliente |
| CARICO_PRODUZIONE | + | Prodotto finito interno |
| CARICO_TRASFERIMENTO | + | Da altro magazzino |
| SCARICO_VENDITA | − | Vendita/consegna |
| SCARICO_RESO | − | Reso a fornitore |
| SCARICO_TRASFERIMENTO | − | Verso altro magazzino |
| SCARICO_CONSUMO | − | Consumo interno |
| RETTIFICA_POSITIVA | + | Correzione manuale + |
| RETTIFICA_NEGATIVA | − | Correzione manuale − |
| INVENTARIO | ± | Da inventario fisico |
| STORNO | + | Annullamento scarico |
Filtri: tipo, data dal/al, paginazione. Solo movimenti manuali eliminabili.
- Premere “+ Movimento” nel footer → dialog modale.
- Selezionare tipo (12 opzioni).
- Cercare articolo da catalogo (autocomplete).
- Selezionare ubicazione (opzionale).
- Inserire quantità e costo unitario.
- Opzionale: numero lotto, data scadenza, data, note.
- Premere Salva.
Colonne: articolo, lotto, qta iniziale, qta residua, U.M., scadenza, giorni alla scadenza (rosso <30, arancione <90), data ricevimento, fornitore.
Filtro “Solo in scadenza”: mostra solo lotti che scadono entro 30 giorni.
Alla conferma documento, scarico automatico:
| Metodo | Criterio | Uso |
|---|---|---|
| FEFO | First Expired, First Out — prima lotti con scadenza vicina | Farmaci, integratori, alimenti |
| FIFO | First In, First Out — prima lotti ricevuti prima | Articoli senza scadenza |
Split lotti: se un lotto non copre la quantità, lo scarico si distribuisce su più lotti. All'annullamento i movimenti vengono stornati e le quantità ripristinate.
Due sezioni: Sotto scorta minima (card per articolo con giacenza, scorta min, deficit) e Lotti in scadenza 30gg (card con lotto, quantità, scadenza, giorni).
KPI: valore stock, articoli totali, sotto scorta, rotazione media. Metodo valorizzazione (art. 92 TUIR):
| Metodo | Formula | Normativa |
|---|---|---|
| Costo Medio | (costo acquisti + rimanenze) / quantità totale | Art. 92 c.1 TUIR, OIC 13 |
| FIFO | Rimanenze valutate al costo ultimi acquisti | Art. 92 c.2 TUIR |
| LIFO | Rimanenze valutate al costo primi acquisti | Art. 92 c.2 TUIR |
Sotto i KPI: tabella categorie e top 10 articoli per valore stock.
Classificazione Pareto:
| Classe | % Valore | Gestione |
|---|---|---|
| A | 0–80% | Monitoraggio stretto, riordino frequente, scorte di sicurezza |
| B | 80–95% | Monitoraggio periodico, riordino a soglia |
| C | 95–100% | Gestione semplificata, ordini meno frequenti |
Colonne: articolo, giacenza, mov/mese, indice rotazione, giorni copertura (giacenza / consumo medio), stato:
| Stato | Indice | Significato |
|---|---|---|
| OBSOLETO | < 1 | Meno di 1 scarico/anno — capitale immobilizzato |
| LENTO | 1–3 | Bassa rotazione, valutare promozioni |
| NORMALE | 3–10 | Rotazione nella norma |
| VELOCE | > 10 | Alta rotazione, garantire scorte |
Formula: ROP = (consumo medio giornaliero × lead time) + scorta di sicurezza
Colonne: giacenza, scorta min, consumo medio, lead time, ROP, da ordinare (ROP − giacenza). Articoli con “da ordinare” positivo richiedono riapprovvigionamento.
- Aprire dialog Trasferimento.
- Selezionare magazzino origine e destinazione.
- Selezionare articolo e quantità.
- Salva: genera SCARICO_TRASFERIMENTO nell'origine e CARICO_TRASFERIMENTO nella destinazione.
Struttura a 4 livelli: Corridoio — Scaffale — Ripiano — Cella + barcode opzionale. Premere “Nuova Ubicazione” nel footer per crearne una.
Cronologia costi unitari alimentata dai movimenti di carico. Colonne: data, articolo, tipo, costo unit., quantità, fornitore. Utile per monitorare l'andamento prezzi e negoziare.
Scanner: campo barcode nell'header per ricerca rapida EAN. Etichette: singola (icona nella riga giacenze) o batch (checkbox + “Stampa etichette” nel footer). Include: codice, descrizione, barcode, prezzo, ubicazione.
Creare un inventario
- Premere “+ Nuovo Inventario”.
- Descrizione (opzionale), ubicazione (opzionale = tutti).
- Crea: genera elenco articoli con giacenza teorica.
Conteggio
- Aprire l'inventario (stato IN_CORSO).
- Per ogni articolo inserire quantità contata.
- Differenza automatica: +N (verde surplus), −N (rosso ammanco), 0 (grigio ok).
- KPI: contati/totale, righe con differenze.
Filtri
Solo non contati (toggle), ricerca per codice/descrizione.
Chiusura
- Premere “Chiudi Inventario”.
- Il sistema genera movimenti INVENTARIO (rettifiche) per ogni differenza ≠ 0.
- Giacenze aggiornate ai valori contati. Stato → COMPLETATO.
Aggiornamento strutturale del modulo Magazzino. Le novità sono pensate nel rispetto della natura contabile dei movimenti: i movimenti di magazzino sono cronologia e non si cancellano — si stornano. Il soft-delete e applicato solo alle anagrafiche (magazzini, ubicazioni), non alle registrazioni.
Storno dei movimenti (pattern contabilmente corretto)
Nel tab Movimenti, selezionando una o piu righe con le checkbox, compare una barra blu con le azioni di gruppo:
- ↵ Storna: crea, per ogni movimento selezionato, un movimento di rettifica di segno opposto (CARICO_RETTIFICA per uno scarico, SCARICO_RETTIFICA per un carico). Il movimento originale rimane tracciato. Questo e il modo corretto per correggere un errore senza perdere lo storico. Se un movimento e gia stato stornato, viene bloccato.
- 🗑 Elimina manuali: cancella fisicamente i movimenti selezionati che non hanno documento collegato (bolla, ordine, fattura, documento). I movimenti generati da documenti vengono ignorati e riportati come bloccati nella risposta. La giacenza viene riallineata automaticamente.
Entrambe le azioni registrano un'entry nell'audit log del movimento.
Audit log dei movimenti
Ogni modifica o cancellazione di un movimento (manuale o automatica) viene registrata nella tabella log_modifiche_movimenti_magazzino con campo modificato, valore precedente, valore nuovo, utente e timestamp. Lo storico e accessibile via GET /api/magazzino/movimenti/:id/audit-log.
Audit log degli inventari
La chiusura di un inventario fisico (transizione IN_CORSO → COMPLETATO) viene registrata nella tabella log_modifiche_inventari con utente e data. Accesso via GET /api/magazzino/inventari/:id/audit-log.
Timeline voce magazzino
Nuovo endpoint GET /api/magazzino/voce/:id/timeline che aggrega in ordine cronologico decrescente: movimenti (con flag di storno), righe inventario (conteggiate e non) con giacenza attesa/contata/differenza. Utile per ricostruire la storia di un articolo dal punto di vista del magazzino.
Soft-delete + Cestino su Magazzini e Ubicazioni
Le anagrafiche (depositi e scaffali) sono ora soft-deletabili:
- DELETE marca i campi
cancellatoIlecancellatoDa, disattiva automaticamente il record e lo rimuove dalla lista standard. Giacenze e movimenti storici restano intatti. - Lista cancellati via
GET /api/magazzino/magazzini/_/cestinoeGET /api/magazzino/ubicazioni/_/cestino(con counters di giacenze/movimenti collegati). - Ripristino via
POST /api/magazzino/magazzini/:id/ripristinaePOST /api/magazzino/ubicazioni/:id/ripristina. - Eliminazione definitiva via
DELETE /api/magazzino/{tipo}/:id/definitivo: hard delete consentito solo se il record e gia soft-deletato e non ha giacenze ne movimenti collegati.
Perche NON c'e il cestino per movimenti, giacenze e inventari
- Movimenti: sono cronologia contabile. La correzione corretta e lo storno, non la cancellazione logica.
- Giacenze: sono snapshot calcolati (voce × ubicazione). Non ha senso “cancellarle”: si svuotano azzerando i movimenti.
- Inventari: hanno gia un proprio lifecycle IN_CORSO / COMPLETATO / ANNULLATO. Lo stato ANNULLATO e il meccanismo corretto.
Quando emetti una fattura e scarichi merce dal magazzino, il gestionale deve decidere a che costo registrare quello scarico. I tre metodi riconosciuti fiscalmente sono CMP (Costo Medio Ponderato), FIFO (primo entrato, primo uscito) e LIFO (ultimo entrato, primo uscito).
Dove si imposta
- Apri Amministrazione → Parametri
- Scorri fino alla sezione “📦 Valorizzazione magazzino”
- Scegli il metodo dal menu a tendina:
- CMP — il più comune per PMI. Media ponderata tra tutte le giacenze
- FIFO — tipico per prodotti con obsolescenza (elettronica, alimentare non deperibile)
- LIFO — usato con prezzi in crescita per “caricare” i costi recenti (risparmio fiscale immediato ma magazzino sottovalorizzato)
- Salva. Il cambio del metodo impatta solo i nuovi scarichi; i movimenti già registrati restano invariati.
Override per singolo prodotto
Nella scheda di un prodotto in Catalogo, se vuoi che quel singolo articolo usi un metodo diverso dal default aziendale, c'è un campo “Metodo valorizzazione” personalizzato. Lasciare vuoto per ereditare la scelta aziendale.
Simulazione rapida
Se prima di confermare una vendita vuoi vedere quanto ti costa con i 3 metodi, nella pagina Giacenze Magazzino → tab Lotti trovi per ogni articolo il costo/pz e il valore residuo. Così decidi se vendere questo o quello a parità di tipo prodotto.
Il tab “🏷 Lotti” della pagina Giacenze Magazzino è stato potenziato per mostrare in un colpo d'occhio quanto hai in magazzino come valore, non solo come quantità.
Cosa vedi
- Filtro ricerca testuale per codice articolo, descrizione o numero lotto
- Toggle “Solo lotti in scadenza (30gg)”
- Colonne: N° lotto, Q.tà iniziale, Q.tà residua, U.M., Costo/pz, Valore residuo, Data scadenza, Giorni rimanenti, Data ricevimento, Fornitore
- Riga colorata:
- rosso = lotto scaduto
- giallo = scade entro 30 giorni
- bianco = tutto ok
KPI in alto
Nella barra filtri vedi due numeri aggregati:
- Lotti attivi: quanti lotti sono attualmente in magazzino
- Valore residuo: quanto valgono complessivamente (Q.tà residua × costo unitario)
Quando filtri per articolo o per scadenze, i KPI si aggiornano. Utile per calcolare al volo quanto ti costerebbe uno smaltimento di merce scaduta.
Dal 2026 il gestionale ti segnala proattivamente i lotti scaduti o in scadenza, senza bisogno che vai a controllare manualmente.
Dove compare l'alert
Nella Dashboard, tra le schede statistica colorate, trovi una card dedicata “Lotti in scadenza” che compare solo se hai almeno uno scaduto/critico/warning:
- Rosso — ci sono lotti già scaduti: URGENTE, rischio sanitario/fiscale
- Arancio — ci sono lotti critici (scadono entro 7 giorni)
- Neutro — solo warning (scadenza fra 8-30 giorni)
Al centro della card vedi il numero (scaduti + critici) e il valore a rischio in euro. Un click ti porta direttamente al tab Lotti filtrato sui lotti interessati.
Email automatica giornaliera
Ogni mattina alle 07:00 il sistema invia una mail riepilogativa a tutti gli admin aziendali con gli alert del giorno. Se non hai configurato l'SMTP aziendale, l'alert resta comunque visibile in dashboard.
GET /api/magazzino/inventari/:id/audit-log, oppure osservando il campo utente sui movimenti di rettifica generati alla chiusura.GET /api/magazzino/voce/:id/timeline: restituisce in ordine cronologico decrescente tutti i movimenti dell'articolo (marcati con il flag di storno se applicabile) e le righe di inventario fisico in cui compare (attesa, contata, differenza). E la visione completa per capire carichi, scarichi, storni e rettifiche di inventario.• Pacchetto
MAGAZZINO attivo sul workspace (configurabile da SUPERADMIN in /admin/pacchetti)
• Profilo attività compatibile: Studio dentistico, Farmacia, Ferramenta, Elettronica, Verniciatura, Generico
• Permesso utente abilitato in Modifica Utente → Moduli
I tre livelli si applicano in intersezione. Dettagli completi in Gerarchia Pacchetti+Profilo+Utente.
A partire dalla versione 2.2, il modulo Magazzino adotta lo standard di certificazione NOX con i seguenti presidi:
Cestino e soft-delete
Gli elementi cancellati non vengono rimossi fisicamente ma spostati in un cestino interno (campi cancellatoIl / cancellatoDa). Dalla toolbar il pulsante Cestino alterna tra vista attivi e vista cestino. Dal cestino è possibile:
- Ripristinare l'elemento (riportarlo nella lista attiva) — operazione riservata ad amministratori.
- Eliminare definitivamente con motivazione obbligatoria — azione irreversibile, riservata ad amministratori, tracciata nell'audit log.
Azioni massive (bulk)
È possibile selezionare più elementi con le checkbox della prima colonna. Appare una barra inferiore con le azioni disponibili: Per i movimenti si esegue STORNO contabile (inserimento movimento opposto) invece di cancellazione. La risposta indica N operazioni riuscite / M fallite; i dettagli delle fallite compaiono nella console browser (F12).
Guard periodo IVA chiuso (v 2.2)
La creazione di un movimento di magazzino (POST /api/magazzino/movimenti) con dataMovimento che cade in un periodo IVA chiuso viene bloccata con HTTP 409.
- Il guard verifica la data rispetto alle chiusure attive del registro vendite (tipo DDT)
- Impedisce di alterare giacenze di un periodo già consolidato contabilmente
- Per eventuali correzioni: riapertura periodo (admin + motivazione) oppure movimento di storno nel periodo corrente
Storico modifiche (audit log)
L'icona history nelle azioni di riga apre un modal con la storia completa delle modifiche: data, campo, valore precedente, valore nuovo, operatore, eventuale motivazione. I record di audit non sono modificabili né eliminabili via UI. Conservazione: indefinita (art. 2220 c.c. — 10 anni minimo).
Mascheramento dati sensibili (GDPR art. 32)
Se i campi modificati contengono dati sensibili (IBAN, Codice Fiscale, Partita IVA, password/token), l'audit log salva il valore mascherato anziché in chiaro:
| Campo | Esempio originale | Nel log |
|---|---|---|
| IBAN | IT60X0542811101000000123456 | IT60****3456 |
| Codice Fiscale (PF) | RSSMRA80A01H501Z | RSSMRA****501Z |
| Partita IVA | 12345678901 | 123****901 |
| Password / token | (qualsiasi) | ***REDACTED*** |
Timeline aggregata
Per ciascun elemento è disponibile una vista Timeline che aggrega in ordine cronologico audit, eventi del ciclo di vita ed eventuali entità collegate (es. documenti, movimenti, storni).
RBAC uniforme
Tutte le azioni distruttive o massive (soft-delete, ripristino, eliminazione definitiva, bulk, storno) richiedono il ruolo ADMIN o superiore. Gli operatori possono continuare a creare / modificare / consultare secondo le proprie abilitazioni.
Integrazione automatica DDT → movimenti magazzino (v 2.2 wave 9)
Trigger automatico che genera i movimenti di magazzino a partire dalle righe di un DDT con il tipo di movimento corretto in funzione della causale. Previene la doppia esecuzione tramite log di tracciamento.
Mapping DDT → tipo movimento
| Scenario DDT | Tipo movimento generato | Segno quantità |
|---|---|---|
| DDT di vendita (causale VENDITA) | SCARICO_VENDITA | negativo (scarica) |
| DDT reso cliente (resoTipo RESO_CLIENTE) | CARICO_RESO_CLIENTE | positivo (carica) |
| DDT reso fornitore (resoTipo RESO_FORNITORE) | SCARICO_RESO_FORN | negativo (scarica) |
Endpoint
POST /api/bollettazione/magazzino-auto/ddt/:docId[ADMIN] body{magazzinoId, forza?}- Scandisce
documento_righe.voceCatalogoIde genera un recordmovimenti_magazzinoper ogni riga con articolo di catalogo - Traccia l'esecuzione in
log_magazzino_autocon arraymovimenti_generati[], esito (OK/ERRORE/SKIP), eventuale errore testuale - Il flag
forza: truepermette di rieseguire il trigger anche se un log OK esiste già (utile dopo correzioni)
voceCatalogoId (es. righe di testo libero, spese accessorie) vengono saltate silenziosamente perché non rappresentano giacenze. Il costo unitario applicato al movimento è il prezzoUnitario della riga, e il valore totale è il totaleRiga.MAGAZZINO v 2.2 — 11ª ondata (ALTA + MEDIA priorità)
Estensione del pacchetto MAGAZZINO con 8 macro-funzionalità avanzate richieste dal mercato enterprise. Tutti gli endpoint sono montati sotto /api/magazzino-v11/* (router magazzino-v22-wave11.routes.js). 8 nuove tabelle DB + estensioni schema.
A. Causali rettifica classificate (14 codici seed)
Sostituisce il campo causale a testo libero con un elenco strutturato e parametrizzabile di causali standard.
| Codice | Tipo | Foto | Soglia approvazione |
|---|---|---|---|
| DANNEGGIATO | SCARICO | ✓ | € 100,00 |
| OBSOLETO | SCARICO | — | € 500,00 |
| FURTO | SCARICO | ✓ | sempre (€ 0,01) |
| FURTO_ASSICURATO | SCARICO | ✓ | sempre |
| SCADUTO | SCARICO | — | € 100,00 |
| SOTTOINVENTARIO | SCARICO | — | € 200,00 |
| SOVRAINVENTARIO | CARICO | — | € 200,00 |
| CAMBIO_LOTTO | CARICO | — | — |
| RESO_CLIENTE | CARICO | — | — |
| OMAGGIO | SCARICO | — | € 50,00 |
| AUTOCONSUMO | SCARICO | — | € 100,00 |
| DISTRUZIONE_CERTIFICATA | SCARICO | ✓ | sempre |
| PRODUZIONE_CARICO/SCARICO | BI | — | — |
GET /api/magazzino-v11/causali-rettifica— elencoPUT /api/magazzino-v11/causali-rettifica/:id[ADMIN] — modifica soglia/foto/attivoPOST /api/magazzino-v11/movimenti/rettificabody{voceCatalogoId, magazzinoId, quantita, causaleRettificaId, motivazione, costoUnitario}- Se
sogliaApprovazioneEurimpostata evalore ≥ soglia, il movimento nasce in statoIN_ATTESA_APPROVAZIONE
B. Workflow approvazione movimenti
Stato movimento: BOZZA → IN_ATTESA_APPROVAZIONE → APPROVATO / RIFIUTATO. Ogni movimento in attesa richiede firma ADMIN.
GET /api/magazzino-v11/movimenti/in-approvazione— coda approvazionePOST /api/magazzino-v11/movimenti/:id/approva[ADMIN]POST /api/magazzino-v11/movimenti/:id/rifiuta[ADMIN] body{motivo}- Campi:
statoApprovazione,approvatoDa,approvatoIl,rifiutatoMotivo,richiestaApprovazioneDa
C. Allegati foto/documenti giustificativi
Upload di foto, verbali, certificati di distruzione allegati al singolo movimento. Salvataggio disco con hash SHA-256.
- Tabella
movimento_allegaticon tipo (FOTO/DOCUMENTO/CERTIFICATO_DISTRUZIONE/VERBALE) POST /api/magazzino-v11/movimenti/:id/allegatiform-datafile+tipoAllegato+noteGET /api/magazzino-v11/movimenti/:id/allegati,/allegati/:allegId/download- Cartella:
/app/magazzino-allegati/, max 15 MB per file
D. Giacenza retrospettiva a data
Ricostruzione della giacenza a qualunque data storica sommando i movimenti approvati fino a quel giorno. Utile per export periodo d'imposta, confronti storici, analisi stagionalità.
GET /api/magazzino-v11/giacenza-a-data?data=2026-12-31&voceCatalogoId=X&magazzinoId=Y- Per performance su dataset grandi: snapshot giornaliero opzionale con
POST /api/magazzino-v11/giacenza-snapshot/genera - Tabella
giacenze_snapshot: UNIQUE (data, magazzino, voce, ubicazione, numLotto)
E. Valorizzazione FIFO / LIFO / CMP selezionabile
Nuovo campo metodoValorizzazione su voci_catalogo: default CMP (costo medio ponderato), selezionabile FIFO o LIFO per articolo.
PATCH /api/magazzino-v11/valorizzazione/:voceCatalogoIdbody{metodo: 'CMP'|'FIFO'|'LIFO'}GET /api/magazzino-v11/valorizzazione/:voceCatalogoId/preview-scarico?quantita=N— mostra strati (movimenti sorgente) che verranno prelevati e costo medio risultante- FIFO: strati ordinati per data ASC (primi entrati primi usciti)
- LIFO: strati ordinati per data DESC (ultimi entrati primi usciti)
- Se giacenza insufficiente: HTTP 409 con dettaglio strati analizzati
F. Seriali univoci + RMA
Gestione del numero di serie per beni singoli (elettronica, strumenti, beni strumentali) con tracciabilità completa dall'ingresso alla dismissione.
- Tabella
seriali_magazzino: numero, voce, lotto, magazzino, stato (ATTIVO/VENDUTO/IN_RMA/IN_RIPARAZIONE/RESO/SCARTATO/SMARRITO), data garanzia - UNIQUE (voce_catalogo_id, numero_seriale) — stesso numero può esistere per articoli diversi
POST /api/magazzino-v11/seriali[ADMIN],GET /seriali?stato=ATTIVO&voceCatalogoId=XPATCH /seriali/:id/stato[ADMIN] — transizioni di stato con data uscita, cliente, documento vendita
G. RMA (Return Merchandise Authorization)
Workflow completo resi tecnici con link al seriale, documento vendita, diagnosi, soluzione applicata.
- Tabella
rma_pratiche: numero, seriale, voce, cliente, stato (APERTA/IN_ANALISI/IN_RIPARAZIONE/RIPARATA/NON_RIPARABILE/SOSTITUITA/RIMBORSATA/CHIUSA) POST /api/magazzino-v11/rma[ADMIN] body{numeroRma, serialeId?, voceCatalogoId, clienteId?, motivoReso, difettoDescrizione}PATCH /api/magazzino-v11/rma/:id/avanzamento[ADMIN] — aggiorna stato + diagnosi + costo + seriale sostituzione + NC- L'apertura RMA con seriale imposta automaticamente il seriale in stato
IN_RMA
H. MRP — Material Requirements Planning
Generazione automatica di proposte d'ordine per articoli sotto scorta minima, con calcolo quantità suggerita basata su scorta_massima o quantita_riordino.
- Tabella
mrp_proposte_ordine: voce, magazzino, quantità suggerita, giacenza attuale, scorta minima, costo stimato, stato (NUOVA/IN_VALUTAZIONE/ORDINATA/ANNULLATA/IGNORATA) - Tabella
mrp_config: scheduler attivo, cron expression, email destinatario alert, giorni copertura target GET/PUT /api/magazzino-v11/mrp/config[ADMIN PUT]POST /api/magazzino-v11/mrp/genera-proposte[ADMIN] — analizza tutte le giacenze sotto scorta e crea proposte (evita duplicati)GET /api/magazzino-v11/mrp/proposte?stato=NUOVA,PATCH /mrp/proposte/:id[ADMIN] — valuta e transiziona
I. Batch import movimenti CSV
Upload CSV per carichi iniziali, rettifiche massive, importazione da sistemi legacy. Mapping colonne automatico, validazione riga per riga, report dettagliato errori.
- Tabella
movimenti_import_batch: righe totali/importate/scartate, errori JSONB, esito (OK/ERRORE/PARZIALE) POST /api/magazzino-v11/import-movimenti[ADMIN] form-datafile(max 15 MB) + querytipoDefault+magazzinoDefaultId- Colonne accettate (case-insensitive, flessibili):
codice_voce | voce_codice | sku | codice,quantita | qty | qta,costo_unitario | costo | prezzo,data,tipo_movimento | tipo,lotto | numLotto,note - Delimitatori supportati:
,;\t GET /api/magazzino-v11/import-movimenti/batch— storico import
J. Carico automatico da fattura passiva
Integrazione con il ciclo passive SDI (wave 8): a partire dalle righe parsed della fattura passiva crea automaticamente i movimenti CARICO_ACQUISTO con costo unitario = prezzo unitario fattura.
- Prerequisito: fattura passiva con righe parsed in
fattura_passiva_righe(eseguire primaPOST /api/fatturazione/sdi-passive/:id/parse-xml) POST /api/magazzino-v11/carico-da-fattura-passiva/:id[ADMIN] body{magazzinoId, forza?}- Matching voce via
codice_articolo_valoredel XML FatturaPA →voci_catalogo.codice - Righe senza corrispondenza catalogo vengono silenziosamente saltate (non bloccante)
- Flag
caricoMagazzinoGeneratoIl+ arraycaricoMovimentiIds[]sufatture_passiveper tracciabilità
MAGAZZINO v 2.2 — 12ª ondata (chiusura residui BASSA)
Chiusura dei 4 residui aperti: listini multi-magazzino, workflow trasferimenti inter-magazzino, regole approvazione granulari per ruolo/categoria, link bidirezionale DDT ↔ RMA. Tutti gli endpoint sotto /api/magazzino-v12/*.
A. Listini multi-magazzino (prezzi per ubicazione)
Nuovo campo magazzinoId su voci_listino (NULL = prezzo globale valido per tutti, valore specifico = prezzo solo per quel magazzino). Utile per aziende multi-sede con politiche commerciali differenziate.
GET /api/magazzino-v12/listini-multi?listinoId=X&voceCatalogoId=Y&magazzinoId=Z— lista con fallback globaleGET /api/magazzino-v12/listini-multi/best-price?voceCatalogoId=X&magazzinoId=Y&data=2026-04-19— ritorna il miglior prezzo applicabile: specifico magazzino vince su globale, a parità priorità listino decidePOST /api/magazzino-v12/listini-multi[ADMIN] — crea/duplica prezzo per magazzino specificoPUT /api/magazzino-v12/listini-multi/:id[ADMIN] — modifica prezzo/date/magazzino- Response include
matchType:SPECIFICO_MAGAZZINOoGLOBALE
B. Trasferimenti inter-magazzino con workflow
Gestione strutturata delle richieste di trasferimento merce tra magazzini con approvazione, tracking trasporto e rilevazione differenze in consegna. Sostituisce l'uso diretto dei movimenti TRASFERIMENTO_IN/OUT con un flusso governato.
Workflow stati
| Stato | Evento | Chi può eseguire |
|---|---|---|
| RICHIESTO | Creazione richiesta con righe | qualunque utente |
| APPROVATO | /approva | ADMIN |
| IN_TRANSITO | /avvia — genera TRASFERIMENTO_OUT | operatore |
| COMPLETATO | /completa — genera TRASFERIMENTO_IN + rileva differenze | operatore destinazione |
| RIFIUTATO | /rifiuta con motivo | ADMIN |
| ANNULLATO | /annulla (non da COMPLETATO) | ADMIN |
Tabelle e campi
- Tabella
trasferimenti_magazzino: numero progressivo annuale, magazzino origine/destinazione, priorità (BASSA/NORMALE/ALTA/URGENTE), vettore, tracking number, date approva/avvia/completa, motivi - Tabella
trasferimento_righe: quantità richiesta / inviata / ricevuta, differenza, motivo differenza, lotto, costo unitario - Collegamento automatico ai movimenti generati (
movimento_out_id,movimento_in_id)
Endpoint
POST /api/magazzino-v12/trasferimentibody{magazzinoOrigineId, magazzinoDestinazioneId, priorita, motivazione, righe:[{voceCatalogoId, quantitaRichiesta, costoUnitario, numLotto}]}POST /trasferimenti/:id/approva[ADMIN]POST /trasferimenti/:id/rifiuta[ADMIN] body{motivo}POST /trasferimenti/:id/avviabody{trackingNumber?, vettoreId?}— genera TRASFERIMENTO_OUT con quantità negativePOST /trasferimenti/:id/completabody{righeRicevute:[{rigaId, quantitaRicevuta, motivoDifferenza}]}— genera TRASFERIMENTO_IN con quantità effettivamente ricevute; conteggio automatico righe con differenzaPOST /trasferimenti/:id/annulla[ADMIN]GET /trasferimenti?stato=IN_TRANSITO&magazzinoOrigineId=XGET /trasferimenti/:id— dettaglio con righe + progress
C. Regole approvazione granulari
Sostituisce la singola soglia globale configurata sulle causali rettifica con un sistema di regole configurabili con priorità. Ogni movimento candidato viene valutato contro le regole attive e la regola con priorità minore (match più specifico) vince.
Parametri regola
tipoMovimento(opzionale) — es. SCARICO_RETTIFICA, CARICO_INIZIALEcausaleRettificaId(opzionale) — causale specifica da causali_rettificacategoriaVoceId(opzionale) — articoli di una categoriamagazzinoId(opzionale) — magazzino specificosogliaValoreEur(opzionale) — soglia €ruoloMinimoApprovatore: UTENTE | OPERATORE | MANAGER | ADMIN | SUPERADMINemailNotificaApprovatori: lista email separata da virgola per notifiche pushpriorita: numero intero — più basso vince (specificità maggiore)
Seed regole default
| Nome | Tipo | Soglia | Ruolo richiesto | Priorità |
|---|---|---|---|---|
| Furti (qualsiasi importo) | SCARICO_RETTIFICA | € 0,01 | ADMIN | 10 |
| Carichi manuali > 5000 € | CARICO_INIZIALE | € 5.000 | ADMIN | 30 |
| Rettifiche > 1000 € | SCARICO_RETTIFICA | € 1.000 | MANAGER | 50 |
Endpoint
GET/POST /api/magazzino-v12/regole-approvazione[ADMIN POST]PUT /api/magazzino-v12/regole-approvazione/:id[ADMIN]DELETE /api/magazzino-v12/regole-approvazione/:id[ADMIN] — soft-delete (attivo = false)POST /api/magazzino-v12/regole-approvazione/checkbody{tipoMovimento, causaleRettificaId, categoriaVoceId, magazzinoId, valoreEur}— verifica se un movimento candidato richiede approvazione e quale ruolo la può concedere
D. DDT reso ↔ RMA link bidirezionale
Collegamento robusto tra pratica RMA (wave 11) e i DDT coinvolti (reso dal cliente + eventuale sostituzione). Navigazione bidirezionale: da RMA ai suoi documenti, da documento alla RMA.
Campi aggiunti
rma_pratiche.ddt_reso_id— DDT con cui il cliente ha restituito il benerma_pratiche.ddt_sostituzione_id— DDT con cui è stato spedito il bene sostitutivodocumenti.rmaPraticaId— riferimento inverso per navigazione rapida
Endpoint
POST /api/magazzino-v12/ddt-rma-link[ADMIN] body{rmaId, ddtResoId?, ddtSostituzioneId?}— crea link bidirezionaleGET /api/magazzino-v12/ddt-rma-link/rma/:rmaId— restituisce RMA + documenti collegati (ddtReso, ddtSostituzione, documentoOrigine, notaCredito) con numero, data, tipo, statoGET /api/magazzino-v12/ddt-rma-link/documento/:docId— dato un documento trova la RMA collegataPOST /api/magazzino-v12/rma/:id/log-transizione— registra transizione di stato inrma_log_transizioniper auditGET /api/magazzino-v12/rma/:id/log— storico transizioni di stato
Voce sidebar Magazzino > Back-Order. Pagina dedicata agli articoli in attesa di evasione: quando un DDT esce con quantità minori di quanto richiesto (per scarsa giacenza, conversione parziale ordine, ecc.) le righe non spedite finiscono qui, da consegnare appena disponibili.
Come si crea un back-order
Modo principale: dal dialog di conversione ORD → DDT con il toggle «Genera back-order per le quantità non spedite» (acceso di default). Per ogni riga con qta non trasferita nel DDT viene creata automaticamente una riga di back-order, collegata al DDT origine.
Pagina Back-Order
Mostra in cima 3 stat card (Pendenti / Parziali / Totale attivi). Filtro per stato in alto (default mostra solo PENDENTI e PARZIALI, escludendo evasi/annullati).
Per ogni riga vedi: descrizione articolo, cliente, DDT origine, quantità attesa, fornita, residuo, stato, data creazione. Azioni:
- Matita: edit inline della
quantitaFornita; lo stato si aggiorna automaticamente (PENDENTE / PARZIALE / EVASO) - ✓ Marca evaso: imposta quantità fornita = quantità attesa, stato → EVASO
- ✕ Annulla: stato → ANNULLATO (es. cliente ha rinunciato)
Stati
- PENDENTE: nessuna fornitura ancora registrata
- PARZIALE: quantità fornita parziale, in attesa del resto
- EVASO: completamente fornito (chiuso)
- ANNULLATO: cancellato senza evasione