Sistema di Notifiche
Panoramica
Il sistema di notifiche permette di informare gli utenti di eventi importanti, operazioni automatiche e azioni che richiedono attenzione. Le notifiche sono categorizzate per tipo, priorità e categoria, e possono includere azioni da intraprendere.
Modello Dati
Notification Schema
{
tenant_id: ObjectId (required) - Tenant di appartenenza
user_id: ObjectId (optional) - Utente specifico (null = tutti gli utenti)
title: string - Titolo della notifica
message: string - Messaggio dettagliato
type: "info" | "success" | "warning" | "error" - Tipo di notifica
priority: "low" | "medium" | "high" | "urgent" - Priorità
category: "system" | "inventory" | "sales" | "costs" | "invoices" | "general"
actionUrl: string (optional) - URL dell'azione associata
actionLabel: string (optional) - Label del pulsante azione
metadata: Object (optional) - Dati aggiuntivi
isRead: boolean - Stato di lettura
readAt: Date (optional) - Data di lettura
source: string (optional) - Origine della notifica
expiresAt: Date (optional) - Data di scadenza
createdAt: Date - Data di creazione
updatedAt: Date - Data di aggiornamento
}API Endpoints
GET /api/notifications
Recupera le notifiche dell’utente corrente.
Query Parameters:
unreadOnly(boolean) - Solo notifiche non lettelimit(number) - Limite risultati (default: 50)category(string) - Filtra per categoria
Response:
{
"success": true,
"notifications": [...],
"unreadCount": 5
}POST /api/notifications
Crea una nuova notifica.
Body:
{
"user_id": "optional_user_id",
"title": "Titolo notifica",
"message": "Messaggio dettagliato",
"type": "warning",
"priority": "high",
"category": "inventory",
"actionUrl": "/inventario",
"actionLabel": "Gestisci Inventario",
"metadata": { "productId": "123" },
"source": "job:inventory-check"
}PUT /api/notifications
Aggiorna lo stato delle notifiche.
Body (marca come letta):
{
"notificationIds": ["id1", "id2"],
"markAsRead": true
}Body (marca tutte come lette):
{
"markAllAsRead": true
}DELETE /api/notifications
Elimina notifiche.
Query Parameters:
id(string) - ID notifica da eliminaredeleteAll(boolean) - Elimina tutte le notifiche lette
Utility Functions
Il file src/lib/notifications.ts fornisce funzioni helper per creare notifiche comuni:
createNotification(params)
Funzione generica per creare qualsiasi tipo di notifica.
await createNotification({
tenant_id: "tenant123",
title: "Titolo",
message: "Messaggio",
type: "info",
priority: "medium",
category: "general",
});notifyLowStock(tenant_id, productName, currentStock, productId)
Notifica per stock basso.
await notifyLowStock(tenant_id, "Farina 00", 5, "product_id");notifyInvoiceImported(tenant_id, invoiceNumber, supplierName, amount, invoiceId)
Notifica per fattura importata.
await notifyInvoiceImported(
tenant_id,
"FT-2024-001",
"Fornitore Rossi",
1500.0,
"invoice_id",
);notifySyncError(tenant_id, service, errorMessage)
Notifica per errore di sincronizzazione.
await notifySyncError(tenant_id, "Cassa in Cloud", "API Key non valida");notifyHighFoodCost(tenant_id, productName, foodCostPercentage, productId)
Notifica per food cost elevato.
await notifyHighFoodCost(tenant_id, "Pizza Margherita", 45.5, "product_id");notifyUnusualSales(tenant_id, message, changePercentage)
Notifica per andamento vendite anomalo.
await notifyUnusualSales(
tenant_id,
"Le vendite sono aumentate del 25% questa settimana",
25,
);notifySystemMessage(tenant_id, title, message, priority)
Notifica generica di sistema.
await notifySystemMessage(
tenant_id,
"Manutenzione Programmata",
"Il sistema sarà in manutenzione domenica dalle 2:00 alle 4:00",
"medium",
);Componenti UI
NotificationBell
Componente campana per l’header che mostra il badge con il conteggio notifiche non lette.
Caratteristiche:
- Badge con conteggio notifiche non lette
- Dropdown con ultime 20 notifiche
- Polling automatico ogni 30 secondi
- Click per marcare come letta
- Azioni rapide (elimina, segna tutte lette)
Uso:
import { NotificationBell } from "@/components/NotificationBell";
<NotificationBell />;Pagina Notifiche (/notifiche)
Pagina completa per gestire tutte le notifiche.
Caratteristiche:
- Visualizzazione completa di tutte le notifiche
- Filtri (tutte/non lette)
- Badge priorità e categoria
- Azioni (segna letta, elimina singola, elimina tutte lette)
- Indicatori visivi per tipo e priorità
- Link alle azioni associate
Integrazione nel Codice
Esempio: Generazione notifica dopo importazione fattura
import { notifyInvoiceImported } from "@/lib/notifications";
// Dopo il salvataggio della fattura
const invoice = await Invoice.create(invoiceData);
await notifyInvoiceImported(
tenant_id,
invoice.invoice_number,
invoice.supplier.name,
invoice.total,
invoice._id.toString(),
);Esempio: Notifica da Job/Cron
import { notifyLowStock, notifyHighFoodCost } from "@/lib/notifications";
// In un job che controlla l'inventario
async function checkInventory() {
const products = await SellingProduct.find({
isSemifinished: true,
stockEstimate: { $lt: 10 },
});
for (const product of products) {
await notifyLowStock(
product.tenant_id,
product.name,
product.stockEstimate,
product._id.toString(),
);
}
}Esempio: Notifica da API
// In una route API
import { createNotification } from "@/lib/notifications";
export async function POST(request: Request) {
const { tenant_id } = requireAuth(request);
// ... logica applicativa ...
await createNotification({
tenant_id,
title: "Operazione Completata",
message: "L'operazione è stata completata con successo",
type: "success",
priority: "low",
category: "general",
source: "api:custom-operation",
});
}Best Practices
- Priorità: Usa
urgentsolo per situazioni critiche che richiedono attenzione immediata - Categorie: Mantieni le categorie coerenti per permettere filtri efficaci
- Azioni: Quando possibile, fornisci sempre
actionUrleactionLabelper notifiche che richiedono follow-up - Metadata: Usa il campo metadata per memorizzare informazioni contestuali utili
- Source: Specifica sempre la source per tracciare l’origine delle notifiche
- Scadenza: Usa
expiresAtper notifiche temporanee (es. promozioni, eventi) - Target: Usa
user_id: nullper notifiche broadcast a tutto il tenant
Notifiche Automatiche Implementate
✅ Fatture
- Fattura importata con successo
🔄 Da Implementare
- Stock basso (job automatico)
- Food cost elevato (analisi periodica)
- Errori sincronizzazione servizi esterni
- Andamento vendite anomalo
- Scadenze pagamenti fornitori
- Prodotti in scadenza
- Obiettivi food cost raggiunti/mancati
- Backup completati
- Aggiornamenti sistema
Performance
Indici MongoDB
{ tenant_id: 1, isRead: 1, createdAt: -1 }- Query principali{ tenant_id: 1, user_id: 1, isRead: 1 }- Filtri utente{ expiresAt: 1 }- TTL index per pulizia automatica
Polling
Il componente NotificationBell effettua polling ogni 30 secondi per aggiornare il conteggio.
Cleanup
Le notifiche con expiresAt vengono eliminate automaticamente da MongoDB tramite TTL index.
Estensibilità
Il sistema è progettato per essere facilmente estendibile:
- Nuovi tipi: Aggiungi nuovi tipi al enum
typenel modello - Nuove categorie: Aggiungi nuove categorie al enum
category - Nuove helper functions: Crea funzioni in
lib/notifications.tsper casi d’uso specifici - Integrazione WebSocket: Possibile implementare notifiche real-time con WebSocket
- Email notifications: Possibile aggiungere invio email per notifiche prioritarie
- Push notifications: Possibile implementare push notifications per mobile