detailsp = new Statistique(); } public function index() { // Mesure du temps d'exécution pour les performances $startTime = microtime(true); try { // Récupération des paramètres $idPolice = $this->requete->getParametreFormulaire("idPolice"); $debutStat = $this->requete->getParametreDate("debutStat"); $finStat = $this->requete->getParametreDate("finStat"); $codeGcAssureur = $this->requete->getParametreFormulaire("codeGcAssureur"); // VÉRIFICATION 1: Données de base nécessaires if (empty($debutStat) || empty($finStat) || empty($idPolice)) { throw new Exception(_("Paramètres de filtrage incomplets")); } // VÉRIFICATION 2: Dates valides et cohérentes if ($debutStat > $finStat) { throw new Exception(_("La date de début doit être antérieure à la date de fin")); } // VÉRIFICATION 3: Format des dates if (!DateTime::createFromFormat('Y-m-d', $debutStat) || !DateTime::createFromFormat('Y-m-d', $finStat)) { throw new Exception(_("Format de date invalide")); } $_SESSION['debutStat'] = $debutStat; $_SESSION['finStat'] = $finStat; // VÉRIFICATION 4: Récupération des données d'entête $entete = $this->detailsp->detailrapportspperiodepdfentete($idPolice); if (empty($entete)) { throw new Exception(_("Aucune donnée disponible pour cette police")); } $p_datedebut = $debutStat; $p_datefin = $finStat; $p_garant = $codeGcAssureur; $p_id = $idPolice; $p_id_college = null; $p_id_clients = null; // VÉRIFICATION 5: Récupération des données statistiques $tranchesfts = $this->detailsp->recapdepensestranchesage($p_garant, $p_id_clients, $p_id, $p_id_college, $p_datedebut, $p_datefin); // VÉRIFICATION 6: Données statistiques disponibles if (empty($tranchesfts)) { throw new Exception(_("Aucune donnée statistique disponible pour cette période")); } // VÉRIFICATION 7: Création du PDF avec gestion du pied de page $pdf = new class extends FPDF { function Header() { // Vous pouvez ajouter un en-tête personnalisé ici si besoin } function Footer() { // Positionnement à 1.5 cm du bas $this->SetY(-15); // Police Arial italique 8 $this->SetFont('Arial', 'I', 9); $this->SetTextColor(100, 100, 100); // Numéro de page centré - utilisation de {nb} qui est géré automatiquement par FPDF $this->Cell(0, 10, convertirc(_('Page')) . ' ' . $this->PageNo() . '/{nb}', 0, 0, 'C'); $this->SetTextColor(0); } }; if (!$pdf) { throw new Exception(_("Impossible d'initialiser le générateur PDF")); } $pdf->AliasNbPages(); // VÉRIFICATION 8: Ajout de la première page $pdf->AddPage(); $pdf->SetMargins(10, 10, 10); $logoPath = $_SESSION['lienLogo']; $pdf->Image($logoPath, 94, 3, 15); // Génération du contenu $this->genererEntete($pdf, $entete, $debutStat, $finStat, $p_id, $p_garant); $this->genererTableau($pdf, $tranchesfts, $p_id); // VÉRIFICATION 9: Ajout conditionnel du graphique $currentPage = $pdf->PageNo(); if ($p_id != null && $currentPage < 5) { $this->genererGraphique($pdf, $tranchesfts); } // VÉRIFICATION 10: Génération du fichier PDF $fichier = "Temp/TMP_CUMUL_SP_FICHE4_" . uniqid() . ".pdf"; $pdf->Output($fichier, "F"); // VÉRIFICATION 11: Fichier créé avec succès if (!file_exists($fichier) || filesize($fichier) == 0) { throw new Exception(_("Erreur lors de la création du fichier PDF")); } // Affichage du résultat $t_html = '
'; $t_html .= ''; $t_html .= _("TELECHARGER FICHE 04"); $t_html .= ''; $t_html .= '
'; echo $t_html; } catch (Exception $e) { // Gestion centralisée des erreurs error_log("Erreur génération PDF Fiche 04: " . $e->getMessage()); echo '
' . $e->getMessage() . '
'; } } private function genererEntete($pdf, $entete, $debutStat, $finStat, $p_id, $p_garant) { $pdf->SetFont('Arial','B',7); $pdf->Cell(0,5,convertirc(_('FICHE TECHNIQUE No 4')),0,1,'L',false); $pdf->SetY(10); $pdf->SetFont('Arial','',7); $pdf->Cell(0,5,convertirc(_('Edition du').': '.heureCouranteLang($_SESSION['lang'])),0,1,'R',false); $pdf->Ln(2); $pdf->SetFont('Arial','B',13); $pdf->SetFillColor(182,216,242); $pdf->Cell(0,8,convertirc(_("RECAPITULATIF DES DEPENSES PAR TRANCHES D'AGES")),1,0,'C',true); $pdf->Ln(10); $pdf->SetFont('Arial', 'B', 11); $pdf->SetTextColor(0); $pdf->Ln(8); $pdf->Cell(0, 5, convertirc(_('PERIODE COMPTABLE CONSIDEREE').': '.dateLang($debutStat, $_SESSION['lang']).' '._('AU').' '.dateLang($finStat, $_SESSION['lang'])), 0, 1, 'C', false); if ($p_id != null) { $pdf->Ln(10); $pdf->SetFont('Arial', 'BUI', 11); $pdf->Cell(35, 8, convertirc(_('GARANT').': '), 0, 0, 'L', false); $pdf->SetFont('Arial', 'BI', 11); $pdf->Cell(0, 8, convertirc($entete['garant']), 0, 1, 'L', false); $pdf->SetFont('Arial', 'BUI', 11); $pdf->Cell(35, 8, convertirc(_('SOUSCRIPTEUR').': '), 0, 0, 'L', false); $pdf->SetFont('Arial', 'BI', 11); $pdf->Cell(0, 8, convertirc($entete['souscripteur']), 0, 1, 'L', false); $pdf->SetFont('Arial', 'BUI', 11); $pdf->Cell(35, 8, convertirc(_('POLICE No').': '), 0, 0, 'L', false); $pdf->SetFont('Arial', 'BI', 11); $pdf->Cell(0, 8, convertirc($entete['numeroPolice'].' / '.$entete['libellePolice']), 0, 1, 'L', false); $pdf->SetFont('Arial', 'BUI', 11); $pdf->Cell(35, 8, convertirc(_('COURTIER').': '), 0, 0, 'L', false); $pdf->SetFont('Arial', 'BI', 11); $pdf->Cell(0, 8, convertirc($entete['courtier']), 0, 1, 'L', false); } else { $pdf->Ln(10); $pdf->SetFont('Arial', 'BUI', 11); $pdf->Cell(35, 8, convertirc(_('GARANT').': '), 0, 0, 'L', false); $pdf->SetFont('Arial', 'BI', 11); $pdf->Cell(0, 8, convertirc($p_garant), 0, 1, 'L', false); } $pdf->Ln(12); } private function genererTableau($pdf, $tranchesfts, $p_id) { $hl = 6; $pdf->SetFont('Arial','B',8); $pdf->SetFillColor(182,216,242); // En-tête du tableau $pdf->Cell(37,$hl*2,convertirc(_("Tranche d'âge")),1,0,'C',true); $pdf->Cell(62,8,convertirc(_("Effectif sur la période")),1,0,'C',true); $pdf->Cell(65,8,convertirc(_("Dépenses sur la période")),1,0,'C',true); $pdf->Cell(26,$hl*2,convertirc(_("Coût moyen")),1,1,'C',true); // Sous-en-tête $yPosition = $p_id != null ? 100 : 76; $pdf->SetY($yPosition); $pdf->SetX(47); $pdf->Cell(31,$hl,convertirc(_("Nombre")),1,0,'C',true); $pdf->Cell(31,$hl,convertirc(_("Taux")),1,0,'C',true); $pdf->Cell(34,$hl,convertirc(_("Montant")),1,0,'C',true); $pdf->Cell(31,$hl,convertirc(_("Taux")),1,0,'C',true); $pdf->Cell(26,0,convertirc(""),0,0,'C',false); // Données du tableau $pdf->SetFont('Arial','',9); $yDataPosition = $p_id != null ? 106 : 82; $pdf->SetY($yDataPosition); $totals = [ 'Nombre' => 0, 'Taux_Eff' => 0, 'Depense_Tranche' => 0, 'Taux_Depense' => 0, 'CoutMoyen' => 0 ]; foreach ($tranchesfts as $tranchesft) { // VÉRIFICATION: Données de ligne valides if (!isset($tranchesft['libelleTrancheAge']) || !isset($tranchesft['Nombre'])) { continue; // Skip les lignes incomplètes } $pdf->Cell(37,$hl,convertirc($tranchesft['libelleTrancheAge']),1,0,'L',false); $pdf->Cell(31,$hl,convertirc(format_N($tranchesft['Nombre'])),1,0,'C',false); $pdf->Cell(31,$hl,convertirc($tranchesft['Taux_Eff']."%"),1,0,'C',false); $pdf->Cell(34,$hl,convertirc(format_N($tranchesft['Depense_Tranche'])),1,0,'C',false); $pdf->Cell(31,$hl,convertirc($tranchesft['Taux_Depense']."%"),1,0,'C',false); $pdf->Cell(26,$hl,convertirc(format_N($tranchesft['CoutMoyen'])),1,1,'C',false); // Calcul des totaux foreach ($totals as $key => $value) { $totals[$key] += $tranchesft[$key] ?? 0; } } // Ligne de total $pdf->SetFont('Arial','B',9); $pdf->Cell(37,$hl,convertirc("TOTAL"),"1",0,'C',true); $pdf->Cell(31,$hl,format_N($totals['Nombre']),1,0,'C',true); $pdf->Cell(31,$hl,format_N($totals['Taux_Eff']) . "%",1,0,'C',true); $pdf->Cell(34,$hl,format_N($totals['Depense_Tranche']),1,0,'C',true); $pdf->Cell(31,$hl,format_N($totals['Taux_Depense']) . "%",1,0,'C',true); $pdf->Cell(26,$hl,format_N($totals['CoutMoyen']),1,0,'C',true); } private function genererGraphique($pdf, $tranchesfts) { // Vérification données suffisantes pour le graphique $valeurs = array_column($tranchesfts, 'Nombre'); if (count($valeurs) < 2 || max($valeurs) == 0) { return; // Données insuffisantes } $chartX = 15; $chartY = 175; // Dimensions $chartWidth = 180; $chartHeight = 100; // Padding $chartTopPadding = 12; $chartLeftPadding = 20; $chartBottomPadding = 10; $chartRightPadding = 5; // Chart box $chartBoxX = $chartX + $chartLeftPadding; $chartBoxY = $chartY + $chartTopPadding; $chartBoxWidth = $chartWidth - $chartLeftPadding - $chartRightPadding; $chartBoxHeight = $chartHeight - $chartBottomPadding - $chartTopPadding; // Bar width $barWidth = 8; // Préparation des données pour le graphique $data = []; $libelles = [ '0-5', '6-15', '16-25', '26-35', '36-45', '46-55', '56-65', '66-75', '76 et plus' ]; $colors = [ [255, 0, 0], [255, 255, 0], [50, 0, 255], [255, 0, 255], [0, 255, 0], [200, 255, 100], [121, 248, 248], [237, 127, 16], [187, 210, 225] ]; for ($i = 0; $i < count($libelles); $i++) { $value = $valeurs[$i] ?? 0; $data[$libelles[$i]] = [ 'color' => $colors[$i], 'value' => $value ]; } $dataMax = max($valeurs); // Détermination du pas des données if ($dataMax > 200 && $dataMax < 600) { $dataStep = 20; } elseif ($dataMax < 200) { $dataStep = 10; } elseif ($dataMax > 1000) { $dataStep = 100; } else { $dataStep = 50; } // Configuration du style $pdf->SetFont('Arial', '', 8); $pdf->SetLineWidth(0.1); $pdf->SetDrawColor(0); // Cadre du graphique $pdf->Rect($chartX, $chartY, $chartWidth, $chartHeight); // Axe vertical $pdf->Line($chartBoxX, $chartBoxY, $chartBoxX, $chartBoxY + $chartBoxHeight); // Axe horizontal $pdf->Line($chartBoxX - 2, $chartBoxY + $chartBoxHeight, $chartBoxX + $chartBoxWidth, $chartBoxY + $chartBoxHeight); // Échelle de l'axe Y $yAxisUnits = $dataMax > 0 ? $chartBoxHeight / $dataMax : 0; // Graduations de l'axe Y for ($i = 0; $i <= $dataMax; $i += $dataStep) { $yAxisPos = $chartBoxY + ($yAxisUnits * $i); $pdf->Line($chartBoxX - 2, $yAxisPos, $chartBoxX, $yAxisPos); $pdf->SetXY($chartBoxX - $chartLeftPadding, $yAxisPos - 2); $pdf->Cell($chartLeftPadding - 4, 5, $dataMax - $i, 0, 0, 'R'); } // Labels de l'axe X et dessin des barres $pdf->SetXY($chartBoxX, $chartBoxY + $chartBoxHeight); $xLabelWidth = count($data) > 0 ? $chartBoxWidth / count($data) : 0; $barXPos = 0; foreach ($data as $itemName => $item) { $pdf->Cell($xLabelWidth, 5, $itemName, 0, 0, 'C'); // Dessin de la barre $pdf->SetFillColor($item['color'][0], $item['color'][1], $item['color'][2]); $barHeight = $yAxisUnits * $item['value']; $barX = ($xLabelWidth / 2) + ($xLabelWidth * $barXPos) - ($barWidth / 2) + $chartBoxX; $barY = $chartBoxY + $chartBoxHeight - $barHeight; $pdf->Rect($barX, $barY, $barWidth, $barHeight, 'DF'); $barXPos++; } // Labels des axes $pdf->SetFont('Arial', 'B', 9); $pdf->SetXY($chartX, $chartY); $pdf->Cell(30, 10, "Nombre", 0); $pdf->SetXY(($chartWidth / 2) - 50 + $chartX, $chartY + $chartHeight - ($chartBottomPadding / 2)); $pdf->Cell(100, 5, convertirc(_("Effectif sur la période par tranche d'âge")), 0, 0, 'C'); } }