Ruolo & ambito
Cookinglife (e-commerce di articoli da cucina, affiancato da negozi fisici) gestisce l'intero processo di magazzino su un sistema che ho costruito e che continuo a far evolvere: acquisizione ordini, picking (singolo, batch, con carrello e multi-livello), gestione delle giacenze e delle ubicazioni, imballaggio, etichette di spedizione e sincronizzazione con NetSuite come ERP. Accanto alla manutenzione continua, la piattaforma PHP esistente viene migrata a Laravel modulo per modulo, senza interruzioni di servizio.
- Dall'acquisizione dell'ordine alla spedizione: un unico sistema per l'intero processo di fulfilment, collegato a NetSuite come fonte di verità per ordini e giacenze.
- Più metodi di picking (singolo, batch, carrello, multi-livello) e scansione dei codici a barre in reparto tramite OnScan.js.
- Etichette di spedizione multi-corriere via Sendcloud, con un job di sweep dedicato che preleva le etichette non appena NetSuite le crea dopo lo stato «packed».
- Integrazioni con Shopify e Magento, oltre alla normalizzazione di indirizzi e numeri di telefono tramite Alumio.
- Migrazione a Laravel senza downtime: modulo per modulo (ordini, picking, giacenze, spedizioni, NetSuite, admin) tramite routing nginx, con rollback immediato per singolo modulo.
Impatto
- Un unico sistema per l'intero processo di fulfilment invece di strumenti separati per picking, giacenze e spedizioni.
- Risolto un errore strutturale di NetSuite sugli ordini kit (prodotti composti da più componenti) allocando automaticamente le giacenze su più ubicazioni invece di pretendere che tutto stesse in una sola.
- Eliminata una race condition tra la creazione e il prelievo delle etichette di spedizione con un job di sincronizzazione ricorrente, così le etichette non si perdono più di tanto in tanto.
- Un percorso di spedizione di riserva per quando il WMS cade fuori orario d'ufficio, con riconciliazione perché gli ordini non ricompaiano doppi nella coda di picking.
- Quasi due anni in produzione continua (848 commit da agosto 2024) — non un progetto greenfield ma un sistema che continua a crescere con l'azienda.
Architettura
Tre livelli: un Core condiviso, il modulo TailorFitWMS stesso e gli Overwrites per cliente — così le personalizzazioni specifiche di un'azienda non finiscono nel nucleo. Le funzionalità sono costruite come moduli plugin attivabili o disattivabili per azienda, con punti di estensione event-driven. I dati stanno in MySQL (dati transazionali), MongoDB (documenti) e Redis (cache e sessioni); il lavoro in background (sync delle etichette, task NetSuite) passa da Laravel Horizon, con 100-500 job all'ora. La migrazione in corso dalla piattaforma PHP esistente a Laravel avviene modulo per modulo tramite location block di nginx, così ogni parte può essere rilasciata e ripristinata separatamente senza toccare il resto.
Scelta del modello
Nessuna AI/LLM nel cuore di questa piattaforma: la logica di fulfilment (giacenze, picking, spedizioni, sincronizzazione ERP) richiede prevedibilità e tracciabilità, non la flessibilità di un modello linguistico. La principale «scelta di modello» qui è architetturale, non di AI: passare dal framework PHP proprietario esistente a Laravel per un ecosistema di strumenti più ampio e una migliore manutenibilità, ma gradualmente e modulo per modulo invece che con un rewrite big-bang, per limitare il rischio su un sistema che governa un magazzino 24 ore su 24.
Costi & latenza
- L'ambiente di produzione gira su 5 servizi Docker, ciascuno con 8 CPU / 8 GB assegnati — un dimensionamento adatto a un sistema che elabora di continuo traffico di ordini e NetSuite, non solo ai picchi.
- Le etichette di spedizione sono volutamente asincrone: NetSuite crea l'etichetta solo dopo lo stato «packed», quindi il sistema non deve attendere — un job di sweep raccoglie le etichette ogni 3 minuti invece di interrogare ordine per ordine.
- L'integrazione NetSuite (OAuth1 TBA, SOAP + RESTlet + REST) è l'anello più lento della catena; le azioni locali di magazzino come scansione e picking continuano a funzionare indipendentemente.
Lezioni apprese
Gli ordini kit (prodotti composti da più componenti) si bloccavano sull'errore VALID_LINE_ITEM_REQD di NetSuite, perché la giacenza dei componenti era distribuita su più ubicazioni mentre NetSuite si aspettava una sola ubicazione per riga. Risolto riscrivendo l'integrazione RESTlet in modo che la giacenza si allochi automaticamente su più ubicazioni. Le etichette di spedizione ogni tanto sparivano per una race condition tra il momento in cui NetSuite crea l'etichetta e quello in cui il sistema la preleva; un job di sweep ricorrente ogni 3 minuti ha risolto la cosa strutturalmente invece che con una patch una tantum. E per le sere e i fine settimana in cui è il WMS stesso a cadere, esiste un percorso d'emergenza esterno per continuare a spedire — con una logica di riconciliazione che impedisce a quegli stessi ordini di ricomparire doppi nella coda di picking quando il sistema torna online.