Files
demat-facturation/todo.md
2026-08-30 08:56:27 +00:00

828 lines
46 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Invoice Analyzer - TODO
## Phase 1: Base de données et schéma
- [x] Créer table users avec support authentification locale + Azure AD
- [x] Créer table sourceFiles pour fichiers PDF uploadés
- [x] Créer table invoices pour factures extraites
- [x] Créer table userSettings pour paramètres utilisateur
- [x] Créer table importLogs pour historique des imports
- [x] Créer table llmLogs pour logs des appels LLM
- [x] Pousser les migrations avec pnpm db:push
## Phase 2: Authentification
- [x] Implémenter authentification locale (email/password avec bcrypt)
- [x] Implémenter authentification Azure AD avec MSAL
- [x] Créer helpers de génération de tokens JWT
- [x] Créer middleware de vérification des rôles (user/admin)
## Phase 3: Stockage et extraction IA
- [x] Créer helper de stockage local avec préfixe YYYY-MM
- [x] Implémenter extraction PDF avec Mistral OCR
- [x] Implémenter extraction de métadonnées avec Mistral LLM
- [x] Créer système de scoring de qualité (0-100)
- [x] Implémenter détection de doublons
- [x] Créer helper de génération de fichiers JSON de métadonnées
- [x] Implémenter logger LLM pour debug
## Phase 4: Export SFTP
- [x] Créer helper de connexion SFTP
- [x] Implémenter export manuel de factures
- [x] Implémenter export automatique de factures
- [x] Créer test de connexion SFTP
## Phase 5: Routes tRPC
- [x] Routes auth (me, loginLocal, getAzureLoginUrl, logout)
- [x] Routes invoices (upload, list, getById, update, delete, search, getStats)
- [x] Routes sourceFiles (getByIds pour polling)
- [x] Routes settings (get, upsert)
- [x] Routes admin (createUser, getAllUsers, updatePassword, toggleActive, deleteUser)
- [x] Routes sftp (testConnection, exportInvoices)
- [x] Routes importLogs (getByUser)
- [x] Routes llmLogs (getBySourceFile, getByInvoice)
## Phase 6: Pages Frontend
- [x] Page Login avec formulaire local + bouton Azure AD
- [x] Page Dashboard avec statistiques et graphiques
- [x] Page Upload avec drag-and-drop et suivi temps réel
- [x] Page Invoices avec liste, recherche, filtres, pagination
- [x] Page Settings avec configuration LLM, keywords, SFTP
- [x] Page History avec logs et détails
- [x] Page Users (admin) pour gestion des utilisateurs
- [x] Layout avec navigation adaptée (DashboardLayout)
- [x] Configuration des routes dans App.tsx
## Phase 7: Tests et finalisation
- [x] Tests unitaires d'authentification (hashPassword, verifyPassword, JWT)
- [x] Tests de logout avec cookies multiples
- [x] Vérification du build et de la compilation TypeScript
- [x] Vérification du serveur de développement
- [x] Créer le checkpoint final
## Corrections et améliorations
- [x] Créer un utilisateur administrateur avec login adminServFacturation
- [x] Tester la connexion locale avec le nouvel utilisateur
- [x] Modifier l'email de l'administrateur de adminServFacturation à o.pareige@itinova.org
- [x] Diagnostiquer le problème de connexion locale avec o.pareige@itinova.org
- [x] Corriger l'authentification locale (ajout support cookie auth_token)
## Amélioration du Dashboard
- [x] Créer route tRPC pour statistiques détaillées (factures par semaine, top fournisseurs)
- [x] Créer cartes de statistiques (Factures traitées, Montant total, Score moyen, Dernière activité)
- [x] Créer graphique en barres des factures par semaine (Recharts)
- [x] Créer graphique circulaire du top 10 fournisseurs (Recharts)
- [x] Créer liste détaillée des fournisseurs avec nombre de factures
- [x] Ajouter bouton "Voir les statistiques détaillées"
## Modification page Factures - Export PDF
- [x] Ajouter champ exportStatus dans le schéma invoices (exported/not_exported/export_error)
- [x] Ajouter champ exportedAt dans le schéma invoices (déjà existant)
- [x] Créer route tRPC pour exporter les factures en PDF
- [x] Créer route tRPC pour mettre à jour le statut d'export
- [x] Ajouter cases à cocher pour sélection multiple dans la page Factures
- [x] Ajouter case "Tout sélectionner"
- [x] Modifier l'affichage des statuts (Exporté/Non exporté/Erreur export)
- [x] Ajouter bouton "Exporter" (actif uniquement pour score 100%)
- [x] Implémenter le téléchargement de PDF pour les factures sélectionnées
- [x] Valider que seules les factures avec score 100% peuvent être exportées
## Nouvelles fonctionnalités
- [x] Ajouter des boutons de filtre par statut d'export (Tous/Exportés/Non exportés/Erreurs)
- [x] Créer route tRPC pour export Excel
- [x] Créer page InvoiceDetail avec visualisation des métadonnées
- [x] Ajouter formulaire d'édition manuelle des champs
- [x] Implémenter la mise à jour des métadonnées
- [x] Recalculer le score de qualité après édition manuelle
- [x] Ajouter bouton "Export Excel" dans la page Factures
- [x] Générer fichier Excel avec toutes les métadonnées
## Correction export PDF
- [x] Diagnostiquer le problème d'export PDF (URLs non accessibles)
- [x] Corriger la route exportToPdf pour retourner les bonnes URLs
- [x] Modifier le code client pour ouvrir les PDFs dans de nouveaux onglets
- [x] Ajouter un délai entre chaque ouverture pour éviter le blocage des popups
## Correction erreur 404 PDF
- [x] Vérifier la configuration Express pour servir les fichiers statiques
- [x] Vérifier les URLs générées pour les fichiers PDF
- [x] Identifier que les fichiers n'ont pas été stockés lors de l'import initial
- [x] Ajouter bouton "Supprimer" pour supprimer les factures sélectionnées
- [x] Créer le dossier storage pour le stockage local
## Correction bouton Supprimer
- [x] Permettre la sélection de toutes les factures pour suppression (pas seulement celles à 100%)
- [x] Séparer la logique de sélection pour export et suppression
- [x] Supprimer les restrictions disabled sur les checkboxes
- [x] Ajouter validation pour export PDF (seulement score 100%)
## Diagnostic problème 404 persistant
- [ ] Vérifier si les fichiers sont stockés dans le dossier storage
- [ ] Vérifier les URLs générées dans la base de données
- [ ] Vérifier la configuration Express pour servir les fichiers statiques
- [ ] Corriger le chemin d'accès aux fichiers PDF
## Correction formulaire d'édition
- [x] Pré-remplir les valeurs existantes dans le formulaire d'édition de facture
- [x] Utiliser useEffect pour initialiser les valeurs du formulaire
## Amélioration visuelle formulaire d'édition
- [x] Ajouter un bord rouge sur les champs vides du formulaire d'édition
- [x] Identifier visuellement les données manquantes non extraites par l'IA
## Correction stockage PDF
- [x] Diagnostiquer pourquoi localStoragePut ne sauvegarde pas les fichiers
- [x] Vérifier si les données PDF sont bien reçues dans la route upload
- [x] Identifier le bug: l'URL de localStoragePut était écrasée par une URL locale
- [x] Corriger la route upload pour utiliser l'URL retournée par localStoragePut
- [ ] Tester le stockage avec un upload réel
## Paramètres de réception
- [x] Créer table importSettings dans le schéma de base de données
- [x] Ajouter routes tRPC pour gérer les paramètres de réception (get, update)
- [x] Créer page Paramètres de réception avec configuration import manuel/automatique/email
- [x] Implémenter activation/désactivation import manuel
- [x] Implémenter activation/désactivation import automatique avec dossier source et fréquence
- [x] Implémenter activation/désactivation import par email avec compte mail et mot de passe
- [x] Tester la sauvegarde et récupération des paramètres
## Correction page Paramètres de réception
- [x] Ajouter DashboardLayout à la page ImportSettings pour afficher le menu latéral
## Import automatique par email
- [x] Installer les dépendances npm pour IMAP (imap et mailparser)
- [x] Créer le service emailImportService.ts pour se connecter à IMAP
- [x] Implémenter la détection des nouveaux emails non lus avec pièces jointes PDF
- [x] Implémenter le téléchargement et traitement des pièces jointes
- [x] Implémenter le marquage des emails comme lus après traitement
- [x] Créer un scheduler pour exécuter le service selon la fréquence configurée
- [x] Ajouter des routes tRPC pour démarrer/arrêter le service
- [x] Ajouter des boutons de contrôle du service dans la page Paramètres de réception
- [ ] Tester l'import automatique par email avec un vrai compte
## Import automatique depuis dossier
- [x] Installer la dépendance chokidar pour surveiller les dossiers
- [x] Créer le service folderImportService.ts pour surveiller un dossier
- [x] Implémenter la détection des nouveaux fichiers PDF dans le dossier
- [x] Implémenter le traitement des fichiers détectés
- [x] Implémenter le déplacement des fichiers traités vers un sous-dossier "processed"
- [x] Créer un scheduler pour vérifier le dossier selon la fréquence configurée
- [x] Ajouter des routes tRPC pour démarrer/arrêter le service
- [x] Ajouter des boutons de contrôle dans la page Paramètres de réception
## Système de notifications
- [x] Créer le service notificationService.ts pour gérer les notifications
- [x] Implémenter l'envoi de notifications après import automatique email
- [x] Implémenter l'envoi de notifications après import automatique dossier
- [x] Inclure le résumé : nombre de factures importées, doublons ignorés, erreurs
- [ ] Tester les fonctionnalités avec des données réelles
## Bouton effacer les logs d'import
- [x] Ajouter fonction deleteAllImportLogs dans db.ts
- [x] Ajouter route tRPC importLogs.deleteAll
- [x] Ajouter bouton "Effacer les logs" dans la page History
- [x] Ajouter confirmation avant suppression (AlertDialog)
- [x] Tester la fonctionnalité
## Bug : Import automatique par email ne fonctionne pas
- [x] Vérifier la configuration IMAP dans la base de données
- [x] Vérifier si le service d'import email est démarré
- [x] Ajouter un bouton "Vérifier maintenant" pour forcer une vérification immédiate
- [x] Ajouter fonction triggerEmailCheck dans emailImportService
- [x] Ajouter route tRPC emailImportService.checkNow
- [ ] Tester avec un email réel et diagnostiquer les erreurs IMAP
## Bugs interface ImportSettings
- [x] Corriger l'encodage Unicode du bouton "Vérifier maintenant"
- [x] Ajouter rafraîchissement automatique du statut du service après démarrage/arrêt (email et dossier)
## Champs métier pour les factures
- [x] Ajouter colonnes service_concerne, type_achat, ventilation_comptable à la table invoices
- [x] Créer table departmentList pour gérer la liste "Service concerné"
- [x] Créer table accountingAllocationList pour gérer la liste "Ventilation comptable"
- [x] Ajouter routes tRPC pour CRUD des listes enrichissables
- [x] Créer page d'administration pour gérer les listes (ListsAdmin.tsx)
- [x] Ajouter les champs dans le formulaire d'édition de facture (InvoiceDetail.tsx)
- [x] Ajouter les colonnes dans la liste des factures (Invoices.tsx)
- [x] Initialiser les valeurs par défaut dans les tables (initializeDefaultLists)
- [x] Ajouter le lien "Administration des listes" dans le menu de navigation
## Bug : Erreur lors de l'ajout d'un service
- [x] Corriger la fonction initializeDefaultLists pour éviter les erreurs de duplication
- [x] Vérifier que l'ajout de services et ventilations fonctionne correctement
## Chargement dynamique des listes dans le formulaire
- [x] Modifier InvoiceDetail.tsx pour charger les listes depuis la base de données
- [x] Remplacer les valeurs codées en dur par des appels tRPC
- [x] Tester que les valeurs personnalisées apparaissent dans les menus déroulants
## Boutons Modifier et Supprimer dans la liste des factures
- [x] Ajouter une colonne "Actions" dans le tableau des factures
- [x] Ajouter un bouton "Modifier" qui redirige vers InvoiceDetail
- [x] Ajouter un bouton "Supprimer" avec confirmation (AlertDialog)
- [x] Utiliser la route tRPC existante pour supprimer une facture
- [x] Tester la suppression avec confirmation
## Édition directe des champs métier dans la liste
- [x] Charger les listes de services et ventilations dans la page Invoices
- [x] Transformer la cellule Service en menu déroulant éditable
- [x] Transformer la cellule Type d'achat en menu déroulant éditable
- [x] Transformer la cellule Ventilation en menu déroulant éditable
- [x] Sauvegarder automatiquement les modifications (mutation updateFieldMutation)
- [x] Afficher une notification de succès après sauvegarde
## Ajout dynamique depuis les menus déroulants
- [x] Ajouter option "➜ Ajouter..." dans le menu Service
- [x] Ajouter option "➜ Ajouter..." dans le menu Ventilation
- [x] Créer une boîte de dialogue pour saisir le nouveau nom
- [x] Sauvegarder la nouvelle entrée dans la base de données (createDepartmentMutation, createAllocationMutation)
- [x] Sélectionner automatiquement la nouvelle valeur pour la facture
- [x] Rafraîchir les listes après ajout (invalidate queries)
## Affichage du texte extrait de la facture
- [x] Ajouter une colonne extractedText dans la table invoices
- [x] Modifier le prompt Mistral pour demander le texte extrait
- [x] Modifier le type ExtractedInvoiceData pour inclure extractedText
- [x] Modifier routers.ts, emailImportService.ts et folderImportService.ts pour sauvegarder extractedText
- [x] Ajouter un bouton "Détail" (icône FileText) dans la liste des factures
- [x] Créer une boîte de dialogue pour afficher le texte complet
- [ ] Tester l'affichage du texte extrait avec une nouvelle facture importée
## Champ Abonnement pour les factures
- [x] Ajouter colonne isSubscription (OUI/NON) à la table invoices avec valeur par défaut NON
- [x] Ajouter champ subscriptionKeywords dans la table userSettings
- [x] Ajouter interface pour gérer les mots-clés d'abonnement dans la page Settings
- [x] Modifier l'extraction pour détecter automatiquement les abonnements via mots-clés
- [x] Modifier le prompt Mistral pour demander isSubscription
- [x] Modifier routers.ts, emailImportService.ts et folderImportService.ts pour utiliser subscriptionKeywords
- [x] Ajouter la colonne Abonnement dans la liste des factures
- [x] Permettre l'édition directe du champ Abonnement dans la liste (select OUI/NON)
- [x] Ajouter isSubscription dans le schéma de validation update
- [ ] Tester la détection automatique avec une nouvelle facture importée
## Bug : Détection incorrecte du champ Abonnement
- [x] Analyser le prompt Mistral pour comprendre pourquoi isSubscription est à OUI
- [x] Identifier le problème: mots-clés génériques codés en dur au lieu d'utiliser subscriptionKeywords
- [x] Corriger le prompt pour utiliser UNIQUEMENT les mots-clés configurés dans subscriptionKeywords
- [x] Ajouter logique: si subscriptionKeywords est vide, isSubscription = false par défaut
- [ ] Tester avec une nouvelle facture importée et le mot-clé "BLOB" (ne devrait pas détecter)
## Nouvelle page Factures BAP
- [ ] Créer une nouvelle page InvoicesBAP.tsx affichant uniquement les factures avec Abonnement = NON
- [ ] Inclure les colonnes Type d'achat et Ventilation dans la page Factures BAP
- [ ] Ajouter la route /invoices-bap dans App.tsx
- [ ] Ajouter le lien "Factures BAP" dans le menu de navigation
- [ ] Supprimer les colonnes Type d'achat et Ventilation de la page Factures principale
- [ ] Tester le filtrage et l'affichage des factures BAP
## Page Factures BAP
- [x] Créer nouvelle page InvoicesBAP.tsx basée sur Invoices.tsx
- [x] Filtrer uniquement les factures avec Abonnement = NON (isSubscription = 0)
- [x] Inclure les colonnes Type d'achat et Ventilation dans Factures BAP
- [x] Supprimer les colonnes Type d'achat et Ventilation de la page Factures principale
- [x] Ajouter la route /invoices-bap dans App.tsx
- [x] Ajouter le menu "Factures BAP" dans DashboardLayout
- [ ] Tester le filtrage et l'édition directe dans la nouvelle page
## Paramètre Dossier d'export
- [x] Ajouter le champ exportFolder dans la table importSettings du schéma
- [x] Pousser la migration avec pnpm db:push
- [x] Ajouter le champ dans l'interface ImportSettings.tsx
- [x] Tester la sauvegarde et récupération du paramètre
## Système de gestion des automatismes
- [x] Créer la table automationRules dans le schéma pour stocker les règles
- [x] Définir la structure JSON pour les conditions (SI) et actions (ALORS)
- [x] Pousser la migration avec pnpm db:push
- [x] Créer les fonctions CRUD dans db.ts pour les règles
- [x] Créer les routes tRPC pour gérer les règles (list, create, update, delete, reorder)
- [x] Créer la page AutomationRules.tsx pour l'interface de gestion
- [x] Ajouter le menu "Automatismes" dans DashboardLayout
- [x] Implémenter le formulaire de création/édition de règles
- [x] Implémenter l'affichage de la liste des règles avec ordre de priorité
- [x] Créer la fonction d'évaluation des règles (applyAutomationRules)
- [x] Intégrer l'application des règles dans le processus d'import
- [x] Tester avec des règles réelles
## Coloration des valeurs dans Factures BAP
- [x] Ajouter les champs de traçage (autoFilledFields) dans la table invoices
- [x] Pousser la migration avec pnpm db:push
- [x] Mettre à jour automationEngine.ts pour marquer les champs remplis automatiquement
- [x] Modifier InvoicesBAP.tsx pour afficher les valeurs en vert (auto) et bleu (manuel)
- [x] Mettre à jour la logique d'édition pour marquer les valeurs comme manuelles
- [x] Tester l'affichage avec des règles d'automatisme
## Correction erreur Select.Item dans AutomationRules
- [x] Identifier tous les Select.Item avec valeurs vides dans AutomationRules.tsx
- [x] Remplacer les valeurs vides par des valeurs par défaut valides
- [x] Tester la création de nouvelles règles
## Améliorations de la gestion des règles d'automatisme
- [x] Créer une route tRPC pour tester une règle sur les factures existantes
- [x] Créer une route tRPC pour dupliquer une règle
- [x] Implémenter l'assistant de création guidée avec étapes progressives
- [x] Ajouter le bouton "Tester" dans le formulaire de création/édition
- [x] Afficher les résultats du test (nombre de factures affectées)
- [x] Ajouter le bouton "Dupliquer" dans la liste des règles
- [x] Tester toutes les nouvelles fonctionnalités
## Assistant de création guidée (interface différenciée)
- [x] Créer l'interface de l'assistant avec navigation par étapes (1/2/3)
- [x] Implémenter l'étape 1 : Questions simples pour les conditions
- [x] Implémenter l'étape 2 : Sélection des actions à appliquer
- [x] Implémenter l'étape 3 : Récapitulatif et validation
- [x] Ajouter la navigation Précédent/Suivant entre les étapes
- [x] Tester le parcours complet de l'assistant
## Ré-application automatique des règles sur factures BAP
- [x] Créer une route tRPC pour ré-appliquer toutes les règles actives sur les factures BAP
- [x] Intégrer l'appel automatique après création d'une règle
- [x] Intégrer l'appel automatique après modification d'une règle
- [x] Intégrer l'appel automatique après activation d'une règle
- [x] Ajouter une notification avec le nombre de factures mises à jour
- [x] Tester avec différents scénarios (création, modification, activation)
## Création utilisateur admin local sur VPS
- [x] Créer l'utilisateur admin dans la base de données MySQL
- [x] Hacher le mot de passe avec bcrypt
- [x] Vérifier la création de l'utilisateur
## Mise à jour email admin
- [x] Mettre à jour l'email de admin@local à o.pareige@itinova.org
## Bug connexion locale VPS
- [x] Vérifier les logs PM2 pour identifier l'erreur
- [x] Diagnostiquer le problème d'authentification
- [x] Corriger le bug et tester la connexion
## Bug ajout service
- [x] Identifier le problème (contrainte d'unicité)
- [x] Améliorer la gestion des erreurs pour afficher un message convivial
- [x] Tester l'ajout de service
- [x] Déployer la correction sur le VPS
## Configuration clé API Mistral sur VPS
- [x] Ajouter MISTRAL_API_KEY dans le fichier .env du VPS
- [x] Modifier le code pour utiliser Mistral API directement
- [x] Redémarrer l'application PM2
- [x] Tester l'extraction de factures
## Bug extraction PDF qui ne se termine pas sur VPS
- [x] Vérifier les logs PM2 pour identifier l'erreur
- [x] Diagnostiquer le problème (Data too long for column 'processingProgress')
- [ ] Modifier le code pour stocker les PDF dans un dossier local
- [ ] Configurer Nginx pour servir les fichiers PDF
- [ ] Tester et redéployer sur le VPS
## Configuration des champs obligatoires pour le score LLM
- [x] Créer table llmFieldsConfig pour stocker la configuration des champs (nom, obligatoire/optionnel)
- [x] Ajouter routes tRPC pour gérer la configuration des champs (get, update)
- [x] Créer interface utilisateur dans les paramètres LLM pour afficher tous les champs
- [x] Ajouter cases à cocher pour marquer chaque champ comme obligatoire ou optionnel
- [x] Modifier le code d'extraction (invoiceExtractor.ts) pour utiliser la configuration
- [x] Adapter le calcul du qualityScore selon les champs obligatoires configurés
- [x] Initialiser les valeurs par défaut (supplierName, invoiceNumber, invoiceDate, totalAmount obligatoires)
- [x] Tester la configuration et vérifier le calcul du score
- [x] Déployer sur le VPS
## Modernisation de la page Paramètres
- [x] Analyser la structure actuelle et identifier les améliorations UX
- [x] Remplacer le layout par un système de Tabs pour organiser les sections
- [x] Utiliser des Cards modernes avec ombres et bordures pour chaque section
- [x] Améliorer la typographie (titres, descriptions, espacements)
- [x] Ajouter des icônes plus grandes et colorées pour chaque section
- [x] Implémenter des animations de transition fluides
- [x] Améliorer le responsive design pour mobile
- [x] Ajouter des badges de statut (Actif/Inactif) avec couleurs
- [x] Tester localement l'interface modernisée
- [x] Déployer sur le VPS
## Modernisation des pages Administration et Import
- [x] Identifier les pages Administration des listes et Paramètres d'import
- [x] Analyser la structure actuelle de ces pages
- [x] Moderniser la page Administration des listes avec Tabs, icônes colorées, cards
- [x] Moderniser la page Paramètres d'import avec le même style
- [x] Appliquer les badges de statut et animations
- [x] Améliorer la typographie et les espacements
- [x] Tester localement les interfaces modernisées
- [x] Déployer sur le VPS
## Menu latéral accordéon
- [x] Modifier DashboardLayout pour ajouter un menu accordéon
- [x] Créer la structure avec 4 sections : Tableau de bord, Facturation, Configuration, Traçabilité
- [x] Implémenter l'accordéon pour les sections Facturation, Configuration, Traçabilité
- [x] Ajouter les icônes pour chaque section et sous-menu
- [x] Configurer "Tableau de bord" comme section ouverte par défaut
- [x] Créer les pages manquantes (Factures BAP, Automatismes, Utilisateurs, Historiques)
- [x] Mettre à jour App.tsx avec les nouvelles routes
- [x] Tester la navigation et le comportement de l'accordéon
- [x] Déployer sur le VPS
## Amélioration du menu accordéon
- [x] Modifier le comportement pour qu'un seul accordéon soit ouvert à la fois (exclusif)
- [x] Ajouter des dégradés de couleurs distinctifs pour chaque section
- [x] Agrandir les icônes et améliorer leur visibilité
- [x] Ajouter des animations fluides pour l'ouverture/fermeture
- [x] Améliorer les effets hover et les transitions
- [x] Optimiser les espacements et la typographie
- [x] Tester le comportement exclusif
- [x] Déployer sur le VPS
## Correction bug accordéon
- [x] Empêcher la fermeture de l'accordéon lors du clic sur un sous-menu
- [x] Tester le comportement après correction
- [x] Déployer sur le VPS
## Configuration HTTPS sur le VPS
- [x] Générer un certificat SSL auto-signé sur le VPS
- [x] Créer le répertoire /etc/nginx/ssl pour stocker les certificats
- [x] Configurer Nginx pour écouter sur le port 443 (HTTPS)
- [x] Ajouter la redirection HTTP vers HTTPS
- [x] Configurer les en-têtes de sécurité SSL
- [x] Redémarrer Nginx
- [x] Tester l'accès HTTPS via https://20.56.92.59
- [x] Vérifier la redirection HTTP vers HTTPS
## Configuration sécurité VPS (UFW + Fail2Ban)
- [x] Vérifier l'état actuel du pare-feu UFW
- [x] Configurer UFW pour autoriser SSH (port 22)
- [x] Configurer UFW pour autoriser HTTP (port 80)
- [x] Configurer UFW pour autoriser HTTPS (port 443)
- [x] Activer le pare-feu UFW
- [x] Installer Fail2Ban
- [x] Configurer Fail2Ban pour SSH (maxretry=3, bantime=3600)
- [x] Créer une liste blanche d'IPs de confiance
- [x] Démarrer et activer Fail2Ban
- [x] Tester la configuration et vérifier les logs
## Ajout des IPs de confiance à la liste blanche Fail2Ban
- [x] Mettre à jour /etc/fail2ban/jail.local avec les IPs 185.61.190.35 et 197.221.123.242
- [x] Redémarrer Fail2Ban pour appliquer les modifications
- [x] Vérifier que les IPs sont bien dans la liste blanche
## Configuration Let's Encrypt pour facturation.itinova.org
- [x] Vérifier la configuration DNS (facturation.itinova.org → 20.56.92.59)
- [x] Installer Certbot (client Let's Encrypt)
- [x] Obtenir le certificat SSL pour facturation.itinova.org
- [x] Configurer Nginx pour utiliser le certificat Let's Encrypt
- [x] Tester l'accès HTTPS via https://facturation.itinova.org
- [x] Configurer le renouvellement automatique du certificat
- [x] Vérifier que la redirection HTTP → HTTPS fonctionne
## Correction configuration Nginx pour facturation.itinova.org
- [x] Vérifier la configuration Nginx actuelle
- [x] Identifier pourquoi facturation.itinova.org affiche la page par défaut
- [x] Créer une configuration Nginx spécifique pour facturation.itinova.org pointant vers l'application Node.js
- [x] Tester la configuration Nginx
- [x] Redémarrer Nginx
- [x] Vérifier que https://facturation.itinova.org affiche l'application
## Export des factures BAP
- [x] Définir les critères d'exportabilité : Score 100% + Type d'achat rempli + Service rempli + Ventilation remplie
- [x] Ajouter fonction isExportable dans InvoicesBAP.tsx
- [x] Ajouter colonne avec cases à cocher pour sélection des factures exportables
- [x] Ajouter case à cocher générale qui sélectionne toutes les factures exportables
- [x] Désactiver les cases à cocher pour les factures non exportables
- [x] Ajouter bouton "Exporter" qui s'active si au moins une facture est cochée
- [x] Utiliser la route tRPC existante pour exporter les factures sélectionnées
- [x] Implémenter la génération de fichiers d'export (PDF)
- [x] Tester la sélection et l'export des factures BAP
## Améliorations export factures BAP
- [x] Ajouter icône verte ✓ dans la colonne Score pour les factures exportables
- [x] Modifier la fonction getQualityBadge pour afficher l'indicateur d'exportabilité
- [x] Modifier la route tRPC exportToPdf pour copier les PDFs vers exportFolder
- [x] Ajouter la logique de copie de fichiers avec fs.copyFile
- [x] Récupérer le paramètre exportFolder depuis importSettings
- [x] Créer le dossier exportFolder s'il n'existe pas
- [x] Gérer les erreurs de copie de fichiers
- [x] Afficher une notification de succès avec le chemin du dossier d'export
- [ ] Tester l'export vers le dossier configuré
## Bouton Validation BAP
- [x] Analyser la structure de la page InvoicesBAP.tsx
- [x] Créer la route tRPC validateBAP dans routers.ts (mise à jour du statut en "validated")
- [x] Ajouter la colonne "Actions" en fin de chaque ligne du tableau
- [x] Ajouter le bouton "Validation BAP" avec icône CheckCircle2
- [x] Implémenter la logique d'activation : Score 100% + non exportée + isSubscription=0 + service + typeAchat + ventilation remplis
- [x] Désactiver le bouton avec tooltip explicatif pour les factures non éligibles
- [x] Afficher un toast de confirmation après validation
- [x] Rafraîchir la liste après validation
## Onglet Signatures dans Paramètres
- [x] Créer la table `signatures` dans drizzle/schema.ts (id, userId, firstName, lastName, imageKey, imageUrl, createdAt)
- [x] Appliquer la migration DB (pnpm db:push)
- [x] Créer les routes tRPC : signatures.list, signatures.upload, signatures.create, signatures.delete
- [x] Ajouter la route d'upload d'image de signature (stockage local base64)
- [x] Ajouter l'onglet "Signatures" dans la page Settings.tsx
- [x] Créer le formulaire d'ajout de signature (prénom, nom, upload image)
- [x] Afficher la liste des signatures avec aperçu de l'image en grille
- [x] Ajouter le bouton de suppression par signature (hover)
- [ ] Tester l'upload et l'affichage des signatures sur le VPS
## Canvas de signature à la souris (onglet Signatures)
- [x] Ajouter un sélecteur de mode : "Importer un fichier" / "Dessiner la signature"
- [x] Créer un composant canvas interactif pour dessiner la signature à la souris
- [x] Gérer les événements souris (mousedown, mousemove, mouseup) et tactile (touch)
- [x] Ajouter un bouton "Effacer" pour réinitialiser le canvas
- [x] Exporter le canvas en PNG base64 pour l'upload
- [x] Tester le dessin à la souris et l'enregistrement
## Correction affichage canvas signature
- [x] Corriger le problème d'initialisation du canvas (fond blanc non affiché)
- [x] S'assurer que le canvas est visible et fonctionnel dans l'onglet Signatures
## Association Service → Signature et export PDF avec signature
- [x] Créer la table `serviceSignatures` dans drizzle/schema.ts (serviceName → signatureId)
- [x] Appliquer la migration DB (pnpm db:push)
- [x] Créer les routes tRPC : serviceSignatures.list, serviceSignatures.upsert, serviceSignatures.delete
- [x] Ajouter une section "Association Service → Signature" dans l'onglet Signatures des Paramètres
- [x] Afficher la liste des services disponibles avec un sélecteur de signature pour chacun
- [x] Modifier la route exportToPdf pour récupérer la signature associée au service de la facture
- [x] Apposer la signature sur le PDF exporté (image en bas à droite + nom du signataire)
- [x] Tester l'export PDF avec signature automatique
## Modification page de connexion
- [x] Arriver directement sur la connexion locale (supprimer l'écran de choix)
- [x] Afficher le logo Itinova au-dessus du formulaire de connexion
- [x] Afficher "powered by" + logo Santinova en dessous du formulaire
- [x] Renommer l'application "Invoice Analyzer" en "Gestion facturation"
- [x] Appliquer le même comportement en cas de déconnexion
## Connexion locale avec identifiant libre
- [x] Analyser le schéma DB et les routes d'auth locale
- [x] Modifier la validation Zod pour accepter un identifiant libre (non-email)
- [x] Modifier la route tRPC `auth.loginLocal` pour accepter un username libre
- [x] Modifier la page Login.tsx pour remplacer le champ email par un champ "Identifiant"
- [x] Créer le compte admin `adminItinova` avec mot de passe `Itinova69!` en base de données locale
- [x] Créer le compte admin `adminItinova` sur le VPS
- [x] Déployer sur le VPS
## Correction connexion adminItinova VPS
- [x] Diagnostiquer le problème d'authentification (hash bcrypt Python vs Node.js)
- [x] Corriger le hash du mot de passe sur le VPS (généré avec Node.js bcrypt)
- [x] Vérifier que la connexion fonctionne (API tRPC répond 200 avec user)
## Ajout du champ Destinataire
- [x] Ajouter colonne `recipientName` dans la table `invoices` (schéma DB + migration)
- [x] Ajouter colonne `recipientKeywords` dans la table `userSettings` (schéma DB + migration)
- [x] Mettre à jour le prompt LLM pour extraire le destinataire
- [x] Mettre à jour l'interface `ExtractedInvoiceData` dans invoiceExtractor.ts
- [x] Mettre à jour les mots-clés personnalisés dans invoiceExtractor.ts
- [x] Mettre à jour la route `settings.upsert` dans routers.ts
- [x] Mettre à jour la route `invoices.update` dans routers.ts
- [x] Ajouter le champ destinataire dans InvoiceDetail.tsx
- [x] Ajouter le champ mots-clés destinataire dans Settings.tsx (onglet Mots-clés)
- [x] Ajouter destinataire dans AutomationRules.tsx (conditions)
- [x] Ajouter recipientName dans les champs LLM par défaut (db.ts)
- [x] Ajouter colonne Destinataire dans la liste des factures (Invoices.tsx)
- [x] Ajouter Destinataire dans l'export Excel
- [ ] Déployer sur le VPS
## Filtre destinataire + Top destinataires + Filtre SFTP
- [x] Ajouter filtre par destinataire dans Invoices.tsx (dropdown + recherche)
- [x] Ajouter colonne `sftpRecipientFilter` dans userSettings (schéma DB + migration)
- [x] Ajouter topRecipients et recipientsList dans getInvoiceStats (db.ts)
- [x] Ajouter graphique Top destinataires dans Dashboard.tsx
- [x] Ajouter filtre destinataire dans la section SFTP de Settings.tsx
- [x] Mettre à jour la route settings.upsert pour sftpRecipientFilter
## Améliorations Factures BAP + Export PDF annoté + Historique BAP
- [x] Supprimer la colonne "Abonnement" de la fenêtre Factures BAP
- [x] Ajouter le choix du mode d'export dans les paramètres (dossier local ou ouverture navigateur)
- [x] Ajouter colonne bapExportMode dans importSettings (schéma DB + migration)
- [x] Générer PDF annoté lors du clic BAP : zone blanche avec CAPEX/OPEX, BAP, destinataire, signature du service
- [x] Exporter ou ouvrir le PDF selon le mode d'export configuré
- [x] Créer la page Historique BAP dans le menu Traçabilité
- [x] Ajouter table bapHistory en base de données (schéma + migration)
- [x] Enregistrer chaque validation BAP dans l'historique
- [x] Ajouter la route dans App.tsx et le lien dans le menu Traçabilité
## Correction génération PDF BAP (fallback URL)
- [x] Corriger la lecture du PDF source dans validateBAP (fallback URL si fichier local absent)
- [x] Corriger la lecture de l'image de signature dans validateBAP (fallback URL)
- [x] Corriger la lecture du PDF source dans exportToPdf (fallback URL)
- [x] Corriger la lecture de l'image de signature dans exportToPdf (fallback URL)
## Correction table signatures VPS
- [x] Corriger noms de colonnes dans signatures et service_signatures sur le VPS (snake_case -> camelCase)
## Correction affectation signature à service (serviceSignatures)
- [x] Corriger l'upsert serviceSignatures (renommage table service_signatures -> serviceSignatures sur le VPS)
## Correction PDF BAP non affiché sur VPS
- [ ] Diagnostiquer et corriger la génération du PDF annoté lors de la validation BAP sur le VPS
## Validation BAP en masse
- [ ] Ajouter la route validateBAPBulk côté serveur (traitement séquentiel de toutes les factures éligibles)
- [ ] Ajouter le bouton "Valider tout en BAP" dans InvoicesBAP.tsx avec barre de progression
- [ ] Déployer sur le VPS
## Visibilité admin - toutes les factures
- [x] Ajouter getAllInvoices() dans db.ts (sans filtre userId)
- [x] Ajouter getAllImportLogs() dans db.ts (sans filtre userId)
- [x] Ajouter getAllBapHistory() dans db.ts (sans filtre userId)
- [x] Modifier invoices.list : les admins voient toutes les factures, les users voient les leurs
- [x] Modifier importLogs.getByUser : les admins voient tous les logs
- [x] Modifier bapHistory.getAll : les admins voient tout l'historique BAP
- [x] Ajouter colonne "Utilisateur" dans Invoices.tsx (visible uniquement pour les admins)
## Améliorations SharePoint
- [ ] Log SharePoint dans l'historique BAP (colonnes sharepointUploadStatus + sharepointUploadPath)
- [ ] Bouton "Tester la connexion" Azure AD dans les paramètres
- [ ] Champ date d'expiration du secret Azure AD + alerte dans les paramètres
## OAuth2 IMAP pour Office 365
- [x] Créer server/office365OAuth.ts avec getOffice365ImapToken et buildXOAuth2String
- [x] Ajouter champ emailImportAuthMode (basic/oauth2) dans le schéma DB importSettings
- [x] Appliquer migration DB (pnpm db:push)
- [x] Modifier emailImportService.ts pour supporter OAuth2 XOAUTH2 via Azure AD
- [x] Ajouter fonction testImapConnection dans emailImportService.ts
- [x] Ajouter procédure testEmailConnection dans routers.ts
- [x] Ajouter emailImportAuthMode dans le schéma Zod de importSettings.update
- [x] Ajouter sélecteur mode auth (basic/oauth2) dans ImportSettings.tsx
- [x] Ajouter bouton "Tester la connexion IMAP" dans ImportSettings.tsx
- [x] Déployer sur recette (git push + docker compose up --build)
- [x] Appliquer migration emailImportAuthMode sur recette (colonne ajoutée en DB)
- [ ] Déployer sur production (en attente de validation recette)
## Module Ventilation FreePro
- [x] Schéma DB : tables freeproImports et freeproVentilationLines
- [x] Migration DB appliquée (pnpm db:push)
- [x] Service freeproService.ts : transformation Excel → ventilation (script/TTC/type)
- [x] Helpers DB dans db.ts : createFreeproImport, getFreeproImportsByUser, getFreeproImportWithLines, deleteFreeproImport
- [x] Procédures tRPC : freepro.import, freepro.list, freepro.getById, freepro.delete
- [x] Page VentilationFreePro.tsx : import drag&drop, tableau de ventilation, historique, export PDF
- [x] Menu "Ventilations > FreePro" ajouté dans DashboardLayout
- [x] Route /ventilation-freepro ajoutée dans App.tsx
- [x] Déploiement sur recette (git pull + migrations DB + docker compose up --build)
## Module Ventilation FreePro - Onglet Paramétrage (connexion automatique web FreePro)
- [x] Schéma DB : ajouter table `freeproSettings` (URL portail, login, password, fréquence, date antériorité, dernière récupération)
- [x] Migration DB : pnpm db:push
- [x] Helper DB : getFreeproSettings, upsertFreeproSettings
- [x] Service freeproAutoImport.ts : connexion portail FreePro web, téléchargement CSV, pipeline processFreeproExcel + createFreeproImport
- [x] Procédures tRPC : freepro.getSettings, freepro.saveSettings, freepro.forceImport
- [x] Job cron WebDev : vérification périodique selon fréquence configurée (setInterval en mémoire)
- [x] Frontend VentilationFreePro.tsx : wrapper Tabs (onglet 1 = import manuel, onglet 2 = paramétrage)
- [x] Onglet Paramétrage : formulaire credentials FreePro web, fréquence, date antériorité, bouton "Forcer récupération", statut dernière récupération
## Colonne Source import dans l'historique des imports
- [x] Ajouter colonne importSource (file/folder/email) dans la table importLogs (schéma + migration)
- [x] Enregistrer importSource="file" lors d'un import manuel (routers.ts)
- [x] Enregistrer importSource="email" lors d'un import par email (emailImportService.ts)
- [x] Enregistrer importSource="folder" lors d'un import par dossier (folderImportService.ts)
- [x] Afficher la colonne "Source" avec badge coloré dans le tableau History.tsx (Email=bleu, Dossier=violet, Fichier=gris)
- [x] Afficher la source dans le dialog de détails de l'import
## Listes globales partagées entre tous les utilisateurs
- [ ] Modifier getAccountingAllocationsByUser → retourner toutes les ventilations (sans filtre userId)
- [ ] Modifier getAutomationRulesByUser → retourner tous les automatismes (sans filtre userId)
- [ ] Modifier getDepartmentsByUser → retourner tous les services (sans filtre userId)
- [ ] Modifier getSignaturesByUser → retourner toutes les signatures (sans filtre userId)
- [ ] Modifier getServiceSignaturesByUser → retourner toutes les signatures de service (sans filtre userId)
- [ ] Migrer les données en production : dédoublonner les listes fusionnées
- [ ] Déployer en production
## Connecteurs web (scraping login/mdp)
- [ ] Table webImportSources dans le schéma DB
- [ ] Procédures tRPC CRUD pour webImportSources
- [ ] Interface de gestion des sources web dans les paramètres
- [ ] Endpoint API sécurisé pour déclencher l'import et recevoir les PDFs
- [ ] Script cron externe Node.js + Playwright pour SFR
- [ ] Framework connecteur générique extensible
## Audit technique et robustesse
- [x] Inventorier les artefacts, scripts et dépendances inutilisés
- [x] Supprimer les artefacts de développement et le code mort confirmés
- [x] Charger les pages à la demande pour réduire le JavaScript initial
- [x] Consolider le mécanisme de sauvegarde de base de données et ses validations
- [x] Renforcer les contrôles daccès et la gestion derreur des endpoints critiques
- [x] Documenter les modules métier, les invariants et les décisions techniques critiques
- [x] Ajouter des tests de non-régression ciblés et vérifier build, types et tests
- [x] Normaliser les valeurs OAuth de loginMethod avant écriture en base
## Incident production — erreur HTTP 404
- [x] Reproduire la 404 et contrôler le domaine, Traefik et les conteneurs
- [x] Identifier et corriger la cause racine sans modifier les données
- [x] Vérifier le retour HTTP 200 et la santé des conteneurs
## Audit production — 674 factures affichées
- [x] Compter les factures par utilisateur, source et statut
- [x] Identifier les groupes de doublons selon plusieurs clés métier
- [x] Vérifier les références de stockage et les effets de la fusion précédente
- [x] Préparer une correction réversible sans suppression immédiate
- [x] Sauvegarder la base et le volume puis suspendre les imports email
- [x] Bloquer les réimports par empreinte PDF et fiabiliser le traitement IMAP
- [x] Déployer le correctif anti-réimport et migrer la base de production
- [x] Appliquer la correction confirmée et vérifier le comptage final
## Audit authentification IMAP Microsoft 365
- [x] Vérifier la génération du jeton Azure et le format XOAUTH2 envoyé à IMAP
- [x] Comparer les scopes, permissions et méthode dauthentification aux exigences Microsoft 365
- [x] Tester la configuration active de production sans exposer les secrets
- [x] Documenter la cause du refus IMAP et le correctif requis
## Migration import email vers ImapFlow
- [x] Remplacer la dépendance `imap` par `imapflow`
- [x] Réécrire la connexion OAuth2, la recherche UNSEEN et la lecture des messages
- [x] Conserver le traitement séquentiel, le verrou anti-concurrence et le marquage Seen après succès
- [x] Adapter le test de connexion IMAP et les messages derreur
- [x] Ajouter des tests de non-régression du flux ImapFlow
- [x] Vérifier TypeScript, tests, build et authentification OAuth2 réelle
## Déploiement ImapFlow — recette et production
- [x] Pousser la version ImapFlow vers le dépôt Gitea de recette
- [x] Réduire limage runtime Docker pour fiabiliser le build sur le serveur de recette
- [x] Charger Vite uniquement en développement pour lexclure de limage runtime
- [x] Déployer et valider HTTP et conteneurs ImapFlow en recette (aucune source OAuth2 active à tester)
- [x] Corriger les règles Docker orphelines qui bloquaient MySQL en recette
- [x] Pousser la version validée vers le dépôt Gitea de production
- [x] Déployer et valider HTTP, conteneurs et OAuth2 ImapFlow en production
## Navigation depuis lédition des factures BAP
- [x] Reproduire et identifier la perte du contexte de navigation depuis Factures BAP
- [x] Restaurer la page dorigine après fermeture de lédition
- [x] Conserver les filtres et tris sélectionnés sur Factures BAP
- [x] Ajouter des tests de non-régression du retour contextuel
- [x] Vérifier TypeScript, tests, build et parcours en sandbox
- [x] Pousser le correctif vers Gitea recette et redéployer
- [x] Vérifier le parcours et la santé de la recette
## Automatisation de lindicateur Abonnement
- [x] Analyser le modèle, le formulaire et lexécution actuelle des automatismes
- [x] Ajouter loption Abonnement : Oui, Non ou Ne pas modifier aux règles
- [x] Appliquer loption Abonnement lors du traitement automatique des factures
- [x] Ajouter des tests de non-régression des règles dabonnement
- [x] Valider les deux correctifs en sandbox
## Déploiement recette — navigation BAP et abonnement
- [x] Pousser les deux correctifs vers Gitea recette
- [x] Déployer, vérifier HTTP et valider le parcours de retour en recette
## Correctif recette — dialogue dautomatisme
- [x] Vérifier le commit et localiser lemplacement absent de loption Abonnement
- [x] Corriger le dialogue dédition et le valider en recette
- [x] Arrêter le processus non applicatif autorisé qui bloque le build Docker
## Déploiement production — dialogue Abonnement
- [x] Pousser le correctif vers Gitea production
- [x] Construire et redémarrer uniquement le conteneur applicatif
- [x] Vérifier le commit, la santé, HTTP et le bundle de production
## Filtre par action des automatismes
- [x] Identifier les types daction disponibles et leurs règles de détection
- [x] Ajouter un filtre daction dans la liste des automatismes
- [x] Permettre disoler les règles Abonnement, Oui ou Non
- [x] Ajouter les tests et valider TypeScript, tests et build
## Déploiement — filtre par action des automatismes
- [x] Pousser le filtre par action vers Gitea recette
- [x] Déployer et vérifier le filtre par action en recette
- [x] Pousser la version validée vers Gitea production
- [x] Déployer et vérifier le filtre par action en production
## Seuil déligibilité BAP à 90 %
- [x] Identifier les validations BAP fondées sur le score de qualité
- [x] Abaisser le seuil de 100 % à 90 % pour les opérations BAP
- [x] Ajouter les tests de seuil et valider TypeScript, tests et build
## Déploiement — seuil BAP à 90 %
- [x] Pousser le correctif vers Gitea recette
- [x] Déployer et vérifier le seuil BAP à 90 % en recette
- [x] Pousser la version validée vers Gitea production
- [x] Déployer et vérifier le seuil BAP à 90 % en production
## Rétablissement du serveur de recette
- [x] Redémarrer le serveur de recette autorisé par lutilisateur
- [x] Rétablir le conteneur applicatif et terminer le déploiement BAP à 90 %
## Factures abonnements et filtres de période
- [x] Analyser les listes Factures, Factures BAP et le menu Facturation
- [x] Ajouter les filtres Année et Mois à la page Factures
- [x] Créer la page Factures abonnements affichant uniquement les abonnements
- [x] Reprendre les recherches, filtres et actions de la page Factures
- [x] Ajouter lentrée Factures abonnements après Factures BAP dans le menu
- [x] Ajouter les tests et valider TypeScript, build et affichage en sandbox
- [x] Déployer et vérifier le correctif en recette
- [x] Déployer et vérifier le correctif en production
## Synthèse annuelle du tableau de bord
- [x] Analyser les données et le tableau de bord existant
- [x] Calculer par année les volumes et montants BAP et abonnements
- [x] Afficher le nombre de factures et les montants par type, puis le total
- [x] Ajouter les tests et valider TypeScript, build et affichage en sandbox
## Budget réel par fournisseur
- [x] Définir lagrégation des montants par fournisseur et statut Abonnement
- [x] Ajouter les filtres Année et Mois à lécran Budget réel
- [x] Créer lécran Budget réel à la fin du menu Facturation
- [x] Afficher par fournisseur les montants Abonnement, Hors abonnement et le total
- [x] Ajouter les tests et valider TypeScript, build et affichage en sandbox
## Améliorations Budget réel et tableau de bord
- [x] Confirmer le tri décroissant par montant total dans le budget
- [x] Ajouter un graphique annuel BAP versus abonnements au tableau de bord
- [x] Ajouter les tests et valider TypeScript, build et rendu sandbox