Aller au contenu

Rapport QR-010 : Anomalies du tableau de bord + Lot de clôtures automatiques +

@assignee: @m-kouassi

Module de périmètre de gestion : qr-attendance Tranche : QR-T3-002 + QR-T3-004 + US-QR-010 (autres AC) Contexte de la marque : [LES DEUX] Papillon HR Suite + ALTARYS ENTERPRISE HR Suite Priorité : 10 Dépend de : QR-009 (tableau de bord de base) Peut être développé en parallèle avec : Aucun (prolonge QR-009) Ordre de fusion : Après QR-009 Complexité estimée : M PRD User Stories : US-QR-002 (AC-002), US-QR-010 (AC-003, AC-004)


Objectif

Étendre le tableau de bord des présences quotidiennes avec trois fonctionnalités : - (1) une tâche batch de fermeture automatique qui crée des événements de pointage de sortie synthétiques pour les employés qui oublient de pointer leur sortie, - (2) la détection d'anomalies sur les appareils partagés qui signale lorsque plusieurs employés utilisent le même appareil, - et (3) un filtrage par périmètre de gestion afin que les managers ne voient que leurs subordonnés directs. Ces fonctionnalités complètent la préparation opérationnelle du tableau de bord pour les workflows RH quotidiens.


Portée du backend

Entités et enregistrements

Aucune nouvelle table. Extension du tableau de bord et ajout de tâches batch.

Migrations Flyway

Aucune.

Couche de référentiel

Aucun nouveau repository. Extension des requêtes existantes.

Couche de service

AutoCloseService + AutoCloseScheduledJob : - Tâche quotidienne @Scheduled à une heure configurable (par défaut 23 h 59 à partir de AttendanceModuleConfig.autoCloseTime) - Parcourt les tenants actifs dont le module QRCONTR est activé - Pour chaque employé ayant une pointe d'arrivée ouverte (IN sans OUT) dont l'heure de fin prévue est dépassée : - Créer une sortie synthétique à l'heure de fin prévue, source=SYSTEM, autoCloseReason="MISSED_CLOCK_OUT" - Définir DailyAttendance.isAutoClosed=true, AUCUNE heure supplémentaire créditée - Indicateur : « Pointage incomplet (fermeture automatique) » - Si l'employé n'a pas d'horaire : NE PAS fermer automatiquement, signaler « Pointage incomplet — pas d'horaire configuré », régularisation manuelle requise

SharedDeviceDetector : - Vérification : si 2 employés différents ou plus ont des événements de pointage avec le même deviceIdHash le même jour -> générer une anomalie - Ajouter au JSONB DailyAttendance.anomalyDetails : {"type":"SHARED_DEVICE","employeeIds":["uuid1","uuid2"],"details":"Appareil partagé avec [name]"} - Définir hasAnomaly=true - Événements de pointage NON rejetés — indicateur informatif uniquement

Étendre DashboardService : - Ajouter la liste des anomalies à la réponse du tableau de bord - Ajouter la liste autoClosedYesterday (consolidée pour la revue matinale des RH) - Portée du responsable : filtrer les employeeIds par managerId à partir de CachedEmployeeData.currentManagerId

Endpoints API

Mêmes endpoints que QR-009, réponses étendues :

Method Path Changes
GET /api/v1/qrcontr/attendance/today DashboardResponse now includes anomalies and autoClosedYesterday
GET /api/v1/qrcontr/attendance/daily Same extensions

DashboardResponse comprend désormais : - anomalies (List) — type, employeeId, details - autoClosedYesterday (List) — employeeId, name, scheduledEnd, autoClosedAt

Filtre « Manager » : lorsque le rôle de l'utilisateur authentifié est MANAGER, le filtrage s'applique automatiquement aux seuls subordonnés directs.

Règles de validation

  • Fermeture automatique uniquement pour les employés ayant un horaire configuré
  • La détection des appareils partagés est purement informative — aucun événement n'est rejeté
  • La portée du gestionnaire est appliquée côté serveur en fonction du contexte d'authentification

Considérations multi-tenant

Le lot de fermeture automatique itère les tenants individuellement. La détection des appareils partagés s'applique au niveau du tenant (un même deviceIdHash chez différents tenants ne constitue pas une anomalie).


Portée du frontend

Étend DashboardPage de QR-009.

Composants à ajouter/étendre

AnomalyBadge : - Badge coloré sur la ligne de l'employé (appuyer pour afficher les détails) - Types : SHARED_DEVICE (avertissement), AUTO_CLOSED (horloge), NO_SCHEDULE (calendrier)

AnomalyDetailPanel : - Déploiement en ligne (animation de hauteur de 200 ms) affichant les détails de l'anomalie

AutoClosedList : - Section en haut du tableau de bord affichant les enregistrements fermés automatiquement hier

Étendre EmployeeAttendanceRow : - Ajouter la prise en charge des badges d'anomalie, icône différente pour les enregistrements fermés automatiquement

