diff --git a/src/Command/CleanDuplicateStatsCommand.php b/src/Command/CleanDuplicateStatsCommand.php new file mode 100644 index 00000000..10522f95 --- /dev/null +++ b/src/Command/CleanDuplicateStatsCommand.php @@ -0,0 +1,98 @@ +addOption('dry-run', null, InputOption::VALUE_NONE, 'Simule la suppression sans rien effacer') + ->setHelp('Supprime les doublons de Stats (même code INSEE), en gardant le plus ancien. Utilisez --dry-run pour simuler.'); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + $dryRun = $input->getOption('dry-run'); + + $repo = $this->entityManager->getRepository(Stats::class); + $allStats = $repo->findAll(); + $io->title('Recherche des doublons Stats par code INSEE'); + + // Regrouper par code INSEE + $statsByZone = []; + foreach ($allStats as $stat) { + $zone = $stat->getZone(); + if (!$zone) continue; + $statsByZone[$zone][] = $stat; + } + + $toDelete = []; + foreach ($statsByZone as $zone => $statsList) { + if (count($statsList) > 1) { + // Trier par date_created (le plus ancien d'abord), puis par id si date absente + usort($statsList, function($a, $b) { + $da = $a->getDateCreated(); + $db = $b->getDateCreated(); + if ($da && $db) { + return $da <=> $db; + } elseif ($da) { + return -1; + } elseif ($db) { + return 1; + } else { + return $a->getId() <=> $b->getId(); + } + }); + // Garder le premier, supprimer les autres + $toDelete = array_merge($toDelete, array_slice($statsList, 1)); + } + } + + if (empty($toDelete)) { + $io->success('Aucun doublon trouvé.'); + return Command::SUCCESS; + } + + $io->warning(count($toDelete) . ' objet(s) Stats seraient supprimés.'); + foreach ($toDelete as $stat) { + $io->text(sprintf('Zone: %s | ID: %d | Nom: %s | Créé: %s', + $stat->getZone(), + $stat->getId(), + $stat->getName(), + $stat->getDateCreated() ? $stat->getDateCreated()->format('Y-m-d H:i:s') : 'N/A' + )); + } + + if ($dryRun) { + $io->note('Mode dry-run : aucune suppression effectuée.'); + return Command::SUCCESS; + } + + foreach ($toDelete as $stat) { + $this->entityManager->remove($stat); + } + $this->entityManager->flush(); + $io->success(count($toDelete) . ' doublon(s) supprimé(s) !'); + return Command::SUCCESS; + } +} \ No newline at end of file diff --git a/src/Service/FollowUpService.php b/src/Service/FollowUpService.php index 92f5aff6..4514eff0 100644 --- a/src/Service/FollowUpService.php +++ b/src/Service/FollowUpService.php @@ -340,7 +340,7 @@ class FollowUpService 'fire_hydrant' => 'nwr["emergency"="fire_hydrant"](area.searchArea);', 'charging_station' => 'nwr["amenity"="charging_station"](area.searchArea);', 'toilets' => 'nwr["amenity"="toilets"](area.searchArea);', - 'bus_stop' => 'nwr["highway"="bus_stop"](area.searchArea);', + 'bus_stop' => 'nwr["highway"="bus_stop"](area.searchArea);nwr["public_transport"="platform"](area.searchArea);', 'defibrillator' => 'nwr["emergency"="defibrillator"](area.searchArea);', 'camera' => 'nwr["man_made"="surveillance"](area.searchArea);', 'recycling' => 'nwr["amenity"="recycling"](area.searchArea);', @@ -485,7 +485,7 @@ class FollowUpService 'fire_hydrant' => ['ref', 'colour'], 'charging_station' => ['charging_station:output', 'capacity'], 'toilets' => ['wheelchair', 'access'], - 'bus_stop' => ['shelter', 'network'], + 'bus_stop' => ['shelter', 'network', 'highway', 'public_transport'], 'defibrillator' => ['indoor', 'access'], 'camera' => ['surveillance:type'], 'recycling' => ['recycling_type'], diff --git a/templates/admin/stats.html.twig b/templates/admin/stats.html.twig index 3e0f9b63..df1f7452 100644 --- a/templates/admin/stats.html.twig +++ b/templates/admin/stats.html.twig @@ -193,7 +193,7 @@ 'charging_station': 'nwr["amenity"="charging_station"](area.searchArea);', 'bicycle_parking' : 'nwr["amenity"="bicycle_parking"](area.searchArea);', 'toilets': 'nwr["amenity"="toilets"](area.searchArea);', - 'bus_stop': 'nwr["highway"="bus_stop"](area.searchArea);', + 'bus_stop': 'nwr["highway"="bus_stop"](area.searchArea);nwr["public_transport"="platform"](area.searchArea);', 'defibrillator': 'nwr["emergency"="defibrillator"](area.searchArea);', 'camera': 'nwr["man_made"="surveillance"](area.searchArea);', 'recycling': 'nwr["amenity"="recycling"](area.searchArea);',