diff --git a/src/Controller/AdminController.php b/src/Controller/AdminController.php index ab8fc7b..40e07f8 100644 --- a/src/Controller/AdminController.php +++ b/src/Controller/AdminController.php @@ -2079,6 +2079,7 @@ final class AdminController extends AbstractController ]); } + #[Route('/admin/followup-graph/{insee_code}', name: 'admin_followup_graph', requirements: ['insee_code' => '\d+'])] public function followupGraph(Request $request, string $insee_code): Response { $stats = $this->entityManager->getRepository(Stats::class)->findOneBy(['zone' => $insee_code]); @@ -2086,17 +2087,15 @@ final class AdminController extends AbstractController $this->addFlash('error', 'Aucune stats trouvée pour ce code INSEE.'); return $this->redirectToRoute('app_admin'); } - $themes = \App\Service\FollowUpService::getFollowUpThemes(); // On ne vérifie pas ici un thème unique, on boucle sur tous les thèmes plus loin - // Ici, on ne prépare que les variables globales pour le template return $this->render('admin/followup_graph.html.twig', [ 'stats' => $stats, 'completion_tags' => \App\Service\FollowUpService::getFollowUpCompletionTags(), 'followup_labels' => \App\Service\FollowUpService::getFollowUpThemes(), 'followup_icons' => \App\Service\FollowUpService::getFollowUpIcons(), - // ... autres variables nécessaires ... + ]); } @@ -2111,4 +2110,41 @@ final class AdminController extends AbstractController // Pour éviter l'erreur, on retourne une redirection par défaut si rien n'est fait return $this->redirectToRoute('admin_dashboard'); } + + #[Route('/admin/stats/{insee_code}/street-completion', name: 'admin_street_completion', requirements: ['insee_code' => '\d+'])] + public function streetCompletion(string $insee_code): Response + { + $stats = $this->entityManager->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'); + } + $places = $stats->getPlaces(); + $rues = []; + foreach ($places as $place) { + $rue = $place->getStreet() ?: '(sans nom)'; + if (!isset($rues[$rue])) { + $rues[$rue] = [ 'places' => [], 'completion_sum' => 0 ]; + } + $rues[$rue]['places'][] = $place; + $rues[$rue]['completion_sum'] += $place->getCompletionPercentage(); + } + $rues_data = []; + foreach ($rues as $nom => $data) { + $count = count($data['places']); + $avg = $count > 0 ? round($data['completion_sum'] / $count, 1) : 0; + $rues_data[] = [ + 'name' => $nom, + 'count' => $count, + 'avg_completion' => $avg, + ]; + } + // Tri décroissant par complétion moyenne + usort($rues_data, fn($a, $b) => $b['avg_completion'] <=> $a['avg_completion']); + return $this->render('admin/street_completion.html.twig', [ + 'stats' => $stats, + 'rues' => $rues_data, + 'insee_code' => $insee_code, + ]); + } } diff --git a/src/Controller/FollowUpController.php b/src/Controller/FollowUpController.php index 186297a..1e73ce0 100644 --- a/src/Controller/FollowUpController.php +++ b/src/Controller/FollowUpController.php @@ -90,12 +90,12 @@ class FollowUpController extends AbstractController $all_points = []; foreach ($followups as $fu) { $series[$fu->getName()][] = [ - 'date' => $fu->getDate()->format('c'), + 'date' => $fu->getDate()->format('Y-m-d'), 'value' => $fu->getMeasure(), 'name' => $fu->getName(), ]; $all_points[] = [ - 'date' => $fu->getDate()->format('c'), + 'date' => $fu->getDate()->format('Y-m-d'), 'type' => $fu->getName(), 'name' => $fu->getName(), 'value' => $fu->getMeasure(), @@ -110,6 +110,43 @@ class FollowUpController extends AbstractController }); } unset($points); + // Ajout du calcul all_completion_data + $themes = \App\Service\FollowUpService::getFollowUpThemes(); + $all_completion_data = []; + $latest_diffs = []; + foreach ($themes as $type => $label) { + $all_completion_data[$type] = $series[$type . '_completion'] ?? []; + // Calcul du diff sur 7 jours pour le nombre et la complétion + $count_series = $series[$type . '_count'] ?? []; + $completion_series = $series[$type . '_completion'] ?? []; + $count_now = count($count_series) ? $count_series[count($count_series)-1]['value'] : null; + $count_7d = null; + foreach (array_reverse($count_series) as $point) { + $date = \DateTime::createFromFormat('Y-m-d', $point['date']); + if ($date && $date <= (new \DateTime('-7 days'))) { + $count_7d = $point['value']; + break; + } + } + $completion_now = count($completion_series) ? $completion_series[count($completion_series)-1]['value'] : null; + $completion_7d = null; + foreach (array_reverse($completion_series) as $point) { + $date = \DateTime::createFromFormat('Y-m-d', $point['date']); + if ($date && $date <= (new \DateTime('-7 days'))) { + $completion_7d = $point['value']; + break; + } + } + $latest_diffs[$type] = [ + 'count_now' => $count_now, + 'count_7d' => $count_7d, + 'count_diff' => ($count_now !== null && $count_7d !== null) ? $count_now - $count_7d : null, + 'completion_now' => $completion_now, + 'completion_7d' => $completion_7d, + 'completion_diff' => ($completion_now !== null && $completion_7d !== null) ? $completion_now - $completion_7d : null, + 'label' => $label, + ]; + } return $this->render('admin/followup_graph.html.twig', [ 'stats' => $stats, 'series' => $series, @@ -118,6 +155,8 @@ class FollowUpController extends AbstractController 'followup_icons' => FollowUpService::getFollowUpIcons(), 'followup_overpass' => FollowUpService::getFollowUpOverpassQueries(), 'completion_tags' => FollowUpService::getFollowUpCompletionTags(), + 'all_completion_data' => $all_completion_data, + 'latest_diffs' => $latest_diffs, ]); } diff --git a/src/Controller/PublicController.php b/src/Controller/PublicController.php index 69b8d0c..eac9dc6 100644 --- a/src/Controller/PublicController.php +++ b/src/Controller/PublicController.php @@ -229,8 +229,11 @@ class PublicController extends AbstractController $base_tags = array_fill_keys($base_tags, ''); $commerce_overpass = $this->motocultrice->get_osm_object_data($place->getOsmKind(), $place->getOsmId()); + // Mettre à jour la Place à partir des infos Overpass + $place->update_place_from_overpass_data($commerce_overpass); + $this->entityManager->persist($place); + $this->entityManager->flush(); // Fusionner les tags de base avec les tags existants - $commerce_overpass['tags_converted'] = array_merge($base_tags, $commerce_overpass['tags_converted']); // Trier les tags par ordre alphabétique des clés diff --git a/templates/admin/followup_graph.html.twig b/templates/admin/followup_graph.html.twig index 1d1d58c..ba93d4d 100644 --- a/templates/admin/followup_graph.html.twig +++ b/templates/admin/followup_graph.html.twig @@ -20,6 +20,54 @@
Historique des objets suivis (nombre et complétion).
+Thème | +Évolution du nombre | +Évolution de la complétion | +
---|---|---|
+ + {{ diff.label }} + + | ++ {% if diff.count_diff > 0 %} + + {% else %} + + {% endif %} + {{ diff.count_diff > 0 ? '+' ~ diff.count_diff : diff.count_diff }} objets + | ++ {% if diff.completion_diff > 0 %} + + {% elseif diff.completion_diff < 0 %} + + {% else %} + + {% endif %} + {{ diff.completion_diff > 0 ? '+' ~ diff.completion_diff : diff.completion_diff }}% + | +
Aucun changement significatif cette semaine. |
Rue | +Nombre de lieux | +Complétion moyenne (%) | +
---|---|---|
+ + {{ rue.name }} + + | +{{ rue.count }} | +{{ rue.avg_completion }} | +
Aucune rue trouvée. |