Skip to content

Pointage et journées ​

C'est le cœur du métier : comment un appui sur « Clock in » devient une journée de travail, avec ses pauses, et comment on en tire des heures.

Les trois notions ​

TableCe que c'estQui l'écrit
clockschaque appui : une arrivée (status: true) ou un départ (false), à une heurela personne, en pointant
workingtimeune journée : de l'arrivée (start) au départ (end, vide tant qu'elle continue)le pointage, ou un manager
breaksles pauses d'une journée : une pause n'est pas du temps de travailla personne, ou un manager

Temps travaillé = durée de la journée − ses pauses.

Pointer : une arrivée ouvre la journée, un départ la ferme ​

Clocks.clock/2, dans une seule transaction :

  • Le pointage et sa journée réussissent ou échouent ensemble : il n'existe jamais de pointage sans journée.
  • Un départ pendant une pause ferme aussi la pause, à la même heure.
  • La ligne de la personne est verrouillée pendant l'opération : deux appuis simultanés passent l'un après l'autre.
  • Personne ne pointe pour un autre, pas même un manager (voir Droits par rôle).

Le site web envoie un simple « pointer » : l'API inverse l'état (arrivée si la personne est absente, départ sinon). L'application mobile dit ce que la personne a fait ("action": "in"), pour qu'un envoi en double ne puisse pas inverser l'état deux fois (voir Mode hors ligne).

Les règles d'une journée ​

RègleOùErreur
Une personne n'a qu'une journée en cours à la foisindex unique workingtime_one_open_per_user422
Une personne n'a qu'une pause en cours par journéeindex unique breaks_one_open_per_working_time422
Deux journées d'une personne ne se chevauchent jamaisWorkingtime.check_no_overlap422 overlaps
La fin est après le débutTimeTracking.changeset422 not_after_start
La fin n'est pas dans le futur (1 minute de tolérance)TimeTracking.changeset422 in_future
Les pauses sont dans la journée, et ne se chevauchent pasTimeTracking.edit_changeset422 outside, overlaps
Une semaine validée est verrouilléeWeekValidations.check_unlocked409 week_validated

Pourquoi aucun chevauchement ?

Une correction corrige la journée fausse, elle n'en ajoute pas une seconde par-dessus. Sinon, les mêmes heures compteraient deux fois.

Une journée appartient au jour où elle commence ​

C'est la règle BR-11. Une nuit de 22:00 à 06:00 compte pour le premier jour. Une journée oubliée, fermée trois jours plus tard, compte aussi pour son jour de début.

Elle s'applique partout :

  • GET /api/workingtime/:userID?start=…&end=… renvoie les journées qui commencent dans la période, même si elles finissent après ;
  • les totaux et moyennes comptent chaque journée sur son jour de début, dans le fuseau de la mairie (Europe/Paris) : une arrivée à 00:30 à Paris un lundi est encore dimanche en UTC, mais compte bien pour lundi.

L'oubli de départ ​

Une personne qui oublie de pointer son départ garde sa journée ouverte. Le pointage suivant (le lendemain matin, par exemple) la ferme : elle dure alors 20 heures, ce qui est faux.

L'API considère comme oubliée une journée de plus de 14 heures du début à la fin, pauses comprises (@max_shift_hours). La loi limite une journée à 10 heures de travail (12 par dérogation) : 14 heures est donc une limite large. Les totaux et moyennes l'ignorent, pour ne pas fausser les moyennes de l'équipe. Le site affiche alors « Missing clock-out », et l'employé la corrige par une demande de correction.

Quand un manager modifie des heures ​

Un manager (ou le General Manager) peut créer, modifier ou supprimer la journée de ses gens, mais jamais la sienne.

  • Avec "breaks", la modification envoie la liste complète des pauses : une pause avec un id est modifiée, une pause sans id est ajoutée, une pause absente de la liste est supprimée.
  • Sans "breaks", les pauses restent comme elles sont.

Chaque écriture ajoute dans la même transaction une ligne au journal working_time_changes : l'action (create, update, delete), les heures et les pauses avant et après, et qui l'a faite. Les deux réussissent ou échouent ensemble : aucune modification n'échappe au journal.

Puis la personne reçoit une notification (dans la cloche et par e-mail). Elle retrouve toutes les modifications de ses heures dans « My Changes » (GET /api/users/:id/changes). Personne ne voit ses heures changer en silence.

Les totaux et moyennes ​

GET /api/users/:id/averages et GET /api/teams/:id/averages, sur une période (Reports) :

ValeurCalcul
total_minutesla somme du temps travaillé
days_workedles jours avec du travail
per_day_minutestotal ÷ jours travaillés
per_week_minutestotal ÷ semaines travaillées (une semaine commence le lundi)
daily, weeklyles minutes jour par jour, semaine par semaine

Un jour sans travail ne fait pas baisser les moyennes : un week-end n'abaisse pas la moyenne quotidienne. Seules les journées terminées et de moins de 14 heures comptent.

Le calcul est fait par PostgreSQL (Workingtime.minutes_per_day/3) : la base soustrait les pauses, convertit chaque début dans le fuseau de la mairie et additionne par jour. Les données ne remontent pas une à une dans Elixir.

Les fichiers ​

FichierRôle
lib/timemanager/clocks.expointer : arrivée, départ, rejeu
lib/timemanager/workingtime.exjournées, pauses, modifications et leur journal, minutes par jour
lib/timemanager/workingtime/time_tracking.exles règles d'une journée et de ses pauses
lib/timemanager/reports.extotaux et moyennes