Files
e-cosplay/src/Service/Pdf/EchPdfDetails.php
Serreau Jovann aff07c97e1 feat(Customer): Ajoute la gestion des échéances de paiement client
Ajoute l'entité CustomerSplit et les services associés pour gérer
les échéances de paiement des clients (PDF, envoi mail, etc.).
2025-10-09 09:18:01 +02:00

289 lines
13 KiB
PHP

<?php
namespace App\Service\Pdf;
use App\Entity\CustomerSplit;
use Fpdf\Fpdf;
use IntlDateFormatter;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use App\Entity\Account; // Import inutile, laissé pour garder la cohérence avec le code fourni
// Define the EURO symbol as it's often missing in standard character sets for FPDF's ISO-8859-1
if (!defined('EURO_ECH')) {
define('EURO_ECH', chr(128));
}
class EchPdfDetails extends FPDF
{
private array $items;
public function __construct(
private readonly KernelInterface $kernel,
private readonly CustomerSplit $customerSplit,
)
{
parent::__construct();
$items = [];
foreach ($this->customerSplit->getCustomerSplitLines() as $line) {
$items[] = [
'dates' => $line->getDatePrev(),
'amount' => $line->getAmount(),
];
}
// Assuming ksort was intended to sort by date, but it sorts by key.
// Given $items is a simple array of indexed arrays, ksort does nothing useful here.
// If sorting by date is needed, a custom sort function should be used.
// For now, I'll keep the original logic but note the intent.
// ksort($items);
$this->items = $items;
$title = mb_convert_encoding("FACILITE DE PAIEMENT N° " . $this->customerSplit->getNum(), "ISO-8859-1", "UTF-8");
$this->SetTitle($title);
}
public function Header(): void
{
$this->SetFont('Arial', '', 10);
$this->Image($this->kernel->getProjectDir() . "/public/assets/logo_siteconseil.png", 90, 5, 25);
$formatter = new IntlDateFormatter(
'fr_FR',
IntlDateFormatter::FULL,
IntlDateFormatter::NONE,
'Europe/Paris',
IntlDateFormatter::GREGORIAN
);
// Uniformisation de l'encodage en 'ISO-8859-1'
$numDevisText = mb_convert_encoding("FACILITE DE PAIEMENT N° " . $this->customerSplit->getNum(), 'ISO-8859-1', 'UTF-8');
$dateText = mb_convert_encoding("Saint-Quentin, " . $formatter->format($this->customerSplit->getCreateAt()), 'ISO-8859-1', 'UTF-8');
$this->Text(15, 80, $numDevisText);
$this->Text(15, 85, $dateText);
$this->SetFont('Arial', 'B', 12);
$y = 60;
$customer = $this->customerSplit->getCustomer();
// Uniformisation de l'encodage en 'ISO-8859-1'
$this->Text(110, $y, mb_convert_encoding($customer->getRaisonSocial(), 'ISO-8859-1', 'UTF-8'));
$y += 5;
$this->Text(110, $y, mb_convert_encoding($customer->getAddress(), 'ISO-8859-1', 'UTF-8'));
if ($address2 = $customer->getAddress2()) {
$y += 5;
$this->Text(110, $y, mb_convert_encoding($address2, 'ISO-8859-1', 'UTF-8'));
}
if ($address3 = $customer->getAddress3()) {
$y += 5;
$this->Text(110, $y, mb_convert_encoding($address3, 'ISO-8859-1', 'UTF-8'));
}
$y += 5;
$cityLine = $customer->getZipcode() . " " . $customer->getCity();
$this->Text(110, $y, mb_convert_encoding($cityLine, 'ISO-8859-1', 'UTF-8'));
// Add a line break after the header to start the content below.
$this->SetY(100);
}
public function generated(): void
{
$this->AddPage(); // Ensure a page is available
$this->SetY(105); // Start position after the header
$this->SetFont('Arial', '', 10);
$this->SetTextColor(0, 0, 0);
// Calculate total amount and number of installments
$totalAmount = 0.0;
$installmentsCount = count($this->items);
foreach ($this->items as $item) {
$totalAmount += $item['amount'];
}
// Format total amount with two decimals
$formattedTotalAmount = number_format($totalAmount, 2, ',', ' ');
// Main text introduction
$introText = "Voici la facilité de paiement qui vous a été accordée :";
$this->Write(5, mb_convert_encoding($introText, 'ISO-8859-1', 'UTF-8'));
$this->Ln(8);
// ----------------------------------------------
// --- CLAUSE : Rétractation ---
// ----------------------------------------------
$this->SetFont('Arial', 'U', 10); // Souligné
$retractTitle = "Droit de Rétractation";
$this->Write(5, mb_convert_encoding($retractTitle, 'ISO-8859-1', 'UTF-8'));
$this->SetFont('Arial', '', 10);
$this->Ln(5);
// Correction du problème de mise en gras de l'email
$this->Write(5, mb_convert_encoding("Pour vous rétracter de cette facilité de paiement, vous devez envoyer un mail à l'adresse ", 'ISO-8859-1', 'UTF-8'));
$this->SetFont('Arial', 'B', 10); // DÉBUT GRAS
$this->Write(5, mb_convert_encoding("s.com@siteconseil.fr", 'ISO-8859-1', 'UTF-8'));
$this->SetFont('Arial', '', 10); // FIN GRAS
$retractTextEnd = " pour en demander l'annulation, à condition qu'aucun paiement n'ait déjà été effectué.";
$this->Write(5, mb_convert_encoding($retractTextEnd, 'ISO-8859-1', 'UTF-8')); // Utilisation de Write() pour continuer sur la même ligne
$this->Ln(8);
// ----------------------------------------------
// --- CLAUSE : Limitation et Impayé ---
// ----------------------------------------------
$this->SetFont('Arial', 'I', 10); // Italique
$limitationText = "Attention : Une seule facilité de paiement peut être accordée à la fois. Tout impayé entraînera l'impossibilité de demander une nouvelle facilité de paiement.";
$this->MultiCell(180, 5, mb_convert_encoding($limitationText, 'ISO-8859-1', 'UTF-8'), 0, 'L');
$this->Ln(8);
$this->SetFont('Arial', '', 10); // Retour à la police normale
// Summary details - Displayed in parts to allow for bolding
$this->Write(5, mb_convert_encoding("Cette facilité de paiement est répartie sur ", 'ISO-8859-1', 'UTF-8'));
$this->SetFont('Arial', 'B', 10);
$this->Write(5, mb_convert_encoding($installmentsCount . " mensualité(s)", 'ISO-8859-1', 'UTF-8'));
$this->SetFont('Arial', '', 10);
$this->Write(5, mb_convert_encoding(" pour un montant total de ", 'ISO-8859-1', 'UTF-8'));
$this->SetFont('Arial', 'B', 10);
$this->Write(5, mb_convert_encoding($formattedTotalAmount. " ", 'ISO-8859-1', 'UTF-8').EURO_ECH);
$this->Ln(10);
// Reset font for the rest of the content
$this->SetFont('Arial', '', 10);
// Add installment details table
if (!empty($this->items)) {
$this->SetFont('Arial', 'B', 10);
$this->Cell(50, 7, mb_convert_encoding('Échéance', 'ISO-8859-1', 'UTF-8'), 1, 0, 'C');
$this->Cell(50, 7, mb_convert_encoding('Montant', 'ISO-8859-1', 'UTF-8'), 1, 1, 'C');
$this->SetFont('Arial', '', 10);
$formatter = new IntlDateFormatter(
'fr_FR',
IntlDateFormatter::SHORT,
IntlDateFormatter::NONE,
'Europe/Paris',
IntlDateFormatter::GREGORIAN
);
foreach ($this->items as $item) {
// Assuming 'dates' is a \DateTimeInterface object
$dateText = $formatter->format($item['dates']);
$amountText = number_format($item['amount'], 2, ',', ' ');
$this->Cell(50, 6, mb_convert_encoding($dateText, 'ISO-8859-1', 'UTF-8'), 1, 0, 'C');
$this->Cell(50, 6, mb_convert_encoding($amountText, 'ISO-8859-1', 'UTF-8')." ".EURO_ECH, 1, 1, 'R');
}
$this->Ln(10);
}
// --- SECTION: Default Payment Clause & Services Suspension ---
$this->SetFont('Arial', 'B', 10);
$this->SetTextColor(255, 0, 0); // Red color for emphasis
$defaultTitle = "Conséquences en cas de défaut de paiement :";
$this->Write(5, mb_convert_encoding($defaultTitle, 'ISO-8859-1', 'UTF-8'));
$this->Ln(7);
$this->SetFont('Arial', '', 10);
$this->SetTextColor(0, 0, 0); // Reset to black
// 1. Regularization Clause (7 days) with manual bolding
$this->Write(5, mb_convert_encoding("En cas de défaut de paiement à l'échéance convenue, vous disposerez d'un délai de ", 'ISO-8859-1', 'UTF-8'));
$this->SetFont('Arial', 'B', 10);
$this->Write(5, mb_convert_encoding("7 jours calendaires", 'ISO-8859-1', 'UTF-8'));
$this->SetFont('Arial', '', 10);
$this->Write(5, mb_convert_encoding(" pour régulariser votre situation. Passé ce délai, la présente facilité de paiement sera ", 'ISO-8859-1', 'UTF-8'));
$this->SetFont('Arial', 'B', 10);
$this->Write(5, mb_convert_encoding("immédiatement rompue", 'ISO-8859-1', 'UTF-8'));
$this->SetFont('Arial', '', 10);
$this->Write(5, mb_convert_encoding(" et l'intégralité des sommes restant dues deviendra exigible, ", 'ISO-8859-1', 'UTF-8'));
$this->SetFont('Arial', 'B', 10);
$this->Write(5, mb_convert_encoding("sans qu'aucun remboursement ne puisse être accordé", 'ISO-8859-1', 'UTF-8'));
$this->SetFont('Arial', '', 10);
$this->Write(5, mb_convert_encoding(".", 'ISO-8859-1', 'UTF-8'));
$this->Ln(5);
// 2. Service Suspension Clause and Collection with manual bolding
$this->Write(5, mb_convert_encoding("Tout défaut de paiement entraînera la ", 'ISO-8859-1', 'UTF-8'));
$this->SetFont('Arial', 'B', 10);
$this->Write(5, mb_convert_encoding("suspension immédiate des services associés", 'ISO-8859-1', 'UTF-8'));
$this->SetFont('Arial', '', 10);
$this->Write(5, mb_convert_encoding(" et la créance pourra être transmise à une ", 'ISO-8859-1', 'UTF-8'));
$this->SetFont('Arial', 'B', 10);
$this->Write(5, mb_convert_encoding("société de recouvrement", 'ISO-8859-1', 'UTF-8'));
$this->SetFont('Arial', '', 10);
$this->Write(5, mb_convert_encoding(".", 'ISO-8859-1', 'UTF-8'));
$this->Ln(15);
// ----------------------------------------------
// --- Signature Blocks ---
// ----------------------------------------------
$this->SetFont('Arial', 'B', 10);
// Signature Block for the Client
$this->Cell(80, 5, mb_convert_encoding('Le Client', 'ISO-8859-1', 'UTF-8'), 0, 0, 'C');
// Separator/Spacer
$this->Cell(30, 5, '', 0, 0, 'C');
// Signature Block for SARL SITECONSEIL
$this->Cell(80, 5, mb_convert_encoding('SARL SITECONSEIL', 'ISO-8859-1', 'UTF-8'), 0, 1, 'C'); // 1 = Go to next line
$this->Ln(5); // Vertical space for the signature line and placeholder
// Signature Line for the Client
$this->Cell(80, 0, '', 'T', 0, 'C'); // 'T' for Top border (the line)
// Separator/Spacer
$this->Cell(30, 0, '', 0, 0, 'C');
// Signature Line for SARL SITECONSEIL
$this->Cell(80, 0, '', 'T', 1, 'C'); // 1 = Go to next line
$this->SetY($this->GetY() - 5); // Remonte d'une ligne pour aligner les marqueurs
// Add Signature Placeholder for the Client
$this->SetX(15);
$this->Cell(70, 5, '{{Signature;type=signature;role=Client}}', 0, 0, 'C');
// Separator/Spacer
$this->Cell(30, 5, '', 0, 0, 'C');
$t = new \DateTimeImmutable();
// Add Acceptance Text for SARL SITECONSEIL (Restored previous logic)
$this->Cell(80, 5, mb_convert_encoding("Accepter le ".$t->format('d/m/y H:i'), 'ISO-8859-1', 'UTF-8'), 0, 1, 'C');
}
public function Footer()
{
// This is where FPDF positions the footer content, regardless of the page content length.
// SetY(-30) ensures the pointer is 30mm from the bottom, placing the footer reliably.
$this->SetY(-30);
$this->SetFont('Arial', 'B', 8);
$this->SetTextColor(253, 140,4);
$this->SetDrawColor(253, 140,4);
$this->Cell(190, 5, mb_convert_encoding("Partenaire de vos projects de puis 1997", 'ISO-8859-1', 'UTF-8'), 0, 1,'C');
$this->Line(15,$this->GetY(),195,$this->GetY());
$this->SetFont('Arial', '', 8);
$this->SetTextColor(0, 0, 0);
$this->Ln(2);
$this->Cell(190, 4, mb_convert_encoding("27, rue le Sérurier - 02100 SAINT-QUENTIN - Tél: 03 23 05 62 43 - Réglement par virement: FR76 1020 6006 7198 7497 7981 061", 'ISO-8859-1', 'UTF-8'), 0, 1,'C');
$this->Cell(190, 4, mb_convert_encoding("e-mail : s.com@siteconseil.fr - www.siteconseil.fr", 'ISO-8859-1', 'UTF-8'), 0, 1,'C');
$this->Cell(190, 4, mb_convert_encoding("S.A.R.L aux captial de 71400 ", 'ISO-8859-1', 'UTF-8').EURO_ECH." - ".mb_convert_encoding("N°SIRET 418 664 058 00025 - N° TVA FR 05 418 664 058 - CODE APE 6201 Z - R.C. St-Quentin 418 664 058", 'ISO-8859-1', 'UTF-8'), 0,0 ,'C');
}
}