# App technicien & capture passive du temps (durées apprises) > But : mesurer **sans effort tech** le temps réel passé par job → apprendre les durées par **type × technicien** → alimenter le recommandeur « prochaine dispo » et le solveur. Principe directeur : **aucun tap dédié** — la durée se *déduit* d'événements que le tech produit déjà + géorepérage GPS automatique. ## 1. Modèle « fil de checkpoints » Chaque job accumule des **checkpoints** horodatés (et géolocalisés). La durée réelle = **1er checkpoint sur place → dernier** (ou entrée→sortie de géorepérage). | Type de checkpoint | Source | Effort tech | |---|---|---| | `geo_enter` / `geo_exit` | Géorepérage GPS (zone de l'adresse) | **nul** (auto) | | `scan` (série / MAC / code-barre) | Caméra app (modem, ONU, mesh, STB) | déjà fait (activation) | | `photo` / `signature` | App | déjà fait | | `reply` | Réponse au ticket | déjà fait | | `manual_start` / `manual_finish` | Override répartiteur (Ops) ou tech | filet de sécurité | **Dérivation** : `actual_start` = 1er checkpoint « sur place » (geo_enter, ou 1er scan/photo/reply à < R m de l'adresse) ; `actual_end` = dernier ; `actual_minutes = end − start`. Les checkpoints hors-zone (> R m) sont ignorés pour la durée mais conservés pour l'audit. ## 2. Backend (cette itération — indépendant de l'app) - **Endpoint public token-gated** `POST /field/checkpoint` `{ token, type, ts, lat, lon, acc, ref }` → vérifie le token (HMAC du job), enregistre le checkpoint, recalcule `actual_start/end` du Dispatch Job, ajoute une ligne d'audit dans `completion_notes`. Réponse : `{ ok, on_site, distance_m, minutes }`. - **Lecture** `GET /field/job?t=` → infos job (sujet, client, adresse, coords, état) pour l'app. - **Token** = `base64url(jobName).hmac12` signé (`crypto`, secret stable du hub) → stateless, valable pour tout job, aucun champ DB ni login. - `/field` + `/field/*` câblés **publics** dans `server.js` (calqués sur `/book`, hors forwardAuth Authentik). ## 3. App Capacitor (projet natif dédié — `apps/field-tech/`) Véhicule unique pour les techs (remplace le mobile legacy) : - **Géorepérage arrière-plan économe** : `@transistorsoft/capacitor-background-geolocation` (référence batterie + geofencing natif iOS/Android) — ou `@capacitor-community/background-geolocation` pour démarrer. On enregistre un geofence par job du jour ; `enter`/`exit` → POST `/field/checkpoint`. - **Scan caméra** : `@capacitor-mlkit/barcode-scanning` → série/MAC → checkpoint `scan` **et** push vers GenieACS (par MAC) — réunit l'item roadmap « scan série/MAC des devices ». - **Offline-first** : file d'attente locale (Preferences/SQLite) → rejoue les checkpoints à la reconnexion. - **Auth** : login Authentik (groupe `tech`) → l'app reçoit ses jobs du jour + un token par job ; ou device-token. (À finaliser.) - **Push** : web-push/FCM (déjà côté legacy) pour les nouvelles assignations. - Builds : iOS (TestFlight) + Android (APK interne) ; permissions localisation « toujours » + caméra. ## 4. Amorçage SANS app (mineur legacy — cette itération) Estimer une 1re durée par ticket depuis les événements legacy **déjà horodatés** : `ticket_msg.date_orig` du staff (réponses), création `device` (scan série), activation Ministra. Fenêtre sur-site ≈ (dernière activité − première) le même jour, filtrée < 8 h (exclut le multi-jour). **Bruité à l'unité, mais l'agrégat (médiane par type) donne une baseline d'apprentissage dès aujourd'hui.** Rapport `GET /dispatch/legacy-sync/mine-durations` (lecture seule). ## 5. Boucle d'apprentissage (consomme les durées) 1. Capture (checkpoints app + override Ops + baseline minée) → `actual_minutes` par job. 2. Agrégation : **médiane / p75 par sous-type × tech** (sous-types fins par mots-clés du sujet : « modem » vs « fil/fibre/drop » vs « ONT » vs « install »). 3. Remplace la table statique `DUR` (util/legacy-parse) + affine `skill_eff` (facteur vitesse par tech×compétence). 4. Le recommandeur « prochaine dispo » (`bookingSlots/fitBooking`) utilise la durée apprise ajustée au tech. ## 6. Phasage - **P1 (maintenant)** : backend checkpoints (§2) + mineur legacy (§4). - **P2** : recommandeur « prochaine dispo » (UI Ops) + sous-types fins + durées seed. - **P3** : app Capacitor (§3) — scaffold → geofence → scan → offline → stores. - **P4** : agrégation apprise (§5) qui remplace les seeds, une fois les données accumulées. ## 7. Sécurité / contraintes - Endpoint checkpoint **public mais token-gaté** (HMAC par job) ; pas de PII dans le token. - N'écrit QUE sur le Dispatch Job (ERPNext) ; ne touche pas le legacy en écriture. - GPS = **preuve + contrôle de distance**, pas du tracking continu serveur (le geofencing reste sur l'appareil). - Le tap répartiteur ▶/⏹ (Ops) reste comme override/fallback.