Aller au contenu

Story QR-017: Monthly Attendance Report + Export

Module: qr-attendance Slice: QR-T5-002 + QR-T5-004 Brand context: [BOTH] Papillon HR Suite + ALTARYS ENTERPRISE HR Suite Priority: 17 Depends on: QR-012 (regularization info in reports) Can develop concurrently with: QR-018 Merge order: Before QR-018 (export service shared) Estimated complexity: M PRD User Stories: US-QR-011


Objective

Build the monthly attendance report for individual employees and department-level summaries, with Excel (.xlsx) and CSV export capabilities. The monthly employee report shows per-day detail (scheduled vs actual hours, status, overtime, anomalies, regularizations) plus a summary row. The department summary aggregates stats across all employees. Export files use French formatting conventions (DD/MM/YYYY dates, HH:MM times, comma decimal separators, UTF-8 with BOM for CSV).


Backend Scope

Entities & Records

No new tables. Uses existing DailyAttendance, Clock, RegularizationRequest.

Flyway Migrations

None.

Repository Layer

No new repositories. Extends existing queries on DailyAttendance.

Service Layer

MonthlyAttendanceReportService: - generateEmployeeReport(tenantId, employeeId, month): - Returns MonthlyEmployeeReport - Per row (one per working day): date, dayOfWeek, scheduledStart, scheduledEnd, actualClockIn, actualClockOut, workedMinutes, status, overtimeMinutes, earlyDepartureMinutes, anomalies, regularizationsApplied - Summary: totalWorkedHours, totalScheduledHours, totalOvertime (by band), totalLateCount+minutes, totalEarlyDepartureCount+minutes, totalAbsences, totalTeletravailDays, totalHolidays

DepartmentSummaryReportService: - generateDepartmentSummary(tenantId, departmentId, month): - Returns DepartmentSummaryReport - Per row (one per employee): name, totalWorkedHours, totalOvertime, totalLateCount, totalEarlyDepartureCount, totalAbsences, totalTeletravail, attendanceRate (%)

ExcelExportService: - Uses Apache POI to generate .xlsx files - French date format: DD/MM/YYYY, time: HH:MM, decimal separator: comma - Company header + report title in first rows - Styled headers, auto-sized columns - Enterprise: includes signature line at bottom

CsvExportService: - UTF-8 with BOM (for Excel compatibility with French characters) - Same format conventions as Excel (DD/MM/YYYY, HH:MM, comma decimals) - Semicolon delimiter (French CSV standard)

API Endpoints

Method Path Request Body Response Auth
GET /api/v1/qrcontr/reports/monthly-attendance ?employeeId=&month=2026-03 ApiResponse<MonthlyEmployeeReport> HR, Comptable
GET /api/v1/qrcontr/reports/department-summary ?departmentId=&month=2026-03 ApiResponse<DepartmentSummaryReport> HR, Manager (own dept)
GET /api/v1/qrcontr/reports/export ?type=monthly-attendance&employeeId=&month=&format=xlsx\|csv File download (Content-Disposition) HR, Comptable

DTOs

MonthlyEmployeeReport: - employeeId (UUID), employeeName (String), month (YearMonth) - summary (ReportSummary): totalWorkedHours, totalScheduledHours, totalOvertimeByBand (Map), totalLateCount, totalLateMinutes, totalEarlyDepartureCount, totalEarlyDepartureMinutes, totalAbsences, totalTeletravailDays, totalHolidays - days (List): date, dayOfWeek, scheduledStart, scheduledEnd, actualClockIn, actualClockOut, workedMinutes, status, overtimeMinutes, earlyDepartureMinutes, anomalies, regularizationsApplied

DepartmentSummaryReport: - departmentId (UUID), departmentName (String), month (YearMonth) - employees (List): employeeId, name, totalWorkedHours, totalOvertime, totalLateCount, totalEarlyDepartureCount, totalAbsences, totalTeletravail, attendanceRate

Validation Rules

  • month format: YYYY-MM (required)
  • employeeId required for monthly-attendance report
  • departmentId required for department-summary report
  • format must be xlsx or csv for export endpoint
  • Manager can only access own department summary

Multi-Tenant Considerations

All report queries filter by tenant_id. Manager restricted to own department. HR and Comptable see all within tenant.


Frontend Scope

Pages & Routes

  • /qrcontr/reports — Report hub
  • /qrcontr/reports/monthly — Monthly attendance report view
  • /qrcontr/reports/department — Department summary view

Components

ReportHubPage (design spec wireframe 3.13): - Links to monthly attendance report and overtime report (QR-018)

