Ajouter les statistiques par période

This commit is contained in:
Alexandre NOEL 2026-10-02 12:11:30 +02:00
commit 86642095cd
14 changed files with 315 additions and 125 deletions

View file

@ -95,17 +95,39 @@ final class DirectoryController
'SELECT id,name,internal_code,species,status,intake_date event_date FROM animals WHERE depositor_contact_id=:id ORDER BY date(intake_date) DESC,name COLLATE NOCASE',
);
$deposited->execute([':id' => $id]);
$periodRequested = array_key_exists('year', $_GET);
$periodRequested = array_key_exists('year', $_GET) || array_key_exists('period_type', $_GET);
$periodRaw = (string) ($_GET['year'] ?? 'all');
$periodYear =
ctype_digit($periodRaw) && (int) $periodRaw >= 2000 && (int) $periodRaw <= 2100 ? (int) $periodRaw : null;
$periodType = (string) ($_GET['period_type'] ?? ($periodYear ? 'year' : 'all'));
$periodStart = $periodEnd = null;
$periodQuery = ['period_type' => $periodType];
if ($periodType === 'year' && $periodYear !== null) {
$periodStart = sprintf('%04d-01-01', $periodYear);
$periodEnd = sprintf('%04d-12-31', $periodYear);
$periodQuery['year'] = $periodYear;
} elseif ($periodType === 'month' && preg_match('/^\d{4}-(0[1-9]|1[0-2])$/', (string) ($_GET['month'] ?? ''))) {
$periodQuery['month'] = (string) $_GET['month'];
$periodStart = $periodQuery['month'] . '-01';
$periodEnd = (new DateTimeImmutable($periodStart))->modify('last day of this month')->format('Y-m-d');
} elseif ($periodType === 'custom') {
$from = (string) ($_GET['date_from'] ?? '');
$to = (string) ($_GET['date_to'] ?? '');
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $from) && preg_match('/^\d{4}-\d{2}-\d{2}$/', $to)) {
[$periodStart, $periodEnd] = $from <= $to ? [$from, $to] : [$to, $from];
$periodQuery += ['date_from' => $periodStart,'date_to' => $periodEnd];
}
}
$periodLabel = $periodStart && $periodEnd
? (new DateTimeImmutable($periodStart))->format('d/m/Y') . ' – ' . (new DateTimeImmutable($periodEnd))->format('d/m/Y')
: t('statistics.all_years');
$periodMunicipality = trim((string) ($_GET['municipality'] ?? ''));
$expenseWhere = ['ae.clinic_contact_id=:id', 'a.deleted_at IS NULL'];
$expenseParams = [':id' => $id];
if ($periodYear !== null) {
if ($periodStart !== null && $periodEnd !== null) {
$expenseWhere[] = 'date(ae.occurred_on) BETWEEN :expense_start AND :expense_end';
$expenseParams[':expense_start'] = sprintf('%04d-01-01', $periodYear);
$expenseParams[':expense_end'] = sprintf('%04d-12-31', $periodYear);
$expenseParams[':expense_start'] = $periodStart;
$expenseParams[':expense_end'] = $periodEnd;
}
$expenses = $db->prepare(
'SELECT ae.*,a.name animal_name,a.internal_code,a.rescue_location_name,a.rescue_address FROM animal_expenses ae JOIN animals a ON a.id=ae.animal_id WHERE ' .
@ -129,9 +151,10 @@ final class DirectoryController
$expenseRows = array_slice($expenseRows, 0, 250);
$invoiceWhere = ['vendor_contact_id=:vendor', 'deleted_at IS NULL'];
$invoiceParams = [':vendor' => $id];
if ($periodYear !== null) {
$invoiceWhere[] = "strftime('%Y',invoice_date)=:invoice_year";
$invoiceParams[':invoice_year'] = (string) $periodYear;
if ($periodStart !== null && $periodEnd !== null) {
$invoiceWhere[] = 'date(invoice_date) BETWEEN :invoice_start AND :invoice_end';
$invoiceParams[':invoice_start'] = $periodStart;
$invoiceParams[':invoice_end'] = $periodEnd;
}
$invoiceStmt = $db->prepare(
'SELECT * FROM accounting_invoices WHERE ' .
@ -162,6 +185,8 @@ final class DirectoryController
'expenseCount' => $expenseCount,
'expensePeriodRequested' => $periodRequested,
'expensePeriodYear' => $periodYear,
'expensePeriodLabel' => $periodLabel,
'expensePeriodQuery' => $periodQuery,
'expensePeriodMunicipality' => $periodMunicipality,
'contactInvoices' => $contactInvoices,
'contactInvoiceTotal' => $contactInvoiceTotal,

View file

@ -6,37 +6,95 @@ final class StatisticsController
{
public static function index(): void
{
$requested = (string) ($_GET['year'] ?? date('Y'));
$all = $requested === 'all';
$year = $all ? null : max(2000, min(2200, (int) $requested));
$years = StatisticsService::years();
$requestedYear = (string) ($_GET['year'] ?? date('Y'));
$periodType = (string) ($_GET['period_type'] ?? ($requestedYear === 'all' ? 'all' : 'year'));
if (!in_array($periodType, ['all','year','month','custom'], true)) {
$periodType = 'year';
}
$year = max(2000, min(2200, (int) ($requestedYear === 'all' ? date('Y') : $requestedYear)));
$month = preg_match('/^\d{4}-(0[1-9]|1[0-2])$/', (string) ($_GET['month'] ?? ''))
? (string) $_GET['month']
: date('Y-m');
$validDate = static function (string $value): bool {
$date = DateTimeImmutable::createFromFormat('!Y-m-d', $value);
return $date !== false && $date->format('Y-m-d') === $value;
};
$dateFrom = $validDate((string) ($_GET['date_from'] ?? '')) ? (string) $_GET['date_from'] : date('Y-01-01');
$dateTo = $validDate((string) ($_GET['date_to'] ?? '')) ? (string) $_GET['date_to'] : date('Y-m-d');
if ($dateFrom > $dateTo) {
[$dateFrom, $dateTo] = [$dateTo, $dateFrom];
}
$start = $end = null;
if ($periodType === 'year') {
$start = sprintf('%04d-01-01', $year);
$end = sprintf('%04d-12-31', $year);
} elseif ($periodType === 'month') {
$start = $month . '-01';
$end = (new DateTimeImmutable($start))->modify('last day of this month')->format('Y-m-d');
$year = (int) substr($month, 0, 4);
} elseif ($periodType === 'custom') {
$start = $dateFrom;
$end = $dateTo;
$year = (int) substr($dateFrom, 0, 4);
}
$all = $periodType === 'all';
$formatDate = static fn(string $date): string => (new DateTimeImmutable($date))->format('d/m/Y');
$periodLabel = match ($periodType) {
'all' => t('statistics.all_years'),
'month' => substr($month, 5, 2) . '/' . substr($month, 0, 4),
'custom' => $formatDate($dateFrom) . ' – ' . $formatDate($dateTo),
default => (string) $year,
};
$periodQuery = ['period_type' => $periodType];
if ($periodType === 'year') $periodQuery['year'] = $year;
if ($periodType === 'month') $periodQuery['month'] = $month;
if ($periodType === 'custom') $periodQuery += ['date_from' => $dateFrom,'date_to' => $dateTo];
$municipalities = StatisticsService::municipalities();
$municipality = trim((string) ($_GET['municipality'] ?? ''));
if ($municipality !== '' && !isset($municipalities[$municipality])) {
$municipality = '';
}
$ids = $municipality !== '' ? StatisticsService::animalIdsForMunicipality($municipality) : null;
if ($all) {
$comparison = [];
$previousPeriodLabel = '';
} elseif ($periodType === 'year') {
$comparison = StatisticsService::comparison($year, $ids);
$previousPeriodLabel = (string) ($year - 1);
} else {
$comparisonResult = StatisticsService::comparisonPeriod($start, $end, $ids);
$comparison = $comparisonResult['rows'];
$previousPeriodLabel = $formatDate($comparisonResult['previous_start']) . ' – ' . $formatDate($comparisonResult['previous_end']);
}
render('statistics.php', [
'title' => t('statistics.title'),
'pageDescription' => t('statistics.description'),
'year' => $year,
'allYears' => $all,
'periodType' => $periodType,
'month' => $month,
'dateFrom' => $dateFrom,
'dateTo' => $dateTo,
'periodLabel' => $periodLabel,
'previousPeriodLabel' => $previousPeriodLabel,
'periodQuery' => $periodQuery,
'years' => $years,
'municipality' => $municipality,
'municipalities' => $municipalities,
'municipalityCoverage' => StatisticsService::municipalityCoverage(),
'stats' => $all ? StatisticsService::all($ids) : StatisticsService::annual($year, $ids),
'comparison' => $all ? [] : StatisticsService::comparison($year, $ids),
'stats' => $all ? StatisticsService::all($ids) : StatisticsService::period($start, $end, $ids),
'comparison' => $comparison,
'timeline' => StatisticsService::timeline($years, $ids),
'undatedHandled' => StatisticsService::undatedHandled($ids),
'undatedDeaths' => StatisticsService::undatedDeaths($ids),
'undatedBirths' => StatisticsService::undatedBirths($ids),
'undatedExits' => StatisticsService::undatedExits($ids),
'scopeCounts' => StatisticsService::scopeCounts($ids),
'distributions' => StatisticsService::distributions($year, $ids, $municipality ?: null),
'distributions' => StatisticsService::distributions($all ? null : $year, $ids, $municipality ?: null, $start, $end),
'health' => StatisticsService::currentHealth($ids),
'costs' => StatisticsService::costs($year, $ids),
'municipalityCosts' => StatisticsService::costsByMunicipality($year),
'costs' => StatisticsService::costs($all ? null : $year, $ids, $start, $end),
'municipalityCosts' => StatisticsService::costsByMunicipality($all ? null : $year, $start, $end),
]);
}
}