<?php namespace Paheko; require_once __DIR__ . '/_inc.php'; $session->requireAccess($session::SECTION_ACCOUNTING, $session::ACCESS_READ); $users = new Users\Users; f(['id' => 'required|numeric']); $id = (int) qg('id'); $sign_tag = UserTemplate\Functions::signature(); // Vérification que le document existe if (!$f = $facture->get($id)) { throw new UserException("Ce document n'existe pas."); } $moyen_paiement = $facture->getMoyenPaiement($f->moyen_paiement); // Récupération infos membre try { if ($f->receveur_membre) { $c = $users->get($f->receveur_id); foreach(['ville','code_postal','adresse'] as $v) { if($c->$v == '') { $c->$v = '[A RENSEIGNER DANS LA FICHE MEMBRE]'; } } } else { $c = $client->get($f->receveur_id); } } catch(UserException $e) { $form->addError($e); } // Formatage dates $emission = $f->date_emission->format('d/m/Y'); if (isset($f->date_echeance)) { $echeance = $f->date_echeance->format('d/m/Y'); } // -- Création du PDF // Génération factures, devis et cotisation if ($f->type_facture != CERFA) { switch ($f->type_facture) { case FACT: $doc = 'Facture n°'. $f->numero; break; case DEVIS: $doc = 'Devis n°'. $f->numero; break; case COTIS: $doc = 'Reçu de cotisation n°'. $f->numero; break; } // utiliser l'adresse configurée dans le plugin sinon celle de l'asso sinon rien ! if ($plugin->getConfig('rue_asso') != null && $plugin->getConfig('cp_asso') != null && $plugin->getConfig('ville_asso') != null) { $adresse = (($plugin->getConfig('numero_rue_asso') != null) ? $plugin->getConfig('numero_rue_asso') . " " : "") . $plugin->getConfig('rue_asso') . "<br>" . $plugin->getConfig('cp_asso') . " " . $plugin->getConfig('ville_asso'); } else if ($config->get('org_address') != null) { $adresse = str_replace("\n", '<br>', $config->get('org_address')); } else { $adresse = ""; } $asso = // 'Émis par :<br><br>'. '<b>'.$config->get('org_name')."</b><br>". $adresse ."<br>". (($t = $plugin->getConfig('rna_asso'))?"RNA : $t<br>":''). (($t = $plugin->getConfig('siret_asso'))?"SIRET : " . implode(' ', str_split($t, 3)) . "<br>":''). (($t = $config->get('email_asso'))?"Email : $t<br>":''). (($t = $config->get('site_asso'))?"Site web : $t<br>":''); $receveur = 'Adressé à :<br><br>'. '<b>'.$c->nom.'</b><br>'. $c->adresse."<br>". $c->code_postal.' '.$c->ville."<br>". (($t = $c->siret)?"SIREN/SIRET : " . implode(' ', str_split($t, 3)) . "<br>":''). (($t = $c->email)?"Email : $t<br>":''). (($t = $c->telephone)?"Tel : $t<br>":''); $total = Utils::money_format($f->total, ',', ' '); // Devis et facture if ($f->type_facture != COTIS) { $echeance = ($f->type_facture?'Échéance de paiement':'Échéance du devis')." : ".$echeance; $reglee = !$f->reglee?'Cette facture est en attente de règlement.':'Cette facture a été reglée.'; $footer = str_replace("\n", '<br>', $plugin->getConfig('footer') ?? '[Pied de page à configurer]'); $ttc = $plugin->getConfig('ttc') ? 'TTC':'HT'; // Génération du contenu de la facture ob_start(); echo <<<EOF <div class="h2"> <span>Contenu</span> - $doc </div> <hr> <table class="contenu"> <thead> <tr> <th> Désignations </th> <th> Prix </th> </tr> </thead> <tbody> EOF; $i = 1; foreach($f->contenu as $k=>$v) { echo '<tr><td>'; echo str_replace("\n", '<br>', $v['designation']); echo '</td><td>'; echo Utils::money_format($v['prix'], ',', ' ') .' €'; echo '</td></tr>'; $i++; } echo <<<EOF </tbody> <tfoot> <tr> <td><b>Total</b><br>Net à payer</td> <td><b>$total €</b><br>({$ttc})</td> </tr> </tfoot> </table> <footer> <div class="h2"><span>Détails</span></div> <hr> $echeance <br> $reglee Moyen de paiement : $moyen_paiement <p> $footer </p> </footer> EOF; $content = ob_get_clean(); } else // Reçu de cotisation { $lieu = $plugin->getConfig('ville_asso'); $intitule = $f->contenu['intitule']; $souscription = date('d/m/Y', strtotime($f->contenu['souscription'])); if($f->contenu['expiration'] == '1970-01-01') { $expiration = "jour même, s'agissant d'une cotisation ponctuelle."; } else { $expiration = date('d/m/Y', strtotime($f->contenu['expiration'])); } // Génération du contenu du reçu de cotisation $content = <<<EOF <div class="h2"> <span>Reçu de votre cotisation</span> - $doc </div> <hr> <div class="contenuTexte"> <p>À $lieu, le $emission,</p> <p>Bonjour,</p> <p>Nous accusons réception de votre cotisation « $intitule » reçue le $emission et nous vous en remercions.</p> <p>Nous reconnaissons que vous avez acquitté la somme de {$total} €.<br>111 Votre adhésion sera donc effective à compter du $souscription jusqu’au $expiration.</p> <br> <p>Nous vous prions de recevoir, chère adhérente, cher adhérent, nos meilleures salutations,</p> <br> <p>-représentant·e de l'asso-</p> <br> <p><i>Nous vous rappelons que la cotisation n’est pas soumise à la TVA et qu’elle ne donne pas lieu à la délivrance d’une facture. Elle n’ouvre pas droit au bénéfice des dispositions des articles 200, 238 bis et 885-0 V bis A du code général des impôts.</i></p> </div> EOF; } //-- Layout du document ob_start(); echo <<<EOF <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>{$doc}_{$emission}</title> <style> @page { size: A4 portrait; margin: 0; } body { padding: 4mm; font-family: Helvetica, Arial, sans; font-size: 10pt; background: white; } .titre { text-align: center; font-size: 8pt; margin-bottom: 6mm; margin-top: 0mm; } .h2 { margin: 20px 20px 0px 20px; } .h2 span { font-weight: bold; font-size: 14pt; } hr { margin: 5px 0px 15px 0px; border: none; border-top: 1px solid; } .adressage { font-size: 11pt; margin: auto; } .adressage td { width: 40%; vertical-align: top; } .contenuTexte { padding: 0 6mm; } .contenu { width: 100%; } .contenu td, .contenu th { vertical-align: top; padding: 8px 10px; margin : 0px; border-collapse: collapse; } .contenu tr th, .contenu tr td { text-align: right; width: 16%; } .contenu tr td:nth-child(1), .contenu tr th:nth-child(1) { text-align: left; width: 84%; } .contenu thead tr, .contenu tfoot tr { background-color: #CCE; border: 10px solid black; } .contenu tbody tr:nth-child(even) { background-color: #DDF !important; } .contenu tfoot { display: table-row-group; } footer { bottom: 0; margin: 14mm 0; width: inherit; font-size: 9pt; } </style> </head> <body> <p class="titre"> $doc - Émis le $emission </p> <table class="adressage"> <tr> <td>$asso</td> <td>$receveur</td> </tr> </table> <br> $content </body> </html> EOF; $html = ob_get_clean(); } // Génération du CERFA elseif ($f->type_facture == CERFA) { $doc = 'Reçu de don n°'. $f->numero; $url = WWW_URL; $libelles = $facture->listTextesCerfa(false); $t['numero'] = $f->numero; $t['org_name'] = $config->get('org_name'); $t['n_rue_asso'] = $plugin->getConfig('numero_rue_asso'); $t['rue_asso'] = $plugin->getConfig('rue_asso'); $t['cp_asso'] = $plugin->getConfig('cp_asso'); $t['ville_asso'] = $plugin->getConfig('ville_asso'); $t['objet0'] = $plugin->getConfig('objet_0'); $t['objet1'] = $plugin->getConfig('objet_1'); $t['objet2'] = $plugin->getConfig('objet_2'); $t['nom'] = $c->nom; $t['adresse'] = $c->adresse; $t['cp'] = $c->code_postal; $t['ville'] = $c->ville; $t['total'] = '***'.Utils::money_format($f->total).'***'; $t['total_lettre'] = numfmt_create('fr_FR', \NumberFormatter::SPELLOUT)->format($f->total/100). ' euros'; $t['d'] = ($f->date_emission->format('d')); $t['m'] = ($f->date_emission->format('m')); $t['Y'] = ($f->date_emission->format('Y')); $t['forme'] = $f->contenu['forme']; $t['nature'] = $f->contenu['nature']; $t['texte'] = $libelles[$f->contenu['texte']]; $t['art200'] = $t['art238'] = $t['art885'] = ''; if($plugin->getConfig('droit_art200')){ $t['art200'] = 'X'; } if($plugin->getConfig('droit_art238bis')){ $t['art238'] = 'X'; } if($plugin->getConfig('droit_art885-0VbisA')){ $t['art885'] = 'X'; } // forme du don switch ($t['forme']){ case '1': $t['frm'] = 'left: 15mm;'; break; case '2': $t['frm'] = 'left: 57.3mm;'; break; case '3': $t['frm'] = 'left: 115.2mm;'; break; case '4': $t['frm'] = 'left: 175.2mm;'; } // nature du don switch ($t['nature']){ case '1': $t['nat'] = 'left: 15mm;'; break; case '2': $t['nat'] = 'left: 57.3mm;'; break; case '3': $t['nat'] = 'left: 115.2mm;'; } // moyen de paiement switch ($f->moyen_paiement){ case 'ES': $t['pos'] = 'left: 15mm;'; break; case 'CH': $t['pos'] = 'left: 57.3mm;'; break; default: $t['pos'] = 'left: 115.2mm;'; } $t['d2'] = ($f->date_echeance->format('d')); $t['m2'] = ($f->date_echeance->format('m')); $t['Y2'] = ($f->date_echeance->format('Y')); ob_start(); echo <<<EOF <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>{$doc}_{$emission}</title> <style> @page { size: A4 portrait; margin: 0; padding: 0; } body { font-family: Helvetica, Arial, sans; font-size: 10pt; background: white; padding: 0; margin: 0; } .page div { position: absolute; } .page { padding: 0; margin: 0; break-after: always; width: 210mm; height: 297mm; background-size: cover; background-position: -5mm -4.8mm; } #p1 { background-image: url('{$url}p/facturation/cerfa-1.png'); } #p2 { background-image: url('{$url}p/facturation/cerfa-2.png'); position: relative; } </style> </head> <body> <div class="page" id="p1"> <div style="top: 10mm; left: 170mm;">{$t['numero']}</div> <div style="top: 35mm; left: 20mm;">{$t['org_name']}</div> <div style="top: 46mm; left: 20mm;">{$t['n_rue_asso']}</div> <div style="top: 46mm; left: 40mm;">{$t['rue_asso']}</div> <div style="top: 51.5mm; left: 37mm;">{$t['cp_asso']}</div> <div style="top: 51.5mm; left: 75mm;">{$t['ville_asso']}</div> <div style="top: 62mm; left: 18mm;">{$t['objet0']}</div> <div style="top: 66.5mm; left: 18mm;">{$t['objet1']}</div> <div style="top: 70.8mm; left: 18mm;">{$t['objet2']}</div> <div style="top: 128.5mm; left: 15mm;">X</div> </div> <div class="page" id="p2"> <div style="top: 18mm; left: 18mm;">{$t['nom']}</div> <div style="top: 32mm; left: 18mm;">{$t['adresse']}</div> <div style="top: 37mm; left: 40mm;">{$t['cp']}</div> <div style="top: 37mm; left: 80mm;">{$t['ville']}</div> <div style="top: 63mm; left: 87mm;">{$t['total']}</div> <div style="top: 73mm; left: 58mm;">{$t['total_lettre']}</div> <div style="top: 82mm; left: 69mm;">{$t['d']}</div> <div style="top: 82mm; left: 82mm;">{$t['m']}</div> <div style="top: 82mm; left: 99mm;">{$t['Y']}</div> <div style="top: 96mm; left: 53mm;">{$t['art200']}</div> <div style="top: 96mm; left: 103mm;">{$t['art238']}</div> <div style="top: 96mm; left: 153.0mm;">{$t['art885']}</div> <div style="top: 113mm; {$t['frm']}">X</div> <div style="top: 136mm; {$t['nat']}">X</div> <div style="top: 142mm; left: 25mm;">{$t['texte']}</div> <div style="top: 158.2mm; {$t['pos']}">X</div> <div style="top: 239mm; left: 139mm;">{$t['d2']}</div> <div style="top: 239mm; left: 148mm;">{$t['m2']}</div> <div style="top: 239mm; left: 156mm;">{$t['Y2']}</div> <div style="top: 243mm; left: 137mm;">{$sign_tag}</div> </div> </body> </html> EOF; $html = ob_get_clean(); } // End if cerfa if(qg('d') !== null) { $filename = 'Print'; if (preg_match('!<title>(.*)</title>!U', $html, $match)) { $filename = trim($match[1]); } header('Content-type: application/pdf'); header(sprintf('Content-Disposition: attachment; filename="%s.pdf"', Utils::safeFileName($filename))); Utils::streamPDF($html); } else { echo $html; }