mirror of
https://forge.chapril.org/tykayn/osm-commerces
synced 2025-10-04 17:04:53 +02:00

# Conflicts: # src/Command/ProcessLabourageQueueCommand.php # src/Controller/PublicController.php
179 lines
No EOL
8.2 KiB
PHP
179 lines
No EOL
8.2 KiB
PHP
<?php
|
|
|
|
namespace App\Command;
|
|
|
|
use App\Entity\Place;
|
|
use App\Entity\Stats;
|
|
use App\Service\FollowUpService;
|
|
use App\Service\Motocultrice;
|
|
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\Output\OutputInterface;
|
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
|
|
|
#[AsCommand(
|
|
name: 'app:process-labourage-queue',
|
|
description: 'Traite la file d\'attente de labourage différé des villes (cron)'
|
|
)]
|
|
class ProcessLabourageQueueCommand extends Command
|
|
{
|
|
public function __construct(
|
|
private EntityManagerInterface $entityManager,
|
|
private Motocultrice $motocultrice,
|
|
private FollowUpService $followUpService
|
|
)
|
|
{
|
|
parent::__construct();
|
|
}
|
|
|
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
|
{
|
|
$io = new SymfonyStyle($input, $output);
|
|
// Sélectionner la Stats à traiter (date_labourage_requested la plus ancienne, non traitée ou à refaire)
|
|
$stats = $this->entityManager->getRepository(Stats::class)
|
|
->createQueryBuilder('s')
|
|
->where('s.date_labourage_requested IS NOT NULL')
|
|
->andWhere('s.date_labourage_done IS NULL OR s.date_labourage_done < s.date_labourage_requested')
|
|
->andWhere('s.zone != :global_zone')
|
|
->setParameter('global_zone', '00000')
|
|
->orderBy('s.date_labourage_requested', 'ASC')
|
|
->setMaxResults(1)
|
|
->getQuery()
|
|
->getOneOrNullResult();
|
|
if (!$stats) {
|
|
// 1. Villes jamais labourées (date_labourage_done NULL, hors 00000)
|
|
$stats = $this->entityManager->getRepository(Stats::class)
|
|
->createQueryBuilder('s')
|
|
->where('s.zone != :global_zone')
|
|
->andWhere('s.date_labourage_done IS NULL')
|
|
->setParameter('global_zone', '00000')
|
|
->orderBy('s.date_modified', 'ASC')
|
|
->setMaxResults(1)
|
|
->getQuery()
|
|
->getOneOrNullResult();
|
|
if ($stats) {
|
|
$io->note('Aucune ville en attente, on traite en priorité une ville jamais labourée : ' . $stats->getName() . ' (' . $stats->getZone() . ')');
|
|
$stats->setDateLabourageRequested(new \DateTime());
|
|
$this->entityManager->persist($stats);
|
|
$this->entityManager->flush();
|
|
} else {
|
|
// 2. Ville la plus anciennement modifiée (hors 00000)
|
|
$stats = $this->entityManager->getRepository(Stats::class)
|
|
->createQueryBuilder('s')
|
|
->where('s.zone != :global_zone')
|
|
->setParameter('global_zone', '00000')
|
|
->orderBy('s.date_modified', 'ASC')
|
|
->setMaxResults(1)
|
|
->getQuery()
|
|
->getOneOrNullResult();
|
|
if (!$stats) {
|
|
$io->success('Aucune ville à traiter.');
|
|
return Command::SUCCESS;
|
|
}
|
|
$io->note('Aucune ville en attente, on demande le labourage de la ville la plus anciennement modifiée : ' . $stats->getName() . ' (' . $stats->getZone() . ')');
|
|
$stats->setDateLabourageRequested(new \DateTime());
|
|
$this->entityManager->persist($stats);
|
|
$this->entityManager->flush();
|
|
}
|
|
}
|
|
$io->section('Traitement de la ville : ' . $stats->getName() . ' (' . $stats->getZone() . ')');
|
|
// Vérifier la RAM disponible (>= 1 Go)
|
|
$meminfo = @file_get_contents('/proc/meminfo');
|
|
$ram_ok = false;
|
|
if ($meminfo !== false && preg_match('/^MemAvailable:\s+(\d+)/m', $meminfo, $matches)) {
|
|
$mem_kb = (int)$matches[1];
|
|
$ram_ok = ($mem_kb >= 1024 * 1024); // 1 Go
|
|
}
|
|
if (!$ram_ok) {
|
|
$io->warning('RAM insuffisante, on attend le prochain cron.');
|
|
return Command::SUCCESS;
|
|
}
|
|
// Effectuer le labourage complet (reprendre la logique de création/màj des objets Place)
|
|
$io->info('RAM suffisante, lancement du labourage...');
|
|
$places_overpass = $this->motocultrice->labourer($stats->getZone());
|
|
$processedCount = 0;
|
|
$updatedCount = 0;
|
|
$existingPlacesQuery = $this->entityManager->getRepository(Place::class)
|
|
->createQueryBuilder('p')
|
|
->select('p.osmId, p.osm_kind, p.id')
|
|
->where('p.zip_code = :zip_code')
|
|
->setParameter('zip_code', $stats->getZone())
|
|
->getQuery();
|
|
$existingPlacesResult = $existingPlacesQuery->getResult();
|
|
$placesByOsmKey = [];
|
|
foreach ($existingPlacesResult as $placeData) {
|
|
$osmKey = $placeData['osm_kind'] . '_' . $placeData['osmId'];
|
|
$placesByOsmKey[$osmKey] = $placeData['id'];
|
|
}
|
|
foreach ($places_overpass as $placeData) {
|
|
$osmKey = $placeData['type'] . '_' . $placeData['id'];
|
|
$existingPlaceId = $placesByOsmKey[$osmKey] ?? null;
|
|
if (!$existingPlaceId) {
|
|
$place = new Place();
|
|
$place->setOsmId($placeData['id'])
|
|
->setOsmKind($placeData['type'])
|
|
->setZipCode($stats->getZone())
|
|
->setUuidForUrl($this->motocultrice->uuid_create())
|
|
->setModifiedDate(new \DateTime())
|
|
->setStats($stats)
|
|
->setDead(false)
|
|
->setOptedOut(false)
|
|
->setMainTag($this->motocultrice->find_main_tag($placeData['tags']) ?? '')
|
|
->setStreet($this->motocultrice->find_street($placeData['tags']) ?? '')
|
|
->setHousenumber($this->motocultrice->find_housenumber($placeData['tags']) ?? '')
|
|
->setSiret($this->motocultrice->find_siret($placeData['tags']) ?? '')
|
|
->setAskedHumainsSupport(false)
|
|
->setLastContactAttemptDate(null)
|
|
->setPlaceCount(0);
|
|
$place->update_place_from_overpass_data($placeData);
|
|
$this->entityManager->persist($place);
|
|
$stats->addPlace($place);
|
|
$processedCount++;
|
|
} else {
|
|
$existingPlace = $this->entityManager->getRepository(Place::class)->find($existingPlaceId);
|
|
if ($existingPlace) {
|
|
$existingPlace->setDead(false);
|
|
$existingPlace->update_place_from_overpass_data($placeData);
|
|
$stats->addPlace($existingPlace);
|
|
$this->entityManager->persist($existingPlace);
|
|
$updatedCount++;
|
|
}
|
|
}
|
|
}
|
|
$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);
|
|
|
|
|
|
// update completion
|
|
$stats->computeCompletionPercent();
|
|
$followups = $stats->getCityFollowUps();
|
|
if ($followups) {
|
|
|
|
$lastFollowUp = $followups[count($followups) - 1];
|
|
if ($lastFollowUp) {
|
|
|
|
$name = $lastFollowUp->getName();
|
|
|
|
$io->success("Followup le plus récent : $name : " . $lastFollowUp->getDate()->format('d/m/Y') . ' : ' . $lastFollowUp->getMeasure());
|
|
}
|
|
}
|
|
$io->info('Pourcentage de complétion: ' . $stats->getCompletionPercent());
|
|
|
|
|
|
$this->entityManager->persist($stats);
|
|
$this->entityManager->flush();
|
|
$io->success("Labourage terminé : $processedCount nouveaux lieux, $updatedCount lieux mis à jour.");
|
|
return Command::SUCCESS;
|
|
}
|
|
}
|