Files
Omika/docs/MOBILE_FUNCTIONAL_STATUS.md
T
2026-10-23 18:46:50 +02:00

40 KiB

MOBILE FUNCTIONAL STATUS — État fonctionnel actuel de l'application mobile

Bilan fonctionnel global de l'application mobile Omika, tel qu'il est réellement implémenté et validé aujourd'hui. Ce document décrit ce que l'utilisateur peut réellement faire, ce qui est en lecture seule, ce qui sait écrire offline, ce qui manque, ce qui est bloqué backend et ce qui reste à développer.

Ce document est orienté fonctionnel : il ne remplace pas docs/LOT_MOBILE_0.md (architecture technique, décisions, principes offline-first, SQLite, Sync, identités, Design System). Il ne duplique pas son contenu.

Aucun code de production n'est modifié par ce document.


1. Vue d'ensemble — ce que l'utilisateur peut faire aujourd'hui

L'application mobile Omika est aujourd'hui une application de consultation offline du dernier snapshot métier synchronisé. L'utilisateur peut :

  • Naviguer entre les écrans (Agenda, Interventions, Dossiers, Équipe, Clients, Sites, Paramètres) via une barre latérale (desktop/tablette) ou une barre basse + menu « Plus » (smartphone).
  • Consulter l'agenda du jour et le détail d'un rendez-vous.
  • Consulter la liste des interventions, les rechercher localement, filtrer les archivées, et ouvrir la fiche d'une intervention.
  • Consulter les dossiers, clients, sites et collaborateurs (liste + détail).
  • Consulter les contacts liés à une intervention et le détail d'un contact.
  • Consulter les documents / photos d'une intervention, les télécharger à la demande, les ouvrir offline s'ils sont en cache, et en ajouter (photo ou document) offline-first.
  • Créer, modifier et archiver une intervention offline-first (formulaire partagé Create/Edit, bouton Nouvelle Intervention, action Modifier, action Archiver avec confirmation, aucun DELETE).
  • Synchroniser manuellement via « Synchroniser maintenant ».
  • Personnaliser le thème (clair / sombre / système) et la couleur principale.

L'utilisateur ne peut pas aujourd'hui : créer/modifier un rendez-vous, un dossier, un client, un site ou un collaborateur ; saisir des temps ; rédiger des notes ; créer un compte rendu ou un rapport ; envoyer un email ; utiliser le GPS ; réinitialiser l'application ; purger le cache depuis l'UI.

Note importante (vérification Sync) : le backend + Sync supportent déjà réellement la création, la modification et l'archivage d'une Intervention (handler InterventionSyncOperationHandler, contrat InterventionSyncPayload, pipeline SUCCESS/REJECTED). L'UI + mutation locale Intervention est réalisée (formulaire Create/Edit, bouton Nouvelle Intervention, action Modifier, action Archiver avec confirmation, aucun DELETE, protection double Save, navigation contextuelle, états Pending/Rejected affichés). Les autres entités (RendezVous, Dossier, Client, Site, Collaborateur) ne disposent d'aucun handler Sync ni payload : elles restent bloquées backend.


2. Matrice fonctionnelle synthétique

Légende des états :

État Signification
REAL Fonctionnalité réellement implémentée et utilisable
PARTIAL Partiellement implémentée (une partie seulement du périmètre maquette)
READ-ONLY Consultation seule, aucune écriture
BLOCKED Bloqué par un prérequis backend / snapshot / sync manquant
NOT IMPLEMENTED Non implémenté (aucun parcours utilisateur)
PLACEHOLDER Écran d'attente « Fonctionnalité à venir »
Domaine Fonctionnalité État Offline Écriture Réseau requis Backend requis Commentaire
Shell / navigation Navigation entre écrans REAL Oui Non Non Non Barre latérale + barre basse + menu « Plus »
Shell / navigation Thème clair / sombre / système REAL Oui Non Non Non Persisté localement
Shell / navigation Couleur principale REAL Oui Non Non Non Presets + personnalisée, persistée
Agenda Liste des rendez-vous du jour REAL Oui Non Non Non Lecture SQLite
Agenda Navigation jour précédent / suivant REAL Oui Non Non Non —
RendezVous Détail d'un rendez-vous REAL Oui Non Non Non Lecture seule
RendezVous Saisie des temps (accès) REAL (UI CREATE) Oui Oui Non (offline-first) Oui Accès contextuel RendezVous → liste filtrée → Nouvelle saisie (RendezVousId prérempli) — voir section 7
RendezVous Annulation / modification NOT IMPLEMENTED — — — Oui Aucun handler Sync RendezVous

| Interventions | Liste des interventions | REAL | Oui | Non | Non | Non | Lecture SQLite | | Interventions | Recherche locale | REAL | Oui | Non | Non | Non | Reference, Titre, ClientNom, SiteNom, DossierReference | | Interventions | Filtre Actif / Archivé | REAL | Oui | Non | Non | Non | Basé sur EstArchive | | Interventions | Fiche intervention | REAL | Oui | Non | Non | Non | Client/Site/Dossier/RendezVous/Documents | | Interventions | Rendez-vous liés | REAL | Oui | Non | Non | Non | Liste + tri chronologique | | Interventions | Création / modification Intervention | REAL (UI + mutation locale) | Oui | Oui | Non (offline-first) | Oui | Backend + Sync SUPPORTED ; UI Create/Edit + mutation locale + Outbox implémentées (CREATE/UPDATE/ARCHIVE), aucun DELETE | | Interventions | Archiver une intervention | REAL (UI + mutation locale) | Oui | Oui | Non (offline-first) | Oui | Action Archiver + confirmation, ArchiveAsync via IInterventionLocalService, aucun DELETE | | Interventions | État Sync (Pending / Rejected) | REAL | Oui | Non | Non | Non | Affiché sur la fiche à partir des vraies données Outbox (IsPendingSync, HasSyncError, SyncErrorMessage) |

| Documents / Photos | Liste des documents d'une intervention | REAL | Oui | Non | Non | Non | Métadonnées SQLite | | Documents / Photos | Téléchargement à la demande | REAL | Non | Non | Oui | Oui | HTTP GET /api/documents/{guid} | | Documents / Photos | Ouverture offline | REAL | Oui | Non | Non | Non | Si présent en cache | | Documents / Photos | Ajout photo / document | REAL | Oui | Oui | Non (offline-first) | Oui | Outbox + SyncEngine | | Contacts | Contacts liés à une intervention | REAL | Oui | Non | Non | Non | Relation ContactIds explicite | | Contacts | Détail d'un contact | REAL | Oui | Non | Non | Non | Téléphone / email plateforme | | Dossiers | Liste des dossiers | REAL | Oui | Non | Non | Non | Lecture SQLite | | Dossiers | Détail d'un dossier | REAL | Oui | Non | Non | Non | Interventions liées | | Dossiers | Création / modification Dossier | NOT IMPLEMENTED | — | — | — | Oui | Aucun handler Sync Dossier | | Clients | Liste des clients | REAL | Oui | Non | Non | Non | Lecture SQLite | | Clients | Détail d'un client | REAL | Oui | Non | Non | Non | Sites, contacts, dossiers, interventions | | Clients | Création / modification Client | NOT IMPLEMENTED | — | — | — | Oui | Aucun handler Sync Client | | Sites / Lieux | Liste des sites | REAL | Oui | Non | Non | Non | Lecture SQLite | | Sites / Lieux | Détail d'un site | REAL | Oui | Non | Non | Non | Client, contacts, interventions | | Sites / Lieux | GPS / itinéraire | NOT IMPLEMENTED | — | — | — | Non | — | | Équipe / Collaborateurs | Liste des collaborateurs | REAL | Oui | Non | Non | Non | Lecture SQLite | | Équipe / Collaborateurs | Détail d'un collaborateur | REAL | Oui | Non | Non | Non | Rendez-vous + interventions liés | | Paramètres | Thème / couleur / version | REAL | Oui | Non | Non | Non | — | | Paramètres | Synchroniser maintenant | REAL | Non | Non | Oui | Oui | Via SyncEngine | | Paramètres | Purge cache | NOT IMPLEMENTED (UI) | — | — | — | — | PurgeAsync existe ; problème technique mobile uniquement | | Paramètres | Reset application | NOT IMPLEMENTED (UI) | — | — | — | — | Primitives locales existent ; dépendance protection Outbox | | Paramètres | Licence / activation | REAL | Oui | Non | Non | Oui | Activation par code client + n° licence ; session + token sécurisé ; identité affichée |

| Synchronisation | Synchronisation manuelle | REAL | Non | Non | Oui | Oui | SyncEngine + Outbox | | Synchronisation | État de synchronisation | REAL | Oui | Non | Non | Non | Idle / Syncing / Synced / Offline / Error | | Notes Intervention | Lecture / écriture notes | NOT IMPLEMENTED | — | — | — | Oui | CAS E — voir section 6 | | SuiviTemps | Consultation des temps | REAL (UI LIST) | Oui | Non | Non | Non | Liste offline via ISuiviTempsLocalService (PHASE 3) — voir section 7 | | SuiviTemps | Saisie des temps | REAL (UI CREATE) | Oui | Oui | Non (offline-first) | Oui | UI CREATE READY — formulaire offline-first via ISuiviTempsLocalService.CreateAsync ; TypeTemps depuis IParametreMetierLocalService.GetTypeTempsAsync() (Key = PA_CLE) ; aucun UPDATE/ARCHIVE/DELETE — voir section 7 |

| Rapports / CompteRendu | Création / consultation | NOT IMPLEMENTED | — | — | — | Oui | Backend only — voir section 8 |


3. Écritures offline réellement opérationnelles

La seule écriture offline réellement opérationnelle aujourd'hui est l'ajout de documents / photos à une intervention.

3.1 Ajout d'une photo ou d'un document (offline-first)

Ce que fait l'utilisateur :

  1. Depuis la fiche intervention, il ouvre l'écran Documents / Photos.
  2. Il choisit Ajouter une photo ou Ajouter un document (sélecteur de fichier plateforme).
  3. Le fichier est immédiatement visible dans la liste, marqué comme en attente de synchronisation.

Ce qui se passe techniquement (chaîne complète vérifiée) :

Étape Détail
Mutation SQLite Copie du fichier dans l'espace contrôlé de l'application + création de la métadonnée locale LocalDocumentMetadata (payload DocumentSummaryDto)
Outbox Création d'une opération OutboxOperation (EntityType = Document, OperationType = Create, état Pending)
OperationId Guid.NewGuid() — distinct du GUID métier
GUID métier DocumentGuid (identité publique du document)
SyncEngine À la synchronisation, l'opération Document est envoyée via POST /api/documents (multipart)
SUCCESS L'opération passe à l'état Succeeded ; le document est marqué synchronisé
REJECTED L'opération passe à l'état Rejected ; l'erreur est affichée dans l'UI

Le DocumentGuid est distinct de l'OperationId : le GUID métier identifie le document, l'OperationId identifie la transaction de synchronisation.

Important

: la capacité générique de l'Outbox n'est pas une fonctionnalité utilisateur en soi. Seule l'écriture Documents / Photos est réellement branchée de bout en bout (UI → SQLite → Outbox → SyncEngine → backend).


4. Domaines actuellement en lecture seule

Les domaines suivants sont strictement en lecture seule : aucune écriture, aucune Outbox, aucun CREATE / UPDATE / DELETE / ARCHIVE depuis le mobile.

Domaine État réel Détail
RendezVous READ-ONLY Consultation du détail uniquement
Intervention WRITE (mutation locale) Liste, recherche, filtre, fiche, relations. Backend + Sync SUPPORTED pour CREATE/UPDATE/ARCHIVE ; mutation locale + Outbox implémentées (service InterventionLocalService)

| Dossier | READ-ONLY | Liste + détail | | Client | READ-ONLY | Liste + détail | | Site / Lieu | READ-ONLY | Liste + détail | | Collaborateur | READ-ONLY | Liste + détail | | Contact | READ-ONLY | Liste + détail (téléphone / email plateforme) |

Aucune de ces entités ne dispose d'une écriture mobile branchée à l'UI. Les données proviennent exclusivement du snapshot synchronisé.

Capacité Sync réelle : seul Intervention dispose d'un handler Sync (InterventionSyncOperationHandler) et d'un contrat public (InterventionSyncPayload). Les autres entités (RendezVous, Dossier, Client, Site, Collaborateur) n'ont aucun handler ni payload : toute opération Sync sur ces types est rejetée (NO_HANDLER → REJECTED).


5. Synchronisation, Offline, SQLite, Outbox, cache Documents

5.1 Synchronisation

  • Déclenchement : manuel via « Synchroniser maintenant » (Paramètres ou Shell). Aucune synchronisation automatique périodique.
  • Moteur : SyncEngine (unique système de mise à jour).
  • États UI : Idle, Syncing, Synced, Offline, Error.
  • Hors ligne : aucun appel réseau, état non intrusif (« Hors ligne »).
  • Erreurs : nombre d'opérations rejetées / anomalies affiché.

5.2 Offline / SQLite

  • Toutes les lectures (liste, fiche, contacts, documents) se font depuis SQLite (dernier snapshot).
  • Aucun appel HTTP obligatoire à l'ouverture d'un écran.
  • Le snapshot est reconstruit atomiquement depuis le backend.

5.3 Outbox

  • L'Outbox est opérationnelle pour Documents / Photos uniquement.
  • Les opérations sont envoyées à la synchronisation, avec états Pending / Sending / Accepted / WaitingResult / Succeeded / Rejected.
  • Le mécanisme d'identité RequestedEntityGuid / CanonicalEntityGuid est opérationnel : après un CREATE réussi, le backend retourne le GUID canonique (GUID physique Omika ou GUID synthétique réversible Batik), réconcilié côté mobile pour les opérations suivantes (UPDATE/ARCHIVE).

5.4 Cache Documents

  • Les documents téléchargés sont stockés dans un cache fichier local (DocumentCacheService).
  • L'ouverture offline est possible si le fichier est présent en cache.
  • Purge du cache : la capacité technique PurgeAsync existe dans DocumentCacheService, mais n'est pas branchée à une interface utilisateur. Aucun bouton « Purger le cache » n'est accessible à l'utilisateur.

6. Notes Intervention — état démontré (CAS E)

