Readme
EBO <eric.bouhana@softalys.com> committé le 2026-07-23 18:49
a9a1f85a97668ea11b3d94515bbd50a8961ede62
1 parent(s)
3 fichiers modifiés
+59
-3
M
.gitignore
+2
-0
@@ -25,6 +25,8 @@ __pycache__/
| 25 | 25 | *.pyc |
| 26 | 26 | |
| 27 | 27 | .venv/ |
| 28 | +#workspace | |
| 29 | +EBII_mobileVCF.code-workspace | |
| 28 | 30 | |
| 29 | 31 | # QR codes — regenerated on-site with real SSID/pass/IP values |
| 30 | 32 | staging/*.png |
M
README.md
+6
-3
@@ -28,11 +28,14 @@ Sync **offline-first** avec un serveur [Projectiaon](https://github.com/) (ailia
| 28 | 28 | |
| 29 | 29 | **Prérequis serveur :** variable `AILIANCE_API_CLES` (clés API par utilisateur), endpoints `/api/auth/cle`, `/api/sync/status`, `/api/sync/pull` — voir le [plan serveur](../Projectiaon/docs/plans/sync_api_mobile_v1.md). |
| 30 | 30 | |
| 31 | -**Configuration dans l’app :** Paramètres (engrenage) → URL HTTPS du serveur → identifiant + mot de passe → « Obtenir la clé » → retaper le mot de passe pour déchiffrer la clé API (stockée chiffrée sur l’appareil ; le mot de passe n’est jamais conservé). | |
| 31 | +**Configuration dans l’app :** Paramètres (engrenage) → URL **HTTPS** du serveur → identifiant + mot de passe → « Obtenir la clé » → retaper le mot de passe pour déchiffrer la clé API (stockée chiffrée sur l’appareil ; le mot de passe n’est jamais conservé). | |
| 32 | 32 | |
| 33 | -**Utilisation :** à l’ouverture, un bandeau signale les changements distants sans pull automatique. Le bouton **Sync** pousse les modifications locales (contacts créés/édités dans le carnet, tâches, CR…) puis tire le delta serveur. Sans sync configurée, le carnet reste local uniquement. | |
| 33 | +Pour le **développement**, un **réseau interne** ou une **démo** sans TLS : cocher **« Autoriser HTTP (clair) »** avant de saisir une URL `http://…`. Sans cette case, l’app refuse le HTTP (HTTPS obligatoire). Ne pas activer cette option en production sur Internet. | |
| 34 | 34 | |
| 35 | -Plan d’implémentation client : [`docs/plans/sync_card2vcf_projectiaon_v1.md`](docs/plans/sync_card2vcf_projectiaon_v1.md). | |
| 35 | +**Utilisation :** à l’ouverture, un bandeau signale les changements distants sans pull automatique. Le bouton **Sync** pousse les modifications locales (contacts créés/édités dans le carnet **y compris l’image de carte scannée** et la photo de profil si présentes, tâches, CR…) puis tire le delta serveur. Sans sync configurée, le carnet reste local uniquement. | |
| 36 | + | |
| 37 | +Plan d’implémentation client : [`docs/plans/sync_card2vcf_projectiaon_v1.md`](docs/plans/sync_card2vcf_projectiaon_v1.md). | |
| 38 | +Sync images carte/photo : [`docs/plans/sync_cartes_visite_v1.md`](docs/plans/sync_cartes_visite_v1.md). | |
| 36 | 39 | |
| 37 | 40 | > **Upgrade schéma v2 :** la migration Room peut réinitialiser les données locales (documenté dans le plan sync). |
| 38 | 41 |
A
docs/plans/sync_cartes_visite_v1.md
+51
-0
@@ -0,0 +1,51 @@
| 1 | +# Sync cartes de visite (images) — v1 | |
| 2 | + | |
| 3 | +**Date :** 2026-07-23 | |
| 4 | +**Dépôts :** Projectiaon (serveur) + EBII_mobileVCF / Card2vcf (client) | |
| 5 | +**Statut :** implémenté | |
| 6 | + | |
| 7 | +## Objectif | |
| 8 | + | |
| 9 | +À la sync, pousser/tirer non seulement le **contact texte**, mais aussi l’**image de carte de visite** (et la photo de profil) déjà gérées côté Projectiaon via `Contact.carte_visite` / `Contact.photo`. | |
| 10 | + | |
| 11 | +## Contexte | |
| 12 | + | |
| 13 | +La sync CRM v1 excluait explicitement les « médias serveur ». L’upload image n’existait qu’en session web (`POST /contacts/:id/carte`), inutilisable par Card2vcf (Bearer). | |
| 14 | + | |
| 15 | +## API serveur (Bearer) | |
| 16 | + | |
| 17 | +| Méthode | Route | Rôle | | |
| 18 | +|---|---|---| | |
| 19 | +| `POST` | `/api/contacts/:id/carte` | multipart → `carte_visite` | | |
| 20 | +| `GET` | `/api/contacts/:id/carte` | sert le fichier | | |
| 21 | +| `POST` | `/api/contacts/:id/photo` | multipart → `photo` | | |
| 22 | +| `GET` | `/api/contacts/:id/photo` | sert la photo | | |
| 23 | + | |
| 24 | +- Auth : même garde Bearer que le reste de `/api` | |
| 25 | +- Validation : png/jpg/jpeg/webp/gif, max 5 Mo (`medias::enregistrer_upload`) | |
| 26 | +- POST : `200` + JSON `Contact` (avec `mis_a_jour_le` mis à jour) | |
| 27 | +- Routes web `/contacts/:id/carte|photo` inchangées (session) | |
| 28 | + | |
| 29 | +## Client Card2vcf | |
| 30 | + | |
| 31 | +1. **Push** : après `create`/`update` contact JSON réussi, upload `card.jpg` / `profile.jpg` si présents. | |
| 32 | +2. **Retry** : échec upload → SyncOp `contact_media` (ne re-crée pas le contact). | |
| 33 | +3. **Rotation** : `rotateCardImage` enqueue un update contact pour re-pousser l’image. | |
| 34 | +4. **Pull** : si DTO a `carte_visite`/`photo` et (fichier local absent **ou** serveur plus récent), `GET` + `ContactImageStore.saveBytes`. Skip si SyncOp contact/média pending. | |
| 35 | + | |
| 36 | +## Hors scope | |
| 37 | + | |
| 38 | +- Fichier `.vcf` en pièce jointe | |
| 39 | +- Champ `PHOTO` dans l’export VCF | |
| 40 | +- Sync des champs locaux non mappés (`website`, `address`, …) | |
| 41 | + | |
| 42 | +## Tests | |
| 43 | + | |
| 44 | +- Projectiaon : `tests/api_contacts_media_http.rs` | |
| 45 | +- Card2vcf : `AilianceApiClientTest` (multipart/download), `SyncEngineTest` (push image, retry, pull) | |
| 46 | + | |
| 47 | +## Critères de succès | |
| 48 | + | |
| 49 | +1. Scan + sync → vignette carte visible dans l’UI web Projectiaon | |
| 50 | +2. 2ᵉ appareil / réinstall → pull récupère contact + `card.jpg` | |
| 51 | +3. Routes web inchangées |
GitRust