<?php
namespace App\Controller\Api\AdresseIncomming;
use DateTime;
use App\Service\HierarchyService;
use App\Repository\UserRepository;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpKernel\KernelInterface;
use App\Repository\NmdAdressesIncommingRepository;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
class AdresseIncommingHierarchyController extends AbstractController
{
private $adresseRepository;
private $userRepository;
private $hierarchyService;
public function __construct(
NmdAdressesIncommingRepository $adresseRepository,
UserRepository $userRepository,
HierarchyService $hierarchyService
) {
$this->adresseRepository = $adresseRepository;
$this->userRepository = $userRepository;
$this->hierarchyService = $hierarchyService;
}
public function __invoke(int $idUser, KernelInterface $kernel, Request $request): JsonResponse
{
$user = $this->userRepository->find($idUser);
if (!$user) {
return new JsonResponse(['error' => 'Utilisateur introuvable'], 404);
}
$userRoles = $user->getRoles();
$cpv = $request->query->get('cpv');
$migrable = strtoupper($request->query->get('migrable', 'NON')) === 'OUI';
// Cas sans cpv et utilisateur avec rôle organisation
if (!$cpv && in_array('ROLE_ORGANISATION', $userRoles)) {
$data = $migrable
? $this->adresseRepository->getGlobalHierarchyMigrable()
: $this->adresseRepository->getGlobalHierarchy();
return new JsonResponse($data ?? [], 200);
}
// Cas avec rôles manager/director/seller
if ($this->hasManagementRole($userRoles)) {
return $this->handleManagerData($idUser, $kernel, $request, $migrable);
}
// Cas avec cpv
return $this->handleHierarchyData($kernel, $request, $cpv, $migrable);
}
private function hasManagementRole(array $roles): bool
{
$managementRoles = ['ROLE_MANAGER', 'ROLE_DIRECTOR', 'ROLE_SELLER'];
return !empty(array_intersect($managementRoles, $roles));
}
private function handleManagerData(int $idUser, KernelInterface $kernel, Request $request, bool $migrable): JsonResponse
{
$userIds = array_unique(array_merge(
[$idUser],
array_map(fn($p) => (int) $p['id'], $this->hierarchyService->getHierarchyDescendante($idUser))
));
$cpv = $request->query->get('cpv');
$baseDir = $kernel->getProjectDir() . "/fileAttached/geo_map/prises_neuves/{$cpv}/distributed_by_user";
$codeCluster = $request->query->get('codeCluster');
$codeInsee = $request->query->get('codeInsee');
if ($codeCluster && $codeInsee) {
$semaine = $request->query->get('semaine');
return new JsonResponse(
$this->mergeDistributedVoiesFiles($userIds, $baseDir, $codeCluster, $codeInsee, $semaine, $migrable),
200
);
}
return new JsonResponse($this->mergeDistributedClusters($userIds, $baseDir, $migrable), 200);
}
private function handleHierarchyData(KernelInterface $kernel, Request $request, string $cpv, bool $migrable): JsonResponse
{
$baseDir = $kernel->getProjectDir() . "/fileAttached/geo_map/prises_neuves/{$cpv}";
$hierarchyFile = $migrable
? "$baseDir/migrables/hierarchy_cluster_city_migrable.json"
: "$baseDir/hierarchy_clusters_cities.json";
if (!file_exists($hierarchyFile)) {
return new JsonResponse(['error' => "Fichier hiérarchie introuvable"], 200);
}
$jsonData = json_decode(file_get_contents($hierarchyFile), true);
if (empty($jsonData)) {
return new JsonResponse(['error' => "Fichier hiérarchie vide ou invalide"], 200);
}
$semaine = $request->query->get('semaine');
if (!$semaine) {
return new JsonResponse($jsonData, 200);
}
return $this->filterByHierarchy($jsonData, $request, $kernel, $cpv, $migrable);
}
private function filterByHierarchy(array $jsonData, Request $request, KernelInterface $kernel, string $cpv, bool $migrable): JsonResponse
{
$semaine = $request->query->get('semaine');
$jour = $request->query->get('date');
$codeCluster = $request->query->get('codeCluster');
$codeInsee = $request->query->get('codeInsee');
$anneeActuelle = (new \DateTimeImmutable())->format('Y');
// Récupération des voies si codeCluster & codeInsee & semaine existent
if ($codeCluster && $codeInsee && $semaine) {
$baseDir = $kernel->getProjectDir() . "/fileAttached/geo_map/prises_neuves/{$cpv}";
$hierarchyFile = $migrable
? "$baseDir/migrables/voies/{$anneeActuelle}/S{$semaine}/{$codeCluster}/{$codeInsee}/liste_voies.json"
: "$baseDir/voies/{$anneeActuelle}/S{$semaine}/{$codeCluster}/{$codeInsee}/liste_voies.json";
if (!file_exists($hierarchyFile)) {
return new JsonResponse(['error' => "Fichier des voies introuvable"], 200);
}
$voiesData = json_decode(file_get_contents($hierarchyFile), true);
if (empty($voiesData)) {
return new JsonResponse(['error' => "Fichier des voies vide ou invalide"], 200);
}
return new JsonResponse($voiesData, 200);
} else {
//Filter v1
$semaines = array_values(array_filter($jsonData, fn($s) => ($s['numero_semaine'] ?? null) == $semaine));
if (empty($semaines)) {
return new JsonResponse([], 200);
}
if (!$jour) {
return new JsonResponse($semaines, 200);
}
$jours = [];
foreach ($semaines as $sem) {
$filteredDays = array_values(array_filter($sem['jours'] ?? [], fn($d) => ($d['date_jour'] ?? null) === $jour));
$jours = array_merge($jours, $filteredDays);
}
if (empty($jours)) {
return new JsonResponse([], 200);
}
if (!$codeCluster) {
return new JsonResponse($jours, 200);
}
$clusters = [];
foreach ($jours as $day) {
$filteredClusters = array_values(array_filter($day['clusters'] ?? [], fn($c) => ($c['clusterCode'] ?? null) === $codeCluster));
$clusters = array_merge($clusters, $filteredClusters);
}
if (empty($clusters)) {
return new JsonResponse([], 200);
}
if (!$codeInsee) {
return new JsonResponse($clusters[0], 200);
}
// Si on arrive ici, on retourne la ville trouvée
$villes = [];
foreach ($clusters as $cluster) {
$filteredVilles = array_values(array_filter($cluster['villes'] ?? [], fn($v) => ($v['cod_insee'] ?? null) == $codeInsee));
$villes = array_merge($villes, $filteredVilles);
}
return new JsonResponse($villes[0] ?? [], 200);
}
}
private function mergeDistributedClusters(array $userIds, string $baseDir, bool $isMigrable): array
{
$subdir = $isMigrable ? 'distributed_hierarchy_cluster_city_migrable.json' : 'distributed_hierarchy_cluster_city.json';
foreach ($userIds as $uid) {
$file = "{$baseDir}/{$uid}/{$subdir}";
if (!file_exists($file)) continue;
$data = json_decode(file_get_contents($file), true);
if (is_array($data)) {
return $data;
}
}
return [];
}
private function mergeDistributedVoiesFiles(array $userIds, string $baseDir, string $codeCluster, string $codeInsee, ?int $semaine, bool $isMigrable): array
{
$subdir = $isMigrable ? 'voies_migrable' : 'voies';
foreach ($userIds as $uid) {
$file = "{$baseDir}/{$subdir}/{$uid}/semaine_{$semaine}/{$codeCluster}/{$codeInsee}/liste_voies.json";
if (!file_exists($file)) continue;
$data = json_decode(file_get_contents($file), true);
if (is_array($data)) {
return $data;
}
}
return [];
}
/**
* @Route("/api/adresses-incomming-streets/{idUser}", name="api_get_adresse_incoming_streets_from_json", methods={"GET"})
*/
public function getAdressesIncomingStreetsFromJson(int $idUser, KernelInterface $kernel, Request $request): JsonResponse
{
$migrable = strtoupper($request->query->get('migrable', 'NON'));
$cpv = $request->query->get('cpv', null);
$semaine = $request->query->get('semaine', null);
$jour = $request->query->get('date', null);
$codeCluster = $request->query->get('codeCluster', null);
$codeInsee = $request->query->get('codeInsee', null);
$projectDir = $kernel->getProjectDir();
$anneeActuelle = (new \DateTimeImmutable())->format('Y');
$result = []; // Initialisation de la variable résultat
$user = $this->userRepository->find($idUser);
if (!$user) {
$result = ['error' => 'Utilisateur introuvable'];
return new JsonResponse($result, 404);
}
if (!$cpv) {
$result = ['error' => 'CPV manquant'];
return new JsonResponse($result, 400);
}
$baseDir = "$projectDir/fileAttached/geo_map/prises_neuves/{$cpv}";
if ($codeCluster && $codeInsee) {
$voiesFile = $migrable === 'OUI'
? "$baseDir/migrables/voies/$anneeActuelle/$semaine/$jour/$codeCluster/$codeInsee/liste_voies.json"
: "$baseDir/voies/$anneeActuelle/$semaine/$jour/$codeCluster/$codeInsee/liste_voies.json";
if (!file_exists($voiesFile)) {
$result = ['error' => "Fichier voies introuvable"];
return new JsonResponse($result, 404);
}
$voiesData = json_decode(file_get_contents($voiesFile), true);
if ($voiesData === null && json_last_error() !== JSON_ERROR_NONE) {
$result = ['error' => "Fichier voies vide ou invalide"];
return new JsonResponse($result, 400);
}
$result = $voiesData;
}
return new JsonResponse($result, 200);
}
/**
* @Route("/api/adresses-incomming-hierarchy-by-anciennete/{cpv}", name="api_get_adresse_incomming_hierarchy_by_anciennete_from_json", methods={"GET"})
*/
public function getHierarchyByAncienneteFromJson(
int $cpv,
KernelInterface $kernel,
Request $request
): JsonResponse {
$filePath = $kernel->getProjectDir() . "/fileAttached/geo_map/prises_neuves/{$cpv}/anciennete/anciennete.json";
if (!file_exists($filePath)) {
return new JsonResponse(['error' => 'Fichier non trouvé'], 200);
}
$jsonData = json_decode(file_get_contents($filePath), true);
if ($jsonData === null) {
return new JsonResponse(['error' => 'Erreur de lecture du JSON'], 200);
}
// Récupérer les paramètres de l'intervalle d'ancienneté
$debutAnciennete = $request->query->get('debutAnciennete', null);
$finAnciennete = $request->query->get('finAnciennete', null);
$codeCluster = $request->query->get('codeCluster', null);
$codeInsee = $request->query->get('codeInsee', null);
// Vérification des paramètres d'intervalle d'ancienneté
if ($debutAnciennete != null && $finAnciennete != null && $debutAnciennete <= $finAnciennete) {
// Convertir debutAnciennete et finAnciennete en nombre (supporter négatif et positif)
$debutAnciennete = floatval($debutAnciennete);
$finAnciennete = floatval($finAnciennete);
// Tableaux pour la combinaison des clusters et totalPrises
$finalClusters = [];
$finalTotalPrises = 0;
// Filtrer et combiner les clusters pour les niveaux d'ancienneté dans l'intervalle
foreach ($jsonData as $key => $data) {
$keyAnciennete = floatval($key); // S'assurer que la clé est un nombre
if ($keyAnciennete >= $debutAnciennete && $keyAnciennete <= $finAnciennete) {
// Ajouter les clusters de cet ancienneté
foreach ($data['clusters'] as $cluster) {
$clusterCode = $cluster['code_cluster'];
// Si le cluster existe déjà, on additionne le totalPrises
if (isset($finalClusters[$clusterCode])) {
// Ajouter les villes et additionner les prises des villes existantes
foreach ($cluster['villes'] as $ville) {
$villeCode = $ville['cod_insee'];
$foundVille = false;
// Si la ville existe déjà, on additionne son totalPrises
foreach ($finalClusters[$clusterCode]['villes'] as &$existingVille) {
if ($existingVille['cod_insee'] === $villeCode) {
$existingVille['totalPrises'] += $ville['totalPrises'];
$foundVille = true;
break;
}
}
// Si la ville n'existe pas encore, on l'ajoute
if (!$foundVille) {
$finalClusters[$clusterCode]['villes'][] = $ville;
}
}
// Additionner les totalPrises du cluster
$finalClusters[$clusterCode]['totalPrises'] += $cluster['totalPrises'];
} else {
// Si le cluster n'existe pas encore, on l'ajoute avec ses villes
$finalClusters[$clusterCode] = [
'code_cluster' => $cluster['code_cluster'],
'libelle_cluster' => $cluster['libelle_cluster'],
'totalPrises' => $cluster['totalPrises'],
'villes' => $cluster['villes'],
];
}
// Additionner les prises du cluster à la somme globale
$finalTotalPrises += $cluster['totalPrises'];
}
}
}
// Si aucun cluster n'a été trouvé dans l'intervalle, renvoyer une erreur
if (empty($finalClusters)) {
return new JsonResponse('Aucun cluster trouvé dans l\'intervalle d\'ancienneté', 200);
}
$jsonDataByAncinneteRange = [
'totalPrises' => $finalTotalPrises,
'clusters' => array_values($finalClusters),
];
// Si codeCluster est fourni, rechercher le cluster correspondant
if ($codeCluster) {
$cluster = array_filter($jsonDataByAncinneteRange['clusters'], function ($c) use ($codeCluster) {
return $c['code_cluster'] === $codeCluster;
});
if (empty($cluster)) {
return new JsonResponse(['Cluster non trouvé'], 200);
}
$cluster = array_values($cluster)[0]; // Récupérer le premier élément
// Si codeInsee est fourni, rechercher la ville correspondante
if ($codeInsee) {
$ville = array_filter($cluster['villes'], function ($v) use ($codeInsee) {
return $v['cod_insee'] === $codeInsee;
});
if (empty($ville)) {
return new JsonResponse(['error' => 'Ville non trouvée'], 200);
}
return new JsonResponse(array_values($ville)[0], 200);
}
return new JsonResponse($cluster, 200);
}
// Retourner la réponse finale avec totalPrises et clusters combinés
return new JsonResponse($jsonDataByAncinneteRange, 200);
}
return new JsonResponse($jsonData, 200);
}
/**
* @Route("/api/adresses-incomming-streets-by-anciennete/{cpv}/{codeCluster}/{codeInsee}", name="api_get_adresses_incomming_voies_by_anciennete_from_json", methods={"GET"})
*/
public function getInterventionPlaceVoiesFromJson(int $cpv, string $codeCluster, $codeInsee, KernelInterface $kernel, Request $request): JsonResponse
{
$filePath = $kernel->getProjectDir() . "/fileAttached/geo_map/prises_neuves/{$cpv}/anciennete/voies/{$codeCluster}/{$codeInsee}/liste_voies.json";
if (!file_exists($filePath)) {
return new JsonResponse(['error' => 'Fichier non trouvé'], 200);
}
$anciennete = $request->query->get('anciennete', null);
// Lire et décoder le fichier JSON
$jsonData = json_decode(file_get_contents($filePath), true);
if ($jsonData === null) {
return new JsonResponse(['error' => 'Erreur de lecture du JSON'], 200);
}
if ($anciennete) {
if (!isset($jsonData[$anciennete])) {
return new JsonResponse(['error' => 'Ancienneté non trouvée'], 200);
}
return new JsonResponse($jsonData[$anciennete], 200);
}
// Renvoi des données paginées
return new JsonResponse($jsonData, 200);
}
/**
* @Route("/api/adresses-incomming-hierarchy-arret-cu-v2/{cpv}", name="api_get_adresses_incomming_arret_cu_from_json_v2", methods={"GET"})
*/
public function getHierrachyByArretCuFromJsonV2(int $cpv, KernelInterface $kernel, Request $request): JsonResponse
{
// Récupérer les paramètres de la requête
$codeCluster = $request->query->get('codeCluster', null);
$codeInsee = $request->query->get('codeInsee', null);
$annee = $request->query->get('annee', null);
$mois = $request->query->get('mois', null);
// Définir le chemin du fichier JSON principal
$filePath = $kernel->getProjectDir() . "/fileAttached/geo_map/prises_neuves/{$cpv}/arret_cu_v2/arret_cu.json";
if (!file_exists($filePath)) {
return new JsonResponse([], 200);
}
$jsonData = json_decode(file_get_contents($filePath), true);
if ($jsonData === null) {
return new JsonResponse([], 200);
}
// --- Filtrage par codeCluster ---
if ($codeCluster) {
$cluster = array_filter($jsonData, fn($c) => $c['code_cluster'] == $codeCluster);
if (count($cluster) < 1) {
return new JsonResponse([], 200);
}
$cluster = array_values($cluster)[0];
// --- Filtrage par codeInsee ---
if ($codeInsee) {
$ville = array_filter($cluster['villes'], fn($v) => $v['cod_insee'] == $codeInsee);
if (count($ville) < 1) {
return new JsonResponse([], 200);
}
$ville = array_values($ville)[0];
// --- Ici on ajoute l’appel à la 2e API ---
$streetsFilePath = $kernel->getProjectDir() . "/fileAttached/geo_map/prises_neuves/{$cpv}/arret_cu/voies/{$codeCluster}/{$codeInsee}/liste_voies.json";
if (file_exists($streetsFilePath)) {
$streetsData = json_decode(file_get_contents($streetsFilePath), true) ?? [];
// Filtrage par année et mois si demandé
if ($annee !== null && isset($streetsData[$annee])) {
$streetsData = $streetsData[$annee];
if ($mois !== null && isset($streetsData[$mois])) {
$streetsData = $streetsData[$mois];
}
}
// On enrichit la réponse avec les rues
$ville['voies'] = $streetsData;
}
return new JsonResponse($ville, 200);
}
return new JsonResponse($cluster, 200);
}
return new JsonResponse($jsonData, 200);
}
/**
* @Route("/api/adresses-incomming-hierarchy-arret-cu/{cpv}", name="api_get_adresses_incomming_arret_cu_from_json", methods={"GET"})
*/
public function getHierarchyArretCufromJson(int $cpv, KernelInterface $kernel, Request $request): JsonResponse
{
// Récupérer les paramètres de la requête
$annee = $request->query->get('annee', null);
$mois = $request->query->get('mois', null);
$codeCluster = $request->query->get('codeCluster', null);
$codeInsee = $request->query->get('codeInsee', null);
// Définir le chemin du fichier JSON principal
$filePath = $kernel->getProjectDir() . "/fileAttached/geo_map/prises_neuves/{$cpv}/arret_cu/arret_cu.json";
if (!file_exists($filePath)) {
return new JsonResponse([], 200);
}
$jsonData = json_decode(file_get_contents($filePath), true);
if ($jsonData === null) {
return new JsonResponse([], 200);
}
// Filtrage par année
if ($annee !== null && isset($jsonData[$annee])) {
$jsonDataAnnee = $jsonData[$annee];
// Filtrage par mois
if ($mois !== null && isset($jsonDataAnnee[$mois])) {
$jsonDataMois = $jsonDataAnnee[$mois];
// Filtrage par cluster
if ($codeCluster !== null && isset($jsonDataMois['clusters'])) {
$clusterData = null;
foreach ($jsonDataMois['clusters'] as $c) {
if ($c['code_cluster'] == $codeCluster) {
$clusterData = $c;
break;
}
}
// Filtrage par ville (codeInsee)
if ($clusterData !== null && $codeInsee !== null && isset($clusterData['villes'])) {
$villeData = null;
foreach ($clusterData['villes'] as $villeItem) {
if ($villeItem['cod_insee'] == $codeInsee) {
$villeData = $villeItem;
break;
}
}
// Si une ville est trouvée → chercher aussi les rues
if ($villeData !== null) {
$streetsFilePath = $kernel->getProjectDir() . "/fileAttached/geo_map/prises_neuves/{$cpv}/arret_cu/voies/{$codeCluster}/{$codeInsee}/liste_voies.json";
if (file_exists($streetsFilePath)) {
$streetsData = json_decode(file_get_contents($streetsFilePath), true) ?? [];
// Filtrage rues par année et mois
if ($annee !== null && isset($streetsData[$annee])) {
$streetsData = $streetsData[$annee];
if ($mois !== null && isset($streetsData[$mois])) {
$streetsData = $streetsData[$mois];
}
}
// Enrichir la ville avec ses voies
$villeData['voies'] = $streetsData;
}
return new JsonResponse($villeData, 200);
}
return new JsonResponse([], 200);
}
return new JsonResponse($clusterData ?? [], 200);
}
return new JsonResponse($jsonDataMois ?? [], 200);
} else {
return new JsonResponse(['error' => 'Mois non défini'], 404);
}
}
// Si pas de filtre → retourner le JSON complet
return new JsonResponse($jsonData, 200);
}
}