Aller au contenu

Cas QR-009 : Tableau de bord des présences quotidiennes — Résumé + Liste des employés +

@assignee: @m-kouassi

Module de détection : qr-attendance Segment : QR-T5-001 + QR-T3-001 (détection des retards) + QR-T3-003 (détection des absences) Contexte de la marque : [LES DEUX] Papillon HR Suite + ALTARYS ENTERPRISE HR Suite Priorité : 9 Dépend de : QR-007 (point de sortie + validation), QR-005 (congés pour absence) Peut être développé en parallèle avec : QR-011 (régularisation) Ordre de fusion : Avant QR-010 Complexité estimée : L PRD User Stories : US-QR-010 (AC-001, AC-002, AC-005)


Objectif

Construire le tableau de bord de présence quotidienne pour les RH et les managers, combinant une ligne de fiches récapitulatives (présent, en retard, absent, télétravail, en congé) avec une liste d'employés filtrable. Mettre simultanément en œuvre la détection des retards (avec une tolérance configurable) et la détection des absences (en recoupant les données avec les jours fériés, les congés et le télétravail). Il s'agit de la vue opérationnelle principale pour la gestion quotidienne des présences.


Portée du backend

Entités et enregistrements

Pas de nouvelles tables. Étend DailyAttendanceService et ajoute DashboardService.

Migrations Flyway

Aucune.

Couche de référentiel

Pas de nouveaux référentiels. Étend les requêtes existantes sur DailyAttendance et Clock.

Couche de service

LateDetectionService : - Un employé est « en retard » si son premier pointage > heure de début prévue + tolérance applicable - Recherche de la tolérance : niveau départemental (DepartmentAttendanceConfig.lateToleranceMinutes) > niveau entreprise (AttendanceModuleConfig.defaultLateToleranceMinutes) - Durée du retard = heure de pointage - heure de début prévue (SANS ajustement de la tolérance). Exemple : horaire 08h00, tolérance 5 min, pointage à 08h07 -> signalé RETARD, late_minutes=7 - Si dans la tolérance : PAS signalé, l'heure réelle est tout de même enregistrée - Met à jour DailyAttendance.status sur RETARD, définit late_minutes

NoShowDetectionService : - Vérification quotidienne : employés sans événement de pointage sur un jour ouvré - Recoupement : - Jours fériés (HolidayService.isHoliday) -> FERIE - Congés (cache LeaveApproved) -> EN_CONGE - Télétravail approuvé -> TELETRAVAIL - Télétravail en attente -> ABSENT_PENDING - Autres -> ABSENT

LeaveEventListener : - Écoute les événements LeaveApproved et LeaveCancelled provenant du module ABSMGT - Met à jour le cache local des congés pour le recoupement

DashboardService : - getTodayDashboard(tenantId, filters) — renvoie les totaux récapitulatifs + la liste des employés - Récapitulatif : total, présent, en retard, absent, télétravail, enConge, ferie, incomplet, absentPending - Liste des employés : nom, service, site, heure d'arrivée, heure de départ, heures travaillées, statut, anomalies - Filtrage : departmentId, siteId, status (séparés par des virgules), recherche par nom - Les RH voient tous les employés ; le responsable ne voit que ses subordonnés directs (application reportée à QR-010) - Pagination par jeu de clés (ADR-12)

Endpoints API

Method Path Request Body Response Auth
GET /api/v1/qrcontr/attendance/today ?departmentId=&siteId=&status=&search=&cursor=&size= ApiResponse<DashboardResponse> HR, Manager
GET /api/v1/qrcontr/attendance/daily ?date=&departmentId=&siteId=&status=&cursor=&size= ApiResponse<CursorPage<DailyAttendanceResponse>> HR, Manager
### DTO

DashboardResponse : - date (LocalDate) - summary (DashboardSummary) — total, présent, en retard, absent, télétravail, en congé, en vacances, incomplet, absent en attente - employees (List)

EmployeeDashboardRow : - employeeId (UUID) - name (String) - department (String) - site (String) - firstClockIn (LocalTime) - lastClockOut (LocalTime) - workedMinutes (int) - status (String) - anomalies (List)

Règles de validation

  • Le paramètre date prend par défaut la date du jour s'il n'est pas fourni
  • Le filtre status accepte des valeurs séparées par des virgules
  • La valeur par défaut de size est 20, avec un maximum de 100

Considérations relatives au multi-tenant

Toutes les requêtes du tableau de bord sont filtrées par tenant_id. Le cache des événements de départ est limité au tenant. La référence croisée des jours fériés utilise le code pays du tenant.


Portée du frontend

Pages et routes

  • /qrcontr/dashboard — Tableau de bord des présences quotidiennes (RH/Responsable)

Composants

DashboardPage (maquettes de conception 3.3, 3.4) : - Cartes de statut + mise en page de la liste des employés

StatusCardRow : - Cartes à défilement horizontal : Présent (vert), En retard (orange), Absent (rouge), Télétravail (bleu), En congé (violet) - Chacune affiche un compteur

EmployeeAttendanceList : - Liste des employés consultable et filtrable avec des badges de statut

FilterBar : - Champ de recherche + boutons de filtrage par service/site/statut

EmployeeAttendanceRow : - Nom, service, heure d'arrivée, badge de statut, badges d'anomalie (le cas échéant)

