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