357 lines
15 KiB
PHP
357 lines
15 KiB
PHP
<?php
|
|
|
|
require_once(__DIR__ .'/../vendor/tecnickcom/tcpdf/tcpdf.php'); // Include the main TCPDF library
|
|
require_once(__DIR__ .'/../vendor/phpqrcode/qrlib.php');
|
|
|
|
|
|
class MYPDF extends TCPDF {
|
|
public function Header() {
|
|
$this->Image('images/logo_koriolan.png', 10, 10, 60, 0, 'PNG', 'https://koriolan.tech');
|
|
}
|
|
|
|
public function Footer() {
|
|
$this->SetFont('helvetica', '', 7);
|
|
$this->SetTextColor(150, 150, 150);
|
|
|
|
// Partie gauche :
|
|
$this->SetXY(10, -23);
|
|
$this->Cell(90, 10, 'Koriolan', 0, false, 'L');
|
|
$this->SetXY(10, -19);
|
|
$this->Cell(90, 10, 'SASU au capital social de 50 000€', 0, false, 'L');
|
|
$this->SetXY(10, -15);
|
|
$this->Cell(90, 10, '6 rue Grange Bruyère - 69110 Sainte-Foy-Lès-Lyon - FRANCE', 0, false, 'L');
|
|
|
|
// Partie droite :
|
|
$this->SetXY(110, -23);
|
|
$this->Cell(90, 10, 'RCS Lyon 879 809 341', 0, false, 'R');
|
|
$this->SetXY(110, -19);
|
|
$this->Cell(90, 10, 'SIRET 879 809 341 00016', 0, false, 'R');
|
|
$this->SetXY(110, -15);
|
|
$this->Cell(90, 10, 'TVA Intraco. FR29 879 809 341', 0, false, 'R');
|
|
}
|
|
|
|
public function CreateTextBox($textval, $x = 0, $y = 0, $width = 0, $height = 10, $fontsize = 10, $fontstyle = '', $align = 'L', $border = 0) {
|
|
$this->SetXY($x, $y);
|
|
$this->SetFont('helvetica', $fontstyle, $fontsize);
|
|
$this->Cell($width, $height, $textval, 0, false, $align);
|
|
}
|
|
}
|
|
|
|
|
|
//********************************************************************************************************************************
|
|
// Fonction : Génère le document PDF à partir des données reçues en paramètres
|
|
// Reçoit : une autre concernant la pièce ('Commande', 'Facture') et ses attributs, une variable concernant le client,
|
|
// et une autre contenant les lignes de la pièce. Le fichier généré est stocké dans 'documents/commandes' ou 'documents/factures'.
|
|
// Retour : 0 si Ok, -1 si erreur
|
|
//********************************************************************************************************************************
|
|
function document_pdf($piece, $client, $lignes)
|
|
{
|
|
|
|
switch($piece['type'])
|
|
{
|
|
case "commande":
|
|
{
|
|
$nom_piece = $_SESSION['textes']['fonctions_pdf']['document']['piece']['type_commande'];
|
|
$rep = "commandes";
|
|
break;
|
|
}
|
|
case "facture":
|
|
{
|
|
$nom_piece = $_SESSION['textes']['fonctions_pdf']['document']['piece']['type_facture'];
|
|
$rep = "factures";
|
|
break;
|
|
}
|
|
default: return(-1);
|
|
}
|
|
|
|
$pdf = new MYPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
|
|
|
|
// set document (meta) information :
|
|
$pdf->SetCreator(PDF_CREATOR);
|
|
$pdf->SetAuthor('Koriolan');
|
|
$pdf->SetTitle($nom_piece.' '.$piece['no']);
|
|
$pdf->SetSubject('ShipHeart');
|
|
$pdf->SetKeywords('ShipHeart by Koriolan');
|
|
|
|
$pdf->SetTextColor(0, 69, 99);
|
|
$pdf->SetFont('helvetica', '', 10);
|
|
|
|
$pdf->AddPage();
|
|
|
|
// L'abscisse x varie de 10 à 200 (soit une marge de 10 à gauche et 10 à droite)
|
|
|
|
// ---------------------------------------------------------
|
|
// Adresse du client :
|
|
$x = 120; // Doit rester < 200 qui est la marge droite !
|
|
$y = 30;
|
|
$pdf->CreateTextBox($client['entreprise'], $x, $y, (200 - $x), 12, 12, 'B', 'L');
|
|
$y += 6;
|
|
$pdf->CreateTextBox($client['nom_complet'], $x, $y, (200 - $x), 10, 10, '', 'L');
|
|
$y += 5;
|
|
$pdf->CreateTextBox($client['rue'], $x, $y, (200 - $x), 10, 10, '', 'L');
|
|
$y += 5;
|
|
$pdf->CreateTextBox($client['ville_complete'], $x, $y, (200 - $x), 10, 10, '', 'L');
|
|
$y += 5;
|
|
$pdf->CreateTextBox($client['libelle_pays'], $x, $y, (200 - $x), 10, 10, '', 'L');
|
|
|
|
|
|
// ---------------------------------------------------------
|
|
// N° de commande :
|
|
$x = 10;
|
|
$y += 10;
|
|
$pdf->CreateTextBox($nom_piece.' '.$piece['no'], $x, $y, (200 - $x), 20, 20, 'B', 'L');
|
|
|
|
// ---------------------------------------------------------
|
|
// Date :
|
|
$x = 120;
|
|
$y += 15;
|
|
|
|
$pdf->CreateTextBox('Date : '.date(''.$_SESSION['textes']['all']['all']['date']['format_d_m_y'].''), $x, $y, (200 - $x), 10, 10, '', 'R');
|
|
|
|
// ---------------------------------------------------------
|
|
// Tableau
|
|
$x = 10;
|
|
$y += 15;
|
|
$pdf->Line($x, $y, (210 - $x), $y); // Ligne horizontale
|
|
|
|
$x = 10;
|
|
// $y += 5;
|
|
$largeur_1 = 90;
|
|
$largeur_2 = 20;
|
|
$largeur_3 = 30;
|
|
$largeur_4 = 20;
|
|
$largeur_5 = 30;
|
|
$pdf->CreateTextBox($_SESSION['textes']['fonctions_pdf']['document']['piece']['designation_titre'], $x, $y, $largeur_1, 10, 10, 'B', 'L', 1); // Ligne d'entête
|
|
$x += $largeur_1;
|
|
$pdf->CreateTextBox($_SESSION['textes']['fonctions_pdf']['document']['piece']['quantite_titre'], $x, $y, $largeur_2, 10, 10, 'B', 'C', 1);
|
|
$x += $largeur_2;
|
|
$pdf->CreateTextBox($_SESSION['textes']['fonctions_pdf']['document']['piece']['pu_ht_titre'], $x, $y, $largeur_3, 10, 10, 'B', 'R', 1);
|
|
$x += $largeur_3;
|
|
$pdf->CreateTextBox($_SESSION['textes']['fonctions_pdf']['document']['piece']['taux_tva_titre'], $x, $y, $largeur_4, 10, 10, 'B', 'C', 1);
|
|
$x += $largeur_4;
|
|
$pdf->CreateTextBox($_SESSION['textes']['fonctions_pdf']['document']['piece']['pt_ttc_titre'], $x, $y, $largeur_5, 10, 10, 'B', 'R', 1);
|
|
|
|
$x = 10;
|
|
$y += 10;
|
|
$pdf->Line($x, $y, (210 - $x), $y); // Ligne horizontale
|
|
|
|
$x = 10;
|
|
// $y += 5;
|
|
for ($i = 0; $i < $piece['nb_lignes']; $i ++)
|
|
{
|
|
$pdf->CreateTextBox($lignes[$i]['designation'],
|
|
$x, $y, $largeur_1, 10, 10, '', 'L');
|
|
$x += $largeur_1;
|
|
$pdf->CreateTextBox($lignes[$i]['qte'],
|
|
$x, $y, $largeur_2, 10, 10, '', 'C');
|
|
$x += $largeur_2;
|
|
$pdf->CreateTextBox(number_format($lignes[$i]['pu_ht'], 2, ".", " ").' €',
|
|
$x, $y, $largeur_3, 10, 10, '', 'R');
|
|
$x += $largeur_3;
|
|
$pdf->CreateTextBox(number_format($lignes[$i]['taux_tva'], 2, ".", " ").' %',
|
|
$x, $y, $largeur_4, 10, 10, '', 'C');
|
|
$x += $largeur_4;
|
|
$pdf->CreateTextBox(number_format(($lignes[$i]['qte'] * $lignes[$i]['pu_ht'] * (1 + ($lignes[$i]['taux_tva']/100))), 2, ".", " ").' €',
|
|
$x, $y, $largeur_5, 10, 10, '', 'R');
|
|
$x = 10;
|
|
$y += 5;
|
|
|
|
if ($y > 260) // Détection d'un saut de page nécessaire
|
|
{
|
|
$y = 30;
|
|
$pdf->AddPage();
|
|
}
|
|
}
|
|
|
|
// Ligne horizontale :
|
|
$x = 10;
|
|
$y += 5;
|
|
$pdf->Line($x, $y, (210 - $x), $y);
|
|
|
|
// ---------------------------------------------------------
|
|
// Vérification si un saut de page est nécessaire :
|
|
if ($y > 260)
|
|
{
|
|
$y = 30;
|
|
$pdf->AddPage();
|
|
}
|
|
|
|
// ---------------------------------------------------------
|
|
// Totaux :
|
|
$x = 10;
|
|
// $y += 5;
|
|
$pdf->CreateTextBox('TOTAL', $x, $y, $largeur_1, 10, 11, 'B', 'R');
|
|
$x += $largeur_1;
|
|
$x += $largeur_2;
|
|
$pdf->CreateTextBox(number_format($piece['total_ht'], 2, ".", " ").' €',
|
|
$x, $y, $largeur_3, 10, 11, '', 'R');
|
|
$x += $largeur_3;
|
|
$x += $largeur_4;
|
|
$pdf->CreateTextBox(number_format($piece['total_ttc'], 2, ".", " ").' €',
|
|
$x, $y, $largeur_5, 10, 11, 'B', 'R');
|
|
|
|
|
|
// ---------------------------------------------------------
|
|
// Commentaire :
|
|
if ($piece['commentaire'] != "")
|
|
{
|
|
if ($y > 260) // Vérification si un saut de page est nécessaire
|
|
{
|
|
$y = 30;
|
|
$pdf->AddPage();
|
|
}
|
|
|
|
$x = 10;
|
|
$y += 30;
|
|
$pdf->SetFont('helvetica', '', 10);
|
|
$pdf->MultiCell((200 - $x), 10, $piece['commentaire'],
|
|
'TRBL', 'J', 0, 1, $x, $y, true, 0, true, true);
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------
|
|
// Ajout des numéros de page :
|
|
// NB : les fonctions usuelles ('getAliasNumPage()' et 'getAliasNbPages()') dans le Header ou le Footer fonctionnent bien mais posent des soucis d'alignement...
|
|
$nb_pages = $pdf->getNumPages();
|
|
|
|
for($i = 1; $i < ($nb_pages + 1); $i ++)
|
|
{
|
|
$pdf->setPage($i);
|
|
$pdf->SetFont('helvetica', '', 10);
|
|
$pdf->SetTextColor(0, 69, 99);
|
|
$pdf->SetXY(150,10);
|
|
$pdf->Cell(50, 10, 'Page '.$i.'/'.$nb_pages, 0, false, 'R');
|
|
}
|
|
|
|
// ---------------------------------------------------------
|
|
// Fermeture de l'objet PDF et enreigistrement du fichier :
|
|
ob_clean(); // Semble nécessaire ; sinon erreur du 'output' suivant
|
|
$pdf_string = $pdf->Output('pseudo.pdf', 'S'); // export du flux dans une chaine (le nom du fichier est ignoré...)
|
|
|
|
// Copie de cette chaine dans le fichier final (cette solution en 2 temps permet d'éviter de devoir utiliser un nom de fichier absolu (semble obligatoire avec Output et l'option 'F')
|
|
file_put_contents('../../documents/'.$rep.'/'.$piece['no'].'.pdf', $pdf_string);
|
|
|
|
return(0);
|
|
}
|
|
|
|
|
|
|
|
class MYPDF2 extends TCPDF {
|
|
public function Header() {
|
|
// $this->Image('images/logo_shipheart.png', 10, 10, 60, 0, 'PNG', 'https://shipheart.tech');
|
|
}
|
|
|
|
public function CreateTextBox($textval, $x = 0, $y = 0, $width = 0, $height = 10, $fontsize = 10, $fontstyle = '', $align = 'J', $border = 0) {
|
|
$this->SetXY($x, $y);
|
|
$this->SetFont('helvetica', $fontstyle, $fontsize);
|
|
$this->SetFillColor(255,255,255);
|
|
$this->MultiCell($width, $height, $textval, 0, $align, false);
|
|
}
|
|
}
|
|
|
|
|
|
//********************************************************************************************************************************
|
|
// Fonction : URL d'activation d'un code d'invitation, portée par le QR code ET par le lien cliquable du PDF d'invitation.
|
|
// Construite à partir de URL_SITE (definitions.php) : plus d'adresse écrite en dur (synthèse §47).
|
|
// Reçoit : le code d'invitation
|
|
// Retour : l'URL complète
|
|
//********************************************************************************************************************************
|
|
function Url_activation_code_acces($code)
|
|
{
|
|
return 'https://'.URL_SITE.'/shipmembers.php?code_acces='.urlencode($code);
|
|
}
|
|
|
|
|
|
//********************************************************************************************************************************
|
|
// Fonction : Image PNG d'un QR code, produite EN MÉMOIRE (aucun fichier temporaire : l'ancienne version écrivait le QR code
|
|
// et le PDF dans html/temp/, donc dans la partie publique du site - synthèse §47).
|
|
// Reçoit : le texte à encoder
|
|
// Retour : le contenu binaire de l'image PNG
|
|
//********************************************************************************************************************************
|
|
function Qr_code_png($texte)
|
|
{
|
|
ob_start();
|
|
QRcode::png($texte, false, QR_ECLEVEL_M, 8, 2); // false = sortie standard, capturée par le tampon
|
|
$png = ob_get_clean();
|
|
header_remove('Content-Type'); // phpqrcode a posé un en-tête image/png : retiré, le PDF posera le sien
|
|
return $png;
|
|
}
|
|
|
|
|
|
//********************************************************************************************************************************
|
|
// Fonction : Génère et ENVOIE au navigateur le PDF d'une invitation nominative à accéder à un bateau (synthèse §47).
|
|
// La page appelante doit s'arrêter juste après (exit) : rien ne doit suivre le PDF.
|
|
// Reçoit : l'invitation (tableau) : Code, Nom_bateau, Email_invite, Prenom_invite, Nom_invite, Type_acces,
|
|
// Expiration_invitation
|
|
// Retour : rien (le PDF est envoyé en téléchargement)
|
|
//********************************************************************************************************************************
|
|
function code_acces_pdf($invitation)
|
|
{
|
|
$code = $invitation['Code'];
|
|
$nom_bateau = $invitation['Nom_bateau'];
|
|
$email = $invitation['Email_invite'];
|
|
$destinataire = trim(($invitation['Prenom_invite'] ?? '').' '.($invitation['Nom_invite'] ?? ''));
|
|
$type_acces = $invitation['Type_acces'] ?? '';
|
|
$expiration = ($invitation['Expiration_invitation'] != NULL) ? date_format(date_create($invitation['Expiration_invitation']), 'd/m/Y') : '';
|
|
$nom_fichier = 'Invitation_'.preg_replace('/[^A-Za-z0-9_-]/', '_', $nom_bateau).'_'.$code.'.pdf';
|
|
|
|
$pdf = new MYPDF2('LANDSCAPE', 'px', 'A4', true, 'UTF-8', false);
|
|
|
|
// set document (meta) information :
|
|
$pdf->SetCreator(PDF_CREATOR);
|
|
$pdf->SetAuthor('Koriolan');
|
|
$pdf->SetTitle('Invitation - '.$nom_bateau);
|
|
$pdf->SetSubject('ShipHeart');
|
|
$pdf->SetKeywords('ShipHeart by Koriolan');
|
|
|
|
$pdf->SetTextColor(0, 69, 99);
|
|
$pdf->SetFont('helvetica', '', 10);
|
|
$pdf->SetAutoPageBreak(false); // Mise en page fixe sur 2 feuilles : pas de saut de page automatique (l'ancienne version
|
|
// obtenait sa 2e feuille par un saut automatique, déclenché par le texte du bas de la 1re)
|
|
|
|
//---------------------------------------------------------
|
|
// Feuille 1 (pliée en deux : à droite la couverture, à gauche le mot d'accueil) :
|
|
$pdf->AddPage();
|
|
$pdf->SetDrawColor(217,217,217);
|
|
$pdf->Line(421, 0, 421, 595);
|
|
|
|
$pdf->Image('images/logo_shipheart.png', 506, 214, 252, 167, 'PNG', 'https://shipheart.tech'); // Couverture
|
|
$pdf->Image('images/logo_shipheart.png', 12, 12, 64, 45, 'PNG', 'https://shipheart.tech');
|
|
|
|
$salutation = ($destinataire != '') ? $destinataire.",\n\n" : '';
|
|
$pdf->CreateTextBox($salutation."Nous vous remercions pour votre confiance et sommes ravis de vous offrir un accès aux informations du bateau ".$nom_bateau." via notre plateforme Ship2net.\n\n"
|
|
."We thank you for your trust and are delighted to offer you access to the information of the boat ".$nom_bateau." via our Ship2net platform.",
|
|
52, 150, 317, 230, 12, '', 'L');
|
|
|
|
$pdf->CreateTextBox($nom_bateau.(($type_acces != '') ? ' - '.$type_acces : ''), 0, 520, 421, 46, 12, 'B', 'C');
|
|
|
|
//---------------------------------------------------------
|
|
// Feuille 2 (à gauche le mode d'emploi, à droite le QR code et le code) :
|
|
$pdf->AddPage();
|
|
$pdf->SetDrawColor(217,217,217);
|
|
$pdf->Line(421, 0, 421, 595);
|
|
$pdf->Image('images/logo_shipheart.png', 12, 12, 64, 45, 'PNG', 'https://shipheart.tech');
|
|
$pdf->Image('images/logo_shipheart.png', 766, 12, 64, 45, 'PNG', 'https://shipheart.tech');
|
|
|
|
$pdf->CreateTextBox("Cette invitation est réservée à l'adresse ".$email.".\n"
|
|
."Pour l'activer, scannez le QR code ci-contre, puis connectez-vous à votre compte ShipMember avec cette adresse (ou créez votre compte avec cette adresse).\n"
|
|
."Sans appareil photo : rendez-vous sur ".URL_SITE." et connectez-vous avec cette adresse ; l'invitation apparaîtra dans « Mes invitations ».\n"
|
|
.(($expiration != '') ? "Invitation valable jusqu'au ".$expiration.".\n" : '')
|
|
."\n"
|
|
."This invitation is reserved for the address ".$email.".\n"
|
|
."To activate it, scan the QR code opposite, then log in to your ShipMember account with this address (or create your account with this address).\n"
|
|
."Without a camera: go to ".URL_SITE." and log in with this address; the invitation will appear in \"My invitations\".\n"
|
|
.(($expiration != '') ? "Invitation valid until ".$expiration."." : ''),
|
|
52, 110, 317, 400, 11, '', 'L');
|
|
|
|
$pdf->Image('@'.Qr_code_png(Url_activation_code_acces($code)), 546, 196, 164, 164, 'PNG', Url_activation_code_acces($code));
|
|
$pdf->CreateTextBox($code, 506, 372, 244, 30, 18, 'B', 'C');
|
|
$pdf->CreateTextBox(URL_SITE, 506, 400, 244, 20, 11, '', 'C');
|
|
|
|
//---------------------------------------------------------
|
|
// Envoi direct au navigateur, sans fichier intermédiaire. Tout ce qui aurait déjà été mis en tampon (espaces,
|
|
// avertissements...) est jeté : un seul octet parasite avant le PDF le corromprait.
|
|
while (ob_get_level() > 0) ob_end_clean();
|
|
$pdf->Output($nom_fichier, 'D');
|
|
}
|