reports/src/Features/Reports/ReportsApi.php

93 lines
3.6 KiB
PHP
Raw Normal View History

2026-06-19 17:23:25 +03:00
<?php declare(strict_types=1);
namespace Nechaev\Reports\Features\Reports;
use Nechaev\Reports\Core\App;
use Nechaev\Reports\Framework\Database\Database;
final class ReportsApi {
private Database $db;
public function __construct(?Database $db = null) {
$this->db = $db ?? App::getDb();
}
/**
* @return array<int, array{id: int, name: string}>
*/
public function getTeams(): array {
$rows = $this->db->getRowset(
'SELECT id, TRIM(team_name) AS name FROM teams ORDER BY TRIM(team_name)'
);
return array_map(
static fn (array $row): array => [
'id' => (int) $row['id'],
'name' => $row['name'],
],
$rows
);
}
/**
* @return array<int, array{
* id: int,
* jira_sprint_id: int,
* sprint_name: string,
* sprint_activate_datetime: string,
* sprint_complete_datetime: string,
* sprint_completion_percentage: float|null,
* lead_time_max: int|null,
* lead_time_min: int|null,
* lead_time_p95: float|null,
* lead_time_p80: float|null,
* lead_time_p50: float|null
2026-06-19 17:23:25 +03:00
* }>
*/
public function getSprintsByTeamId(int $teamId): array {
$rows = $this->db->getRowset(
'SELECT s.id,
s.jira_sprint_id,
s.sprint_name,
s.sprint_activate_datetime,
s.sprint_complete_datetime,
s.sprint_completion_percentage,
MAX(t.lead_time_days) AS lead_time_max,
MIN(t.lead_time_days) AS lead_time_min,
percentile_cont(0.95) WITHIN GROUP (ORDER BY t.lead_time_days) AS lead_time_p95,
percentile_cont(0.80) WITHIN GROUP (ORDER BY t.lead_time_days) AS lead_time_p80,
percentile_cont(0.50) WITHIN GROUP (ORDER BY t.lead_time_days) AS lead_time_p50
FROM sprints s
LEFT JOIN tasks t ON t.sprint_id = s.id AND t.lead_time_days IS NOT NULL
WHERE s.team_id = :team_id
GROUP BY s.id,
s.jira_sprint_id,
s.sprint_name,
s.sprint_activate_datetime,
s.sprint_complete_datetime,
s.sprint_completion_percentage
ORDER BY s.sprint_activate_datetime ASC',
2026-06-19 17:23:25 +03:00
['team_id' => $teamId]
);
return array_map(
static fn (array $row): array => [
'id' => (int) $row['id'],
'jira_sprint_id' => (int) $row['jira_sprint_id'],
'sprint_name' => $row['sprint_name'],
'sprint_activate_datetime' => $row['sprint_activate_datetime'],
'sprint_complete_datetime' => $row['sprint_complete_datetime'],
'sprint_completion_percentage' => $row['sprint_completion_percentage'] !== null
? (float) $row['sprint_completion_percentage']
: null,
'lead_time_max' => $row['lead_time_max'] !== null ? (int) $row['lead_time_max'] : null,
'lead_time_min' => $row['lead_time_min'] !== null ? (int) $row['lead_time_min'] : null,
'lead_time_p95' => $row['lead_time_p95'] !== null ? (float) $row['lead_time_p95'] : null,
'lead_time_p80' => $row['lead_time_p80'] !== null ? (float) $row['lead_time_p80'] : null,
'lead_time_p50' => $row['lead_time_p50'] !== null ? (float) $row['lead_time_p50'] : null,
2026-06-19 17:23:25 +03:00
],
$rows
);
}
}