Aller au contenu

Scénario QR-007 : Sortie + Règles de validation (doublon, licenciement, départ anticipé)

@assignee: @m-kouassi

Module : qr-attendance Tranche : QR-T2-001 (extension) + QR-T3-001 (départ anticipé) Contexte de la marque : [LES DEUX] Papillon HR Suite + ALTARYS ENTERPRISE HR Suite Priorité : 7 Dépend de : QR-006 Peut être développé en parallèle avec : Aucun (prolonge directement QR-006) Ordre de fusion : Avant QR-009 Complexité estimée : M PRD User Stories : US-QR-001 (AC-004, AC-005), US-QR-002 (AC-001, AC-003)


Objectif

Étendre le pipeline d'événements d'horloge de QR-006 avec trois règles de validation essentielles : détection des scans en double (dans un intervalle de 15 minutes), rejet des employés licenciés/ayant quitté l'entreprise et signalement des départs anticipés. Ces règles garantissent l'intégrité des données et la conformité sans nécessiter de nouvelles tables ou de nouveaux endpoints — elles s'ajoutent au flux existant POST /api/v1/qrcontr/clock-events.


Portée du backend

Entités et enregistrements

Aucune nouvelle table ni entity. Étend les entities existantes Clock et DailyAttendance de QR-006.

Migrations Flyway

Aucune — aucune nouvelle table.

Couche de référentiel

Pas de nouveaux repositories.

Couche de service

DuplicateDetector : - SI deux scans du même type d'événement sont enregistrés dans les 15 minutes pour le même employé : conserver le plus ancien, marquer le second comme is_duplicate=true - Enregistrer dans l'audit : « Doublon détecté (fenêtre de 15 min). » - Si l'intervalle est supérieur à 15 minutes, traiter comme des événements distincts

Étendre ClockEventService.recordClockEvent : - Vérifier le statut de l'employé via CachedEmployeeData — s'il est TERMINÉ ou HORS SERVICE, rejeter avec « Compte désactivé — contactez les RH » et consigner la tentative dans l'audit - À la sortie : vérifier si la sortie a lieu avant l'heure de fin prévue — marquer DailyAttendance comme DEPART_ANTICIPE, calculer early_departure_minutes = heure de fin prévue - heure de sortie

EarlyDepartureDetector : - Compare la dernière sortie avec l'heure de fin prévue de l'horaire de l'employé - Aucune tolérance pour les départs anticipés (tout départ avant l'heure de fin prévue est signalé)

Endpoints API

Aucun nouveau endpoint. L'endpoint existant POST /api/v1/qrcontr/clock-events applique désormais ces règles.

Règles de validation

Rule Condition Outcome
Duplicate Same employee + same event type + within 15 min is_duplicate=true on later event
Terminated employee_status in (TERMINATED, OFFBOARDED) 403 with message "Compte desactive — contactez les RH"
Early departure Clock-out time < schedule end time DailyAttendance.earlyDepartureMinutes set, status includes DEPART_ANTICIPE flag
### Considérations relatives à l'environnement multi-tenant

Toutes les requêtes de validation incluent un filtrage par tenant_id. CachedEmployeeData est déjà limité au niveau du locataire.


Portée du frontend

Aucune nouvelle page ni route. Étend les états du QR Scanner de QR-006.

Composants à étendre

QRScanner — ajouter un état d'information de doublon : - Orange (pas rouge) : « Pointage déjà enregistré à HH:MM » (fermeture automatique après 2 s)

QRScanner — ajouter un état d'erreur de terminaison : - Secouement rouge + « Compte désactivé — contactez les RH »

ClockConfirmation — pour la sortie : - Afficher « Départ — [Nom du site] » au lieu de « Arrivée »

États de l'interface utilisateur

