ManagementSystem/BACKEND/app/Services/JiraService.php

344 lines
13 KiB
PHP

<?php
namespace App\Services;
use App\Helper\Cache\UserJiraCacheHelper;
use App\Models\User;
use GuzzleHttp\Client;
use GuzzleHttp\Promise\Utils;
class JiraService
{
protected $client;
protected $baseUrl;
protected $authHeader;
public function __construct()
{
$this->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);
}
}