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.mddocs/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 —
DailyAttendanceaearlyDepartureMinutesdé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
anyen TypeScript, pas de types bruts en Java - [ ] Entrées de piste d'audit pour les doublons et les scans rejetés
- [ ]
./gradlew testest vert - [ ]
./gradlew spotlessApplyréussit