APAndrea Pellizzari
Tutti i lavori
SaaS B2B

Sistema di assistenza ticket con plugin Outlook VSTO, AI summary con Claude e integrazione Mexal via proxy PHP

Piattaforma di gestione ticket per assistenza clienti B2B, in produzione interna su due istanze gemelle (stessa codebase, deploy separati). Plugin Outlook nativo VSTO .NET che allega email al ticket con un click, riassunti AI generati da Claude via tool calling, integrazione Mexal per anagrafiche e storico ordini, access-token pubblici per condivisione sicura con riparatori esterni.

Next.js 16TypeScriptNeon PostgreSQLVercel BlobOutlook VSTO (.NET)WPF Email Uploader+3
Cliente
PMI manifatturiere italiane del Nordest, due istanze gemelle
Ruolo
Architettura, sviluppo full-stack, plugin Outlook VSTO, integrazione Claude, proxy Mexal
Durata
6 mesi al primo core operativo, sviluppo attivo
Anno
2026
Stack tecnico
Next.js 16TypeScriptNeon PostgreSQLVercel BlobOutlook VSTO (.NET)WPF Email UploaderClaude APIMexal WebAPIPHP proxy

Contesto

Due PMI manifatturiere del Nordest con struttura simile: rete di dealer B2B, assistenza post-vendita in capo a un team ristretto di operatori, la maggior parte delle richieste che arriva via email su caselle generiche e viene lavorata direttamente in Outlook. Canali secondari: telefono ritrascritto a mano, chat saltuaria, form di contatto. Risultato: nessuno aveva la storia completa del cliente, le richieste "cadevano nel vuoto", il cliente ripeteva la stessa cosa a interlocutori diversi.

Sfida

Costruire una piattaforma di ticketing che mettesse ordine senza costringere gli operatori a cambiare strumento quotidiano (Outlook), che si integrasse con il gestionale Mexal per non duplicare anagrafiche e storico ordini, e che potesse girare come due istanze gemelle — stessa codebase, due deploy separati, due database Neon indipendenti, branding diverso. Niente multi-tenant con tenantId su tabella condivisa: isolamento per deploy, più semplice da auditare e più sicuro tra clienti che non devono vedersi i dati.

Approccio

Stack Next.js 16 + TypeScript + Neon PostgreSQL + Vercel Blob, con Claude API per le feature AI-assisted. Di seguito le feature che fanno la differenza — non le cose standard di un sistema di ticketing.

Plugin Outlook VSTO nativo: allega email al ticket con un click

Un add-in VSTO in .NET/C# (non Office.js, scelta deliberata per lavorare direttamente sull'object model di Outlook desktop) che aggiunge un ribbon "ArcoService" in Outlook. L'operatore seleziona l'email, apre il dialog di ricerca ticket, seleziona il ticket corrispondente, e il plugin invia il .msg completo al backend via POST /api/tickets/{id}/attach-email in multipart form-data con header x-api-key. Il backend estrae mittente, destinatari, oggetto, preview corpo, allegati, carica il .msg su Vercel Blob e crea un record TicketEmail agganciato al ticket. Distribuzione via installer ClickOnce, configurazione UI per API key e URL backend.

Email Uploader WPF come alternativa drag&drop

Per gli operatori che preferiscono lavorare fuori da Outlook — o che usano client di posta diversi — una seconda applicazione Windows in WPF (.NET 8) permette di trascinare file .msg direttamente sul desktop app e caricarli sul ticket. Usa MsgReader.dll per il parsing dei messaggi Outlook, stesso endpoint del plugin. Due strade per lo stesso risultato, perché non tutti lavorano nello stesso modo.

Proxy PHP lato server per Mexal, credenziali mai nel frontend

Le API Next.js non chiamano direttamente Mexal WebAPI: passano da un micro-proxy PHP ospitato su un hosting esterno (SiteGround), autenticato con header X-Proxy-Secret, che aggiunge le credenziali Mexal server-side e inoltra la richiesta via HTTPS. Significa che il deploy Vercel non conosce le credenziali del gestionale, la superficie d'attacco è ridotta, e se compromesso il frontend non porta a compromissione diretta del gestionale. Dodici endpoint coperti: anagrafiche clienti, storico ordini, articoli venduti a un cliente, movimenti magazzino, documenti DDT/fatture, esposizione crediti-debiti.

Claude come motore di riassunti strutturati con tool calling

Sul ticket è disponibile un'azione "genera riassunto AI": un endpoint POST /api/tickets/{id}/summary che raccoglie l'intero thread (email allegate + messaggi operatori + commenti interni), lo passa a Claude Sonnet via callClaudeWithTools() — wrapper proprio con supporto tool use — e riceve un riassunto in formato strutturato (Riepilogo, Cronologia Interventi datata, Esito, Documenti collegati, Note). Il summary viene persistito in ticket_summaries per evitare di pagare di nuovo l'inferenza a ogni apertura ticket. Non è un chatbot, è un digest ragionato.

access_token pubblici per scambio con fornitori e riparatori esterni

Ogni ticket ha un access_token generato da un trigger PostgreSQL (32 byte base64) salvato sulla riga. Lo si passa in URL /ticket/[access_token] a un riparatore terzo o a un fornitore esterno per dargli accesso al ticket senza aprirgli un account — vede messaggi pubblici, allegati pubblici, può caricare la sua risposta. JWT per gli interni, access_token per gli esterni: due modelli di sicurezza separati per due categorie di utenti.

Schema ticket-centric con audit trail immutabile e escalation multi-tier

La tabella ticket_history è append-only (nessun update): ogni cambio stato, assegnazione, escalation finisce lì come riga. ticket_escalations permette catene a più livelli (ticket → escalation a riparatore → escalation a produttore) dove ogni livello ha propri commenti, stato e assegnazioni, ma resta legato al ticket padre. Quando un cliente chiede "perché il mio problema è ancora aperto", l'audit risponde con evidenza.

Stato attuale: core stabile, modulo agenti in rifattorizzazione

Il sistema di ticketing è in produzione interna su entrambe le istanze, il plugin Outlook è usato quotidianamente, l'integrazione Mexal gira, l'AI summary è attiva. Sto rifattorizzando un modulo parallelo (portale agenti commerciali: catalogo, budget, visite) che vive nella stessa codebase ma tocca un dominio diverso — rewrite degli hook data-fetching, store Zustand più leggero, UI KPI più reattiva. Il ticketing non è toccato da questa rifattorizzazione: è la parte stabile su cui sto costruendo.

La case study è qui ora perché il lavoro fatto è significativo — sei mesi di architettura coerente, plugin desktop nativo, tre modelli di sicurezza diversi (JWT interni, access_token esterni, proxy PHP Mexal) — e perché quando qualcosa non è al 100% lo dico, invece di vendere come "completo" un prodotto in evoluzione. Quando il rilascio al cliente finale sarà fatto, aggiorno numeri e apprendimenti.