diff --git a/src/Controller/AdminController.php b/src/Controller/AdminController.php index 0f44d1c..39427b1 100644 --- a/src/Controller/AdminController.php +++ b/src/Controller/AdminController.php @@ -142,8 +142,74 @@ final class AdminController extends AbstractController } $stats->computeCompletionPercent(); - $this->entityManager->persist($stats); + + // Calculer les statistiques de fraîcheur des données OSM + $timestamps = []; + foreach ($stats->getPlaces() as $place) { + if ($place->getOsmDataDate()) { + $timestamps[] = $place->getOsmDataDate()->getTimestamp(); + } + } + if (!empty($timestamps)) { + // Date la plus ancienne (min) + $minTimestamp = min($timestamps); + $stats->setOsmDataDateMin(new \DateTime('@' . $minTimestamp)); + + // Date la plus récente (max) + $maxTimestamp = max($timestamps); + $stats->setOsmDataDateMax(new \DateTime('@' . $maxTimestamp)); + + // Date moyenne + $avgTimestamp = array_sum($timestamps) / count($timestamps); + $stats->setOsmDataDateAvg(new \DateTime('@' . (int)$avgTimestamp)); + } + + if($stats->getDateCreated() == null) { + $stats->setDateCreated(new \DateTime()); + } + + $stats->setDateModified(new \DateTime()); + + // Créer un historique des statistiques + $statsHistory = new StatsHistory(); + $statsHistory->setDate(new \DateTime()) + ->setStats($stats); + + // Compter les Places avec email et SIRET + $placesWithEmail = 0; + $placesWithSiret = 0; + foreach ($stats->getPlaces() as $place) { + if ($place->getEmail() && $place->getEmail() !== '') { + $placesWithEmail++; + } + if ($place->getSiret() && $place->getSiret() !== '') { + $placesWithSiret++; + } + } + + $statsHistory->setPlacesCount($stats->getPlaces()->count()) + ->setOpeningHoursCount($stats->getAvecHoraires()) + ->setAddressCount($stats->getAvecAdresse()) + ->setWebsiteCount($stats->getAvecSite()) + ->setSiretCount($placesWithSiret) + ->setEmailsCount($placesWithEmail) + // ->setAccessibiliteCount($stats->getAvecAccessibilite()) + // ->setNoteCount($stats->getAvecNote()) + ->setCompletionPercent($stats->getCompletionPercent()) + ->setStats($stats); + + $this->entityManager->persist($statsHistory); + + + $this->entityManager->persist($stats); + $this->entityManager->flush(); + + $message = 'Labourage terminé avec succès. ' . $processedCount . ' nouveaux lieux traités.'; + if ($updateExisting) { + $message .= ' ' . $updatedCount . ' lieux existants mis à jour pour la zone '.$stats->getName().' ('.$stats->getZone().').'; + } + $this->addFlash('success', $message); } $this->entityManager->flush(); @@ -200,10 +266,69 @@ final class AdminController extends AbstractController $this->entityManager->flush(); $stats->computeCompletionPercent(); + + // Calculer les statistiques de fraîcheur des données OSM + $timestamps = []; + foreach ($stats->getPlaces() as $place) { + if ($place->getOsmDataDate()) { + $timestamps[] = $place->getOsmDataDate()->getTimestamp(); + } + } + + if (!empty($timestamps)) { + // Date la plus ancienne (min) + $minTimestamp = min($timestamps); + $stats->setOsmDataDateMin(new \DateTime('@' . $minTimestamp)); + + // Date la plus récente (max) + $maxTimestamp = max($timestamps); + $stats->setOsmDataDateMax(new \DateTime('@' . $maxTimestamp)); + + // Date moyenne + $avgTimestamp = array_sum($timestamps) / count($timestamps); + $stats->setOsmDataDateAvg(new \DateTime('@' . (int)$avgTimestamp)); + } + + if($stats->getDateCreated() == null) { + $stats->setDateCreated(new \DateTime()); + } + + $stats->setDateModified(new \DateTime()); + + // Créer un historique des statistiques + $statsHistory = new StatsHistory(); + $statsHistory->setDate(new \DateTime()) + ->setStats($stats); + + // Compter les Places avec email et SIRET + $placesWithEmail = 0; + $placesWithSiret = 0; + foreach ($stats->getPlaces() as $place) { + if ($place->getEmail() && $place->getEmail() !== '') { + $placesWithEmail++; + } + if ($place->getSiret() && $place->getSiret() !== '') { + $placesWithSiret++; + } + } + + $statsHistory->setPlacesCount($stats->getPlaces()->count()) + ->setOpeningHoursCount($stats->getAvecHoraires()) + ->setAddressCount($stats->getAvecAdresse()) + ->setWebsiteCount($stats->getAvecSite()) + ->setSiretCount($placesWithSiret) + ->setEmailsCount($placesWithEmail) + // ->setAccessibiliteCount($stats->getAvecAccessibilite()) + // ->setNoteCount($stats->getAvecNote()) + ->setCompletionPercent($stats->getCompletionPercent()) + ->setStats($stats); + + $this->entityManager->persist($statsHistory); + + $this->entityManager->persist($stats); $this->entityManager->flush(); - - // Récupérer l'historique des stats APRÈS que l'entité soit persistée + $statsHistory = $this->entityManager->getRepository(StatsHistory::class) ->createQueryBuilder('sh') ->where('sh.stats = :stats') @@ -375,6 +500,28 @@ final class AdminController extends AbstractController // Mettre à jour les statistiques finales $stats->computeCompletionPercent(); + // Calculer les statistiques de fraîcheur des données OSM + $timestamps = []; + foreach ($stats->getPlaces() as $place) { + if ($place->getOsmDataDate()) { + $timestamps[] = $place->getOsmDataDate()->getTimestamp(); + } + } + + if (!empty($timestamps)) { + // Date la plus ancienne (min) + $minTimestamp = min($timestamps); + $stats->setOsmDataDateMin(new \DateTime('@' . $minTimestamp)); + + // Date la plus récente (max) + $maxTimestamp = max($timestamps); + $stats->setOsmDataDateMax(new \DateTime('@' . $maxTimestamp)); + + // Date moyenne + $avgTimestamp = array_sum($timestamps) / count($timestamps); + $stats->setOsmDataDateAvg(new \DateTime('@' . (int)$avgTimestamp)); + } + if($stats->getDateCreated() == null) { $stats->setDateCreated(new \DateTime()); } diff --git a/templates/admin/stats.html.twig b/templates/admin/stats.html.twig index e1c1abe..7418afc 100644 --- a/templates/admin/stats.html.twig +++ b/templates/admin/stats.html.twig @@ -19,6 +19,28 @@ .completion-info { margin-bottom: 2rem; } + .osm-modification-info { + font-size: 0.85rem; + line-height: 1.3; + } + .osm-modification-info .text-muted { + font-size: 0.75rem; + } + .osm-modification-info a { + text-decoration: none; + color: #0d6efd; + } + .osm-modification-info a:hover { + text-decoration: underline; + } + .osm-freshness-info { + font-size: 0.95rem; + line-height: 1.4; + } + .osm-freshness-info .alert { + border-left: 4px solid #0dcaf0; + background-color: #f8f9fa; + } {% endblock %} @@ -59,6 +81,74 @@ {% endif %} + + {# Affichage de la fraîcheur des données OSM #} + {% if stats.osmDataDateMin and stats.osmDataDateMax and stats.osmDataDateAvg %} + {% set now = "now"|date("U") %} + {% set minDate = stats.osmDataDateMin|date("U") %} + {% set maxDate = stats.osmDataDateMax|date("U") %} + {% set avgDate = stats.osmDataDateAvg|date("U") %} + + {% set minDiff = now - minDate %} + {% set maxDiff = now - maxDate %} + {% set avgDiff = now - avgDate %} + + {% set minYears = (minDiff / 31536000)|round(0, 'floor') %} + {% set minMonths = ((minDiff % 31536000) / 2592000)|round(0, 'floor') %} + {% set maxYears = (maxDiff / 31536000)|round(0, 'floor') %} + {% set maxMonths = ((maxDiff % 31536000) / 2592000)|round(0, 'floor') %} + {% set avgYears = (avgDiff / 31536000)|round(0, 'floor') %} + {% set avgMonths = ((avgDiff % 31536000) / 2592000)|round(0, 'floor') %} + +
+
+
+ + Fraîcheur des données OSM : + {% if minYears == maxYears and minMonths == maxMonths %} + Toutes les modifications ont été faites il y a + {% if minYears > 0 %} + {{ minYears }} an{{ minYears > 1 ? 's' : '' }} + {% if minMonths > 0 %}, {{ minMonths }} mois{% endif %} + {% elseif minMonths > 0 %} + {{ minMonths }} mois + {% else %} + moins d'un mois + {% endif %} + {% else %} + Les modifications ont été faites entre il y a + {% if maxYears > 0 %} + {{ maxYears }} an{{ maxYears > 1 ? 's' : '' }} + {% if maxMonths > 0 %}, {{ maxMonths }} mois{% endif %} + {% elseif maxMonths > 0 %} + {{ maxMonths }} mois + {% else %} + moins d'un mois + {% endif %} + et il y a + {% if minYears > 0 %} + {{ minYears }} an{{ minYears > 1 ? 's' : '' }} + {% if minMonths > 0 %}, {{ minMonths }} mois{% endif %} + {% elseif minMonths > 0 %} + {{ minMonths }} mois + {% else %} + moins d'un mois + {% endif %}, + en moyenne il y a + {% if avgYears > 0 %} + {{ avgYears }} an{{ avgYears > 1 ? 's' : '' }} + {% if avgMonths > 0 %}, {{ avgMonths }} mois{% endif %} + {% elseif avgMonths > 0 %} + {{ avgMonths }} mois + {% else %} + moins d'un mois + {% endif %} + {% endif %} +
+
+
+ {% endif %} +
@@ -954,8 +1044,8 @@ window.updateMarkers = updateMarkers; {# markClosedSiretsOnTable(); #} function makeDonutGraphOfTags() { - // Récupérer tous les tags de la colonne 2 - const tags = Array.from(document.querySelectorAll('table tbody tr td:nth-child(3)')) + // Récupérer tous les tags de la colonne 4 (Type) + const tags = Array.from(document.querySelectorAll('table tbody tr td:nth-child(4)')) .map(cell => cell.textContent.trim()) .filter(tag => tag.includes('=')) // Filtrer les cellules qui ne contiennent pas de = .filter(tag => tag); // Filtrer les cellules vides diff --git a/templates/admin/stats/row.html.twig b/templates/admin/stats/row.html.twig index 0a0d66e..8910345 100644 --- a/templates/admin/stats/row.html.twig +++ b/templates/admin/stats/row.html.twig @@ -107,6 +107,50 @@ {# (si siret clos) #} + {% if commerce.osmDataDate %} + {% set now = "now"|date("U") %} + {% set osmDate = commerce.osmDataDate|date("U") %} + {% set diff = now - osmDate %} + {% set years = (diff / 31536000)|round(0, 'floor') %} + {% set months = ((diff % 31536000) / 2592000)|round(0, 'floor') %} + {% set days = ((diff % 2592000) / 86400)|round(0, 'floor') %} + +
+
+ + {{ commerce.osmDataDate|date('d/m/Y H:i') }} +
+ {% if commerce.osmUser %} +
+ + + {{ commerce.osmUser }} + +
+ {% endif %} +
+ + {% if diff < 86400 %} + Aujourd'hui + {% elseif years > 0 %} + {{ years }} an{{ years > 1 ? 's' : '' }} + {% if months > 0 %}, {{ months }} mois{% endif %} + {% elseif months > 0 %} + {{ months }} mois + {% if days > 0 %}, {{ days }} jour{{ days > 1 ? 's' : '' }}{% endif %} + {% elseif days > 0 %} + {{ days }} jour{{ days > 1 ? 's' : '' }} + {% else %} + Aujourd'hui + {% endif %} + +
+
+ {% else %} + Non disponible + {% endif %} + + diff --git a/templates/admin/stats/table-head.html.twig b/templates/admin/stats/table-head.html.twig index 3f58543..6fbf92a 100644 --- a/templates/admin/stats/table-head.html.twig +++ b/templates/admin/stats/table-head.html.twig @@ -50,6 +50,10 @@ Siret clos + + Dernière modif. OSM + + Osm id