Story AB-019 : Tableau de Bord RH (Backend + Frontend)¶
Module : absence-management Tranche : VS-AB-014 de l'architecture Contexte de marque : [LES DEUX] Papillon HR Suite + ALTARYS ENTERPRISE HR Suite Priorité : 19 Dépend de : AB-009, AB-011 Peut se développer en parallèle avec : AB-018, AB-020 Ordre de fusion : Après AB-009 et AB-011 Complexité estimée : M PRD User Stories : US-ABS-008
Objectif¶
Fournir aux responsables RH et aux DG un tableau de bord synthétique affichant les indicateurs clés d'absence : nombre de demandes en attente d'approbation, taux d'absence, nombre d'absents aujourd'hui, congés à venir et avertissements pour les employés avec un solde faible. Le tableau de bord inclut une liste compacte des demandes en attente avec des actions inline et un aperçu calendrier de 2 semaines.
Périmètre Backend¶
Entités et Enregistrements¶
Enregistrements de réponse :
public record DashboardSummaryResponse(
int pendingApprovalsCount,
BigDecimal absenceRatePercent, // (jours d'absence / jours ouvrables du mois en cours) x 100, 1 décimale
int absentToday,
int lowBalanceEmployeesCount, // employés avec solde de congé annuel < 5 jours
List<UpcomingLeave> upcomingLeavesThisWeek,
List<PendingApprovalSummary> recentPendingApprovals
) {}
public record UpcomingLeave(
UUID leaveRequestId,
UUID employeeId,
String employeeName, // abrégé : "DIALLO F."
LocalDate startDate,
LocalDate endDate,
String leaveType
) {}
public record PendingApprovalSummary(
UUID leaveRequestId,
UUID employeeId,
String employeeName, // abrégé : "DIALLO F."
LocalDate startDate,
LocalDate endDate,
String leaveType,
int numberOfDays,
Instant submittedAt
) {}
Couche Repository¶
Utilise les repositories existants d'AB-002 et AB-009 :
- LeaveRequestRepository — compter PENDING_APPROVAL, interroger les congés approuvés à venir
- LeaveBalanceLedgerRepository — pour le calcul du taux d'absence
- LeaveEmployeeProfileRepository — pour le comptage des employés à solde faible
- Requêtes personnalisées :
- countByTenantIdAndStatus(UUID tenantId, LeaveStatus status) — comptage des demandes en attente
- findApprovedLeavesOverlappingDate(UUID tenantId, LocalDate date) — absents aujourd'hui
- findUpcomingApprovedLeaves(UUID tenantId, LocalDate fromDate, LocalDate toDate) — congés à venir cette semaine
- findRecentPendingApprovals(UUID tenantId, int limit) — dernières demandes en attente (limite=5)
- countEmployeesWithBalanceBelow(UUID tenantId, BigDecimal threshold) — comptage des soldes faibles
Couche Service¶
DashboardService.java :
getSummary(UUID tenantId): DashboardSummaryResponsependingApprovalsCount: COUNT des LeaveRequests avec status=PENDING_APPROVALabsenceRatePercent: (total des jours d'absence du mois en cours / total des jours ouvrables du mois en cours) x 100, calculé à la volée avec BigDecimalabsentToday: COUNT des employés actuellement en congé approuvé (période de congé incluant aujourd'hui)lowBalanceEmployeesCount: COUNT des employés avec solde de congé annuel < 5 joursupcomingLeavesThisWeek: congés approuvés débutant dans la semaine en cours (lundi-dimanche)recentPendingApprovals: 5 dernières demandes d'approbation en attente, triées par submittedAt desc
Objectif de performance : < 500ms pour un tenant de 50 employés (utiliser des requêtes COUNT, pas de scans complets)
Points de terminaison API¶
| Méthode | Chemin | Paramètres de requête | Réponse | Auth |
|---|---|---|---|---|
| GET | /api/v1/absence/dashboard/summary |
— | ApiResponse<DashboardSummaryResponse> |
HR_MANAGER, DG |
Règles de validation¶
- Seuls HR_MANAGER et DG peuvent accéder au tableau de bord — 403 pour les autres rôles
- Aucune validation d'entrée nécessaire (pas de paramètres de requête au-delà de l'auth)
Considérations Multi-Tenant¶
- Toutes les requêtes incluent
tenantIddepuisScopedValue<TenantContext> - Le calcul du taux d'absence est limité aux employés du tenant uniquement
- Le seuil de solde faible (5 jours) est codé en dur en MVP — configurable en V2
- Fonctionne avec les 4 profils de base de données (conçu pour BYO-DB en priorité)
Périmètre Frontend¶
RAPPEL SYNCHRONISATION HORS LIGNE (Papillon — CRITIQUE) : Le tableau de bord est une vue d'agrégation en lecture seule. Les données du tableau de bord en cache sont servies hors connexion avec un bandeau indiquant les données périmées. Les actions d'approbation depuis le tableau de bord sont en ligne uniquement. Voir
docs/standards/offline-sync-guidelines.md.
Pages et Routes¶
| Route | Page | Description |
|---|---|---|
/absences/tableau-de-bord |
AbsenceDashboardPage | Tableau de bord absences RH/DG |
Composants¶
KpiCard— Carte métrique avec icône, label, valeur et couleur de fond optionnellePendingApprovalCard— Carte d'approbation compacte avec nom de l'employé, dates, type de congé et boutons d'action inlineMiniCalendarTimeline— Widget aperçu calendrier 2 semaines (réutilise la logique CalendarTimeline d'AB-018 sous forme compacte)GhostLink— Lien de navigation avec icône flècheWelcomeEmptyState— État vide plein écran pour les nouveaux tenants
États UI (TOUS REQUIS)¶
| État | Comportement | Copie Française |
|---|---|---|
| Chargement | 4 petits rectangles squelette (KPIs) + 2 rectangles moyens (listes) | — |
| Vide (nouveau tenant) | EmptyState avec illustration de fusée | "Bienvenue dans la gestion des absences" / CTA : "Configurer les parametres" |
| Erreur | Toast + bouton réessayer | "Impossible de charger le tableau de bord." |
| Hors ligne | Données en cache + bandeau données périmées | "Hors connexion — derniere synchro : {time}" |
| Succès | N/A (tableau de bord en lecture seule) | — |
Comportement Responsive¶
Mobile (360px — Papillon en priorité) :
- 4 cartes KPI en grille 2x2 :
1. "En attente" — comptage en attente, bg=warning-light, appuyable → navigue vers /absences/approbations
2. "Taux d'absence" — pourcentage, bg=neutral-light
3. "Absents aujourd'hui" — comptage, bg=neutral-light
4. "Soldes bas" — comptage (employés avec < 5 jours), bg=amber-light
- Section "Demandes récentes" :
- PendingApprovalCards compactes avec nom de l'employé, dates, type
- Boutons inline "Approuver" (primary, sm) + "Voir" (ghost, sm)
- Maximum 5 cartes affichées
- Section "Calendrier (2 semaines)" :
- MiniCalendarTimeline montrant un instantané de 14 jours
- Lien ghost "Voir toutes les approbations" → /absences/approbations
- Lien ghost "Voir le calendrier complet" → /absences/calendrier
- Toutes les cibles tactiles >= 48px
Desktop (1024px+ — Enterprise en priorité) : - 4 cartes KPI en ligne horizontale unique - Mise en page 2 colonnes sous les KPIs : - Colonne gauche : "Demandes en attente" — liste des approbations en attente avec actions inline - Colonne droite : "Calendrier (2 semaines)" — aperçu calendrier 2 semaines - Liens ghost en bas de chaque section - Clic sur le nom d'un employé dans la liste en attente → naviguer vers le détail du solde employé
Interactions¶
- Appui sur la carte KPI "En attente" → naviguer vers
/absences/approbations - Appui sur "Approuver" sur la carte en attente → approbation inline (PATCH vers l'endpoint d'approbation d'AB-011), la carte s'anime à la sortie en cas de succès
- Appui sur "Voir" sur la carte en attente → naviguer vers le détail de la demande de congé
- Appui sur le nom d'un employé depuis le contexte du tableau de bord → naviguer vers le détail du solde employé (AB-021)
- Liens ghost → naviguer vers la liste complète des approbations ou le calendrier complet
- Pull-to-refresh (mobile) → recharger le résumé du tableau de bord
- Auto-refresh : le tableau de bord se recharge toutes les 60 secondes quand l'onglet est actif
Micro-Copie Française¶
dashboard.title: "Tableau de bord — Absences"dashboard.kpi.pending: "En attente"dashboard.kpi.absence_rate: "Taux d'absence"dashboard.kpi.absent_today: "Absents aujourd'hui"dashboard.kpi.low_balance: "Soldes bas"dashboard.recent_requests: "Demandes recentes"dashboard.calendar_preview: "Calendrier (2 semaines)"dashboard.view_all_approvals: "Voir toutes les approbations"dashboard.view_full_calendar: "Voir le calendrier complet"dashboard.approve: "Approuver"dashboard.view: "Voir"dashboard.welcome: "Bienvenue dans la gestion des absences"dashboard.welcome_cta: "Configurer les parametres"dashboard.error: "Impossible de charger le tableau de bord."dashboard.offline: "Hors connexion — derniere synchro : {time}"dashboard.low_balance_warning: "{count} employes ont un solde inferieur a 5 jours"
Critères d'Acceptation¶
AC-060 : Le tableau de bord RH affiche les indicateurs clés
Étant donné que je suis HR_MANAGER
Quand j'ouvre le tableau de bord Absences
Alors je vois : le nombre de demandes en attente (badge), le taux d'absence (%), le nombre d'absents aujourd'hui, le nombre d'employés à solde faible, les congés à venir cette semaine
AC-061 : Le détail du solde employé est accessible depuis le tableau de bord
Étant donné que je clique sur le nom d'un employé dans la liste des approbations en attente
Quand la vue détail s'ouvre
Alors je vois le grand livre complet des acquisitions, déductions, ajustements et reports
AC-062 : Les approbations en attente sont actionnables depuis le tableau de bord
Étant donné qu'il y a des demandes d'approbation en attente
Quand je consulte le tableau de bord
Alors je peux approuver ou naviguer vers le détail directement depuis les cartes du tableau de bord
AC-063 : Le nouveau tenant voit l'état de bienvenue
Étant donné qu'un nouveau tenant CI vient d'activer le module ABSMGT
Quand le RH ouvre le tableau de bord
Alors il voit l'EmptyState de bienvenue avec le CTA pour configurer les paramètres
Règles OHADA et Réglementaires¶
N/A — le tableau de bord est une fonctionnalité d'affichage/agrégation sans exigences réglementaires.
Standards et Conventions¶
docs/standards/java-spring-guidelines.md— §Patterns REST controller, §Autorisation RBAC, §Optimisation des requêtesdocs/standards/database-guidelines.md— §Pattern repository multi-tenant, §BigDecimal pour les calculs de taux, §Optimisation des requêtes COUNTdocs/standards/api-guidelines.md— §Patterns endpoints GET, §Enveloppe ApiResponsedocs/standards/react-typescript-guidelines.md— §Patterns de composants, §CSS Modules, §i18n, §Patterns de grille responsivedocs/standards/design-system.md— §Card, §Button (variantes inline), §EmptyState, §Toast, §GhostLinkdocs/standards/offline-sync-guidelines.md— §Données en lecture seule en cache, §Bandeau de données périmées, §Actions en ligne uniquement (approbation)docs/standards/multi-datasource-patterns.md— §Requêtes repository limitées au tenant
Exigences de Test¶
Tests Unitaires¶
DashboardService.getSummary(): 3 demandes en attente → pendingApprovalsCount=3DashboardService.getSummary(): 0 demandes en attente → pendingApprovalsCount=0DashboardService.getSummary(): 2 employés absents aujourd'hui → absentToday=2DashboardService.getSummary(): 15 jours d'absence dans le mois avec 22 jours ouvrables → absenceRatePercent=68.2 (BigDecimal)DashboardService.getSummary(): 0 jour d'absence → absenceRatePercent=0.0DashboardService.getSummary(): 4 employés avec solde < 5 jours → lowBalanceEmployeesCount=4DashboardService.getSummary(): congés à venir filtrés à la semaine en cours uniquementDashboardService.getSummary(): approbations en attente récentes limitées à 5, triées par submittedAt desc
Tests d'Intégration¶
- GET /dashboard/summary en tant que HR_MANAGER → 200, toutes les métriques présentes
- GET /dashboard/summary en tant que DG → 200, même accès que HR_MANAGER
- GET /dashboard/summary en tant que EMPLOYEE → 403
- GET /dashboard/summary en tant que MANAGER → 403
- Nouveau tenant sans données → pendingApprovalsCount=0, absenceRatePercent=0.0, absentToday=0
- Multi-tenant : les métriques du tenant A n'incluent pas les données du tenant B
Ce que QA Validera¶
- Le tableau de bord s'affiche à 360px avec la grille KPI 2x2
- Les cartes KPI affichent les valeurs correctes et sont appuyables
- La carte "En attente" navigue vers la page des approbations
- Les cartes d'approbation en attente affichent les boutons Approuver/Voir inline
- L'approbation inline fonctionne (la carte s'anime à la sortie en cas de succès)
- L'aperçu calendrier 2 semaines s'affiche correctement
- Les liens ghost naviguent vers les pages correctes
- Le nouveau tenant voit l'EmptyState de bienvenue avec le CTA
- Hors ligne : données en cache affichées avec bandeau de données périmées, bouton Approuver désactivé
- Desktop : 4 KPIs en ligne, mise en page 2 colonnes dessous
Hors Périmètre¶
- Filtres avancés (Enterprise V2)
- Export CSV/Excel/PDF (Enterprise V2)
- 6-8 KPIs pour l'édition Enterprise (V2)
- Mise en page du tableau de bord personnalisable / glisser-déposer de widgets (V2)
- Tendances historiques / graphiques (V2)
- Mises à jour en temps réel via WebSocket (V2 — polling utilisé en MVP)
Définition de Done¶
- [ ] Tous les endpoints backend implémentés et retournant les réponses correctes
- [ ] Toutes les pages frontend s'affichent correctement à 360px, 768px, 1024px
- [ ] Les 5 états UI implémentés (chargement, vide, erreur, hors ligne, succès)
- [ ] La micro-copie française correspond exactement à la spécification design
- [ ] Tous les critères d'acceptation passent manuellement
- [ ] Tests unitaires écrits et passants
- [ ] Tests d'intégration écrits et passants
- [ ] Isolation multi-tenant vérifiée — toutes les métriques limitées au tenant
- [ ] La lecture hors ligne fonctionne (Papillon) — données en cache affichées avec bandeau de données périmées, actions bloquées
- [ ] Pas de
anyTypeScript - [ ] Pas de types bruts Java — tous les génériques explicites
- [ ] Les réponses API suivent le format d'enveloppe standard
- [ ] Performance vérifiée : < 500ms pour un tenant de 50 employés