mirror of
https://forge.chapril.org/tykayn/osm-commerces
synced 2025-10-04 17:04:53 +02:00
export command et enddpoint pour les villes
This commit is contained in:
parent
c81affd3e3
commit
46d3b21cf6
4 changed files with 663 additions and 0 deletions
220
docs/api-stats-export.md
Normal file
220
docs/api-stats-export.md
Normal file
|
@ -0,0 +1,220 @@
|
|||
# API - Export des objets Stats
|
||||
|
||||
## Endpoint
|
||||
|
||||
```
|
||||
GET /api/v1/stats/export
|
||||
```
|
||||
|
||||
## Description
|
||||
|
||||
Cet endpoint permet d'exporter les objets Stats au format JSON avec leurs propriétés de nom et de décomptes, similaire à la commande `app:export-stats`.
|
||||
|
||||
## Paramètres de requête
|
||||
|
||||
| Paramètre | Type | Défaut | Description |
|
||||
|-----------|------|--------|-------------|
|
||||
| `zone` | string | - | Code INSEE spécifique à exporter (optionnel) |
|
||||
| `pretty` | boolean | false | Formater le JSON avec indentation |
|
||||
| `include_followups` | boolean | true | Inclure les données de followup |
|
||||
| `include_places` | boolean | false | Inclure les données des lieux (peut être volumineux) |
|
||||
|
||||
## Exemples d'utilisation
|
||||
|
||||
### Export de toutes les zones
|
||||
```bash
|
||||
curl "https://osm-commerces.cipherbliss.com/api/v1/stats/export"
|
||||
```
|
||||
|
||||
### Export avec formatage JSON
|
||||
```bash
|
||||
curl "https://osm-commerces.cipherbliss.com/api/v1/stats/export?pretty=true"
|
||||
```
|
||||
|
||||
### Export d'une zone spécifique
|
||||
```bash
|
||||
curl "https://osm-commerces.cipherbliss.com/api/v1/stats/export?zone=75056"
|
||||
```
|
||||
|
||||
### Export d'une zone avec formatage et sans followups
|
||||
```bash
|
||||
curl "https://osm-commerces.cipherbliss.com/api/v1/stats/export?zone=75056&pretty=true&include_followups=false"
|
||||
```
|
||||
|
||||
### Export complet avec lieux
|
||||
```bash
|
||||
curl "https://osm-commerces.cipherbliss.com/api/v1/stats/export?pretty=true&include_places=true"
|
||||
```
|
||||
|
||||
## Réponse
|
||||
|
||||
### Succès (200 OK)
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"zone": "75056",
|
||||
"name": "Paris",
|
||||
"dateCreated": "2024-01-15 10:30:00",
|
||||
"dateModified": "2024-01-20 14:45:00",
|
||||
"population": 2161000,
|
||||
"budgetAnnuel": "8500000000",
|
||||
"siren": 200054781,
|
||||
"codeEpci": 200054781,
|
||||
"codesPostaux": "75001;75002;75003;...",
|
||||
"decomptes": {
|
||||
"placesCount": 1250,
|
||||
"avecHoraires": 980,
|
||||
"avecAdresse": 1200,
|
||||
"avecSite": 850,
|
||||
"avecAccessibilite": 450,
|
||||
"avecNote": 320,
|
||||
"completionPercent": 75,
|
||||
"placesCountReal": 1250
|
||||
},
|
||||
"followups": [
|
||||
{
|
||||
"name": "fire_hydrant_count",
|
||||
"measure": 1250,
|
||||
"date": "2024-01-20 14:45:00"
|
||||
},
|
||||
{
|
||||
"name": "fire_hydrant_completion",
|
||||
"measure": 85.5,
|
||||
"date": "2024-01-20 14:45:00"
|
||||
}
|
||||
],
|
||||
"places": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Boulangerie du Centre",
|
||||
"mainTag": "shop",
|
||||
"osmId": 123456,
|
||||
"osmKind": "node",
|
||||
"email": "contact@boulangerie.fr",
|
||||
"note": "Boulangerie artisanale",
|
||||
"zipCode": "75001",
|
||||
"siret": "12345678901234",
|
||||
"lat": 48.8566,
|
||||
"lon": 2.3522,
|
||||
"hasOpeningHours": true,
|
||||
"hasAddress": true,
|
||||
"hasWebsite": true,
|
||||
"hasWheelchair": false,
|
||||
"hasNote": true,
|
||||
"completionPercentage": 85
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### Erreur - Zone non trouvée (404 Not Found)
|
||||
|
||||
```json
|
||||
{
|
||||
"error": "Aucun objet Stats trouvé",
|
||||
"message": "Aucune zone trouvée pour le code INSEE: 99999"
|
||||
}
|
||||
```
|
||||
|
||||
### Erreur - Erreur serveur (500 Internal Server Error)
|
||||
|
||||
```json
|
||||
{
|
||||
"error": "Erreur lors de l'export",
|
||||
"message": "Description de l'erreur"
|
||||
}
|
||||
```
|
||||
|
||||
## Headers de réponse
|
||||
|
||||
| Header | Description |
|
||||
|--------|-------------|
|
||||
| `Content-Type` | `application/json` |
|
||||
| `Content-Disposition` | `attachment; filename="stats_export.json"` |
|
||||
| `X-Export-Count` | Nombre d'objets exportés |
|
||||
| `X-Export-Generated` | Date/heure de génération (format ISO 8601) |
|
||||
| `X-Export-Zone` | Code INSEE si export d'une zone spécifique |
|
||||
|
||||
## Structure des données
|
||||
|
||||
### Informations générales
|
||||
- `id` : Identifiant unique de l'objet Stats
|
||||
- `zone` : Code INSEE de la zone
|
||||
- `name` : Nom de la ville/zone
|
||||
- `dateCreated` : Date de création
|
||||
- `dateModified` : Date de dernière modification
|
||||
|
||||
### Données démographiques et administratives
|
||||
- `population` : Population de la zone
|
||||
- `budgetAnnuel` : Budget annuel de la collectivité
|
||||
- `siren` : Code SIREN
|
||||
- `codeEpci` : Code EPCI
|
||||
- `codesPostaux` : Codes postaux de la zone
|
||||
|
||||
### Décomptes
|
||||
- `placesCount` : Nombre de lieux enregistrés
|
||||
- `avecHoraires` : Nombre de lieux avec horaires d'ouverture
|
||||
- `avecAdresse` : Nombre de lieux avec adresse complète
|
||||
- `avecSite` : Nombre de lieux avec site web
|
||||
- `avecAccessibilite` : Nombre de lieux avec accessibilité PMR
|
||||
- `avecNote` : Nombre de lieux avec note
|
||||
- `completionPercent` : Pourcentage de complétion global
|
||||
- `placesCountReal` : Nombre réel de lieux (comptage direct)
|
||||
|
||||
### Followups (si `include_followups=true`)
|
||||
- `followups` : Tableau des mesures de suivi (CityFollowUp)
|
||||
- `name` : Nom de la mesure
|
||||
- `measure` : Valeur de la mesure
|
||||
- `date` : Date de la mesure
|
||||
|
||||
### Places (si `include_places=true`)
|
||||
- `places` : Tableau des lieux de la zone
|
||||
- `id` : Identifiant du lieu
|
||||
- `name` : Nom du lieu
|
||||
- `mainTag` : Tag principal OSM
|
||||
- `osmId` : ID OSM
|
||||
- `osmKind` : Type OSM (node/way)
|
||||
- `email` : Email de contact
|
||||
- `note` : Note
|
||||
- `zipCode` : Code postal
|
||||
- `siret` : Numéro SIRET
|
||||
- `lat` : Latitude
|
||||
- `lon` : Longitude
|
||||
- `hasOpeningHours` : A des horaires d'ouverture
|
||||
- `hasAddress` : A une adresse complète
|
||||
- `hasWebsite` : A un site web
|
||||
- `hasWheelchair` : A des informations d'accessibilité
|
||||
- `hasNote` : A une note
|
||||
- `completionPercentage` : Pourcentage de complétion du lieu
|
||||
|
||||
## Cas d'usage
|
||||
|
||||
### Export pour analyse
|
||||
```bash
|
||||
# Export de toutes les villes avec formatage
|
||||
curl "https://osm-commerces.cipherbliss.com/api/v1/stats/export?pretty=true" > analyse_villes.json
|
||||
|
||||
# Export d'une ville spécifique
|
||||
curl "https://osm-commerces.cipherbliss.com/api/v1/stats/export?zone=75056&pretty=true" > paris.json
|
||||
```
|
||||
|
||||
### Export pour traitement automatisé
|
||||
```bash
|
||||
# Export compact pour traitement par script
|
||||
curl "https://osm-commerces.cipherbliss.com/api/v1/stats/export" > stats_compact.json
|
||||
```
|
||||
|
||||
### Export avec données complètes
|
||||
```bash
|
||||
# Export avec tous les lieux (attention: peut être volumineux)
|
||||
curl "https://osm-commerces.cipherbliss.com/api/v1/stats/export?include_places=true&pretty=true" > stats_complet.json
|
||||
```
|
||||
|
||||
## Limitations
|
||||
|
||||
- L'option `include_places=true` peut générer des fichiers très volumineux pour les grandes villes
|
||||
- Les requêtes avec `include_places=true` peuvent être plus lentes
|
||||
- Le formatage JSON (`pretty=true`) augmente la taille de la réponse
|
142
docs/export-stats-command.md
Normal file
142
docs/export-stats-command.md
Normal file
|
@ -0,0 +1,142 @@
|
|||
# Commande d'export des objets Stats
|
||||
|
||||
## Description
|
||||
|
||||
La commande `app:export-stats` permet d'exporter les objets Stats au format JSON avec leurs propriétés de nom et de décomptes.
|
||||
|
||||
## Utilisation
|
||||
|
||||
### Export de tous les objets Stats
|
||||
```bash
|
||||
php bin/console app:export-stats
|
||||
```
|
||||
|
||||
### Export avec formatage JSON
|
||||
```bash
|
||||
php bin/console app:export-stats --pretty
|
||||
```
|
||||
|
||||
### Export vers un fichier spécifique
|
||||
```bash
|
||||
php bin/console app:export-stats --output=mon_export.json
|
||||
```
|
||||
|
||||
### Export d'une zone spécifique
|
||||
```bash
|
||||
php bin/console app:export-stats --zone=75056
|
||||
```
|
||||
|
||||
### Export avec toutes les options
|
||||
```bash
|
||||
php bin/console app:export-stats --output=paris_stats.json --zone=75056 --pretty
|
||||
```
|
||||
|
||||
### Export avec mode verbeux
|
||||
```bash
|
||||
php bin/console app:export-stats -v
|
||||
```
|
||||
|
||||
## Options disponibles
|
||||
|
||||
- `--output, -o` : Fichier de sortie (défaut: `stats_export.json`)
|
||||
- `--zone, -z` : Code INSEE spécifique à exporter (optionnel)
|
||||
- `--pretty, -p` : Formater le JSON avec indentation
|
||||
- `-v, --verbose` : Mode verbeux pour afficher un aperçu des données
|
||||
|
||||
## Structure des données exportées
|
||||
|
||||
Le fichier JSON contient un tableau d'objets avec la structure suivante :
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"zone": "75056",
|
||||
"name": "Paris",
|
||||
"dateCreated": "2024-01-15 10:30:00",
|
||||
"dateModified": "2024-01-20 14:45:00",
|
||||
"population": 2161000,
|
||||
"budgetAnnuel": "8500000000",
|
||||
"siren": "200054781",
|
||||
"codeEpci": "200054781",
|
||||
"codesPostaux": "75001;75002;75003;...",
|
||||
"decomptes": {
|
||||
"placesCount": 1250,
|
||||
"avecHoraires": 980,
|
||||
"avecAdresse": 1200,
|
||||
"avecSite": 850,
|
||||
"avecAccessibilite": 450,
|
||||
"avecNote": 320,
|
||||
"completionPercent": 75,
|
||||
"placesCountReal": 1250
|
||||
},
|
||||
"followups": [
|
||||
{
|
||||
"name": "fire_hydrant_count",
|
||||
"measure": 1250,
|
||||
"date": "2024-01-20 14:45:00"
|
||||
},
|
||||
{
|
||||
"name": "fire_hydrant_completion",
|
||||
"measure": 85.5,
|
||||
"date": "2024-01-20 14:45:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## Propriétés exportées
|
||||
|
||||
### Informations générales
|
||||
- `id` : Identifiant unique de l'objet Stats
|
||||
- `zone` : Code INSEE de la zone
|
||||
- `name` : Nom de la ville/zone
|
||||
- `dateCreated` : Date de création
|
||||
- `dateModified` : Date de dernière modification
|
||||
|
||||
### Données démographiques et administratives
|
||||
- `population` : Population de la zone
|
||||
- `budgetAnnuel` : Budget annuel de la collectivité
|
||||
- `siren` : Code SIREN
|
||||
- `codeEpci` : Code EPCI
|
||||
- `codesPostaux` : Codes postaux de la zone
|
||||
|
||||
### Décomptes
|
||||
- `placesCount` : Nombre de lieux enregistrés
|
||||
- `avecHoraires` : Nombre de lieux avec horaires d'ouverture
|
||||
- `avecAdresse` : Nombre de lieux avec adresse complète
|
||||
- `avecSite` : Nombre de lieux avec site web
|
||||
- `avecAccessibilite` : Nombre de lieux avec accessibilité PMR
|
||||
- `avecNote` : Nombre de lieux avec note
|
||||
- `completionPercent` : Pourcentage de complétion global
|
||||
- `placesCountReal` : Nombre réel de lieux (comptage direct)
|
||||
|
||||
### Followups
|
||||
- `followups` : Tableau des mesures de suivi (CityFollowUp)
|
||||
- `name` : Nom de la mesure
|
||||
- `measure` : Valeur de la mesure
|
||||
- `date` : Date de la mesure
|
||||
|
||||
## Exemples d'utilisation
|
||||
|
||||
### Export pour analyse
|
||||
```bash
|
||||
# Export de toutes les villes avec formatage
|
||||
php bin/console app:export-stats --pretty --output=analyse_villes.json
|
||||
|
||||
# Export d'une ville spécifique
|
||||
php bin/console app:export-stats --zone=75056 --pretty --output=paris.json
|
||||
```
|
||||
|
||||
### Export pour traitement automatisé
|
||||
```bash
|
||||
# Export compact pour traitement par script
|
||||
php bin/console app:export-stats --output=stats_compact.json
|
||||
```
|
||||
|
||||
### Vérification des données
|
||||
```bash
|
||||
# Export avec aperçu des données
|
||||
php bin/console app:export-stats --pretty -v
|
||||
```
|
167
src/Command/ExportStatsCommand.php
Normal file
167
src/Command/ExportStatsCommand.php
Normal file
|
@ -0,0 +1,167 @@
|
|||
<?php
|
||||
|
||||
namespace App\Command;
|
||||
|
||||
use App\Entity\Stats;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
#[AsCommand(
|
||||
name: 'app:export-stats',
|
||||
description: 'Exporte les objets Stats au format JSON avec leurs propriétés de nom et de décomptes'
|
||||
)]
|
||||
class ExportStatsCommand extends Command
|
||||
{
|
||||
public function __construct(
|
||||
private EntityManagerInterface $entityManager
|
||||
) {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
$this
|
||||
->addOption(
|
||||
'output',
|
||||
'o',
|
||||
InputOption::VALUE_REQUIRED,
|
||||
'Fichier de sortie (par défaut: stats_export.json)',
|
||||
'stats_export.json'
|
||||
)
|
||||
->addOption(
|
||||
'zone',
|
||||
'z',
|
||||
InputOption::VALUE_REQUIRED,
|
||||
'Code INSEE spécifique à exporter (optionnel)'
|
||||
)
|
||||
->addOption(
|
||||
'pretty',
|
||||
'p',
|
||||
InputOption::VALUE_NONE,
|
||||
'Formater le JSON avec indentation'
|
||||
)
|
||||
->setHelp('Cette commande exporte les objets Stats au format JSON avec leurs propriétés de nom et de décomptes.');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
$outputFile = $input->getOption('output');
|
||||
$zone = $input->getOption('zone');
|
||||
$pretty = $input->getOption('pretty');
|
||||
|
||||
$io->title('Export des objets Stats');
|
||||
|
||||
try {
|
||||
// Construire la requête
|
||||
$qb = $this->entityManager->getRepository(Stats::class)->createQueryBuilder('s');
|
||||
|
||||
if ($zone) {
|
||||
$qb->where('s.zone = :zone')
|
||||
->setParameter('zone', $zone);
|
||||
$io->note("Export pour la zone INSEE: $zone");
|
||||
}
|
||||
|
||||
$stats = $qb->getQuery()->getResult();
|
||||
|
||||
if (empty($stats)) {
|
||||
$io->warning('Aucun objet Stats trouvé.');
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
|
||||
$io->info(sprintf('Export de %d objet(s) Stats...', count($stats)));
|
||||
|
||||
// Préparer les données pour l'export
|
||||
$exportData = [];
|
||||
|
||||
foreach ($stats as $stat) {
|
||||
$statData = [
|
||||
'id' => $stat->getId(),
|
||||
'zone' => $stat->getZone(),
|
||||
'name' => $stat->getName(),
|
||||
'dateCreated' => $stat->getDateCreated() ? $stat->getDateCreated()->format('Y-m-d H:i:s') : null,
|
||||
'dateModified' => $stat->getDateModified() ? $stat->getDateModified()->format('Y-m-d H:i:s') : null,
|
||||
'population' => $stat->getPopulation(),
|
||||
'budgetAnnuel' => $stat->getBudgetAnnuel(),
|
||||
'siren' => $stat->getSiren(),
|
||||
'codeEpci' => $stat->getCodeEpci(),
|
||||
'codesPostaux' => $stat->getCodesPostaux(),
|
||||
'decomptes' => [
|
||||
'placesCount' => $stat->getPlacesCount(),
|
||||
'avecHoraires' => $stat->getAvecHoraires(),
|
||||
'avecAdresse' => $stat->getAvecAdresse(),
|
||||
'avecSite' => $stat->getAvecSite(),
|
||||
'avecAccessibilite' => $stat->getAvecAccessibilite(),
|
||||
'avecNote' => $stat->getAvecNote(),
|
||||
'completionPercent' => $stat->getCompletionPercent(),
|
||||
'placesCountReal' => $stat->getPlaces()->count(),
|
||||
],
|
||||
'followups' => []
|
||||
];
|
||||
|
||||
// Ajouter les followups si disponibles
|
||||
foreach ($stat->getCityFollowUps() as $followup) {
|
||||
$statData['followups'][] = [
|
||||
'name' => $followup->getName(),
|
||||
'measure' => $followup->getMeasure(),
|
||||
'date' => $followup->getDate()->format('Y-m-d H:i:s')
|
||||
];
|
||||
}
|
||||
|
||||
$exportData[] = $statData;
|
||||
}
|
||||
|
||||
// Préparer le JSON
|
||||
$jsonOptions = JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES;
|
||||
if ($pretty) {
|
||||
$jsonOptions |= JSON_PRETTY_PRINT;
|
||||
}
|
||||
|
||||
$jsonContent = json_encode($exportData, $jsonOptions);
|
||||
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
throw new \Exception('Erreur lors de l\'encodage JSON: ' . json_last_error_msg());
|
||||
}
|
||||
|
||||
// Écrire dans le fichier
|
||||
$bytesWritten = file_put_contents($outputFile, $jsonContent);
|
||||
|
||||
if ($bytesWritten === false) {
|
||||
throw new \Exception("Impossible d'écrire dans le fichier: $outputFile");
|
||||
}
|
||||
|
||||
$io->success(sprintf(
|
||||
'Export terminé avec succès ! %d objet(s) exporté(s) vers %s (%s octets)',
|
||||
count($stats),
|
||||
$outputFile,
|
||||
number_format($bytesWritten, 0, ',', ' ')
|
||||
));
|
||||
|
||||
// Afficher un aperçu des données
|
||||
if ($io->isVerbose()) {
|
||||
$io->section('Aperçu des données exportées');
|
||||
foreach ($exportData as $index => $data) {
|
||||
$io->text(sprintf(
|
||||
'%d. %s (%s) - %d lieux, %d%% complété',
|
||||
$index + 1,
|
||||
$data['name'],
|
||||
$data['zone'],
|
||||
$data['decomptes']['placesCountReal'],
|
||||
$data['decomptes']['completionPercent']
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
return Command::SUCCESS;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
$io->error('Erreur lors de l\'export: ' . $e->getMessage());
|
||||
return Command::FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -198,4 +198,138 @@ class ApiController extends AbstractController
|
|||
$response->headers->set('Content-Disposition', 'attachment; filename="places_'.$insee.'.csv"');
|
||||
return $response;
|
||||
}
|
||||
|
||||
#[Route('/api/v1/stats/export', name: 'api_stats_export', methods: ['GET'])]
|
||||
public function statsExport(
|
||||
StatsRepository $statsRepository,
|
||||
\Symfony\Component\HttpFoundation\Request $request
|
||||
): JsonResponse {
|
||||
// Récupérer les paramètres de requête
|
||||
$zone = $request->query->get('zone');
|
||||
$pretty = $request->query->getBoolean('pretty', false);
|
||||
$includeFollowups = $request->query->getBoolean('include_followups', true);
|
||||
$includePlaces = $request->query->getBoolean('include_places', false);
|
||||
|
||||
try {
|
||||
// Construire la requête
|
||||
$qb = $statsRepository->createQueryBuilder('s');
|
||||
|
||||
if ($zone) {
|
||||
$qb->where('s.zone = :zone')
|
||||
->setParameter('zone', $zone);
|
||||
}
|
||||
|
||||
$stats = $qb->getQuery()->getResult();
|
||||
|
||||
if (empty($stats)) {
|
||||
return new JsonResponse([
|
||||
'error' => 'Aucun objet Stats trouvé',
|
||||
'message' => $zone ? "Aucune zone trouvée pour le code INSEE: $zone" : 'Aucune donnée disponible'
|
||||
], Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
// Préparer les données pour l'export
|
||||
$exportData = [];
|
||||
|
||||
foreach ($stats as $stat) {
|
||||
$statData = [
|
||||
'id' => $stat->getId(),
|
||||
'zone' => $stat->getZone(),
|
||||
'name' => $stat->getName(),
|
||||
'dateCreated' => $stat->getDateCreated() ? $stat->getDateCreated()->format('Y-m-d H:i:s') : null,
|
||||
'dateModified' => $stat->getDateModified() ? $stat->getDateModified()->format('Y-m-d H:i:s') : null,
|
||||
'population' => $stat->getPopulation(),
|
||||
'budgetAnnuel' => $stat->getBudgetAnnuel(),
|
||||
'siren' => $stat->getSiren(),
|
||||
'codeEpci' => $stat->getCodeEpci(),
|
||||
'codesPostaux' => $stat->getCodesPostaux(),
|
||||
'decomptes' => [
|
||||
'placesCount' => $stat->getPlacesCount(),
|
||||
'avecHoraires' => $stat->getAvecHoraires(),
|
||||
'avecAdresse' => $stat->getAvecAdresse(),
|
||||
'avecSite' => $stat->getAvecSite(),
|
||||
'avecAccessibilite' => $stat->getAvecAccessibilite(),
|
||||
'avecNote' => $stat->getAvecNote(),
|
||||
'completionPercent' => $stat->getCompletionPercent(),
|
||||
'placesCountReal' => $stat->getPlaces()->count(),
|
||||
],
|
||||
];
|
||||
|
||||
// Ajouter les followups si demandé
|
||||
if ($includeFollowups) {
|
||||
$statData['followups'] = [];
|
||||
foreach ($stat->getCityFollowUps() as $followup) {
|
||||
$statData['followups'][] = [
|
||||
'name' => $followup->getName(),
|
||||
'measure' => $followup->getMeasure(),
|
||||
'date' => $followup->getDate()->format('Y-m-d H:i:s')
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// Ajouter les lieux si demandé
|
||||
if ($includePlaces) {
|
||||
$statData['places'] = [];
|
||||
foreach ($stat->getPlaces() as $place) {
|
||||
$statData['places'][] = [
|
||||
'id' => $place->getId(),
|
||||
'name' => $place->getName(),
|
||||
'mainTag' => $place->getMainTag(),
|
||||
'osmId' => $place->getOsmId(),
|
||||
'osmKind' => $place->getOsmKind(),
|
||||
'email' => $place->getEmail(),
|
||||
'note' => $place->getNote(),
|
||||
'zipCode' => $place->getZipCode(),
|
||||
'siret' => $place->getSiret(),
|
||||
'lat' => $place->getLat(),
|
||||
'lon' => $place->getLon(),
|
||||
'hasOpeningHours' => $place->hasOpeningHours(),
|
||||
'hasAddress' => $place->hasAddress(),
|
||||
'hasWebsite' => $place->hasWebsite(),
|
||||
'hasWheelchair' => $place->hasWheelchair(),
|
||||
'hasNote' => $place->hasNote(),
|
||||
'completionPercentage' => $place->getCompletionPercentage(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$exportData[] = $statData;
|
||||
}
|
||||
|
||||
// Préparer le JSON
|
||||
$jsonOptions = JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES;
|
||||
if ($pretty) {
|
||||
$jsonOptions |= JSON_PRETTY_PRINT;
|
||||
}
|
||||
|
||||
$jsonContent = json_encode($exportData, $jsonOptions);
|
||||
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
return new JsonResponse([
|
||||
'error' => 'Erreur lors de l\'encodage JSON',
|
||||
'message' => json_last_error_msg()
|
||||
], Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
// Retourner la réponse
|
||||
$response = new JsonResponse($exportData, Response::HTTP_OK);
|
||||
$response->headers->set('Content-Type', 'application/json');
|
||||
$response->headers->set('Content-Disposition', 'attachment; filename="stats_export.json"');
|
||||
|
||||
// Ajouter des métadonnées dans les headers
|
||||
$response->headers->set('X-Export-Count', count($stats));
|
||||
$response->headers->set('X-Export-Generated', (new \DateTime())->format('c'));
|
||||
if ($zone) {
|
||||
$response->headers->set('X-Export-Zone', $zone);
|
||||
}
|
||||
|
||||
return $response;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return new JsonResponse([
|
||||
'error' => 'Erreur lors de l\'export',
|
||||
'message' => $e->getMessage()
|
||||
], Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue