#69 — mobile-audit-pwa
PLANIFIÉ
Priorité: 🟠 HAUTE · Type: TYPE B · Conteneur: rgz-api · Code: app/api/v1/endpoints/audit.py + portal/pwa/
Dépendances: #1 rgz-api
Description
Application PWA (Progressive Web App) mobile pour les audits terrain des techniciens RGZ. Fonctionne en mode offline sur le terrain (pas de connexion 3G/4G requise) et synchronise les données dès que la connexion est rétablie.
Le formulaire capture les métriques terrain (RSSI, SNR, CCQ, photos, GPS), les problèmes observés et les actions correctives. Conçu pour fonctionner sur smartphone Android sans installation depuis le Play Store.
Installable via le navigateur Chrome/Firefox : access-rgz.duckdns.org/pwa/ → "Ajouter à l'écran d'accueil".
Architecture Interne
Technicien → Smartphone → PWA (Service Worker cache)
↓ [offline]
Remplissage formulaire audit
↓
Stockage IndexedDB local (queue)
↓ [connexion disponible]
Sync automatique → POST /api/v1/audit/sync (batch)
↓
rgz-api → Table site_audits (PostgreSQL)
↓
Dashboard NOC (#52) → historique auditsPWA Files (portal/pwa/)
portal/pwa/
├── manifest.json # PWA manifest (nom, icône, theme)
├── sw.js # Service Worker (cache offline)
├── audit.html # Formulaire audit
├── audit.js # IndexedDB + sync logic
└── audit.css # Styles mobile-firstTable site_audits
sql
CREATE TABLE site_audits (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
site_id UUID REFERENCES reseller_sites(id),
technician_id UUID REFERENCES staff(id),
rssi_dbm INT,
snr_db INT,
ccq_percent INT,
dl_mbps FLOAT,
ul_mbps FLOAT,
photo_url TEXT,
notes TEXT,
latitude DOUBLE PRECISION,
longitude DOUBLE PRECISION,
issues_found JSONB DEFAULT '[]',
actions_taken JSONB DEFAULT '[]',
audited_at TIMESTAMPTZ NOT NULL,
synced_at TIMESTAMPTZ DEFAULT NOW(),
created_at TIMESTAMPTZ DEFAULT NOW()
);Configuration PWA
manifest.json
json
{
"name": "RGZ Audit Terrain",
"short_name": "RGZ Audit",
"start_url": "/pwa/audit.html",
"display": "standalone",
"theme_color": "#3f68ae",
"background_color": "#ffffff",
"icons": [
{"src": "/img/icon-192.png", "sizes": "192x192", "type": "image/png"},
{"src": "/img/icon-512.png", "sizes": "512x512", "type": "image/png"}
]
}Variables d'environnement
env
PWA_API_URL=https://api-rgz.duckdns.org
PWA_SYNC_INTERVAL_MS=30000 # Tentative sync toutes les 30s
PWA_MAX_OFFLINE_QUEUE=100 # Max audits en queueEndpoints API
| Méthode | Route | Body | Réponse | Auth |
|---|---|---|---|---|
| POST | /api/v1/audit | {site_id, rssi, snr, ccq, ...} | 201 {id} | JWT |
| POST | /api/v1/audit/sync | {audits: [...]} | 200 {synced: N} | JWT |
| GET | /api/v1/audit?site_id= | — | {items, total} | JWT |
| GET | /api/v1/audit/{id} | — | {audit} | JWT |
POST /api/v1/audit/sync (batch offline)
json
{
"audits": [
{
"local_id": "local_uuid_generated_offline",
"site_id": "550e8400-...",
"rssi_dbm": -68,
"snr_db": 24,
"ccq_percent": 91,
"dl_mbps": 18.5,
"ul_mbps": 6.2,
"notes": "Antenne réalignée. OK.",
"latitude": 6.3654,
"longitude": 2.3912,
"audited_at": "2026-02-21T10:30:00Z"
}
]
}Commandes Utiles
bash
# Accès PWA
open https://access-rgz.duckdns.org/pwa/
# Voir audits non synchronisés
curl -H "Authorization: Bearer $JWT" \
https://api-rgz.duckdns.org/api/v1/audit?synced=false
# Audits d'un site
curl -H "Authorization: Bearer $JWT" \
"https://api-rgz.duckdns.org/api/v1/audit?site_id=550e8400-..."
# Stats audits du mois
docker exec rgz-db psql -U postgres -c \
"SELECT DATE(audited_at), COUNT(*) FROM site_audits
WHERE audited_at > NOW()-'30 days'::interval
GROUP BY DATE(audited_at) ORDER BY 1;"Implémentation TODO
- [ ]
portal/pwa/manifest.json+ Service Workersw.js - [ ] Formulaire mobile
portal/pwa/audit.html(mobile-first CSS) - [ ] IndexedDB queue offline
portal/pwa/audit.js - [ ] Sync automatique détection connexion (navigator.onLine)
- [ ] POST
/api/v1/auditendpoint - [ ] POST
/api/v1/audit/syncendpoint (batch, idempotent via local_id) - [ ] Capture photo (Camera API)
- [ ] GPS automatique (Geolocation API)
- [ ] Tests PWA offline (Chrome DevTools → Network → Offline)
Dernière mise à jour: 2026-02-21