Le besoin
SmartPlanning gère les plannings et les congés d'équipes de terrain. Avant d'écrire du code, j'ai mené un benchmark documenté de 14 concurrents, défini quatre personas, rédigé les user stories avec leurs critères d'acceptation et produit les maquettes Figma. Le travail a été découpé en 24 epics Jira et en sprints thématiques, avec une documentation continue dans Confluence.
Détails : analyse des besoins et gestion de projet Agile.
Ce que fait l'application
- Quatre rôles (administrateur système, directeur, manager, employé), avec des autorisations RBAC et un tableau de bord par rôle
- Plannings interactifs, récurrences, détection de conflits et exports
- Congés, jours ouvrés, jours fériés et soldes annuels
- Abonnements Stripe facturés par employé
- Messagerie interne, import CSV et notifications en temps réel
- Fonctions RGPD : export, suppression, soft delete et traçabilité
L'architecture
L'application suit quatre couches : présentation, métier, accès aux données et
infrastructure. Plusieurs entreprises partagent la même base (architecture
multi-tenant) : les accès aux données sont filtrés par l'identifiant de l'entreprise,
companyId, et des tests couvrent les tentatives d'accès aux données d'une
autre entreprise. Le schéma compte une vingtaine de tables métier, modélisées d'abord
avec Merise (MCD puis MLD sous Looping). TypeScript vérifie les types pendant le
développement, Zod contrôle les données reçues et PostgreSQL impose les contraintes
de la base.
Détails : conception de la base de données et architecture Next.js.
Trois décisions techniques
1. Détecter les conflits sans casser le glisser-déposer
Quand un manager crée ou déplace un créneau, l'application doit savoir s'il chevauche un congé validé, un arrêt maladie ou une préférence horaire. Un congé validé bloque l'opération. Une préférence horaire déclenche un simple avertissement. Cette distinction vient de situations que je connaissais par mon expérience dans la grande distribution.
Côté serveur, le chevauchement se teste par la condition
start_date < newEnd AND end_date > newStart, exécutée via Prisma à chaque
création ou déplacement. Côté interface, la mise à jour est optimiste : l'état précédent
du créneau est gardé dans une ref React, la mutation part en parallèle, et l'interface
revient en arrière avec un message clair si elle échoue. J'ai testé la génération d'une
année de planning, soit 52 occurrences, sans ralentissement visible. Je n'ai pas
encore mesuré les performances sous charge.
- Le manager glisse le créneau de Léa du mardi au jeudi : l'interface l'affiche aussitôt, sans attendre le serveur.
- En parallèle, le serveur cherche un chevauchement avec la condition
start_date < newEnd AND end_date > newStart. - Il trouve un congé validé : c'est un conflit dur, l'opération est refusée.
- L'interface remet le créneau à sa place, à partir de l'état gardé avant le déplacement, et explique pourquoi.
2. Garder la base de données hors du middleware
Le middleware de Next.js tourne sur le runtime Edge, où Prisma n'est pas disponible. J'ai enrichi le jeton JWT avec le rôle et l'entreprise de l'utilisateur, ce qui permet au middleware de filtrer la navigation sans interroger la base.
3. SSE plutôt que WebSockets pour les notifications
Les notifications vont toujours du serveur vers le navigateur. Server-Sent Events couvre ce besoin avec une connexion HTTP simple, là où des WebSockets auraient ajouté un canal bidirectionnel inutile à maintenir.
Détails : développement des fonctionnalités.
Tests et qualité
Le projet compte 3 003 tests automatisés répartis dans 169 fichiers : 2 814 tests unitaires et d'intégration avec Vitest et React Testing Library, et 189 tests de bout en bout avec Playwright, organisés en Page Object Model. L'intégration continue bloque la fusion si le lint, le typage, les tests ou le build échouent, et la suite complète tourne chaque nuit. Il n'existe pas encore de test de charge (k6 ou Artillery).
Détails : stratégie de tests.
Infrastructure et déploiement
L'application tourne sur un VPS OVH que j'administre : quatre services Docker (application, PostgreSQL, Redis, Nginx), images multi-stage, conteneurs sans droits root, SSL, pare-feu et accès SSH durci. GitHub Actions enchaîne les contrôles puis le déploiement, et un endpoint de santé mesure la latence de la base.
Détails : CI/CD, Docker et déploiement.
Une erreur en production, et ce qu'elle a changé
J'ai découvert en production que l'inscription d'une entreprise ne créait pas sa ligne dans la table des abonnements. Les entreprises concernées ne recevaient pas les relances prévues à la fin de leur essai gratuit. J'ai ouvert trois tickets liés, écrit une migration Prisma propre et ajouté 24 tests couvrant les deux parcours d'inscription et la reprise des données existantes.
Depuis, le typage complet et la suite de tests sont obligatoires avant chaque fusion, aucune écriture en production ne se fait sans validation humaine (y compris quand un assistant IA participe au développement), et je documente les décisions d'architecture au moment où je les prends, plutôt qu'après coup.
Où en est le projet
SmartPlanning est en ligne et utilisé par des testeurs qui travaillent dans la grande distribution. Leurs retours ont déjà conduit à des corrections et à des améliorations de l'interface. Ce sont des testeurs, pas encore des clients abonnés. Je travaille aujourd'hui sur sa visibilité dans les moteurs de recherche et les assistants IA.