Aller au contenu

Story QR-015: Teletravail Approval + Day-of Status Handling

Module: qr-attendance Slice: QR-T4-002 (partial: approve + day-of status) Brand context: [BOTH] Papillon HR Suite + ALTARYS ENTERPRISE HR Suite Priority: 15 Depends on: QR-014 (requests exist) Can develop concurrently with: QR-013 Merge order: After QR-014 Estimated complexity: M PRD User Stories: US-QR-007 (AC-004, AC-005)


Objective

Implement the manager/HR approval workflow for teletravail requests and the day-of status handling logic. When a teletravail request is approved, the employee's DailyAttendance status is set to TELETRAVAIL with scheduled hours credited automatically (no QR scan expected). If a request is still PENDING when the day arrives, the employee is conservatively marked ABSENT_PENDING. Retroactive approval corrects the status with full audit trail.


Backend Scope

Entities & Records

No new tables. Extends RemoteWorkService and DailyAttendanceService from prior stories.

Flyway Migrations

None.

Repository Layer

No new repositories. Uses existing RemoteWorkRepository and DailyAttendanceRepository.

Service Layer

RemoteWorkService.approve(id, approverId): - Sets status=APPROVED, approvedBy, approvedAt - Calls DailyAttendanceService to set day status=TELETRAVAIL - Credits scheduled hours automatically (no overtime) - No QR scan expected for the day - Publishes notification to employee: "Votre demande de teletravail a ete approuvee."

RemoteWorkService.reject(id, rejecterId, reason): - Sets status=REJECTED, rejectionReason - Publishes notification to employee with rejection reason: "Votre demande de teletravail a ete refusee. Motif : {reason}"

Day-of status handling (batch integration with NoShowDetectionService from QR-009): - If APPROVED teletravail for date → DailyAttendance.status = TELETRAVAIL, scheduledMinutes credited - If PENDING on day of → DailyAttendance.status = ABSENT_PENDING ("Absent en attente de validation") - If approver approves retroactively after day → status changes from ABSENT_PENDING to TELETRAVAIL, hours credited - Publishes notification to approver when request is overdue (request_date = today and status still PENDING)

API Endpoints

Method Path Request Body Response Auth
POST /api/v1/qrcontr/remote-work/{id}/approve ApiResponse<RemoteWorkResponse> Manager (N+1), HR
POST /api/v1/qrcontr/remote-work/{id}/reject {reason: string} ApiResponse<RemoteWorkResponse> Manager (N+1), HR

DTOs

Reuses RemoteWorkResponse from QR-014.

RejectRemoteWorkRequest: - reason (String, required)

Validation Rules

  • Approve/reject: only PENDING requests
  • Reject: reason is mandatory
  • Only Manager (N+1 of employee) or HR can approve/reject
  • Retroactive approval: allowed — status correction is audited

Multi-Tenant Considerations

All queries filter by tenant_id. Manager can only approve/reject requests from their direct reports. HR can approve/reject any request within tenant.


Frontend Scope

Pages & Routes

No new routes. Extends Approval page from QR-012.

Components

TeletravailApprovalCard: - Displayed in approval list under "Teletravail" tab - Shows: employee name, date, reason (if provided), limit warning (if applicable) - Approve/Reject buttons - Overdue indicator: amber badge "! Demande pour aujourd'hui" on cards where request_date = today

Extends ApprovalPage (from QR-012): - Adds teletravail tab/filter alongside regularization requests

TeletravailCalendar (from QR-014): - Approved requests now show green dots (updated from amber pending)

UI States

State Behavior French Copy
Loading Skeleton cards
Empty No pending teletravail requests "Aucune demande de teletravail en attente."
Error Inline retry "Impossible de charger les demandes. Reessayez."
Offline Cached requests, approve/reject queued "Actions sauvegardees — seront synchronisees."
Success (approve) Green flash → card slides out "Teletravail approuve pour {date}."
Success (reject) Red flash → card slides out "Demande refusee."

Responsive Behavior

Same as QR-012 approval page: - 360px: Full-width approval cards, swipe gestures - 768px: Cards with more detail - 1024px+: Split view with list and detail panel

Interactions

  • Same swipe approve/reject as regularization (QR-012)
  • Reject requires reason in popup dialog
  • Undo: 5-second toast window after approve/reject
  • Overdue indicator: amber badge on cards where request_date = today

Acceptance Criteria

AC-001: Approved teletravail credits hours
Given my teletravail request is approved
When the day arrives
Then my status on the dashboard is "Teletravail", no QR scan is expected, and scheduled hours are credited automatically

AC-002: Pending teletravail on day-of marks absent pending
Given my request is still PENDING when the day arrives
When the system evaluates my status
Then I am marked as "Absent en attente de validation" (conservative approach)

OHADA & Regulatory Rules

  • Conservative approach (ABSENT_PENDING) protects employer's attendance record integrity
  • Retroactive approval corrects status with full audit trail
  • All status changes are logged for regulatory compliance

Standards & Conventions

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

Testing Requirements

Unit Tests

  • RemoteWorkService.approve: sets status=APPROVED, DailyAttendance.status=TELETRAVAIL, scheduledMinutes credited
  • RemoteWorkService.reject: sets status=REJECTED, notification sent with reason
  • Day-of handling: PENDING on day → ABSENT_PENDING
  • Retroactive approve: ABSENT_PENDING → TELETRAVAIL, hours credited
  • Overdue notification: triggered when request_date = today and status = PENDING

Integration Tests

  • POST /remote-work/{id}/approve → 200 APPROVED, DailyAttendance updated
  • POST /remote-work/{id}/reject → 200 REJECTED with reason
  • POST /remote-work/{id}/approve with non-manager → 403
  • POST /remote-work/{id}/reject without reason → 400
  • Retroactive approval: DailyAttendance status changes correctly
  • Tenant isolation verified

What QA Will Validate

  • Full approval flow: request → approve → dashboard shows TELETRAVAIL
  • Rejection flow: request → reject → employee notified with reason
  • Verify dashboard status for approved teletravail (no QR scan expected)
  • Verify ABSENT_PENDING for pending requests on day-of
  • Retroactive approval corrects status
  • Swipe approve/reject gestures on mobile
  • Undo toast window (5 seconds)
  • Offline: approve/reject queued and synced

Out of Scope

  • Request creation (QR-014)
  • Dashboard integration of teletravail counts (already in QR-009)
  • Bulk approval (V2)

Definition of Done

  • [ ] Approve/reject endpoints implemented and returning correct responses
  • [ ] DailyAttendance status updated correctly on approval
  • [ ] Scheduled hours credited on approval (no overtime)
  • [ ] ABSENT_PENDING set for pending requests on day-of
  • [ ] Retroactive approval corrects status with audit trail
  • [ ] Approval cards displayed in approval page under teletravail tab
  • [ ] 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
  • [ ] Offline: approve/reject queued and synced
  • [ ] Audit trail entries for all approval/rejection actions
  • [ ] No TypeScript any, no Java raw types
  • [ ] API responses follow standard envelope format
  • [ ] ./gradlew test is green
  • [ ] ./gradlew spotlessApply passes