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