États de l'interface utilisateur

State Behavior French Copy
Loading 5 skeleton cards (shimmer, stagger 50ms) + 5 skeleton rows (stagger 30ms)
Empty Illustration + guidance "Aucun pointage aujourd'hui. Les pointages apparaitront ici des que vos employes scanneront le QR code." + CTA "Configurer un site" if no sites
Error Inline error card + retry "Impossible de charger les donnees. Verifiez votre connexion."
Offline Amber banner, cached data, "Derniere mise a jour: HH:MM" "Hors ligne — vos pointages seront synchronises"
Success Cards animate in stagger, list items fade in

Comportement adaptatif

  • 360px : cartes de statut à défilement horizontal (2 visibles), fiches employé simplifiées (nom, heure, badge de statut)
  • 768px : 3 cartes visibles, fiches employé plus détaillées
  • 1024px+ : 5 cartes par ligne, tableau complet avec colonnes triables (Enterprise)

Interactions

  • Puces de filtrage : appuyer pour basculer (active : remplie de couleur ambre, inactive : contour). Sélection multiple pour le statut, sélection unique pour le service/site.
  • Appui sur une ligne d'employé : glisser vers la droite pour accéder aux détails de la journée de l'employé
  • Tirer pour actualiser (mobile) : indicateur de chargement orange, actualise toutes les données
  • Le tableau de bord s'actualise automatiquement par interrogation (intervalle de 30 s en ligne)

Critères d'acceptation

AC-001: Dashboard summary counts
Given I open the daily attendance dashboard
When data loads
Then I see summary counts: Presents, En retard, Absents, Teletravail, En conge

AC-002: Dashboard filtering
Given I open the dashboard
When I view the employee list
Then I can filter by department, site, or status

AC-003: HR sees all employees
Given I am HR
When I view the dashboard
Then I see all employees across the company

OHADA et règles réglementaires

  • La détection tardive avec tolérance configurable prend en charge la personnalisation de l'intégration continue (art. 16.1 : les règles doivent figurer dans le règlement intérieur et être consultées avec les délégués)
  • L'absence justifiée établit correctement les liens avec les jours fériés, les congés et le télétravail avant de marquer la personne comme ABSENTE

Normes et conventions

  • docs/standards/java-spring-guidelines.md
  • docs/standards/api-guidelines.md — pagination basée sur le curseur (ADR-12)
  • docs/standards/react-typescript-guidelines.md
  • docs/standards/offline-sync-guidelines.md

Exigences de test

Tests unitaires

  • LateDetectionService : dans les limites de tolérance (non signalé), hors limites de tolérance (signalé), dérogation du service par rapport à la valeur par défaut de l'entreprise, calcul des minutes de retard
  • NoShowDetectionService : jour férié -> FERIE, congé approuvé -> EN_CONGE, télétravail approuvé -> TELETRAVAIL, télétravail en attente -> ABSENT_PENDING, aucune correspondance -> ABSENT
  • DashboardService : comptage des agrégats récapitulatifs, filtrage par statut/département/site, recherche par nom

Tests d'intégration

  • GET /attendance/today — renvoie le tableau de bord avec le récapitulatif et la liste des employés
  • GET /attendance/today?status=RETARD — résultats filtrés
  • GET /attendance/today?departmentId=... — filtré par département
  • GET /attendance/daily?date=2026-03-30 — requête sur une date historique
  • Isolation des locataires : le tableau de bord du tenant A n'inclut pas les données du tenant B
  • Pagination par curseur : vérifier que la pagination par jeu de clés fonctionne correctement

Ce que l'assurance qualité va valider

  • Afficher le tableau de bord, vérifier que les totaux correspondent à la liste des employés
  • Appliquer des filtres, vérifier que les résultats sont mis à jour correctement
  • Vérifier la détection des retards avec tolérance (pointage à la limite de tolérance)
  • Vérifier les références croisées en cas d'absence (employé en congé non marqué comme absent)
  • Actualisation par glissement sur mobile
  • Le mode hors ligne affiche les données mises en cache avec horodatage

Hors du périmètre

  • Filtrage réservé à l'équipe de gestionnaires (QR-010)
  • Détection des anomalies (appareil partagé, fermeture automatique) (QR-010)
  • Page de détails de l'employé depuis le tableau de bord (QR-016)
  • Actions de régularisation depuis le tableau de bord (QR-012)
  • [ ] Toutes les pages front-end s'affichent correctement à 360px, 768px et 1024px
  • [ ] Les 5 états de l'interface utilisateur sont implémentés (chargement, vide, erreur, hors ligne, succès)
  • [ ] Les micro-textes en français correspondent exactement aux spécifications de conception
  • [ ] Tous les critères d'acceptation sont validés manuellement
  • [ ] Les tests unitaires sont écrits et réussis
  • [ ] Les tests d'intégration sont écrits et réussis
  • [ ] Isolation multi-tenant vérifiée
  • [ ] Hors ligne : données du tableau de bord mises en cache avec horodatage « Dernière mise à jour »
  • [ ] Pas de any en TypeScript, pas de types bruts en Java
  • [ ] Les réponses API respectent le format d'enveloppe standard
  • [ ] Entrées de piste d'audit pour les mutations de données
  • [ ] ./gradlew test est vert
  • [ ] ./gradlew spotlessApply réussit