drawHeader($pdf, $agent, $periodLabel, $generatedAt); $this->drawAgentIdentity($pdf, $agent); $this->drawQuotaSummary($pdf, $quota); $this->drawValidationClause($pdf, $periodLabel, $generatedAt); $this->drawSignatures($pdf); $pdf->text( self::MARGIN, 813, sprintf('Document généré par PTA le %s - Référence agent : %s', $generatedAt->format('d/m/Y H:i'), (string) ($agent['matricule'] ?? '-')), 7 ); return $pdf->output(); } private function drawHeader(SimplePdf $pdf, array $agent, string $periodLabel, DateTimeImmutable $generatedAt): void { $pdf->text(self::MARGIN, 48, 'CONTRAT HORAIRE ANNUEL', 18, true); $pdf->text(self::MARGIN, 71, 'Validation du quota annuel de travail', 12, true); $pdf->text(self::MARGIN, 92, 'Période de référence : ' . $periodLabel, 10); $pdf->text(self::MARGIN + 315, 92, 'Édité le : ' . $generatedAt->format('d/m/Y'), 10); $pdf->line(self::MARGIN, 108, self::PAGE_WIDTH - self::MARGIN, 108, 0.35); $pdf->text( self::MARGIN, 130, sprintf('%s %s', (string) ($agent['prenom'] ?? ''), (string) ($agent['nom'] ?? '')), 14, true ); } private function drawAgentIdentity(SimplePdf $pdf, array $agent): void { $x = self::MARGIN; $y = 150.0; $w = self::PAGE_WIDTH - (self::MARGIN * 2); $h = 140.0; $pdf->fillRect($x, $y, $w, 28, 0.93); $pdf->rect($x, $y, $w, $h, 0.65); $pdf->text($x + 12, $y + 19, 'Informations de l\'agent', 11, true); $leftX = $x + 14; $rightX = $x + 278; $row1 = $y + 52; $row2 = $y + 78; $row3 = $y + 102; $row4 = $y + 128; $qualification = !empty($agent['est_diplome']) ? 'Diplômé' . (!empty($agent['diplome_libelle']) ? ' - ' . $agent['diplome_libelle'] : '') : 'Non diplômé'; $pdf->text($leftX, $row1, 'Matricule : ' . (($agent['matricule'] ?? '') ?: '-'), 9); $pdf->text($rightX, $row1, 'E-mail : ' . (($agent['email'] ?? '') ?: 'Non renseigné'), 9); $pdf->text($leftX, $row2, 'Téléphone : ' . (($agent['telephone'] ?? '') ?: 'Non renseigné'), 9); $pdf->text($rightX, $row2, 'Qualification : ' . $qualification, 9); $pdf->text($leftX, $row3, 'Lieu principal : ' . (($agent['structure_principale_nom'] ?? '') ?: 'Non renseigné'), 9); $pdf->text($rightX, $row3, 'Début du contrat : ' . (!empty($agent['date_debut_contrat']) ? (new DateTimeImmutable((string) $agent['date_debut_contrat']))->format('d/m/Y') : 'Non renseigné'), 9); $address = (string) (($agent['adresse'] ?? '') ?: 'Non renseignée'); $addressLines = $pdf->wrap('Adresse : ' . $address, $w - 28, 8.5); $pdf->text($leftX, $row4, (string) ($addressLines[0] ?? 'Adresse : Non renseignée'), 8.5); $pdf->text($rightX, $row4, 'Type du lieu : ' . $this->typeLabel((string) ($agent['structure_principale_type_affectation'] ?? '')), 8.5); } private function drawQuotaSummary(SimplePdf $pdf, array $quota): void { $x = self::MARGIN; $y = 318.0; $w = self::PAGE_WIDTH - (self::MARGIN * 2); $headerH = 30.0; $rowH = 31.0; $rows = [ ['Quota annuel de référence à 100 %', $this->minutesLabel((int) ($quota['quota_reference_minutes'] ?? 0))], ['Quotité de travail applicable', $this->percentLabel((float) ($quota['quotite_travail'] ?? 100))], ['Quota annuel cible de l\'agent', (string) ($quota['quota_cible']['libelle'] ?? $this->minutesLabel((int) ($quota['quota_cible_minutes'] ?? 0)))], ['Heures validées dans PTA à la date d\'édition', (string) ($quota['valides']['libelle'] ?? $this->minutesLabel((int) ($quota['minutes_valides'] ?? 0)))], ['Heures encore en brouillon', (string) ($quota['brouillons']['libelle'] ?? $this->minutesLabel((int) ($quota['minutes_brouillon'] ?? 0)))], ['Solde restant à planifier / affecter', (string) ($quota['restantes']['libelle'] ?? $this->minutesLabel((int) ($quota['minutes_restantes'] ?? 0)))], ]; $pdf->fillRect($x, $y, $w, $headerH, 0.90); $pdf->rect($x, $y, $w, $headerH + (count($rows) * $rowH), 0.60); $pdf->text($x + 12, $y + 20, 'Synthèse du quota horaire', 11, true); $labelWidth = 360.0; $valueWidth = $w - $labelWidth; $cursorY = $y + $headerH; foreach ($rows as $index => [$label, $value]) { if ($index % 2 === 1) { $pdf->fillRect($x, $cursorY, $w, $rowH, 0.975); } $pdf->line($x, $cursorY, $x + $w, $cursorY, 0.82); $pdf->line($x + $labelWidth, $cursorY, $x + $labelWidth, $cursorY + $rowH, 0.82); $pdf->text($x + 12, $cursorY + 20, (string) $label, 8.6, $index === 2); $pdf->text($x + $labelWidth + 12, $cursorY + 20, (string) $value, 9.2, $index === 2); $cursorY += $rowH; } } private function drawValidationClause(SimplePdf $pdf, string $periodLabel, DateTimeImmutable $generatedAt): void { $x = self::MARGIN; $y = 557.0; $w = self::PAGE_WIDTH - (self::MARGIN * 2); $pdf->text($x, $y, 'Validation', 11, true); $paragraphs = [ sprintf( 'Le présent document fixe et récapitule le quota annuel de travail applicable à l\'agent pour la période %s. La signature de l\'agent et la contre-signature du responsable valent validation du quota annuel indiqué ci-dessus.', $periodLabel ), 'Les heures validées et les heures en brouillon constituent un état de suivi à la date d\'édition. Toute modification ultérieure du planning doit faire l\'objet d\'une nouvelle validation dans PTA lorsque cela est nécessaire.', ]; $cursorY = $y + 22; foreach ($paragraphs as $paragraph) { foreach ($pdf->wrap($paragraph, $w, 9) as $line) { $pdf->text($x, $cursorY, $line, 9); $cursorY += 13; } $cursorY += 8; } $pdf->text($x, 638, 'Fait à : ____________________________________', 9); $pdf->text($x + 286, 638, 'Le : ____ / ____ / ________', 9); $pdf->text($x, 658, 'Document établi le ' . $generatedAt->format('d/m/Y') . '.', 8); } private function drawSignatures(SimplePdf $pdf): void { $x = self::MARGIN; $y = 680.0; $gap = 18.0; $w = (self::PAGE_WIDTH - (self::MARGIN * 2) - $gap) / 2; $h = 120.0; $pdf->rect($x, $y, $w, $h, 0.55); $pdf->rect($x + $w + $gap, $y, $w, $h, 0.55); $pdf->fillRect($x, $y, $w, 28, 0.94); $pdf->fillRect($x + $w + $gap, $y, $w, 28, 0.94); $pdf->text($x + 10, $y + 19, 'Signature de l\'agent', 10, true); $pdf->text($x + $w + $gap + 10, $y + 19, 'Contre-signature du responsable', 10, true); $pdf->text($x + 10, $y + 48, 'Nom : ______________________________', 8.5); $pdf->text($x + 10, $y + 68, 'Mention « Lu et approuvé » :', 8.5); $pdf->text($x + 10, $y + 101, 'Signature :', 8.5); $rightX = $x + $w + $gap + 10; $pdf->text($rightX, $y + 48, 'Nom / qualité : _____________________', 8.5); $pdf->text($rightX, $y + 68, 'Mention « Bon pour validation » :', 8.5); $pdf->text($rightX, $y + 101, 'Signature et cachet :', 8.5); } private function typeLabel(string $type): string { return match (strtoupper($type)) { 'EXTRASCOLAIRE' => 'Extrascolaire', 'PERISCOLAIRE' => 'Périscolaire', default => 'Non renseigné', }; } private function percentLabel(float $rate): string { $formatted = rtrim(rtrim(number_format($rate, 2, ',', ' '), '0'), ','); return $formatted . ' %'; } private function minutesLabel(int $minutes): string { $sign = $minutes < 0 ? '-' : ''; $absolute = abs($minutes); return sprintf('%s%d h %02d', $sign, intdiv($absolute, 60), $absolute % 60); } }