État déjà démontré, aucune décision n'est réouverte :

  • Aucune Note Intervention exploitable dans le snapshot / local.
  • Aucune table SQLite Note.
  • Aucune UI Notes.
  • CompteRendu existe côté backend mais n'est pas peuplé dans le snapshot.
  • MessageInterne / IN_NoteInterne restent backend (non exposés au mobile).
  • DocumentNote est un concept différent (document, pas note d'intervention).

État fonctionnel : NOT IMPLEMENTED (bloqué backend — données absentes du snapshot).

Classification : C — BACKEND + MOBILE (snapshot / SQLite / Sync manquant)

  • D uniquement pour la décision de représentation métier exacte (Note vs DocumentNote). DocumentNote reste distinct.

7. Suivi des temps — état démontré (CAS C)

État déjà démontré, aucune décision n'est réouverte :

  • L'entité métier SuiviTemps est réelle côté backend.

  • Les relations Intervention / RendezVous / Collaborateur existent.

  • Présent dans le snapshot mobile (PHASE 1B) : le MobileSnapshotResponse expose désormais SuivisTemps (liste de SuiviTempsDto, lecture seule, réutilisant le DTO métier public — aucune colonne HFSQL exposée). Le GUID exposé est le GUID physique existant (Batik et Omika), aucun GUID synthétique n'est créé.

  • Sync CREATE (PHASE 1C) : le pipeline Sync serveur moderne supporte la création d'une saisie de temps via SuiviTempsSyncOperationHandler → ISuiviTempsService → repository adaptatif. EntityType SuiviTemps, payload SuiviTempsSyncPayload (CollaborateurId, InterventionId, RendezVousId, Date, DureeMinutes, TypeTempsKey, Description). Le champ Valide n'est pas positionnable depuis le mobile (état de validation métier géré côté backend). UPDATE / ARCHIVE / DELETE → PERMANENT_FAILURE.

  • SQLite local (PHASE 2) : la table SuiviTemps est présente dans le schéma SQLite local, importée atomiquement par le SnapshotApplier (avec les références typées Collaborateur / Intervention / RendezVous pour la réconciliation d'identité A → B). Le service local SuiviTempsLocalService permet la lecture (liste, par GUID, par intervention) et la création offline-first (écriture locale + Outbox CREATE, Valide toujours false côté mobile).

  • UI LIST (PHASE 3) : la vue SuiviTempsView + SuiviTempsViewModel permettent la consultation offline des saisies de temps via ISuiviTempsLocalService.GetAllAsync (et GetByInterventionAsync / GetByRendezVousAsync pour les filtres par intervention / rendez-vous). La liste affiche les données métier utiles (date, durée, type de temps, description, collaborateur, intervention, rendez-vous, validation, état Sync Pending/Rejected/ErrorMessage). Aucun UPDATE / ARCHIVE / DELETE. Accès global via la navigation + accès contextuel depuis une Intervention (liste filtrée) et depuis un RendezVous (liste filtrée).

  • Référentiel TypeTemps local (micro-lot) : READY — le référentiel ParametreMetier est désormais disponible offline au mobile. Le pipeline est : HFSQL ParametreMetier → repository adaptatif (AdaptiveParametreMetierRepository) → MobileBootstrapService (chargé au bootstrap) → SQLite local → service local IParametreMetierLocalService.GetTypeTempsAsync(). Ce service retourne une liste ordonnée d'options ReferenceValueDto (Key = clé métier PA_CLE, Label = libellé métier) sans réseau, sans API, sans HFSQL, uniquement à partir des données snapshot déjà présentes localement. Le filtrage suit la convention générique du projet (Actif / Invisible) et l'ordre métier (PA_Ordre). Aucune valeur métier n'est codée en dur ; les options proviennent des vraies données ParametreMetier. L'ancienne règle Batik (exclusion PA_Valeur 0/1/99, cas particulier 2) n'est pas reprise faute de règle moderne explicite.

  • UI CREATE (PHASE 3) : READY — le formulaire SuiviTempsCreateView + SuiviTempsCreateViewModel permettent la saisie offline-first d'un temps via ISuiviTempsLocalService.CreateAsync (écriture locale + Outbox CREATE, Valide toujours false côté mobile). Le formulaire contient uniquement CollaborateurId, InterventionId, RendezVousId, Date, DureeMinutes, TypeTempsKey, Description. Le champ Valide est absent. Le TypeTemps est chargé depuis IParametreMetierLocalService.GetTypeTempsAsync() (affichage ReferenceValueDto.Label, valeur envoyée ReferenceValueDto.Key == PA_CLE, aucune valeur hardcodée). DureeMinutes est saisie manuellement (aucun calcul automatique depuis RendezVous/Intervention). Aucune écriture directe SQLite / Outbox / API / SyncEngine depuis le ViewModel (le service local reste responsable). Protection double clic : SaveCommand.CanExecute == false pendant l'exécution (binding Avalonia) + garde interne IsBusy. Accès global (liste SuiviTemps → Nouvelle saisie) et contextuel depuis une Intervention (liste filtrée → Nouvelle saisie → InterventionId prérempli) et depuis un RendezVous (liste filtrée → Nouvelle saisie → RendezVousId prérempli, sans déduction automatique d'Intervention / durée / date).

État fonctionnel : REAL — UI LIST READY, TYPE TEMPS LOCAL REFERENCE READY, UI CREATE READY, RENDEZVOUS ENTRY POINT READY. Backend métier, snapshot, Sync CREATE, SQLite local, référentiel TypeTemps local, consultation et saisie offline-first sont opérationnels. UPDATE / ARCHIVE / DELETE : NOT SUPPORTED.

Classification : C — BACKEND + MOBILE (inchangée, CAS C non rouvert). Les PHASE 1B (snapshot), 1C (Sync CREATE), 2 (SQLite local), 3 (UI LIST), le micro-lot référentiel TypeTemps local et l'UI CREATE sont réalisés.

Statut détaillé SuiviTemps (après correctif snapshot — persistance des colonnes de référence) :

Capacité Statut
BACKEND METIER READY
SNAPSHOT READY
SYNC CREATE READY
LOCAL SQLITE READY
SNAPSHOT LOCAL READY
LOCAL CREATE READY
OUTBOX CREATE READY
RECONCILIATION READY
UI LIST READY
TYPE TEMPS LOCAL REFERENCE READY
UI CREATE READY
UPDATE NOT SUPPORTED

| ARCHIVE | NOT SUPPORTED | | DELETE | NOT SUPPORTED | | RENDEZVOUS ENTRY POINT | READY |

Le correctif snapshot garantit que le refresh persiste les colonnes structurées (CollaborateurId, InterventionId, RendezVousId) de manière générique (mécanisme partagé avec LocalRepository), sans fix spécifique SuiviTemps, et préserve l'atomicité de la transaction snapshot ainsi que les données techniques (Outbox, Sync state, profil, droits, licence, configuration, cache documents).


8. Rapports / CompteRendu — état réel

Il ne faut pas confondre les concepts suivants :

Concept Nature État mobile
CompteRendu Entité backend (CompteRenduRow, CompteRenduDto) BACKEND ONLY — non peuplé dans le snapshot, aucune UI
Rapport Modèles de rapports (ModeleRapport, ModeleRapportMob) BACKEND ONLY — aucune UI mobile
Note Note d'intervention NOT IMPLEMENTED (CAS E)
Document Fichier / métadonnée REAL (liste, téléchargement, ajout offline)

État fonctionnel :

  • CompteRendu : BACKEND ONLY (aucune UI, non peuplé dans le snapshot).
  • Rapports : BACKEND ONLY (aucune UI mobile).
  • Aucune création / consultation de compte rendu ou rapport depuis le mobile.

9. Paramètres — ce qui est réellement accessible

La page Paramètres expose réellement à l'utilisateur :

Réglage État Détail
Thème (Light / Dark / System) REAL ComboBox + bouton « Appliquer le thème »
Couleur principale REAL Presets + couleur personnalisée
Synchroniser maintenant REAL Bouton + état + erreur
État de synchronisation REAL Texte d'état
Version REAL Affichage « À propos »

Non accessibles à l'utilisateur (capacité technique ≠ fonction UI) :

Réglage État Détail
Purge cache NOT IMPLEMENTED (UI) PurgeAsync existe mais non branché à l'UI
Reset application NOT IMPLEMENTED (UI) Aucun parcours utilisateur

10. Reset application

État : NOT IMPLEMENTED (UI).

Il n'existe aucun parcours utilisateur de réinitialisation de l'application. Même si certaines primitives techniques de suppression existent (ex. purge du cache), il n'y a pas de bouton ni d'écran « Reset » accessible à l'utilisateur.

Classification : A — MOBILE UNIQUEMENT. Le comportement fonctionnel est déjà défini (réinitialisation des données locales / cache / outbox / licence) et aucune évolution backend n'est nécessaire. La seule dépendance est technique : la protection des fichiers référencés par des opérations Outbox en attente (Pending / Rejected) avant suppression. Aucune décision métier non résolue ne bloque ce lot.


11. Purge cache

État : NOT IMPLEMENTED (UI).

Le bouton de purge du cache Documents n'a pas été branché : la protection des fichiers nécessaires aux opérations Outbox en attente n'était pas suffisamment fiable. La capacité technique DocumentCacheService.PurgeAsync existe mais n'est exposée à aucune interface utilisateur.

Classification : A — MOBILE UNIQUEMENT. Le problème est uniquement technique côté mobile (fiabiliser la protection des fichiers référencés par l'Outbox Pending / Rejected avant suppression). Aucune décision métier réelle ne manque. Dépendance : protection fichiers Outbox.


12. Licence / Bootstrap — état fonctionnel utilisateur

  • Le backend licence / bootstrap est réel : POST /api/license/activate, POST /api/license/validate, GET /api/mobile/bootstrap, token signé, identité/profil/droits.
  • Émission du token de session : activate et validate retournent une réponse de session MobileLicenseSessionResponse contenant le Bearer token (AccessToken) et son expiration exacte (AccessTokenExpiresAtUtc, 24 h par défaut via MobileAuth:TokenLifetimeHours). Le token n'est émis que si la licence est valide ; en cas d'échec, la réponse contient le code d'erreur métier et aucun token. Le token est stateless (HMAC-SHA256), jamais loggé, jamais stocké en HFSQL.
  • Côté application : l'UI d'activation est réellement branchée. Au premier démarrage sans session valide, l'utilisateur voit l'écran Activation (code client + numéro de licence). Après activation réussie, le token est stocké en secure storage (jamais en SQLite en clair), le bootstrap (profil, droits, licence, configuration) est persisté en SQLite, et l'application bascule vers le Shell.
  • Redémarrage : si une session valide existe (licence valide ou période offline autorisée), l'application démarre directement sur le Shell sans repasser par l'activation.
  • Offline : session déjà validée + période offline autorisée → accès aux données SQLite sans connexion obligatoire. Premier démarrage sans session valide + offline → activation impossible (message réseau).
  • Identité : le nom de l'utilisateur (et ses initiales) est affiché dans le Shell à partir du bootstrap local. Une licence expirée/révoquée ne supprime jamais automatiquement les données locales (SQLite métier, cache, Documents, Outbox).

État fonctionnel : REAL — activation, validation, bootstrap, token sécurisé et identité utilisateur sont opérationnels côté mobile.

Classification : A — MOBILE UNIQUEMENT — réalisé. Le backend activation, validation et bootstrap existaient déjà ; l'UI mobile d'activation / identité a été ajoutée. Risque sécurité : moyen/élevé (parcours d'activation, token, identité utilisateur) — traité par le secure storage et l'absence de token en clair.


13. Comparaison avec la maquette maquetteOmika.html

La maquette reste une référence UX uniquement. Comparaison des grandes fonctions :

Fonction maquette Application actuelle État Écart restant
Agenda (Mes rendez-vous) Agenda du jour réel PARTIAL Pas de vue semaine/équipe, pas de saisie temps
RendezVous (détail) Détail réel PARTIAL Pas de saisie temps, pas d'annulation
Interventions (recherche) Liste + recherche locale PARTIAL Filtres avancés (relation RDV, date, collaborateur) absents
Interventions (fiche) Fiche réelle PARTIAL Pas de GPS, création, planification RDV, compte rendu, rapports, emails
Dossiers Liste + détail réels PARTIAL Pas de création / ajout d'intervention
Clients Liste + détail réels PARTIAL Pas de création / modification
Sites / Lieux Liste + détail réels PARTIAL Pas de GPS / itinéraire
Équipe Liste + détail réels PARTIAL Pas d'agenda d'équipe
Documents Liste + téléchargement + ajout offline REAL —
Photos Ajout photo offline REAL —
Contacts Liste + détail réels REAL —
Notes — NOT IMPLEMENTED CAS E
Temps — NOT IMPLEMENTED CAS C
Rapports — NOT IMPLEMENTED Backend only
CompteRendu — NOT IMPLEMENTED Backend only
Paramètres Thème / couleur / sync / version / licence PARTIAL Pas de purge cache, reset

| Synchronisation | Manuelle via SyncEngine | REAL | Pas d'automatique | | Reset | — | NOT IMPLEMENTED | — |


14. Backlog — classification des restes

A — MOBILE UNIQUEMENT

Données / backend déjà disponibles ; manque UI / service mobile.

Élément Détail
Filtres de recherche avancés Interventions Données disponibles (RDV, collaborateur) ; manque l'UI de filtrage
GPS / itinéraire Données adresse disponibles ; manque l'UI + lanceur carte
Email / appel depuis la fiche intervention Launcher plateforme existe (contact) ; manque l'UI fiche
Reset application Primitives locales existent ; comportement fonctionnel défini ; aucune évolution backend nécessaire. Dépendance technique : protection fichiers Outbox
Purge cache DocumentCacheService.PurgeAsync existe ; problème uniquement technique mobile (protection fichiers Outbox Pending/Rejected). Dépendance : protection fichiers Outbox

B — MOBILE WRITE

Backend / sync réellement capables de l'écriture ; UI + mutation locale réalisées.

Élément Détail
Modification Intervention mobile ✅ RÉALISÉ Backend + Sync SUPPORTED : handler InterventionSyncOperationHandler, contrat InterventionSyncPayload, CREATE/UPDATE/ARCHIVE réels, pipeline SUCCESS/REJECTED. UI + mutation locale réalisées : formulaire Create/Edit, bouton Nouvelle Intervention, action Modifier, action Archiver avec confirmation, aucun DELETE, protection double Save, navigation contextuelle, états Pending/Rejected affichés.

Vérification : CREATE, UPDATE et ARCHIVE Intervention sont réellement supportés de bout en bout par le backend + Sync (contrat public exploitable, EntityType reconnu, handler réel, traitement métier réel via IInterventionService, résultat SUCCESS/REJECTED possible). DELETE n'est pas supporté (archivage logique uniquement → PERMANENT_FAILURE). Le lot Intervention Write UI est COMPLET : CREATE UI COMPLETE, UPDATE UI COMPLETE, ARCHIVE UI COMPLETE, OFFLINE-FIRST, OUTBOX, IDENTITY RECONCILIATION. DELETE : NOT SUPPORTED.

C — BACKEND + MOBILE

Contrat / snapshot / sync manquant avant l'UI.

Élément Détail
Notes Intervention Absentes du snapshot / SQLite / Sync (CAS E)
Suivi des temps Snapshot (PHASE 1B) + Sync CREATE (PHASE 1C) + SQLite local (PHASE 2) faits ; UI LIST (PHASE 3) faite ; TYPE TEMPS LOCAL REFERENCE READY ; UI CREATE (PHASE 3) faite (offline-first, TypeTemps Key=PA_CLE, aucun UPDATE/ARCHIVE/DELETE) ; RENDEZVOUS ENTRY POINT RÉALISÉ (accès contextuel RendezVous → liste filtrée → Nouvelle saisie, RendezVousId prérempli)

| CompteRendu | Non peuplé dans le snapshot | | Rapports | Modèles backend, aucune exposition mobile | | RendezVous (création / modification / annulation) | Aucun handler Sync RendezVous, aucun payload ; toute opération Sync est rejetée (NO_HANDLER) | | Dossier (création / modification) | Aucun handler Sync Dossier, aucun payload | | Client (création / modification) | Aucun handler Sync Client, aucun payload | | Site (création / modification) | Aucun handler Sync Site, aucun payload | | Collaborateur (création / modification) | Aucun handler Sync Collaborateur, aucun payload |

D — DÉCISION MÉTIER

Sémantique à décider avant développement.

Élément Détail
Sémantique Note vs DocumentNote Distinction à confirmer avant développement Notes (décision de représentation métier exacte)

Note

: Purge cache et Reset ne sont plus en D : ce sont des problèmes techniques mobiles (protection fichiers Outbox), sans décision métier non résolue. Ils sont classés en A — MOBILE UNIQUEMENT avec dépendance technique sur la protection Outbox.


15. Prochains lots recommandés

À partir de la cartographie réelle, 5 prochains lots recommandés (aucun code n'est écrit ici). Priorité forte donnée à l'activation/licence/identité, aux écritures métier terrain réellement supportées par le Sync, au SuiviTemps et aux Notes/CompteRendu, avant les améliorations purement cosmétiques ou les filtres avancés.

Lot 1 — Licence / activation + identité utilisateur ✅ RÉALISÉ

  • Objectif : brancher l'UI d'activation / validation licence et afficher l'identité utilisateur (nom, profil, droits).
  • Catégorie : A (MOBILE UNIQUEMENT) — backend activation/validation/bootstrap déjà existants.
  • Backend nécessaire : Non (déjà existant).
  • Dépendances : Bootstrap / token / profil.
  • Risque : Moyen/élevé (sécurité, parcours d'activation, identité).
  • Raison de la priorité : Prérequis de mise en production réelle — sans activation/licence/identité, l'application n'est pas exploitable en production.
  • Statut : RÉALISÉ — écran d'activation, session + token sécurisé (secure storage), bootstrap local, identité Shell, offline grace. Voir section 12.

Lot 2 — Modification Intervention mobile (B — MOBILE WRITE) ✅ RÉALISÉ

  • Objectif : brancher l'UI + mutation locale (Outbox) pour créer, modifier et archiver une intervention, en s'appuyant sur le handler Sync déjà opérationnel.
  • Catégorie : B (MOBILE WRITE) — backend + Sync déjà supportés.
  • Backend nécessaire : Non (handler InterventionSyncOperationHandler et contrat InterventionSyncPayload existants).
  • Dépendances : UI fiche + mutation locale + Outbox + réconciliation RequestedEntityGuid → CanonicalEntityGuid.
  • Risque : Moyen (mutation locale, identité, ordre CREATE → UPDATE).
  • Raison de la priorité : Écriture métier terrain réellement déjà supportée par le Sync — valeur terrain immédiate, sans évolution backend.
  • Statut : RÉALISÉ — formulaire Create/Edit partagé, bouton Nouvelle Intervention, action Modifier, action Archiver avec confirmation, aucun DELETE, protection double Save, navigation contextuelle, états Pending/Rejected affichés. Voir section 14 B.

Lot 3 — Suivi des temps (CAS C)

  • Objectif : exposer le SuiviTemps dans le snapshot / SQLite / Sync, puis UI de saisie.
  • Catégorie : C (BACKEND + MOBILE).
  • Backend nécessaire : Oui (sync + handler ; snapshot fait).
  • Dépendances : SQLite, Sync, UI.
  • Risque : Moyen (contrat + sync).
  • Raison de la priorité : Fonction terrain très attendue (saisie des temps), nécessite le backend.
  • Statut : PHASE 1B (snapshot) RÉALISÉE — SuivisTemps exposé dans le MobileSnapshotResponse (lecture seule, GUID physique, aucun GUID synthétique). PHASE 1C (Sync CREATE) RÉALISÉE — handler SuiviTempsSyncOperationHandler + payload SuiviTempsSyncPayload, CREATE supporté, UPDATE/ARCHIVE/DELETE non supportés. PHASE 2 (SQLite local) RÉALISÉE — table SuiviTemps dans le schéma SQLite, import snapshot (SnapshotApplier), service local SuiviTempsLocalService (lecture + création offline-first via Outbox CREATE, Valide toujours false côté mobile), réconciliation d'identité A → B. PHASE 3 (UI LIST) RÉALISÉE — SuiviTempsView + SuiviTempsViewModel (consultation offline, états Pending/Rejected/ErrorMessage, accès global + depuis Intervention). RÉFÉRENTIEL TYPE TEMPS LOCAL RÉALISÉ — IParametreMetierLocalService
    • GetTypeTempsAsync() (options ReferenceValueDto Key/Label depuis les vraies données ParametreMetier, offline). UI CREATE RÉALISÉE — SuiviTempsCreateView + SuiviTempsCreateViewModel (saisie offline-first, TypeTemps Key=PA_CLE, aucun UPDATE/ARCHIVE/DELETE, protection double clic CanExecute). RENDEZVOUS ENTRY POINT RÉALISÉ — accès contextuel RendezVous → liste filtrée → Nouvelle saisie (RendezVousId prérempli, sans déduction automatique d'Intervention / durée / date).

Lot 4 — Notes / CompteRendu (CAS E)

  • Objectif : définir la représentation Note, l'exposer dans le snapshot / SQLite / Sync, puis UI.
  • Catégorie : C (BACKEND + MOBILE) + D (décision métier Note vs DocumentNote).
  • Backend nécessaire : Oui (snapshot + sync + handler).
  • Dépendances : Décision métier, snapshot, SQLite, Sync, UI.
  • Risque : Moyen (sémantique + contrat).
  • Raison de la priorité : Fonction terrain attendue (notes / compte rendu), nécessite une décision métier préalable.

Lot 5 — Reset + Purge cache (A — MOBILE UNIQUEMENT)

  • Objectif : brancher l'UI Reset application et Purge cache, avec protection des fichiers référencés par l'Outbox en attente.
  • Catégorie : A (MOBILE UNIQUEMENT) — primitives locales existantes, aucune évolution backend.
  • Backend nécessaire : Non.
  • Dépendances : Protection fichiers Outbox (Pending / Rejected) avant purge / reset.
  • Risque : Faible à moyen (intégrité des opérations en attente).
  • Raison de la priorité : Hygiène de production (réinitialisation / libération d'espace), sans backend.

16. Baseline de validation

Vérification Résultat Commande
Tests Mobile 587/587 dotnet test tests/Omika.Tests/Omika.Tests.csproj -c Debug --filter "FullyQualifiedName~Omika.Tests.Mobile"
Tests ViewModel SuiviTemps (List) 11/11 dotnet test tests/Omika.Tests/Omika.Tests.csproj -c Debug --filter "FullyQualifiedName~SuiviTempsViewModelTests"
Tests ViewModel SuiviTemps (Create) 18/18 dotnet test tests/Omika.Tests/Omika.Tests.csproj -c Debug --filter "FullyQualifiedName~SuiviTempsCreateViewModelTests"
Tests ViewModel RendezVous (Detail) 1/1 dotnet test tests/Omika.Tests/Omika.Tests.csproj -c Debug --filter "FullyQualifiedName~RendezVousDetailViewModelTests"
Tests ViewModel Intervention (Edit/List/Detail) 30/30 dotnet test tests/Omika.Tests/Omika.Tests.csproj -c Debug --filter "FullyQualifiedName~InterventionEditViewModelTests|FullyQualifiedName~InterventionsViewModelTests|FullyQualifiedName~InterventionDetailViewModelTests"
Tests Référentiel TypeTemps local 6/6 dotnet test tests/Omika.Tests/Omika.Tests.csproj -c Debug --filter "FullyQualifiedName~ParametreMetierLocalServiceTests"
Suite unitaire (hors intégration HFSQL) 1853/1853 dotnet test tests/Omika.Tests/Omika.Tests.csproj -c Debug --filter "FullyQualifiedName!~Omika.Tests.Connection.HfSqlOleDb"

| Build Omika.slnx | VERT (projets .NET) | dotnet build Omika.slnx -c Debug | | Build Omika.App.Local | VERT | dotnet build src/Omika.App.Local/Omika.App.Local.csproj -c Debug | | Build Omika.App | VERT | dotnet build src/Omika.App/Omika.App.csproj -c Debug | | Build Android | VERT | dotnet build src/Omika.App.Android/Omika.App.Android.csproj -c Debug |

Note — Lot serveur Licence (connexion physique base HFSQL) : le lot est en état de STOP (voir docs/LOT_SERVEUR_LICENCE.md). Les probes de lecture OLEDB ont révélé que la base Licence réelle (BASE_LICENCES) ne contient pas les tables ClientBase, Licence, LicenceHisto attendues par le repository (seulement 2 tables de backup système). Aucune écriture n'a été effectuée. La suite complète de tests affiche 1779 réussis / 10 échecs : les 10 échecs sont des tests d'intégration HFSQL environnementaux (HfSqlOleDb*IntegrationTests) qui échouent faute de base d'intégration configurée (connexion <:0>), hors périmètre de la baseline unitaire. Les 34 tests de configuration Licence

(HfSqlTestConfigurationLoaderTests, E2EOptionsTests, LicenseConnectionOptionsValidatorTests, LicenseOleDbConnectionTests) passent 34/34.


Document de bilan fonctionnel global — ne modifie aucun code de production.