retapage accueil, gestion de Demandes
This commit is contained in:
parent
d777221d0d
commit
f4c5e048ff
26 changed files with 2498 additions and 292 deletions
|
|
@ -4,16 +4,21 @@ namespace App\Controller;
|
|||
|
||||
use App\Entity\Stats;
|
||||
use App\Entity\Place;
|
||||
use App\Entity\CityFollowUp;
|
||||
use App\Entity\Demande;
|
||||
use App\Service\Motocultrice;
|
||||
use App\Service\FollowUpService;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use GuzzleHttp\Client;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Mime\Email;
|
||||
use Symfony\Component\Mailer\MailerInterface;
|
||||
use App\Service\ActionLogger;
|
||||
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
|
||||
|
||||
class PublicController extends AbstractController
|
||||
{
|
||||
|
|
@ -24,7 +29,8 @@ class PublicController extends AbstractController
|
|||
private EntityManagerInterface $entityManager,
|
||||
private Motocultrice $motocultrice,
|
||||
private MailerInterface $mailer,
|
||||
private ActionLogger $actionLogger
|
||||
private ActionLogger $actionLogger,
|
||||
private FollowUpService $followUpService
|
||||
) {}
|
||||
|
||||
#[Route('/propose-email/{email}/{type}/{id}', name: 'app_public_propose_email')]
|
||||
|
|
@ -115,6 +121,73 @@ class PublicController extends AbstractController
|
|||
return $this->redirectToRoute('app_public_index');
|
||||
}
|
||||
|
||||
#[Route('/api/demande/create', name: 'app_public_create_demande', methods: ['POST'])]
|
||||
public function createDemande(Request $request): JsonResponse
|
||||
{
|
||||
$data = json_decode($request->getContent(), true);
|
||||
|
||||
if (!isset($data['businessName']) || empty($data['businessName'])) {
|
||||
return new JsonResponse(['success' => false, 'message' => 'Le nom du commerce est requis'], 400);
|
||||
}
|
||||
|
||||
// Create a new Demande
|
||||
$demande = new Demande();
|
||||
$demande->setQuery($data['businessName']);
|
||||
$demande->setStatus('new');
|
||||
$demande->setCreatedAt(new \DateTime());
|
||||
|
||||
// Save the INSEE code if provided
|
||||
if (isset($data['insee']) && !empty($data['insee'])) {
|
||||
$demande->setInsee((int)$data['insee']);
|
||||
}
|
||||
|
||||
// Save the OSM object type if provided
|
||||
if (isset($data['osmObjectType']) && !empty($data['osmObjectType'])) {
|
||||
$demande->setOsmObjectType($data['osmObjectType']);
|
||||
}
|
||||
|
||||
// Save the OSM ID if provided
|
||||
if (isset($data['osmId']) && !empty($data['osmId'])) {
|
||||
$demande->setOsmId((int)$data['osmId']);
|
||||
}
|
||||
|
||||
$this->entityManager->persist($demande);
|
||||
$this->entityManager->flush();
|
||||
|
||||
return new JsonResponse([
|
||||
'success' => true,
|
||||
'message' => 'Demande créée avec succès',
|
||||
'id' => $demande->getId()
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/api/demande/{id}/email', name: 'app_public_update_demande_email', methods: ['POST'])]
|
||||
public function updateDemandeEmail(int $id, Request $request): JsonResponse
|
||||
{
|
||||
$data = json_decode($request->getContent(), true);
|
||||
|
||||
if (!isset($data['email']) || empty($data['email'])) {
|
||||
return new JsonResponse(['success' => false, 'message' => 'L\'email est requis'], 400);
|
||||
}
|
||||
|
||||
$demande = $this->entityManager->getRepository(Demande::class)->find($id);
|
||||
|
||||
if (!$demande) {
|
||||
return new JsonResponse(['success' => false, 'message' => 'Demande non trouvée'], 404);
|
||||
}
|
||||
|
||||
$demande->setEmail($data['email']);
|
||||
$demande->setStatus('email_provided');
|
||||
|
||||
$this->entityManager->persist($demande);
|
||||
$this->entityManager->flush();
|
||||
|
||||
return new JsonResponse([
|
||||
'success' => true,
|
||||
'message' => 'Email ajouté avec succès'
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/', name: 'app_public_index')]
|
||||
public function index(): Response
|
||||
{
|
||||
|
|
@ -122,11 +195,11 @@ class PublicController extends AbstractController
|
|||
|
||||
// Préparer les données pour la carte
|
||||
$citiesForMap = [];
|
||||
|
||||
|
||||
foreach ($stats as $stat) {
|
||||
if ($stat->getZone() && $stat->getZone() !== 'undefined' && preg_match('/^\d+$/', $stat->getZone()) && $stat->getZone() !== '00000') {
|
||||
$cityName = $stat->getName() ?: $stat->getZone();
|
||||
|
||||
|
||||
// Utiliser les coordonnées stockées si disponibles
|
||||
if ($stat->getLat() && $stat->getLon()) {
|
||||
$citiesForMap[] = [
|
||||
|
|
@ -160,33 +233,33 @@ class PublicController extends AbstractController
|
|||
{
|
||||
// Cache simple pour éviter trop d'appels API
|
||||
$cacheKey = 'city_coords_' . $inseeCode;
|
||||
|
||||
|
||||
// Vérifier le cache (ici on utilise une approche simple)
|
||||
// En production, vous pourriez utiliser le cache Symfony
|
||||
|
||||
|
||||
$query = urlencode($cityName . ', France');
|
||||
$url = "https://nominatim.openstreetmap.org/search?q={$query}&format=json&limit=1&countrycodes=fr";
|
||||
|
||||
|
||||
try {
|
||||
// Ajouter un délai pour respecter les limites de l'API Nominatim
|
||||
usleep(100000); // 0.1 seconde entre les appels
|
||||
|
||||
|
||||
$context = stream_context_create([
|
||||
'http' => [
|
||||
'timeout' => 5, // Timeout de 5 secondes
|
||||
'user_agent' => 'OSM-Commerces/1.0'
|
||||
]
|
||||
]);
|
||||
|
||||
|
||||
$response = file_get_contents($url, false, $context);
|
||||
|
||||
|
||||
if ($response === false) {
|
||||
error_log("DEBUG: Échec de récupération des coordonnées pour $cityName ($inseeCode)");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
$data = json_decode($response, true);
|
||||
|
||||
|
||||
if (!empty($data) && isset($data[0]['lat']) && isset($data[0]['lon'])) {
|
||||
error_log("DEBUG: Coordonnées trouvées pour $cityName ($inseeCode): " . $data[0]['lat'] . ", " . $data[0]['lon']);
|
||||
return [
|
||||
|
|
@ -199,7 +272,7 @@ class PublicController extends AbstractController
|
|||
} catch (\Exception $e) {
|
||||
error_log("DEBUG: Exception lors de la récupération des coordonnées pour $cityName ($inseeCode): " . $e->getMessage());
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -262,7 +335,7 @@ class PublicController extends AbstractController
|
|||
{
|
||||
|
||||
$this->actionLogger->log('dashboard', []);
|
||||
|
||||
|
||||
$stats_repo = $this->entityManager->getRepository(Stats::class)->findAll();
|
||||
|
||||
$stats_for_chart = [];
|
||||
|
|
@ -291,6 +364,74 @@ class PublicController extends AbstractController
|
|||
]);
|
||||
}
|
||||
|
||||
#[Route('/api/dashboard/regression', name: 'api_dashboard_regression', methods: ['POST'])]
|
||||
public function saveRegressionData(Request $request): JsonResponse
|
||||
{
|
||||
$this->actionLogger->log('save_regression_data', []);
|
||||
|
||||
// Récupérer les données de la requête
|
||||
$data = json_decode($request->getContent(), true);
|
||||
|
||||
if (!isset($data['angle']) || !isset($data['slope']) || !isset($data['intercept'])) {
|
||||
return new JsonResponse([
|
||||
'success' => false,
|
||||
'message' => 'Données de régression incomplètes'
|
||||
], Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
// Récupérer les stats globales (zone 00000)
|
||||
$statsGlobal = $this->entityManager->getRepository(Stats::class)->findOneBy(['zone' => '00000']);
|
||||
|
||||
if (!$statsGlobal) {
|
||||
// Créer les stats globales si elles n'existent pas
|
||||
$statsGlobal = new Stats();
|
||||
$statsGlobal->setZone('00000');
|
||||
$statsGlobal->setName('toutes les villes');
|
||||
$this->entityManager->persist($statsGlobal);
|
||||
$this->entityManager->flush();
|
||||
}
|
||||
|
||||
// Créer un nouveau followup pour la régression linéaire
|
||||
$followup = new CityFollowUp();
|
||||
$followup->setName('regression_angle');
|
||||
$followup->setMeasure($data['angle']);
|
||||
$followup->setDate(new \DateTime());
|
||||
$followup->setStats($statsGlobal);
|
||||
|
||||
$this->entityManager->persist($followup);
|
||||
|
||||
// Créer un followup pour la pente
|
||||
$followupSlope = new CityFollowUp();
|
||||
$followupSlope->setName('regression_slope');
|
||||
$followupSlope->setMeasure($data['slope']);
|
||||
$followupSlope->setDate(new \DateTime());
|
||||
$followupSlope->setStats($statsGlobal);
|
||||
|
||||
$this->entityManager->persist($followupSlope);
|
||||
|
||||
// Créer un followup pour l'ordonnée à l'origine
|
||||
$followupIntercept = new CityFollowUp();
|
||||
$followupIntercept->setName('regression_intercept');
|
||||
$followupIntercept->setMeasure($data['intercept']);
|
||||
$followupIntercept->setDate(new \DateTime());
|
||||
$followupIntercept->setStats($statsGlobal);
|
||||
|
||||
$this->entityManager->persist($followupIntercept);
|
||||
|
||||
$this->entityManager->flush();
|
||||
|
||||
return new JsonResponse([
|
||||
'success' => true,
|
||||
'message' => 'Données de régression enregistrées avec succès',
|
||||
'followup' => [
|
||||
'id' => $followup->getId(),
|
||||
'name' => $followup->getName(),
|
||||
'measure' => $followup->getMeasure(),
|
||||
'date' => $followup->getDate()->format('Y-m-d H:i:s')
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/modify/{osm_object_id}/{version}/{changesetID}', name: 'app_public_submit')]
|
||||
public function submit($osm_object_id, $version, $changesetID): Response
|
||||
{
|
||||
|
|
@ -666,7 +807,7 @@ class PublicController extends AbstractController
|
|||
$followups = $stats->getCityFollowUps();
|
||||
$countData = [];
|
||||
$completionData = [];
|
||||
|
||||
|
||||
foreach ($followups as $fu) {
|
||||
if ($fu->getName() === $theme . '_count') {
|
||||
$countData[] = [
|
||||
|
|
@ -849,4 +990,47 @@ class PublicController extends AbstractController
|
|||
'places_6mois' => $places_6mois,
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/rss/demandes', name: 'app_public_rss_demandes')]
|
||||
public function rssDemandes(): Response
|
||||
{
|
||||
$demandes = $this->entityManager->getRepository(Demande::class)->findAllOrderedByCreatedAt();
|
||||
|
||||
$content = $this->renderView('public/rss/demandes.xml.twig', [
|
||||
'demandes' => $demandes,
|
||||
'base_url' => $this->getParameter('router.request_context.host'),
|
||||
]);
|
||||
|
||||
$response = new Response($content);
|
||||
$response->headers->set('Content-Type', 'application/rss+xml');
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
#[Route('/cities', name: 'app_public_cities')]
|
||||
public function cities(): Response
|
||||
{
|
||||
$stats = $this->entityManager->getRepository(Stats::class)->findAll();
|
||||
|
||||
// Prepare data for the map
|
||||
$citiesForMap = [];
|
||||
foreach ($stats as $stat) {
|
||||
if ($stat->getZone() !== 'undefined' && preg_match('/^\d+$/', $stat->getZone())) {
|
||||
$citiesForMap[] = [
|
||||
'name' => $stat->getName(),
|
||||
'zone' => $stat->getZone(),
|
||||
'lat' => $stat->getLat(),
|
||||
'lon' => $stat->getLon(),
|
||||
'placesCount' => $stat->getPlacesCount(),
|
||||
'completionPercent' => $stat->getCompletionPercent(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $this->render('public/cities.html.twig', [
|
||||
'stats' => $stats,
|
||||
'citiesForMap' => $citiesForMap,
|
||||
'maptiler_token' => $_ENV['MAPTILER_TOKEN'] ?? null,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue