0) { // Début = exactement $nbAnnees années avant "maintenant" $start = (clone $now)->modify('-' . $nbAnnees . ' years'); // On met des heures/minutes pour éviter l'ambiguïté minuit UTC $startStr = $start->format('Y-m-d H:i'); // Fin = maintenant $endStr = $now->format('Y-m-d H:i'); $jql = sprintf( 'project = %s AND reporter = "%s" AND created >= "%s" AND created <= "%s" ORDER BY status ASC, created DESC', $projectKey, $email, $startStr, $endStr ); } else { // Pas de limite de date $jql = sprintf( 'project = %s AND reporter = "%s" ORDER BY status ASC, created DESC', $projectKey, $email ); } $url = $jiraDomain . '/rest/api/3/search?jql=' . urlencode($jql) . '&maxResults=100'; $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Authorization: Basic ' . base64_encode("$userEmail:$apiToken"), 'Content-Type: application/json' ]); $response = curl_exec($ch); $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); $result = json_decode($response, true); $ticketsOuverts = []; $ticketsResolus = []; if ($httpcode == 200 && isset($result['issues'])) { foreach ($result['issues'] as $issue) { $ticket = [ 'key' => $issue['key'], 'summary' => $issue['fields']['summary'], 'status' => $issue['fields']['status']['name'], 'url' => $jiraDomain . '/browse/' . $issue['key'], 'created' => $issue['fields']['created'] ?? null, 'resolved' => $issue['fields']['resolutiondate'] ?? null ]; if (in_array(strtolower($ticket['status']), ['done', 'resolved', 'terminé', 'fermé', 'résolu', 'annulé'])) { $ticketsResolus[] = $ticket; } else { $ticketsOuverts[] = $ticket; } } return [ 'success' => true, 'ouverts' => $ticketsOuverts, 'resolus' => $ticketsResolus ]; } return [ 'success' => false, 'message' => $result['errorMessages'][0] ?? 'Erreur inconnue', 'debug' => $result ]; } /** * Recherche les tickets d’un reporter (email → accountId) avec la nouvelle API /search/jql. * Sortie: ['success'=>bool, 'ouverts'=>[], 'resolus'=>[], 'message'?, 'debug'?] */ function jira_get_tickets_by_email($email) { $jiraDomain = 'https://progiwebinc.atlassian.net'; $userEmail = 'stephan@progiweb.ca'; // Nom du jeton support_crm $apiToken = 'ATATT3xFfGF0Z91qESp8j7uO783qK0E4BWsY8rhPWEmexSa4Rw3c21Spg6hYIkmVgy6Vwzb34RxqFl3sR00Kby_DuY1NdcUJyfPQYZ0_JbeEjAk9ybFgNY8-MBSABMCxzaDk4szTbWupfjxHT8sJxJMvSNxgHPds5FxXaGo2DnZICZu5dXuvWbk=F73E15AE'; $projectKey = 'SM'; // --- Paramètre : nombre d'années à remonter --- $nbAnnees = 1; $tz = new DateTimeZone('America/Toronto'); $now = new DateTime('now', $tz); if ($nbAnnees > 0) { $start = (clone $now)->modify('-' . $nbAnnees . ' years'); $startStr = $start->format('Y-m-d H:i'); $endStr = $now->format('Y-m-d H:i'); $jql = sprintf( 'project = %s AND reporter = "%s" AND created >= "%s" AND created <= "%s" ORDER BY status ASC, created DESC', $projectKey, $email, $startStr, $endStr ); } else { $jql = sprintf( 'project = %s AND reporter = "%s" ORDER BY status ASC, created DESC', $projectKey, $email ); } // 🆕 Nouveau endpoint (POST JSON) $url = $jiraDomain . '/rest/api/3/search/jql'; $payload = [ 'jql' => $jql, 'maxResults' => 100, 'fields' => ['summary', 'status', 'created', 'resolutiondate'] ]; $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Authorization: Basic ' . base64_encode("$userEmail:$apiToken"), 'Content-Type: application/json', 'Accept: application/json' ]); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload)); $response = curl_exec($ch); $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); $result = json_decode($response, true); $ticketsOuverts = []; $ticketsResolus = []; // 🧩 même logique de sortie que ta version originale if ($httpcode == 200 && isset($result['issues'])) { foreach ($result['issues'] as $issue) { $ticket = [ 'key' => $issue['key'], 'summary' => $issue['fields']['summary'], 'status' => $issue['fields']['status']['name'], 'url' => $jiraDomain . '/browse/' . $issue['key'], 'created' => $issue['fields']['created'] ?? null, 'resolved' => $issue['fields']['resolutiondate'] ?? null ]; if (in_array(strtolower($ticket['status']), ['done', 'resolved', 'terminé', 'fermé', 'résolu', 'annulé'])) { $ticketsResolus[] = $ticket; } else { $ticketsOuverts[] = $ticket; } } return [ 'success' => true, 'ouverts' => $ticketsOuverts, 'resolus' => $ticketsResolus ]; } // ⚠️ même structure d’erreur que ta version originale return [ 'success' => false, 'message' => $result['errorMessages'][0] ?? 'Erreur inconnue', 'debug' => $result ]; } /** * Résout l’accountId (Cloud) pour un email donné. * Retourne null si non trouvé / non accessible. */ function jira_find_account_id_by_email($jiraDomain, $userEmail, $apiToken, $email) { $headers = [ 'Authorization: Basic ' . base64_encode("$userEmail:$apiToken"), 'Accept: application/json' ]; $url = $jiraDomain . '/rest/api/3/user/search?query=' . urlencode($email); $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); $response = curl_exec($ch); $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($httpcode !== 200) { return null; } $users = json_decode($response, true); if (is_array($users) && count($users) > 0) { foreach ($users as $u) { if (!empty($u['emailAddress']) && strcasecmp($u['emailAddress'], $email) === 0) { return $u['accountId'] ?? null; } } return $users[0]['accountId'] ?? null; } return null; }