Files
SIRH/src/State/EmployeeYearlyHoursBulkPrintProvider.php
tristan ff7566d4cd
Some checks failed
Auto Tag Develop / tag (push) Has been cancelled
feat : export PDF heures groupé depuis la liste employés + memory_limit 256M
- Nouveau endpoint GET /yearly-hours/print-all (admin, par mois uniquement)
- Service YearlyHoursExportBuilder extrait du provider existant (logique partagée)
- EmployeeYearlyHoursPrintProvider refactorisé pour utiliser le builder
- Template print-all.html.twig avec saut de page entre chaque employé
- Drawer BulkYearlyHoursDrawer avec loader "Génération en cours..."
- Bouton "Export heures" ajouté sur la page liste employés
- PHP memory_limit passé de 128M à 256M dans php.ini (nécessaire pour Dompdf multi-employés)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-17 16:57:58 +02:00

87 lines
3.0 KiB
PHP

<?php
declare(strict_types=1);
namespace App\State;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProviderInterface;
use App\Repository\EmployeeRepository;
use App\Service\WorkHours\YearlyHoursExportBuilder;
use DateTimeImmutable;
use Dompdf\Dompdf;
use Dompdf\Options;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException;
use Twig\Environment;
class EmployeeYearlyHoursBulkPrintProvider implements ProviderInterface
{
public function __construct(
private Environment $twig,
private readonly RequestStack $requestStack,
private EmployeeRepository $employeeRepository,
private YearlyHoursExportBuilder $exportBuilder,
) {}
public function provide(Operation $operation, array $uriVariables = [], array $context = []): Response
{
$request = $this->requestStack->getCurrentRequest();
if (!$request) {
return new Response('Missing request.', Response::HTTP_BAD_REQUEST);
}
$yearRaw = (string) $request->query->get('year');
if (!preg_match('/^\d{4}$/', $yearRaw)) {
throw new UnprocessableEntityHttpException('year must use YYYY format.');
}
$year = (int) $yearRaw;
$monthRaw = (string) $request->query->get('month', '');
$month = null;
if ('' !== $monthRaw) {
if (!preg_match('/^(?:0?[1-9]|1[0-2])$/', $monthRaw)) {
throw new UnprocessableEntityHttpException('month must be between 1 and 12.');
}
$month = (int) $monthRaw;
}
if (null !== $month) {
$from = new DateTimeImmutable(sprintf('%d-%02d-01', $year, $month));
$to = $from->modify('last day of this month');
} else {
$from = new DateTimeImmutable("{$year}-01-01");
$to = new DateTimeImmutable("{$year}-12-31");
}
$employees = $this->employeeRepository->findAll();
usort($employees, fn ($a, $b) => ($a->getLastName() ?? '') <=> ($b->getLastName() ?? ''));
$entries = $this->exportBuilder->buildForEmployees($employees, $from, $to);
$options = new Options();
$options->set('isRemoteEnabled', true);
$dompdf = new Dompdf($options);
$html = $this->twig->render('employee-yearly-hours/print-all.html.twig', [
'entries' => $entries,
'year' => $year,
'month' => $month,
]);
$dompdf->loadHtml($html);
$dompdf->setPaper('A4', 'portrait');
$dompdf->render();
$filename = null !== $month
? sprintf('heures_tous_%d-%02d.pdf', $year, $month)
: sprintf('heures_tous_%d.pdf', $year);
return new Response($dompdf->output(), Response::HTTP_OK, [
'Content-Type' => 'application/pdf',
'Content-Disposition' => 'inline; filename="'.$filename.'"',
]);
}
}