: historique des réalisations d'un contact, avec le * libellé de l'action (jointure sur ASP_Actions), trié du plus ancien * au plus récent. * POST : journalise une nouvelle réalisation (REA_IncrContact, REA_Action * obligatoires ; REA_Comment optionnel). REA_Date est déterminée côté * serveur (NOW()). * * ⚠️ Session utilisateur intégrée le 24 août 2026 (voir journal, sections 14 * et 15) : accès réservé aux utilisateurs identifiés, et REA_CodeUser est * désormais lu directement dans `$_SESSION['USR_Code']` (ouverte par * `aspic.php`) — le champ REA_CodeUser du corps de la requête POST n'est * plus utilisé et ne peut plus être falsifié par le client. Le "JMP" en dur * précédent a été supprimé (n'avait de sens que faute de session). * * REA_NomAffiche (7 septembre 2026, nuit) : Jean-Marc voulait voir "Jean-Marc" * plutôt que "JMP" dans l'historique d'un contact. Deux idées écartées en * cours de route : renommer USR_Code lui-même (trop structurant, utilisé * partout — session, REA_CodeUser, OPE_CodeUser...), et une jointure * ASP_Users refaite à chaque affichage (Jean-Marc : "comment vas-tu faire * pour les agents qui sont dans une autre base ?" — une jointure suppose que * tout vit dans la même base, hypothèse fragile). Solution retenue, dans les * mots de Jean-Marc : "si on stocke le prénom de l'utilisateur d'un côté et * le prénom de l'agent en dur on est cool" — un INSTANTANÉ pris UNE SEULE * FOIS à la création de la réalisation, jamais recalculé : * - Utilisateur humain : REA_NomAffiche = $_SESSION['USR_Prenom'], lui-même * posé une seule fois à la connexion (voir aspic.php) — aucune requête * supplémentaire ici, juste une lecture de session. * - Agent IA : REA_NomAffiche = le nom déjà en clair (CNS_Agent, voir * moteur_consignes.php et journaliserRealisationsIA() dans contacts.php) — * "en dur", aucune recherche à faire, la valeur existe déjà. * Nullable : une ligne plus ancienne, créée avant l'ajout de cette colonne, * n'en a pas — le front-end retombe alors sur REA_CodeUser tel quel (voir * liste_contacts.html, même principe que ACT_Libelle/REA_Action juste à * côté). */ session_start(); header('Content-Type: application/json; charset=utf-8'); require __DIR__ . '/db.php'; if (empty($_SESSION['USR_Code'])) { http_response_code(401); echo json_encode(['error' => 'Non identifié — veuillez vous connecter.']); exit; } $method = $_SERVER['REQUEST_METHOD']; try { $pdo = getDbConnection(); } catch (PDOException $e) { http_response_code(500); echo json_encode(['error' => 'Connexion base de données impossible']); exit; } try { switch ($method) { case 'GET': if (!isset($_GET['id'])) { http_response_code(400); echo json_encode(['error' => 'id (REA_IncrContact) manquant']); exit; } // REA_NomAffiche lu directement (voir commentaire d'en-tête) : // aucune jointure nécessaire, la colonne porte déjà la bonne // valeur depuis la création de la réalisation. $stmt = $pdo->prepare( 'SELECT r.REA_Incr, r.REA_Date, r.REA_CodeUser, r.REA_NomAffiche, r.REA_Action, r.REA_Comment, a.ACT_Libelle FROM ASP_Realisations r LEFT JOIN ASP_Actions a ON a.ACT_Code = r.REA_Action WHERE r.REA_IncrContact = ? ORDER BY r.REA_Date ASC' ); $stmt->execute([$_GET['id']]); echo json_encode(['realisations' => $stmt->fetchAll()]); break; case 'POST': $data = json_decode(file_get_contents('php://input'), true); $idContact = $data['REA_IncrContact'] ?? null; $action = $data['REA_Action'] ?? null; if (!$idContact || !$action) { http_response_code(400); echo json_encode(['error' => 'REA_IncrContact et REA_Action sont obligatoires']); exit; } // REA_CodeUser ET REA_NomAffiche viennent tous les deux de la // session (voir en-tête de ce fichier) — jamais du corps de la // requête, impossible pour le client de se faire passer pour un // autre utilisateur. REA_NomAffiche = USR_Prenom posé une seule // fois à la connexion (aspic.php) : aucune requête supplémentaire // ici. $codeUser = $_SESSION['USR_Code']; $nomAffiche = $_SESSION['USR_Prenom'] ?? null; $commentaire = $data['REA_Comment'] ?? ''; $stmt = $pdo->prepare( 'INSERT INTO ASP_Realisations (REA_IncrContact, REA_CodeUser, REA_NomAffiche, REA_Date, REA_Action, REA_Comment) VALUES (?, ?, ?, NOW(), ?, ?)' ); $stmt->execute([$idContact, $codeUser, $nomAffiche, $action, $commentaire]); echo json_encode(['id' => (int)$pdo->lastInsertId()]); break; default: http_response_code(405); echo json_encode(['error' => 'Méthode non autorisée']); } } catch (PDOException $e) { // Toute exception PDO (ex. REA_Action trop long pour la colonne, valeur // rejetée par une contrainte) renvoie du JSON exploitable côté front // plutôt qu'une erreur PHP brute — voir contacts.php pour le même // correctif du 24 août 2026. http_response_code(500); echo json_encode(['error' => 'Erreur base de données : ' . $e->getMessage()]); }