Livraison d ela gestion des opérations v0.4.0

This commit is contained in:
d6soft
2025-06-24 13:01:43 +02:00
parent b9672a6228
commit 7763d02fae
819 changed files with 306790 additions and 145462 deletions

276
api/docs/EXPORT-SYSTEM.md Normal file
View File

@@ -0,0 +1,276 @@
# Système d'Export/Import d'Opérations - Geosector API
## Vue d'ensemble
Le système d'export/import permet de sauvegarder et restaurer des opérations complètes avec toutes leurs données associées (passages, utilisateurs, secteurs, relations).
## Architecture
### Routes API
#### Exports
- `GET /api/operations/{id}/export/excel` - Export Excel (consultation)
- `GET /api/operations/{id}/export/json` - Export JSON (sauvegarde)
- `GET /api/operations/{id}/export/full` - Export combiné (Excel + JSON)
#### Gestion des sauvegardes
- `GET /api/operations/{id}/backups` - Liste des sauvegardes
- `GET /api/operations/{id}/backups/{backup_id}` - Télécharger une sauvegarde
- `DELETE /api/operations/{id}/backups/{backup_id}` - Supprimer une sauvegarde
### Structure des fichiers
```
uploads/entites/{entite_id}/operations/{operation_id}/documents/exports/
├── excel/
│ └── geosector-export-{operation_id}-{timestamp}.xlsx
└── json/
└── geosector-backup-{operation_id}-{type}-{timestamp}.json
```
## Export Excel
### Contenu
Le fichier Excel contient 4 feuilles :
#### 1. Feuille "Passages"
- **Colonnes** : ID_Passage, Date, Heure, Prénom, Nom, Tournée, Type, N°, Rue, Ville, Habitat, Donateur, Email, Tél, Montant, Règlement, Remarque, FK_User, FK_Sector, FK_Operation
- **Données déchiffrées** : Noms, emails, téléphones
- **Formatage** : Dates françaises (dd/mm/yyyy), types traduits
#### 2. Feuille "Utilisateurs"
- **Colonnes** : ID_User, Nom, Prénom, Email, Téléphone, Mobile, Rôle, Date_création, Actif, FK_Entite
- **Données déchiffrées** : Informations personnelles
#### 3. Feuille "Secteurs"
- **Colonnes** : ID_Sector, Libellé, Couleur, Date_création, Actif, FK_Operation
#### 4. Feuille "Secteurs-Utilisateurs"
- **Colonnes** : ID_Relation, FK_Sector, Nom_Secteur, FK_User, Nom_Utilisateur, Date_assignation, FK_Operation
### Paramètres optionnels
- `?user_id={id}` - Filtrer les passages par utilisateur
### Exemple d'utilisation
```bash
# Export complet
GET /api/operations/2644/export/excel
# Export filtré par utilisateur
GET /api/operations/2644/export/excel?user_id=123
```
## Export JSON
### Structure du fichier JSON
```json
{
"export_metadata": {
"version": "1.0",
"export_date": "2025-06-21T16:19:23Z",
"source_entite_id": 5,
"export_type": "full_operation"
},
"operation": {
"id": 2644,
"libelle": "OPE 2024-25",
"date_deb": "2024-09-01",
"date_fin": "2025-05-30",
"fk_entite": 5,
"chk_distinct_sectors": 1,
"created_at": "2024-08-15T10:00:00Z"
},
"users": [...],
"sectors": [...],
"passages": [...],
"user_sectors": [...]
}
```
### Types d'export JSON
- **manual** : Export à la demande (par défaut)
- **auto** : Sauvegarde automatique (avant modifications importantes)
### Paramètres
- `?type=manual|auto` - Type d'export
## Sécurité
### Contrôles d'accès
- ✅ Authentification obligatoire
- ✅ Vérification d'appartenance à l'entité
- ✅ Isolation des données par entité
- ✅ Logs détaillés de toutes les opérations
### Données sensibles
- ✅ Chiffrement/déchiffrement automatique
- ✅ Données personnelles protégées
- ✅ Pas d'exposition des clés de chiffrement
## Stockage et organisation
### Enregistrement en base
Tous les fichiers sont enregistrés dans la table `medias` :
```sql
support = 'operation'
support_id = {operation_id}
file_type = 'xlsx' | 'json'
description = 'Export Excel opération - {libelle}'
```
### Métadonnées des fichiers
- **ID** : Identifiant unique en base
- **Filename** : Nom du fichier généré
- **Path** : Chemin relatif depuis la racine
- **Size** : Taille en octets
- **Type** : excel | json
## Exemples de réponses API
### Export Excel réussi
```json
{
"status": "success",
"message": "Export Excel généré avec succès",
"file": {
"id": 123,
"filename": "geosector-export-2644-20250621-161923.xlsx",
"path": "uploads/entites/5/operations/2644/documents/exports/excel/geosector-export-2644-20250621-161923.xlsx",
"size": 45678,
"type": "excel"
}
}
```
### Export complet réussi
```json
{
"status": "success",
"message": "Export complet généré avec succès",
"files": {
"excel": {
"id": 123,
"filename": "geosector-export-2644-20250621-161923.xlsx",
"path": "uploads/entites/5/operations/2644/documents/exports/excel/geosector-export-2644-20250621-161923.xlsx",
"size": 45678,
"type": "excel"
},
"json": {
"id": 124,
"filename": "geosector-backup-2644-manual-20250621-161923.json",
"path": "uploads/entites/5/operations/2644/documents/exports/json/geosector-backup-2644-manual-20250621-161923.json",
"size": 12345,
"type": "json"
}
}
}
```
### Liste des sauvegardes
```json
{
"status": "success",
"backups": [
{
"id": 124,
"fichier": "geosector-backup-2644-manual-20250621-161923.json",
"file_type": "json",
"file_size": 12345,
"description": "Sauvegarde JSON opération - manual - OPE 2024-25",
"created_at": "2025-06-21 16:19:23",
"fk_user_creat": 1
},
{
"id": 123,
"fichier": "geosector-export-2644-20250621-161923.xlsx",
"file_type": "xlsx",
"file_size": 45678,
"description": "Export Excel opération - OPE 2024-25",
"created_at": "2025-06-21 16:19:23",
"fk_user_creat": 1
}
]
}
```
## Installation et dépendances
### PhpSpreadsheet
```bash
composer require phpoffice/phpspreadsheet
```
### Permissions de dossiers
```bash
chmod 755 uploads/
chmod 755 uploads/entites/
```
## Gestion des erreurs
### Erreurs courantes
- **401** : Non authentifié
- **403** : Pas d'accès à l'entité
- **404** : Opération non trouvée
- **500** : Erreur de génération
### Logs
Tous les événements sont loggés via `LogService` :
- Exports réussis (level: info)
- Erreurs de génération (level: error)
- Tentatives d'accès non autorisées (level: warning)
## Maintenance
### Nettoyage automatique (à implémenter)
- Sauvegardes auto > 30 jours
- Fichiers temporaires > 24h
- Vérification cohérence base/fichiers
### Monitoring
- Espace disque utilisé
- Nombre de fichiers par entité
- Fréquence des exports
## Évolutions futures
### Import/Restauration
- Validation des fichiers JSON
- Import transactionnel
- Gestion des conflits d'IDs
- Mapping entités source/cible
### Optimisations
- Compression des fichiers
- Export asynchrone pour gros volumes
- Cache des exports fréquents
- API de streaming pour téléchargements

