Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion class/actions_dolimeet.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -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')) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

la tu peux normalement faire un meilleur preg_match

require_once __DIR__ . '/dolimeetdocuments/completioncertificatedocument.class.php';

$document = new CompletioncertificateDocument($this->db);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,282 @@
<?php
/* Copyright (C) 2025 EVARISK <[email protected]>
*
* 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 <https://www.gnu.org/licenses/>.
* 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();
Comment on lines +131 to +135
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Problème de logique l'object viens de contrat donc ici t'as un contrat


$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;
}
}
2 changes: 2 additions & 0 deletions core/modules/modDoliMeet.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
Binary file added img/ministere_du_travail.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 31 additions & 0 deletions langs/fr_FR/dolimeet.lang
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.