Rapport QR-018 : Rapport sur les heures supplémentaires +¶
Module de classification hebdomadaire : qr-attendance Tranche : QR-T4-003 + QR-T5-003 Contexte de la marque : [LES DEUX] Papillon HR Suite + ALTARYS ENTERPRISE HR Suite Priorité : 18 Dépend de : QR-006 (DailyAttendance), QR-004 (configuration des heures supplémentaires) Peut être développé en parallèle avec : QR-017 Ordre de fusion : Après QR-004, QR-006 Complexité estimée : M PRD User Stories : US-QR-012
Objectif¶
Mettre en place la classification hebdomadaire des heures supplémentaires et le rapport sur les heures supplémentaires. Un job batch planifié s'exécute chaque semaine pour classer les heures supplémentaires dans des tranches réglementaires (TRANCHE_1 : 40-46 h, TRANCHE_2 : 46-48 h, TRANCHE_3 : >48 h) avec des indicateurs supplémentaires pour le travail de nuit (21 h 00-05 h 00) et le travail le dimanche/jours fériés. Le rapport sur les heures supplémentaires présente une ventilation par tranche hebdomadaire et par employé à l'intention des RH et des comptables pour le rapprochement de la paie. Les heures supplémentaires sont enregistrées en minutes (et non en valeur monétaire); la paie applique les taux séparément.
Portée du backend¶
Entités et enregistrements¶
WeeklyOvertimeSummary :
- id (UUID)
- tenantId (UUID)
- employeeId (UUID)
- weekStartDate (LocalDate)
- weekEndDate (LocalDate)
- totalWorkedMinutes (int)
- band1Minutes (int)
- band2Minutes (int)
- band3Minutes (int)
- nightMinutes (int)
- sundayHolidayMinutes (int)
- totalOvertimeMinutes (int)
- createdAt (Instant)
- updatedAt (Instant)
Migrations Flyway¶
V001_017__attendance_weekly_overtime_summary.sql :
sql
CREATE TABLE attendance_weekly_overtime_summary (
id UUID PRIMARY KEY,
tenant_id UUID NOT NULL,
employee_id UUID NOT NULL,
week_start_date DATE NOT NULL,
week_end_date DATE NOT NULL,
total_worked_minutes INTEGER NOT NULL DEFAULT 0,
band_1_minutes INTEGER NOT NULL DEFAULT 0,
band_2_minutes INTEGER NOT NULL DEFAULT 0,
band_3_minutes INTEGER NOT NULL DEFAULT 0,
night_minutes INTEGER NOT NULL DEFAULT 0,
sunday_holiday_minutes INTEGER NOT NULL DEFAULT 0,
total_overtime_minutes INTEGER NOT NULL DEFAULT 0,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
UNIQUE(tenant_id, employee_id, week_start_date)
);
CREATE INDEX idx_weekly_overtime_tenant ON attendance_weekly_overtime_summary(tenant_id, employee_id, week_start_date);### Couche de référentiel
WeeklyOvertimeSummaryRepository
:
- findByTenantIdAndEmployeeIdAndWeekStartDate(tenantId, employeeId, weekStart) — pour l'upsert
- findByTenantIdAndWeekStartDateBetween(tenantId, from, to) — pour le rapport
- findByTenantIdAndEmployeeIdAndWeekStartDateBetween(tenantId, employeeId, from, to) — par employé
Couche de service¶
OvertimeClassificationService
:
- classifyWeek(tenantId, employeeId, weekStart, weekEnd) :
- Total hebdomadaire travaillé = somme de DailyAttendance.workedMinutes pour la semaine
- Si total > 2400 min (40 h) : heures supplémentaires = total - 2400
- Classer en tranches (à partir de OvertimeConfig) :
- BAND_1 : premières 360 min d'heures supplémentaires (40 h-46 h)
- BAND_2 : 120 min suivantes (46 h-48 h)
- BAND_3 : reste (> 48 h)
- NIGHT : heures travaillées entre nightStartTime et nightEndTime (21 h 00-05 h 00 par défaut) — indicateur supplémentaire (ajouté en plus de la classification par tranche)
- SUNDAY_HOLIDAY : heures travaillées le dimanche ou un jour férié — indicateur supplémentaire
- Upsert WeeklyOvertimeSummary
- Publier WeeklyOvertimeComputed
- La semaine s'étend du jour de début configuré (lundi 00h00 par défaut) jusqu'à la veille du début de la semaine suivante
OvertimeClassificationScheduledJob
:
- @Scheduled hebdomadaire (lundi 00h30)
- Parcourt les locataires actifs pour lesquels le module QRCONTR est activé
- Classe la semaine précédente pour tous les employés ayant des événements d'horloge au cours de cette semaine
OvertimeReportService
:
- generateOvertimeReport(tenantId, month, weekStart, employeeId, departmentId):
- Renvoie OvertimeReport — ventilation par tranche horaire par employé et par semaine
- Utilise la table WeeklyOvertimeSummary
Recalcul rétroactif
:
- Lorsqu'une régularisation (QR-012) affecte une semaine passée, réexécute classifyWeek pour cette semaine
- Écoute l'événement RegularizationApplied et vérifie si la présence quotidienne concernée se situe dans une semaine passée
| Method | Path | Request Body | Response | Auth |
|---|---|---|---|---|
| GET | /api/v1/qrcontr/reports/overtime |
?month=2026-03&weekStart=&employeeId=&departmentId= |
ApiResponse<OvertimeReport> |
HR, Comptable |
| GET | /api/v1/qrcontr/reports/export |
?type=overtime&month=&format=xlsx\|csv |
File download (Content-Disposition) | HR, Comptable |
| ### DTO |
« OvertimeReport »
:
- « month » (YearMonth)
- « employees » (Listband1Minutes (int)
- band2Minutes (int)
- band3Minutes (int)
- nightMinutes (int)
- sundayHolidayMinutes (int)
- totalOvertimeMinutes (int)
Règles de validation¶
- Format
month: AAAA-MM (obligatoire pour le rapport) formatdoit êtrexlsxoucsvpour l'exportation- Configuration des plages lue à partir du fichier
OvertimeConfig(QR-004) du tenant
Considérations multi-tenant¶
Toutes les requêtes filtrent par tenant_id. La tâche planifiée itère les tenants indépendamment. Les seuils des plages sont configurables par le tenant. Les RH et la comptabilité voient tout au sein du tenant.
Portée du frontend¶
Pages et routes¶
/qrcontr/reports/overtime— Affichage du rapport sur les heures supplémentaires
Composants¶
OvertimeReportPage
:
- Sélecteur de mois/semaine, filtre employé/service, tableau des heures supplémentaires
OvertimeTable
:
- Par employé et par semaine : Tranche 1, Tranche 2, Tranche 3, Nuit, Dimanche/Jour férié, Total
- Colonnes triables
- Ligne des totaux en bas
Réutilise ExportButtons
de QR-017 :
- « Exporter vers Excel » + « Exporter vers CSV »
États de l'interface utilisateur¶
| State | Behavior | French Copy |
|---|---|---|
| Loading | Skeleton table | — |
| Empty | No overtime for period | "Aucune heure supplementaire pour la periode selectionnee." |
| Error | Inline retry | "Impossible de generer le rapport. Reessayez." |
| Offline | Cached summaries only | "Rapport complet disponible en ligne uniquement." |
| Success | Overtime table rendered | — |
Comportement adaptatif¶
- 360px : tableau à défilement horizontal, 3 colonnes visibles, première colonne fixe (nom de l'employé)
- 768px : 5 colonnes visibles
- 1024px+ : tableau complet avec toutes les colonnes
Interactions¶
- Sélecteur de mois/semaine : menu déroulant pour le mois, bascule entre les semaines au sein du mois
- Filtre employé/service : sélecteurs déroulants
- Exportation : réutilise le flux d'exportation de QR-017 (téléchargement via le navigateur)
- Tableau : défilement horizontal sur mobile, première colonne fixe
Critères d'acceptation¶
```gherkin AC-001: Overtime report by band per employee per week Given I generate the overtime report When I view it Then I see per employee per week: Band 1 hours, Band 2 hours, Band 3 hours, Night hours, Sunday/holiday hours, Total overtime hours
AC-002: Overtime report export for payroll Given I export the report When Payroll receives it Then the data is structured for direct import (Excel/CSV with correct formatting) ```---
OHADA et dispositions réglementaires¶
- Code du travail de la CI, art. 21.2-21.3 : heures supplémentaires réglementées par décret, sur la base de 40 heures par semaine
- Valeurs par défaut de la CI (TV-QR-002) : BAND_1 40-46 h, BAND_2 46-48 h, BAND_3 >48 h
- NUIT : 21h00-05h00 (classification supplémentaire, s'ajoute à la tranche)
- DIMANCHE_JOUR FÉRIÉ : classification supplémentaire (s'ajoute à la tranche)
- Les tranches sont configurables par tenant — les valeurs par défaut incorrectes peuvent être corrigées sans modification du code
- Les heures supplémentaires sont stockées en minutes de type INTEGER (pas en valeur monétaire — la paie applique les taux)
Normes et conventions¶
docs/standards/java-spring-guidelines.md— Modèles@Scheduleddocs/standards/api-guidelines.mddocs/standards/react-typescript-guidelines.mddocs/standards/database-guidelines.md— Nommage des migrations Flyway
Exigences de test¶
Tests unitaires¶
OvertimeClassificationService: pas d'heures supplémentaires pour une semaine <= 40 h (2 400 min)OvertimeClassificationService: 43 h par semaine → 3 h BAND_1, 0 h BAND_2, 0 h BAND_3OvertimeClassificationService: 47 h par semaine → 6 h BAND_1, 1 h BAND_2, 0 h BAND_3OvertimeClassificationService: semaine de 50 h → 6 h BAND_1, 2 h BAND_2, 2 h BAND_3OvertimeClassificationService: détection des heures de nuit (entre 21 h et 5 h)OvertimeClassificationService: détection des dimanches et jours fériésOvertimeClassificationService: recalcul rétroactif lors de la régularisationOvertimeReportService: agrégation par employé et par semaine
Tests d'intégration¶
- Exécution hebdomadaire de la tâche : s'exécute pour tous les tenants, classe correctement
- GET
/reports/overtime?month=2026-03→ répartition correcte par tranche - GET
/reports/export?type=overtime&format=xlsx→ téléchargement du fichier - GET
/reports/export?type=overtime&format=csv→ téléchargement du fichier avec BOM - Non-RH/Comptable → 403
- Isolation des locataires : les données du locataire A n'apparaissent pas dans le rapport du locataire B
Ce que l'assurance qualité va valider¶
- Vérifier que les tranches d'heures supplémentaires correspondent à la configuration (base de 40 h, valeurs par défaut CI)
- Générer un rapport pour le mois avec les heures supplémentaires connues, vérifier la répartition par tranche
- Exporter vers Excel et CSV, vérifier la mise en forme et l'exactitude des données
- Vérifier le recalcul rétroactif après régularisation
- Tableau réactif à tous les points de rupture
Hors périmètre¶
- Calcul monétaire des heures supplémentaires (module Paie)
- Taux d'heures supplémentaires multi-pays (V2)
- Dérogations aux conventions collectives (V2)
- Alertes d'heures supplémentaires en temps réel (V2)
Définition de « terminé »¶
- [ ] Le traitement par lots hebdomadaire de classification s'exécute correctement
- [ ] Les tranches d'heures supplémentaires sont classées selon la configuration du tenant
- [ ] Le recalcul rétroactif lors de la régularisation fonctionne
- [ ] L'événement
WeeklyOvertimeComputedest publié après la classification - [ ] L'endpoint du rapport sur les heures supplémentaires renvoie une répartition correcte des tranches
- [ ] L'exportation réutilise les services Excel/CSV de QR-017
- [ ] La migration Flyway a été appliquée avec succès
- [ ] L'affichage du rapport s'affiche correctement à tous les points de rupture (360px, 768px, 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 satisfaits manuellement
- [ ] Les tests unitaires sont écrits et réussis
- [ ] Les tests d'intégration sont écrits et réussis
- [ ] L'isolation multi-tenant est vérifiée
- [ ] Pas de
anyen TypeScript, pas de types bruts en Java - [ ] Les réponses API respectent le format d'enveloppe standard
- [ ]
./gradlew testest vert - [ ]
./gradlew spotlessApplyréussit