Hub (lib/roster.js, vision.js, legacy-dispatch-sync.js, server.js) + Ops + pont legacy. - Capacité par jour AM/PM (Soir = réserve garde/urgence, jamais offerte) calculée client-side sur les techs visibles -> suit le filtre de compétence. - Modèle de durée ADDITIF (caractéristiques, tableur inline) + auto-détection DÉTERMINISTE par mots-clés (sans IA permanente) ; est_min branché sur capacité + pool. - Capture terrain passive : endpoints publics /field (job/tech/checkpoint/ts/photo/ device/vision), tokens HMAC signés sans PII ; dérive actual_start/end. UI hébergée public/field-app.html (liste/carte Mapbox/Street View/photo/scan MLKit->Gemini). - Chrono job (start/finish), repositionnement carte (set-location), vue satellite, Street View clic-droit, année devant les dates dues groupées. - Sync techniciens : rapport de réconciliation 3 systèmes (staff legacy / Dispatch Technician / groupe Authentik), application MANUELLE, zéro écriture Authentik (+11 fiches). - vision.js : extractEquipment() réutilisable (marque/modèle/série/MAC/codes-barres). - Pont legacy (ops_reassign.php) : désassignation reflétée, fermeture ticket, retour au pool ; notification courriel à l'assignation. Déployé sur le hub ; ce commit aligne le repo sur l'état en production. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
53 lines
4.9 KiB
Markdown
53 lines
4.9 KiB
Markdown
# 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=<token>` → 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.
|