commande pour enlever les duplications de Places

This commit is contained in:
Tykayn 2025-08-02 15:14:13 +02:00 committed by tykayn
parent 37fd162824
commit eee5d6349a
4 changed files with 217 additions and 6 deletions

View file

@ -6,6 +6,7 @@ use App\Entity\Demande;
use App\Entity\Stats;
use App\Repository\DemandeRepository;
use App\Repository\StatsRepository;
use App\Service\Motocultrice;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
@ -22,16 +23,19 @@ class CreateStatsFromDemandesCommand extends Command
private EntityManagerInterface $entityManager;
private DemandeRepository $demandeRepository;
private StatsRepository $statsRepository;
private Motocultrice $motocultrice;
public function __construct(
EntityManagerInterface $entityManager,
DemandeRepository $demandeRepository,
StatsRepository $statsRepository
StatsRepository $statsRepository,
Motocultrice $motocultrice
) {
parent::__construct();
$this->entityManager = $entityManager;
$this->demandeRepository = $demandeRepository;
$this->statsRepository = $statsRepository;
$this->motocultrice = $motocultrice;
}
protected function execute(InputInterface $input, OutputInterface $output): int
@ -74,11 +78,19 @@ class CreateStatsFromDemandesCommand extends Command
$stats = new Stats();
$stats->setZone((string) $insee);
// Try to set the city name from the first Demande
$firstDemande = $demandes[0];
if ($firstDemande->getQuery()) {
// Use the query as a fallback name (will be updated during labourage)
$stats->setName($firstDemande->getQuery());
// Try to get the city name from the API based on INSEE code
$apiCityName = $this->motocultrice->get_city_osm_from_zip_code($insee);
if ($apiCityName) {
// Use the API-provided city name
$stats->setName($apiCityName);
$io->text(sprintf('Using API city name: %s', $apiCityName));
} else {
// Fallback to the query from the first Demande if API doesn't return a name
$firstDemande = $demandes[0];
if ($firstDemande->getQuery()) {
$stats->setName($firstDemande->getQuery());
$io->text(sprintf('Using query as fallback name: %s', $firstDemande->getQuery()));
}
}
$stats->setDateCreated(new \DateTime());

View file

@ -142,6 +142,14 @@ class ProcessLabourageQueueCommand extends Command
}
}
$stats->setDateLabourageDone(new \DateTime());
// Update city name from API if available
$apiCityName = $this->motocultrice->get_city_osm_from_zip_code($stats->getZone());
if ($apiCityName && $apiCityName !== $stats->getName()) {
$io->info(sprintf('Updating city name from "%s" to "%s" based on API data', $stats->getName(), $apiCityName));
$stats->setName($apiCityName);
}
$io->info('Récupération des followups de cette ville...');
// $this->followUpService->generateCityFollowUps($stats, $this->motocultrice, $this->entityManager);

View file

@ -0,0 +1,123 @@
<?php
namespace App\Command;
use App\Entity\Place;
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:remove-duplicate-places',
description: 'Remove duplicate Places based on OSM type and ID',
)]
class RemoveDuplicatePlacesCommand extends Command
{
private EntityManagerInterface $entityManager;
public function __construct(
EntityManagerInterface $entityManager
) {
parent::__construct();
$this->entityManager = $entityManager;
}
protected function configure(): void
{
$this
->addOption('dry-run', null, InputOption::VALUE_NONE, 'Show duplicates without removing them')
->addOption('zip-code', null, InputOption::VALUE_REQUIRED, 'Process only places with this ZIP code');
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$io->title('Removing duplicate Places based on OSM type and ID');
$dryRun = $input->getOption('dry-run');
$zipCode = $input->getOption('zip-code');
// Build the query to get all places sorted by OSM type and ID
$queryBuilder = $this->entityManager->createQueryBuilder()
->select('p')
->from(Place::class, 'p')
->orderBy('p.osm_kind', 'ASC')
->addOrderBy('p.osmId', 'ASC');
// Add ZIP code filter if provided
if ($zipCode) {
$queryBuilder->andWhere('p.zip_code = :zip_code')
->setParameter('zip_code', $zipCode);
$io->info(sprintf('Processing only places with ZIP code: %s', $zipCode));
}
$places = $queryBuilder->getQuery()->getResult();
if (empty($places)) {
$io->warning('No places found.');
return Command::SUCCESS;
}
$io->info(sprintf('Found %d places.', count($places)));
// Find duplicates by comparing consecutive places
$duplicates = [];
$previousPlace = null;
$duplicateCount = 0;
foreach ($places as $place) {
if ($previousPlace !== null &&
$previousPlace->getOsmKind() === $place->getOsmKind() &&
$previousPlace->getOsmId() === $place->getOsmId()) {
// This is a duplicate
$duplicates[] = [
'keep' => $previousPlace,
'remove' => $place
];
$duplicateCount++;
}
$previousPlace = $place;
}
if (empty($duplicates)) {
$io->success('No duplicate places found.');
return Command::SUCCESS;
}
$io->info(sprintf('Found %d duplicate places.', $duplicateCount));
// Process duplicates
$removedCount = 0;
foreach ($duplicates as $duplicate) {
$keep = $duplicate['keep'];
$remove = $duplicate['remove'];
$io->text(sprintf(
'Duplicate found: Keep #%d, Remove #%d (OSM %s/%s)',
$keep->getId(),
$remove->getId(),
$keep->getOsmKind(),
$keep->getOsmId()
));
if (!$dryRun) {
// Remove the duplicate
$this->entityManager->remove($remove);
$removedCount++;
}
}
if (!$dryRun && $removedCount > 0) {
$this->entityManager->flush();
$io->success(sprintf('Removed %d duplicate places.', $removedCount));
} elseif ($dryRun) {
$io->info('Dry run completed. No places were removed.');
}
return Command::SUCCESS;
}
}