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
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