State Behavior French Copy
Duplicate Amber info, no red "Pointage deja enregistre a {time}."
Terminated Red shake, distinct message "Compte desactive — contactez les RH"
Clock-out success Same celebration as clock-in "Pointage enregistre" + "HH:MM" + "Depart — [Site name]"
### Comportement adaptatif

Identique à QR-006 (360 px pour les appareils mobiles, 768 px pour les tablettes, 1024 px et plus pour les ordinateurs de bureau).


Critères d'acceptation

AC-001: Duplicate scan detection within 15 minutes
Given I scan the same QR code twice within 15 minutes
When the system processes the scans
Then the second scan is discarded as a duplicate

AC-002: Terminated employee scan rejection
Given I am a terminated employee
When I try to scan
Then the scan is rejected with message "Compte desactive — contactez les RH"

AC-003: Clock-out event recording
Given I have a clock-in recorded for today
When I scan the QR code
Then a clock-out event is recorded

AC-004: Early departure detection
Given I clock out before my scheduled end time
When the system processes the event
Then an early departure (depart anticipe) is flagged

OHADA et règles réglementaires

  • Les événements horodatés constituent des enregistrements d'audit immuables (ADR-10). Les doublons sont signalés mais ne sont jamais supprimés.
  • Le rejet d'un employé licencié est consigné dans la piste d'audit (FR-QR-013).

Normes et conventions

  • docs/standards/java-Spring-guidelines.md
  • docs/standards/api-guidelines.md

Exigences en matière de tests

Tests unitaires

  • DuplicateDetector : dans un intervalle de 15 minutes (duplicata), en dehors de l'intervalle de 15 minutes (pas de duplicata), type d'événement identique ou différent
  • Vérification des employés licenciés : statut TERMINATED rejeté, statut OFFBOARDED rejeté, statut ACTIVE autorisé
  • Calcul des départs anticipés : pointage de sortie avant la fin de l'horaire, pointage de sortie à la fin de l'horaire (pas de drapeau), pointage de sortie après la fin de l'horaire (pas de drapeau)

Tests d'intégration

  • POST d'un événement d'horodatage avec doublon dans les 15 minutes — deuxième événement marqué is_duplicate=true
  • POST d'un événement d'horodatage avec un employé licencié — réponse 403
  • POST d'un pointage de sortie avant la fin de l'horaire — DailyAttendance a earlyDepartureMinutes défini et le statut DEPART_ANTICIPE
  • Isolation des locataires : la détection des doublons ne traverse pas les locataires

Ce que le contrôle qualité va valider

  • Effectuer deux scans rapides, vérifier le message de doublon (orange, pas rouge)
  • Vérifier que la sortie affiche « Départ — [Nom du site] » au lieu de « Arrivée »
  • Vérifier que le départ anticipé est signalé dans les registres de présence
  • Vérifier que l'employé licencié voit une alerte rouge avec le message correct

Hors du champ d'application

  • Détection des retards (QR-009)
  • Fermeture automatique en cas de pointage de sortie manqué (QR-010)
  • Détection des anomalies sur les appareils partagés (QR-010)

Définition de « Terminé »

  • [ ] Toutes les règles de validation backend implémentées (doublon, licenciement, départ anticipé)
  • [ ] États du scanner frontend mis à jour (doublon orange, licenciement rouge, pointage de sortie réussi)
  • [ ] Les 5 états de l'interface utilisateur de QR-006 fonctionnent toujours + nouveaux états ajoutés
  • [ ] Le micro-texte en français correspond exactement aux spécifications de conception
  • [ ] Tous les critères d'acceptation sont satisfaits manuellement
  • [ ] Tests unitaires écrits et réussis
  • [ ] Tests d'intégration écrits et réussis
  • [ ] Isolation multi-tenant vérifiée
  • [ ] Pas de any en TypeScript, pas de types bruts en Java
  • [ ] Entrées de piste d'audit pour les doublons et les scans rejetés
  • [ ] ./gradlew test est vert
  • [ ] ./gradlew spotlessApply réussit