États de l'interface utilisateur

State Behavior French Copy
Anomaly badge Colored badge on employee row, tappable "Alerte : appareil partage" / "Pointage incomplet (fermeture automatique)"
Manager view Filtered to team only, no team selector Header shows "Mon equipe"
Auto-closed list Highlighted section at top "Fermetures automatiques d'hier"

Comportement adaptatif

  • 360px : les badges d'anomalie s'affichent sous forme de petites icônes ; appuyer pour les développer en ligne. La liste à fermeture automatique s'affiche sous forme d'accordéon repliable.
  • 768px : badges avec un texte court ; la liste à fermeture automatique est visible par défaut.
  • 1024px+ : détails complets de l'anomalie visibles ; la liste à fermeture automatique s'affiche sous forme de tableau.

Interactions

  • Appui sur le badge d'anomalie : affichage en ligne avec les détails (200 ms)
  • Balayage vers la gauche sur la ligne de l'employé (mobile, RH uniquement) : affiche l'action rapide « Régularisation directe » (renvoie vers QR-013)
  • Badge du responsable dans l'en-tête pour indiquer la portée de l'équipe

Critères d'acceptation

```gherkin AC-001: Missed clock-out auto-close Given I forget to clock out When my scheduled end time passes Then the system auto-closes my record at the scheduled end time, flags it as SYSTEM-generated, and does NOT credit overtime

AC-002: Anomaly visual flagging on dashboard Given an anomaly exists (incomplete record, shared device alert) When I view the dashboard Then the anomaly is visually flagged with a colored badge

AC-003: Manager team-only view Given I am a manager When I view the dashboard Then I see only my team's data (direct reports) ```---

OHADA et règles réglementaires

  • La fermeture automatique NE génère PAS d'heures supplémentaires (mesure de protection pour l'employeur — évite les heures supplémentaires fantômes dues à des pointages de sortie oubliés)
  • Les événements de pointage d'origine sont conservés, les événements synthétiques sont marqués source=SYSTEM (piste d'audit immuable, ADR-10)
  • La détection des appareils partagés est purement informative (FR-QR-092) — les événements ne sont pas rejetés

Normes et conventions

  • docs/standards/java-Spring-guidelines.md — modèles @Scheduled, tâche batch avec itération par tenant
  • docs/standards/api-guidelines.md
  • docs/standards/react-typescript-guidelines.md

Exigences de test

Tests unitaires

  • AutoCloseService : fin programmée dépassée -> événement synthétique créé, pas de programmation -> pas de fermeture automatique + indicateur, pas d'heures supplémentaires créditées lors de la fermeture automatique, déjà fermé -> aucune action
  • SharedDeviceDetector : même appareil, employés différents -> anomalie créée, même appareil, même employé -> pas d'anomalie, appareils différents -> pas d'anomalie
  • Filtrage par périmètre de gestion : le responsable ne voit que ses subordonnés directs, les RH voient tout

Tests d'intégration

  • Exécuter la tâche de fermeture automatique, vérifier que des événements de pointage de sortie synthétiques sont créés avec source=SYSTEM
  • Vérifier isAutoClosed=true sur DailyAttendance
  • Vérifier que l'anomalie apparaît dans la réponse du tableau de bord
  • Vérifier que la requête GET du responsable /attendance/today renvoie uniquement les subordonnés directs
  • La requête GET des RH /attendance/today renvoie tous les employés
  • Isolation des locataires : la tâche de fermeture automatique traite les locataires indépendamment
  • Vérifier les badges d'anomalie sur le tableau de bord (appareil partagé, fermeture automatique)
  • Vérifier que le responsable ne voit que les données de son équipe
  • Vérifier que la liste des fermetures automatiques apparaît en haut du tableau de bord le lendemain matin
  • Appuyer sur le badge d'anomalie, vérifier l'affichage des détails

Hors du périmètre

  • Régularisation pour corriger les enregistrements de fermeture automatique (QR-012)
  • Détection des absences (déjà dans QR-009)
  • Exportation du tableau de bord (QR-017)

Définition de « Terminé »

  • [ ] Le traitement par lots de fermeture automatique s'exécute correctement et crée des événements synthétiques
  • [ ] La détection des appareils partagés génère des entrées d'anomalie
  • [ ] Le filtrage par périmètre du responsable fonctionne pour le tableau de bord
  • [ ] Les badges d'anomalie s'affichent sur le tableau de bord avec les icônes et les couleurs correctes
  • [ ] Tous les critères d'acceptation sont satisfaits manuellement
  • [ ] Les tests unitaires et les tests d'intégration sont réussis
  • [ ] L'isolation multi-tenant est vérifiée
  • [ ] Pas de any en TypeScript, pas de types bruts en Java
  • [ ] Entrées de piste d'audit pour les événements de fermeture automatique
  • [ ] ./gradlew test est vert
  • [ ] ./gradlew spotlessApply réussit