From c8e3cf2adaca73d191cdca3d83d74f63ba1183b3 Mon Sep 17 00:00:00 2001 From: Tykayn Date: Sat, 12 Jul 2025 12:53:06 +0200 Subject: [PATCH] =?UTF-8?q?up=20pages=20rues=20et=20=C3=A9volutions=20dans?= =?UTF-8?q?=20le=20temps?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Controller/AdminController.php | 42 ++++- src/Controller/FollowUpController.php | 43 ++++- src/Controller/PublicController.php | 5 +- templates/admin/followup_graph.html.twig | 54 ++++++- .../admin/followup_theme_graph.html.twig | 6 + templates/admin/stats.html.twig | 3 + templates/admin/street_completion.html.twig | 152 ++++++++++++++++++ templates/public/edit.html.twig | 9 +- templates/public/stats_evolutions.html.twig | 27 +++- templates/public/view.html.twig | 2 +- 10 files changed, 329 insertions(+), 14 deletions(-) create mode 100644 templates/admin/street_completion.html.twig diff --git a/src/Controller/AdminController.php b/src/Controller/AdminController.php index ab8fc7bb..40e07f82 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 186297ac..1e73ce03 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 69b8d0cb..eac9dc66 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 1d1d58ce..ba93d4d9 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).

+
+ {% set has_change = false %} + + + + + + + + + + {% for type, diff in latest_diffs %} + {% if diff.count_diff is not null and diff.count_diff != 0 %} + {% set has_change = true %} + + + + + + {% endif %} + {% endfor %} + {% if not has_change %} + + {% endif %} + +
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.
+
+ {% for type, label in followup_labels %}

{{ label }}

@@ -41,6 +89,8 @@ 'all_types': [type] } %} {% endfor %} +

Comparaison de la complétion par thème

+

Données brutes

@@ -71,10 +121,11 @@ + {% endblock %} \ No newline at end of file diff --git a/templates/admin/followup_theme_graph.html.twig b/templates/admin/followup_theme_graph.html.twig index 4f479d98..2d235cc0 100644 --- a/templates/admin/followup_theme_graph.html.twig +++ b/templates/admin/followup_theme_graph.html.twig @@ -161,6 +161,12 @@ Accueil admin + + Évolutions temporelles + + + Complétion des rues + {% if josm_url %} diff --git a/templates/admin/stats.html.twig b/templates/admin/stats.html.twig index 7a1b5128..a7341296 100644 --- a/templates/admin/stats.html.twig +++ b/templates/admin/stats.html.twig @@ -136,6 +136,9 @@ Évolutions des objets + + Complétion des rues + {% if stats.population %} diff --git a/templates/admin/street_completion.html.twig b/templates/admin/street_completion.html.twig new file mode 100644 index 00000000..509d57ca --- /dev/null +++ b/templates/admin/street_completion.html.twig @@ -0,0 +1,152 @@ +{% extends 'base.html.twig' %} + +{% block title %}Complétion des rues - {{ stats.name }}{% endblock %} + +{% block body %} +
+

Complétion des rues à {{ stats.name }} ({{ stats.zone }})

+ Retour aux stats +
+ + + + + + + + + {% for rue in rues %} + + + + + + {% else %} + + {% endfor %} + +
RueNombre de lieuxComplétion moyenne (%)
+ + {{ rue.name }} + + {{ rue.count }}{{ rue.avg_completion }}
Aucune rue trouvée.
+ + +
+

Rues sans lieu associé (données OSM)

+
Chargement des rues OSM…
+ +
+ + +{% endblock %} \ No newline at end of file diff --git a/templates/public/edit.html.twig b/templates/public/edit.html.twig index 749d3985..91cbf7dc 100644 --- a/templates/public/edit.html.twig +++ b/templates/public/edit.html.twig @@ -8,7 +8,14 @@
-

{{ 'display.welcome'|trans }} {{ commerce_overpass.tags_converted.name }} - {{ commerce.stats.name }}

+

+ {{ 'display.welcome'|trans }} + {% set main_tag = commerce.mainTag is defined and commerce.mainTag is not empty ? commerce.mainTag : (commerce_overpass.tags_converted.main_tag is defined ? commerce_overpass.tags_converted.main_tag : null) %} + {% if main_tag %} + {{ tag_emoji(main_tag) }} + {% endif %} + {{ commerce_overpass.tags_converted.name }} - {{ commerce.stats.name }} +

{% include 'public/edit/address.html.twig' %} diff --git a/templates/public/stats_evolutions.html.twig b/templates/public/stats_evolutions.html.twig index c641269a..c6e945e8 100644 --- a/templates/public/stats_evolutions.html.twig +++ b/templates/public/stats_evolutions.html.twig @@ -15,19 +15,36 @@ Type - Décompte actuel + Décompte actuel {% for p in periods %} - Évolution sur {{ p }} + Évolution sur {{ p }} {% endfor %} {% for type, evo in evolutions %} - {{ type }} - {{ evo.now }} + + + + + {{ type }} + + {{ evo.now }} {% for p in periods %} - {% if evo[p] is not null %}{{ evo[p] > 0 ? '+' ~ evo[p] : evo[p] }}{% else %}-{% endif %} + + {% if evo[p] is not null %} + {% if evo[p] > 0 %} + + {% elseif evo[p] < 0 %} + + {% endif %} + {{ evo[p] > 0 ? '+' ~ evo[p] : evo[p] }} + {% else %} + - + {% endif %} + {% endfor %} {% else %} diff --git a/templates/public/view.html.twig b/templates/public/view.html.twig index 106d3a1c..1852a71a 100644 --- a/templates/public/view.html.twig +++ b/templates/public/view.html.twig @@ -8,7 +8,7 @@ {% block body %}
-

Modification du lieu {{ commerce.tags_converted.name }}!

+

Modification du lieu {{ commerce.tags_converted.name is defined and commerce.tags_converted.name is not empty ? commerce.tags_converted.name : '(sans nom)' }}!

{% if status == "Les tags ont été mis à jour avec succès" %} {{status}}