143 lines
5.7 KiB
PHP
143 lines
5.7 KiB
PHP
global$config; #!/usr/bin/env php
|
||
<?php
|
||
|
||
/**
|
||
* @var array $config
|
||
* @var array $teams
|
||
* @var string[] $holidays
|
||
*/
|
||
|
||
use GuzzleHttp\Client;
|
||
use GuzzleHttp\Exception\GuzzleException;
|
||
use Nechaev\Reports\StatusHelper;
|
||
|
||
require __DIR__ . '/../init.php';
|
||
require __DIR__ . '/functions.php';
|
||
|
||
// --- 1. Обработка параметров командной строки ---
|
||
$options = getopt('', ['start-date:', 'end-date:']);
|
||
|
||
if (empty($options['start-date']) || empty($options['end-date'])) {
|
||
echo "Использование: php jira_export.php --start-date=ГГГГ-ММ-ДД --end-date=ГГГГ-ММ-ДД\n";
|
||
exit(1);
|
||
}
|
||
|
||
$startDate = $options['start-date'];
|
||
$endDate = $options['end-date'];
|
||
|
||
// Валидация формата дат
|
||
if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $startDate) || !preg_match('/^\d{4}-\d{2}-\d{2}$/', $endDate)) {
|
||
die("Ошибка: даты должны быть в формате ГГГГ-ММ-ДД\n");
|
||
}
|
||
|
||
// Извлекаем настройки из конфига
|
||
$jiraUrl = $config['jira']['url'];
|
||
$apiToken = $config['jira']['apiToken'];
|
||
$maxResults = $config['export']['maxResults'];
|
||
|
||
// --- 2. Инициализация клиента Guzzle ---
|
||
$client = new Client([
|
||
'base_uri' => $jiraUrl,
|
||
'headers' => [
|
||
'Authorization' => 'Bearer ' . $apiToken,
|
||
'Accept' => 'application/json',
|
||
],
|
||
]);
|
||
|
||
foreach ($teams as $team => $teamData) {
|
||
echo "Расчет для команды {$team}\n";
|
||
$filename = "{$team}_tasks_{$startDate}_to_{$endDate}.csv";
|
||
|
||
// --- 3. Подготовка JQL-запроса ---
|
||
// Запрос ищет задачи, у которых статус изменился на "Done" в указанный период.
|
||
$jql = "project in (".$teamData['projects'].") AND issuetype in standardIssueTypes() AND issuetype not in (Epic, \"Admin work\") AND resolutiondate > \"{$startDate}\" AND resolutiondate < \"{$endDate}\"";
|
||
|
||
$params = [
|
||
'jql' => $jql,
|
||
'maxResults' => $maxResults,
|
||
'fields' => 'issuetype,key,summary,assignee,resolution,aggregatetimeoriginalestimate,aggregateprogress,resolutiondate',
|
||
];
|
||
|
||
try {
|
||
// --- 4. Обработка пагинации ---
|
||
// Если задач больше, чем maxResults, Jira вернет только часть.
|
||
// Мы будем запрашивать страницы до тех пор, пока не получим все.
|
||
$allIssues = [];
|
||
$startAt = 0;
|
||
$totalFetched = 0;
|
||
|
||
do {
|
||
$response = $client->get('rest/api/2/search', [
|
||
'query' => $params + ['startAt' => $startAt]
|
||
]);
|
||
|
||
$data = json_decode($response->getBody(), true);
|
||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||
throw new Exception("Ошибка декодирования JSON-ответа от Jira.");
|
||
}
|
||
|
||
$issues = $data['issues'] ?? [];
|
||
$allIssues = array_merge($allIssues, $issues);
|
||
|
||
// Обновляем счетчики для следующей итерации
|
||
$totalFetched += count($issues);
|
||
$startAt += count($issues);
|
||
|
||
echo "Получено задач: {$totalFetched} из {$data['total']}\n";
|
||
|
||
} while ($startAt < ($data['total'] ?? 0));
|
||
|
||
if (!empty($allIssues)) {
|
||
// Убираем дубликаты, там где изменения не требуются
|
||
$allIssues = filterByResolution($allIssues);
|
||
|
||
// Убираем задачи, исполнители на которых не исполнители
|
||
$allIssues = filterByExecutors($allIssues, array_keys($teamData['executors']));
|
||
|
||
//file_put_contents($filename.".json", json_encode($allIssues, JSON_PRETTY_PRINT));die();
|
||
|
||
echo "Убрали лишнее, осталось ".count($allIssues)."\n";
|
||
|
||
$task = null;
|
||
foreach ($allIssues as $i => $issue) {
|
||
$statuses = getStatusForIssue($issue['key'], $client);
|
||
//$allIssues[$i]['countStatuses'] = $statuses;
|
||
$firstDateInStatus = array_map(function($value) {
|
||
return is_array($value) && count($value) > 1 ? $value[1] : null;
|
||
}, $statuses);
|
||
|
||
$countStatus = array_map(function($value) {
|
||
return is_array($value) && count($value) > 1 ? $value[0] : null;
|
||
}, $statuses);
|
||
|
||
$task = new \Nechaev\Reports\Task(
|
||
$issue["fields"]["issuetype"]["name"],
|
||
$issue['key'],
|
||
$issue["fields"]["summary"],
|
||
$issue["fields"]["assignee"]["name"],
|
||
$issue["fields"]["aggregatetimeoriginalestimate"],
|
||
$issue["fields"]["aggregateprogress"]["progress"],
|
||
StatusHelper::getDataByStatus($firstDateInStatus, StatusHelper::getInWorkStatuses()),
|
||
$issue["fields"]["resolutiondate"],
|
||
StatusHelper::getDataByStatus($countStatus, StatusHelper::getInReviewStatuses()),
|
||
StatusHelper::getDataByStatus($countStatus, StatusHelper::getInTestingStatuses()),
|
||
);
|
||
file_put_contents($filename, $task, FILE_APPEND | LOCK_EX);
|
||
}
|
||
|
||
|
||
|
||
// --- 5. Сохранение в файл ---
|
||
|
||
|
||
echo "Данные успешно сохранены в файл: {$filename}\n";
|
||
} else {
|
||
echo "За указанный период завершенных задач не найдено.\n";
|
||
}
|
||
|
||
} catch (GuzzleException | Exception $e) {
|
||
echo "Ошибка: " . $e->getMessage() . "\n";
|
||
}
|
||
|
||
}
|