376
api/docs/FILE-SYSTEM-API.md Normal file
View File

@@ -0,0 +1,376 @@
# API de Gestion des Fichiers - Geosector
## Vue d'ensemble
L'API de gestion des fichiers permet aux administrateurs de naviguer, rechercher et gérer les fichiers stockés dans l'application Geosector avec des contrôles d'accès basés sur les rôles.
## Contrôles d'accès
### Rôle 2 (Admin d'entité)
- Accès limité aux fichiers de son entité uniquement
- Chemin racine : `/uploads/entites/{son_entite_id}/`
- Peut naviguer dans tous les sous-dossiers de son entité
### Rôle > 2 (Super admin)
- Accès complet à tous les fichiers
- Chemin racine : `/uploads/` (accès total)
- Peut naviguer dans toutes les entités et dossiers système
## Routes disponibles
### Navigation et listing
#### `GET /api/files/browse`
Navigation dans l'arborescence avec recherche et pagination.
**Paramètres de requête :**
- `path` (string) : Chemin à explorer (ex: `entites/5/operations`)
- `page` (int) : Page (défaut: 1)
- `per_page` (int) : Éléments par page (défaut: 50, max: 100)
- `search` (string) : Recherche dans nom, nom original, description
- `type` (string) : Filtrage par extension (pdf, jpg, xlsx, etc.)
- `category` (string) : Filtrage par catégorie métier
- `sort` (string) : Tri (name, date, size, type) - défaut: date
- `order` (string) : Ordre (asc, desc) - défaut: desc
**Exemple :**
```bash
GET /api/files/browse?path=entites/5/operations&search=2024&type=xlsx&page=1
```
**Réponse :**
```json
{
"status": "success",
"current_path": "entites/5/operations",
"parent_path": "entites/5",
"pagination": {
"current_page": 1,
"per_page": 50,
"total_items": 127,
"total_pages": 3,
"has_next": true,
"has_prev": false
},
"filters": {
"search": "2024",
"type": "xlsx",
"category": null,
"sort": "date",
"order": "desc"
},
"files": [
{
"id": 123,
"fichier": "planning_2024_op2644.xlsx",
"original_name": "Planning Opération 2024.xlsx",
"file_type": "xlsx",
"file_category": "planning",
"description": "Planning détaillé opération 2024",
"file_size": 1024000,
"file_path": "entites/5/operations/2644/documents/planning_2024_op2644.xlsx",
"created_at": "2025-06-22 08:30:00",
"creator_name": "Jean Dupont"
}
],
"summary": {
"total_files": 45,
"total_size": 25600000,
"by_category": {
"planning": 12,
"export": 20,
"backup": 13
}
}
}
```
#### `GET /api/files/list/{support}/{id}`
Liste des fichiers par support (entite, user, operation, passage).
**Paramètres :**
- `support` : Type de support (entite, user, operation, passage)
- `id` : ID de l'élément
- Mêmes paramètres de requête que `/browse`
**Exemple :**
```bash
GET /api/files/list/operation/2644?category=export&page=1
```
### Recherche
#### `GET /api/files/search`
Recherche globale dans tous les fichiers accessibles.
**Paramètres de requête :**
- `q` (string, requis) : Terme de recherche
- `page`, `per_page`, `type`, `category`, `sort`, `order` : Mêmes que browse
**Exemple :**
```bash
GET /api/files/search?q=planning&type=xlsx&category=planning
```
### Actions sur fichiers
#### `GET /api/files/download/{id}`
Téléchargement sécurisé d'un fichier.
**Réponse :** Fichier en téléchargement direct avec headers appropriés.
#### `DELETE /api/files/{id}`
Suppression sécurisée d'un fichier (physique + base de données).
**Réponse :**
```json
{
"status": "success",
"message": "Fichier supprimé avec succès"
}
```
#### `GET /api/files/info/{id}`
Informations détaillées d'un fichier.
**Réponse :**
```json
{
"status": "success",
"file": {
"id": 123,
"fichier": "planning_2024.xlsx",
"original_name": "Planning Opération 2024.xlsx",
"file_type": "xlsx",
"file_category": "planning",
"file_size": 1024000,
"mime_type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"description": "Planning détaillé",
"support": "operation",
"support_id": 2644,
"fk_entite": 5,
"created_at": "2025-06-22 08:30:00",
"updated_at": "2025-06-22 08:30:00",
"creator_name": "Jean Dupont",
"modifier_name": null,
"file_exists": true
}
}
```
### Statistiques
#### `GET /api/files/stats`
Statistiques d'utilisation des fichiers.
**Pour admin d'entité (rôle 2) :**
```json
{
"status": "success",
"entite_id": 5,
"storage": {
"total_files": 245,
"total_size": 157286400,
"by_support": {
"entite": { "count": 12, "size": 45000000 },
"operation": { "count": 180, "size": 98000000 },
"user": { "count": 45, "size": 12000000 },
"passage": { "count": 8, "size": 2286400 }
},
"by_category": {
"document": 25,
"export": 120,
"avatar": 45,
"photo": 55
},
"by_type": {
"xlsx": 85,
"jpg": 120,
"pdf": 40
}
}
}
```
**Pour super admin (rôle > 2) :**
```json
{
"status": "success",
"global_stats": {
"total_files": 2450,
"total_size": 1572864000,
"entites_count": 25,
"by_entite": [
{ "entite_id": 5, "files": 245, "size": 157286400 },
{ "entite_id": 12, "files": 180, "size": 98000000 }
]
}
}
```
### Métadonnées
#### `GET /api/files/metadata`
Informations sur les catégories, extensions et limites autorisées.
**Réponse :**
```json
{
"status": "success",
"categories": {
"entite": ["logo", "document", "reglement", "statut"],
"user": ["avatar", "photo"],
"operation": ["planning", "liste", "export", "backup"],
"passage": ["recu", "photo", "justificatif", "carte"]
},
"extensions": ["pdf", "jpg", "jpeg", "png", "gif", "webp", "xlsx", "xls", "json", "csv"],
"mime_types": {
"pdf": "application/pdf",
"jpg": "image/jpeg",
"xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
},
"max_file_sizes": {
"entite": 20971520, // 20 MB
"user": 5242880, // 5 MB
"operation": 20971520, // 20 MB
"passage": 10485760 // 10 MB
}
}
```
## Catégories de fichiers
### Distinction Extension vs Catégorie
- **Extension** (`file_type`) : Type technique (pdf, jpg, xlsx, png, etc.)
- **Catégorie** (`file_category`) : Type métier (logo, carte, photo, document, planning, etc.)
### Catégories par support
#### Entité
- `logo` : Logo de l'entité
- `document` : Documents généraux
- `reglement` : Règlements internes
- `statut` : Statuts de l'entité
#### Utilisateur
- `avatar` : Photo de profil
- `photo` : Photos diverses
#### Opération
- `planning` : Plannings d'opération
- `liste` : Listes diverses
- `export` : Exports de données
- `backup` : Sauvegardes automatiques
#### Passage
- `recu` : Reçus de passage
- `photo` : Photos de passage
- `justificatif` : Justificatifs divers
- `carte` : Cartes et plans
## Sécurité
### Validation des chemins
- Empêche les traversées de répertoire (`../`)
- Validation stricte selon le rôle utilisateur
- Contrôle d'accès au niveau fichier
### Logs
- Tous les téléchargements sont loggés
- Toutes les suppressions sont tracées
- Erreurs d'accès enregistrées
### Contrôles d'intégrité
- Vérification de l'existence physique des fichiers
- Validation des permissions avant chaque action
- Contrôle de cohérence base/fichiers
## Exemples d'utilisation
### Navigation dans les opérations d'une entité
```bash
GET /api/files/browse?path=entites/5/operations&sort=name&order=asc
```
### Recherche de tous les exports Excel
```bash
GET /api/files/search?q=export&type=xlsx&category=export
```
### Statistiques de stockage
```bash
GET /api/files/stats
```
### Téléchargement d'un fichier
```bash
GET /api/files/download/123
```
### Suppression d'un fichier
```bash
DELETE /api/files/123
```
## Codes d'erreur
- **401** : Non authentifié
- **403** : Accès refusé (rôle insuffisant ou fichier d'une autre entité)
- **404** : Fichier ou chemin non trouvé
- **400** : Paramètres invalides (terme de recherche manquant, etc.)
- **500** : Erreur serveur
## Migration base de données
Pour utiliser le système, exécuter la migration :
```sql
-- Ajout de la colonne file_category
ALTER TABLE `medias`
ADD COLUMN `file_category` varchar(50) DEFAULT NULL COMMENT 'Catégorie du fichier (logo, carte, photo, document, etc.)' AFTER `file_type`;
-- Index pour optimiser les requêtes
ALTER TABLE `medias`
ADD INDEX `idx_file_category` (`file_category`);
```
---
**Version** : 1.0
**Date** : Juin 2025
**Auteur** : API Geosector Team

339
api/docs/README-UPLOAD.md Normal file
View File

@@ -0,0 +1,339 @@
# Système de Gestion des Fichiers - API Geosector
## Vue d'ensemble
Ce document décrit l'organisation et la gestion des fichiers uploadés dans l'API Geosector. Le système permet de stocker et organiser différents types de fichiers par entité, utilisateur, opération et passage.
## Structure des Dossiers
```
uploads/
├── entites/
│ ├── {entite_id}/
│ │ ├── documents/ # PDF, Excel généraux de l'entité
│ │ ├── images/ # Images de l'entité
│ │ ├── users/ # Dossier pour les fichiers des utilisateurs
│ │ │ └── {user_id}/ # Images par utilisateur (avatars, etc.)
│ │ └── operations/ # Dossier pour les opérations
│ │ └── {operation_id}/
│ │ ├── documents/ # Fichiers Excel de l'opération
│ │ └── passages/ # Fichiers des passages de cette opération
│ │ └── {passage_id}/ # PDF et images par passage
│ └── temp/ # Fichiers temporaires avant validation
```
### Exemples de chemins
- Document d'entité : `uploads/entites/5/documents/reglement_2024.pdf`
- Avatar utilisateur : `uploads/entites/5/users/123/avatar.jpg`
- Excel d'opération : `uploads/entites/5/operations/2644/documents/planning.xlsx`
- Photo de passage : `uploads/entites/5/operations/2644/passages/789/photo_1.jpg`
## Structure de la Table `medias`
### Table existante enrichie
```sql
-- Structure complète de la table medias
CREATE TABLE `medias` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`support` varchar(45) NOT NULL DEFAULT '' COMMENT 'Type de support (entite, user, operation, passage)',
`support_id` int(10) unsigned NOT NULL DEFAULT 0 COMMENT 'ID de l\'élément associé',
`fichier` varchar(250) NOT NULL DEFAULT '' COMMENT 'Nom du fichier stocké',
`file_type` varchar(50) DEFAULT NULL COMMENT 'Extension du fichier (pdf, jpg, xlsx, etc.)',
`file_size` int(10) unsigned DEFAULT NULL COMMENT 'Taille du fichier en octets',
`mime_type` varchar(100) DEFAULT NULL COMMENT 'Type MIME du fichier',
`original_name` varchar(255) DEFAULT NULL COMMENT 'Nom original du fichier uploadé',
`fk_entite` int(10) unsigned DEFAULT NULL COMMENT 'ID de l\'entité propriétaire',
`fk_operation` int(10) unsigned DEFAULT NULL COMMENT 'ID de l\'opération (pour passages)',
`file_path` varchar(500) DEFAULT NULL COMMENT 'Chemin complet du fichier',
`original_width` int(10) unsigned DEFAULT NULL COMMENT 'Largeur originale de l\'image',
`original_height` int(10) unsigned DEFAULT NULL COMMENT 'Hauteur originale de l\'image',
`processed_width` int(10) unsigned DEFAULT NULL COMMENT 'Largeur après traitement',
`processed_height` int(10) unsigned DEFAULT NULL COMMENT 'Hauteur après traitement',
`is_processed` tinyint(1) unsigned DEFAULT 0 COMMENT 'Image redimensionnée (1) ou originale (0)',
`description` varchar(100) NOT NULL DEFAULT '' COMMENT 'Description du fichier',
`created_at` timestamp NOT NULL DEFAULT current_timestamp(),
`fk_user_creat` int(10) unsigned NOT NULL DEFAULT 0,
`updated_at` timestamp NULL DEFAULT NULL ON UPDATE current_timestamp(),
`fk_user_modif` int(10) unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `id_UNIQUE` (`id`),
KEY `idx_entite` (`fk_entite`),
KEY `idx_operation` (`fk_operation`),
KEY `idx_support_type` (`support`, `support_id`),
KEY `idx_file_type` (`file_type`),
CONSTRAINT `fk_medias_entite` FOREIGN KEY (`fk_entite`) REFERENCES `entites` (`id`) ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT `fk_medias_operation` FOREIGN KEY (`fk_operation`) REFERENCES `operations` (`id`) ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
```
### Migration SQL pour table existante
```sql
-- Ajout des nouvelles colonnes à la table existante
ALTER TABLE `medias`
ADD COLUMN `file_type` varchar(50) DEFAULT NULL COMMENT 'Extension du fichier (pdf, jpg, xlsx, etc.)' AFTER `fichier`,
ADD COLUMN `file_size` int(10) unsigned DEFAULT NULL COMMENT 'Taille du fichier en octets' AFTER `file_type`,
ADD COLUMN `mime_type` varchar(100) DEFAULT NULL COMMENT 'Type MIME du fichier' AFTER `file_size`,
ADD COLUMN `original_name` varchar(255) DEFAULT NULL COMMENT 'Nom original du fichier uploadé' AFTER `mime_type`,
ADD COLUMN `fk_entite` int(10) unsigned DEFAULT NULL COMMENT 'ID de l\'entité propriétaire' AFTER `support_id`,
ADD COLUMN `fk_operation` int(10) unsigned DEFAULT NULL COMMENT 'ID de l\'opération (pour passages)' AFTER `fk_entite`,
ADD COLUMN `file_path` varchar(500) DEFAULT NULL COMMENT 'Chemin complet du fichier' AFTER `original_name`,
ADD COLUMN `original_width` int(10) unsigned DEFAULT NULL COMMENT 'Largeur originale de l\'image' AFTER `file_path`,
ADD COLUMN `original_height` int(10) unsigned DEFAULT NULL COMMENT 'Hauteur originale de l\'image' AFTER `original_width`,
ADD COLUMN `processed_width` int(10) unsigned DEFAULT NULL COMMENT 'Largeur après traitement' AFTER `original_height`,
ADD COLUMN `processed_height` int(10) unsigned DEFAULT NULL COMMENT 'Hauteur après traitement' AFTER `processed_width`,
ADD COLUMN `is_processed` tinyint(1) unsigned DEFAULT 0 COMMENT 'Image redimensionnée (1) ou originale (0)' AFTER `processed_height`;
-- Ajout des index pour optimiser les requêtes
ALTER TABLE `medias`
ADD INDEX `idx_entite` (`fk_entite`),
ADD INDEX `idx_operation` (`fk_operation`),
ADD INDEX `idx_support_type` (`support`, `support_id`),
ADD INDEX `idx_file_type` (`file_type`);
-- Ajout des contraintes de clés étrangères
ALTER TABLE `medias`
ADD CONSTRAINT `fk_medias_entite` FOREIGN KEY (`fk_entite`) REFERENCES `entites` (`id`) ON UPDATE CASCADE ON DELETE CASCADE,
ADD CONSTRAINT `fk_medias_operation` FOREIGN KEY (`fk_operation`) REFERENCES `operations` (`id`) ON UPDATE CASCADE ON DELETE CASCADE;
```
## Types de Support
### 1. Entité (`support = 'entite'`)
- **Fichiers autorisés** : PDF, Excel, Images (JPG, PNG)
- **Taille max** : 20 MB
- **Usage** : Documents généraux de l'entité (règlements, statuts, etc.)
- **Chemin** : `uploads/entites/{entite_id}/documents/`
### 2. Utilisateur (`support = 'user'`)
- **Fichiers autorisés** : Images uniquement (JPG, PNG, GIF, WebP)
- **Taille max** : 5 MB
- **Usage** : Avatars, photos de profil
- **Chemin** : `uploads/entites/{entite_id}/users/{user_id}/`
- **Traitement** : Redimensionnement automatique
### 3. Opération (`support = 'operation'`)
- **Fichiers autorisés** : Excel uniquement (XLS, XLSX)
- **Taille max** : 20 MB
- **Usage** : Plannings, listes, données d'opération
- **Chemin** : `uploads/entites/{entite_id}/operations/{operation_id}/documents/`
### 4. Passage (`support = 'passage'`)
- **Fichiers autorisés** : PDF et Images (JPG, PNG, PDF)
- **Taille max** : 10 MB par fichier
- **Usage** : Reçus, photos de passage, justificatifs
- **Chemin** : `uploads/entites/{entite_id}/operations/{operation_id}/passages/{passage_id}/`
- **Traitement** : Redimensionnement automatique pour les images
## Traitement Automatique des Images
### Règles de redimensionnement
- **Dimension maximale** : 250px (hauteur ou largeur, selon la plus grande)
- **Résolution** : 72 DPI (optimisé web)
- **Préservation du ratio** : Redimensionnement proportionnel
- **Formats supportés** : JPG, PNG, GIF, WebP
- **Qualité JPEG** : 85% (bon compromis qualité/poids)
### Exemples de transformation
```
Image originale 1000x800px → Image traitée 250x200px
Image originale 600x1200px → Image traitée 125x250px
Image originale 200x150px → Pas de redimensionnement (déjà < 250px)
```
### Workflow de traitement
1. **Upload** → Validation du type MIME
2. **Analyse** → Détection des dimensions originales
3. **Traitement** → Redimensionnement si nécessaire
4. **Optimisation** → Compression et résolution web
5. **Sauvegarde** → Image optimisée + métadonnées
6. **Nettoyage** → Suppression du fichier temporaire
## API Endpoints
### Routes de gestion des fichiers
```php
// Upload de fichiers
POST /api/medias/upload
Content-Type: multipart/form-data
Body: {
"file": [fichier],
"support": "entite|user|operation|passage",
"support_id": 123,
"description": "Description du fichier"
}
// Récupération d'un fichier
GET /api/medias/{id}
// Liste des fichiers par support
GET /api/medias/list/{support}/{support_id}
// Suppression d'un fichier
DELETE /api/medias/{id}
```
### Exemples de requêtes
#### Upload d'un avatar utilisateur
```bash
curl -X POST "https://api.geosector.fr/medias/upload" \
-H "Authorization: Bearer {token}" \
-F "file=@avatar.jpg" \
-F "support=user" \
-F "support_id=123" \
-F "description=Avatar utilisateur"
```
#### Upload d'une photo de passage
```bash
curl -X POST "https://api.geosector.fr/medias/upload" \
-H "Authorization: Bearer {token}" \
-F "file=@photo_passage.jpg" \
-F "support=passage" \
-F "support_id=789" \
-F "description=Photo du passage"
```
## Sécurité et Contrôles
### Validation des fichiers
- **Types MIME** : Vérification stricte du type de fichier
- **Extensions** : Validation de l'extension par rapport au contenu
- **Taille** : Limite selon le type de support
- **Contenu** : Scan antivirus recommandé en production
### Contrôles d'accès
- **Authentification** : Token JWT requis
- **Autorisation** : Utilisateur ne peut accéder qu'aux fichiers de son entité
- **Vérification** : Contrôle que l'utilisateur appartient à l'entité du fichier
- **Logs** : Traçabilité complète des uploads et accès
### Nommage des fichiers
```php
// Format : {timestamp}_{random}_{sanitized_name}.{extension}
// Exemple : 1640995200_a1b2c3_document_reglement.pdf
```
## Gestion des Erreurs
### Codes d'erreur HTTP
- **400** : Fichier invalide ou paramètres manquants
- **401** : Non authentifié
- **403** : Accès refusé à cette entité
- **413** : Fichier trop volumineux
- **415** : Type de fichier non supporté
- **500** : Erreur serveur lors du traitement
### Messages d'erreur
```json
{
"status": "error",
"message": "Type de fichier non autorisé pour ce support",
"code": "INVALID_FILE_TYPE",
"allowed_types": ["jpg", "png", "gif", "webp"]
}
```
## Maintenance et Nettoyage
### Nettoyage automatique
- **Fichiers temporaires** : Suppression après 24h
- **Fichiers orphelins** : Détection et suppression des fichiers sans référence en base
- **Anciennes opérations** : Suppression en cascade lors de la suppression d'une opération
### Commandes de maintenance
```bash
# Nettoyage des fichiers temporaires
php scripts/cleanup_temp_files.php
# Détection des fichiers orphelins
php scripts/find_orphan_files.php
# Statistiques d'utilisation
php scripts/storage_stats.php
```
## Performances et Optimisation
### Optimisations
- **CDN** : Recommandé pour la distribution des fichiers
- **Cache** : Headers de cache appropriés pour les fichiers statiques
- **Compression** : Gzip pour les réponses API
- **Index** : Index optimisés sur la table medias
### Monitoring
- **Espace disque** : Surveillance de l'utilisation
- **Performance** : Temps de traitement des images
- **Erreurs** : Logs des échecs d'upload et de traitement
## Exemples d'Utilisation
### Cas d'usage typiques
1. **Upload d'avatar utilisateur**
- Fichier JPG de 2MB
- Redimensionnement automatique à 250x250px
- Stockage dans `uploads/entites/5/users/123/`
2. **Document d'opération**
- Fichier Excel de planning
- Stockage dans `uploads/entites/5/operations/2644/documents/`
- Pas de traitement (fichier conservé tel quel)
3. **Photo de passage**
- Photo JPG de 8MB prise sur mobile
- Redimensionnement automatique à 250px max
- Stockage dans `uploads/entites/5/operations/2644/passages/789/`
### Intégration frontend
```javascript
// Upload avec progress
const uploadFile = async (file, support, supportId, description) => {
const formData = new FormData();
formData.append('file', file);
formData.append('support', support);
formData.append('support_id', supportId);
formData.append('description', description);
const response = await fetch('/api/medias/upload', {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
},
body: formData,
});
return response.json();
};
```
---
**Version** : 1.0
**Date** : Juin 2025
**Auteur** : API Geosector Team

View File

@@ -237,17 +237,37 @@ CREATE TABLE `entites` (
CREATE TABLE `medias` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`support` varchar(45) NOT NULL DEFAULT '',
`support_id` int(10) unsigned NOT NULL DEFAULT 0,
`fichier` varchar(250) NOT NULL DEFAULT '',
`description` varchar(100) NOT NULL DEFAULT '',
`support` varchar(45) NOT NULL DEFAULT '' COMMENT 'Type de support (entite, user, operation, passage)',
`support_id` int(10) unsigned NOT NULL DEFAULT 0 COMMENT 'ID de élément associé',
`fichier` varchar(250) NOT NULL DEFAULT '' COMMENT 'Nom du fichier stocké',
`file_type` varchar(50) DEFAULT NULL COMMENT 'Extension du fichier (pdf, jpg, xlsx, etc.)',
`file_category` varchar(50) DEFAULT NULL COMMENT 'export, logo, carte, etc.',
`file_size` int(10) unsigned DEFAULT NULL COMMENT 'Taille du fichier en octets',
`mime_type` varchar(100) DEFAULT NULL COMMENT 'Type MIME du fichier',
`original_name` varchar(255) DEFAULT NULL COMMENT 'Nom original du fichier uploadé',
`fk_entite` int(10) unsigned DEFAULT NULL COMMENT 'ID de entité propriétaire',
`fk_operation` int(10) unsigned DEFAULT NULL COMMENT 'ID de opération (pour passages)',
`file_path` varchar(500) DEFAULT NULL COMMENT 'Chemin complet du fichier',
`original_width` int(10) unsigned DEFAULT NULL COMMENT 'Largeur originale de image',
`original_height` int(10) unsigned DEFAULT NULL COMMENT 'Hauteur originale de image',
`processed_width` int(10) unsigned DEFAULT NULL COMMENT 'Largeur après traitement',
`processed_height` int(10) unsigned DEFAULT NULL COMMENT 'Hauteur après traitement',
`is_processed` tinyint(1) unsigned DEFAULT 0 COMMENT 'Image redimensionnée (1) ou originale (0)',
`description` varchar(100) NOT NULL DEFAULT '' COMMENT 'Description du fichier',
`created_at` timestamp NOT NULL DEFAULT current_timestamp(),
`fk_user_creat` int(10) unsigned NOT NULL DEFAULT 0,
`updated_at` timestamp NULL DEFAULT NULL ON UPDATE current_timestamp(),
`fk_user_modif` int(10) unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `id_UNIQUE` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=176 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci `PAGE_COMPRESSED`='ON';
UNIQUE KEY `id_UNIQUE` (`id`),
KEY `idx_entite` (`fk_entite`),
KEY `idx_operation` (`fk_operation`),
KEY `idx_support_type` (`support`, `support_id`),
KEY `idx_file_type` (`file_type`),
KEY `idx_file_category` (`file_category`),
CONSTRAINT `fk_medias_entite` FOREIGN KEY (`fk_entite`) REFERENCES `entites` (`id`) ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT `fk_medias_operation` FOREIGN KEY (`fk_operation`) REFERENCES `operations` (`id`) ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `ope_pass` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
@@ -375,22 +395,6 @@ CREATE TABLE `ope_users_sectors` (
CONSTRAINT `ope_users_sectors_ibfk_3` FOREIGN KEY (`fk_sector`) REFERENCES `ope_sectors` (`id`) ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=48082 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci `PAGE_COMPRESSED`='ON';
CREATE TABLE `ope_users_suivis` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`fk_operation` int(10) unsigned NOT NULL DEFAULT 0,
`fk_user` int(10) unsigned NOT NULL DEFAULT 0,
`date_suivi` timestamp NOT NULL DEFAULT current_timestamp() COMMENT 'Date du suivi',
`gps_lat` varchar(20) NOT NULL DEFAULT '',
`gps_lng` varchar(20) NOT NULL DEFAULT '',
`vitesse` varchar(20) NOT NULL DEFAULT '',
`created_at` timestamp NOT NULL DEFAULT current_timestamp() COMMENT 'Date de création',
`fk_user_creat` int(10) unsigned NOT NULL DEFAULT 0,
`updated_at` timestamp NULL DEFAULT NULL ON UPDATE current_timestamp() COMMENT 'Date de modification',
`fk_user_modif` int(10) unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `id_UNIQUE` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci `PAGE_COMPRESSED`='ON';
CREATE TABLE `operations` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`fk_entite` int(10) unsigned NOT NULL DEFAULT 1,