# pointeuse-optimisator Saisie des horaires de travail avec calcul en temps réel de l'heure de sortie optimale pour finir la semaine à **exactement 0h d'heures supplémentaires**. ![Interface principale](docs/screenshot.png) --- ## Démarrage rapide Avant le premier lancement, copie et adapte le fichier de config (voir [Configuration](#configuration) plus bas) : ```bash cp data/config.example.json data/config.json ``` Pour surcharger `compose.yml` localement (ports, variables d'env, volumes...) sans modifier le fichier versionné, crée un `compose.override.yml` — il est chargé automatiquement par `docker compose` et déjà ignoré par git. --- ## Principe La semaine cible est **39h** (7h48 / jour). Les directives imposent des plages de présence minimum : | Demi-journée | Plage minimale | |---|---| | Matin | 09:00 → 12:00 | | Après-midi | 14:00 → 17:00 | Ces horaires sont configurables (voir [Configuration](#configuration)). Quand un écart apparaît, l'outil ne le reporte pas d'un coup sur la fin de la journée en cours : il **répartit le manque à parts égales sur toutes les demi-journées restantes** de la semaine (matin et après-midi, aujourd'hui compris), pour un rattrapage progressif et confortable plutôt qu'un rush le soir même. Si le rythme normal suffit déjà à rentrer dans les clous, aucune préconisation n'est affichée. --- ## Ce que tu vois dans le tableau | Colonne | Ce qu'elle dit | |---|---| | **Travaillé** | Heures effectivement saisies ce jour | | **Δ jour** | Écart par rapport aux 7h48 dus (affiché dès qu'une heure est enregistrée) | | **Δ sem.** | Solde cumulé depuis lundi — visible uniquement quand la journée est complète et sans jour manquant | | **Fin cible** | Préconisation de sortie **M** (matin) et/ou **A** (après-midi) pour cette demi-journée — vide si le rythme normal suffit | Les plages qui ne respectent pas les minimums sont signalées en rouge dès la saisie. Le bandeau au-dessus du tableau ajoute, quand il reste du retard à rattraper, une ligne **Reste à faire** : le total encore dû, le nombre de demi-journées restantes, et la part supplémentaire moyenne à ajouter sur chacune. --- ## Lancement ```bash docker compose up -d ``` Ouvre [http://localhost:8000](http://localhost:8000). Les données (pointages, congés, comptes) sont stockées dans `data/` et ignorées par git.\ Seul `data/config.example.json` est versionné. --- ## Configuration `data/config.json` (voir `data/config.example.json`) : ```json { "heures_jour": 7.8, "log_level": "DEBUG", "allowed_email_domain": "exemple.fr", "mail_from": "no-reply@exemple.fr", "smtp": { "host": "smtp.exemple.fr", "port": 587, "user": "no-reply@exemple.fr", "password": "change-moi", "use_tls": true }, "plages": { "matin_debut": "09:00", "matin_fin": "12:00", "aprem_debut": "14:00", "aprem_fin": "17:00", "pause_dejeuner_fin": "13:30" } } ``` - `heures_jour` — `7.8` = 7h48 = 39h ÷ 5 jours. Modifier cette valeur recentre tous les calculs. - `log_level` — `DEBUG`, `INFO`, `WARNING` ou `ERROR`. Contrôle la verbosité des logs (`docker logs`). - `allowed_email_domain` — seules les adresses de ce domaine peuvent se connecter. - `mail_from` — adresse expéditrice des emails de connexion. - `smtp` — serveur relais utilisé pour l'envoi (host, port, identifiants, TLS). - `plages` — bornes de présence obligatoire matin/après-midi (voir [Principe](#principe)) et heure de reprise par défaut de l'après-midi (`pause_dejeuner_fin`) tant que l'entrée aprem n'est pas encore saisie. Modifier ces valeurs change à la fois les avertissements de saisie, les stats de conformité et le calcul de l'heure de sortie optimale. Les rappels ntfy (topic, serveur, plage horaire) se règlent par utilisateur depuis la page **Réglages** de l'app, pas dans `config.json`. --- ## Tests ```bash docker compose run --rm pointeuse pytest -v ``` --- ## Congés Trois boutons par ligne : **MA** (matin), **AM** (après-midi), **J** (journée entière).\ Ils réduisent les heures dues et recalculent les préconisations **Fin cible** pour les demi-journées restantes. --- ## Stack `FastAPI` · `HTMX` · `Jinja2` · fichiers JSON · `Docker`