ajout de l'export des votes dans un fichier ODS avec toutes les données (anonymisées par défaut - réglable dans les paramètres)
This commit is contained in:
278
docs/EXPORT-FEATURE.md
Normal file
278
docs/EXPORT-FEATURE.md
Normal file
@@ -0,0 +1,278 @@
|
||||
# 📊 Fonctionnalité d'Export ODS - Statistiques de Vote
|
||||
|
||||
## 🎯 Vue d'ensemble
|
||||
|
||||
La fonctionnalité d'export ODS permet d'exporter les statistiques de vote d'une campagne dans un format tableur compatible avec LibreOffice Calc, OpenOffice Calc et Microsoft Excel.
|
||||
|
||||
## 📋 Fonctionnalités
|
||||
|
||||
### ✅ **Export complet des données**
|
||||
- **Onglet principal** : "Synthèse des votes" - Matrice des votes (participants × propositions)
|
||||
- **6 onglets de tri** : Un pour chaque critère de tri des propositions
|
||||
- **Toutes les propositions** en colonnes
|
||||
- **Tous les participants** (votants ou non) en lignes
|
||||
- **Montants investis** à l'intersection colonne/ligne
|
||||
- **Totaux par ligne** (total voté par participant)
|
||||
- **Totaux par colonne** (total reçu par proposition)
|
||||
- **Budget restant** par participant
|
||||
- **Anonymisation RGPD** : 3 niveaux de protection des données personnelles
|
||||
|
||||
### 📊 **Structure du fichier exporté**
|
||||
|
||||
#### **Onglet principal : "Synthèse des votes"**
|
||||
```
|
||||
Statistiques de vote - [Nom de la campagne]
|
||||
|
||||
Participant | Proposition 1 | Proposition 2 | ... | Total voté | Budget restant
|
||||
-----------|---------------|---------------|-----|------------|---------------
|
||||
Alice Doe | 50 | 30 | ... | 80 | 20
|
||||
Bob Smith | 40 | 0 | ... | 40 | 60
|
||||
... | ... | ... | ... | ... | ...
|
||||
TOTAL | 90 | 30 | ... | 120 | 80
|
||||
```
|
||||
|
||||
#### **Onglets de tri (6 onglets)**
|
||||
Chaque onglet contient les propositions triées selon un critère :
|
||||
|
||||
**Onglet "Impact total"**
|
||||
```
|
||||
Statistiques de vote - [Nom de la campagne] - Tri par Impact total (Somme totale investie)
|
||||
|
||||
Proposition | Votes reçus | Montant total | Montant moyen | Montant min | Montant max | Taux participation | Répartition votes | Score consensus
|
||||
-----------|-------------|---------------|---------------|-------------|-------------|-------------------|-------------------|------------------
|
||||
Prop A | 5 | 250 | 50 | 30 | 70 | 100 | 5 | 15.8
|
||||
Prop B | 3 | 120 | 40 | 20 | 60 | 60 | 3 | 16.3
|
||||
```
|
||||
|
||||
**Onglets disponibles :**
|
||||
- **Impact total** : Tri par montant total investi
|
||||
- **Popularité** : Tri par montant moyen puis nombre de votants
|
||||
- **Consensus** : Tri par score de consensus (écart-type)
|
||||
- **Engagement** : Tri par taux de participation
|
||||
- **Répartition** : Tri par nombre de votes différents
|
||||
- **Alphabétique** : Tri par ordre alphabétique
|
||||
|
||||
**Format des en-têtes :** "Statistiques de vote - [Nom Campagne] - Tri par [Critère] ([Description])"
|
||||
|
||||
**Descriptions des critères :**
|
||||
- **Impact total** : "Somme totale investie"
|
||||
- **Popularité** : "Moyenne puis nombre de votants"
|
||||
- **Consensus** : "Plus petit écart-type"
|
||||
- **Engagement** : "Taux de participation"
|
||||
- **Répartition** : "Nombre de votes différents"
|
||||
- **Alphabétique** : "Ordre alphabétique"
|
||||
|
||||
### 🎨 **Formatage**
|
||||
- **En-tête** avec le titre de la campagne
|
||||
- **Colonnes dimensionnées** automatiquement
|
||||
- **Ligne des totaux** avec texte en gras et bordures épaisses
|
||||
- **Colonnes des totaux** (Total voté, Budget restant) avec bordures épaisses
|
||||
- **Nom de fichier** automatique avec date
|
||||
|
||||
## 🚀 Utilisation
|
||||
|
||||
### **Configuration de l'anonymisation**
|
||||
|
||||
1. **Accédez** à **Paramètres** > **Exports**
|
||||
2. **Choisissez** le niveau d'anonymisation :
|
||||
- **Anonymisation complète** : Noms remplacés par "XXXX" (recommandé)
|
||||
- **Initiales uniquement** : Premières lettres des noms/prénoms
|
||||
- **Aucune anonymisation** : Noms complets (attention RGPD)
|
||||
3. **Sauvegardez** les paramètres
|
||||
|
||||
### **Dans l'interface d'administration**
|
||||
|
||||
1. **Accédez** à la page des statistiques d'une campagne
|
||||
2. **Cliquez** sur le bouton "Exporter les votes (ODS)" en haut à droite
|
||||
3. **Attendez** la génération du fichier
|
||||
4. **Le fichier** se télécharge automatiquement avec le niveau d'anonymisation configuré
|
||||
|
||||
### **Format du nom de fichier**
|
||||
```
|
||||
statistiques_vote_[nom_campagne]_[date].ods
|
||||
```
|
||||
|
||||
**Exemples :**
|
||||
- `statistiques_vote_budget_participatif_2024_2025-08-27.ods`
|
||||
- `statistiques_vote_campagne_ete_2025-08-27.ods`
|
||||
|
||||
## 🔧 Architecture technique
|
||||
|
||||
### **Fichiers impliqués**
|
||||
|
||||
#### `src/lib/export-utils.ts`
|
||||
- **`generateVoteExportODS()`** : Génère le fichier ODS
|
||||
- **`downloadODS()`** : Télécharge le fichier
|
||||
- **`formatFilename()`** : Formate le nom de fichier
|
||||
|
||||
#### `src/components/ExportStatsButton.tsx`
|
||||
- **Composant React** pour le bouton d'export
|
||||
- **Gestion des états** (chargement, erreur)
|
||||
- **Interface utilisateur** avec icône et texte
|
||||
|
||||
#### `src/app/admin/campaigns/[id]/stats/page.tsx`
|
||||
- **Intégration** du bouton d'export
|
||||
- **Passage des données** nécessaires
|
||||
|
||||
### **Dépendances**
|
||||
```json
|
||||
{
|
||||
"xlsx": "^0.18.5"
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 Structure des données
|
||||
|
||||
### **Interface ExportData**
|
||||
```typescript
|
||||
interface ExportData {
|
||||
campaignTitle: string;
|
||||
propositions: Proposition[];
|
||||
participants: Participant[];
|
||||
votes: Vote[];
|
||||
budgetPerUser: number;
|
||||
}
|
||||
```
|
||||
|
||||
### **Calculs effectués**
|
||||
|
||||
#### **Totaux par participant**
|
||||
```typescript
|
||||
const totalVoted = votes
|
||||
.filter(v => v.participant_id === participant.id)
|
||||
.reduce((sum, vote) => sum + vote.amount, 0);
|
||||
```
|
||||
|
||||
#### **Totaux par proposition**
|
||||
```typescript
|
||||
const propositionTotal = votes
|
||||
.filter(v => v.proposition_id === proposition.id)
|
||||
.reduce((sum, vote) => sum + vote.amount, 0);
|
||||
```
|
||||
|
||||
#### **Budget restant**
|
||||
```typescript
|
||||
const budgetRemaining = budgetPerUser - totalVoted;
|
||||
```
|
||||
|
||||
## 🧪 Tests
|
||||
|
||||
### **Tests unitaires**
|
||||
- **Génération ODS** : Vérification de la structure
|
||||
- **Formatage des noms** : Gestion des caractères spéciaux
|
||||
- **Cas limites** : Participants sans votes, propositions vides
|
||||
|
||||
### **Fichier de test**
|
||||
`src/__tests__/lib/export-utils.test.ts`
|
||||
|
||||
### **Exécution des tests**
|
||||
```bash
|
||||
npm test -- src/__tests__/lib/export-utils.test.ts
|
||||
```
|
||||
|
||||
## 🔒 Sécurité et RGPD
|
||||
|
||||
### **Anonymisation des données**
|
||||
- **3 niveaux de protection** configurables dans les paramètres
|
||||
- **Anonymisation complète** : Noms remplacés par "XXXX" (recommandé)
|
||||
- **Initiales uniquement** : Premières lettres des noms/prénoms
|
||||
- **Aucune anonymisation** : Noms complets (avec avertissement RGPD)
|
||||
|
||||
### **Données exportées**
|
||||
- **Aucune donnée sensible** (mots de passe, clés API)
|
||||
- **Données publiques** uniquement (votes, participants, propositions)
|
||||
- **Conformité RGPD** : Respect du niveau d'anonymisation configuré
|
||||
- **Avertissement** : Alerte RGPD pour l'export sans anonymisation
|
||||
|
||||
### **Validation**
|
||||
- **Vérification des types** TypeScript
|
||||
- **Validation des données** avant export
|
||||
- **Gestion d'erreurs** robuste
|
||||
|
||||
## 🎨 Interface utilisateur
|
||||
|
||||
### **Bouton d'export**
|
||||
- **Icône** : FileSpreadsheet (Lucide React)
|
||||
- **Texte** : "Exporter les votes (ODS)"
|
||||
- **État de chargement** : Spinner + "Export en cours..."
|
||||
- **Position** : En haut à droite de la page statistiques
|
||||
- **Anonymisation** : Respecte le paramètre configuré dans les paramètres
|
||||
|
||||
### **États visuels**
|
||||
- **Normal** : Bouton cliquable
|
||||
- **Chargement** : Spinner + texte modifié
|
||||
- **Désactivé** : Quand les données ne sont pas chargées
|
||||
|
||||
## 🔄 Workflow
|
||||
|
||||
### **1. Clic sur le bouton**
|
||||
```typescript
|
||||
const handleExport = async () => {
|
||||
setIsExporting(true);
|
||||
// Génération et téléchargement
|
||||
setIsExporting(false);
|
||||
};
|
||||
```
|
||||
|
||||
### **2. Génération des données**
|
||||
```typescript
|
||||
const exportData: ExportData = {
|
||||
campaignTitle,
|
||||
propositions,
|
||||
participants,
|
||||
votes,
|
||||
budgetPerUser
|
||||
};
|
||||
```
|
||||
|
||||
### **3. Création du fichier ODS**
|
||||
```typescript
|
||||
const odsData = generateVoteExportODS(exportData);
|
||||
```
|
||||
|
||||
### **4. Téléchargement**
|
||||
```typescript
|
||||
const filename = formatFilename(campaignTitle);
|
||||
downloadODS(odsData, filename);
|
||||
```
|
||||
|
||||
## 🐛 Dépannage
|
||||
|
||||
### **Problèmes courants**
|
||||
|
||||
#### **Fichier ne se télécharge pas**
|
||||
- Vérifiez les permissions du navigateur
|
||||
- Désactivez les bloqueurs de popup
|
||||
- Vérifiez l'espace disque disponible
|
||||
|
||||
#### **Erreur de génération**
|
||||
- Vérifiez que toutes les données sont chargées
|
||||
- Consultez la console du navigateur
|
||||
- Relancez l'export
|
||||
|
||||
#### **Fichier corrompu**
|
||||
- Vérifiez la taille du fichier
|
||||
- Essayez d'ouvrir avec un autre logiciel
|
||||
- Régénérez l'export
|
||||
|
||||
### **Logs de débogage**
|
||||
```typescript
|
||||
console.error('Erreur lors de l\'export:', error);
|
||||
```
|
||||
|
||||
## 🚀 Améliorations futures
|
||||
|
||||
### **Fonctionnalités envisagées**
|
||||
- **Export PDF** : Version imprimable
|
||||
- **Filtres** : Export partiel (participants spécifiques)
|
||||
- **Templates** : Formats personnalisables
|
||||
- **Export automatique** : Programmation d'exports
|
||||
|
||||
### **Optimisations**
|
||||
- **Compression** : Réduction de la taille des fichiers
|
||||
- **Cache** : Mise en cache des exports récents
|
||||
- **Asynchrone** : Export en arrière-plan pour les gros volumes
|
||||
|
||||
---
|
||||
|
||||
**Cette fonctionnalité facilite l'analyse et le partage des résultats de vote ! 📊✨**
|
||||
Reference in New Issue
Block a user