baseUrl = env('JIRA_BASE_URL'); $this->authHeader = 'Basic ' . base64_encode(env('JIRA_USERNAME') . ':' . env('JIRA_API_TOKEN')); $this->client = new Client([ 'base_uri' => $this->baseUrl, 'headers' => [ 'Authorization' => $this->authHeader, 'Accept' => 'application/json', 'Content-Type' => 'application/json' ], 'timeout' => 60, // Tăng thời gian timeout lên 60 giây 'connect_timeout' => 30 // Tăng thời gian chờ kết nối lên 30 giây ]); } public function getAllProjects() { $response = $this->client->get('/rest/api/3/project'); return json_decode($response->getBody()->getContents(), true); } public function getIssuesAsync($projectKey, $startAt = 0, $maxResults = 50) { $body = [ 'expand' => ['names', 'schema', 'operations'], 'fields' => ['summary', 'status', 'description', 'timeoriginalestimate', 'timespent', 'worklog', 'assignee'], 'jql' => "project = '{$projectKey}' ORDER BY created DESC", 'maxResults' => $maxResults, 'startAt' => $startAt ]; return $this->client->postAsync($this->baseUrl . '/rest/api/3/search', [ 'body' => json_encode($body), 'headers' => [ 'Authorization' => $this->authHeader, 'Accept' => 'application/json', 'Content-Type' => 'application/json' ] ]); } public function getIssues($projectKey, $startAt = 0) { $body = [ 'expand' => ['names', 'schema', 'operations'], 'fields' => ['summary', 'status', 'description', 'timeoriginalestimate', 'timespent', 'worklog', 'assignee'], 'jql' => "project = '{$projectKey}' ORDER BY created DESC", 'maxResults' => 100, 'startAt' => $startAt ]; $response = $this->client->post('/rest/api/3/search', [ 'body' => json_encode($body) ]); return json_decode($response->getBody()->getContents(), true); } public function getIssuesByUser($accountId, $startAt = 0) { $body = [ 'expand' => ['names', 'schema', 'operations'], 'fields' => ['summary', 'status', 'timeoriginalestimate', 'timespent', 'assignee', 'project'], 'jql' => sprintf( "assignee = '%s' AND status IN ('backlog', 'to do', 'in progress')", $accountId ), 'maxResults' => 50, 'startAt' => $startAt ]; $response = $this->client->post('/rest/api/3/search', [ 'body' => json_encode($body) ]); $issues = json_decode($response->getBody()->getContents(), true); foreach ($issues['issues'] as &$issue) { $issueKey = $issue['key']; $issueResponse = $this->client->get("/rest/api/3/issue/{$issueKey}?expand=changelog"); $issueDetails = json_decode($issueResponse->getBody()->getContents(), true); $issue['changelog'] = $issueDetails['changelog']; } return $issues; } public function getAllUsers() { $response = $this->client->get('/rest/api/3/users/search', [ 'headers' => [ 'Authorization' => $this->authHeader, 'Accept' => 'application/json' ] ]); return json_decode($response->getBody()->getContents(), true); } public function getUserByEmail($email) { $response = $this->client->get("/rest/api/3/user/search?query={$email}", [ 'headers' => [ 'Authorization' => $this->authHeader, 'Accept' => 'application/json' ] ]); if ($response->getStatusCode() == 200) { return json_decode($response->getBody(), true); } return null; } public function getUsersByEmails($all_users) { $users = []; foreach ($all_users as $user) { $user_info = $this->getUserByEmail($user->email); if (isset($user_info[0]['self'])) { $user_info[0]['emailAddress'] = $user->email; $users[] = $user_info; } } return $users; } public function getUserWorkLogs($accountId, $startDate, $endDate) { $body = [ 'jql' => "worklogAuthor = '{$accountId}'AND worklogDate >= '{$startDate}' AND worklogDate <= '{$endDate}'", 'fields' => ['summary', 'status', 'timeoriginalestimate', 'timespent', 'project'], 'maxResults' => 100 ]; $response = $this->client->post('/rest/api/3/search', [ 'body' => json_encode($body), 'headers' => [ 'Authorization' => $this->authHeader, 'Accept' => 'application/json', 'Content-Type' => 'application/json' ] ]); $data_response = json_decode($response->getBody()->getContents(), true); if ($data_response['total'] == 0) { return $data_response; } $promises = []; foreach ($data_response['issues'] as $index => $issue) { $issueId = $issue['id']; // Get the initial worklog data to determine total number of worklogs $promises[$index] = $this->client->getAsync("/rest/api/3/issue/{$issueId}/worklog", [ 'query' => [ 'startAt' => 0, 'maxResults' => 1 ] ])->then(function ($checkApiResponse) use ($issueId, $index) { $checkApi = json_decode($checkApiResponse->getBody()->getContents(), true); $maxResults = 100; $totalWorklogs = $checkApi['total']; return $this->client->getAsync("/rest/api/3/issue/{$issueId}/worklog", [ 'query' => [ 'startAt' => $totalWorklogs - $maxResults, 'maxResults' => $totalWorklogs ] ])->then(function ($worklogResponse) use ($index) { return [ 'index' => $index, 'worklogs' => json_decode($worklogResponse->getBody()->getContents(), true) ]; }); }); } // Wait for all promises to complete $results = Utils::settle($promises)->wait(); // Attach worklogs to issues foreach ($results as $result) { if ($result['state'] === 'fulfilled') { $data_response['issues'][$result['value']['index']]["fields"]['worklog'] = $result['value']['worklogs']; } } return $data_response; } public function getAllUserWorkLogs($startDate, $endDate) { $users = $this->getAllUsers(); $workLogs = []; foreach ($users as $user) { $userWorkLogs = $this->getUserWorkLogs($user['accountId'], $startDate, $endDate); $assignTask = []; if (count($userWorkLogs['issues']) > 0) { $assignTask = $this->getIssuesByUser($user['accountId']); $workLogs[] = ['username' => $user['displayName'], 'information' => $userWorkLogs, 'tasksAssign' => $assignTask, 'user' => $user]; } } return $workLogs; } public function getAllUserDoing() { $users = UserJiraCacheHelper::getCacheSetting(); $groupedIssues = []; $users_data = []; $user_warning = []; $ignore_projects = ['PJ_tracking']; foreach ($users as $user) { $user = (array) $user[0]; $users_data[$user['displayName']]['user'] = $user; $users_data[$user['displayName']]['total_spent'] = 0; $users_data[$user['displayName']]['total_est'] = 0; $body = [ 'expand' => ['names', 'schema', 'changelog'], 'fields' => ['summary', 'status', 'timeoriginalestimate', 'timespent', 'assignee', 'project', 'updated'], 'jql' => sprintf( "assignee = '%s' AND status IN ('to do', 'todo', 'in progress') ORDER BY updated DESC", $user['accountId'] ), 'maxResults' => 50, 'startAt' => 0 ]; $response = $this->client->post('/rest/api/3/search', [ 'body' => json_encode($body) ]); $issues = json_decode($response->getBody()->getContents(), true); // Lọc các issue không thuộc các project bị ignore $filtered_issues = array_filter($issues['issues'], function ($issue) use ($ignore_projects) { return !in_array($issue['fields']['project']['name'], $ignore_projects); }); $issues['issues'] = $filtered_issues; if (count($issues['issues']) == 0) { $user_warning[] = $user; } foreach ($issues['issues'] as $issue) { $projectName = $issue['fields']['project']['name']; if (!in_array($projectName, $ignore_projects)) { $username = $issue['fields']['assignee']['displayName']; $issue['fields']['assignee']['emailAddress'] = $user['emailAddress']; if (!isset($groupedIssues[$projectName])) { $groupedIssues[$projectName] = []; $groupedIssues[$projectName]['project'] = $issue['fields']['project']; } if (!isset($groupedIssues[$projectName]['users'][$username])) { $groupedIssues[$projectName]['users'][$username] = []; $groupedIssues[$projectName]['users'][$username]['user'] = $issue['fields']['assignee']; $groupedIssues[$projectName]['users'][$username]['p_total_spent'] = 0; $groupedIssues[$projectName]['users'][$username]['p_total_est'] = 0; } $groupedIssues[$projectName]['users'][$username]['issues'][] = $issue; $groupedIssues[$projectName]['users'][$username]['p_total_spent'] = $groupedIssues[$projectName]['users'][$username]['p_total_spent'] + $issue['fields']['timespent']; $groupedIssues[$projectName]['users'][$username]['p_total_est'] = $groupedIssues[$projectName]['users'][$username]['p_total_est'] + ($issue['fields']['timeoriginalestimate'] ?? 0); $users_data[$user['displayName']]['total_spent'] = $users_data[$user['displayName']]['total_spent'] + $issue['fields']['timespent']; $users_data[$user['displayName']]['total_est'] = $users_data[$user['displayName']]['total_est'] + ($issue['fields']['timeoriginalestimate'] ?? 0); } } } return ['projects' => $groupedIssues, 'users' => $users_data, 'warningList' => $user_warning]; } public function getDetailIssueByKey($issueKey) { $issueResponse = $this->client->get("/rest/api/3/issue/{$issueKey}?expand=changelog"); $issueDetail = json_decode($issueResponse->getBody()->getContents(), true); return $issueDetail; } public function getDetailsProjectsById($id) { $response = $this->client->get('/rest/api/3/project/' . $id); return json_decode($response->getBody()->getContents(), true); } public function getAllBoardByIdProjects($id) { $response = $this->client->get('/rest/agile/1.0/board?projectKeyOrId=' . $id); return json_decode($response->getBody()->getContents(), true); } public function getAllSprintByIdBoard($id) { $response = $this->client->get('/rest/agile/1.0/board/' . $id . '/sprint'); return json_decode($response->getBody()->getContents(), true); } public function getAllIssueByIdSprint($id) { $response = $this->client->get('/rest/agile/1.0/sprint/' . $id . '/issue'); return json_decode($response->getBody()->getContents(), true); } public function getWeeklyReport() { $body = [ 'fields' => ['summary', 'status', 'timeoriginalestimate', 'timespent', 'assignee', 'project', 'worklog'], 'jql' => 'worklogDate >= startOfWeek() AND worklogDate < startOfWeek(1) order by created DESC', 'maxResults' => 1000 ]; $response = $this->client->post('/rest/api/3/search', [ 'body' => json_encode($body) ]); return json_decode($response->getBody()->getContents(), true); } }