osm-commerces/src/Controller/FollowUpController.php

227 lines
No EOL
9.1 KiB
PHP

<?php
namespace App\Controller;
use App\Entity\Stats;
use App\Entity\CityFollowUp;
use App\Service\Motocultrice;
use App\Service\FollowUpService;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class FollowUpController extends AbstractController
{
private FollowUpService $followUpService;
public function __construct(FollowUpService $followUpService)
{
$this->followUpService = $followUpService;
}
#[Route('/admin/followup/{insee_code}/delete', name: 'admin_followup_delete', requirements: ['insee_code' => '\\d+'])]
public function deleteFollowups(string $insee_code, EntityManagerInterface $em): Response {
$stats = $em->getRepository(Stats::class)->findOneBy(['zone' => $insee_code]);
if (!$stats) {
$this->addFlash('error', 'Aucune stats trouvée pour ce code INSEE.');
return $this->redirectToRoute('app_admin');
}
$followups = $stats->getCityFollowUps();
foreach ($followups as $fu) {
$em->remove($fu);
}
$em->flush();
$this->addFlash('success', 'Tous les suivis ont été supprimés pour cette ville.');
return $this->redirectToRoute('admin_followup_graph', ['insee_code' => $insee_code]);
}
#[Route('/admin/followup/{insee_code}', name: 'admin_followup', requirements: ['insee_code' => '\\d+'])]
public function followup(
string $insee_code,
Motocultrice $motocultrice,
EntityManagerInterface $em
): Response {
$stats = $em->getRepository(Stats::class)->findOneBy(['zone' => $insee_code]);
if (!$stats) {
$this->addFlash('error', 'Aucune stats trouvée pour ce code INSEE.');
return $this->redirectToRoute('app_admin');
}
$this->followUpService->generateCityFollowUps($stats, $motocultrice, $em);
$this->addFlash('success', 'Suivi enregistré pour la ville.');
return $this->redirectToRoute('admin_followup_graph', ['insee_code' => $insee_code]);
}
#[Route('/admin/followup/{insee_code}/graph', name: 'admin_followup_graph', requirements: ['insee_code' => '\\d+'])]
public function followupGraph(
string $insee_code,
EntityManagerInterface $em,
Motocultrice $motocultrice
) {
$stats = $em->getRepository(Stats::class)->findOneBy(['zone' => $insee_code]);
if (!$stats) {
$this->addFlash('error', 'Aucune stats trouvée pour ce code INSEE.');
return $this->redirectToRoute('app_admin');
}
$followups = $stats->getCityFollowUps();
$refresh = false;
if (!$followups->isEmpty()) {
$latest = null;
foreach ($followups as $fu) {
if ($latest === null || $fu->getDate() > $latest->getDate()) {
$latest = $fu;
}
}
if ($latest && $latest->getDate() < (new \DateTime('-1 day'))) {
$refresh = true;
}
} else {
$refresh = true;
}
if ($refresh) {
$this->followUpService->generateCityFollowUps($stats, $motocultrice, $em);
$followups = $stats->getCityFollowUps();
}
$followups = $followups->toArray();
usort($followups, fn($a, $b) => $a->getDate() <=> $b->getDate());
$series = [];
$all_points = [];
foreach ($followups as $fu) {
$series[$fu->getName()][] = [
'date' => $fu->getDate()->format('c'),
'value' => $fu->getMeasure(),
'name' => $fu->getName(),
];
$all_points[] = [
'date' => $fu->getDate()->format('c'),
'type' => $fu->getName(),
'name' => $fu->getName(),
'value' => $fu->getMeasure(),
];
}
usort($all_points, fn($a, $b) => strcmp($b['date'], $a['date']));
$all_points = array_slice($all_points, 0, 20);
// Tri par date dans chaque série
foreach ($series as &$points) {
usort($points, function($a, $b) {
return strtotime($a['date']) <=> strtotime($b['date']);
});
}
unset($points);
return $this->render('admin/followup_graph.html.twig', [
'stats' => $stats,
'series' => $series,
'all_points' => $all_points,
'followup_labels' => FollowUpService::getFollowUpThemes(),
'followup_icons' => FollowUpService::getFollowUpIcons(),
'followup_overpass' => FollowUpService::getFollowUpOverpassQueries(),
]);
}
#[Route('/admin/followup/all', name: 'admin_followup_all')]
public function followupAll(
EntityManagerInterface $em,
Motocultrice $motocultrice
) {
$statsList = $em->getRepository(Stats::class)->findAll();
foreach ($statsList as $stats) {
$this->followUpService->generateCityFollowUps($stats, $motocultrice, $em);
}
$this->addFlash('success', 'Suivi généré pour toutes les villes.');
return $this->redirectToRoute('app_admin');
}
#[Route('/admin/followup/global', name: 'admin_followup_global')]
public function followupGlobal(EntityManagerInterface $em) {
$this->followUpService->generateGlobalFollowUps($em);
$this->addFlash('success', 'Suivi global généré pour toutes les villes.');
return $this->redirectToRoute('admin_followup_global_graph');
}
#[Route('/admin/followup/global/graph', name: 'admin_followup_global_graph')]
public function followupGlobalGraph(EntityManagerInterface $em) {
$stats = $em->getRepository(Stats::class)->findOneBy(['zone' => '00000']);
if (!$stats) {
$this->addFlash('error', 'Aucun suivi global trouvé.');
return $this->redirectToRoute('app_admin');
}
$followups = $stats->getCityFollowUps();
$followups = $followups->toArray();
usort($followups, fn($a, $b) => $a->getDate() <=> $b->getDate());
$series = [];
foreach ($followups as $fu) {
$series[$fu->getName()][] = [
'date' => $fu->getDate()->format('c'),
'value' => $fu->getMeasure(),
'name' => $fu->getName(),
];
}
// Tri par date dans chaque série
foreach ($series as &$points) {
usort($points, function($a, $b) {
return strtotime($a['date']) <=> strtotime($b['date']);
});
}
unset($points);
return $this->render('admin/followup_global_graph.html.twig', [
'stats' => $stats,
'series' => $series,
'followup_labels' => FollowUpService::getFollowUpThemes(),
'followup_icons' => FollowUpService::getFollowUpIcons(),
'followup_overpass' => FollowUpService::getFollowUpOverpassQueries(),
]);
}
#[Route('/admin/followup/{insee_code}/embed/{theme}', name: 'admin_followup_embed_graph', requirements: ['insee_code' => '\\d+', 'theme' => '[a-zA-Z0-9_]+'])]
public function followupEmbedGraph(
string $insee_code,
string $theme,
EntityManagerInterface $em,
Motocultrice $motocultrice
) {
$stats = $em->getRepository(Stats::class)->findOneBy(['zone' => $insee_code]);
if (!$stats) {
$this->addFlash('error', 'Aucune stats trouvée pour ce code INSEE.');
return $this->redirectToRoute('app_admin');
}
$followups = $stats->getCityFollowUps();
$refresh = false;
if (!$followups->isEmpty()) {
$latest = null;
foreach ($followups as $fu) {
if ($latest === null || $fu->getDate() > $latest->getDate()) {
$latest = $fu;
}
}
if ($latest && $latest->getDate() < (new \DateTime('-1 day'))) {
$refresh = true;
}
} else {
$refresh = true;
}
if ($refresh) {
$this->followUpService->generateCityFollowUps($stats, $motocultrice, $em);
$followups = $stats->getCityFollowUps();
}
$followups = $followups->toArray();
usort($followups, fn($a, $b) => $a->getDate() <=> $b->getDate());
$series = [];
foreach ($followups as $fu) {
if (str_starts_with($fu->getName(), $theme)) {
$series[$fu->getName()][] = [
'date' => $fu->getDate()->format('c'),
'value' => $fu->getMeasure(),
'name' => $fu->getName(),
];
}
}
return $this->render('admin/followup_embed_graph.html.twig', [
'stats' => $stats,
'series' => $series,
'theme' => $theme,
'label' => FollowUpService::getFollowUpThemes()[$theme] ?? $theme,
'icon' => FollowUpService::getFollowUpIcons()[$theme] ?? 'bi-question-circle',
]);
}
}