feat: import work hours from SaaS and exchange signed time sheet
This commit is contained in:
1 parent
7cf39850e6
commit
1a7c272414
73 files changed
+10488
-72
No files matched your search
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
namespace App\Service\Pdf;
|
||||
|
||||
use App\Entity\TeamerWorkMonth;
|
||||
use Dompdf\Dompdf;
|
||||
use Dompdf\Options;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Twig\Environment;
|
||||
|
||||
/**
|
||||
* Renders the Arbeitszeitnachweis a teamer signs for one month.
|
||||
*
|
||||
* Deliberately a sibling of AbstractPdfRenderer rather than a subclass: that base exists for
|
||||
* the FPDI renderers, which stamp text at fixed millimetre coordinates onto a pre-made PDF.
|
||||
* That works for the one-page contract and invoice forms but not for a table whose length
|
||||
* depends on the month, so this one goes through Twig and Dompdf instead. Dompdf's bundled
|
||||
* DejaVu fonts also carry umlauts natively, where the FPDI path has to convert every string
|
||||
* to ISO-8859-1 first (see Pdf::encodeString()).
|
||||
*/
|
||||
class WorkMonthRenderer
|
||||
{
|
||||
private array $config;
|
||||
|
||||
public function __construct(
|
||||
private readonly Environment $twig,
|
||||
array $options,
|
||||
) {
|
||||
$this->config = $this->resolveOptions($options);
|
||||
}
|
||||
|
||||
public function render(TeamerWorkMonth $workMonth): string
|
||||
{
|
||||
$options = new Options();
|
||||
// Nothing in the document is fetched from anywhere: the stylesheet is inline and
|
||||
// there are no images, so the renderer never needs to leave the project directory.
|
||||
$options->setIsRemoteEnabled(false);
|
||||
$options->setChroot($this->config['project_dir']);
|
||||
$options->setDefaultFont('DejaVu Sans');
|
||||
$options->setDefaultPaperSize('A4');
|
||||
$options->setDefaultPaperOrientation('portrait');
|
||||
|
||||
$dompdf = new Dompdf($options);
|
||||
$dompdf->loadHtml($this->twig->render('pdf/work_month.html.twig', [
|
||||
'workMonth' => $workMonth,
|
||||
'teamer' => $workMonth->getTeamer(),
|
||||
'days' => $workMonth->getDays()->forCalendarMonth($workMonth->getYear(), $workMonth->getMonth()),
|
||||
'logo' => $this->logoPath(),
|
||||
]), 'UTF-8');
|
||||
$dompdf->render();
|
||||
|
||||
return (string) $dompdf->output();
|
||||
}
|
||||
|
||||
/**
|
||||
* The letterhead logo, as an absolute path inside the chroot.
|
||||
*
|
||||
* Read from the filesystem rather than embedded: remote loading is off and the chroot is
|
||||
* the project directory, so Dompdf can open this and nothing outside it. Null when the
|
||||
* file is missing, because a working-time record is worth printing without its letterhead.
|
||||
*/
|
||||
private function logoPath(): ?string
|
||||
{
|
||||
$path = $this->config['project_dir'].'/assets/images/logo.png';
|
||||
|
||||
return is_readable($path) ? $path : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Arbeitszeitnachweis_Test_2026-03.pdf.
|
||||
*/
|
||||
public function filename(TeamerWorkMonth $workMonth): string
|
||||
{
|
||||
$lastName = $workMonth->getTeamer()?->getLastName() ?? 'Teamer';
|
||||
|
||||
return sprintf(
|
||||
'Arbeitszeitnachweis_%s_%04d-%02d.pdf',
|
||||
preg_replace('/[^A-Za-z0-9]+/', '_', $lastName),
|
||||
$workMonth->getYear(),
|
||||
$workMonth->getMonth(),
|
||||
);
|
||||
}
|
||||
|
||||
private function resolveOptions(array $options): array
|
||||
{
|
||||
$optionsResolver = new OptionsResolver();
|
||||
$optionsResolver->setRequired(['project_dir']);
|
||||
$optionsResolver->setAllowedTypes('project_dir', 'string');
|
||||
|
||||
return $optionsResolver->resolve($options);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user