diff --git a/gestion/lib/Service/Devis/DevisPdfGenerator.php b/gestion/lib/Service/Devis/DevisPdfGenerator.php index d3979fb..adad6f6 100644 --- a/gestion/lib/Service/Devis/DevisPdfGenerator.php +++ b/gestion/lib/Service/Devis/DevisPdfGenerator.php @@ -81,16 +81,31 @@ class DevisPdfGenerator private function calculatePagination($totalItems) { + if ($totalItems <= 8) { + // Tout sur 1 page + return [ + 'nb_pages' => 1, + 'items_per_page' => 15, + 'current_index' => 0 + ]; + } + + // Réserver 8 items pour dernière page + $itemsAvantDernierePage = $totalItems - 8; + $nbPagesNormales = ceil($itemsAvantDernierePage / 15); + return [ - 'nb_pages' => ceil($totalItems / 12), // RÉDUIRE à 12 par page - 'items_per_page' => 12, + 'nb_pages' => $nbPagesNormales + 1, + 'items_per_page' => 15, 'current_index' => 0 ]; } - // VOICI LA FONCTION CORRIGÉE - 4 paramètres au lieu de 10 private function generateSinglePage(PageContext $context, $num_page, &$pagination, &$totals) { + $startIndex = $pagination['current_index']; + $remainingItems = count($context->dataDevis) - $startIndex; + $context->pdf->AddPage(); $context->pdf->SetAutoPagebreak(false); $context->pdf->SetMargins(0, 0, 10); @@ -100,7 +115,17 @@ class DevisPdfGenerator $this->layoutManager->addClientInfoSection($context->pdf, $context->clientInfo, $context->dataDevis[0]); $this->layoutManager->addDocumentTitle($context->pdf, $context->dataDevis[0], $context->year); - $itemsToProcess = min($pagination['items_per_page'], count($context->dataDevis) - $pagination['current_index']); + // ✅ Calculer items + $isLastPage = ($num_page == $pagination['nb_pages']); + $hasAmounts = !$context->montant; + + if ($isLastPage && $hasAmounts) { + // Dernière page avec totaux : max 8 items + $itemsToProcess = min(8, $remainingItems); + } else { + // Pages normales : 15 items + $itemsToProcess = min(15, $remainingItems); + } $config = [ 'pagination' => $pagination, @@ -111,7 +136,7 @@ class DevisPdfGenerator 'sansMontant' => $context->montant ]; - $this->tableRenderer->createDevisTable( + $finalY = $this->tableRenderer->createDevisTable( $context->pdf, $context->dataDevis, $config diff --git a/gestion/lib/Service/Devis/DevisPdfLayoutManager.php b/gestion/lib/Service/Devis/DevisPdfLayoutManager.php index 8728c66..3ab56e1 100644 --- a/gestion/lib/Service/Devis/DevisPdfLayoutManager.php +++ b/gestion/lib/Service/Devis/DevisPdfLayoutManager.php @@ -63,17 +63,18 @@ class DevisPdfLayoutManager ); } - public function addLegalFooter($pdf, $config) + public function addLegalFooter($pdf, $config, $tableEndY = 0) { - $y0 = 260; + $y0 = 280; + $pageWidth = $pdf->GetPageWidth(); $pdf->SetFont('Arial', '', 6); - $pdf->SetXY(1, $y0 + 4); + $pdf->SetXY(1, $y0); $pdf->Cell($pageWidth, 5, mb_convert_encoding(html_entity_decode($config->legal_one), 'ISO-8859-1', 'UTF-8'), 0, 0, 'C'); - $pdf->SetXY(1, $y0 + 8); + $pdf->SetXY(1, $y0 + 4); $pdf->Cell($pageWidth, 5, mb_convert_encoding(html_entity_decode($config->legal_two), 'ISO-8859-1', 'UTF-8'), 0, 0, 'C'); - $pdf->SetXY(1, $y0 + 12); + $pdf->SetXY(1, $y0 + 8); $pdf->Cell($pageWidth, 5, mb_convert_encoding(html_entity_decode($config->telephone), 'ISO-8859-1', 'UTF-8'), 0, 0, 'C'); } diff --git a/gestion/lib/Service/Devis/DevisPdfTableRenderer.php b/gestion/lib/Service/Devis/DevisPdfTableRenderer.php index 4ae83ed..0f0a9e2 100644 --- a/gestion/lib/Service/Devis/DevisPdfTableRenderer.php +++ b/gestion/lib/Service/Devis/DevisPdfTableRenderer.php @@ -13,40 +13,59 @@ class DevisPdfTableRenderer $totals = &$config['totals']; $sansMontant = $config['sansMontant'] ?? false; - // Système de pagination comme les factures - $maxItemsPerPage = 22; // Nombre maximum d'éléments par page $startIndex = $pagination['current_index']; $itemsThisPage = min($itemsToProcess, count($dataDevis) - $startIndex); - $this->drawTableStructure($pdf, $numPage, $nbPage, $sansMontant); + $tableEndY = $this->drawTableStructure($pdf, $numPage, $nbPage, $sansMontant, $itemsThisPage); $this->addTableHeaders($pdf, $sansMontant); $this->populateTableData($pdf, $dataDevis, $startIndex, $itemsThisPage, $totals, $sansMontant); - // Totaux seulement sur la dernière page if ($numPage == $nbPage && !$sansMontant) { - $this->addTableTotals($pdf, $totals); + $finalY = $this->addTableTotals($pdf, $totals, $tableEndY); + } else { + $finalY = $tableEndY; } + + return $finalY; } - private function drawTableStructure($pdf, $numPage, $nbPage, $sansMontant) + private function drawTableStructure($pdf, $numPage, $nbPage, $sansMontant, $itemsOnPage) { $pdf->SetLineWidth(0.2); - $pdf->Rect(5, 105, 200, 130, "D"); + + $headerHeight = 10; + $rowHeight = 10; + + $tableHeight = $headerHeight + ($itemsOnPage * $rowHeight); + $endY = 105 + $tableHeight; + + $isLastPage = ($numPage == $nbPage); + $hasAmounts = !$sansMontant; + + if ($isLastPage && $hasAmounts) { + // Dessiner 3 côtés seulement (haut, gauche, droite) + $pdf->Line(5, 105, 205, 105); // Haut + $pdf->Line(5, 105, 5, $endY); // Gauche + $pdf->Line(205, 105, 205, $endY); // Droite + // Pas de ligne du bas - elle sera tracée dans addTableTotals + } else { + // Dessiner rectangle complet + $pdf->Rect(5, 105, 200, $tableHeight, "D"); + } + $pdf->Line(5, 115, 205, 115); - $endY = ($numPage == $nbPage && !$sansMontant) ? 225 : 235; - if (!$sansMontant) { - // Ajout de la colonne Thanatopracteur entre Défunt et H.T. $verticalLines = [24, 41, 58, 77, 102, 127, 147, 167, 178, 189]; } else { - // Pour sans montant: ajout de Thanatopracteur à la fin $verticalLines = [27, 47, 67, 85, 110, 135, 160]; } foreach ($verticalLines as $x) { $pdf->Line($x, 105, $x, $endY); } + + return $endY; } private function addTableHeaders($pdf, $sansMontant) @@ -176,43 +195,44 @@ class DevisPdfTableRenderer } } - private function addTableTotals($pdf, $totals) + private function addTableTotals($pdf, $totals, $tableEndY) { - $pdf->Line(5, 225, 205, 225); + $totalEndY = $tableEndY + 8; + + $pdf->SetLineWidth(0.2); + + // Juste les lignes horizontales haut et bas + $pdf->Line(5, $tableEndY, 205, $tableEndY); + $pdf->Line(5, $totalEndY, 205, $totalEndY); + + $pdf->Line(5, $tableEndY, 5, $totalEndY); + $pdf->Line(205, $tableEndY, 205, $totalEndY); + $pdf->SetFont('Arial', 'B', 8); - // Alignement des totaux avec les colonnes HT, TVA, TTC avec espaces entre les valeurs - $pdf->SetXY(5, 225); + $pdf->SetXY(5, $tableEndY); $pdf->Cell(162, 8, 'TOTAL', 0, 0, 'C'); - // POSITIONS avec espaces entre les valeurs - plus d'espace entre HT et TVA - $pdf->SetXY(167, 225); + $pdf->SetXY(167, $tableEndY); $pdf->Cell(9, 8, number_format($totals['ht'], 2, '.', '') . chr(128), 0, 0, 'R'); - $pdf->SetXY(181, 225); + $pdf->SetXY(181, $tableEndY); $pdf->Cell(9, 8, number_format($totals['tva'], 2, '.', '') . chr(128), 0, 0, 'R'); - $pdf->SetXY(189, 225); + $pdf->SetXY(189, $tableEndY); $pdf->Cell(16, 8, number_format($totals['ttc'], 2, '.', '') . chr(128), 0, 0, 'R'); - // CADRE TOTAL TTC - Cadre encore plus agrandi - $pdf->SetXY(170, 241); + $cadreY = $totalEndY + 3; + + $pdf->SetXY(170, $cadreY + 1); $pdf->Cell(19, 6, 'TOTAL TTC', 0, 0, 'C'); - $pdf->SetXY(189, 241); + $pdf->SetXY(189, $cadreY + 1); $pdf->Cell(16, 6, number_format($totals['ttc'], 2, '.', '') . chr(128), 0, 0, 'C'); - // Cadre TOTAL TTC aligné avec la fin du tableau (205) - $lines = [ - [170, 240, 170, 248], // Ligne verticale gauche (déplacée de 173 à 170 pour agrandir) - [189, 240, 189, 248], // Ligne de séparation (alignée avec colonne T.T.C) - [205, 240, 205, 248], // Ligne verticale droite (alignée avec fin du tableau) - [170, 240, 205, 240], // Ligne horizontale haute - [170, 248, 205, 248] // Ligne horizontale basse - ]; + $pdf->Rect(170, $cadreY, 35, 8, 'D'); + $pdf->Line(189, $cadreY, 189, $cadreY + 8); - foreach ($lines as $line) { - $pdf->Line($line[0], $line[1], $line[2], $line[3]); - } + return $cadreY + 8; } }