MonthlyReportPage: - Employee selector, month picker, summary cards, daily table

DepartmentSummaryPage: - Department selector, month picker, employee summary table

ExportButtons: - "Exporter Excel" + "Exporter CSV" floating action buttons - Triggers browser download on click

ReportTable: - Scrollable table with sticky headers - Sticky first column (date or employee name) on horizontal scroll

UI States

State Behavior French Copy
Loading Skeleton summary + table
Empty No data for period "Aucune donnee pour la periode selectionnee."
Error Inline retry "Impossible de generer le rapport. Reessayez."
Offline Cached summaries only, full report requires server "Rapport complet disponible en ligne uniquement."
Success Summary cards + detailed table

Responsive Behavior

  • 360px: Horizontal scroll table (3 columns visible), export FABs at bottom
  • 768px: 5 columns visible, export FABs at bottom
  • 1024px+: Full table with all columns, export buttons in toolbar

Interactions

  • Employee/department/month selectors: dropdown/picker components
  • Table: horizontal scroll on mobile, sticky first column
  • Export: triggers browser download. Loading spinner on button while generating.
  • Enterprise: Excel file includes company header and signature line

Acceptance Criteria

AC-001: Monthly employee attendance sheet
Given I select an employee and a month
When I generate the report
Then I see for each day: scheduled hours, actual clock-in, actual clock-out, worked hours, status, overtime hours, early departures, anomalies, regularizations applied
And a summary row with: total worked hours, total overtime (by band), total late arrivals (count + minutes), total early departures, total absences, total teletravail days

AC-002: Department summary report
Given I select a department and a month
When I generate a department summary
Then I see aggregated stats across all employees in that department

AC-003: Report export to Excel and CSV
Given I generate any report
When I click export
Then I can download it as Excel (.xlsx) or CSV (.csv) with French date/time/decimal formatting

OHADA & Regulatory Rules

  • FR-QR-113: CSV encoding UTF-8 with BOM, dates DD/MM/YYYY, times HH:MM, decimals with comma
  • Reports support 10-year retention obligation (TV-QR-003)
  • Reports feed payroll reconciliation (accountant access)
  • Attendance records are legal proof in labor disputes

Standards & Conventions

  • docs/standards/java-spring-guidelines.md
  • docs/standards/api-guidelines.md
  • docs/standards/react-typescript-guidelines.md

Testing Requirements

Unit Tests

  • MonthlyAttendanceReportService: monthly report calculation (summary totals, day records)
  • DepartmentSummaryReportService: department aggregation (per-employee stats, attendance rate)
  • ExcelExportService: French date format (DD/MM/YYYY), time format (HH:MM), comma decimal separator
  • CsvExportService: UTF-8 BOM present, semicolon delimiter, French formatting

Integration Tests

  • GET /reports/monthly-attendance?employeeId=&month= → correct report data
  • GET /reports/department-summary?departmentId=&month= → correct summary
  • GET /reports/export?type=monthly-attendance&format=xlsx → file download with correct content type
  • GET /reports/export?type=monthly-attendance&format=csv → file download with BOM
  • Non-HR/Comptable → 403
  • Manager accessing other department → 403
  • Tenant isolation verified

What QA Will Validate

  • Generate monthly report, verify data accuracy against known attendance data
  • Generate department summary, verify aggregation
  • Download Excel file, open in Excel, verify French formatting
  • Download CSV file, open in Excel, verify French characters display correctly (BOM)
  • Responsive table behavior at all breakpoints
  • Offline: cached summary displayed, full report shows online-only message

Out of Scope

  • Overtime report (QR-018)
  • PDF export (Enterprise V2)
  • Year-to-date reports (V2)
  • Email/scheduled report delivery (V2)

Definition of Done

  • [ ] Report generation endpoints return correct data
  • [ ] Excel export with Apache POI works correctly
  • [ ] CSV export with UTF-8 BOM works correctly
  • [ ] French formatting applied (DD/MM/YYYY, HH:MM, comma decimals)
  • [ ] Report hub page links to all report types
  • [ ] Report view renders at all breakpoints (360px, 768px, 1024px)
  • [ ] All 5 UI states implemented (loading, empty, error, offline, success)
  • [ ] French micro-copy matches design spec exactly
  • [ ] All acceptance criteria pass manually
  • [ ] Unit tests written and passing
  • [ ] Integration tests written and passing
  • [ ] Multi-tenant isolation verified
  • [ ] No TypeScript any, no Java raw types
  • [ ] API responses follow standard envelope format
  • [ ] ./gradlew test is green
  • [ ] ./gradlew spotlessApply passes