- Ajout système complet de gestion des secteurs avec contours géographiques - Import des contours départementaux depuis GeoJSON - API REST pour la gestion des secteurs (/api/sectors) - Service de géolocalisation pour déterminer les secteurs - Migration base de données avec tables x_departements_contours et sectors_adresses - Interface Flutter pour visualisation et gestion des secteurs - Ajout thème sombre dans l'application - Corrections diverses et optimisations 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
679 lines
16 KiB
Markdown
Executable File
679 lines
16 KiB
Markdown
Executable File
# API Endpoints de GEOSECTOR
|
|
|
|
## Description générale
|
|
|
|
GEOSECTOR utilise une API REST modulaire développée en PHP 8.3 pour communiquer avec le backend. Cette API permet la gestion des utilisateurs, des opérations, des secteurs et des passages. Ce document décrit tous les endpoints disponibles, leurs paramètres et leurs réponses.
|
|
|
|
## Configuration de base
|
|
|
|
- **URL de base**: `https://app.geosector.fr/api/geo`
|
|
- **Authentification**: Session PHP avec token Bearer
|
|
- **Format des réponses**: JSON
|
|
- **Timeouts**:
|
|
- Connexion: 5 secondes
|
|
- Réception: 30 secondes
|
|
|
|
## Headers par défaut
|
|
|
|
```
|
|
Content-Type: application/json
|
|
X-App-Identifier: app.geosector.fr
|
|
X-Client-Type: web/mobile (détecté automatiquement)
|
|
Accept: application/json
|
|
```
|
|
|
|
## Authentification
|
|
|
|
### Login
|
|
|
|
Permet à un utilisateur de se connecter et d'obtenir un ID de session.
|
|
|
|
- **URL**: `/login`
|
|
- **Méthode**: `POST`
|
|
- **Authentification requise**: Non
|
|
- **Paramètres**:
|
|
|
|
| Paramètre | Type | Description |
|
|
|-----------|--------|--------------------------------------------|
|
|
| username | string | Nom d'utilisateur |
|
|
| password | string | Mot de passe |
|
|
| type | string | Type de connexion ('admin' ou 'user') |
|
|
|
|
- **Réponse réussie**:
|
|
```json
|
|
{
|
|
"status": "success",
|
|
"message": "Connexion réussie",
|
|
"session_id": "session_token_here",
|
|
"user": {
|
|
"id": 123,
|
|
"email": "user@example.com",
|
|
"name": "Nom Utilisateur",
|
|
"username": "username",
|
|
"first_name": "Prénom",
|
|
"sect_name": "Nom section",
|
|
"fk_role": 1,
|
|
"interface": "user"
|
|
},
|
|
"operations": [...],
|
|
"sectors": [...],
|
|
"passages": [...]
|
|
}
|
|
```
|
|
|
|
- **Réponse d'erreur**:
|
|
```json
|
|
{
|
|
"status": "error",
|
|
"message": "Identifiants incorrects"
|
|
}
|
|
```
|
|
|
|
### Logout
|
|
|
|
Déconnecte l'utilisateur en invalidant sa session.
|
|
|
|
- **URL**: `/logout`
|
|
- **Méthode**: `POST`
|
|
- **Authentification requise**: Oui
|
|
- **Paramètres**: Aucun
|
|
- **Réponse réussie**:
|
|
```json
|
|
{
|
|
"status": "success",
|
|
"message": "Déconnexion réussie"
|
|
}
|
|
```
|
|
|
|
### Register
|
|
|
|
Enregistre un nouvel administrateur d'amicale.
|
|
|
|
- **URL**: `/register`
|
|
- **Méthode**: `POST`
|
|
- **Authentification requise**: Non
|
|
- **Paramètres**:
|
|
|
|
| Paramètre | Type | Description |
|
|
|---------------|--------|----------------------------|
|
|
| email | string | Email |
|
|
| name | string | Nom |
|
|
| amicale_name | string | Nom de l'amicale |
|
|
| postal_code | string | Code postal |
|
|
| city_name | string | Nom de la ville |
|
|
|
|
- **Réponse réussie**:
|
|
```json
|
|
{
|
|
"status": "success",
|
|
"message": "Inscription réussie",
|
|
"user_id": 123,
|
|
"session_id": "session_token_here",
|
|
"session_expiry": "2025-04-20T12:00:00Z"
|
|
}
|
|
```
|
|
|
|
## Gestion des utilisateurs
|
|
|
|
### Récupérer tous les utilisateurs
|
|
|
|
- **URL**: `/users`
|
|
- **Méthode**: `GET`
|
|
- **Authentification requise**: Oui
|
|
- **Paramètres**: Aucun
|
|
- **Réponse**:
|
|
```json
|
|
[
|
|
{
|
|
"id": 123,
|
|
"email": "user@example.com",
|
|
"name": "Nom Utilisateur",
|
|
"role": 1,
|
|
"isActive": true
|
|
},
|
|
...
|
|
]
|
|
```
|
|
|
|
### Récupérer un utilisateur par ID
|
|
|
|
- **URL**: `/users/{id}`
|
|
- **Méthode**: `GET`
|
|
- **Authentification requise**: Oui
|
|
- **Paramètres**: ID dans l'URL
|
|
- **Réponse**:
|
|
```json
|
|
{
|
|
"id": 123,
|
|
"email": "user@example.com",
|
|
"name": "Nom Utilisateur",
|
|
"role": 1,
|
|
"isActive": true
|
|
}
|
|
```
|
|
|
|
### Créer un utilisateur
|
|
|
|
- **URL**: `/users`
|
|
- **Méthode**: `POST`
|
|
- **Authentification requise**: Oui (Admin)
|
|
- **Paramètres**:
|
|
|
|
| Paramètre | Type | Description |
|
|
|-----------|---------|------------------------------|
|
|
| email | string | Email de l'utilisateur |
|
|
| name | string | Nom de l'utilisateur |
|
|
| role | integer | Rôle (1=user, 2/4/9=admin) |
|
|
|
|
- **Réponse**:
|
|
```json
|
|
{
|
|
"id": 123,
|
|
"email": "user@example.com",
|
|
"name": "Nom Utilisateur",
|
|
"role": 1,
|
|
"isActive": true
|
|
}
|
|
```
|
|
|
|
### Mettre à jour un utilisateur
|
|
|
|
- **URL**: `/users/{id}`
|
|
- **Méthode**: `PUT`
|
|
- **Authentification requise**: Oui (Admin ou propriétaire du compte)
|
|
- **Paramètres**: ID dans l'URL + corps de la requête
|
|
|
|
| Paramètre | Type | Description |
|
|
|-----------|---------|----------------------------------|
|
|
| email | string | Email de l'utilisateur |
|
|
| name | string | Nom de l'utilisateur |
|
|
| role | integer | Rôle (1=user, 2/4/9=admin) |
|
|
| isActive | boolean | Statut de l'utilisateur |
|
|
|
|
- **Réponse**:
|
|
```json
|
|
{
|
|
"id": 123,
|
|
"email": "user@example.com",
|
|
"name": "Nom Utilisateur",
|
|
"role": 1,
|
|
"isActive": true
|
|
}
|
|
```
|
|
|
|
### Supprimer un utilisateur
|
|
|
|
- **URL**: `/users/{id}`
|
|
- **Méthode**: `DELETE`
|
|
- **Authentification requise**: Oui (Admin)
|
|
- **Paramètres**: ID dans l'URL
|
|
- **Réponse**:
|
|
```json
|
|
{
|
|
"status": "success",
|
|
"message": "Utilisateur supprimé avec succès"
|
|
}
|
|
```
|
|
|
|
## Gestion des opérations
|
|
|
|
### Récupérer toutes les opérations
|
|
|
|
- **URL**: `/operations`
|
|
- **Méthode**: `GET`
|
|
- **Authentification requise**: Oui
|
|
- **Filtres optionnels**:
|
|
|
|
| Paramètre | Type | Description |
|
|
|-----------|---------|----------------------------------------|
|
|
| active | boolean | Filtrer par statut actif/inactif |
|
|
|
|
- **Réponse**:
|
|
```json
|
|
[
|
|
{
|
|
"id": 456,
|
|
"libelle": "Opération 2025",
|
|
"date_deb": "2025-01-01",
|
|
"date_fin": "2025-12-31",
|
|
"active": true
|
|
},
|
|
...
|
|
]
|
|
```
|
|
|
|
### Récupérer une opération par ID
|
|
|
|
- **URL**: `/operations/{id}`
|
|
- **Méthode**: `GET`
|
|
- **Authentification requise**: Oui
|
|
- **Paramètres**: ID dans l'URL
|
|
- **Réponse**:
|
|
```json
|
|
{
|
|
"id": 456,
|
|
"libelle": "Opération 2025",
|
|
"date_deb": "2025-01-01",
|
|
"date_fin": "2025-12-31",
|
|
"active": true,
|
|
"sectors": [
|
|
{
|
|
"id": 789,
|
|
"libelle": "Secteur Nord",
|
|
"color": "#FF5733",
|
|
"sector": "POLYGON((...))"
|
|
},
|
|
...
|
|
]
|
|
}
|
|
```
|
|
|
|
### Créer une opération
|
|
|
|
- **URL**: `/operations`
|
|
- **Méthode**: `POST`
|
|
- **Authentification requise**: Oui (Admin)
|
|
- **Paramètres**:
|
|
|
|
| Paramètre | Type | Description |
|
|
|-----------|---------|----------------------------------|
|
|
| libelle | string | Nom de l'opération |
|
|
| date_deb | string | Date de début (YYYY-MM-DD) |
|
|
| date_fin | string | Date de fin (YYYY-MM-DD) |
|
|
| active | boolean | Statut de l'opération |
|
|
|
|
- **Réponse**:
|
|
```json
|
|
{
|
|
"id": 456,
|
|
"libelle": "Opération 2025",
|
|
"date_deb": "2025-01-01",
|
|
"date_fin": "2025-12-31",
|
|
"active": true
|
|
}
|
|
```
|
|
|
|
### Mettre à jour une opération
|
|
|
|
- **URL**: `/operations/{id}`
|
|
- **Méthode**: `PUT`
|
|
- **Authentification requise**: Oui (Admin)
|
|
- **Paramètres**: ID dans l'URL + corps de la requête
|
|
|
|
| Paramètre | Type | Description |
|
|
|-----------|---------|----------------------------------|
|
|
| libelle | string | Nom de l'opération |
|
|
| date_deb | string | Date de début (YYYY-MM-DD) |
|
|
| date_fin | string | Date de fin (YYYY-MM-DD) |
|
|
| active | boolean | Statut de l'opération |
|
|
|
|
- **Réponse**:
|
|
```json
|
|
{
|
|
"id": 456,
|
|
"libelle": "Opération 2025",
|
|
"date_deb": "2025-01-01",
|
|
"date_fin": "2025-12-31",
|
|
"active": true
|
|
}
|
|
```
|
|
|
|
## Gestion des secteurs
|
|
|
|
### Récupérer tous les secteurs
|
|
|
|
- **URL**: `/sectors`
|
|
- **Méthode**: `GET`
|
|
- **Authentification requise**: Oui
|
|
- **Filtres optionnels**:
|
|
|
|
| Paramètre | Type | Description |
|
|
|--------------|---------|----------------------------------------|
|
|
| operation_id | integer | Filtrer par ID d'opération |
|
|
|
|
- **Réponse**:
|
|
```json
|
|
[
|
|
{
|
|
"id": 789,
|
|
"libelle": "Secteur Nord",
|
|
"color": "#FF5733",
|
|
"sector": "POLYGON((...))"
|
|
},
|
|
...
|
|
]
|
|
```
|
|
|
|
### Récupérer un secteur par ID
|
|
|
|
- **URL**: `/sectors/{id}`
|
|
- **Méthode**: `GET`
|
|
- **Authentification requise**: Oui
|
|
- **Paramètres**: ID dans l'URL
|
|
- **Réponse**:
|
|
```json
|
|
{
|
|
"id": 789,
|
|
"libelle": "Secteur Nord",
|
|
"color": "#FF5733",
|
|
"sector": "POLYGON((...))",
|
|
"adresses": [
|
|
{
|
|
"id": 101,
|
|
"numero": "12",
|
|
"rue": "Rue des Lilas",
|
|
"cp": "75001",
|
|
"ville": "Paris",
|
|
"gps_lat": "48.8566",
|
|
"gps_lng": "2.3522"
|
|
},
|
|
...
|
|
]
|
|
}
|
|
```
|
|
|
|
### Créer un secteur
|
|
|
|
- **URL**: `/sectors`
|
|
- **Méthode**: `POST`
|
|
- **Authentification requise**: Oui (Admin)
|
|
- **Paramètres**:
|
|
|
|
| Paramètre | Type | Description |
|
|
|--------------|---------|----------------------------------|
|
|
| libelle | string | Nom du secteur |
|
|
| color | string | Couleur au format hexadécimal |
|
|
| sector | string | Coordonnées WKT du polygone |
|
|
| operation_id | integer | ID de l'opération associée |
|
|
|
|
- **Réponse**:
|
|
```json
|
|
{
|
|
"id": 789,
|
|
"libelle": "Secteur Nord",
|
|
"color": "#FF5733",
|
|
"sector": "POLYGON((...))"
|
|
}
|
|
```
|
|
|
|
### Mettre à jour un secteur
|
|
|
|
- **URL**: `/sectors/{id}`
|
|
- **Méthode**: `PUT`
|
|
- **Authentification requise**: Oui (Admin)
|
|
- **Paramètres**: ID dans l'URL + corps de la requête
|
|
|
|
| Paramètre | Type | Description |
|
|
|--------------|---------|----------------------------------|
|
|
| libelle | string | Nom du secteur |
|
|
| color | string | Couleur au format hexadécimal |
|
|
| sector | string | Coordonnées WKT du polygone |
|
|
|
|
- **Réponse**:
|
|
```json
|
|
{
|
|
"id": 789,
|
|
"libelle": "Secteur Nord",
|
|
"color": "#FF5733",
|
|
"sector": "POLYGON((...))"
|
|
}
|
|
```
|
|
|
|
## Gestion des passages
|
|
|
|
### Récupérer tous les passages
|
|
|
|
- **URL**: `/passages`
|
|
- **Méthode**: `GET`
|
|
- **Authentification requise**: Oui
|
|
- **Filtres optionnels**:
|
|
|
|
| Paramètre | Type | Description |
|
|
|--------------|---------|----------------------------------------|
|
|
| operation_id | integer | Filtrer par ID d'opération |
|
|
| sector_id | integer | Filtrer par ID de secteur |
|
|
| user_id | integer | Filtrer par ID d'utilisateur |
|
|
| date_start | string | Date de début (YYYY-MM-DD) |
|
|
| date_end | string | Date de fin (YYYY-MM-DD) |
|
|
|
|
- **Réponse**:
|
|
```json
|
|
[
|
|
{
|
|
"id": 1001,
|
|
"fk_operation": 456,
|
|
"fk_sector": 789,
|
|
"fk_user": 123,
|
|
"date_eve": "2025-01-15T14:30:00Z",
|
|
"montant": 25.50,
|
|
"fk_type": 1,
|
|
"fk_type_reglement": 2,
|
|
"numero": "12",
|
|
"rue": "Rue des Lilas",
|
|
"ville": "Paris"
|
|
},
|
|
...
|
|
]
|
|
```
|
|
|
|
### Récupérer un passage par ID
|
|
|
|
- **URL**: `/passages/{id}`
|
|
- **Méthode**: `GET`
|
|
- **Authentification requise**: Oui
|
|
- **Paramètres**: ID dans l'URL
|
|
- **Réponse**:
|
|
```json
|
|
{
|
|
"id": 1001,
|
|
"fk_operation": 456,
|
|
"fk_sector": 789,
|
|
"fk_user": 123,
|
|
"date_eve": "2025-01-15T14:30:00Z",
|
|
"montant": 25.50,
|
|
"fk_type": 1,
|
|
"fk_type_reglement": 2,
|
|
"numero": "12",
|
|
"rue": "Rue des Lilas",
|
|
"ville": "Paris",
|
|
"historique": [
|
|
{
|
|
"date_histo": "2025-01-15T14:30:00Z",
|
|
"sujet": "Création",
|
|
"remarque": "Passage créé"
|
|
},
|
|
...
|
|
],
|
|
"recus": [
|
|
{
|
|
"chemin": "/recus/2025/...",
|
|
"nom_recu": "recu_20250115_1001.pdf",
|
|
"date_recu": "2025-01-15T14:35:00Z"
|
|
},
|
|
...
|
|
]
|
|
}
|
|
```
|
|
|
|
### Créer un passage
|
|
|
|
- **URL**: `/passages`
|
|
- **Méthode**: `POST`
|
|
- **Authentification requise**: Oui
|
|
- **Paramètres**:
|
|
|
|
| Paramètre | Type | Description |
|
|
|-------------------|---------|----------------------------------|
|
|
| fk_operation | integer | ID de l'opération |
|
|
| fk_sector | integer | ID du secteur |
|
|
| date_eve | string | Date du passage (ISO 8601) |
|
|
| montant | number | Montant collecté |
|
|
| fk_type | integer | Type de passage (1-6) |
|
|
| fk_type_reglement | integer | Type de règlement (0-3) |
|
|
| numero | string | Numéro de rue |
|
|
| rue | string | Nom de la rue |
|
|
| ville | string | Ville |
|
|
| send_email | boolean | Envoyer un reçu par email |
|
|
| email | string | Email pour l'envoi du reçu |
|
|
| send_sms | boolean | Envoyer un SMS de confirmation |
|
|
| telephone | string | Numéro pour l'envoi du SMS |
|
|
|
|
- **Réponse**:
|
|
```json
|
|
{
|
|
"id": 1001,
|
|
"fk_operation": 456,
|
|
"fk_sector": 789,
|
|
"fk_user": 123,
|
|
"date_eve": "2025-01-15T14:30:00Z",
|
|
"montant": 25.50,
|
|
"fk_type": 1,
|
|
"fk_type_reglement": 2,
|
|
"numero": "12",
|
|
"rue": "Rue des Lilas",
|
|
"ville": "Paris",
|
|
"recu_url": "/api/geo/recus/2025/recu_20250115_1001.pdf"
|
|
}
|
|
```
|
|
|
|
### Mettre à jour un passage
|
|
|
|
- **URL**: `/passages/{id}`
|
|
- **Méthode**: `PUT`
|
|
- **Authentification requise**: Oui
|
|
- **Paramètres**: ID dans l'URL + corps de la requête
|
|
|
|
| Paramètre | Type | Description |
|
|
|-------------------|---------|----------------------------------|
|
|
| fk_type | integer | Type de passage (1-6) |
|
|
| fk_type_reglement | integer | Type de règlement (0-3) |
|
|
| montant | number | Montant collecté |
|
|
| remarque | string | Remarque sur la modification |
|
|
|
|
- **Réponse**:
|
|
```json
|
|
{
|
|
"id": 1001,
|
|
"fk_operation": 456,
|
|
"fk_sector": 789,
|
|
"fk_user": 123,
|
|
"date_eve": "2025-01-15T14:30:00Z",
|
|
"montant": 30.00,
|
|
"fk_type": 1,
|
|
"fk_type_reglement": 2,
|
|
"numero": "12",
|
|
"rue": "Rue des Lilas",
|
|
"ville": "Paris"
|
|
}
|
|
```
|
|
|
|
## Synchronisation des données
|
|
|
|
### Synchronisation générale
|
|
|
|
Permet de synchroniser plusieurs types de données en une seule requête.
|
|
|
|
- **URL**: `/data/sync`
|
|
- **Méthode**: `POST`
|
|
- **Authentification requise**: Oui
|
|
- **Paramètres**:
|
|
|
|
| Paramètre | Type | Description |
|
|
|------------|-------|------------------------------------------|
|
|
| users | array | Liste des utilisateurs à synchroniser |
|
|
| operations | array | Liste des opérations à synchroniser |
|
|
| sectors | array | Liste des secteurs à synchroniser |
|
|
| passages | array | Liste des passages à synchroniser |
|
|
|
|
- **Réponse**:
|
|
```json
|
|
{
|
|
"status": "success",
|
|
"synced": {
|
|
"users": 5,
|
|
"operations": 2,
|
|
"sectors": 3,
|
|
"passages": 10
|
|
},
|
|
"errors": []
|
|
}
|
|
```
|
|
|
|
## Services géographiques
|
|
|
|
### Recherche d'adresses
|
|
|
|
Recherche des adresses à partir de la base nationale des adresses.
|
|
|
|
- **URL**: `/geo/addresses/search`
|
|
- **Méthode**: `GET`
|
|
- **Authentification requise**: Oui
|
|
- **Paramètres**:
|
|
|
|
| Paramètre | Type | Description |
|
|
|-----------|--------|--------------------------------------------|
|
|
| q | string | Texte de recherche (rue, code postal...) |
|
|
| limit | integer| Nombre maximum de résultats (défaut: 10) |
|
|
|
|
- **Réponse**:
|
|
```json
|
|
[
|
|
{
|
|
"id": "ADDRESS-ID",
|
|
"numero": "12",
|
|
"rue": "Rue des Lilas",
|
|
"cp": "75001",
|
|
"ville": "Paris",
|
|
"latitude": 48.8566,
|
|
"longitude": 2.3522
|
|
},
|
|
...
|
|
]
|
|
```
|
|
|
|
### Récupérer les rues dans un secteur
|
|
|
|
- **URL**: `/geo/sectors/{id}/streets`
|
|
- **Méthode**: `GET`
|
|
- **Authentification requise**: Oui
|
|
- **Paramètres**: ID du secteur dans l'URL
|
|
- **Réponse**:
|
|
```json
|
|
[
|
|
{
|
|
"id": "STREET-ID",
|
|
"name": "Rue des Lilas",
|
|
"city": "Paris",
|
|
"osm_lat": 48.8566,
|
|
"osm_lng": 2.3522
|
|
},
|
|
...
|
|
]
|
|
```
|
|
|
|
## Codes d'erreur
|
|
|
|
| Code | Description |
|
|
|------|--------------------------------------------|
|
|
| 400 | Requête invalide (paramètres manquants) |
|
|
| 401 | Non authentifié |
|
|
| 403 | Non autorisé (droits insuffisants) |
|
|
| 404 | Ressource introuvable |
|
|
| 409 | Conflit (ex: email déjà utilisé) |
|
|
| 422 | Erreur de validation des données |
|
|
| 500 | Erreur serveur |
|
|
|
|
## Notes d'utilisation
|
|
|
|
1. **Authentification**: Après connexion, l'ID de session doit être fourni dans l'en-tête `Authorization` sous forme de `Bearer {session_id}` pour toutes les requêtes authentifiées.
|
|
|
|
2. **Filtrage**: La plupart des endpoints GET supportent des paramètres de filtrage additionnels.
|
|
|
|
3. **Pagination**: Les endpoints retournant des listes importantes supportent la pagination via les paramètres `page` et `limit`.
|
|
|
|
4. **Synchronisation**: La synchronisation des données permet de travailler hors ligne et de synchroniser lors du retour en ligne.
|
|
|
|
5. **Reçus PDF**: Les passages créés peuvent générer automatiquement des reçus PDF qui peuvent être envoyés par email ou SMS.
|
|
|
|
6. **Données géographiques**: Les secteurs sont stockés au format WKT (Well-Known Text) pour les polygones.
|