dolibarr  17.0.4
pdf_cyan.modules.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2004-2014 Laurent Destailleur <eldy@users.sourceforge.net>
3  * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
4  * Copyright (C) 2008 Raphael Bertrand <raphael.bertrand@resultic.fr>
5  * Copyright (C) 2010-2015 Juanjo Menent <jmenent@2byte.es>
6  * Copyright (C) 2012 Christophe Battarel <christophe.battarel@altairis.fr>
7  * Copyright (C) 2012 Cedric Salvador <csalvador@gpcsolutions.fr>
8  * Copyright (C) 2015 Marcos García <marcosgdf@gmail.com>
9  * Copyright (C) 2017 Ferran Marcet <fmarcet@2byte.es>
10  * Copyright (C) 2018 Frédéric France <frederic.france@netlogic.fr>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 3 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program. If not, see <https://www.gnu.org/licenses/>.
24  * or see https://www.gnu.org/
25  */
26 
32 require_once DOL_DOCUMENT_ROOT.'/core/modules/propale/modules_propale.php';
33 require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
34 require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
35 require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
36 require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
37 
38 
43 {
47  public $db;
48 
52  public $name;
53 
57  public $description;
58 
62  public $update_main_doc_field;
63 
67  public $type;
68 
73  public $phpmin = array(7, 0);
74 
79  public $version = 'dolibarr';
80 
84  public $page_largeur;
85 
89  public $page_hauteur;
90 
94  public $format;
95 
99  public $marge_gauche;
100 
104  public $marge_droite;
105 
109  public $marge_haute;
110 
114  public $marge_basse;
115 
120  public $emetteur;
121 
125  public $cols;
126 
127 
133  public function __construct($db)
134  {
135  global $conf, $langs, $mysoc;
136 
137  // Translations
138  $langs->loadLangs(array("main", "bills"));
139 
140  $this->db = $db;
141  $this->name = "cyan";
142  $this->description = $langs->trans('DocModelCyanDescription');
143  $this->update_main_doc_field = 1; // Save the name of generated file as the main doc when generating a doc with this template
144 
145  // Dimension page
146  $this->type = 'pdf';
147  $formatarray = pdf_getFormat();
148  $this->page_largeur = $formatarray['width'];
149  $this->page_hauteur = $formatarray['height'];
150  $this->format = array($this->page_largeur, $this->page_hauteur);
151  $this->marge_gauche = getDolGlobalInt('MAIN_PDF_MARGIN_LEFT', 10);
152  $this->marge_droite = getDolGlobalInt('MAIN_PDF_MARGIN_RIGHT', 10);
153  $this->marge_haute = getDolGlobalInt('MAIN_PDF_MARGIN_TOP', 10);
154  $this->marge_basse = getDolGlobalInt('MAIN_PDF_MARGIN_BOTTOM', 10);
155 
156  $this->option_logo = 1; // Display logo
157  $this->option_tva = 1; // Manage the vat option FACTURE_TVAOPTION
158  $this->option_modereg = 1; // Display payment mode
159  $this->option_condreg = 1; // Display payment terms
160  $this->option_multilang = 1; // Available in several languages
161  $this->option_escompte = 0; // Displays if there has been a discount
162  $this->option_credit_note = 0; // Support credit notes
163  $this->option_freetext = 1; // Support add of a personalised text
164  $this->option_draft_watermark = 1; // Support add of a watermark on drafts
165  $this->watermark = '';
166 
167  // Get source company
168  $this->emetteur = $mysoc;
169  if (empty($this->emetteur->country_code)) {
170  $this->emetteur->country_code = substr($langs->defaultlang, -2); // By default, if was not defined
171  }
172 
173  // Define position of columns
174  $this->posxdesc = $this->marge_gauche + 1; // used for notes ans other stuff
175 
176 
177  $this->tabTitleHeight = 5; // default height
178 
179  // Use new system for position of columns, view $this->defineColumnField()
180 
181  $this->tva = array();
182  $this->tva_array = array();
183  $this->localtax1 = array();
184  $this->localtax2 = array();
185  $this->atleastoneratenotnull = 0;
186  $this->atleastonediscount = 0;
187  }
188 
189  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
201  public function write_file($object, $outputlangs, $srctemplatepath = '', $hidedetails = 0, $hidedesc = 0, $hideref = 0)
202  {
203  // phpcs:enable
204  global $user, $langs, $conf, $mysoc, $db, $hookmanager, $nblines;
205 
206  dol_syslog("write_file outputlangs->defaultlang=".(is_object($outputlangs) ? $outputlangs->defaultlang : 'null'));
207 
208  if (!is_object($outputlangs)) {
209  $outputlangs = $langs;
210  }
211  // For backward compatibility with FPDF, force output charset to ISO, because FPDF expect text to be encoded in ISO
212  if (!empty($conf->global->MAIN_USE_FPDF)) {
213  $outputlangs->charset_output = 'ISO-8859-1';
214  }
215 
216  // Load translation files required by page
217  $outputlangs->loadLangs(array("main", "dict", "companies", "bills", "products", "propal"));
218 
219  // Show Draft Watermark
220  if ($object->statut == $object::STATUS_DRAFT && getDolGlobalString('PROPALE_DRAFT_WATERMARK')) {
221  $this->watermark = getDolGlobalString('PROPALE_DRAFT_WATERMARK');
222  }
223 
224  global $outputlangsbis;
225  $outputlangsbis = null;
226  if (!empty($conf->global->PDF_USE_ALSO_LANGUAGE_CODE) && $outputlangs->defaultlang != $conf->global->PDF_USE_ALSO_LANGUAGE_CODE) {
227  $outputlangsbis = new Translate('', $conf);
228  $outputlangsbis->setDefaultLang($conf->global->PDF_USE_ALSO_LANGUAGE_CODE);
229  $outputlangsbis->loadLangs(array("main", "dict", "companies", "bills", "products", "propal"));
230  }
231 
232  $nblines = count($object->lines);
233 
234  $hidetop = 0;
235  if (!empty($conf->global->MAIN_PDF_DISABLE_COL_HEAD_TITLE)) {
236  $hidetop = $conf->global->MAIN_PDF_DISABLE_COL_HEAD_TITLE;
237  }
238 
239  // Loop on each lines to detect if there is at least one image to show
240  $realpatharray = array();
241  $this->atleastonephoto = false;
242  if (!empty($conf->global->MAIN_GENERATE_PROPOSALS_WITH_PICTURE)) {
243  $objphoto = new Product($this->db);
244 
245  for ($i = 0; $i < $nblines; $i++) {
246  if (empty($object->lines[$i]->fk_product)) {
247  continue;
248  }
249 
250  $objphoto->fetch($object->lines[$i]->fk_product);
251  //var_dump($objphoto->ref);exit;
252  if (getDolGlobalInt('PRODUCT_USE_OLD_PATH_FOR_PHOTO')) {
253  $pdir[0] = get_exdir($objphoto->id, 2, 0, 0, $objphoto, 'product').$objphoto->id."/photos/";
254  $pdir[1] = get_exdir(0, 0, 0, 0, $objphoto, 'product').dol_sanitizeFileName($objphoto->ref).'/';
255  } else {
256  $pdir[0] = get_exdir(0, 0, 0, 0, $objphoto, 'product'); // default
257  $pdir[1] = get_exdir($objphoto->id, 2, 0, 0, $objphoto, 'product').$objphoto->id."/photos/"; // alternative
258  }
259 
260  $arephoto = false;
261  foreach ($pdir as $midir) {
262  if (!$arephoto) {
263  if ($conf->entity != $objphoto->entity) {
264  $dir = $conf->product->multidir_output[$objphoto->entity].'/'.$midir; //Check repertories of current entities
265  } else {
266  $dir = $conf->product->dir_output.'/'.$midir; //Check repertory of the current product
267  }
268 
269  foreach ($objphoto->liste_photos($dir, 1) as $key => $obj) {
270  if (!getDolGlobalInt('CAT_HIGH_QUALITY_IMAGES')) { // If CAT_HIGH_QUALITY_IMAGES not defined, we use thumb if defined and then original photo
271  if ($obj['photo_vignette']) {
272  $filename = $obj['photo_vignette'];
273  } else {
274  $filename = $obj['photo'];
275  }
276  } else {
277  $filename = $obj['photo'];
278  }
279 
280  $realpath = $dir.$filename;
281  $arephoto = true;
282  $this->atleastonephoto = true;
283  }
284  }
285  }
286 
287  if ($realpath && $arephoto) {
288  $realpatharray[$i] = $realpath;
289  }
290  }
291  }
292 
293  if (count($realpatharray) == 0) {
294  $this->posxpicture = $this->posxtva;
295  }
296 
297  if ($conf->propal->multidir_output[$conf->entity]) {
298  $object->fetch_thirdparty();
299 
300  $deja_regle = 0;
301 
302  // Definition of $dir and $file
303  if ($object->specimen) {
304  $dir = $conf->propal->multidir_output[$conf->entity];
305  $file = $dir."/SPECIMEN.pdf";
306  } else {
307  $objectref = dol_sanitizeFileName($object->ref);
308  $dir = $conf->propal->multidir_output[$object->entity]."/".$objectref;
309  $file = $dir."/".$objectref.".pdf";
310  }
311 
312  if (!file_exists($dir)) {
313  if (dol_mkdir($dir) < 0) {
314  $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
315  return 0;
316  }
317  }
318 
319  if (file_exists($dir)) {
320  // Add pdfgeneration hook
321  if (!is_object($hookmanager)) {
322  include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
323  $hookmanager = new HookManager($this->db);
324  }
325  $hookmanager->initHooks(array('pdfgeneration'));
326  $parameters = array('file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs);
327  global $action;
328  $reshook = $hookmanager->executeHooks('beforePDFCreation', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
329 
330  // Set nblines with the new content of lines after hook
331  $nblines = count($object->lines);
332  //$nbpayments = count($object->getListOfPayments());
333 
334  // Create pdf instance
335  $pdf = pdf_getInstance($this->format);
336  $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance
337  $pdf->SetAutoPageBreak(1, 0);
338 
339  if (class_exists('TCPDF')) {
340  $pdf->setPrintHeader(false);
341  $pdf->setPrintFooter(false);
342  }
343  $pdf->SetFont(pdf_getPDFFont($outputlangs));
344  // Set path to the background PDF File
345  if (!empty($conf->global->MAIN_ADD_PDF_BACKGROUND)) {
346  $logodir = $conf->mycompany->dir_output;
347  if (!empty($conf->mycompany->multidir_output[$object->entity])) {
348  $logodir = $conf->mycompany->multidir_output[$object->entity];
349  }
350  $pagecount = $pdf->setSourceFile($logodir.'/'.$conf->global->MAIN_ADD_PDF_BACKGROUND);
351  $tplidx = $pdf->importPage(1);
352  }
353 
354  $pdf->Open();
355  $pagenb = 0;
356  $pdf->SetDrawColor(128, 128, 128);
357 
358  $pdf->SetTitle($outputlangs->convToOutputCharset($object->ref));
359  $pdf->SetSubject($outputlangs->transnoentities("PdfCommercialProposalTitle"));
360  $pdf->SetCreator("Dolibarr ".DOL_VERSION);
361  $pdf->SetAuthor($outputlangs->convToOutputCharset($user->getFullName($outputlangs)));
362  $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("PdfCommercialProposalTitle")." ".$outputlangs->convToOutputCharset($object->thirdparty->name));
363  if (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) {
364  $pdf->SetCompression(false);
365  }
366 
367  $pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite); // Left, Top, Right
368 
369  // Set $this->atleastonediscount if you have at least one discount
370  for ($i = 0; $i < $nblines; $i++) {
371  if ($object->lines[$i]->remise_percent) {
372  $this->atleastonediscount++;
373  }
374  }
375 
376 
377  // New page
378  $pdf->AddPage();
379  if (!empty($tplidx)) {
380  $pdf->useTemplate($tplidx);
381  }
382  $pagenb++;
383 
384  $heightforinfotot = 40; // Height reserved to output the info and total part
385  $heightforsignature = empty($conf->global->PROPAL_DISABLE_SIGNATURE) ? (pdfGetHeightForHtmlContent($pdf, $outputlangs->transnoentities("ProposalCustomerSignature")) + 10) : 0;
386  $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
387  $heightforfooter = $this->marge_basse + (empty($conf->global->MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS) ? 12 : 22); // Height reserved to output the footer (value include bottom margin)
388  //print $heightforinfotot + $heightforsignature + $heightforfreetext + $heightforfooter;exit;
389 
390  $top_shift = $this->_pagehead($pdf, $object, 1, $outputlangs, $outputlangsbis);
391  $pdf->SetFont('', '', $default_font_size - 1);
392  $pdf->MultiCell(0, 3, ''); // Set interline to 3
393  $pdf->SetTextColor(0, 0, 0);
394 
395 
396  $tab_top = 90 + $top_shift;
397  $tab_top_newpage = (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD') ? 42 + $top_shift : 10);
398 
399 
400  // Incoterm
401  $height_incoterms = 0;
402  if (isModEnabled('incoterm')) {
403  $desc_incoterms = $object->getIncotermsForPDF();
404  if ($desc_incoterms) {
405  $tab_top -= 2;
406 
407  $pdf->SetFont('', '', $default_font_size - 1);
408  $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top - 1, dol_htmlentitiesbr($desc_incoterms), 0, 1);
409  $nexY = max($pdf->GetY(), $nexY);
410  $height_incoterms = $nexY - $tab_top;
411 
412  // Rect takes a length in 3rd parameter
413  $pdf->SetDrawColor(192, 192, 192);
414  $pdf->Rect($this->marge_gauche, $tab_top - 1, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $height_incoterms + 1);
415 
416  $tab_top = $nexY + 6;
417  $height_incoterms += 4;
418  }
419  }
420 
421  // Displays notes
422  $notetoshow = empty($object->note_public) ? '' : $object->note_public;
423  if (!empty($conf->global->MAIN_ADD_SALE_REP_SIGNATURE_IN_NOTE)) {
424  // Get first sale rep
425  if (is_object($object->thirdparty)) {
426  $salereparray = $object->thirdparty->getSalesRepresentatives($user);
427  $salerepobj = new User($this->db);
428  $salerepobj->fetch($salereparray[0]['id']);
429  if (!empty($salerepobj->signature)) {
430  $notetoshow = dol_concatdesc($notetoshow, $salerepobj->signature);
431  }
432  }
433  }
434 
435  // Extrafields in note
436  $extranote = $this->getExtrafieldsInHtml($object, $outputlangs);
437  if (!empty($extranote)) {
438  $notetoshow = dol_concatdesc($notetoshow, $extranote);
439  }
440 
441  if (!empty($conf->global->MAIN_ADD_CREATOR_IN_NOTE) && $object->user_author_id > 0) {
442  $tmpuser = new User($this->db);
443  $tmpuser->fetch($object->user_author_id);
444 
445  $creator_info = $langs->trans("CaseFollowedBy").' '.$tmpuser->getFullName($langs);
446  if ($tmpuser->email) $creator_info .= ', '.$langs->trans("EMail").': '.$tmpuser->email;
447  if ($tmpuser->office_phone) $creator_info .= ', '.$langs->trans("Phone").': '.$tmpuser->office_phone;
448 
449  $notetoshow = dol_concatdesc($notetoshow, $creator_info);
450  }
451 
452  $tab_height = $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforsignature - $heightforfooter;
453 
454  $pagenb = $pdf->getPage();
455  if ($notetoshow) {
456  $tab_top -= 2;
457 
458  $tab_width = $this->page_largeur - $this->marge_gauche - $this->marge_droite;
459  $pageposbeforenote = $pagenb;
460 
461  $substitutionarray = pdf_getSubstitutionArray($outputlangs, null, $object);
462  complete_substitutions_array($substitutionarray, $outputlangs, $object);
463  $notetoshow = make_substitutions($notetoshow, $substitutionarray, $outputlangs);
464  $notetoshow = convertBackOfficeMediasLinksToPublicLinks($notetoshow);
465 
466  $pdf->startTransaction();
467 
468  $pdf->SetFont('', '', $default_font_size - 1);
469  $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top, dol_htmlentitiesbr($notetoshow), 0, 1);
470  // Description
471  $pageposafternote = $pdf->getPage();
472  $posyafter = $pdf->GetY();
473 
474  if ($pageposafternote > $pageposbeforenote) {
475  $pdf->rollbackTransaction(true);
476 
477  // prepare pages to receive notes
478  while ($pagenb < $pageposafternote) {
479  $pdf->AddPage();
480  $pagenb++;
481  if (!empty($tplidx)) {
482  $pdf->useTemplate($tplidx);
483  }
484  if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
485  $this->_pagehead($pdf, $object, 0, $outputlangs);
486  }
487  // $this->_pagefoot($pdf,$object,$outputlangs,1);
488  $pdf->setTopMargin($tab_top_newpage);
489  // The only function to edit the bottom margin of current page to set it.
490  $pdf->setPageOrientation('', 1, $heightforfooter + $heightforfreetext);
491  }
492 
493  // back to start
494  $pdf->setPage($pageposbeforenote);
495  $pdf->setPageOrientation('', 1, $heightforfooter + $heightforfreetext);
496  $pdf->SetFont('', '', $default_font_size - 1);
497  $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top, dol_htmlentitiesbr($notetoshow), 0, 1);
498  $pageposafternote = $pdf->getPage();
499 
500  $posyafter = $pdf->GetY();
501 
502  if ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + 20))) { // There is no space left for total+free text
503  $pdf->AddPage('', '', true);
504  $pagenb++;
505  $pageposafternote++;
506  $pdf->setPage($pageposafternote);
507  $pdf->setTopMargin($tab_top_newpage);
508  // The only function to edit the bottom margin of current page to set it.
509  $pdf->setPageOrientation('', 1, $heightforfooter + $heightforfreetext);
510  //$posyafter = $tab_top_newpage;
511  }
512 
513 
514  // apply note frame to previous pages
515  $i = $pageposbeforenote;
516  while ($i < $pageposafternote) {
517  $pdf->setPage($i);
518 
519 
520  $pdf->SetDrawColor(128, 128, 128);
521  // Draw note frame
522  if ($i > $pageposbeforenote) {
523  $height_note = $this->page_hauteur - ($tab_top_newpage + $heightforfooter);
524  $pdf->Rect($this->marge_gauche, $tab_top_newpage - 1, $tab_width, $height_note + 1);
525  } else {
526  $height_note = $this->page_hauteur - ($tab_top + $heightforfooter);
527  $pdf->Rect($this->marge_gauche, $tab_top - 1, $tab_width, $height_note + 1);
528  }
529 
530  // Add footer
531  $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it.
532  $this->_pagefoot($pdf, $object, $outputlangs, 1);
533 
534  $i++;
535  }
536 
537  // apply note frame to last page
538  $pdf->setPage($pageposafternote);
539  if (!empty($tplidx)) {
540  $pdf->useTemplate($tplidx);
541  }
542  if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
543  $this->_pagehead($pdf, $object, 0, $outputlangs);
544  }
545  $height_note = $posyafter - $tab_top_newpage;
546  $pdf->Rect($this->marge_gauche, $tab_top_newpage - 1, $tab_width, $height_note + 1);
547  } else {
548  // No pagebreak
549  $pdf->commitTransaction();
550  $posyafter = $pdf->GetY();
551  $height_note = $posyafter - $tab_top;
552  $pdf->Rect($this->marge_gauche, $tab_top - 1, $tab_width, $height_note + 1);
553 
554 
555  if ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + 20))) {
556  // not enough space, need to add page
557  $pdf->AddPage('', '', true);
558  $pagenb++;
559  $pageposafternote++;
560  $pdf->setPage($pageposafternote);
561  if (!empty($tplidx)) {
562  $pdf->useTemplate($tplidx);
563  }
564  if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
565  $this->_pagehead($pdf, $object, 0, $outputlangs);
566  }
567 
568  $posyafter = $tab_top_newpage;
569  }
570  }
571  $tab_height = $tab_height - $height_note;
572  $tab_top = $posyafter + 6;
573  } else {
574  $height_note = 0;
575  }
576 
577  // Use new auto column system
578  $this->prepareArrayColumnField($object, $outputlangs, $hidedetails, $hidedesc, $hideref);
579 
580  // Table simulation to know the height of the title line
581  $pdf->startTransaction();
582  $this->pdfTabTitles($pdf, $tab_top, $tab_height, $outputlangs, $hidetop);
583  $pdf->rollbackTransaction(true);
584 
585  $nexY = $tab_top + $this->tabTitleHeight;
586 
587  // Loop on each lines
588  $pageposbeforeprintlines = $pdf->getPage();
589  $pagenb = $pageposbeforeprintlines;
590  for ($i = 0; $i < $nblines; $i++) {
591  $curY = $nexY;
592  $pdf->SetFont('', '', $default_font_size - 1); // Into loop to work with multipage
593  $pdf->SetTextColor(0, 0, 0);
594 
595  // Define size of image if we need it
596  $imglinesize = array();
597  if (!empty($realpatharray[$i])) {
598  $imglinesize = pdf_getSizeForImage($realpatharray[$i]);
599  }
600 
601  $pdf->setTopMargin($tab_top_newpage);
602  $pdf->setPageOrientation('', 1, $heightforfooter + $heightforfreetext + $heightforsignature + $heightforinfotot); // The only function to edit the bottom margin of current page to set it.
603  $pageposbefore = $pdf->getPage();
604 
605  $showpricebeforepagebreak = 1;
606  $posYAfterImage = 0;
607  $posYAfterDescription = 0;
608 
609  if ($this->getColumnStatus('photo')) {
610  // We start with Photo of product line
611  if (isset($imglinesize['width']) && isset($imglinesize['height']) && ($curY + $imglinesize['height']) > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforsignature + $heightforinfotot))) { // If photo too high, we moved completely on new page
612  $pdf->AddPage('', '', true);
613  if (!empty($tplidx)) {
614  $pdf->useTemplate($tplidx);
615  }
616  $pdf->setPage($pageposbefore + 1);
617 
618  $curY = $tab_top_newpage;
619 
620  // Allows data in the first page if description is long enough to break in multiples pages
621  if (!empty($conf->global->MAIN_PDF_DATA_ON_FIRST_PAGE)) {
622  $showpricebeforepagebreak = 1;
623  } else {
624  $showpricebeforepagebreak = 0;
625  }
626  }
627 
628 
629  if (!empty($this->cols['photo']) && isset($imglinesize['width']) && isset($imglinesize['height'])) {
630  $pdf->Image($realpatharray[$i], $this->getColumnContentXStart('photo'), $curY + 1, $imglinesize['width'], $imglinesize['height'], '', '', '', 2, 300); // Use 300 dpi
631  // $pdf->Image does not increase value return by getY, so we save it manually
632  $posYAfterImage = $curY + $imglinesize['height'];
633  }
634  }
635 
636  // Description of product line
637  if ($this->getColumnStatus('desc')) {
638  $pdf->startTransaction();
639 
640  $this->printColDescContent($pdf, $curY, 'desc', $object, $i, $outputlangs, $hideref, $hidedesc);
641  $pageposafter = $pdf->getPage();
642 
643  if ($pageposafter > $pageposbefore) { // There is a pagebreak
644  $pdf->rollbackTransaction(true);
645 
646  $pdf->setPageOrientation('', 1, $heightforfooter); // The only function to edit the bottom margin of current page to set it.
647 
648  $this->printColDescContent($pdf, $curY, 'desc', $object, $i, $outputlangs, $hideref, $hidedesc);
649 
650  $pageposafter = $pdf->getPage();
651  $posyafter = $pdf->GetY();
652  //var_dump($posyafter); var_dump(($this->page_hauteur - ($heightforfooter+$heightforfreetext+$heightforinfotot))); exit;
653  if ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforsignature + $heightforinfotot))) { // There is no space left for total+free text
654  if ($i == ($nblines - 1)) { // No more lines, and no space left to show total, so we create a new page
655  $pdf->AddPage('', '', true);
656  if (!empty($tplidx)) {
657  $pdf->useTemplate($tplidx);
658  }
659  $pdf->setPage($pageposafter + 1);
660  }
661  } else {
662  // We found a page break
663  // Allows data in the first page if description is long enough to break in multiples pages
664  if (!empty($conf->global->MAIN_PDF_DATA_ON_FIRST_PAGE)) {
665  $showpricebeforepagebreak = 1;
666  } else {
667  $showpricebeforepagebreak = 0;
668  }
669  }
670  } else // No pagebreak
671  {
672  $pdf->commitTransaction();
673  }
674  $posYAfterDescription = $pdf->GetY();
675  }
676 
677  $nexY = $pdf->GetY();
678  $pageposafter = $pdf->getPage();
679 
680  $pdf->setPage($pageposbefore);
681  $pdf->setTopMargin($this->marge_haute);
682  $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it.
683 
684  // We suppose that a too long description or photo were moved completely on next page
685  if ($pageposafter > $pageposbefore && empty($showpricebeforepagebreak)) {
686  $pdf->setPage($pageposafter);
687  $curY = $tab_top_newpage;
688  }
689 
690  $pdf->SetFont('', '', $default_font_size - 1); // We reposition the default font
691 
692  // VAT Rate
693  if ($this->getColumnStatus('vat')) {
694  $vat_rate = pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails);
695  $this->printStdColumnContent($pdf, $curY, 'vat', $vat_rate);
696  $nexY = max($pdf->GetY(), $nexY);
697  }
698 
699  // Unit price before discount
700  if ($this->getColumnStatus('subprice')) {
701  $up_excl_tax = pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails);
702  $this->printStdColumnContent($pdf, $curY, 'subprice', $up_excl_tax);
703  $nexY = max($pdf->GetY(), $nexY);
704  }
705 
706  // Quantity
707  // Enough for 6 chars
708  if ($this->getColumnStatus('qty')) {
709  $qty = pdf_getlineqty($object, $i, $outputlangs, $hidedetails);
710  $this->printStdColumnContent($pdf, $curY, 'qty', $qty);
711  $nexY = max($pdf->GetY(), $nexY);
712  }
713 
714 
715  // Unit
716  if ($this->getColumnStatus('unit')) {
717  $unit = pdf_getlineunit($object, $i, $outputlangs, $hidedetails, $hookmanager);
718  $this->printStdColumnContent($pdf, $curY, 'unit', $unit);
719  $nexY = max($pdf->GetY(), $nexY);
720  }
721 
722  // Discount on line
723  if ($this->getColumnStatus('discount') && $object->lines[$i]->remise_percent) {
724  $remise_percent = pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails);
725  $this->printStdColumnContent($pdf, $curY, 'discount', $remise_percent);
726  $nexY = max($pdf->GetY(), $nexY);
727  }
728 
729  // Total excl tax line (HT)
730  if ($this->getColumnStatus('totalexcltax')) {
731  $total_excl_tax = pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails);
732  $this->printStdColumnContent($pdf, $curY, 'totalexcltax', $total_excl_tax);
733  $nexY = max($pdf->GetY(), $nexY);
734  }
735 
736  // Total with tax line (TTC)
737  if ($this->getColumnStatus('totalincltax')) {
738  $total_incl_tax = pdf_getlinetotalwithtax($object, $i, $outputlangs, $hidedetails);
739  $this->printStdColumnContent($pdf, $curY, 'totalincltax', $total_incl_tax);
740  $nexY = max($pdf->GetY(), $nexY);
741  }
742 
743  // Extrafields
744  if (!empty($object->lines[$i]->array_options)) {
745  foreach ($object->lines[$i]->array_options as $extrafieldColKey => $extrafieldValue) {
746  if ($this->getColumnStatus($extrafieldColKey)) {
747  $extrafieldValue = $this->getExtrafieldContent($object->lines[$i], $extrafieldColKey, $outputlangs);
748  $this->printStdColumnContent($pdf, $curY, $extrafieldColKey, $extrafieldValue);
749  $nexY = max($pdf->GetY(), $nexY);
750  }
751  }
752  }
753 
754  $parameters = array(
755  'object' => $object,
756  'i' => $i,
757  'pdf' =>& $pdf,
758  'curY' =>& $curY,
759  'nexY' =>& $nexY,
760  'outputlangs' => $outputlangs,
761  'hidedetails' => $hidedetails
762  );
763  $reshook = $hookmanager->executeHooks('printPDFline', $parameters, $this); // Note that $object may have been modified by hook
764 
765 
766  // Collection of totals by value of vat in $this->tva["rate"] = total_tva
767  if (isModEnabled("multicurrency") && $object->multicurrency_tx != 1) {
768  $tvaligne = $object->lines[$i]->multicurrency_total_tva;
769  } else {
770  $tvaligne = $object->lines[$i]->total_tva;
771  }
772 
773  $localtax1ligne = $object->lines[$i]->total_localtax1;
774  $localtax2ligne = $object->lines[$i]->total_localtax2;
775  $localtax1_rate = $object->lines[$i]->localtax1_tx;
776  $localtax2_rate = $object->lines[$i]->localtax2_tx;
777  $localtax1_type = $object->lines[$i]->localtax1_type;
778  $localtax2_type = $object->lines[$i]->localtax2_type;
779 
780  if ($object->remise_percent) {
781  $tvaligne -= ($tvaligne * $object->remise_percent) / 100;
782  }
783  if ($object->remise_percent) {
784  $localtax1ligne -= ($localtax1ligne * $object->remise_percent) / 100;
785  }
786  if ($object->remise_percent) {
787  $localtax2ligne -= ($localtax2ligne * $object->remise_percent) / 100;
788  }
789 
790  $vatrate = (string) $object->lines[$i]->tva_tx;
791 
792  // Retrieve type from database for backward compatibility with old records
793  if ((!isset($localtax1_type) || $localtax1_type == '' || !isset($localtax2_type) || $localtax2_type == '') // if tax type not defined
794  && (!empty($localtax1_rate) || !empty($localtax2_rate))) { // and there is local tax
795  $localtaxtmp_array = getLocalTaxesFromRate($vatrate, 0, $object->thirdparty, $mysoc);
796  $localtax1_type = isset($localtaxtmp_array[0]) ? $localtaxtmp_array[0] : '';
797  $localtax2_type = isset($localtaxtmp_array[2]) ? $localtaxtmp_array[2] : '';
798  }
799 
800  // retrieve global local tax
801  if ($localtax1_type && $localtax1ligne != 0) {
802  $this->localtax1[$localtax1_type][$localtax1_rate] += $localtax1ligne;
803  }
804  if ($localtax2_type && $localtax2ligne != 0) {
805  $this->localtax2[$localtax2_type][$localtax2_rate] += $localtax2ligne;
806  }
807 
808  if (($object->lines[$i]->info_bits & 0x01) == 0x01) {
809  $vatrate .= '*';
810  }
811 
812  // Fill $this->tva and $this->tva_array
813  if (!isset($this->tva[$vatrate])) {
814  $this->tva[$vatrate] = 0;
815  }
816  $this->tva[$vatrate] += $tvaligne;
817  $vatcode = $object->lines[$i]->vat_src_code;
818  if (empty($this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'])) {
819  $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'] = 0;
820  }
821  $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')] = array('vatrate'=>$vatrate, 'vatcode'=>$vatcode, 'amount'=> $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'] + $tvaligne);
822 
823  if ($posYAfterImage > $posYAfterDescription) {
824  $nexY = max($nexY, $posYAfterImage);
825  }
826 
827  // Add line
828  if (!empty($conf->global->MAIN_PDF_DASH_BETWEEN_LINES) && $i < ($nblines - 1)) {
829  $pdf->setPage($pageposafter);
830  $pdf->SetLineStyle(array('dash'=>'1,1', 'color'=>array(80, 80, 80)));
831  //$pdf->SetDrawColor(190,190,200);
832  $pdf->line($this->marge_gauche, $nexY + 1, $this->page_largeur - $this->marge_droite, $nexY + 1);
833  $pdf->SetLineStyle(array('dash'=>0));
834  }
835 
836  $nexY += 2; // Add space between lines
837 
838  // Detect if some page were added automatically and output _tableau for past pages
839  while ($pagenb < $pageposafter) {
840  $pdf->setPage($pagenb);
841  if ($pagenb == $pageposbeforeprintlines) {
842  $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, $hidetop, 1, $object->multicurrency_code, $outputlangsbis);
843  } else {
844  $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code, $outputlangsbis);
845  }
846  $this->_pagefoot($pdf, $object, $outputlangs, 1);
847  $pagenb++;
848  $pdf->setPage($pagenb);
849  $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it.
850  if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
851  $this->_pagehead($pdf, $object, 0, $outputlangs);
852  }
853  if (!empty($tplidx)) {
854  $pdf->useTemplate($tplidx);
855  }
856  }
857 
858  if (isset($object->lines[$i + 1]->pagebreak) && $object->lines[$i + 1]->pagebreak) {
859  if ($pagenb == $pageposafter) {
860  $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, $hidetop, 1, $object->multicurrency_code, $outputlangsbis);
861  } else {
862  $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code, $outputlangsbis);
863  }
864  $this->_pagefoot($pdf, $object, $outputlangs, 1);
865  // New page
866  $pdf->AddPage();
867  if (!empty($tplidx)) {
868  $pdf->useTemplate($tplidx);
869  }
870  $pagenb++;
871  if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
872  $this->_pagehead($pdf, $object, 0, $outputlangs);
873  }
874  }
875  }
876 
877  // Show square
878  if ($pagenb == $pageposbeforeprintlines) {
879  $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforsignature - $heightforfooter, 0, $outputlangs, $hidetop, 0, $object->multicurrency_code, $outputlangsbis);
880  $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforsignature - $heightforfooter + 1;
881  } else {
882  $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforsignature - $heightforfooter, 0, $outputlangs, 1, 0, $object->multicurrency_code, $outputlangsbis);
883  $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforsignature - $heightforfooter + 1;
884  }
885 
886  // Display infos area
887  $posy = $this->drawInfoTable($pdf, $object, $bottomlasttab, $outputlangs);
888 
889  // Display total zone
890  $posy = $this->drawTotalTable($pdf, $object, 0, $bottomlasttab, $outputlangs);
891 
892  // Display payment area
893  /*
894  if ($deja_regle || $amount_credit_notes_included || $amount_deposits_included)
895  {
896  $posy=$this->drawPaymentsTable($pdf, $object, $posy, $outputlangs);
897  }
898  */
899 
900  // Customer signature area
901  if (empty($conf->global->PROPAL_DISABLE_SIGNATURE)) {
902  $posy = $this->drawSignatureArea($pdf, $object, $posy, $outputlangs);
903  }
904 
905  // Pagefoot
906  $this->_pagefoot($pdf, $object, $outputlangs);
907  if (method_exists($pdf, 'AliasNbPages')) {
908  $pdf->AliasNbPages();
909  }
910 
911  //If propal merge product PDF is active
912  if (!empty($conf->global->PRODUIT_PDF_MERGE_PROPAL)) {
913  require_once DOL_DOCUMENT_ROOT.'/product/class/propalmergepdfproduct.class.php';
914 
915  $already_merged = array();
916  foreach ($object->lines as $line) {
917  if (!empty($line->fk_product) && !(in_array($line->fk_product, $already_merged))) {
918  // Find the desire PDF
919  $filetomerge = new Propalmergepdfproduct($this->db);
920 
921  if (getDolGlobalInt('MAIN_MULTILANGS')) {
922  $filetomerge->fetch_by_product($line->fk_product, $outputlangs->defaultlang);
923  } else {
924  $filetomerge->fetch_by_product($line->fk_product);
925  }
926 
927  $already_merged[] = $line->fk_product;
928 
929  $product = new Product($this->db);
930  $product->fetch($line->fk_product);
931 
932  if ($product->entity != $conf->entity) {
933  $entity_product_file = $product->entity;
934  } else {
935  $entity_product_file = $conf->entity;
936  }
937 
938  // If PDF is selected and file is not empty
939  if (count($filetomerge->lines) > 0) {
940  foreach ($filetomerge->lines as $linefile) {
941  if (!empty($linefile->id) && !empty($linefile->file_name)) {
942  if (getDolGlobalInt('PRODUCT_USE_OLD_PATH_FOR_PHOTO')) {
943  if (isModEnabled("product")) {
944  $filetomerge_dir = $conf->product->multidir_output[$entity_product_file].'/'.get_exdir($product->id, 2, 0, 0, $product, 'product').$product->id."/photos";
945  } elseif (isModEnabled("service")) {
946  $filetomerge_dir = $conf->service->multidir_output[$entity_product_file].'/'.get_exdir($product->id, 2, 0, 0, $product, 'product').$product->id."/photos";
947  }
948  } else {
949  if (isModEnabled("product")) {
950  $filetomerge_dir = $conf->product->multidir_output[$entity_product_file].'/'.get_exdir(0, 0, 0, 0, $product, 'product');
951  } elseif (isModEnabled("service")) {
952  $filetomerge_dir = $conf->service->multidir_output[$entity_product_file].'/'.get_exdir(0, 0, 0, 0, $product, 'product');
953  }
954  }
955 
956  dol_syslog(get_class($this).':: upload_dir='.$filetomerge_dir, LOG_DEBUG);
957 
958  $infile = $filetomerge_dir.'/'.$linefile->file_name;
959  if (file_exists($infile) && is_readable($infile)) {
960  $pagecount = $pdf->setSourceFile($infile);
961  for ($i = 1; $i <= $pagecount; $i++) {
962  $tplIdx = $pdf->importPage($i);
963  if ($tplIdx !== false) {
964  $s = $pdf->getTemplatesize($tplIdx);
965  $pdf->AddPage($s['h'] > $s['w'] ? 'P' : 'L');
966  $pdf->useTemplate($tplIdx);
967  } else {
968  setEventMessages(null, array($infile.' cannot be added, probably protected PDF'), 'warnings');
969  }
970  }
971  }
972  }
973  }
974  }
975  }
976  }
977  }
978 
979  $pdf->Close();
980 
981  $pdf->Output($file, 'F');
982 
983  //Add pdfgeneration hook
984  $hookmanager->initHooks(array('pdfgeneration'));
985  $parameters = array('file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs);
986  global $action;
987  $reshook = $hookmanager->executeHooks('afterPDFCreation', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
988  if ($reshook < 0) {
989  $this->error = $hookmanager->error;
990  $this->errors = $hookmanager->errors;
991  }
992 
993  if (!empty($conf->global->MAIN_UMASK)) {
994  @chmod($file, octdec($conf->global->MAIN_UMASK));
995  }
996 
997  $this->result = array('fullpath'=>$file);
998 
999  return 1; // No error
1000  } else {
1001  $this->error = $langs->trans("ErrorCanNotCreateDir", $dir);
1002  return 0;
1003  }
1004  } else {
1005  $this->error = $langs->trans("ErrorConstantNotDefined", "PROP_OUTPUTDIR");
1006  return 0;
1007  }
1008  }
1009 
1019  protected function drawPaymentsTable(&$pdf, $object, $posy, $outputlangs)
1020  {
1021  }
1022 
1032  public function drawInfoTable(&$pdf, $object, $posy, $outputlangs)
1033  {
1034  global $conf, $mysoc;
1035  $default_font_size = pdf_getPDFFontSize($outputlangs);
1036 
1037  $pdf->SetFont('', '', $default_font_size - 1);
1038 
1039  $diffsizetitle = (empty($conf->global->PDF_DIFFSIZE_TITLE) ? 3 : $conf->global->PDF_DIFFSIZE_TITLE);
1040 
1041  // If France, show VAT mention if not applicable
1042  if ($this->emetteur->country_code == 'FR' && empty($mysoc->tva_assuj)) {
1043  $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
1044  $pdf->SetXY($this->marge_gauche, $posy);
1045  $pdf->MultiCell(100, 3, $outputlangs->transnoentities("VATIsNotUsedForInvoice"), 0, 'L', 0);
1046 
1047  $posy = $pdf->GetY() + 4;
1048  }
1049 
1050  $posxval = 52;
1051  if (!empty($conf->global->MAIN_PDF_DATE_TEXT)) {
1052  $displaydate = "daytext";
1053  } else {
1054  $displaydate = "day";
1055  }
1056 
1057  // Show shipping date
1058  if (!empty($object->delivery_date)) {
1059  $outputlangs->load("sendings");
1060  $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
1061  $pdf->SetXY($this->marge_gauche, $posy);
1062  $titre = $outputlangs->transnoentities("DateDeliveryPlanned").':';
1063  $pdf->MultiCell(80, 4, $titre, 0, 'L');
1064  $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
1065  $pdf->SetXY($posxval, $posy);
1066  $dlp = dol_print_date($object->delivery_date, $displaydate, false, $outputlangs, true);
1067  $pdf->MultiCell(80, 4, $dlp, 0, 'L');
1068 
1069  $posy = $pdf->GetY() + 1;
1070  } elseif ($object->availability_code || $object->availability) { // Show availability conditions
1071  $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
1072  $pdf->SetXY($this->marge_gauche, $posy);
1073  $titre = $outputlangs->transnoentities("AvailabilityPeriod").':';
1074  $pdf->MultiCell(80, 4, $titre, 0, 'L');
1075  $pdf->SetTextColor(0, 0, 0);
1076  $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
1077  $pdf->SetXY($posxval, $posy);
1078  $lib_availability = $outputlangs->transnoentities("AvailabilityType".$object->availability_code) != ('AvailabilityType'.$object->availability_code) ? $outputlangs->transnoentities("AvailabilityType".$object->availability_code) : $outputlangs->convToOutputCharset($object->availability);
1079  $lib_availability = str_replace('\n', "\n", $lib_availability);
1080  $pdf->MultiCell(80, 4, $lib_availability, 0, 'L');
1081 
1082  $posy = $pdf->GetY() + 1;
1083  }
1084 
1085  // Show delivery mode
1086  if (empty($conf->global->PROPOSAL_PDF_HIDE_DELIVERYMODE) && $object->shipping_method_id > 0) {
1087  $outputlangs->load("sendings");
1088 
1089  $shipping_method_id = $object->shipping_method_id;
1090  if (!empty($conf->global->SOCIETE_ASK_FOR_SHIPPING_METHOD) && !empty($this->emetteur->shipping_method_id)) {
1091  $shipping_method_id = $this->emetteur->shipping_method_id;
1092  }
1093  $shipping_method_code = dol_getIdFromCode($this->db, $shipping_method_id, 'c_shipment_mode', 'rowid', 'code');
1094  $shipping_method_label = dol_getIdFromCode($this->db, $shipping_method_id, 'c_shipment_mode', 'rowid', 'libelle');
1095 
1096  $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
1097  $pdf->SetXY($this->marge_gauche, $posy);
1098  $titre = $outputlangs->transnoentities("SendingMethod").':';
1099  $pdf->MultiCell(43, 4, $titre, 0, 'L');
1100 
1101  $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
1102  $pdf->SetXY($posxval, $posy);
1103  $lib_condition_paiement = ($outputlangs->transnoentities("SendingMethod".strtoupper($shipping_method_code)) != "SendingMethod".strtoupper($shipping_method_code)) ? $outputlangs->trans("SendingMethod".strtoupper($shipping_method_code)) : $shipping_method_label;
1104  $lib_condition_paiement = str_replace('\n', "\n", $lib_condition_paiement);
1105  $pdf->MultiCell(67, 4, $lib_condition_paiement, 0, 'L');
1106 
1107  $posy = $pdf->GetY() + 1;
1108  }
1109 
1110  // Show payments conditions
1111  if (empty($conf->global->PROPOSAL_PDF_HIDE_PAYMENTTERM) && $object->cond_reglement_code) {
1112  $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
1113  $pdf->SetXY($this->marge_gauche, $posy);
1114  $titre = $outputlangs->transnoentities("PaymentConditions").':';
1115  $pdf->MultiCell(43, 4, $titre, 0, 'L');
1116 
1117  $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
1118  $pdf->SetXY($posxval, $posy);
1119  $lib_condition_paiement = $outputlangs->transnoentities("PaymentCondition".$object->cond_reglement_code) != ('PaymentCondition'.$object->cond_reglement_code) ? $outputlangs->transnoentities("PaymentCondition".$object->cond_reglement_code) : $outputlangs->convToOutputCharset($object->cond_reglement_doc ? $object->cond_reglement_doc : $object->cond_reglement_label);
1120  $lib_condition_paiement = str_replace('\n', "\n", $lib_condition_paiement);
1121  if ($object->deposit_percent > 0) {
1122  $lib_condition_paiement = str_replace('__DEPOSIT_PERCENT__', $object->deposit_percent, $lib_condition_paiement);
1123  }
1124  $pdf->MultiCell(67, 4, $lib_condition_paiement, 0, 'L');
1125 
1126  $posy = $pdf->GetY() + 3;
1127  }
1128 
1129  if (empty($conf->global->PROPOSAL_PDF_HIDE_PAYMENTMODE)) {
1130  // Show payment mode
1131  if ($object->mode_reglement_code
1132  && $object->mode_reglement_code != 'CHQ'
1133  && $object->mode_reglement_code != 'VIR') {
1134  $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
1135  $pdf->SetXY($this->marge_gauche, $posy);
1136  $titre = $outputlangs->transnoentities("PaymentMode").':';
1137  $pdf->MultiCell(80, 5, $titre, 0, 'L');
1138  $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
1139  $pdf->SetXY($posxval, $posy);
1140  $lib_mode_reg = $outputlangs->transnoentities("PaymentType".$object->mode_reglement_code) != ('PaymentType'.$object->mode_reglement_code) ? $outputlangs->transnoentities("PaymentType".$object->mode_reglement_code) : $outputlangs->convToOutputCharset($object->mode_reglement);
1141  $pdf->MultiCell(80, 5, $lib_mode_reg, 0, 'L');
1142 
1143  $posy = $pdf->GetY() + 2;
1144  }
1145 
1146  // Show payment mode CHQ
1147  if (empty($object->mode_reglement_code) || $object->mode_reglement_code == 'CHQ') {
1148  // Si mode reglement non force ou si force a CHQ
1149  if (!empty($conf->global->FACTURE_CHQ_NUMBER)) {
1150  if ($conf->global->FACTURE_CHQ_NUMBER > 0) {
1151  $account = new Account($this->db);
1152  $account->fetch($conf->global->FACTURE_CHQ_NUMBER);
1153 
1154  $pdf->SetXY($this->marge_gauche, $posy);
1155  $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
1156  $pdf->MultiCell(100, 3, $outputlangs->transnoentities('PaymentByChequeOrderedTo', $account->proprio), 0, 'L', 0);
1157  $posy = $pdf->GetY() + 1;
1158 
1159  if (empty($conf->global->MAIN_PDF_HIDE_CHQ_ADDRESS)) {
1160  $pdf->SetXY($this->marge_gauche, $posy);
1161  $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
1162  $pdf->MultiCell(100, 3, $outputlangs->convToOutputCharset($account->owner_address), 0, 'L', 0);
1163  $posy = $pdf->GetY() + 2;
1164  }
1165  }
1166  if ($conf->global->FACTURE_CHQ_NUMBER == -1) {
1167  $pdf->SetXY($this->marge_gauche, $posy);
1168  $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
1169  $pdf->MultiCell(100, 3, $outputlangs->transnoentities('PaymentByChequeOrderedTo', $this->emetteur->name), 0, 'L', 0);
1170  $posy = $pdf->GetY() + 1;
1171 
1172  if (empty($conf->global->MAIN_PDF_HIDE_CHQ_ADDRESS)) {
1173  $pdf->SetXY($this->marge_gauche, $posy);
1174  $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
1175  $pdf->MultiCell(100, 3, $outputlangs->convToOutputCharset($this->emetteur->getFullAddress()), 0, 'L', 0);
1176  $posy = $pdf->GetY() + 2;
1177  }
1178  }
1179  }
1180  }
1181 
1182  // If payment mode not forced or forced to VIR, show payment with BAN
1183  if (empty($object->mode_reglement_code) || $object->mode_reglement_code == 'VIR') {
1184  if ($object->fk_account > 0 || $object->fk_bank > 0 || getDolGlobalInt('FACTURE_RIB_NUMBER')) {
1185  $bankid = ($object->fk_account <= 0 ? $conf->global->FACTURE_RIB_NUMBER : $object->fk_account);
1186  if ($object->fk_bank > 0) {
1187  $bankid = $object->fk_bank; // For backward compatibility when object->fk_account is forced with object->fk_bank
1188  }
1189  $account = new Account($this->db);
1190  $account->fetch($bankid);
1191 
1192  $curx = $this->marge_gauche;
1193  $cury = $posy;
1194 
1195  $posy = pdf_bank($pdf, $outputlangs, $curx, $cury, $account, 0, $default_font_size);
1196 
1197  $posy += 2;
1198  }
1199  }
1200  }
1201 
1202  return $posy;
1203  }
1204 
1205 
1217  protected function drawTotalTable(&$pdf, $object, $deja_regle, $posy, $outputlangs, $outputlangsbis = null)
1218  {
1219  global $conf, $mysoc, $hookmanager;
1220 
1221  $default_font_size = pdf_getPDFFontSize($outputlangs);
1222 
1223  if (!empty($conf->global->PDF_USE_ALSO_LANGUAGE_CODE) && $outputlangs->defaultlang != $conf->global->PDF_USE_ALSO_LANGUAGE_CODE) {
1224  $outputlangsbis = new Translate('', $conf);
1225  $outputlangsbis->setDefaultLang($conf->global->PDF_USE_ALSO_LANGUAGE_CODE);
1226  $outputlangsbis->loadLangs(array("main", "dict", "companies", "bills", "products", "propal"));
1227  $default_font_size--;
1228  }
1229 
1230  $tab2_top = $posy;
1231  $tab2_hl = 4;
1232  $pdf->SetFont('', '', $default_font_size - 1);
1233 
1234  // Total table
1235  $col1x = 120;
1236  $col2x = 170;
1237  if ($this->page_largeur < 210) { // To work with US executive format
1238  $col2x -= 20;
1239  }
1240  $largcol2 = ($this->page_largeur - $this->marge_droite - $col2x);
1241 
1242  $useborder = 0;
1243  $index = 0;
1244 
1245  // Total HT
1246  $pdf->SetFillColor(255, 255, 255);
1247  $pdf->SetXY($col1x, $tab2_top + 0);
1248  $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalHT").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transnoentities("TotalHT") : ''), 0, 'L', 1);
1249 
1250  $total_ht = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? $object->multicurrency_total_ht : $object->total_ht);
1251  $pdf->SetXY($col2x, $tab2_top + 0);
1252  $pdf->MultiCell($largcol2, $tab2_hl, price($total_ht + (!empty($object->remise) ? $object->remise : 0), 0, $outputlangs), 0, 'R', 1);
1253 
1254  // Show VAT by rates and total
1255  $pdf->SetFillColor(248, 248, 248);
1256 
1257  $total_ttc = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1) ? $object->multicurrency_total_ttc : $object->total_ttc;
1258 
1259  $this->atleastoneratenotnull = 0;
1260  if (empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT)) {
1261  $tvaisnull = ((!empty($this->tva) && count($this->tva) == 1 && isset($this->tva['0.000']) && is_float($this->tva['0.000'])) ? true : false);
1262  if (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_IFNULL) && $tvaisnull) {
1263  // Nothing to do
1264  } else {
1265  //Local tax 1 before VAT
1266  //if (!empty($conf->global->FACTURE_LOCAL_TAX1_OPTION) && $conf->global->FACTURE_LOCAL_TAX1_OPTION=='localtax1on')
1267  //{
1268  foreach ($this->localtax1 as $localtax_type => $localtax_rate) {
1269  if (in_array((string) $localtax_type, array('1', '3', '5'))) {
1270  continue;
1271  }
1272 
1273  foreach ($localtax_rate as $tvakey => $tvaval) {
1274  if ($tvakey != 0) { // On affiche pas taux 0
1275  //$this->atleastoneratenotnull++;
1276 
1277  $index++;
1278  $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1279 
1280  $tvacompl = '';
1281  if (preg_match('/\*/', $tvakey)) {
1282  $tvakey = str_replace('*', '', $tvakey);
1283  $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1284  }
1285  $totalvat = $outputlangs->transcountrynoentities("TotalLT1", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalLT1", $mysoc->country_code) : '');
1286  $totalvat .= ' ';
1287  $totalvat .= vatrate(abs($tvakey), 1).$tvacompl;
1288  $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1);
1289 
1290  $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1291  $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1);
1292  }
1293  }
1294  }
1295  //}
1296  //Local tax 2 before VAT
1297  //if (!empty($conf->global->FACTURE_LOCAL_TAX2_OPTION) && $conf->global->FACTURE_LOCAL_TAX2_OPTION=='localtax2on')
1298  //{
1299  foreach ($this->localtax2 as $localtax_type => $localtax_rate) {
1300  if (in_array((string) $localtax_type, array('1', '3', '5'))) {
1301  continue;
1302  }
1303 
1304  foreach ($localtax_rate as $tvakey => $tvaval) {
1305  if ($tvakey != 0) { // On affiche pas taux 0
1306  //$this->atleastoneratenotnull++;
1307 
1308 
1309 
1310  $index++;
1311  $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1312 
1313  $tvacompl = '';
1314  if (preg_match('/\*/', $tvakey)) {
1315  $tvakey = str_replace('*', '', $tvakey);
1316  $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1317  }
1318  $totalvat = $outputlangs->transcountrynoentities("TotalLT2", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalLT2", $mysoc->country_code) : '');
1319  $totalvat .= ' ';
1320  $totalvat .= vatrate(abs($tvakey), 1).$tvacompl;
1321  $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1);
1322 
1323  $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1324  $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1);
1325  }
1326  }
1327  }
1328  //}
1329 
1330  // VAT
1331  foreach ($this->tva as $tvakey => $tvaval) {
1332  if ($tvakey != 0) { // On affiche pas taux 0
1333  $this->atleastoneratenotnull++;
1334 
1335  $index++;
1336  $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1337 
1338  $tvacompl = '';
1339  if (preg_match('/\*/', $tvakey)) {
1340  $tvakey = str_replace('*', '', $tvakey);
1341  $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1342  }
1343  $totalvat = $outputlangs->transcountrynoentities("TotalVAT", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalVAT", $mysoc->country_code) : '');
1344  $totalvat .= ' ';
1345  $totalvat .= vatrate($tvakey, 1).$tvacompl;
1346  $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1);
1347 
1348  $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1349  $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1);
1350  }
1351  }
1352 
1353  //Local tax 1 after VAT
1354  //if (!empty($conf->global->FACTURE_LOCAL_TAX1_OPTION) && $conf->global->FACTURE_LOCAL_TAX1_OPTION=='localtax1on')
1355  //{
1356  foreach ($this->localtax1 as $localtax_type => $localtax_rate) {
1357  if (in_array((string) $localtax_type, array('2', '4', '6'))) {
1358  continue;
1359  }
1360 
1361  foreach ($localtax_rate as $tvakey => $tvaval) {
1362  if ($tvakey != 0) { // On affiche pas taux 0
1363  //$this->atleastoneratenotnull++;
1364 
1365  $index++;
1366  $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1367 
1368  $tvacompl = '';
1369  if (preg_match('/\*/', $tvakey)) {
1370  $tvakey = str_replace('*', '', $tvakey);
1371  $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1372  }
1373  $totalvat = $outputlangs->transcountrynoentities("TotalLT1", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalLT1", $mysoc->country_code) : '');
1374  $totalvat .= ' ';
1375 
1376  $totalvat .= vatrate(abs($tvakey), 1).$tvacompl;
1377  $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1);
1378  $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1379  $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1);
1380  }
1381  }
1382  }
1383  //}
1384  //Local tax 2 after VAT
1385  //if (!empty($conf->global->FACTURE_LOCAL_TAX2_OPTION) && $conf->global->FACTURE_LOCAL_TAX2_OPTION=='localtax2on')
1386  //{
1387  foreach ($this->localtax2 as $localtax_type => $localtax_rate) {
1388  if (in_array((string) $localtax_type, array('2', '4', '6'))) {
1389  continue;
1390  }
1391 
1392  foreach ($localtax_rate as $tvakey => $tvaval) {
1393  // retrieve global local tax
1394  if ($tvakey != 0) { // On affiche pas taux 0
1395  //$this->atleastoneratenotnull++;
1396 
1397  $index++;
1398  $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1399 
1400  $tvacompl = '';
1401  if (preg_match('/\*/', $tvakey)) {
1402  $tvakey = str_replace('*', '', $tvakey);
1403  $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1404  }
1405  $totalvat = $outputlangs->transcountrynoentities("TotalLT2", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalLT2", $mysoc->country_code) : '');
1406  $totalvat .= ' ';
1407 
1408  $totalvat .= vatrate(abs($tvakey), 1).$tvacompl;
1409  $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1);
1410 
1411  $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1412  $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1);
1413  }
1414  }
1415  }
1416  //}
1417 
1418  // Total TTC
1419  $index++;
1420  $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1421  $pdf->SetTextColor(0, 0, 60);
1422  $pdf->SetFillColor(224, 224, 224);
1423  $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalTTC").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transnoentities("TotalTTC") : ''), $useborder, 'L', 1);
1424 
1425  $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1426  $pdf->MultiCell($largcol2, $tab2_hl, price($total_ttc, 0, $outputlangs), $useborder, 'R', 1);
1427  }
1428  }
1429 
1430  $pdf->SetTextColor(0, 0, 0);
1431 
1432  $resteapayer = 0;
1433  /*
1434  $resteapayer = $object->total_ttc - $deja_regle;
1435  if (!empty($object->paye)) $resteapayer=0;
1436  */
1437 
1438  if ($deja_regle > 0) {
1439  // Already paid + Deposits
1440  $index++;
1441 
1442  $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1443  $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("AlreadyPaid").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transnoentities("AlreadyPaid") : ''), 0, 'L', 0);
1444 
1445  $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1446  $pdf->MultiCell($largcol2, $tab2_hl, price($deja_regle, 0, $outputlangs), 0, 'R', 0);
1447 
1448  /*
1449  if ($object->close_code == 'discount_vat')
1450  {
1451  $index++;
1452  $pdf->SetFillColor(255,255,255);
1453 
1454  $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1455  $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("EscompteOfferedShort"), $useborder, 'L', 1);
1456 
1457  $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1458  $pdf->MultiCell($largcol2, $tab2_hl, price($object->total_ttc - $deja_regle, 0, $outputlangs), $useborder, 'R', 1);
1459 
1460  $resteapayer=0;
1461  }
1462  */
1463 
1464  $index++;
1465  $pdf->SetTextColor(0, 0, 60);
1466  $pdf->SetFillColor(224, 224, 224);
1467  $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1468  $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("RemainderToPay").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transnoentities("RemainderToPay") : ''), $useborder, 'L', 1);
1469 
1470  $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1471  $pdf->MultiCell($largcol2, $tab2_hl, price($resteapayer, 0, $outputlangs), $useborder, 'R', 1);
1472 
1473  $pdf->SetFont('', '', $default_font_size - 1);
1474  $pdf->SetTextColor(0, 0, 0);
1475  }
1476 
1477  $index++;
1478  return ($tab2_top + ($tab2_hl * $index));
1479  }
1480 
1481  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1496  protected function _tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop = 0, $hidebottom = 0, $currency = '', $outputlangsbis = null)
1497  {
1498  global $conf;
1499 
1500  // Force to disable hidetop and hidebottom
1501  $hidebottom = 0;
1502  if ($hidetop) {
1503  $hidetop = -1;
1504  }
1505 
1506  $currency = !empty($currency) ? $currency : $conf->currency;
1507  $default_font_size = pdf_getPDFFontSize($outputlangs);
1508 
1509  // Amount in (at tab_top - 1)
1510  $pdf->SetTextColor(0, 0, 0);
1511  $pdf->SetFont('', '', $default_font_size - 2);
1512 
1513  if (empty($hidetop)) {
1514  $titre = $outputlangs->transnoentities("AmountInCurrency", $outputlangs->transnoentitiesnoconv("Currency".$currency));
1515  if (!empty($conf->global->PDF_USE_ALSO_LANGUAGE_CODE) && is_object($outputlangsbis)) {
1516  $titre .= ' - '.$outputlangsbis->transnoentities("AmountInCurrency", $outputlangsbis->transnoentitiesnoconv("Currency".$currency));
1517  }
1518 
1519  $pdf->SetXY($this->page_largeur - $this->marge_droite - ($pdf->GetStringWidth($titre) + 3), $tab_top - 4);
1520  $pdf->MultiCell(($pdf->GetStringWidth($titre) + 3), 2, $titre);
1521 
1522  //$conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR='230,230,230';
1523  if (!empty($conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR)) {
1524  $pdf->Rect($this->marge_gauche, $tab_top, $this->page_largeur - $this->marge_droite - $this->marge_gauche, $this->tabTitleHeight, 'F', null, explode(',', $conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR));
1525  }
1526  }
1527 
1528  $pdf->SetDrawColor(128, 128, 128);
1529  $pdf->SetFont('', '', $default_font_size - 1);
1530 
1531  // Output Rect
1532  $this->printRect($pdf, $this->marge_gauche, $tab_top, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $tab_height, $hidetop, $hidebottom); // Rect takes a length in 3rd parameter and 4th parameter
1533 
1534  $this->pdfTabTitles($pdf, $tab_top, $tab_height, $outputlangs, $hidetop);
1535 
1536  if (empty($hidetop)) {
1537  $pdf->line($this->marge_gauche, $tab_top + $this->tabTitleHeight, $this->page_largeur - $this->marge_droite, $tab_top + $this->tabTitleHeight); // line takes a position y in 2nd parameter and 4th parameter
1538  }
1539  }
1540 
1541  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1552  protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $outputlangsbis = null)
1553  {
1554  global $conf, $langs;
1555 
1556  $ltrdirection = 'L';
1557  if ($outputlangs->trans("DIRECTION") == 'rtl') $ltrdirection = 'R';
1558 
1559  // Load traductions files required by page
1560  $outputlangs->loadLangs(array("main", "propal", "companies", "bills"));
1561 
1562  $default_font_size = pdf_getPDFFontSize($outputlangs);
1563 
1564  pdf_pagehead($pdf, $outputlangs, $this->page_hauteur);
1565 
1566  $pdf->SetTextColor(0, 0, 60);
1567  $pdf->SetFont('', 'B', $default_font_size + 3);
1568 
1569  $w = 100;
1570 
1571  $posy = $this->marge_haute;
1572  $posx = $this->page_largeur - $this->marge_droite - $w;
1573 
1574  $pdf->SetXY($this->marge_gauche, $posy);
1575 
1576  // Logo
1577  if (empty($conf->global->PDF_DISABLE_MYCOMPANY_LOGO)) {
1578  if ($this->emetteur->logo) {
1579  $logodir = $conf->mycompany->dir_output;
1580  if (!empty($conf->mycompany->multidir_output[$object->entity])) {
1581  $logodir = $conf->mycompany->multidir_output[$object->entity];
1582  }
1583  if (empty($conf->global->MAIN_PDF_USE_LARGE_LOGO)) {
1584  $logo = $logodir.'/logos/thumbs/'.$this->emetteur->logo_small;
1585  } else {
1586  $logo = $logodir.'/logos/'.$this->emetteur->logo;
1587  }
1588  if (is_readable($logo)) {
1589  $height = pdf_getHeightForLogo($logo);
1590  $pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto)
1591  } else {
1592  $pdf->SetTextColor(200, 0, 0);
1593  $pdf->SetFont('', 'B', $default_font_size - 2);
1594  $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound", $logo), 0, 'L');
1595  $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ErrorGoToGlobalSetup"), 0, 'L');
1596  }
1597  } else {
1598  $text = $this->emetteur->name;
1599  $pdf->MultiCell($w, 4, $outputlangs->convToOutputCharset($text), 0, $ltrdirection);
1600  }
1601  }
1602 
1603  $pdf->SetFont('', 'B', $default_font_size + 3);
1604  $pdf->SetXY($posx, $posy);
1605  $pdf->SetTextColor(0, 0, 60);
1606  $title = $outputlangs->transnoentities("PdfCommercialProposalTitle");
1607  $title .= ' '.$outputlangs->convToOutputCharset($object->ref);
1608  if ($object->statut == $object::STATUS_DRAFT) {
1609  $pdf->SetTextColor(128, 0, 0);
1610  $title .= ' - '.$outputlangs->transnoentities("NotValidated");
1611  }
1612 
1613  $pdf->MultiCell($w, 4, $title, '', 'R');
1614 
1615  $pdf->SetFont('', 'B', $default_font_size);
1616 
1617  /*
1618  $posy += 5;
1619  $pdf->SetXY($posx, $posy);
1620  $pdf->SetTextColor(0, 0, 60);
1621  $textref = $outputlangs->transnoentities("Ref")." : ".$outputlangs->convToOutputCharset($object->ref);
1622  if ($object->statut == $object::STATUS_DRAFT) {
1623  $pdf->SetTextColor(128, 0, 0);
1624  $textref .= ' - '.$outputlangs->transnoentities("NotValidated");
1625  }
1626  $pdf->MultiCell($w, 4, $textref, '', 'R');
1627  */
1628 
1629  $posy += 3;
1630  $pdf->SetFont('', '', $default_font_size - 2);
1631 
1632  if ($object->ref_client) {
1633  $posy += 4;
1634  $pdf->SetXY($posx, $posy);
1635  $pdf->SetTextColor(0, 0, 60);
1636  $pdf->MultiCell($w, 3, $outputlangs->transnoentities("RefCustomer")." : ".dol_trunc($outputlangs->convToOutputCharset($object->ref_client), 65), '', 'R');
1637  }
1638 
1639  if (!empty($conf->global->PDF_SHOW_PROJECT_TITLE)) {
1640  $object->fetch_projet();
1641  if (!empty($object->project->ref)) {
1642  $posy += 3;
1643  $pdf->SetXY($posx, $posy);
1644  $pdf->SetTextColor(0, 0, 60);
1645  $pdf->MultiCell($w, 3, $outputlangs->transnoentities("Project")." : ".(empty($object->project->title) ? '' : $object->project->title), '', 'R');
1646  }
1647  }
1648 
1649  if (!empty($conf->global->PDF_SHOW_PROJECT)) {
1650  $object->fetch_projet();
1651  if (!empty($object->project->ref)) {
1652  $outputlangs->load("projects");
1653  $posy += 3;
1654  $pdf->SetXY($posx, $posy);
1655  $pdf->SetTextColor(0, 0, 60);
1656  $pdf->MultiCell($w, 3, $outputlangs->transnoentities("RefProject")." : ".(empty($object->project->ref) ? '' : $object->project->ref), '', 'R');
1657  }
1658  }
1659 
1660  if (!empty($conf->global->MAIN_PDF_DATE_TEXT)) {
1661  $displaydate = "daytext";
1662  } else {
1663  $displaydate = "day";
1664  }
1665 
1666  $posy += 4;
1667  $pdf->SetXY($posx, $posy);
1668  $pdf->SetTextColor(0, 0, 60);
1669  $pdf->MultiCell($w, 3, $outputlangs->transnoentities("Date")." : ".dol_print_date($object->date, $displaydate, false, $outputlangs, true), '', 'R');
1670 
1671  $posy += 4;
1672  $pdf->SetXY($posx, $posy);
1673  $pdf->SetTextColor(0, 0, 60);
1674 
1675  $title = $outputlangs->transnoentities("DateEndPropal");
1676  if (!empty($conf->global->PDF_USE_ALSO_LANGUAGE_CODE) && is_object($outputlangsbis)) {
1677  $title .= ' - '.$outputlangsbis->transnoentities("DateEndPropal");
1678  }
1679  $pdf->MultiCell($w, 3, $title." : ".dol_print_date($object->fin_validite, $displaydate, false, $outputlangs, true), '', 'R');
1680 
1681  if (empty($conf->global->MAIN_PDF_HIDE_CUSTOMER_CODE) && $object->thirdparty->code_client) {
1682  $posy += 4;
1683  $pdf->SetXY($posx, $posy);
1684  $pdf->SetTextColor(0, 0, 60);
1685  $pdf->MultiCell($w, 3, $outputlangs->transnoentities("CustomerCode")." : ".$outputlangs->transnoentities($object->thirdparty->code_client), '', 'R');
1686  }
1687 
1688  // Get contact
1689  if (!empty($conf->global->DOC_SHOW_FIRST_SALES_REP)) {
1690  $arrayidcontact = $object->getIdContact('internal', 'SALESREPFOLL');
1691  if (count($arrayidcontact) > 0) {
1692  $usertmp = new User($this->db);
1693  $usertmp->fetch($arrayidcontact[0]);
1694  $posy += 4;
1695  $pdf->SetXY($posx, $posy);
1696  $pdf->SetTextColor(0, 0, 60);
1697  $pdf->MultiCell($w, 3, $langs->transnoentities("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R');
1698  }
1699  }
1700 
1701  $posy += 2;
1702 
1703  $top_shift = 0;
1704  // Show list of linked objects
1705  $current_y = $pdf->getY();
1706  $posy = pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, $w, 3, 'R', $default_font_size);
1707  if ($current_y < $pdf->getY()) {
1708  $top_shift = $pdf->getY() - $current_y;
1709  }
1710 
1711  if ($showaddress) {
1712  // Sender properties
1713  $carac_emetteur = '';
1714  // Add internal contact of proposal if defined
1715  $arrayidcontact = $object->getIdContact('internal', 'SALESREPFOLL');
1716  if (count($arrayidcontact) > 0) {
1717  $object->fetch_user($arrayidcontact[0]);
1718  $labelbeforecontactname = ($outputlangs->transnoentities("FromContactName") != 'FromContactName' ? $outputlangs->transnoentities("FromContactName") : $outputlangs->transnoentities("Name"));
1719  $carac_emetteur .= ($carac_emetteur ? "\n" : '').$labelbeforecontactname." ".$outputlangs->convToOutputCharset($object->user->getFullName($outputlangs))."\n";
1720  }
1721 
1722  $carac_emetteur .= pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, '', 0, 'source', $object);
1723 
1724  // Show sender
1725  $posy = !empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 40 : 42;
1726  $posy += $top_shift;
1727  $posx = $this->marge_gauche;
1728  if (!empty($conf->global->MAIN_INVERT_SENDER_RECIPIENT)) {
1729  $posx = $this->page_largeur - $this->marge_droite - 80;
1730  }
1731 
1732  $hautcadre = !empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 38 : 40;
1733  $widthrecbox = !empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 92 : 82;
1734 
1735  // Show sender frame
1736  if (empty($conf->global->MAIN_PDF_NO_SENDER_FRAME)) {
1737  $pdf->SetTextColor(0, 0, 0);
1738  $pdf->SetFont('', '', $default_font_size - 2);
1739  $pdf->SetXY($posx, $posy - 5);
1740  $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillFrom"), 0, $ltrdirection);
1741  $pdf->SetXY($posx, $posy);
1742  $pdf->SetFillColor(230, 230, 230);
1743  $pdf->MultiCell($widthrecbox, $hautcadre, "", 0, 'R', 1);
1744  $pdf->SetTextColor(0, 0, 60);
1745  }
1746 
1747  // Show sender name
1748  if (empty($conf->global->MAIN_PDF_HIDE_SENDER_NAME)) {
1749  $pdf->SetXY($posx + 2, $posy + 3);
1750  $pdf->SetFont('', 'B', $default_font_size);
1751  $pdf->MultiCell($widthrecbox - 2, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, $ltrdirection);
1752  $posy = $pdf->getY();
1753  }
1754 
1755  // Show sender information
1756  $pdf->SetXY($posx + 2, $posy);
1757  $pdf->SetFont('', '', $default_font_size - 1);
1758  $pdf->MultiCell($widthrecbox - 2, 4, $carac_emetteur, 0, $ltrdirection);
1759 
1760 
1761  // If CUSTOMER contact defined, we use it
1762  $usecontact = false;
1763  $arrayidcontact = $object->getIdContact('external', 'CUSTOMER');
1764  if (count($arrayidcontact) > 0) {
1765  $usecontact = true;
1766  $result = $object->fetch_contact($arrayidcontact[0]);
1767  }
1768 
1769  // Recipient name
1770  if ($usecontact && ($object->contact->socid != $object->thirdparty->id && (!isset($conf->global->MAIN_USE_COMPANY_NAME_OF_CONTACT) || !empty($conf->global->MAIN_USE_COMPANY_NAME_OF_CONTACT)))) {
1771  $thirdparty = $object->contact;
1772  } else {
1773  $thirdparty = $object->thirdparty;
1774  }
1775 
1776  $carac_client_name = pdfBuildThirdpartyName($thirdparty, $outputlangs);
1777 
1778  $mode = 'target';
1779  $carac_client = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, ($usecontact ? $object->contact : ''), $usecontact, $mode, $object);
1780 
1781  // Show recipient
1782  $widthrecbox = !empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 92 : 100;
1783  if ($this->page_largeur < 210) {
1784  $widthrecbox = 84; // To work with US executive format
1785  }
1786  $posy = !empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 40 : 42;
1787  $posy += $top_shift;
1788  $posx = $this->page_largeur - $this->marge_droite - $widthrecbox;
1789  if (!empty($conf->global->MAIN_INVERT_SENDER_RECIPIENT)) {
1790  $posx = $this->marge_gauche;
1791  }
1792 
1793  // Show recipient frame
1794  if (empty($conf->global->MAIN_PDF_NO_RECIPENT_FRAME)) {
1795  $pdf->SetTextColor(0, 0, 0);
1796  $pdf->SetFont('', '', $default_font_size - 2);
1797  $pdf->SetXY($posx + 2, $posy - 5);
1798  $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillTo"), 0, $ltrdirection);
1799  $pdf->Rect($posx, $posy, $widthrecbox, $hautcadre);
1800  }
1801 
1802  // Show recipient name
1803  $pdf->SetXY($posx + 2, $posy + 3);
1804  $pdf->SetFont('', 'B', $default_font_size);
1805  $pdf->MultiCell($widthrecbox, 2, $carac_client_name, 0, $ltrdirection);
1806 
1807  $posy = $pdf->getY();
1808 
1809  // Show recipient information
1810  $pdf->SetFont('', '', $default_font_size - 1);
1811  $pdf->SetXY($posx + 2, $posy);
1812  $pdf->MultiCell($widthrecbox, 4, $carac_client, 0, $ltrdirection);
1813  }
1814 
1815  $pdf->SetTextColor(0, 0, 0);
1816  return $top_shift;
1817  }
1818 
1819  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1829  protected function _pagefoot(&$pdf, $object, $outputlangs, $hidefreetext = 0)
1830  {
1831  $showdetails = getDolGlobalInt('MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS', 0);
1832  return pdf_pagefoot($pdf, $outputlangs, 'PROPOSAL_FREE_TEXT', $this->emetteur, $this->marge_basse, $this->marge_gauche, $this->page_hauteur, $object, $showdetails, $hidefreetext, $this->page_largeur, $this->watermark);
1833  }
1834 
1844  protected function drawSignatureArea(&$pdf, $object, $posy, $outputlangs)
1845  {
1846  global $conf;
1847  $default_font_size = pdf_getPDFFontSize($outputlangs);
1848  $tab_top = $posy + 4;
1849  $tab_hl = 4;
1850 
1851  $posx = 120;
1852  $largcol = ($this->page_largeur - $this->marge_droite - $posx);
1853  $useborder = 0;
1854  $index = 0;
1855  // Total HT
1856  $pdf->SetFillColor(255, 255, 255);
1857  $pdf->SetXY($posx, $tab_top + 0);
1858  $pdf->SetFont('', '', $default_font_size - 2);
1859  $pdf->MultiCell($largcol, $tab_hl, $outputlangs->transnoentities("ProposalCustomerSignature"), 0, 'L', 1);
1860 
1861  $pdf->SetXY($posx, $tab_top + $tab_hl);
1862  $pdf->MultiCell($largcol, $tab_hl * 3, '', 1, 'R');
1863  if (!empty($conf->global->MAIN_PDF_PROPAL_USE_ELECTRONIC_SIGNING)) {
1864  $pdf->addEmptySignatureAppearance($posx, $tab_top + $tab_hl, $largcol, $tab_hl * 3);
1865  }
1866 
1867  return ($tab_hl * 7);
1868  }
1869 
1870 
1881  public function defineColumnField($object, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0)
1882  {
1883  global $conf, $hookmanager;
1884 
1885  // Default field style for content
1886  $this->defaultContentsFieldsStyle = array(
1887  'align' => 'R', // R,C,L
1888  'padding' => array(1, 0.5, 1, 0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1889  );
1890 
1891  // Default field style for content
1892  $this->defaultTitlesFieldsStyle = array(
1893  'align' => 'C', // R,C,L
1894  'padding' => array(0.5, 0, 0.5, 0), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1895  );
1896 
1897  /*
1898  * For exemple
1899  $this->cols['theColKey'] = array(
1900  'rank' => $rank, // int : use for ordering columns
1901  'width' => 20, // the column width in mm
1902  'title' => array(
1903  'textkey' => 'yourLangKey', // if there is no label, yourLangKey will be translated to replace label
1904  'label' => ' ', // the final label : used fore final generated text
1905  'align' => 'L', // text alignement : R,C,L
1906  'padding' => array(0.5,0.5,0.5,0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1907  ),
1908  'content' => array(
1909  'align' => 'L', // text alignement : R,C,L
1910  'padding' => array(0.5,0.5,0.5,0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1911  ),
1912  );
1913  */
1914 
1915  $rank = 0; // do not use negative rank
1916  $this->cols['desc'] = array(
1917  'rank' => $rank,
1918  'width' => false, // only for desc
1919  'status' => true,
1920  'title' => array(
1921  'textkey' => 'Designation', // use lang key is usefull in somme case with module
1922  'align' => 'L',
1923  // 'textkey' => 'yourLangKey', // if there is no label, yourLangKey will be translated to replace label
1924  // 'label' => ' ', // the final label
1925  'padding' => array(0.5, 0.5, 0.5, 0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1926  ),
1927  'content' => array(
1928  'align' => 'L',
1929  'padding' => array(1, 0.5, 1, 1.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1930  ),
1931  );
1932 
1933  // Image of product
1934  $rank = $rank + 10;
1935  $this->cols['photo'] = array(
1936  'rank' => $rank,
1937  'width' => (empty($conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH) ? 20 : $conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH), // in mm
1938  'status' => false,
1939  'title' => array(
1940  'textkey' => 'Photo',
1941  'label' => ' '
1942  ),
1943  'content' => array(
1944  'padding' => array(0, 0, 0, 0), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1945  ),
1946  'border-left' => false, // remove left line separator
1947  );
1948 
1949  if (!empty($conf->global->MAIN_GENERATE_PROPOSALS_WITH_PICTURE) && !empty($this->atleastonephoto)) {
1950  $this->cols['photo']['status'] = true;
1951  $this->cols['photo']['border-left'] = true;
1952  }
1953 
1954 
1955  $rank = $rank + 10;
1956  $this->cols['vat'] = array(
1957  'rank' => $rank,
1958  'status' => false,
1959  'width' => 16, // in mm
1960  'title' => array(
1961  'textkey' => 'VAT'
1962  ),
1963  'border-left' => true, // add left line separator
1964  );
1965 
1966  if (empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT) && empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_COLUMN)) {
1967  $this->cols['vat']['status'] = true;
1968  }
1969 
1970  $rank = $rank + 10;
1971  $this->cols['subprice'] = array(
1972  'rank' => $rank,
1973  'width' => 19, // in mm
1974  'status' => true,
1975  'title' => array(
1976  'textkey' => 'PriceUHT'
1977  ),
1978  'border-left' => true, // add left line separator
1979  );
1980 
1981  // Adapt dynamically the width of subprice, if text is too long.
1982  $tmpwidth = 0;
1983  $nblines = count($object->lines);
1984  for ($i = 0; $i < $nblines; $i++) {
1985  $tmpwidth2 = dol_strlen(dol_string_nohtmltag(pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails)));
1986  $tmpwidth = max($tmpwidth, $tmpwidth2);
1987  }
1988  if ($tmpwidth > 10) {
1989  $this->cols['subprice']['width'] += (2 * ($tmpwidth - 10));
1990  }
1991 
1992  $rank = $rank + 10;
1993  $this->cols['qty'] = array(
1994  'rank' => $rank,
1995  'width' => 16, // in mm
1996  'status' => true,
1997  'title' => array(
1998  'textkey' => 'Qty'
1999  ),
2000  'border-left' => true, // add left line separator
2001  );
2002 
2003  $rank = $rank + 10;
2004  $this->cols['unit'] = array(
2005  'rank' => $rank,
2006  'width' => 11, // in mm
2007  'status' => false,
2008  'title' => array(
2009  'textkey' => 'Unit'
2010  ),
2011  'border-left' => true, // add left line separator
2012  );
2013  if (!empty($conf->global->PRODUCT_USE_UNITS)) {
2014  $this->cols['unit']['status'] = true;
2015  }
2016 
2017  $rank = $rank + 10;
2018  $this->cols['discount'] = array(
2019  'rank' => $rank,
2020  'width' => 13, // in mm
2021  'status' => false,
2022  'title' => array(
2023  'textkey' => 'ReductionShort'
2024  ),
2025  'border-left' => true, // add left line separator
2026  );
2027  if ($this->atleastonediscount) {
2028  $this->cols['discount']['status'] = true;
2029  }
2030 
2031  $rank = $rank + 1000; // add a big offset to be sure is the last col because default extrafield rank is 100
2032  $this->cols['totalexcltax'] = array(
2033  'rank' => $rank,
2034  'width' => 26, // in mm
2035  'status' => empty($conf->global->PDF_PROPAL_HIDE_PRICE_EXCL_TAX) ? true : false,
2036  'title' => array(
2037  'textkey' => 'TotalHTShort'
2038  ),
2039  'border-left' => true, // add left line separator
2040  );
2041 
2042  $rank = $rank + 1010; // add a big offset to be sure is the last col because default extrafield rank is 100
2043  $this->cols['totalincltax'] = array(
2044  'rank' => $rank,
2045  'width' => 26, // in mm
2046  'status' => empty($conf->global->PDF_PROPAL_SHOW_PRICE_INCL_TAX) ? false : true,
2047  'title' => array(
2048  'textkey' => 'TotalTTCShort'
2049  ),
2050  'border-left' => true, // add left line separator
2051  );
2052 
2053  // Add extrafields cols
2054  if (!empty($object->lines)) {
2055  $line = reset($object->lines);
2056  $this->defineColumnExtrafield($line, $outputlangs, $hidedetails);
2057  }
2058 
2059  $parameters = array(
2060  'object' => $object,
2061  'outputlangs' => $outputlangs,
2062  'hidedetails' => $hidedetails,
2063  'hidedesc' => $hidedesc,
2064  'hideref' => $hideref
2065  );
2066 
2067  $reshook = $hookmanager->executeHooks('defineColumnField', $parameters, $this); // Note that $object may have been modified by hook
2068  if ($reshook < 0) {
2069  setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
2070  } elseif (empty($reshook)) {
2071  $this->cols = array_replace($this->cols, $hookmanager->resArray); // array_replace is used to preserve keys
2072  } else {
2073  $this->cols = $hookmanager->resArray;
2074  }
2075  }
2076 }
Class to manage bank accounts.
prepareArrayColumnField($object, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0)
Prepare Array Column Field.
getColumnStatus($colKey)
get column status from column key
printStdColumnContent($pdf, &$curY, $colKey, $columnText='')
print standard column content
pdfTabTitles(&$pdf, $tab_top, $tab_height, $outputlangs, $hidetop=0)
Print standard column content.
printColDescContent($pdf, &$curY, $colKey, $object, $i, $outputlangs, $hideref=0, $hidedesc=0, $issupplierline=0)
print description column content
getColumnContentXStart($colKey)
get column content X (abscissa) left position from column key
printRect($pdf, $x, $y, $l, $h, $hidetop=0, $hidebottom=0)
Rect pdf.
getExtrafieldContent($object, $extrafieldKey, $outputlangs=null)
get extrafield content for pdf writeHtmlCell compatibility usage for PDF line columns and object note...
defineColumnExtrafield($object, $outputlangs, $hidedetails=0)
Define Array Column Field for extrafields.
Class to manage hooks.
Classe mere des modeles de propale.
Class to manage products or services.
Put here description of your class.
Class to manage translations.
Class to manage Dolibarr users.
Definition: user.class.php:47
Class to generate PDF proposal Cyan.
drawTotalTable(&$pdf, $object, $deja_regle, $posy, $outputlangs, $outputlangsbis=null)
Show total to pay.
defineColumnField($object, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0)
Define Array Column Field.
_tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop=0, $hidebottom=0, $currency='', $outputlangsbis=null)
Show table for lines.
__construct($db)
Constructor.
_pagefoot(&$pdf, $object, $outputlangs, $hidefreetext=0)
Show footer of page.
_pagehead(&$pdf, $object, $showaddress, $outputlangs, $outputlangsbis=null)
Show top header of page.
write_file($object, $outputlangs, $srctemplatepath='', $hidedetails=0, $hidedesc=0, $hideref=0)
Function to build pdf onto disk.
drawSignatureArea(&$pdf, $object, $posy, $outputlangs)
Show area for the customer to sign.
drawInfoTable(&$pdf, $object, $posy, $outputlangs)
Show miscellaneous information (payment mode, payment term, ...)
drawPaymentsTable(&$pdf, $object, $posy, $outputlangs)
Show payments table.
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...
vatrate($rate, $addpercent=false, $info_bits=0, $usestarfornpr=0, $html=0)
Return a string with VAT rate label formated for view output Used into pdf and HTML pages.
dol_string_nohtmltag($stringtoclean, $removelinefeed=1, $pagecodeto='UTF-8', $strip_tags=0, $removedoublespaces=1)
Clean a string from all HTML tags and entities.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='')
Set event messages in dol_events session object.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
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.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
getDolGlobalInt($key, $default=0)
Return dolibarr global constant int value.
dol_getIdFromCode($db, $key, $tablename, $fieldkey='code', $fieldid='id', $entityfilter=0, $filters='')
Return an id or code from a code or id.
getLocalTaxesFromRate($vatrate, $local, $buyer, $seller, $firstparamisid=0)
Get type and rate of localtaxes for a particular vat rate/country of a thirdparty.
dol_concatdesc($text1, $text2, $forxml=false, $invert=false)
Concat 2 descriptions with a new line between them (second operand after first one with appropriate n...
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...
if(!function_exists('utf8_encode')) if(!function_exists('utf8_decode')) getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
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...
isModEnabled($module)
Is Dolibarr module enabled.
get_exdir($num, $level, $alpha, $withoutslash, $object, $modulepart='')
Return a path to have a the directory according to object where files are stored.
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)
if(!defined( 'CSRFCHECK_WITH_TOKEN'))
pdf_getSizeForImage($realpath)
Return dimensions to use for images onto PDF checking that width and height are not higher than maxim...
Definition: pdf.lib.php:2514
pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line total excluding tax.
Definition: pdf.lib.php:2269
pdf_getPDFFontSize($outputlangs)
Return font size to use for PDF generation.
Definition: pdf.lib.php:288
pdf_getFormat(Translate $outputlangs=null, $mode='setup')
Return array with format properties of default PDF format.
Definition: pdf.lib.php:84
pdf_getHeightForLogo($logo, $url=false)
Return height to use for Logo onto PDF.
Definition: pdf.lib.php:313
pdf_getlinetotalwithtax($object, $i, $outputlangs, $hidedetails=0)
Return line total including tax.
Definition: pdf.lib.php:2325
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:1001
pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line unit price excluding tax.
Definition: pdf.lib.php:1886
pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails=0)
Return line vat rate.
Definition: pdf.lib.php:1824
pdf_getlineunit($object, $i, $outputlangs, $hidedetails=0, $hookmanager=false)
Return line unit.
Definition: pdf.lib.php:2132
pdf_getSubstitutionArray($outputlangs, $exclude=null, $object=null, $onlykey=0)
Return array of possible substitutions for PDF content (without external module substitutions).
Definition: pdf.lib.php:749
pdfGetHeightForHtmlContent(&$pdf, $htmlcontent)
Function to try to calculate height of a HTML Content.
Definition: pdf.lib.php:338
pdf_pagehead(&$pdf, $outputlangs, $page_height)
Show header of page for PDF generation.
Definition: pdf.lib.php:723
pdf_writeLinkedObjects(&$pdf, $object, $outputlangs, $posx, $posy, $w, $h, $align, $default_font_size)
Show linked objects for PDF generation.
Definition: pdf.lib.php:1323
pdf_bank(&$pdf, $outputlangs, $curx, $cury, $account, $onlynumber=0, $default_font_size=10)
Show bank informations for PDF generation.
Definition: pdf.lib.php:824
pdf_getPDFFont($outputlangs)
Return font name to use for PDF generation.
Definition: pdf.lib.php:265
pdf_build_address($outputlangs, $sourcecompany, $targetcompany='', $targetcontact='', $usecontact=0, $mode='source', $object=null)
Return a string with full address formated for output on documents.
Definition: pdf.lib.php:434
pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails=0)
Return line remise percent.
Definition: pdf.lib.php:2175
pdf_getlineqty($object, $i, $outputlangs, $hidedetails=0)
Return line quantity.
Definition: pdf.lib.php:1971
pdf_getInstance($format='', $metric='mm', $pagetype='P')
Return a PDF instance object.
Definition: pdf.lib.php:126
pdfBuildThirdpartyName($thirdparty, Translate $outputlangs, $includealias=0)
Returns the name of the thirdparty.
Definition: pdf.lib.php:386
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition: repair.php:119
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition: repair.php:122
$conf db
API class for accounts.
Definition: inc.php:41