Application Mobile
L'app mobile native iOS + Android. Parité fonctionnelle complète avec le portail web (mêmes endpoints, même flow OTP) + capacités natives : biométrie, caméra KYC, notifications push, fonctionnement offline.
📸 Captures émulateur Android
Captures réelles prises sur émulateur Android Pixel 10 Pro (API 36), APK debug installé, connecté à un backend NestJS local avec données démo (Mohamed Ben Salah, +216 55 101 001, prêt actif AA-2026-001 en retard).
Les écrans présentés sont ceux qui s'affichent réellement aujourd'hui. Les sections marquées À FAIRE dans le tableau d'état plus bas ne figurent pas ici (biométrie, caméra KYC, push, bascule RTL — non implémentés).
1. Authentification OTP par SMS
Flow login standard : sélection pays Tunisie (préfixe +216 verrouillé), saisie numéro, envoi du code à 6 chiffres, vérification, navigation automatique vers le dashboard. Aucun mot de passe.
2. Tableau de bord & prêt actif
Vue d'ensemble pour un emprunteur avec un prêt actif DISBURSED en statut LATE (échéancier de 6 mensualités : 4 payées, 1 en retard, 1 à venir).
3. Simulateur de prêt
3 produits seedés (Micro Credit Express 18%, Prêt Équipement 12%, Prêt Solidaire Groupe 15%). Saisie montant + durée, calcul de la mensualité, des intérêts, et propositions de scénarios alternatifs (durées différentes).
4. Nouvelle demande & suivi
Wizard 5 étapes (produit → montant/durée → motif → documents → signature) + écran de suivi listant les demandes en cours avec leur statut.
5. Profil emprunteur & sécurité
Profil complet (KYC VERIFIED, 100% complétude) avec accès aux sessions actives, journal d'activité, documents et notifications. Token JWT stocké de manière chiffrée sur l'appareil (session persiste après fermeture de l'app).
6. États vides & écrans annexes
Correctifs appliqués depuis la première capture (recapturé sur émulateur en français) :
- ✅ Les dates sont désormais formatées (
1 avr. 2026,il y a 60 jours) via une infra i18n FR/EN/AR — fini l'ISO brut. - ✅ L'écran Mes documents charge sans crash (le contrat API renvoyait un tableau au lieu d'un objet enveloppé — corrigé côté serveur).
- ✅ Le logout (icône ⏻) est couvert par un test unitaire ViewModel ; la vérification end-to-end sur device reste à faire.
- ⏳ Aucun écran ne demande encore de biométrie / Face ID / empreinte — feature native non implémentée (voir tableau ci-dessous).
✨ Fonctionnalités
Parité avec le portail web (mêmes endpoints, même flow OTP) + spécifiques mobile :
SMS 6 chiffres, identique au portail. Stockage du token chiffré dans le coffre-fort sécurisé du système.
Reconnexion silencieuse Face ID / Touch ID / empreinte après opt-in depuis le profil.
Capture CIN recto/verso + selfie avec overlay. Liveness 3 photos (face, gauche, droite).
Notifications push FCM (Android) et APNs (iOS). Deep links vers l'écran concerné.
Wizard identique au portail web — signature OTP de consentement.
Téléchargement PDF, partage natif via share sheet iOS / Intent Android.
Lecture des données récentes sans connexion, mutations bloquées avec message clair.
FR / AR (avec RTL natif) / EN — basculable depuis les paramètres de l'app.
🔐 Authentification + biométrie
Premier login : OTP SMS (comme le portail web). Après le premier login, opt-in possible pour la biométrie depuis la page Profil > Sécurité.
Une fois la biométrie activée, les sessions suivantes sont silencieuses :
- L'utilisateur ouvre l'app
- Face ID / Touch ID / empreinte demandé
- En cas de succès → token déchiffré et utilisateur connecté immédiatement
- En cas d'échec → fallback OTP SMS
⚠️ Pour des raisons de sécurité, le PIN du téléphone n'est pas accepté comme alternative à la biométrie (la biométrie est la seule preuve).
📷 Caméra KYC
Capture native (qualité supérieure à un upload via la galerie) :
- CIN recto/verso — overlay rectangulaire pour guider le cadrage
- Selfie KYC — overlay circulaire pour le visage
- Liveness 3 photos — séquence face → gauche → droite (anti-fraude minimal)
Les images sont uploadées directement au backend après capture, jamais stockées de manière permanente sur le téléphone.
🔔 Notifications push natives
L'app reçoit des notifications push pour les événements importants :
- Prêt approuvé / rejeté / décaissé
- Échéance de remboursement dans 3 jours
- Paiement confirmé
- Demande de complément KYC
- Statut KYC changé
Un tap sur la notification ouvre directement l'écran concerné (deep link) au lieu de la home.
📡 Fonctionnement offline
L'app fonctionne même sans connexion pour :
- Consulter son dashboard et son prêt actif
- Voir l'historique des paiements
- Voir ses documents déjà téléchargés
- Voir ses notifications
Les mutations (signature, soumission demande, etc.) nécessitent un réseau actif. Un bandeau "Hors ligne" s'affiche automatiquement en cas de coupure.
📊 État actuel
Validé par observation directe sur émulateur Android (Pixel 10 Pro, API 36) le 2026-05-24 contre un backend NestJS local avec données démo seedées.
Socle fonctionnel
| Composant | Statut | Note |
|---|---|---|
| Structure projet KMP (Android + iOS + code partagé Compose) | DONE | Compose Multiplatform 1.10, Kotlin 2.3 |
| Design system (charte Émeraude/Cuivre, typo Inter) | DONE | Cohérent avec portail web |
| Navigation entre écrans + bottom nav 4 onglets | DONE | Simulateur / Demande / Suivi / Historique |
| Couche data Ktor + sérialisation | DONE | API Portal NestJS, header x-tenant-slug |
| Stockage sécurisé tokens (session persistante) | DONE | Vérifié : reconnexion sans OTP après fermeture de l'app |
| Formatage des dates localisé (FR / EN / AR) | DONE | Infra LocaleProvider + DateFormat (expect/actual), 15 tests. Convention Tunisie : chiffres latins + mois en arabe |
Écrans implémentés et validés
| Écran | Statut | Note |
|---|---|---|
| Login (sélection pays + numéro) | DONE | Préfixes MENA, validation min 6 chiffres |
| OTP SMS (saisie 6 chiffres, compteur, renvoi) | DONE | Délai 5 min + délai renvoi |
| Dashboard (prêt actif + demandes en cours) | DONE | |
| Détail prêt actif (montants + échéancier complet) | DONE | Statuts par échéance : Payé / Retard / À venir |
| Détail demande (chronologie 5 étapes + %) | DONE | |
| Wizard nouvelle demande (5 étapes) | DONE | Étapes 1 & 2 validées (produit, montant/durée) |
| Suivi des demandes | DONE | |
| Historique des prêts (avec empty state) | DONE | |
| Simulateur de prêt + scénarios alternatifs | DONE | Calcul mensualité, intérêts, frais |
| Profil emprunteur (KYC, CIN masquée, complétude) | DONE | |
| Sessions actives (avec révocation) | DONE | |
| Journal d'activité | DONE | Historique des connexions |
| Centre de notifications (avec empty state) | DONE |
À faire / capacités natives non implémentées
| Composant | Statut | Note |
|---|---|---|
| Biométrie (Face ID / Touch ID / empreinte) | À FAIRE | Aucun écran ne propose l'activation aujourd'hui |
| Caméra KYC (capture CIN recto/verso + selfie) | À FAIRE | Écran existe (DocumentUploadScreen) mais flow natif caméra non testé |
| Liveness 3 photos (face / gauche / droite) | À FAIRE | Écran existe (LivenessScreen) mais non vérifié |
| Push notifications natives (FCM Android + APNs iOS) | À FAIRE | Backend Portal compatible, intégration mobile à faire |
| Bascule de langue FR / AR (RTL) / EN dans l'UI | À FAIRE | Le formatage des dates est déjà localisé FR/EN/AR (infra LocaleProvider + DateFormat), mais le sélecteur de langue dans les paramètres et le layout RTL restent à câbler |
| Mode offline (cache local SQLDelight) | À FAIRE | Bandeau hors-ligne non observé |
| Tests E2E automatisés (exécution) | PARTIEL | Maestro installé + 3 flows écrits (_login, dates-formatted, logout) ; exécution live + endpoint dev OTP renvoyés au sous-projet suivant |
🐛 Bugs observés lors des captures → corrigés
La première campagne de captures avait révélé 3 défauts. Ils ont été corrigés en TDD (tests d'abord), puis les écrans concernés ont été recapturés (ce sont les images ci-dessus).
| Bug | Sévérité | Statut | Correctif |
|---|---|---|---|
| Écran « Mes documents » plante au chargement | BLOQUANT | CORRIGÉ | L'API renvoyait un tableau au lieu de l'objet { applications: [] } déclaré (cast as unknown as trompeur). Aligné côté serveur + hook web ; le DTO mobile était déjà correct. 3 tests serveur qui échouaient en silence passent désormais. |
| Dates affichées en ISO brut | UX | CORRIGÉ | Mini-infra i18n KMP (formatDate / formatRelative, FR/EN/AR, chiffres latins). 11 écrans câblés. 15 tests unitaires. 2026-04-01T00:00:00.000Z → 1 avr. 2026 ; Dans -53 jour(s) → il y a 53 jours. |
| Bouton logout non validé | UX | TESTÉ (unit) | Test unitaire DashboardViewModel.logout() ajouté (refacto AuthRepositoryContract pour la testabilité). Vérification end-to-end sur device encore à faire. |
📥 Installation pour test
L'app n'est pas encore publiée sur les stores. Pour tester sur un appareil :
Android
- Recevoir le fichier APK debug par AirDrop / email / lien
- Sur le téléphone Android : activer "Sources inconnues" dans les paramètres
- Installer l'APK
- Ouvrir Qredon → écran de login
iOS
- Inscription du device dans le profil de provisioning (Apple Developer)
- Installation via TestFlight ou directement via Xcode
- Lancer l'app → écran de login
🧪 Tous les scénarios de test
Catalogue des scénarios pour l'app mobile. Les scénarios de base sont communs avec le portail web (même API).
A. Premier lancement & login OTP (8 scénarios)
- 1Premier lancement — Ouvrir l'app pour la première fois → écran de bienvenue + sélection langue.
- 2Login OTP standard — Saisir
+216 55 101 001→ SMS reçu sur MailHog → saisir code → connecté. - 3Demande de permissions — L'app demande permissions Push notifications + Caméra à l'installation.
- 4Refus permission caméra — L'utilisateur refuse → message explicatif quand on tente une action caméra.
- 5Refus permission push — L'utilisateur refuse → l'app fonctionne mais sans push (toast au lieu de notif).
- 6Code OTP incorrect — Saisir 6 chiffres faux → message "Code invalide".
- 7Code OTP expiré (5 min) — Trop attendre → "Code expiré" + bouton "Recevoir un nouveau code".
- 8Réseau coupé pendant le login — Désactiver wifi pendant la saisie du code → message "Connexion requise pour la vérification".
B. Biométrie (10 scénarios)
- 1Activer Face ID (iOS) — Connecté → Profil → Sécurité → "Activer Face ID" → confirmation Face ID → activé.
- 2Activer Touch ID (iOS ancien) — Idem Face ID mais avec empreinte.
- 3Activer empreinte (Android) — Profil > Sécurité > "Activer biométrie" → empreinte → activé.
- 4Reconnexion biométrique — Fermer l'app, la rouvrir → Face ID demandé → succès → connecté instantanément (pas d'OTP).
- 5Échec biométrique — 3 échecs Face ID → bascule sur écran OTP (fallback).
- 6Annulation biométrique — Bouton "Annuler" sur le prompt biométrique → écran OTP affiché.
- 7Désactiver biométrie — Profil > Sécurité → "Désactiver" → confirmation biométrique requise → désactivé + token effacé du coffre.
- 8Appareil sans biométrie — Téléphone sans Face ID / empreinte → option grisée avec message "Non disponible sur cet appareil".
- 9PIN device refusé — Le PIN du téléphone n'est pas accepté comme fallback de la biométrie (volontaire).
- 10Logout wipe — Logout depuis le profil → token effacé du coffre → prochaine ouverture demande OTP.
C. Caméra KYC (8 scénarios)
- 1Capture CIN recto — Étape Documents lors de l'inscription → "Capturer CIN recto" → caméra ouverte avec overlay rectangulaire → capture → preview.
- 2Capture CIN verso — Idem mais pour le verso.
- 3Selfie KYC — Overlay circulaire centré sur le visage → capture → preview.
- 4Liveness 3 photos — Séquence guidée : "Regardez devant" → photo. "Tournez à gauche" → photo. "Tournez à droite" → photo.
- 5Reprendre la photo — Bouton "Reprendre" sur le preview → recapture.
- 6Lumière insuffisante — Capture trop sombre → message d'avertissement, suggestion de reprendre.
- 7Permission caméra refusée initialement — Si l'utilisateur a refusé, message explicatif + lien vers les paramètres système.
- 8Upload après capture — Photos uploadées au backend après validation → progression visible.
D. Push notifications (8 scénarios)
- 1Push "Prêt approuvé" — IMF approuve le prêt → push sur le téléphone avec son + vibration.
- 2Push "Prêt décaissé" — IMF décaisse → push avec montant et date.
- 3Push "Échéance dans 3 jours" — 3 jours avant l'échéance → push de rappel.
- 4Push "Paiement confirmé" — Caissier enregistre le paiement → push immédiat à l'emprunteur.
- 5Push "Complément KYC requis" — IMF demande un doc supplémentaire → push.
- 6Deep link au tap — Tap sur la push "Prêt approuvé" → l'app s'ouvre directement sur la page du prêt concerné.
- 7Push reçu app fermée — Push reçu alors que l'app n'est pas lancée → notification système → tap ouvre l'app au bon endroit.
- 8Désactiver push — Paramètres iOS/Android → couper les notifs pour Qredon → plus de push reçues mais l'app fonctionne.
E. Demande de prêt depuis mobile (6 scénarios)
- 1Demande complète depuis le mobile — Connecté → "Demander un prêt" → wizard 4 étapes → signature OTP → soumise (identique au portail web).
- 2Sauvegarde brouillon — Quitter l'app au milieu du wizard → revenir → reprise où on en était.
- 3Upload pièces via caméra — Étape Documents → "Capturer avec la caméra" au lieu d'upload galerie.
- 4Signature OTP — À la soumission → OTP envoyé → saisie → demande soumise.
- 5Continuer une demande commencée sur web — Brouillon créé sur le portail web → reprise dans l'app mobile (même compte).
- 6Annuler une demande — Si statut DRAFT ou SUBMITTED → bouton "Annuler".
F. Fonctionnement offline (5 scénarios)
- 1Mode avion activé — Ouvrir l'app sans réseau → bandeau "Hors ligne" → dashboard, prêt actif, historique consultables (depuis cache).
- 2Mutation bloquée offline — Tenter une demande de prêt sans réseau → message "Connexion requise pour cette action".
- 3Reconnexion auto — Désactiver mode avion → bandeau "Hors ligne" disparaît → données rafraîchies.
- 4Push reçue en différé — Push envoyée pendant que le téléphone était offline → reçue dès le retour en ligne.
- 5Cache expiré — Cache local de >24h → l'app force le refresh au retour en ligne.
G. Multilingue & RTL (4 scénarios)
- 1Bascule en arabe — Paramètres > Langue > العربية → toute l'UI bascule + layout RTL.
- 2Bascule en anglais — Choisir English → UI en anglais.
- 3Persistance après redémarrage — Fermer l'app, rouvrir → langue conservée.
- 4Langue système par défaut — Premier lancement → l'app détecte la langue du système et l'utilise par défaut.
H. Documents & partage natif (5 scénarios)
- 1Voir mes documents — Documents → liste de tous mes docs uploadés.
- 2Télécharger un reçu PDF — Reçu d'un paiement → "Télécharger" → PDF généré.
- 3Partager via share sheet — Bouton "Partager" → share sheet natif (WhatsApp, email, AirDrop iOS, Intent Android).
- 4Générer attestation — Documents > Générer > Bonne tenue → PDF généré + QR.
- 5Ouvrir le PDF directement — Tap sur un PDF → ouverture dans le viewer natif iOS/Android.
I. Edge cases mobile (8 scénarios)
- 1Mise en arrière-plan — App en background pendant un appel/SMS → reprise au même endroit.
- 2Rotation de l'écran — Tourner le téléphone → l'app reste utilisable (portrait par défaut, paysage géré).
- 3Faible mémoire — Système low-memory → l'app gère le redémarrage propre sans perte de données.
- 4Batterie faible — L'app continue de fonctionner normalement (pas de mode dégradé).
- 5Mise à jour de l'app — Update via store → ouverture après update → re-connexion biométrique ou OTP si nécessaire.
- 6Désinstallation/réinstallation — Désinstaller l'app → token wipe automatique → réinstaller → premier login OTP requis.
- 7Compte sur deux appareils — Même compte connecté sur 2 téléphones → les deux fonctionnent, les notifs arrivent sur les deux.
- 8Tenant suspendu — L'IMF est suspendue → l'app affiche un message "Service indisponible, contactez votre conseiller".
J. Workflows complets bout-à-bout (3 scénarios)
- 1Onboarding emprunteur 100% mobile
- Installation de l'app Android/iOS
- Premier lancement → Sélection langue (FR/AR/EN)
- "Créer un compte" → saisie phone + email
- Réception double OTP → validation
- Saisie profil de base
- Capture CIN recto/verso via caméra native
- Selfie KYC + liveness 3 photos
- Soumission → statut PENDING_REVIEW
- Activation biométrie proposée pour les prochaines sessions
- Validation par l'agent IMF → push reçue "KYC validé"
- Tap sur la push → écran statut KYC affiché
- 2Cycle prêt + remboursement sur mobile
- Réouverture de l'app → Face ID → connecté instantanément
- Tap "Demander un prêt" → wizard 4 étapes
- Soumission + signature OTP → dossier créé
- 3 jours plus tard → push "Prêt approuvé" → tap → écran du prêt
- 2 jours plus tard → push "Prêt décaissé" + montant
- 30 jours plus tard → push "Échéance dans 3 jours"
- L'utilisateur se rend à l'agence et paie en cash
- Push immédiate "Paiement confirmé" → reçu PDF téléchargeable
- Partage du reçu via WhatsApp à son comptable (share sheet natif)
- 3Utilisation offline en zone rurale
- Emprunteur dans une zone sans réseau → ouvre l'app
- Bandeau "Hors ligne" affiché
- Il consulte son prêt actif et son échéancier (cache local)
- Il télécharge ses derniers reçus pour les partager plus tard
- De retour en ville avec réseau → bandeau "Hors ligne" disparaît
- Les push en attente arrivent
- Les données se rafraîchissent automatiquement