dolibarr 24.0.0-beta
pdf_beluga.modules.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2010-2012 Regis Houssin <regis.houssin@inodbox.com>
3 * Copyright (C) 2015-2018 Charlene Benke <charlie@patas-monkey.com>
4 * Copyright (C) 2018 Laurent Destailleur <eldy@users.sourceforge.net>
5 * Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
6 * Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
7 * Copyright (C) 2024 Nick Fragoulis
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 * or see https://www.gnu.org/
22 */
23
30require_once DOL_DOCUMENT_ROOT.'/core/modules/project/modules_project.php';
31require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
32require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
33require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
34require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
35require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
36require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
37require_once DOL_DOCUMENT_ROOT.'/core/lib/project.lib.php';
38require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
39
40require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
41require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
42require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture-rec.class.php';
43require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
44require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
45require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
46require_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php';
47require_once DOL_DOCUMENT_ROOT.'/fichinter/class/fichinter.class.php';
48require_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php';
49require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php';
50
51
52
58{
62 public $db;
63
67 public $description;
68
72 public $update_main_doc_field;
73
77 public $type;
78
83 public $version = 'dolibarr';
84
89 private $orientation;
90
94 public $posxref;
98 public $posxdate;
102 public $posxsociety;
106 public $posxamountht;
110 public $posxamountttc;
114 public $posxstatut;
115
116
122 public function __construct($db)
123 {
124 global $langs, $mysoc;
125
126 // Translations
127 $langs->loadLangs(array("main", "projects", "companies"));
128
129 $this->db = $db;
130 $this->name = "beluga";
131 $this->description = $langs->trans("DocumentModelBeluga");
132 $this->update_main_doc_field = 1; // Save the name of generated file as the main doc when generating a doc with this template
133
134 // Page size for A4 format
135 $this->type = 'pdf';
136 $formatarray = pdf_getFormat();
137 $this->orientation = 'L';
138 if ($this->orientation == 'L' || $this->orientation == 'Landscape') {
139 $this->page_largeur = $formatarray['height'];
140 $this->page_hauteur = $formatarray['width'];
141 } else {
142 $this->page_largeur = $formatarray['width'];
143 $this->page_hauteur = $formatarray['height'];
144 }
145 $this->format = array($this->page_largeur, $this->page_hauteur);
146 $this->marge_gauche = getDolGlobalInt('MAIN_PDF_MARGIN_LEFT', 10);
147 $this->marge_droite = getDolGlobalInt('MAIN_PDF_MARGIN_RIGHT', 10);
148 $this->marge_haute = getDolGlobalInt('MAIN_PDF_MARGIN_TOP', 10);
149 $this->marge_basse = getDolGlobalInt('MAIN_PDF_MARGIN_BOTTOM', 10);
150 $this->corner_radius = getDolGlobalInt('MAIN_PDF_FRAME_CORNER_RADIUS', 0);
151 $this->option_logo = 1; // Display logo FAC_PDF_LOGO
152 $this->option_tva = 1; // Manage the vat option FACTURE_TVAOPTION
153
154 // Define position of columns
155 if ($this->orientation == 'L' || $this->orientation == 'Landscape') {
156 $this->posxref = $this->marge_gauche + 1;
157 $this->posxdate = $this->marge_gauche + 105;
158 $this->posxsociety = $this->marge_gauche + 126;
159 $this->posxamountht = $this->marge_gauche + 190;
160 $this->posxamountttc = $this->marge_gauche + 215;
161 $this->posxstatut = $this->marge_gauche + 245;
162 } else {
163 $this->posxref = $this->marge_gauche + 1;
164 $this->posxdate = $this->marge_gauche + 25;
165 $this->posxsociety = $this->marge_gauche + 46;
166 $this->posxamountht = $this->marge_gauche + 110;
167 $this->posxamountttc = $this->marge_gauche + 135;
168 $this->posxstatut = $this->marge_gauche + 165;
169 }
170 if ($this->page_largeur < 210) { // To work with US executive format
171 $this->posxref -= 20;
172 $this->posxdate -= 20;
173 $this->posxsociety -= 20;
174 $this->posxamountht -= 20;
175 $this->posxamountttc -= 20;
176 $this->posxstatut -= 20;
177 }
178
179 if ($mysoc === null) {
180 dol_syslog(get_class($this).'::__construct() Global $mysoc should not be null.'. getCallerInfoString(), LOG_ERR);
181 return;
182 }
183
184 // Get source company
185 $this->emetteur = $mysoc;
186 if (!$this->emetteur->country_code) {
187 $this->emetteur->country_code = substr($langs->defaultlang, -2); // By default if not defined
188 }
189 }
190
191
192 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
204 public function write_file($object, $outputlangs, $srctemplatepath = '', $hidedetails = 0, $hidedesc = 0, $hideref = 0)
205 {
206 // phpcs:enable
207 global $conf, $hookmanager, $langs, $user;
208
209 $formproject = new FormProjets($this->db);
210
211 if (!is_object($outputlangs)) {
212 $outputlangs = $langs;
213 }
214 // For backward compatibility with FPDF, force output charset to ISO, because FPDF expect text to be encoded in ISO
215 if (getDolGlobalString('MAIN_USE_FPDF')) {
216 $outputlangs->charset_output = 'ISO-8859-1';
217 }
218
219 // Load traductions files required by page
220 $outputlangs->loadLangs(array("main", "dict", "companies", "projects"));
221
222 if ($conf->project->multidir_output[$object->entity ?? $conf->entity]) {
223 //$nblines = count($object->lines); // This is set later with array of tasks
224
225 $objectref = dol_sanitizeFileName($object->ref);
226 $dir = $conf->project->multidir_output[$object->entity ?? $conf->entity];
227 if (!preg_match('/specimen/i', $objectref)) {
228 $dir .= "/".$objectref;
229 }
230 $file = $dir."/".$objectref.".pdf";
231
232 if (!file_exists($dir)) {
233 if (dol_mkdir($dir) < 0) {
234 $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
235 return 0;
236 }
237 }
238
239 if (file_exists($dir)) {
240 // Add pdfgeneration hook
241 if (!is_object($hookmanager)) {
242 include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
243 $hookmanager = new HookManager($this->db);
244 }
245 $hookmanager->initHooks(array('pdfgeneration'));
246 $parameters = array('file' => $file, 'object' => $object, 'outputlangs' => $outputlangs);
247 global $action;
248 $reshook = $hookmanager->executeHooks('beforePDFCreation', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
249
250 // Create pdf instance
251 $pdf = pdf_getInstance($this->format);
252 $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance
253 $pdf->setAutoPageBreak(true, 0);
254
255 $heightforinfotot = 40; // Height reserved to output the info and total part
256 $heightforfreetext = getDolGlobalInt('MAIN_PDF_FREETEXT_HEIGHT', 5); // Height reserved to output the free text on last page
257 $heightforfooter = $this->marge_basse + 8; // Height reserved to output the footer (value include bottom margin)
258 if (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS')) {
259 $heightforfooter += 6;
260 }
261
262 if (class_exists('TCPDF')) {
263 $pdf->setPrintHeader(false);
264 $pdf->setPrintFooter(false);
265 }
266 $pdf->SetFont(pdf_getPDFFont($outputlangs));
267 // Set path to the background PDF File
268 if (getDolGlobalString('MAIN_ADD_PDF_BACKGROUND')) {
269 $pagecount = $pdf->setSourceFile($conf->mycompany->dir_output.'/' . getDolGlobalString('MAIN_ADD_PDF_BACKGROUND'));
270 $tplidx = $pdf->importPage(1);
271 }
272
273 // Complete object by loading several other information
274 $task = new Task($this->db);
275 $tasksarray = array();
276 $tasksarray = $task->getTasksArray(null, null, $object->id);
277
278 // Special case when used with object = specimen, we may return all lines
279 if (!$object->id > 0) {
280 $tasksarray = array_slice($tasksarray, 0, min(5, count($tasksarray)));
281 }
282
283 $object->lines = $tasksarray;
284 $nblines = count($object->lines);
285
286 $pdf->Open();
287 $pagenb = 0;
288 $pdf->SetDrawColor(128, 128, 128);
289
290 $pdf->SetTitle($outputlangs->convToOutputCharset($object->ref));
291 $pdf->SetSubject($outputlangs->transnoentities("Project"));
292 $pdf->SetCreator("Dolibarr ".DOL_VERSION);
293 $pdf->SetAuthor($outputlangs->convToOutputCharset($user->getAnonymisableFullName($outputlangs)));
294 $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("Project"));
295 if (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) {
296 $pdf->SetCompression(false);
297 }
298
299 // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
300 $pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite); // Left, Top, Right
301
302 // New page
303 $pdf->AddPage($this->orientation);
304 if (!empty($tplidx)) {
305 $pdf->useTemplate($tplidx);
306 }
307 $pagenb++;
308 $this->_pagehead($pdf, $object, 1, $outputlangs);
309 $pdf->SetFont('', '', $default_font_size - 1);
310 $pdf->MultiCell(0, 3, ''); // Set interline to 3
311 $pdf->SetTextColor(0, 0, 0);
312
313 $tab_top = 50;
314 $tab_top_newpage = (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD') ? 42 : 10);
315
316 $tab_height = $this->page_hauteur - $tab_top - $heightforfooter - $heightforfreetext;
317
318 // Show public note
319 $notetoshow = empty($object->note_public) ? '' : $object->note_public;
320 if ($notetoshow) {
321 $substitutionarray = pdf_getSubstitutionArray($outputlangs, null, $object);
322 complete_substitutions_array($substitutionarray, $outputlangs, $object);
323 $notetoshow = make_substitutions($notetoshow, $substitutionarray, $outputlangs);
324 $notetoshow = convertBackOfficeMediasLinksToPublicLinks($notetoshow);
325
326 $tab_top -= 2;
327
328 $pdf->SetFont('', '', $default_font_size - 1);
329 $pdf->writeHTMLCell(190, 3, $this->posxref - 1, $tab_top - 2, dol_htmlentitiesbr($notetoshow), 0, 1);
330 $nexY = $pdf->GetY();
331 $height_note = $nexY - $tab_top;
332
333 // Rect takes a length in 3rd parameter
334 $pdf->SetDrawColor(192, 192, 192);
335 $pdf->RoundedRect($this->marge_gauche, $tab_top - 2, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $height_note + 2, $this->corner_radius, '1234', 'D');
336
337 $tab_height -= $height_note;
338 $tab_top = $nexY + 6;
339 } else {
340 $height_note = 0;
341 }
342
343 $heightoftitleline = 10;
344 $iniY = $tab_top + $heightoftitleline + 1;
345 $curY = $tab_top + $heightoftitleline + 1;
346 $nexY = $tab_top + $heightoftitleline + 1;
347
348 $listofreferent = array(
349 'propal' => array(
350 'name' => "Proposals",
351 'title' => "ListProposalsAssociatedProject",
352 'class' => 'Propal',
353 'table' => 'propal',
354 'datefieldname' => 'datep',
355 'test' => isModEnabled('propal') && $user->hasRight('propal', 'lire'),
356 'lang' => 'propal'),
357 'order' => array(
358 'name' => "CustomersOrders",
359 'title' => "ListOrdersAssociatedProject",
360 'class' => 'Commande',
361 'table' => 'commande',
362 'datefieldname' => 'date_commande',
363 'test' => isModEnabled('order') && $user->hasRight('commande', 'lire'),
364 'lang' => 'orders'),
365 'invoice' => array(
366 'name' => "CustomersInvoices",
367 'title' => "ListInvoicesAssociatedProject",
368 'class' => 'Facture',
369 'margin' => 'add',
370 'table' => 'facture',
371 'datefieldname' => 'datef',
372 'test' => isModEnabled('invoice') && $user->hasRight('facture', 'lire'),
373 'lang' => 'bills'),
374 'invoice_predefined' => array(
375 'name' => "PredefinedInvoices",
376 'title' => "ListPredefinedInvoicesAssociatedProject",
377 'class' => 'FactureRec',
378 'table' => 'facture_rec',
379 'datefieldname' => 'datec',
380 'test' => isModEnabled('invoice') && $user->hasRight('facture', 'lire'),
381 'lang' => 'bills'),
382 'order_supplier' => array(
383 'name' => "SuppliersOrders",
384 'title' => "ListSupplierOrdersAssociatedProject",
385 'class' => 'CommandeFournisseur',
386 'table' => 'commande_fournisseur',
387 'datefieldname' => 'date_commande',
388 'test' => (isModEnabled("fournisseur") && !getDolGlobalString('MAIN_USE_NEW_SUPPLIERMOD') && $user->hasRight('fournisseur', 'commande', 'lire')) || (isModEnabled("supplier_order") && $user->hasRight('supplier_order', 'lire')),
389 'lang' => 'orders'),
390 'invoice_supplier' => array(
391 'name' => "BillsSuppliers",
392 'title' => "ListSupplierInvoicesAssociatedProject",
393 'class' => 'FactureFournisseur',
394 'margin' => 'minus',
395 'table' => 'facture_fourn',
396 'datefieldname' => 'datef',
397 'test' => (isModEnabled("fournisseur") && !getDolGlobalString('MAIN_USE_NEW_SUPPLIERMOD') && $user->hasRight('fournisseur', 'facture', 'lire')) || (isModEnabled("supplier_invoice") && $user->hasRight('supplier_invoice', 'lire')),
398 'lang' => 'bills'),
399 'contract' => array(
400 'name' => "Contracts",
401 'title' => "ListContractAssociatedProject",
402 'class' => 'Contrat',
403 'table' => 'contrat',
404 'datefieldname' => 'date_contrat',
405 'test' => isModEnabled('contract') && $user->hasRight('contrat', 'lire'),
406 'lang' => 'contract'),
407 'intervention' => array(
408 'name' => "Interventions",
409 'title' => "ListFichinterAssociatedProject",
410 'class' => 'Fichinter',
411 'table' => 'fichinter',
412 'datefieldname' => 'date_valid',
413 'disableamount' => 1,
414 'test' => isModEnabled('intervention') && $user->hasRight('ficheinter', 'lire'),
415 'lang' => 'interventions'),
416 'expensereport' => array(
417 'name' => "ExpensesReports",
418 'title' => "ListExpenseReportsAssociatedProject",
419 'class' => 'ExpenseReport',
420 'table' => 'expensereport',
421 'datefieldname' => 'date_debut',
422 'margin' => 'minus',
423 'disableamount' => 0,
424 'test' => isModEnabled('expensereport') && $user->hasRight('expensereport', 'lire'),
425 'lang' => 'trip'),
426 'agenda' => array(
427 'name' => "Agenda",
428 'title' => "ListActionsAssociatedProject",
429 'class' => 'ActionComm',
430 'table' => 'actioncomm',
431 'datefieldname' => 'datep',
432 'disableamount' => 1,
433 'test' => isModEnabled('agenda') && $user->hasRight('agenda', 'allactions', 'read'),
434 'lang' => 'agenda')
435 );
436
437 $hookmanager->initHooks(array('completeListOfReferent'));
438 $hookmanager->executeHooks('completeListOfReferent', ['listofreferent' => $listofreferent], $object, $action);
439 if (!empty($hookmanager->resArray)) {
440 $listofreferent = array_merge($listofreferent, $hookmanager->resArray);
441 }
442
443 $pageposafter = 0;
444
445 foreach ($listofreferent as $key => $value) {
446 $title = $value['title'];
447 $classname = $value['class'];
448 $tablename = $value['table'];
449 $datefieldname = $value['datefieldname'];
450 $qualified = $value['test'];
451 $langstoload = $value['lang'];
452 $projectField = isset($value['project_field']) ? $value['project_field'] : 'fk_projet';
453 $langs->load($langstoload);
454
455 if (!$qualified) {
456 continue;
457 }
458
459 //var_dump("$key, $tablename, $datefieldname, $dates, $datee");
460 $elementarray = $object->get_element_list($key, $tablename, $datefieldname, 0, 0, $projectField);
461
462 $num = is_array($elementarray) ? count($elementarray) : $elementarray;
463 if ($num >= 0) {
464 $nexY = $pdf->GetY() + 5;
465
466 $curY = $nexY;
467 $pdf->SetFont('', '', $default_font_size - 1); // Into loop to work with multipage
468 $pdf->SetTextColor(0, 0, 0);
469
470 $pdf->SetXY($this->posxref, $curY);
471 $pdf->MultiCell($this->posxstatut - $this->posxref, 3, $outputlangs->transnoentities($title), 0, 'L');
472
473 $selectList = $formproject->select_element($tablename, $object->thirdparty->id, '', -2, $projectField);
474 $nexY = $pdf->GetY() + 1;
475 $curY = $nexY;
476 $pdf->SetXY($this->posxref, $curY);
477 $pdf->MultiCell($this->posxdate - $this->posxref, 3, $outputlangs->transnoentities("Ref"), 1, 'L');
478 $pdf->SetXY($this->posxdate, $curY);
479 $pdf->MultiCell($this->posxsociety - $this->posxdate, 3, $outputlangs->transnoentities("Date"), 1, 'C');
480 $pdf->SetXY($this->posxsociety, $curY);
481 $titlethirdparty = $outputlangs->transnoentities("ThirdParty");
482 if ($classname == 'ExpenseReport') {
483 $titlethirdparty = $langs->trans("User");
484 }
485 $pdf->MultiCell($this->posxamountht - $this->posxsociety, 3, $titlethirdparty, 1, 'L');
486 if (empty($value['disableamount'])) {
487 $pdf->SetXY($this->posxamountht, $curY);
488 $pdf->MultiCell($this->posxamountttc - $this->posxamountht, 3, $outputlangs->transnoentities("AmountHTShort"), 1, 'R');
489 $pdf->SetXY($this->posxamountttc, $curY);
490 $pdf->MultiCell($this->posxstatut - $this->posxamountttc, 3, $outputlangs->transnoentities("AmountTTCShort"), 1, 'R');
491 } else {
492 $pdf->SetXY($this->posxamountht, $curY);
493 $pdf->MultiCell($this->posxstatut - $this->posxamountht, 3, "", 1, 'R');
494 }
495 $pdf->SetXY($this->posxstatut, $curY);
496 $pdf->MultiCell($this->page_largeur - $this->marge_droite - $this->posxstatut, 3, $outputlangs->transnoentities("Status"), 1, 'R');
497
498 if (is_array($elementarray) && count($elementarray) > 0) {
499 $nexY = $pdf->GetY();
500
501 $total_ht = 0;
502 $total_ttc = 0;
503 $num = count($elementarray);
504
505 // Loop on each lines
506 for ($i = 0; $i < $num; $i++) {
507 $curY = $nexY;
508 $pdf->SetFont('', '', $default_font_size - 1); // Into loop to work with multipage
509 $pdf->SetTextColor(0, 0, 0);
510
511 $pdf->setTopMargin($tab_top_newpage);
512 $pdf->setPageOrientation($this->orientation, true, $heightforfooter + $heightforfreetext + $heightforinfotot); // The only function to edit the bottom margin of current page to set it.
513 $pageposbefore = $pdf->getPage();
514
515 // Description of line
516 $idofelement = (int) $elementarray[$i];
517 if ($classname == 'ExpenseReport') {
518 // We get id of expense report
519 $expensereportline = new ExpenseReportLine($this->db);
520 $expensereportline->fetch($idofelement);
521 $idofelement = $expensereportline->fk_expensereport;
522 }
523
524 $element = new $classname($this->db);
525 $element->fetch($idofelement);
526 $element->fetch_thirdparty();
527 // print $classname;
528
529 $qualifiedfortotal = true;
530 if ($key == 'invoice') {
531 if ($element->close_code == 'replaced') {
532 $qualifiedfortotal = false; // Replacement invoice
533 }
534 }
535
536 $showpricebeforepagebreak = 1;
537
538 $pdf->startTransaction();
539 // Label
540 $pdf->SetXY($this->posxref, $curY);
541 $pdf->MultiCell($this->posxdate - $this->posxref, 3, (string) $element->ref, 1, 'L');
542 $pageposafter = $pdf->getPage();
543 if ($pageposafter > $pageposbefore) { // There is a pagebreak
544 $pdf->rollbackTransaction(true);
545 $pageposafter = $pageposbefore;
546 //print $pageposafter.'-'.$pageposbefore;exit;
547 $pdf->setPageOrientation($this->orientation, true, $heightforfooter); // The only function to edit the bottom margin of current page to set it.
548 // Label
549 $pdf->SetXY($this->posxref, $curY);
550 $posybefore = $pdf->GetY();
551 $pdf->MultiCell($this->posxdate - $this->posxref, 3, (string) $element->ref, 1, 'L');
552 $pageposafter = $pdf->getPage();
553 $posyafter = $pdf->GetY();
554 if ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforinfotot))) { // There is no space left for total+free text
555 if ($i == ($num - 1)) { // No more lines, and no space left to show total, so we create a new page
556 $pdf->AddPage($this->orientation, '', true);
557 if (!empty($tplidx)) {
558 $pdf->useTemplate($tplidx);
559 }
560 if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
561 $this->_pagehead($pdf, $object, 0, $outputlangs);
562 }
563 $pdf->setPage($pageposafter + 1);
564 }
565 } else {
566 // We found a page break
567
568 // Allows data in the first page if description is long enough to break in multiples pages
569 if (getDolGlobalString('MAIN_PDF_DATA_ON_FIRST_PAGE')) {
570 $showpricebeforepagebreak = 1;
571 } else {
572 $showpricebeforepagebreak = 0;
573 }
574
575 $forcedesconsamepage = 1;
576 if ($forcedesconsamepage) {
577 $pdf->rollbackTransaction(true);
578 $pageposafter = $pageposbefore;
579 $pdf->setPageOrientation($this->orientation, true, $heightforfooter); // The only function to edit the bottom margin of current page to set it.
580
581 $pdf->AddPage($this->orientation, '', true);
582 if (!empty($tplidx)) {
583 $pdf->useTemplate($tplidx);
584 }
585 if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
586 $this->_pagehead($pdf, $object, 0, $outputlangs);
587 }
588 $pdf->setPage($pageposafter + 1);
589 $pdf->SetFont('', '', $default_font_size - 1); // On repositionne la police par default
590 $pdf->MultiCell(0, 3, ''); // Set interline to 3
591 $pdf->SetTextColor(0, 0, 0);
592
593 $pdf->setPageOrientation($this->orientation, true, $heightforfooter); // The only function to edit the bottom margin of current page to set it.
594 $curY = $tab_top_newpage + $heightoftitleline + 1;
595
596 // Label
597 $pdf->SetXY($this->posxref, $curY);
598 $posybefore = $pdf->GetY();
599 $pdf->MultiCell($this->posxdate - $this->posxref, 3, (string) $element->ref, 1, 'L');
600 $pageposafter = $pdf->getPage();
601 $posyafter = $pdf->GetY();
602 }
603 }
604 //var_dump($i.' '.$posybefore.' '.$posyafter.' '.($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforinfotot)).' '.$showpricebeforepagebreak);
605 } else { // No pagebreak
606 $pdf->commitTransaction();
607 }
608 $posYAfterDescription = $pdf->GetY();
609
610 $nexY = $pdf->GetY();
611 $pageposafter = $pdf->getPage();
612 $pdf->setPage($pageposbefore);
613 $pdf->setTopMargin($this->marge_haute);
614 $pdf->setPageOrientation($this->orientation, true, 0); // The only function to edit the bottom margin of current page to set it.
615
616 // We suppose that a too long description is moved completely on next page
617 if ($pageposafter > $pageposbefore && empty($showpricebeforepagebreak)) {
618 //var_dump($pageposbefore.'-'.$pageposafter.'-'.$showpricebeforepagebreak);
619 $pdf->setPage($pageposafter);
620 $curY = $tab_top_newpage + $heightoftitleline + 1;
621 }
622
623 $pdf->SetFont('', '', $default_font_size - 1); // On repositionne la police par default
624
625 // Date
626 if ($tablename == 'commande_fournisseur' || $tablename == 'supplier_order') {
627 $date = $element->date_commande;
628 } else {
629 $date = $element->date;
630 if (empty($date)) {
631 $date = $element->datep;
632 }
633 if (empty($date)) {
634 $date = $element->date_contrat;
635 }
636 if (empty($date)) {
637 $date = $element->datev; // Intervention card
638 }
639 if (empty($date)) {
640 $date = $element->date_debut; // Expense report
641 }
642 }
643
644 $pdf->SetXY($this->posxdate, $curY);
645 $pdf->MultiCell($this->posxsociety - $this->posxdate, 3, dol_print_date($date, 'day'), 1, 'C');
646
647 $pdf->SetXY($this->posxsociety, $curY);
648 if ($classname == 'ExpenseReport') {
649 $fuser = new User($this->db);
650 $fuser->fetch($element->fk_user_author);
651 $pdf->MultiCell($this->posxamountht - $this->posxsociety, 3, $fuser->getFullName($outputlangs), 1, 'L');
652 } else {
653 $pdf->MultiCell($this->posxamountht - $this->posxsociety, 3, (is_object($element->thirdparty) ? $element->thirdparty->name : ''), 1, 'L');
654 }
655
656 // Amount without tax
657 if (empty($value['disableamount'])) {
658 $pdf->SetXY($this->posxamountht, $curY);
659 $pdf->MultiCell($this->posxamountttc - $this->posxamountht, 3, (isset($element->total_ht) ? price($element->total_ht) : ''), 1, 'R');
660 $pdf->SetXY($this->posxamountttc, $curY);
661 $pdf->MultiCell($this->posxstatut - $this->posxamountttc, 3, (isset($element->total_ttc) ? price($element->total_ttc) : ''), 1, 'R');
662 } else {
663 $pdf->SetXY($this->posxamountht, $curY);
664 if ($key == 'agenda') {
665 $textforamount = dol_trunc($element->label, 26);
666 $pdf->MultiCell($this->posxstatut - $this->posxamountht, 3, $textforamount, 1, 'L');
667 } else {
668 $pdf->MultiCell($this->posxstatut - $this->posxamountht, 3, "", 1, 'R');
669 }
670 }
671
672 // Status
673 if ($element instanceof CommonInvoice) {
674 // This applies for Facture and FactureFournisseur
675 $outputstatut = $element->getLibStatut(1, $element->getSommePaiement());
676 } else {
677 $outputstatut = $element->getLibStatut(1);
678 }
679 $pdf->SetXY($this->posxstatut, $curY);
680 $pdf->MultiCell($this->page_largeur - $this->marge_droite - $this->posxstatut, 3, $outputstatut, 1, 'R', false, 1, null, null, true, 0, true);
681
682 if ($qualifiedfortotal) {
683 $total_ht += $element->total_ht;
684 $total_ttc += $element->total_ttc;
685 }
686 $nexY = $pdf->GetY();
687 $curY = $nexY;
688 }
689
690 if (empty($value['disableamount'])) {
691 $curY = $nexY;
692 $pdf->SetXY($this->posxref, $curY);
693 $pdf->MultiCell($this->posxamountttc - $this->posxref, 3, "TOTAL", 1, 'L');
694 $pdf->SetXY($this->posxamountht, $curY);
695 $pdf->MultiCell($this->posxamountttc - $this->posxamountht, 3, (isset($element->total_ht) ? price($total_ht) : ''), 1, 'R');
696 $pdf->SetXY($this->posxamountttc, $curY);
697 $pdf->MultiCell($this->posxstatut - $this->posxamountttc, 3, (isset($element->total_ttc) ? price($total_ttc) : ''), 1, 'R');
698 $pdf->SetXY($this->posxstatut, $curY);
699 $pdf->MultiCell($this->page_largeur - $this->marge_droite - $this->posxstatut, 3, $outputlangs->transnoentities("Nb")." ".$num, 1, 'L');
700 }
701 $nexY = $pdf->GetY() + 5;
702 $curY = $nexY;
703 }
704 }
705
706 $nexY += 2; // Add space between lines
707
708 // Detect if some page were added automatically and output _tableau for past pages
709 while ($pagenb < $pageposafter) {
710 $pdf->setPage($pagenb);
711 $this->_pagefoot($pdf, $object, $outputlangs, 1);
712 $pagenb++;
713 $pdf->setPage($pagenb);
714 $pdf->setPageOrientation($this->orientation, true, 0); // The only function to edit the bottom margin of current page to set it.
715 if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
716 $this->_pagehead($pdf, $object, 0, $outputlangs);
717 }
718 if (!empty($tplidx)) {
719 $pdf->useTemplate($tplidx);
720 }
721 }
722 }
723
724 // Pied de page
725 $this->_pagefoot($pdf, $object, $outputlangs);
726 if (method_exists($pdf, 'AliasNbPages')) {
727 $pdf->AliasNbPages(); // @phan-suppress-current-line PhanUndeclaredMethod
728 }
729
730 $pdf->Close();
731
732 $pdf->Output($file, 'F');
733
734 // Add pdfgeneration hook
735 $hookmanager->initHooks(array('pdfgeneration'));
736 $parameters = array('file' => $file, 'object' => $object, 'outputlangs' => $outputlangs);
737 global $action;
738 $reshook = $hookmanager->executeHooks('afterPDFCreation', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
739 $this->warnings = $hookmanager->warnings;
740 if ($reshook < 0) {
741 $this->error = $hookmanager->error;
742 $this->errors = $hookmanager->errors;
743 dolChmod($file);
744 return -1;
745 }
746
747 dolChmod($file);
748
749 $this->result = array('fullpath' => $file);
750
751 return 1; // No error
752 } else {
753 $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
754 return 0;
755 }
756 } else {
757 $this->error = $langs->transnoentities("ErrorConstantNotDefined", "PROJECT_OUTPUTDIR");
758 return 0;
759 }
760 }
761
762 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
775 protected function _tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop = 0, $hidebottom = 0)
776 {
777 $heightoftitleline = 10;
778
779 $default_font_size = pdf_getPDFFontSize($outputlangs);
780
781 $pdf->SetDrawColor(128, 128, 128);
782
783 // Draw rect of all tab (title + lines). Rect takes a length in 3rd parameter
784 $pdf->RoundedRect($this->marge_gauche, $tab_top, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $tab_height, $this->corner_radius, '1234', 'D');
785
786 // line prend une position y en 3eme param
787 $pdf->line($this->marge_gauche, $tab_top + $heightoftitleline, $this->page_largeur - $this->marge_droite, $tab_top + $heightoftitleline);
788
789 $pdf->SetTextColor(0, 0, 0);
790 $pdf->SetFont('', '', $default_font_size);
791 }
792
793 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
803 protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs)
804 {
805 global $langs, $conf, $mysoc;
806
807 $default_font_size = pdf_getPDFFontSize($outputlangs);
808
809 pdf_pagehead($pdf, $outputlangs, $this->page_hauteur);
810
811 $pdf->SetTextColor(0, 0, 60);
812 $pdf->SetFont('', 'B', $default_font_size + 3);
813
814 $posx = $this->page_largeur - $this->marge_droite - 100;
815 $posy = $this->marge_haute;
816
817 $pdf->SetXY($this->marge_gauche, $posy);
818
819 // Logo
820 $logo = $conf->mycompany->dir_output.'/logos/'.$mysoc->logo;
821 if ($mysoc->logo) {
822 if (is_readable($logo)) {
823 $height = pdf_getHeightForLogo($logo);
824 $pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto)
825 } else {
826 $pdf->SetTextColor(200, 0, 0);
827 $pdf->SetFont('', 'B', $default_font_size - 2);
828 $pdf->MultiCell(100, 3, $langs->transnoentities("ErrorLogoFileNotFound", $logo), 0, 'L');
829 $pdf->MultiCell(100, 3, $langs->transnoentities("ErrorGoToModuleSetup"), 0, 'L');
830 }
831 } else {
832 $pdf->MultiCell(100, 4, $outputlangs->transnoentities($this->emetteur->name), 0, 'L');
833 }
834
835 $pdf->SetFont('', 'B', $default_font_size + 3);
836 $pdf->SetXY($posx, $posy);
837 $pdf->SetTextColor(0, 0, 60);
838 $pdf->MultiCell(100, 4, $outputlangs->transnoentities("Project")." ".$outputlangs->convToOutputCharset($object->ref), '', 'R');
839 $pdf->SetFont('', '', $default_font_size + 2);
840
841 $posy += 6;
842 $pdf->SetXY($posx, $posy);
843 $pdf->SetTextColor(0, 0, 60);
844 $pdf->MultiCell(100, 4, $outputlangs->transnoentities("DateStart")." : ".dol_print_date($object->date_start, 'day', false, $outputlangs, true), '', 'R');
845
846 $posy += 6;
847 $pdf->SetXY($posx, $posy);
848 $pdf->MultiCell(100, 4, $outputlangs->transnoentities("DateEnd")." : ".dol_print_date($object->date_end, 'day', false, $outputlangs, true), '', 'R');
849
850 if (is_object($object->thirdparty)) {
851 $posy += 6;
852 $pdf->SetXY($posx, $posy);
853 $pdf->MultiCell(100, 4, $outputlangs->transnoentities("ThirdParty")." : ".$object->thirdparty->getFullName($outputlangs), '', 'R');
854 }
855
856 $pdf->SetTextColor(0, 0, 60);
857
858 return 0;
859 }
860
861 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
871 protected function _pagefoot(&$pdf, $object, $outputlangs, $hidefreetext = 0)
872 {
873 $showdetails = getDolGlobalInt('MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS', 0);
874 return pdf_pagefoot($pdf, $outputlangs, 'PROJECT_FREE_TEXT', $this->emetteur, $this->marge_basse, $this->marge_gauche, $this->page_hauteur, $object, $showdetails, $hidefreetext);
875 }
876}
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
Superclass for invoice classes.
Class of expense report details lines.
Class to manage building of HTML components.
Class to manage hooks.
Parent class for projects models.
Class to manage tasks.
Class to manage Dolibarr users.
Class to manage generation of project document Beluga.
__construct($db)
Constructor.
write_file($object, $outputlangs, $srctemplatepath='', $hidedetails=0, $hidedesc=0, $hideref=0)
Function generating the project on disk.
_pagehead(&$pdf, $object, $showaddress, $outputlangs)
Show top header of page.
_tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop=0, $hidebottom=0)
Show table for lines.
_pagefoot(&$pdf, $object, $outputlangs, $hidefreetext=0)
Show footer of page.
global $mysoc
print $script_file $mode $langs defaultlang(is_numeric($duration_value) ? " delay=". $duration_value :"").(is_numeric($duration_value2) ? " after cd cd cd description as description
Only used if Module[ID]Desc translation string is not found.
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!function_exists( 'dolEscapeXML')) convertBackOfficeMediasLinksToPublicLinks($notetoshow)
Convert links to local wrapper to medias files into a string into a public external URL readable on i...
getCallerInfoString()
Get caller info as a string that can be appended to a log message.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
dolChmod($filepath, $newmask='')
Change mod of a file.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
complete_substitutions_array(&$substitutionarray, $outputlangs, $object=null, $parameters=null, $callfunc="completesubstitutionarray")
Complete the $substitutionarray with more entries coming from external module that had set the "subst...
make_substitutions($text, $substitutionarray, $outputlangs=null, $converttextinhtmlifnecessary=0)
Make substitution into a text string, replacing keys with vals from $substitutionarray (oldval=>newva...
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
dol_htmlentitiesbr($stringtoencode, $nl2brmode=0, $pagecodefrom='UTF-8', $removelasteolbr=1)
This function is called to encode a string into a HTML string but differs from htmlentities because a...
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
pdf_getFormat($outputlangs=null, $mode='setup')
Return array with format properties of default PDF format.
Definition pdf.lib.php:87
pdf_getPDFFontSize($outputlangs)
Return font size to use for PDF generation.
Definition pdf.lib.php:294
pdf_getHeightForLogo($logo, $url=false)
Return height to use for Logo onto PDF.
Definition pdf.lib.php:317
pdf_pagehead($pdf, $outputlangs, $page_height)
Show header of page for PDF generation.
Definition pdf.lib.php:747
pdf_pagefoot($pdf, $outputlangs, $paramfreetext, $fromcompany, $marge_basse, $marge_gauche, $page_hauteur, $object, $showdetails=0, $hidefreetext=0, $page_largeur=0, $watermark='')
Show footer of page for PDF generation.
Definition pdf.lib.php:1421
pdf_getPDFFont($outputlangs)
Return font name to use for PDF generation.
Definition pdf.lib.php:273
pdf_getSubstitutionArray($outputlangs, $exclude=null, $object=null, $onlykey=0, $include=null)
Return array of possible substitutions for PDF content (without external module substitutions).
Definition pdf.lib.php:1135
pdf_getInstance($format='', $metric='mm', $pagetype='P')
Return a PDF instance object.
Definition pdf.lib.php:129
if(preg_match('/(crypted|dolcrypt):/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
'integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]',...
Definition repair.php:130
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:133