QR Attendance (QRCONTR) — PRD+FSD Hybrid¶
Module Code: QRCONTR Product: (Papillon HR Suite + ALTARYS ENTERPRISE HR Suite) Country Scope: CI (Côte d'Ivoire) — MVP Version: 1.0 Date: 01/03/2026 Author: ANALYST (Claude Code) Input documents: - docs/specs/qr-attendance.md (Tier 1 human-written spec) - docs/prd/platform-vision-prd.md (Platform Vision PRD v1.0) - docs/research/3_validated/qr-attendance-legal-validated.md (legal research) - docs/research/2_audit/qr-attendance-legal-audit.md (legal audit gaps)
PART A — Product Requirements (PRD)¶
A.1 Executive Summary¶
The Problem¶
Attendance tracking in the OHADA zone is typically done on paper sign-in sheets or not at all. This creates three compounding risks for employers:
- Payroll inaccuracy: Overtime and late deductions are estimated, not calculated from actual clock data. This leads to over- or under-payment — both costly.
- Indefensible position in disputes: When an employee disputes overtime pay or attendance deductions, employers without reliable records are at a disadvantage. Courts in Côte d'Ivoire, following the francophone tradition derived from French L.3171-4, tend to favor the employee when the employer cannot produce time-tracking records.
- Buddy punching and phantom attendance: Paper sign-in sheets have zero accountability — employees can sign in for absent colleagues with no detection mechanism.
Additionally, biometric attendance systems (fingerprint, facial recognition), which some employers have adopted, are now effectively prohibited in Côte d'Ivoire by ARTCI (the data protection authority), which declared them disproportionate for attendance control purposes (communiqués 2019, reiterated June 2024). Companies using biometric systems face regulatory risk.
The Solution¶
The QR Attendance module (QRCONTR) replaces paper registers and non-compliant biometric systems with a privacy-compliant, mobile-friendly, offline-capable clock-in/clock-out system based on QR code scanning.
Module positioning: Risk mitigation + operational efficiency. The module: - Protects employers in labor disputes by producing tamper-resistant, timestamped attendance records with full audit trails - Feeds accurate overtime data to Payroll — hours classified by overtime band, ready for monetary calculation - Replaces paper sign-in sheets with a digital system that works on any smartphone, even offline - Complies with CI data protection law — QR codes are explicitly endorsed by ARTCI as a proportionate alternative to biometrics
Module code: QRCONTR Sellable: Yes Sprint: 2b (parallel with Absence Management) Commercial target: March 2026
A.2 User Personas¶
P1: Directeur Général (DG) —¶
- In QR Attendance: Views company-wide attendance dashboard (summary stats). Does not configure or operate the module.
- Key need: "Is my team showing up? How much overtime are we paying?"
- Papillon context: Often the company owner (gérant SARL). In very small businesses (S1-S2, 2-10 employees), may also be the HR manager who configures the module.
P2: Responsable RH / HR Manager —¶
- In QR Attendance: Primary operator. Configures sites, QR codes, work schedules. Reviews daily attendance dashboard. Creates/approves regularizations. Runs reports. Exports data. Manages télétravail requests.
- Key need: "Who's here today? Who's late? Are my overtime records accurate for payroll?"
- Papillon context: Often a trusted employee wearing multiple hats. Needs hand-holding — clear labels, forgiving forms, auto-save. Transitioning from paper or Excel attendance sheets.
- Enterprise context (V2): Professional HR Director. Needs bulk schedule assignment, batch regularization, advanced analytics.
P4: Employé / Employee —¶
- In QR Attendance: Scans QR code to clock in/out. Views own attendance history. Requests regularizations when they forgot to scan. Requests télétravail days.
- Key need: "Clock in quickly, check my hours, request a correction if I forgot."
- Papillon context: Low digital literacy. Android phone (often entry-level). Intermittent connectivity. Needs absolute simplicity — scan, see confirmation, done.
N+1: Manager —¶
- In QR Attendance: Views team attendance. Approves regularization requests for direct reports. Approves télétravail requests. Views team reports.
- Key need: "Who on my team is late or absent? Approve corrections quickly."
- Papillon context: May be a senior employee with limited management tool experience. Needs clear approval actions.
P3: Comptable / Accountant —¶
- In QR Attendance: Read-only access to attendance data for payroll reconciliation. Views overtime reports.
- Key need: "Verify overtime hours before payroll processing."
A.3 User Stories¶
US-QR-001: Employee Clock-In¶
As an employee, I want to scan the site QR code when I arrive at work, So that my attendance is accurately recorded.
Acceptance Criteria: - Given I am logged into the Papillon app and at a site with a posted QR code, When I scan the QR code, Then a clock-in event is recorded with my employee ID, the site ID, and the device timestamp. - Given I scan the QR code, When the scan is successful, Then I see a confirmation message: "Pointage enregistré — [HH:MM]". - Given I am offline, When I scan the QR code, Then the clock event is stored locally and queued for sync. - 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. - Given I am a terminated employee, When I try to scan, Then the scan is rejected with message "Compte désactivé — contactez les RH".
US-QR-002: Employee Clock-Out¶
As an employee, I want to scan the site QR code when I leave work, So that my departure time is recorded and my worked hours calculated.
Acceptance Criteria: - Given I have a clock-in recorded for today, When I scan the QR code, Then a clock-out event is recorded. - Given I forget to clock out, When my scheduled end time passes, Then the system auto-closes my record at the scheduled end time, flags it as SYSTEM-generated, and does NOT credit overtime. - Given I clock out before my scheduled end time, When the system processes the event, Then an early departure (départ anticipé) is flagged.
US-QR-003: View Own Attendance History¶
As an employee, I want to view my attendance history (clock times, late flags, regularizations), So that I can verify my records and dispute inaccuracies.
Acceptance Criteria: - Given I am logged in, When I navigate to my attendance history, Then I see a list of my clock events for the current month (default), filterable by date range. - Given I am offline, When I view my history, Then I see cached data from the last sync.
US-QR-004: Request Regularization¶
As an employee or manager, I want to submit a regularization request when a clock event is missed or incorrect, So that my attendance record can be corrected with an audit trail.
Acceptance Criteria: - Given I forgot to clock in/out, When I submit a regularization request, Then I must select a reason from the predefined list and specify the corrected time(s). - Given I submit a request, When it is saved, Then it enters PENDING status and my manager and HR are notified. - Given I am offline, When I submit a request, Then it is queued for sync.
US-QR-005: Approve Regularization¶
As a manager or HR, I want to review and approve/reject regularization requests, So that attendance records are corrected with proper authorization.
Acceptance Criteria: - Given I am a manager, When I view pending regularizations, Then I see only requests from my direct reports. - Given I am HR, When I view pending regularizations, Then I see all pending requests across the company. - Given I approve a regularization, When the system processes it, Then the attendance record for that day is updated in display/calculation (original record preserved for audit). - Given I am HR, When I see a manager-approved regularization that is incorrect, Then I can override/reject it.
US-QR-006: HR Direct Regularization¶
As HR, I want to create a regularization directly (without a request), So that I can correct records I notice during my daily review without waiting for a request.
Acceptance Criteria: - Given I am HR, When I create a direct regularization, Then it is auto-approved (no pending step) and recorded with HR as both creator and approver. - Given I create a direct regularization, When it is saved, Then the employee is notified that their record was corrected.
US-QR-007: Request Télétravail¶
As an employee, I want to request a télétravail (remote work) day, So that the system knows I am working remotely and does not mark me as absent.
Acceptance Criteria: - Given I request télétravail for a future date, When the date is more than the configured advance notice (default 2 days), Then the request is submitted without mandatory reason. - Given I request same-day or short-notice télétravail, When I submit the request, Then a reason field is mandatory (e.g., 'Enfant malade', 'Problème de transport'). - Given my company has a maximum télétravail days/week configuration, When I already have the maximum approved for this week, Then I am warned before submitting (not blocked — HR can still approve). - Given my request is approved, When the day arrives, Then my status on the dashboard is "Télétravail", no QR scan is expected, and scheduled hours are credited automatically. - 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).
US-QR-008: Configure Sites and QR Codes¶
As HR, I want to create work sites and generate QR codes for each site, So that employees can clock in/out at the correct location.
Acceptance Criteria: - Given I create a new site, When I save it, Then a QR code is generated containing the site ID, tenant ID, and a static HMAC-signed token. - Given I suspect QR code fraud (e.g., screenshot sharing), When I regenerate a site's QR code, Then the previous QR code is immediately invalidated. - Given the QR code is generated, When I view it, Then I can download or print it.
US-QR-009: Configure Work Schedules¶
As HR, I want to define work schedules with per-day start/end times and lunch windows, So that the system can detect late arrivals, early departures, and overtime.
Acceptance Criteria: - Given I create a schedule, When I configure it, Then I can set different start/end times for each day (Mon-Sat). Sunday is off by default. - Given I create a schedule, When I configure it, Then I can define a lunch break window (start/end time) for calculation purposes. - Given I create a schedule, When I configure it, Then I can enable or disable break tracking for this schedule. - Given I create a schedule, When I assign it, Then I can assign it to individual employees or to a department (all employees in that department inherit it).
US-QR-010: Daily Attendance Dashboard¶
As HR or a manager, I want to see a real-time view of today's attendance, So that I can act on late arrivals, absences, and anomalies.
Acceptance Criteria: - Given I open the dashboard, When data loads, Then I see summary counts: Présents, En retard, Absents, Télétravail, En congé. - Given I open the dashboard, When I view the employee list, Then I can filter by department, site, or status. - Given an anomaly exists (incomplete record, shared device alert), When I view the dashboard, Then the anomaly is visually flagged. - Given I am a manager, When I view the dashboard, Then I see only my team's data. - Given I am HR, When I view the dashboard, Then I see all employees.
US-QR-011: Monthly Attendance Report¶
As HR, I want to generate a monthly attendance sheet per employee and per department, So that I have a complete record for payroll input and management review.
Acceptance Criteria: - 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. Summary row: total worked hours, total overtime (by band), total late arrivals (count + minutes), total early departures, total absences, total télétravail days. - 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. - Given I generate any report, When I click export, Then I can download it as Excel or CSV.
US-QR-012: Overtime Report for Payroll¶
As HR or accountant, I want to generate an overtime report classified by band, So that Payroll can apply the correct monetary rates.
Acceptance Criteria: - 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. - Given I export the report, When Payroll receives it, Then the data is structured for direct import.
US-QR-013: Module Activation Compliance Reminder¶
As an HR activating the QR Attendance module, I want to be reminded of the legal obligation to consult délégués du personnel, So that my company is compliant before tracking attendance electronically.
Acceptance Criteria: - Given I activate the QR Attendance module, When the activation screen loads, Then I see a compliance notice referencing Art. 16.1 Code du Travail and the délégués du personnel consultation requirement. - Given I see the notice, When I acknowledge it, Then I can check "Oui, consultation effectuée", optionally enter the consultation date, and optionally upload the PV (procès-verbal). - Given I do NOT check the box, When I continue, Then the module activates anyway (not a blocker) but the system records that the reminder was shown and not acknowledged.
A.4 Non-Functional Requirements¶
| Requirement | Target | Notes |
|---|---|---|
| Clock-in response time | < 1 second from scan to confirmation on-screen | Critical UX — employee is standing at the entrance |
| Offline clock-in | Works fully offline; queues and syncs within 30s of reconnection | Primary use case for factory/construction/rural sites |
| Dashboard refresh | Near-real-time for online scans (≤ 5s latency via WebSocket or polling) | Offline scans appear on dashboard once synced |
| Report generation | < 5 seconds for monthly attendance sheet (single employee) | For department-level: < 15 seconds for departments up to 100 employees |
| QR code scan accuracy | ≥ 99% successful decode on first attempt in normal lighting | Entry-level Android phones with basic cameras |
| Data retention | 10 years, then anonymize personal data | Aligned with OHADA general document retention (see §A.7 Temporarily Validated) |
| Concurrent clock-ins | Support 500 simultaneous clock-in events per tenant | Large SME shift change scenario (S5-S6 segments, 100-350 employees all arriving within 15 minutes) |
| Scale target | 100,000+ tenant companies × average 20 employees × 2 scans/day = 4M daily clock events platform-wide | Shared DB profile must handle this volume |
| Uptime | 99.5% (Papillon), 99.9% (Enterprise, contractual) | Inherited from Platform Vision |
| Offline storage | Up to 30 days of queued clock events per device | Covers extended connectivity outages in rural areas |
| Export performance | < 10 seconds for Excel export of 1 month × 350 employees | Largest Papillon tenant scenario |
A.5 MVP Scope¶
In MVP (V1)¶
| Feature | Description |
|---|---|
| Site management | CRUD sites, generate/regenerate QR codes per site |
| QR code scanning | Built-in camera scanner in Papillon app |
| Clock-in / clock-out | Record with timestamp, employee ID, site ID, hashed device ID |
| Work schedule configuration | Per-day start/end times (Mon-Sat), lunch break window, assignable to employee or department |
| Optional break tracking | HR enables per site/department. When enabled: 4 scans/day. When disabled: scheduled break window used |
| Late arrival detection | Configurable tolerance: company default (5 min) + department override |
| Early departure detection | Flagged when clock-out before scheduled end |
| Missed clock-out handling | Auto-close at scheduled end, flagged SYSTEM, no overtime |
| Overtime hour classification | Classify into configurable bands (Band 1/2/3 + Night + Sunday/Holiday). CI defaults pre-loaded |
| Weekly overtime tracking | Configurable week start (default Monday). 40h/week legal duration |
| Regularization workflow | Employee/manager request → Manager (team) or HR (all) approves. HR direct-create. Additive records |
| Télétravail workflow | Request → approval (Manager N+1 or HR). Configurable advance notice + max days. Same-day with reason |
| Daily attendance dashboard | Summary counts + employee list + anomaly flags + actions |
| Monthly attendance sheet | Per employee + department summary. Export Excel/CSV |
| Overtime report | Per employee/week, classified by band. Export Excel/CSV |
| Early departure report | Track and report départs anticipés |
| Public holiday calendar | Pre-loaded, ALTARYS-maintained. HR can add company-specific non-working days |
| Anti-fraud: device ID | Hashed device UUID captured. Anomaly detection for shared devices |
| Anti-fraud: auth session | Scan requires authenticated Papillon app session |
| Compliance reminder | Délégués du personnel consultation notice on module activation |
| Offline clock-in/out | Queued in IndexedDB, synced on reconnect |
| Offline regularization | Draft offline, queue for sync |
| Offline télétravail request | Draft offline, queue for sync |
| Offline attendance view | Cached own history |
| Audit trail | All actions logged: clock events, regularizations, config changes, QR regenerations |
| Flexible site scanning | Employee has primary site but can scan at any tenant site. Non-primary flagged |
| Standalone mode | Works without Absence module. Non-holiday non-scan days = "Absent". Graceful integration when Absence events available |
| Tenant-configurable overtime bands | Band thresholds configurable per tenant. CI defaults shipped |
Out of MVP (V2+)¶
| Feature | Target |
|---|---|
| GPS coordinate capture at scan | V2 — anti-fraud, single point per scan, privacy review needed |
| QR code token rotation | V2 — daily/hourly rotation for anti-screenshot |
| Shift management | V2 — morning/afternoon/night shifts with rotation |
| Kiosk mode | V2 — shared tablet at site entrance |
| Geofencing | V2 — validate scan within X meters of site |
| Absence pattern analytics | V2 — frequent Monday absences, trends |
| Physical access control integration | V2 — turnstiles, gates |
| Team calendar with attendance overlay | V2 |
| Manager mobile notifications | V2 — push notifications for team late arrivals |
| Bulk schedule assignment | V2 — assign schedule to 500+ employees at once |
| Device binding | V2 — optional bind employee to specific device |
| Anomaly detection (impossible travel) | V2 — clock-in at two sites within impossible travel time |
| Remote clock-in (no QR) | V2 — button-based clock-in for formalized telework |
| Per-employee late tolerance | V2 — for special cases (e.g., mobility constraints) |
| Multi-country overtime rates | Month 9 — BJ, CM rate structures |
| Registre d'employeur integration | V2 — dedicated compliance module |
| Collective agreement override rules | V2 — sector-specific working time rules |
| Night work special rules | V2 — CI night worker regulations |
A.6 Open Questions¶
| ID | Question | Priority | Impact |
|---|---|---|---|
| OQ-QR-001 | ARTCI declaration requirement: Is a prior declaration to ARTCI required before a company can deploy a QR-code-based attendance system? If yes, the module must include an ARTCI filing checklist in the onboarding flow. | CRITICAL | Onboarding UX, compliance |
| OQ-QR-002 | CI overtime band thresholds: The specific CI overtime band structure (which hours fall in Band 1/2/3) needs verification against the Convention Collective Interprofessionnelle and/or implementing decrees of Art. 21.2-21.3 Code du Travail 2015. Currently using configurable thresholds with temporarily-validated CI defaults. | HIGH | Overtime classification correctness |
| OQ-QR-003 | Geolocation single-point proportionality: Does ARTCI's position on proportionality allow a single GPS coordinate capture per clock-in/out, or must location capture be entirely opt-in? Relevant for V2 GPS feature. | MEDIUM | V2 scope |
| OQ-QR-004 | Burden of proof in CI courts: Has CI case law or statute specifically adopted the French L.3171-4 principle (employer bears burden of proof for working time)? Affects product marketing claims. | MEDIUM | Marketing, positioning |
| OQ-QR-005 | Night work special CI rules: Are there additional record-keeping requirements for night workers (21:00-05:00) beyond standard attendance tracking? | MEDIUM | V2 scope |
| OQ-QR-006 | Collective agreement overrides: Do major CI collective agreements (Convention Collective Interprofessionnelle, sector conventions) impose attendance-tracking requirements beyond the Code du Travail? | MEDIUM | V2 scope |
| OQ-QR-007 | Sector-specific working time: Are there sector-specific working-time arrangements (agriculture, hospitality, domestic work) that would affect overtime classification? | MEDIUM | V2 scope |
| OQ-QR-008 | Registre d'employeur size exemption: Does the registre d'employeur obligation apply to ALL employers in CI regardless of size (even 1 employee), or is there a threshold? | LOW | Documentation, positioning |
| OQ-QR-009 | Art. 92.3 citation verification: The legal research cites "Art. 92.3" of Code du Travail 2015 for the 5-year registre retention. OHADA codes typically use integer numbering. Verify this is Article 92, alinéa 3 (Art. 92 al. 3). | LOW | Source credibility |
A.7 Temporarily Validated¶
These items are implemented as-is but flagged for verification before production go-live.
| ID | Item | Current Implementation | Validation Needed |
|---|---|---|---|
| TV-QR-001 | Employee consent for QR scanning | Inform-only approach: employee is notified in-app that attendance is tracked via QR. No consent checkbox. Legal basis assumed: employer's legitimate interest + règlement intérieur. | Confirm with CI data protection specialist that non-biometric QR attendance does not require explicit individual consent under Loi 2013-450. |
| TV-QR-002 | CI overtime band defaults | Band 1: 41st-46th hour/week. Band 2: 47th-48th hour/week. Band 3: Beyond 48h/week. Night: 21:00-05:00. Inferred from Convention Collective Interprofessionnelle. | Verify exact thresholds against the CCI text and/or Art. 21.2-21.3 implementing decrees. Thresholds are tenant-configurable, so incorrect defaults can be corrected without code change. |
| TV-QR-003 | 10-year attendance data retention | Applying OHADA 10-year general document retention rule. Attendance data retained 10 years, then anonymized. | Verify whether attendance scan logs specifically fall under the 10-year rule or the 5-year registre d'employeur rule. Using 10 years is the conservative choice since attendance feeds payroll (which is definitely 10-year). |
PART B — Functional Specifications (FSD)¶
B.1 Functional Rules¶
B.1.1 — Site & QR Code Management¶
FR-QR-001 : Site Creation
- A site represents a physical work location belonging to a tenant.
- Required fields: name (string, max 100 chars), address (string, optional), tenantId (from context).
- Site names must be unique within a tenant.
- IF a site with the same name already exists for this tenant THEN reject with error "Un site avec ce nom existe déjà."
FR-QR-002 : QR Code Generation
- When a site is created, the system automatically generates a QR code.
- QR code payload: JSON { "siteId": "<uuid>", "tenantId": "<uuid>", "token": "<static-hmac-token>" }.
- The payload is HMAC-signed using a tenant-specific secret key. This prevents forgery (a user cannot construct a valid QR payload without the server's secret).
- The QR code image is generated server-side and stored as a downloadable/printable asset.
FR-QR-003 : QR Code Regeneration - HR (P2) can regenerate a site's QR code at any time. - IF HR requests QR regeneration THEN: - Generate a new HMAC token. - Invalidate the previous token (any scan using the old QR will fail validation). - Generate a new QR code image. - Log the regeneration event in the audit trail with reason (optional). - The old QR code printed at the site becomes invalid. HR must print and post the new one.
FR-QR-004 : QR Code Validation
- When an employee scans a QR code:
1. Decode the JSON payload.
2. Verify HMAC signature against the tenant's secret key.
3. Verify tenantId matches the authenticated user's tenant.
4. Verify siteId exists and is active.
5. Verify token matches the site's current valid token.
- IF any validation step fails THEN reject the scan with message "QR code invalide. Contactez les RH."
- IF validation succeeds THEN proceed to record the clock event.
- Offline validation: the app caches the list of valid site/token pairs for the user's tenant. IF offline THEN validate against cached data. Accept the last-known token.
B.1.2 — Clock Events¶
FR-QR-010 : Clock Event Recording
- A clock event records: employeeId, siteId, tenantId, timestamp (device local time, ISO 8601 with timezone), eventType (IN or OUT), deviceIdHash (SHA-256 of device UUID), source (EMPLOYEE_SCAN | SYSTEM | HR_REGULARIZATION), syncTimestamp (server receive time, null until synced).
- The timestamp field uses the device clock at the moment of scan. This is the authoritative time for all attendance calculations.
- The syncTimestamp is the time the server received the event. Used for audit purposes only, never for attendance calculations.
FR-QR-011 : Event Type Determination (IN vs OUT) - The system automatically determines whether a scan is a clock-IN or clock-OUT based on the employee's current state for the day: - IF the employee has no open clock-in for today (i.e., no IN without a matching OUT) THEN the scan is an IN. - IF the employee has an open clock-in (i.e., an IN without a matching OUT) THEN the scan is an OUT. - This supports multiple IN/OUT pairs per day (e.g., IN 08:00, OUT 12:00, IN 14:00, OUT 18:00).
FR-QR-012 : Duplicate Scan Detection - IF two scans of the same event type (both IN or both OUT) occur for the same employee within a 15-minute window THEN: - Keep the earliest scan. - Discard the later scan. - Log the discarded scan in audit trail with reason "Doublon détecté (fenêtre 15 min)." - IF two scans of the same type occur more than 15 minutes apart THEN treat as separate events (legitimate multiple sessions).
FR-QR-013 : Terminated Employee Scan Rejection - IF the employee's status in the Control Plane is TERMINATED or OFFBOARDED THEN: - Reject the scan. - Display message: "Compte désactivé — contactez les RH." - Log the rejected scan attempt in audit trail.
FR-QR-014 : Clock-In Before Scheduled Start - IF an employee clocks in before their scheduled start time THEN: - Record the actual scan time as the clock-in time. - Worked hours count from the actual scan time (the earlier of scan time and scheduled start). - Example: scheduled start 08:00, scan at 07:30 → worked hours begin at 07:30.
FR-QR-015 : Weekend / Non-Scheduled Day Scan - IF an employee with no scheduled work on a given day (e.g., Saturday for a Mon-Fri schedule) scans the QR code THEN: - Allow the scan. Record the clock event normally. - The day is automatically classified as unscheduled overtime / weekend work. - The hours are classified into the Sunday/Holiday overtime band if the day is Sunday or a public holiday, or the appropriate overtime band otherwise.
B.1.3 — Missed Clock-Out Handling¶
FR-QR-020 : Auto-Close at Scheduled End
- At end-of-day processing (batch job, runs at configurable time, default 23:59):
- FOR EACH employee with an open clock-in (IN without OUT) for today:
- IF the employee's scheduled end time has passed THEN:
- Generate a synthetic clock-out event at the employee's scheduled end time.
- Set source = SYSTEM.
- Set autoCloseReason = "MISSED_CLOCK_OUT".
- Do NOT generate overtime for this auto-closed period.
- Flag the day as "Pointage incomplet (fermeture automatique)" on the dashboard.
- IF the employee has no schedule (edge case) THEN:
- Do NOT auto-close. Flag as "Pointage incomplet — pas d'horaire configuré."
- Require manual regularization.
FR-QR-021 : Auto-Close Visibility - Auto-closed records are visually distinct on the dashboard and in reports (different icon/color). - HR sees a consolidated list of all auto-closed records from the previous day each morning. - The employee can request a regularization to correct an auto-closed record (e.g., they actually stayed until 19:00).
B.1.4 — Late Arrival & Early Departure Detection¶
FR-QR-030 : Late Arrival Detection - An employee is flagged as "En retard" IF their first clock-in time of the day exceeds their scheduled start time by MORE than the applicable tolerance. - Tolerance lookup order: 1. Department-level tolerance (if configured). 2. Company-level tolerance (default: 5 minutes). - Late duration = clock-in time − scheduled start time (not tolerance-adjusted). Example: schedule 08:00, tolerance 5 min, clock-in 08:07 → flagged as late, late duration = 7 minutes. - IF clock-in is within tolerance THEN: record the actual time, but do NOT flag as late. - The tolerance only affects the RETARD flag. The actual scan time is ALWAYS recorded as-is and used for worked-hours calculation.
FR-QR-031 : Early Departure Detection - An employee is flagged as "Départ anticipé" IF their last clock-out time of the day precedes their scheduled end time. - Early departure duration = scheduled end time − clock-out time. - No tolerance applied to early departures (any departure before scheduled end is flagged).
FR-QR-032 : No-Show Detection
- IF an employee has no clock events for a working day (and the day is not a public holiday, approved leave, or approved télétravail) THEN:
- Flag as "Absent sans justification."
- IF the Absence Management module is connected and a LeaveApproved event covers this date THEN:
- Flag as "En congé" instead.
- IF the employee has an approved télétravail request for this date THEN:
- Flag as "Télétravail."
- IF the employee has a PENDING télétravail request for this date THEN:
- Flag as "Absent en attente de validation" (conservative).
B.1.5 — Work Schedules¶
FR-QR-040 : Schedule Structure
- A work schedule defines, for each day of the week (Monday through Saturday):
- isWorkingDay (boolean)
- startTime (HH:MM, required if isWorkingDay = true)
- endTime (HH:MM, required if isWorkingDay = true)
- breakStartTime (HH:MM, optional — lunch break window start)
- breakEndTime (HH:MM, optional — lunch break window end)
- breakTrackingEnabled (boolean, default false)
- Sunday: isWorkingDay = false by default. Can be set to true (for businesses that operate on Sundays).
- A schedule has a name (e.g., "Bureau", "Entrepôt", "Terrain") for easy identification.
FR-QR-041 : Schedule Assignment - A schedule can be assigned to: - An individual employee (overrides department schedule). - A department (all employees in the department inherit it, unless they have an individual override). - IF an employee has no schedule assigned (individually or via department) THEN: - The system cannot calculate late/early/overtime for this employee. - Clock events are still recorded, but flags and calculations are suspended. - HR sees a warning: "Pas d'horaire configuré pour [Nom]."
FR-QR-042 : Worked Hours Calculation (Break Tracking Disabled)
- IF break tracking is disabled for the employee's schedule THEN:
- Daily worked hours = Σ(clock-out − clock-in) for all IN/OUT pairs − scheduled break duration.
- Scheduled break duration = breakEndTime − breakStartTime.
- IF no break window is defined THEN: daily worked hours = Σ(clock-out − clock-in) with no break deduction.
FR-QR-043 : Worked Hours Calculation (Break Tracking Enabled) - IF break tracking is enabled THEN: - The system expects 4 scans per day: IN (morning), OUT (break start), IN (break end), OUT (evening). - Daily worked hours = (break-OUT − morning-IN) + (evening-OUT − break-IN). - IF the break scans are missing THEN: auto-apply the scheduled break window (FR-QR-044).
FR-QR-044 : Missing Break Scan Handling
- IF break tracking is enabled AND an employee has only 2 scans (IN and OUT, no break scans) THEN:
- Auto-apply the scheduled break window: insert synthetic BREAK_OUT at breakStartTime and BREAK_IN at breakEndTime.
- Set source = SYSTEM on both synthetic events.
- Flag the day as "Pause non enregistrée (horaire appliqué)."
- HR sees the flag and can create a regularization if the actual break was different.
B.1.6 — Overtime Classification¶
FR-QR-050 : Overtime Band Configuration
- Overtime bands are configurable per tenant via a overtime_config table:
- bandCode (BAND_1, BAND_2, BAND_3, NIGHT, SUNDAY_HOLIDAY)
- weeklyThresholdStart (hours, for BAND_1/2/3 — e.g., 40, 46, 48)
- weeklyThresholdEnd (hours, nullable — null means unlimited)
- nightStartTime (HH:MM, for NIGHT band — default 21:00)
- nightEndTime (HH:MM, for NIGHT band — default 05:00)
- countryCode (CI, BJ, CM — for multi-country V2)
- CI defaults (temporarily validated — see TV-QR-002):
- BAND_1: 40h < weekly ≤ 46h
- BAND_2: 46h < weekly ≤ 48h
- BAND_3: weekly > 48h
- NIGHT: 21:00–05:00
- SUNDAY_HOLIDAY: any work on Sunday or public holiday
FR-QR-051 : Weekly Overtime Calculation - The overtime calculation week runs from the configured start day (default: Monday 00:00) to the day before (default: Sunday 23:59). - The week start day is configurable per tenant. - Legal weekly duration: 40 hours (CI). - At end-of-week processing: - Total weekly worked hours = Σ daily worked hours (Mon through Sun). - IF total > 40h THEN overtime hours = total − 40h. - Classify overtime hours into bands based on configured thresholds: - First N hours over 40 → BAND_1 (until threshold end). - Next N hours → BAND_2. - Remaining → BAND_3. - Hours worked during the NIGHT window are additionally classified into the NIGHT band (these hours are also counted in BAND_1/2/3 — night is a supplementary classification). - Hours worked on Sunday or a public holiday are additionally classified into the SUNDAY_HOLIDAY band.
FR-QR-052 : Daily Overtime Tracking - Daily overtime = actual daily worked hours − scheduled daily hours (per the employee's schedule). - IF daily overtime > 0 THEN flag the day and record the excess hours. - Daily overtime is informational for the dashboard. The binding overtime classification for Payroll is the weekly calculation (FR-QR-051).
B.1.7 — Regularization Workflow¶
FR-QR-060 : Regularization Request
- An employee or manager can create a regularization request.
- Required fields:
- employeeId (the employee whose record is being corrected)
- date (the date to correct)
- reason (enum: OUBLI_POINTAGE | PROBLEME_TECHNIQUE | MISSION_EXTERIEURE | AUTRE)
- reasonDetail (free text, mandatory if reason = AUTRE, optional otherwise)
- correctedClockIn (HH:MM, optional)
- correctedClockOut (HH:MM, optional)
- At least one of correctedClockIn or correctedClockOut must be provided.
- The request enters PENDING state.
FR-QR-061 : Regularization Approval - A manager can approve regularization requests for their direct reports only. - HR (P2) can approve regularization requests for any employee. - One approval is sufficient (either manager OR HR). - IF approved THEN: - The regularization record is marked APPROVED. - The attendance calculation for that date is recalculated using the corrected times. - The original clock events are PRESERVED. The regularization is an additive record that overrides display and calculation. - If the regularization corrects an auto-closed missed clock-out (FR-QR-020), overtime may now be credited based on the corrected time.
FR-QR-062 : HR Direct Regularization - HR can create a regularization directly, without requiring a request from the employee. - The direct regularization is auto-approved (status = APPROVED, approver = HR). - The employee is notified that their record was corrected. - Use case: HR notices a missing clock-out during daily dashboard review and creates the correction immediately.
FR-QR-063 : HR Override of Manager Approval - HR can reject or override a previously manager-approved regularization. - IF HR rejects a manager-approved regularization THEN: - The regularization status changes to REJECTED. - The attendance calculation reverts to the original clock events. - Both the manager and employee are notified.
FR-QR-064 : Regularization Audit Trail - Every regularization action (create, approve, reject, override) is logged with actor, timestamp, and before/after values. - The original clock events are NEVER modified or deleted. All corrections are additive records.
B.1.8 — Télétravail Workflow¶
FR-QR-070 : Télétravail Request
- An employee can request a télétravail day for a future date.
- Required fields:
- date (the requested remote work date)
- reason (free text, mandatory if advance notice < configured minimum, optional otherwise)
- Advance notice configuration:
- minAdvanceNoticeDays (integer, default 2, configurable per tenant)
- IF the request is for a date less than minAdvanceNoticeDays from today (including same-day) THEN the reason field is mandatory.
- The request enters PENDING state.
- The employee can CANCEL a PENDING request before the date.
FR-QR-071 : Télétravail Approval - Manager (N+1) or HR can approve/reject télétravail requests. - IF approved THEN: - The employee's status for that date = "Télétravail." - No QR scan is expected on that date. - Scheduled hours are credited automatically (standard daily hours, no overtime). - IF rejected THEN: - The employee is notified with the rejection reason. - The employee is expected to attend at their site on that date.
FR-QR-072 : Télétravail Day Limits
- maxTeletravailPerWeek (integer, nullable, configurable per tenant). Default: null (no limit).
- maxTeletravailPerMonth (integer, nullable, configurable per tenant). Default: null (no limit).
- IF the employee submits a request that would exceed the weekly or monthly limit THEN:
- The request is accepted (not blocked) but a warning is displayed to the employee: "Limite de X jours/semaine atteinte. Votre demande sera soumise à validation."
- The approver sees the limit-exceeded warning when reviewing the request.
FR-QR-073 : Pending Télétravail on Day of - IF a télétravail request is still PENDING when the requested date arrives THEN: - The employee's status for that date = "Absent en attente de validation." - The system treats the employee as absent (conservative approach). - The approver is notified that a request is overdue for approval. - IF the approver subsequently approves, the status is retroactively changed to "Télétravail" and the day's hours are credited.
B.1.9 — Public Holidays¶
FR-QR-080 [CI]: Holiday Calendar - The system ships with a pre-loaded CI public holiday calendar for the current year and next year. - ALTARYS maintains and updates the calendar annually (platform data update, not tenant action). - CI public holidays include both fixed dates (e.g., 7 August = Independence Day) and moveable dates (e.g., Tabaski, Maouloud — Islamic calendar).
FR-QR-081 : Company-Specific Non-Working Days - HR can add company-specific non-working days (e.g., company anniversary, local festival). - These days are treated identically to public holidays for attendance purposes.
FR-QR-082 : Holiday Attendance Behavior - On a public holiday or company non-working day: - No attendance is expected. Employees are NOT flagged as absent. - The day is displayed as "Jour férié" or "Jour non travaillé" on the dashboard and reports. - IF an employee scans the QR code on a holiday THEN: - Allow the scan. Record the clock event. - The day is classified as Sunday/Holiday overtime (FR-QR-051). - HR sees the work on the dashboard.
B.1.10 — Anti-Fraud¶
FR-QR-090 : Authenticated Session Requirement - A QR scan is only valid if the scanning device has an active, authenticated Papillon app session. - The QR code content alone is NOT sufficient to record a clock event. The scan must be initiated from within the app.
FR-QR-091 : Device ID Capture
- At scan time, the app captures the device UUID, hashes it (SHA-256), and includes the deviceIdHash in the clock event payload.
- The raw device UUID is NEVER stored or transmitted — only the hash.
FR-QR-092 : Shared Device Anomaly Detection
- IF two different employees record clock events with the same deviceIdHash on the same day THEN:
- Generate an "Alerte: appareil partagé" anomaly.
- Display the anomaly on the HR dashboard, linked to both employees.
- The clock events are NOT rejected or modified — this is an informational flag only.
- The first scan from a previously-unseen deviceIdHash for an employee is logged but NOT flagged (employees change phones).
FR-QR-093 : QR Code Fraud (Invalid Token) - IF a scan contains an invalid or expired token (e.g., from a screenshot of a regenerated QR code) THEN: - Reject the scan with message "QR code invalide. Contactez les RH." - Log the failed attempt with employee ID, site ID, and timestamp in audit trail.
B.1.11 — Offline Behavior¶
FR-QR-100 : Offline Clock Event Storage
- When offline, clock events are stored in IndexedDB on the device.
- Each event includes: all fields from FR-QR-010 + isSynced: false.
- Events are queued in FIFO order for sync.
FR-QR-101 : Sync on Reconnection - When connectivity is restored, the app syncs queued events within 30 seconds. - Sync order: FIFO (oldest first). - For each event, the server validates and processes it as if it were received in real-time. - IF sync fails (server error, validation failure) THEN: - Retry with exponential backoff (max 3 retries). - IF all retries fail THEN: mark the event as "sync_failed" and notify the employee: "Pointage du [date/heure] n'a pas pu être synchronisé. Contactez les RH."
FR-QR-102 : Offline QR Validation - The app caches the list of valid {siteId, tenantId, token} tuples for the authenticated user's tenant. - Cache is refreshed on every successful sync. - IF offline THEN: validate scanned QR against the cached list. - IF the QR is not in the cache (new site added while offline) THEN: reject with message "QR code non reconnu hors ligne. Réessayez en ligne."
FR-QR-103 : Offline Regularization & Télétravail
- Regularization requests and télétravail requests can be drafted offline.
- They are stored in IndexedDB and synced when connectivity returns.
- The request createdAt timestamp uses the device clock (moment of creation), not the sync moment.
FR-QR-104 : Offline Attendance History - The employee can view their own attendance history from the local IndexedDB cache. - Cache contains the last-synced data. New server-side changes (e.g., HR approved a regularization) are not visible until next sync.
B.1.12 — Reporting & Export¶
FR-QR-110 : Monthly Attendance Sheet (Per Employee) - Content per row (one row per working day): - Date | Day of week | Scheduled start | Scheduled end | Actual clock-in | Actual clock-out | Worked hours | Status (Présent / Retard / Absent / Télétravail / Congé / Férié / Départ anticipé) | Late duration (min) | Early departure duration (min) | Overtime hours | Anomalies | Regularizations applied - Summary row: - Total worked hours | Total scheduled hours | Total overtime (by band) | Total late arrivals (count + total minutes) | Total early departures (count + total minutes) | Total absences (count) | Total télétravail days | Total public holidays
FR-QR-111 : Monthly Department Summary - Aggregated version of FR-QR-110 for all employees in a department. - Content per row (one row per employee): - Employee name | Total worked hours | Total overtime | Total late (count) | Total early dep. (count) | Total absences | Total télétravail | Attendance rate (%)
FR-QR-112 : Overtime Report (For Payroll) - Content per row (one row per employee per week): - Employee ID | Employee name | Week number | Week start date | Band 1 hours | Band 2 hours | Band 3 hours | Night hours | Sunday/Holiday hours | Total overtime hours
FR-QR-113 : Export Format - All reports exportable to Excel (.xlsx) and CSV (.csv). - CSV encoding: UTF-8 with BOM (for Excel compatibility with French characters). - Date format in exports: DD/MM/YYYY (French convention). - Time format: HH:MM (24-hour). - Decimal separator for hours: comma (French convention — e.g., "7,5" for 7h30).
B.1.13 — Module Activation Compliance¶
FR-QR-120 : Délégués du Personnel Compliance Reminder - When the QR Attendance module is activated for a tenant: - Display a compliance notice: "La mise en place d'un système de pointage électronique doit faire l'objet d'une consultation des délégués du personnel (Art. 16.1 Code du Travail). Avez-vous effectué cette consultation ?" - UI elements: - Checkbox: "Oui, consultation effectuée" - Date field (optional): "Date de la consultation" - File upload (optional): "PV de la consultation" (procès-verbal) - This is NOT a blocker. HR can proceed without checking the box. - The system records: whether the reminder was shown, whether the box was checked, the date (if provided), the PV file ID (if uploaded). - This record is part of the tenant's compliance audit trail.
FR-QR-121 [CI]: Threshold Awareness - The délégués du personnel obligation applies to enterprises with 11+ employees in CI. - IF the tenant has fewer than 11 active employees THEN: still show the reminder but add a note: "Cette obligation concerne les entreprises de 11 salariés et plus."
B.2 State Machines¶
B.2.1 — Clock Event Lifecycle¶
stateDiagram-v2
[*] --> RECORDED : Employee scans QR
RECORDED --> REGULARIZED : HR/Manager approves regularization
RECORDED --> AUTO_CLOSED : System auto-close (missed clock-out)
AUTO_CLOSED --> REGULARIZED : HR/Manager approves regularization
REGULARIZED --> OVERRIDDEN : HR overrides previous regularization
OVERRIDDEN --> REGULARIZED : New regularization applied
note right of RECORDED
source: EMPLOYEE_SCAN
Original timestamp preserved
end note
note right of AUTO_CLOSED
source: SYSTEM
No overtime credited
end note
note right of REGULARIZED
source: HR_REGULARIZATION
Additive record, original preserved
end note
B.2.2 — Regularization Request Lifecycle¶
stateDiagram-v2
[*] --> PENDING : Employee/Manager creates request
PENDING --> APPROVED : Manager (team) or HR approves
PENDING --> REJECTED : Manager or HR rejects
APPROVED --> OVERRIDDEN_BY_HR : HR overrides manager approval
OVERRIDDEN_BY_HR --> REJECTED : HR rejects
note right of PENDING
Notifies approvers
end note
note right of APPROVED
Recalculates attendance
Preserves original events
end note
Note: HR direct regularizations (FR-QR-062) bypass the PENDING state entirely — they are created directly as APPROVED.
B.2.3 — Télétravail Request Lifecycle¶
stateDiagram-v2
[*] --> PENDING : Employee submits request
PENDING --> APPROVED : Manager N+1 or HR approves
PENDING --> REJECTED : Manager or HR rejects
PENDING --> CANCELLED : Employee cancels
APPROVED --> [*] : Day passes (consumed)
REJECTED --> [*] : Employee notified
CANCELLED --> [*] : Request withdrawn
note right of PENDING
If day arrives while PENDING:
Status = "Absent en attente de validation"
end note
note right of APPROVED
No QR scan expected
Schedule hours credited
No overtime tracked
end note
B.2.4 — Daily Attendance Status (Per Employee Per Day)¶
stateDiagram-v2
[*] --> EXPECTED : Working day starts
EXPECTED --> PRESENT : Clock-in recorded
EXPECTED --> TELETRAVAIL : Télétravail approved for today
EXPECTED --> EN_CONGE : Leave approved (Absence module)
EXPECTED --> FERIE : Public holiday / company non-working day
EXPECTED --> ABSENT : End of day, no clock-in
EXPECTED --> ABSENT_PENDING : Télétravail PENDING on day-of
PRESENT --> RETARD : Clock-in after tolerance
PRESENT --> DEPART_ANTICIPE : Clock-out before scheduled end
PRESENT --> INCOMPLET : Scheduled end passed, no clock-out
INCOMPLET --> AUTO_CLOSED : System auto-close at scheduled end
AUTO_CLOSED --> REGULARIZED : Regularization corrects times
ABSENT --> REGULARIZED : Regularization provides clock times
ABSENT_PENDING --> TELETRAVAIL : Approver approves retroactively
ABSENT_PENDING --> ABSENT : Approver rejects or day closes
B.3 Decision Tables¶
B.3.1 — Daily Status Resolution¶
| Has Clock-In? | Has Clock-Out? | Is Holiday? | Is Leave? | Is Télétravail (Approved)? | Is Télétravail (Pending)? | Status |
|---|---|---|---|---|---|---|
| Yes | Yes | No | No | No | — | PRESENT (check late/early flags) |
| Yes | No | No | No | No | — | INCOMPLET → AUTO_CLOSE at scheduled end |
| No | No | Yes | — | — | — | FERIE |
| No | No | No | Yes | — | — | EN_CONGE |
| No | No | No | No | Yes | — | TELETRAVAIL |
| No | No | No | No | No | Yes | ABSENT_PENDING |
| No | No | No | No | No | No | ABSENT |
| Yes | Yes | Yes | No | No | — | FERIE + WORKED (overtime: Sunday/Holiday band) |
B.3.2 — Late Tolerance Resolution¶
| Department Tolerance Set? | Value | Company Default | Effective Tolerance |
|---|---|---|---|
| Yes | 0 min | 5 min | 0 min (department overrides) |
| Yes | 10 min | 5 min | 10 min (department overrides) |
| No | — | 5 min | 5 min (company default applies) |
| No | — | 0 min | 0 min |
B.3.3 — Regularization Approval Authority¶
| Actor | Scope | Can Create Request? | Can Approve? | Can Direct-Create? | Can Override? |
|---|---|---|---|---|---|
| Employee (P4) | Own records | Yes | No | No | No |
| Manager (N+1) | Team records | Yes | Yes (team only) | No | No |
| HR (P2) | All records | Yes | Yes (all) | Yes (auto-approved) | Yes |
| DG (P1) | — | No | No | No | No |
| Comptable (P3) | — | No | No | No | No |
B.3.4 — Overtime Band Classification (CI Defaults — Temporarily Validated)¶
| Weekly Hours | Classification |
|---|---|
| ≤ 40h | Normal (no overtime) |
| 40h < hours ≤ 46h | BAND_1 |
| 46h < hours ≤ 48h | BAND_2 |
| > 48h | BAND_3 |
| Any hours between 21:00-05:00 | NIGHT (supplementary flag, added on top of BAND_1/2/3) |
| Any hours on Sunday or public holiday | SUNDAY_HOLIDAY (supplementary flag) |
B.4 Data Requirements¶
B.4.1 — Key Entities¶
Site¶
| Field | Type | Required | Notes |
|---|---|---|---|
| id | UUID | Yes | PK |
| tenant_id | UUID | Yes | FK → tenant. ALL queries filter by this. |
| name | VARCHAR(100) | Yes | Unique within tenant |
| address | VARCHAR(500) | No | Physical address |
| qr_token | VARCHAR(255) | Yes | Current valid HMAC token |
| qr_generated_at | TIMESTAMP | Yes | When current QR was generated |
| is_active | BOOLEAN | Yes | Default true |
| created_at | TIMESTAMP | Yes | |
| updated_at | TIMESTAMP | Yes |
WorkSchedule¶
| Field | Type | Required | Notes |
|---|---|---|---|
| id | UUID | Yes | PK |
| tenant_id | UUID | Yes | FK → tenant |
| name | VARCHAR(100) | Yes | e.g., "Bureau", "Entrepôt" |
| is_active | BOOLEAN | Yes | Default true |
| created_at | TIMESTAMP | Yes | |
| updated_at | TIMESTAMP | Yes |
WorkScheduleDay¶
| Field | Type | Required | Notes |
|---|---|---|---|
| id | UUID | Yes | PK |
| schedule_id | UUID | Yes | FK → WorkSchedule |
| day_of_week | SMALLINT | Yes | 1=Monday, 7=Sunday |
| is_working_day | BOOLEAN | Yes | |
| start_time | TIME | Conditional | Required if is_working_day = true |
| end_time | TIME | Conditional | Required if is_working_day = true |
| break_start_time | TIME | No | Lunch window start |
| break_end_time | TIME | No | Lunch window end |
| break_tracking_enabled | BOOLEAN | Yes | Default false |
EmployeeScheduleAssignment¶
| Field | Type | Required | Notes |
|---|---|---|---|
| id | UUID | Yes | PK |
| tenant_id | UUID | Yes | FK → tenant |
| employee_id | UUID | Yes | FK → employee (Control Plane) |
| schedule_id | UUID | Yes | FK → WorkSchedule |
| effective_from | DATE | Yes | |
| effective_to | DATE | No | Null = current |
DepartmentScheduleAssignment¶
| Field | Type | Required | Notes |
|---|---|---|---|
| id | UUID | Yes | PK |
| tenant_id | UUID | Yes | FK → tenant |
| department_id | UUID | Yes | FK → department (Control Plane) |
| schedule_id | UUID | Yes | FK → WorkSchedule |
| effective_from | DATE | Yes | |
| effective_to | DATE | No | Null = current |
EmployeeSiteAssignment¶
| Field | Type | Required | Notes |
|---|---|---|---|
| id | UUID | Yes | PK |
| tenant_id | UUID | Yes | FK → tenant |
| employee_id | UUID | Yes | FK → employee |
| site_id | UUID | Yes | FK → Site |
| is_primary | BOOLEAN | Yes | Default true. At most one primary per employee. |
| effective_from | DATE | Yes | |
| effective_to | DATE | No |
Clock¶
| Field | Type | Required | Notes |
|---|---|---|---|
| id | UUID | Yes | PK |
| tenant_id | UUID | Yes | FK → tenant |
| employee_id | UUID | Yes | FK → employee |
| site_id | UUID | Yes | FK → Site |
| event_type | VARCHAR(10) | Yes | IN, OUT, BREAK_OUT, BREAK_IN |
| timestamp | TIMESTAMP WITH TZ | Yes | Device clock at scan time |
| sync_timestamp | TIMESTAMP WITH TZ | No | Server receive time (null until synced) |
| device_id_hash | VARCHAR(64) | Yes | SHA-256 of device UUID |
| source | VARCHAR(20) | Yes | EMPLOYEE_SCAN, SYSTEM, HR_REGULARIZATION |
| is_duplicate | BOOLEAN | Yes | Default false. True if discarded by dedup. |
| auto_close_reason | VARCHAR(30) | No | MISSED_CLOCK_OUT (for SYSTEM source) |
| created_at | TIMESTAMP | Yes |
DailyAttendance (Materialized / Computed)¶
| Field | Type | Required | Notes |
|---|---|---|---|
| id | UUID | Yes | PK |
| tenant_id | UUID | Yes | FK → tenant |
| employee_id | UUID | Yes | FK → employee |
| date | DATE | Yes | |
| status | VARCHAR(30) | Yes | PRESENT, RETARD, ABSENT, TELETRAVAIL, CONGE, FERIE, INCOMPLET, ABSENT_PENDING |
| first_clock_in | TIMESTAMP WITH TZ | No | |
| last_clock_out | TIMESTAMP WITH TZ | No | |
| worked_minutes | INTEGER | No | Total worked minutes (after break deduction) |
| scheduled_minutes | INTEGER | No | Expected minutes from schedule |
| overtime_minutes | INTEGER | No | Daily excess |
| late_minutes | INTEGER | No | 0 if within tolerance |
| early_departure_minutes | INTEGER | No | |
| is_auto_closed | BOOLEAN | Yes | Default false |
| has_anomaly | BOOLEAN | Yes | Default false |
| anomaly_details | JSONB | No | Array of anomaly codes/descriptions |
| regularization_id | UUID | No | FK if regularized |
| created_at | TIMESTAMP | Yes | |
| updated_at | TIMESTAMP | Yes |
RegularizationRequest¶
| Field | Type | Required | Notes |
|---|---|---|---|
| id | UUID | Yes | PK |
| tenant_id | UUID | Yes | FK → tenant |
| employee_id | UUID | Yes | Target employee |
| date | DATE | Yes | The day being corrected |
| reason | VARCHAR(30) | Yes | OUBLI_POINTAGE, PROBLEME_TECHNIQUE, MISSION_EXTERIEURE, AUTRE |
| reason_detail | TEXT | Conditional | Required if reason = AUTRE |
| corrected_clock_in | TIME | Conditional | At least one of in/out required |
| corrected_clock_out | TIME | Conditional | |
| status | VARCHAR(20) | Yes | PENDING, APPROVED, REJECTED |
| requested_by | UUID | Yes | Employee or manager who created |
| approved_by | UUID | No | Manager or HR who approved |
| approved_at | TIMESTAMP | No | |
| is_direct_create | BOOLEAN | Yes | Default false. True if HR created directly. |
| override_of | UUID | No | FK → RegularizationRequest if this overrides a previous one |
| created_at | TIMESTAMP | Yes | |
| updated_at | TIMESTAMP | Yes |
TeletravailRequest¶
| Field | Type | Required | Notes |
|---|---|---|---|
| id | UUID | Yes | PK |
| tenant_id | UUID | Yes | FK → tenant |
| employee_id | UUID | Yes | |
| date | DATE | Yes | Requested remote work date |
| reason | TEXT | Conditional | Mandatory if short-notice |
| status | VARCHAR(20) | Yes | PENDING, APPROVED, REJECTED, CANCELLED |
| approved_by | UUID | No | |
| approved_at | TIMESTAMP | No | |
| rejection_reason | TEXT | No | |
| created_at | TIMESTAMP | Yes | |
| updated_at | TIMESTAMP | Yes |
PublicHoliday¶
| Field | Type | Required | Notes |
|---|---|---|---|
| id | UUID | Yes | PK |
| country_code | VARCHAR(2) | Yes | CI, BJ, CM |
| date | DATE | Yes | |
| name | VARCHAR(200) | Yes | e.g., "Fête de l'Indépendance" |
| is_moveable | BOOLEAN | Yes | True for Islamic holidays |
| year | INTEGER | Yes | Calendar year |
CompanyNonWorkingDay¶
| Field | Type | Required | Notes |
|---|---|---|---|
| id | UUID | Yes | PK |
| tenant_id | UUID | Yes | FK → tenant |
| date | DATE | Yes | |
| name | VARCHAR(200) | Yes | e.g., "Anniversaire entreprise" |
| is_recurring | BOOLEAN | Yes | If true, repeats annually on same date |
| created_at | TIMESTAMP | Yes |
OvertimeConfig¶
| Field | Type | Required | Notes |
|---|---|---|---|
| id | UUID | Yes | PK |
| tenant_id | UUID | Yes | FK → tenant |
| band_code | VARCHAR(20) | Yes | BAND_1, BAND_2, BAND_3, NIGHT, SUNDAY_HOLIDAY |
| weekly_threshold_start | DECIMAL(5,2) | No | Hours (e.g., 40.00) |
| weekly_threshold_end | DECIMAL(5,2) | No | Null = unlimited |
| night_start_time | TIME | No | For NIGHT band |
| night_end_time | TIME | No | For NIGHT band |
| country_code | VARCHAR(2) | Yes | CI (MVP) |
| created_at | TIMESTAMP | Yes | |
| updated_at | TIMESTAMP | Yes |
AttendanceModuleConfig¶
| Field | Type | Required | Notes |
|---|---|---|---|
| id | UUID | Yes | PK |
| tenant_id | UUID | Yes | FK → tenant. One row per tenant. |
| default_late_tolerance_minutes | INTEGER | Yes | Default: 5 |
| overtime_week_start_day | SMALLINT | Yes | 1=Monday (default), 7=Sunday |
| min_teletravail_advance_days | INTEGER | Yes | Default: 2 |
| max_teletravail_per_week | INTEGER | No | Null = no limit |
| max_teletravail_per_month | INTEGER | No | Null = no limit |
| auto_close_time | TIME | Yes | Default: 23:59. When missed clock-out processing runs. |
| delegues_consultation_done | BOOLEAN | No | From compliance reminder |
| delegues_consultation_date | DATE | No | |
| delegues_pv_document_id | UUID | No | FK to document storage |
| created_at | TIMESTAMP | Yes | |
| updated_at | TIMESTAMP | Yes |
DepartmentAttendanceConfig¶
| Field | Type | Required | Notes |
|---|---|---|---|
| id | UUID | Yes | PK |
| tenant_id | UUID | Yes | FK → tenant |
| department_id | UUID | Yes | FK → department |
| late_tolerance_minutes | INTEGER | No | Overrides company default if set |
| created_at | TIMESTAMP | Yes | |
| updated_at | TIMESTAMP | Yes |
WeeklyOvertimeSummary (Computed)¶
| Field | Type | Required | Notes |
|---|---|---|---|
| id | UUID | Yes | PK |
| tenant_id | UUID | Yes | |
| employee_id | UUID | Yes | |
| week_start_date | DATE | Yes | |
| week_end_date | DATE | Yes | |
| total_worked_minutes | INTEGER | Yes | |
| band_1_minutes | INTEGER | Yes | Default 0 |
| band_2_minutes | INTEGER | Yes | Default 0 |
| band_3_minutes | INTEGER | Yes | Default 0 |
| night_minutes | INTEGER | Yes | Default 0 |
| sunday_holiday_minutes | INTEGER | Yes | Default 0 |
| total_overtime_minutes | INTEGER | Yes | |
| created_at | TIMESTAMP | Yes | |
| updated_at | TIMESTAMP | Yes |
B.5 Multi-Tenant Implications¶
The QR Attendance module follows the standard multi-tenant patterns defined in the Platform Vision PRD (FR-PV-040 through FR-PV-047). Specific implications:
| Concern | Implementation |
|---|---|
| QR code tenant isolation | QR payload includes tenantId. Scans are validated against the authenticated user's tenant. A Tenant A employee scanning a Tenant B QR code is rejected at validation step 3 (FR-QR-004). |
| Site uniqueness | Site names unique within tenant (not globally). tenant_id column on all site-related tables. |
| Clock event storage | Shared DB: all events in one clock_event table with tenant_id. Every query includes WHERE tenant_id = ?. |
| Offline cache isolation | The app caches only the authenticated user's tenant data. Switching tenants (for multi-tenant users like P3/Comptable) clears and reloads the cache. |
| Overtime config | Per-tenant configuration. Each tenant can have different overtime bands, even on the same DB. |
| Public holidays | PublicHoliday table is system-wide (not tenant-scoped) — same holidays for all CI tenants. CompanyNonWorkingDay is tenant-scoped. |
| BYO-DB | No special considerations. All entities include tenant_id even in single-tenant databases (for consistency and future migration). |
B.6 Cross-Module Dependencies¶
B.6.1 — Depends On (Hard)¶
| Module | Dependency | What QR Attendance Needs |
|---|---|---|
| Control Plane | Employee data | Active employees (ID, name, department, site assignment). Used for dashboard, reports, schedule assignment, validation. |
| Control Plane | Authentication | User authentication, session management. Required for QR scan validation (FR-QR-090). |
| Control Plane | Organization structure | Departments, sites (if managed centrally). Department hierarchy for manager→team relationships. |
| Control Plane | Module gating | FR-PV-034: every API endpoint checks QRCONTR is ACTIVE for the tenant. |
B.6.2 — Publishes Events¶
| Event Name | Payload | Consumer | Trigger |
|---|---|---|---|
AttendanceRecorded |
{ tenantId, employeeId, date, firstClockIn, lastClockOut, workedMinutes, overtimeMinutes, band1Minutes, band2Minutes, band3Minutes, nightMinutes, sundayHolidayMinutes, lateMinutes, earlyDepartureMinutes, status, isAutoClose } |
Payroll | End-of-day or after regularization that changes a day's calculations |
WeeklyOvertimeComputed |
{ tenantId, employeeId, weekStartDate, weekEndDate, totalOvertimeMinutes, band1Minutes, band2Minutes, band3Minutes, nightMinutes, sundayHolidayMinutes } |
Payroll | End-of-week processing |
Note: The AttendanceRecorded event payload is enriched compared to the Platform Vision PRD's initial definition. The Platform Vision listed overtimeMinutes only; we now include per-band classification. The Payroll module PRD must be updated to consume this enriched payload.
B.6.3 — Consumes Events¶
| Event Name | Source | How QR Attendance Uses It |
|---|---|---|
EmployeeCreated |
Control Plane | Add employee to expected attendance list. No schedule yet — HR must assign one. |
EmployeeUpdated |
Control Plane | Update employee metadata (name, department). Reassignment may change schedule inheritance. |
EmployeeTerminated |
Control Plane | Stop expecting attendance. Reject future scans (FR-QR-013). |
EmployeeOffboarded |
Control Plane | Same as Terminated. |
LeaveApproved |
Absence Mgmt | Suppress attendance expectation for leave dates. Show "En congé" status. IF Absence module not connected: this event is simply never received, and standalone behavior (FR-QR-032) applies. |
LeaveCancelled |
Absence Mgmt | Re-enable attendance expectation for cancelled leave dates. |
B.6.4 — Exposes Internal API (For Future Modules)¶
| Endpoint Pattern | Purpose | Consumer |
|---|---|---|
GET /api/v1/qrcontr/employees/{id}/attendance-summary?month=YYYY-MM |
Monthly attendance summary for an employee | Future Registre/Compliance module |
GET /api/v1/qrcontr/overtime-report?week=YYYY-Wnn |
Weekly overtime data | Payroll module (if event-based delivery is insufficient) |
PART C — Constraints & Boundaries¶
C.1 Regulatory Compliance (CI — Côte d'Ivoire)¶
C.1.1 — Data Protection (Loi n° 2013-450)¶
| Rule | Description | Source |
|---|---|---|
| RC-QR-001 | QR code attendance scanning collects non-biometric personal data (employee ID + timestamp + site + device hash). This falls under the general data processing regime, not the stricter biometric regime. | Loi 2013-450, Art. 1-5; ARTCI communiqués 2019, 2024 |
| RC-QR-002 | Biometric attendance systems (fingerprint, facial recognition) are declared disproportionate by ARTCI and are effectively prohibited for attendance purposes in CI without specific ARTCI authorization. QR code is the explicitly endorsed compliant alternative. | ARTCI communiqué June 2024 |
| RC-QR-003 | Data minimization: the system collects only what is necessary for attendance tracking. No continuous GPS tracking. Device ID is hashed before storage. | Loi 2013-450, proportionality principle |
| RC-QR-004 | Storage limitation: attendance records retained for 10 years (aligned with OHADA general retention), then anonymized. [See TV-QR-003 for validation status.] | OHADA general retention rules |
| RC-QR-005 | OPEN: Whether prior declaration to ARTCI is required for a non-biometric QR attendance system. [See OQ-QR-001.] | Loi 2013-450, declaration requirements |
C.1.2 — Labor Law (Code du Travail 2015, Loi n° 2015-532)¶
| Rule | Description | Source |
|---|---|---|
| RC-QR-010 | The registre d'employeur is mandatory for all employers. Its 2nd fascicule covers "work performed, salary, leave." Attendance data is directly relevant to this obligation. | Art. 92 (al. 3), Code du Travail 2015 |
| RC-QR-011 | Legal weekly working duration: 40 hours. Overtime beyond 40h/week must be compensated with legal majorations (rates determined by implementing decrees and collective agreements). | Art. 21.2-21.3, Code du Travail 2015 |
| RC-QR-012 | The règlement intérieur (internal rules) must be submitted for opinion (avis) to the délégués du personnel before being filed with the labour inspectorate. An electronic attendance system is a work organization measure that should be referenced in the règlement intérieur. | Art. 16.1, Code du Travail 2015 |
| RC-QR-013 | Enterprises with 11+ employees must have délégués du personnel. The system includes a compliance reminder for this consultation (FR-QR-120). | Code du Travail 2015, délégués threshold |
| RC-QR-014 | In overtime disputes, employers who cannot produce attendance records are at a disadvantage. While no CI statute explicitly codifies the French L.3171-4 burden-of-proof principle, francophone court practice follows this tradition. QR attendance records serve as reliable electronic proof. | Francophone jurisprudential tradition; [See OQ-QR-004 for CI-specific validation] |
C.1.3 — Public Holidays (CI)¶
| Rule | Description |
|---|---|
| RC-QR-020 | CI has approximately 14 public holidays per year, including moveable Islamic holidays (Tabaski, Maouloud, etc.) determined annually. |
| RC-QR-021 | Public holidays are paid non-working days. Employees are not required to work. If they do work, they are entitled to Sunday/holiday overtime compensation. |
| RC-QR-022 | The system must not classify employees as "absent" on public holidays where no work is required. |
C.2 Localization Requirements¶
| Dimension | Requirement |
|---|---|
| Language | French (fr-CI). All UI labels, error messages, reports, notifications in French. |
| Currency | XOF (FCFA). Zero decimal places. Formatted: 15 000 FCFA. (Not directly used in this module — monetary calculation is Payroll's responsibility. But if indicative amounts are ever shown, use this format.) |
| Date format | DD/MM/YYYY (e.g., 01/03/2026). In reports and exports. |
| Time format | HH:MM (24-hour). E.g., 08:02, 17:30. |
| Decimal separator | Comma for hours in reports (e.g., 7,5 for 7h30). |
| Week start | Monday (default, configurable). |
| Timezone | Africa/Abidjan (UTC+0, no daylight saving). All timestamps stored with timezone. |
| Name conventions | Last name first, then first name (NOM Prénom). E.g., "KONÉ Aminata." |
| Phone numbers | Not directly used in this module, but if employee contact is needed: +225 XX XX XX XX XX (10-digit CI format). |
C.3 Security Requirements¶
| Requirement | Description |
|---|---|
| Tenant isolation | EVERY database query includes tenant_id filter. No cross-tenant data access. Zero-tolerance policy per Platform Vision FR-PV-041. |
| Role-based access | Employee: own data only. Manager: team data. HR: all employees. DG: dashboards. Comptable: read-only attendance. Per FR-QR decision table B.3.3. |
| Authenticated scanning | QR scans only valid from authenticated Papillon app sessions. The QR code content alone cannot record an event. |
| Device ID hashing | Device UUID is SHA-256 hashed before storage or transmission. Raw UUID never stored. |
| QR token security | QR payloads are HMAC-signed with a tenant-specific secret. Tokens are validated server-side (or against cached data offline). |
| Audit trail | All mutations logged: clock events, regularizations, config changes, QR regenerations, approval actions, compliance acknowledgements. Audit records are immutable (append-only). |
| Data export controls | Excel/CSV exports available only to HR (P2) and Comptable (P3). Exports are logged in audit trail. |
| Offline data protection | IndexedDB data is accessible only to the Papillon app (origin-scoped). Data is encrypted at rest if the device supports it (WebCrypto API). |
| Session timeout | Inherited from Control Plane session management. Expired sessions cannot scan. |
C.4 Out of Scope¶
This module does NOT handle:
| Item | Responsible Module | Timeline |
|---|---|---|
| Payroll salary calculation (overtime pay amounts) | Payroll (PAYROL) | Sprint 4 |
| Leave management (congé annuel, maladie, maternité) | Absence Management (ABSMGT) | Sprint 2a (parallel) |
| Employee lifecycle (hiring, termination, onboarding) | Control Plane / Employee Management | Sprint 1 / Post-MVP |
| Time & Activities tracking (project-based time allocation) | Time & Activities (TIMACT) | Post-MVP |
| Registre d'employeur generation | Future Compliance module | V2 |
| Advanced analytics (absence patterns, predictive) | Analytics (ENTERPRISE ONLY) | V2 |
| Complex shift rotation management | QR Attendance V2 (ENTERPRISE ONLY) | V2 |
| Physical access control integration | QR Attendance V2 (ENTERPRISE ONLY) | V2 |
| Kiosk mode (shared tablet at site entrance) | QR Attendance V2 (ENTERPRISE ONLY) | V2 |
| GPS coordinate capture at scan time | QR Attendance V2 | V2 |
| QR code token rotation | QR Attendance V2 | V2 |
| BJ and CM overtime rate configurations | QR Attendance V2 | Month 9 |
| Country-specific adaptations beyond CI | QR Attendance V2 | Month 9+ |
| Multi-entity consolidation (Enterprise) | ALTARYS ENTERPRISE V2 | Month 18+ |
| SSO/SAML integration | Control Plane V2 | Month 18+ |
| Collective agreement override rules | QR Attendance V2 | V2 |
| Night work special regulations | QR Attendance V2 | V2 |
| Sector-specific working time rules | QR Attendance V2 | V2 |
End of PRD+FSD — QR Attendance (QRCONTR) v1.0