diff --git a/class/actions_dolimeet.class.php b/class/actions_dolimeet.class.php index 4e1553f..f56aecf 100644 --- a/class/actions_dolimeet.class.php +++ b/class/actions_dolimeet.class.php @@ -724,7 +724,7 @@ public function doActions(array $parameters, $object, string $action): int } if (strpos($parameters['context'], 'contractcard') !== false) { - if ($action == 'builddoc' && strstr(GETPOST('model'), 'completioncertificatedocument_odt')) { + if ($action == 'builddoc' && strstr(GETPOST('model'), 'completioncertificatedocument_odt') || $action == 'builddoc' && strstr(GETPOST('model'), 'completioncertificatedocument')) { require_once __DIR__ . '/dolimeetdocuments/completioncertificatedocument.class.php'; $document = new CompletioncertificateDocument($this->db); diff --git a/core/modules/dolimeet/dolimeetdocuments/trainingsessiondocument/pdf_completioncertificatedocument.modules.php b/core/modules/dolimeet/dolimeetdocuments/trainingsessiondocument/pdf_completioncertificatedocument.modules.php new file mode 100644 index 0000000..d1a2196 --- /dev/null +++ b/core/modules/dolimeet/dolimeetdocuments/trainingsessiondocument/pdf_completioncertificatedocument.modules.php @@ -0,0 +1,282 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * or see https://www.gnu.org/ + */ + +/** + * \file class/dolimeetdocuments/trainingsessiondocument/pdf_completioncertificatedocument.modules.php + * \ingroup dolimeet + * \brief Completion certificate pdf model + */ + +// Load Dolibarr libraries +require_once DOL_DOCUMENT_ROOT . '/contrat/class/contrat.class.php'; +require_once DOL_DOCUMENT_ROOT . '/contact/class/contact.class.php'; +require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php'; + +// Load Saturne libraries +require_once __DIR__ . '/../../../../../../saturne/lib/saturne_functions.lib.php'; +require_once __DIR__ . '/../../../../../../saturne/class/saturnesignature.class.php'; +require_once __DIR__ . '/../../../../../../saturne/core/modules/saturne/modules_saturne.php'; + +/** + * Class pdf_completioncertificatedocument. + */ +class pdf_completioncertificatedocument extends SaturneDocumentModel +{ + /** + * @var DoliDb Database handler + */ + public $db; + + /** + * @var string model name + */ + public $name; + + /** + * @var string model description (short text) + */ + public $description; + + /** + * @var string Module + */ + public string $module = 'dolimeet'; + + /** + * @var string Document type + */ + public string $document_type = 'pdf_attendancesheetdocument'; + + public function __construct($db) + { + global $langs; + + $this->db = $db; + $this->name = 'completioncertificatedocument'; + $this->description = $langs->trans("AttendanceSheetDocumentPDFDescription"); + $this->type = 'pdf'; + $this->marge_gauche = 15; + $this->marge_droite = 15; + $this->marge_haute = 15; + $this->marge_basse = 15; + } + + /** + * Show footer signature of page + * + * @param TCPDF $pdf Object PDF + * @param int $tab_top tab height position + * @param float $tab_height tab height + * @param Translate $outputlangs Object language for output + * @param SaturneSignature $signatory Object signatory + * @param User $userTmp Object user + * @return void + */ + protected function tabSignature(&$pdf, $tab_top, $tab_height, $outputlangs, $signatory, $userTmp) + { + global $mysoc, $langs; + + $pdf->SetDrawColor(128, 128, 128); + $posmiddle = $this->marge_gauche + round(($this->page_largeur - $this->marge_gauche - $this->marge_droite) / 2); + $posy = $tab_top + $tab_height; + $posX = $pdf->getPageWidth() - $this->marge_droite - 100; + + $pdf->SetXY($this->marge_droite - 5, $posy); + $pdf->Cell(0, 0, '', 0, 1); + $pdf->Cell(0, 6, $langs->transnoentities('MadeAt') . ' : ' . $mysoc->town, 0, 1); + $pdf->Cell(0, 6, $langs->transnoentities('The') . ' : ' . dol_print_date(dol_now(), 'dayhour', 'tzuser'), 0, 1); + + $pdf->SetXY($posX, $posy + 5); + $pdf->SetFont('helvetica', '', 10); + $pdf->Cell(0, 6, $langs->transnoentities('FormationSignature'), 0, 1); + $pdf->SetX($posX); + $pdf->MultiCell($posmiddle - $this->marge_gauche - 5, 6, $signatory->firstname . ' ' . $signatory->lastname . ' ' . $userTmp->job . ', ' . $outputlangs->trans('The') . ' ' . dol_print_date($signatory->signature_date), 0, 'L', 0); + if (!empty($signatory->signature)) { + $img = base64_decode(explode(',', $signatory->signature)[1]); + $pdf->Image('@' . $img, $posX, $pdf->GetY(), 60, 8, 'PNG'); + $pdf->SetX($posX); + $pdf->Cell(60, 8, '', 1, 1); + } else { + $pdf->Cell(60, 8, 'N/A', 1, 1, 'C'); + } + + $pdf->SetFont('helvetica', 'B', 7); + $pdf->Ln(10); + $pdf->Cell(0, 6, $langs->transnoentities('FirstRealisationCertificateFooter'), 0, 1); + $pdf->Cell(0, 6, $langs->transnoentities('SecondRealisationCertificateFooter'), 0, 1); + } + + public function write_file($objectDocument, Translate $outputLangs, string $srcTemplatePath, int $hideDetails = 0, int $hideDesc = 0, int $hideRef = 0, array $moreParam): int + { + global $conf, $langs, $mysoc, $user; + + require_once DOL_DOCUMENT_ROOT . '/includes/tecnickcom/tcpdf/tcpdf.php'; + + $pdf = new TCPDF(); + $object = $moreParam['object']; + + $contract = new Contrat($this->db); + $contract->fetch($object->fk_contrat); + $contract->fetch_optionals(); + + $userTmp = new User($this->db); + $signatory = new SaturneSignature($this->db, 'dolimeet'); + $signatory = $signatory->fetchSignatory('UserSignature', $conf->global->DOLIMEET_SESSION_TRAINER_RESPONSIBLE, 'user'); + $signatory = array_shift($signatory); + $userTmp->fetch($signatory->element_id); + + $trainingSessionDict = saturne_fetch_dictionary('c_trainingsession_type'); + + // Certificate variables + $beneficiaryName = $moreParam['attendant']->firstname . ' ' . $moreParam['attendant']->lastname; + $companyName = $mysoc->name; + $contractLabel = $contract->array_options['options_label']; + $trainingStart = dol_print_date($object->date_start, 'day', 'tzuser'); + $trainingEnd = dol_print_date($object->date_end, 'day', 'tzuser'); + $totalHours = convertSecondToTime($object->duration, 'allhourmin'); + $actionName = $langs->trans($trainingSessionDict[$contract->array_options['options_trainingsession_type']]->label); + $issuerName = $userTmp->firstname . ' ' . $userTmp->lastname; + $logoPath = DOL_DOCUMENT_ROOT . '/custom/dolimeet/img/ministere_du_travail.png'; + + if ($moreParam['attendant']->element_type == 'user') { + $attendantCompany = $companyName; + } else { + $contact = new Contact($this->db); + $thirdparty = new Societe($this->db); + $contact->fetch($moreParam['attendant']->element_id); + $thirdparty->fetch($contact->fk_soc); + $attendantCompany = $thirdparty->name; + } + + // PDF view page + $pdf->AddPage(); + $pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite); + + if (file_exists($logoPath)) { + $pdf->Image($logoPath, 10, 10, 40); + } + $pdf->Ln(30); + + $pdf->SetFont('helvetica', 'B', 16); + $pdf->SetTextColor(0, 51, 153); + $pdf->Cell(0, 10, strtoupper($langs->transnoentities('RealisationCertificate')), 0, 1, 'C'); + $pdf->Ln(10); + + $pdf->SetTextColor(0, 0, 0); + $pdf->SetFont('helvetica', '', 11); + + $pdf->Write(6, $langs->transnoentities('IntroductionRealisationCertificate') . ' '); + $pdf->SetTextColor(0, 51, 153); + $pdf->Write(6, $langs->transnoentities('FirstnameLastname') . ' '); + $pdf->SetTextColor(0, 0, 0); + $pdf->Write(6, $langs->transnoentities('LegalRepresentativePresentation', $issuerName) . ' '); + $pdf->SetTextColor(0, 51, 153); + $pdf->Write(6, $langs->transnoentities('FormationRepresentativeExplaination')); + $pdf->SetTextColor(0, 0, 0); + $pdf->Write(6, $langs->transnoentities('AttestsThat', $companyName) . ' '); + $pdf->Ln(8); + + $pdf->Write(6, $langs->transnoentities('CivilityMMEShort') . '/' . $langs->transnoentities('CivilityMRShort') . ' '); + $pdf->SetTextColor(0, 51, 153); + $pdf->Write(6, $langs->transnoentities('BeneficiaryNameExplaination') . ' '); + $pdf->SetTextColor(0, 0, 0); + $pdf->Write(6, $langs->transnoentities('BeneficiaryName', $beneficiaryName) . ' '); + $pdf->SetTextColor(0, 51, 153); + $pdf->Write(6, $langs->transnoentities('AttendantCompanyExplaination') . ' '); + $pdf->SetTextColor(0, 0, 0); + $pdf->Write(6, $langs->transnoentities('AttendantCompany', $attendantCompany) . ' '); + $pdf->SetTextColor(0, 51, 153); + $pdf->Write(6, $langs->transnoentities('Labelled', $contractLabel)); + $pdf->SetTextColor(0, 0, 0); + $pdf->Ln(10); + + $pdf->SetFont('helvetica', 'B', 11); + $pdf->SetTextColor(0, 51, 153); + $pdf->Write(6, $langs->transnoentities('NatureActionType')); + $pdf->Ln(8); + + $pdf->SetTextColor(0, 0, 0); + $pdf->SetFont('helvetica', '', 11); + $pdf->Cell(0, 5, $actionName, 0, 1); + + $pdf->Ln(6); + + $pdf->Write(6, $langs->transnoentities('LastFrom') . ' '); + $pdf->SetTextColor(0, 51, 153); + $pdf->Write(6, $langs->transnoentities('FormationDateRange') . ' '); + $pdf->SetTextColor(0, 0, 0); + $pdf->Write(6, $langs->transnoentities('TrainingStart', $trainingStart) . ' ' . $langs->transnoentities('TrainingEnd', $trainingEnd) . ' ' . $langs->transnoentities('LastHours', $totalHours)); + $pdf->SetTextColor(0, 51, 153); + $pdf->Ln(5); + $pdf->Write(6, $langs->transnoentities('FormationRealizedHours')); + $pdf->SetTextColor(0, 0, 0); + $pdf->Ln(6); + $pdf->Write(6, $langs->transnoentities('FormationLegalText')); + $pdf->Ln(10); + + + // SIGNATURE + $tab_top = $pdf->GetY(); + $heightforinfotot = 50; + $heightforfreetext = getDolGlobalInt('MAIN_PDF_FREETEXT_HEIGHT', 5); + $heightforfooter = $this->marge_basse + 8; + $this->tabSignature($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforfooter, $langs, $signatory, $userTmp); + + $diroutput = $conf->dolimeet->multidir_output[$object->entity] ?? ''; + if (empty($diroutput)) { + $this->error = "Configuration manquante: conf->digiquali->dir_output"; + return -1; + } + $dir = $diroutput . "/completioncertificatedocument/" . $object->ref; + if (!file_exists($dir)) { + if (dol_mkdir($dir) < 0) { + $this->error = "Impossible de créer le répertoire: $dir"; + return -1; + } + } + + $file_name = dol_sanitizeFileName(dol_print_date(dol_now(), "dayxcard") . "_" . $contract->ref . "-" . rand(1000, 4000) . '_' . $beneficiaryName . "_certificat-realisation") . ".pdf"; + $file = $dir . '/' . $file_name; + $objectDocument->setValueFrom("last_main_doc", $file_name, '', null, '', '', $user); + + try { + $pdf->Output($file, 'F'); + } catch (Exception $exception) { + $this->error = "Erreur lors de la création du PDF : " . $exception->getMessage(); + return -1; + } + if (!file_exists($file)) { + $this->error = "PDF non généré (fichier introuvable après Output) : $file"; + return -1; + } + + if (is_object($objectDocument) && method_exists($objectDocument, "setValueFrom")) { + $res = $objectDocument->setValueFrom("last_main_doc", $file_name, '', null, '', '', $user, '', ''); + if ($res <= 0 && !empty($objectDocument->error)) { + $this->error = $objectDocument->error; + return -1; + } + } + + if (!empty($conf->global->MAIN_UMASK)) { + @chmod($file, octdec($conf->global->MAIN_UMASK)); + } + $this->result = ['fullpath' => $file]; + return 1; + } +} diff --git a/core/modules/modDoliMeet.class.php b/core/modules/modDoliMeet.class.php index 19cc3b9..f71e28f 100644 --- a/core/modules/modDoliMeet.class.php +++ b/core/modules/modDoliMeet.class.php @@ -535,10 +535,12 @@ public function init($options = ''): int delDocumentModel('completioncertificatedocument_odt', 'trainingsessiondocument'); delDocumentModel('completioncertificatedocument_odt', 'completioncertificatedocument'); delDocumentModel('attendancesheetdocument', 'trainingsessiondocument'); + delDocumentModel('completioncertificatedocument', 'completioncertificatedocument'); addDocumentModel('attendancesheetdocument_odt', 'trainingsessiondocument', 'ODT templates', 'DOLIMEET_ATTENDANCESHEETDOCUMENT_ADDON_ODT_PATH'); addDocumentModel('completioncertificatedocument_odt', 'completioncertificatedocument', 'ODT templates', 'DOLIMEET_COMPLETIONCERTIFICATEDOCUMENT_ADDON_ODT_PATH'); addDocumentModel('attendancesheetdocument', 'trainingsessiondocument', $langs->transnoentities('AttendanceSheetDocumentPDFDescription')); + addDocumentModel('completioncertificatedocument', 'completioncertificatedocument', $langs->transnoentities('CompletionCertificateDocumentPDF')); // Load Saturne libraries require_once __DIR__ . '/../../../saturne/class/saturnemail.class.php'; diff --git a/img/ministere_du_travail.png b/img/ministere_du_travail.png new file mode 100644 index 0000000..031afa8 Binary files /dev/null and b/img/ministere_du_travail.png differ diff --git a/langs/fr_FR/dolimeet.lang b/langs/fr_FR/dolimeet.lang index cc3771a..ccbf2d5 100644 --- a/langs/fr_FR/dolimeet.lang +++ b/langs/fr_FR/dolimeet.lang @@ -198,6 +198,7 @@ AttendanceSheetDocumentPDFDescription = Feuille de présence en PDF DisplayAttendanceAbsentInSignature = Affiche la présence absent dans le champ signature de la feuille de présence DisplayAttendanceAbsentInSignatureDescription = Affiche la présence absent si la personne est absente et qu'elle n'a pas signé CompletionCertificateDocument = Certificat de réalisation +CompletionCertificateDocumentPDF = Certificat de réalisation en PDF CompletionCertificateDocuments = certificats de réalisation completioncertificatedocument = certificat de realisation completioncertificatedocument.odt = Certificat de réalisation @@ -327,3 +328,33 @@ TradFoundSessionTrainer = Nombre de formateur(s) inscrits pour cette s TradFoundTrainee = Nombre de stagiaire(s) inscrits pour cette session de formation TradFoundBilling = Le commanditaire correspond au rôle "Contact client facturation contrat" présent dans Dolibarr TradFoundCustomer = Le client correspond au rôle "Contact client suivi contrat" présent dans Dolibarr + +# +# PDF +# + +RealisationCertificate = certificat de realisation +MadeAt = Fait à +FormationSignature = Cachet et signature du responsable du dispensateur de formation +FirstRealisationCertificateFooter = 1 Lorsque l’action est mise en oeuvre dans le cadre d’un projet de transition professionnelle, le certificat de réalisation doit être transmis mensuellement. +SecondRealisationCertificateFooter = 2 Dans le cadre des formations à distance prendre en compte la réalisation des activités pédagogiques et le temps estimé pour les réaliser. +IntroductionRealisationCertificate = Je soussigné(e) +FirstnameLastname = (prénom et nom) +LegalRepresentativePresentation = %s représentant légal du dispensateur de l’action concourant au développement des compétences +FormationRepresentativeExplaination = (raison sociale du dispensateur de formation ou de l’employeur en cas de formation interne), +AttestsThat = %s, atteste que : +BeneficiaryNameExplaination = (nom et prénom du bénéficiaire) +BeneficiaryName = %s salarié(e) de l’entreprise +AttendantCompanyExplaination = (raison sociale) +AttendantCompany = %s a suivi l’action +Labelled = (intitulé) %s +NatureActionType = Nature de l’action concourant au développement des compétences : +LastFrom = qui s'est déroulée du +FormationDateRange = (dates) +FormationDate = %s au %s pour une durée de %s heure(s) +TrainingStart = %s +TrainingEnd = au %s +LastHours = pour une durée de %s heure(s) +CivilityMRShort = Mr. +FormationRealizedHours = (nombre d’heures réalisées ou, s’agissant d’une formation par apprentissage, nombre de mois réalisés) +FormationLegalText = Sans préjudice des délais imposés par les règles fiscales, comptables ou commerciales, je m’engage à conserver l’ensemble des pièces justificatives qui ont permis d’établir le présent certificat pendant une durée de 3 ans à compter de la fin de l’année du dernier paiement. En cas de cofinancement des fonds européens la durée de conservation est étendue conformément aux obligations conventionnelles spécifiques.