dolibarr  19.0.0-dev
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  if (!empty($conf->global->MAIN_PDF_TITLE_TEXT_COLOR)) {
1537  $arrayColorTextTitle = explode(',', $conf->global->MAIN_PDF_TITLE_TEXT_COLOR);
1538  $pdf->SetTextColor($arrayColorTextTitle[0], $arrayColorTextTitle[1], $arrayColorTextTitle[2]);
1539  }
1540 
1541  $this->pdfTabTitles($pdf, $tab_top, $tab_height, $outputlangs, $hidetop);
1542 
1543  if (!empty($conf->global->MAIN_PDF_TITLE_TEXT_COLOR)) {
1544  $pdf->SetTextColor(0, 0, 0);
1545  }
1546 
1547  if (empty($hidetop)) {
1548  $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
1549  }
1550  }
1551 
1552  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1563  protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $outputlangsbis = null)
1564  {
1565  global $conf, $langs;
1566 
1567  $ltrdirection = 'L';
1568  if ($outputlangs->trans("DIRECTION") == 'rtl') $ltrdirection = 'R';
1569 
1570  // Load traductions files required by page
1571  $outputlangs->loadLangs(array("main", "propal", "companies", "bills"));
1572 
1573  $default_font_size = pdf_getPDFFontSize($outputlangs);
1574 
1575  pdf_pagehead($pdf, $outputlangs, $this->page_hauteur);
1576 
1577  $pdf->SetTextColor(0, 0, 60);
1578  $pdf->SetFont('', 'B', $default_font_size + 3);
1579 
1580  $w = 100;
1581 
1582  $posy = $this->marge_haute;
1583  $posx = $this->page_largeur - $this->marge_droite - $w;
1584 
1585  $pdf->SetXY($this->marge_gauche, $posy);
1586 
1587  // Logo
1588  if (!getDolGlobalInt('PDF_DISABLE_MYCOMPANY_LOGO')) {
1589  if ($this->emetteur->logo) {
1590  $logodir = $conf->mycompany->dir_output;
1591  if (!empty($conf->mycompany->multidir_output[$object->entity])) {
1592  $logodir = $conf->mycompany->multidir_output[$object->entity];
1593  }
1594  if (!getDolGlobalInt('MAIN_PDF_USE_LARGE_LOGO')) {
1595  $logo = $logodir.'/logos/thumbs/'.$this->emetteur->logo_small;
1596  } else {
1597  $logo = $logodir.'/logos/'.$this->emetteur->logo;
1598  }
1599  if (is_readable($logo)) {
1600  $height = pdf_getHeightForLogo($logo);
1601  $pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto)
1602  } else {
1603  $pdf->SetTextColor(200, 0, 0);
1604  $pdf->SetFont('', 'B', $default_font_size - 2);
1605  $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound", $logo), 0, 'L');
1606  $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ErrorGoToGlobalSetup"), 0, 'L');
1607  }
1608  } else {
1609  $text = $this->emetteur->name;
1610  $pdf->MultiCell($w, 4, $outputlangs->convToOutputCharset($text), 0, $ltrdirection);
1611  }
1612  }
1613 
1614  $pdf->SetFont('', 'B', $default_font_size + 3);
1615  $pdf->SetXY($posx, $posy);
1616  $pdf->SetTextColor(0, 0, 60);
1617  $title = $outputlangs->transnoentities("PdfCommercialProposalTitle");
1618  $title .= ' '.$outputlangs->convToOutputCharset($object->ref);
1619  if ($object->statut == $object::STATUS_DRAFT) {
1620  $pdf->SetTextColor(128, 0, 0);
1621  $title .= ' - '.$outputlangs->transnoentities("NotValidated");
1622  }
1623 
1624  $pdf->MultiCell($w, 4, $title, '', 'R');
1625 
1626  $pdf->SetFont('', 'B', $default_font_size);
1627 
1628  /*
1629  $posy += 5;
1630  $pdf->SetXY($posx, $posy);
1631  $pdf->SetTextColor(0, 0, 60);
1632  $textref = $outputlangs->transnoentities("Ref")." : ".$outputlangs->convToOutputCharset($object->ref);
1633  if ($object->statut == $object::STATUS_DRAFT) {
1634  $pdf->SetTextColor(128, 0, 0);
1635  $textref .= ' - '.$outputlangs->transnoentities("NotValidated");
1636  }
1637  $pdf->MultiCell($w, 4, $textref, '', 'R');
1638  */
1639 
1640  $posy += 3;
1641  $pdf->SetFont('', '', $default_font_size - 2);
1642 
1643  if ($object->ref_client) {
1644  $posy += 4;
1645  $pdf->SetXY($posx, $posy);
1646  $pdf->SetTextColor(0, 0, 60);
1647  $pdf->MultiCell($w, 3, $outputlangs->transnoentities("RefCustomer")." : ".dol_trunc($outputlangs->convToOutputCharset($object->ref_client), 65), '', 'R');
1648  }
1649 
1650  if (!empty($conf->global->PDF_SHOW_PROJECT_TITLE)) {
1651  $object->fetch_projet();
1652  if (!empty($object->project->ref)) {
1653  $posy += 3;
1654  $pdf->SetXY($posx, $posy);
1655  $pdf->SetTextColor(0, 0, 60);
1656  $pdf->MultiCell($w, 3, $outputlangs->transnoentities("Project")." : ".(empty($object->project->title) ? '' : $object->project->title), '', 'R');
1657  }
1658  }
1659 
1660  if (!empty($conf->global->PDF_SHOW_PROJECT)) {
1661  $object->fetch_projet();
1662  if (!empty($object->project->ref)) {
1663  $outputlangs->load("projects");
1664  $posy += 3;
1665  $pdf->SetXY($posx, $posy);
1666  $pdf->SetTextColor(0, 0, 60);
1667  $pdf->MultiCell($w, 3, $outputlangs->transnoentities("RefProject")." : ".(empty($object->project->ref) ? '' : $object->project->ref), '', 'R');
1668  }
1669  }
1670 
1671  if (!empty($conf->global->MAIN_PDF_DATE_TEXT)) {
1672  $displaydate = "daytext";
1673  } else {
1674  $displaydate = "day";
1675  }
1676 
1677  //$posy += 4;
1678  $posy = $pdf->getY();
1679  $pdf->SetXY($posx, $posy);
1680  $pdf->SetTextColor(0, 0, 60);
1681  $pdf->MultiCell($w, 3, $outputlangs->transnoentities("Date")." : ".dol_print_date($object->date, $displaydate, false, $outputlangs, true), '', 'R');
1682 
1683  $posy += 4;
1684  $pdf->SetXY($posx, $posy);
1685  $pdf->SetTextColor(0, 0, 60);
1686 
1687  $title = $outputlangs->transnoentities("DateEndPropal");
1688  if (!empty($conf->global->PDF_USE_ALSO_LANGUAGE_CODE) && is_object($outputlangsbis)) {
1689  $title .= ' - '.$outputlangsbis->transnoentities("DateEndPropal");
1690  }
1691  $pdf->MultiCell($w, 3, $title." : ".dol_print_date($object->fin_validite, $displaydate, false, $outputlangs, true), '', 'R');
1692 
1693  if (empty($conf->global->MAIN_PDF_HIDE_CUSTOMER_CODE) && $object->thirdparty->code_client) {
1694  $posy += 4;
1695  $pdf->SetXY($posx, $posy);
1696  $pdf->SetTextColor(0, 0, 60);
1697  $pdf->MultiCell($w, 3, $outputlangs->transnoentities("CustomerCode")." : ".$outputlangs->transnoentities($object->thirdparty->code_client), '', 'R');
1698  }
1699 
1700  // Get contact
1701  if (!empty($conf->global->DOC_SHOW_FIRST_SALES_REP)) {
1702  $arrayidcontact = $object->getIdContact('internal', 'SALESREPFOLL');
1703  if (count($arrayidcontact) > 0) {
1704  $usertmp = new User($this->db);
1705  $usertmp->fetch($arrayidcontact[0]);
1706  $posy += 4;
1707  $pdf->SetXY($posx, $posy);
1708  $pdf->SetTextColor(0, 0, 60);
1709  $pdf->MultiCell($w, 3, $langs->transnoentities("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R');
1710  }
1711  }
1712 
1713  $posy += 2;
1714 
1715  $top_shift = 0;
1716  // Show list of linked objects
1717  $current_y = $pdf->getY();
1718  $posy = pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, $w, 3, 'R', $default_font_size);
1719  if ($current_y < $pdf->getY()) {
1720  $top_shift = $pdf->getY() - $current_y;
1721  }
1722 
1723  if ($showaddress) {
1724  // Sender properties
1725  $carac_emetteur = '';
1726  // Add internal contact of object if defined
1727  $arrayidcontact = $object->getIdContact('internal', 'SALESREPFOLL');
1728  if (count($arrayidcontact) > 0) {
1729  $object->fetch_user($arrayidcontact[0]);
1730  $labelbeforecontactname = ($outputlangs->transnoentities("FromContactName") != 'FromContactName' ? $outputlangs->transnoentities("FromContactName") : $outputlangs->transnoentities("Name"));
1731  $carac_emetteur .= ($carac_emetteur ? "\n" : '').$labelbeforecontactname." ".$outputlangs->convToOutputCharset($object->user->getFullName($outputlangs));
1732  $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') || getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ' (' : '';
1733  $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') && !empty($object->user->office_phone)) ? $object->user->office_phone : '';
1734  $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') && getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ', ' : '';
1735  $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT') && !empty($object->user->email)) ? $object->user->email : '';
1736  $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') || getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ')' : '';
1737  $carac_emetteur .= "\n";
1738  }
1739 
1740  $carac_emetteur .= pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, '', 0, 'source', $object);
1741 
1742  // Show sender
1743  $posy = !empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 40 : 42;
1744  $posy += $top_shift;
1745  $posx = $this->marge_gauche;
1746  if (!empty($conf->global->MAIN_INVERT_SENDER_RECIPIENT)) {
1747  $posx = $this->page_largeur - $this->marge_droite - 80;
1748  }
1749 
1750  $hautcadre = !empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 38 : 40;
1751  $widthrecbox = !empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 92 : 82;
1752 
1753  // Show sender frame
1754  if (empty($conf->global->MAIN_PDF_NO_SENDER_FRAME)) {
1755  $pdf->SetTextColor(0, 0, 0);
1756  $pdf->SetFont('', '', $default_font_size - 2);
1757  $pdf->SetXY($posx, $posy - 5);
1758  $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillFrom"), 0, $ltrdirection);
1759  $pdf->SetXY($posx, $posy);
1760  $pdf->SetFillColor(230, 230, 230);
1761  $pdf->MultiCell($widthrecbox, $hautcadre, "", 0, 'R', 1);
1762  $pdf->SetTextColor(0, 0, 60);
1763  }
1764 
1765  // Show sender name
1766  if (empty($conf->global->MAIN_PDF_HIDE_SENDER_NAME)) {
1767  $pdf->SetXY($posx + 2, $posy + 3);
1768  $pdf->SetFont('', 'B', $default_font_size);
1769  $pdf->MultiCell($widthrecbox - 2, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, $ltrdirection);
1770  $posy = $pdf->getY();
1771  }
1772 
1773  // Show sender information
1774  $pdf->SetXY($posx + 2, $posy);
1775  $pdf->SetFont('', '', $default_font_size - 1);
1776  $pdf->MultiCell($widthrecbox - 2, 4, $carac_emetteur, 0, $ltrdirection);
1777 
1778 
1779  // If CUSTOMER contact defined, we use it
1780  $usecontact = false;
1781  $arrayidcontact = $object->getIdContact('external', 'CUSTOMER');
1782  if (count($arrayidcontact) > 0) {
1783  $usecontact = true;
1784  $result = $object->fetch_contact($arrayidcontact[0]);
1785  }
1786 
1787  // Recipient name
1788  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)))) {
1789  $thirdparty = $object->contact;
1790  } else {
1791  $thirdparty = $object->thirdparty;
1792  }
1793 
1794  $carac_client_name = pdfBuildThirdpartyName($thirdparty, $outputlangs);
1795 
1796  $mode = 'target';
1797  $carac_client = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, ($usecontact ? $object->contact : ''), $usecontact, $mode, $object);
1798 
1799  // Show recipient
1800  $widthrecbox = !empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 92 : 100;
1801  if ($this->page_largeur < 210) {
1802  $widthrecbox = 84; // To work with US executive format
1803  }
1804  $posy = !empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 40 : 42;
1805  $posy += $top_shift;
1806  $posx = $this->page_largeur - $this->marge_droite - $widthrecbox;
1807  if (!empty($conf->global->MAIN_INVERT_SENDER_RECIPIENT)) {
1808  $posx = $this->marge_gauche;
1809  }
1810 
1811  // Show recipient frame
1812  if (empty($conf->global->MAIN_PDF_NO_RECIPENT_FRAME)) {
1813  $pdf->SetTextColor(0, 0, 0);
1814  $pdf->SetFont('', '', $default_font_size - 2);
1815  $pdf->SetXY($posx + 2, $posy - 5);
1816  $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillTo"), 0, $ltrdirection);
1817  $pdf->Rect($posx, $posy, $widthrecbox, $hautcadre);
1818  }
1819 
1820  // Show recipient name
1821  $pdf->SetXY($posx + 2, $posy + 3);
1822  $pdf->SetFont('', 'B', $default_font_size);
1823  $pdf->MultiCell($widthrecbox, 2, $carac_client_name, 0, $ltrdirection);
1824 
1825  $posy = $pdf->getY();
1826 
1827  // Show recipient information
1828  $pdf->SetFont('', '', $default_font_size - 1);
1829  $pdf->SetXY($posx + 2, $posy);
1830  $pdf->MultiCell($widthrecbox, 4, $carac_client, 0, $ltrdirection);
1831  }
1832 
1833  $pdf->SetTextColor(0, 0, 0);
1834  return $top_shift;
1835  }
1836 
1837  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1847  protected function _pagefoot(&$pdf, $object, $outputlangs, $hidefreetext = 0)
1848  {
1849  $showdetails = getDolGlobalInt('MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS', 0);
1850  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);
1851  }
1852 
1862  protected function drawSignatureArea(&$pdf, $object, $posy, $outputlangs)
1863  {
1864  global $conf;
1865  $default_font_size = pdf_getPDFFontSize($outputlangs);
1866  $tab_top = $posy + 4;
1867  $tab_hl = 4;
1868 
1869  $posx = 120;
1870  $largcol = ($this->page_largeur - $this->marge_droite - $posx);
1871  $useborder = 0;
1872  $index = 0;
1873  // Total HT
1874  $pdf->SetFillColor(255, 255, 255);
1875  $pdf->SetXY($posx, $tab_top);
1876  $pdf->SetFont('', '', $default_font_size - 2);
1877  $pdf->MultiCell($largcol, $tab_hl, $outputlangs->transnoentities("ProposalCustomerSignature"), 0, 'L', 1);
1878 
1879  $pdf->SetXY($posx, $tab_top + $tab_hl);
1880  $pdf->MultiCell($largcol, $tab_hl * 3, '', 1, 'R');
1881  if (!empty($conf->global->MAIN_PDF_PROPAL_USE_ELECTRONIC_SIGNING)) {
1882  $pdf->addEmptySignatureAppearance($posx, $tab_top + $tab_hl, $largcol, $tab_hl * 3);
1883  }
1884 
1885  return ($tab_hl * 7);
1886  }
1887 
1888 
1899  public function defineColumnField($object, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0)
1900  {
1901  global $conf, $hookmanager;
1902 
1903  // Default field style for content
1904  $this->defaultContentsFieldsStyle = array(
1905  'align' => 'R', // R,C,L
1906  'padding' => array(1, 0.5, 1, 0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1907  );
1908 
1909  // Default field style for content
1910  $this->defaultTitlesFieldsStyle = array(
1911  'align' => 'C', // R,C,L
1912  'padding' => array(0.5, 0, 0.5, 0), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1913  );
1914 
1915  /*
1916  * For exemple
1917  $this->cols['theColKey'] = array(
1918  'rank' => $rank, // int : use for ordering columns
1919  'width' => 20, // the column width in mm
1920  'title' => array(
1921  'textkey' => 'yourLangKey', // if there is no label, yourLangKey will be translated to replace label
1922  'label' => ' ', // the final label : used fore final generated text
1923  'align' => 'L', // text alignement : R,C,L
1924  'padding' => array(0.5,0.5,0.5,0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1925  ),
1926  'content' => array(
1927  'align' => 'L', // text alignement : R,C,L
1928  'padding' => array(0.5,0.5,0.5,0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1929  ),
1930  );
1931  */
1932 
1933  $rank = 0; // do not use negative rank
1934  $this->cols['desc'] = array(
1935  'rank' => $rank,
1936  'width' => false, // only for desc
1937  'status' => true,
1938  'title' => array(
1939  'textkey' => 'Designation', // use lang key is usefull in somme case with module
1940  'align' => 'L',
1941  // 'textkey' => 'yourLangKey', // if there is no label, yourLangKey will be translated to replace label
1942  // 'label' => ' ', // the final label
1943  'padding' => array(0.5, 0.5, 0.5, 0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1944  ),
1945  'content' => array(
1946  'align' => 'L',
1947  'padding' => array(1, 0.5, 1, 1.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1948  ),
1949  );
1950 
1951  // Image of product
1952  $rank = $rank + 10;
1953  $this->cols['photo'] = array(
1954  'rank' => $rank,
1955  'width' => (empty($conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH) ? 20 : $conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH), // in mm
1956  'status' => false,
1957  'title' => array(
1958  'textkey' => 'Photo',
1959  'label' => ' '
1960  ),
1961  'content' => array(
1962  'padding' => array(0, 0, 0, 0), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1963  ),
1964  'border-left' => false, // remove left line separator
1965  );
1966 
1967  if (!empty($conf->global->MAIN_GENERATE_PROPOSALS_WITH_PICTURE) && !empty($this->atleastonephoto)) {
1968  $this->cols['photo']['status'] = true;
1969  $this->cols['photo']['border-left'] = true;
1970  }
1971 
1972 
1973  $rank = $rank + 10;
1974  $this->cols['vat'] = array(
1975  'rank' => $rank,
1976  'status' => false,
1977  'width' => 16, // in mm
1978  'title' => array(
1979  'textkey' => 'VAT'
1980  ),
1981  'border-left' => true, // add left line separator
1982  );
1983 
1984  if (empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT) && empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_COLUMN)) {
1985  $this->cols['vat']['status'] = true;
1986  }
1987 
1988  $rank = $rank + 10;
1989  $this->cols['subprice'] = array(
1990  'rank' => $rank,
1991  'width' => 19, // in mm
1992  'status' => true,
1993  'title' => array(
1994  'textkey' => 'PriceUHT'
1995  ),
1996  'border-left' => true, // add left line separator
1997  );
1998 
1999  // Adapt dynamically the width of subprice, if text is too long.
2000  $tmpwidth = 0;
2001  $nblines = count($object->lines);
2002  for ($i = 0; $i < $nblines; $i++) {
2003  $tmpwidth2 = dol_strlen(dol_string_nohtmltag(pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails)));
2004  $tmpwidth = max($tmpwidth, $tmpwidth2);
2005  }
2006  if ($tmpwidth > 10) {
2007  $this->cols['subprice']['width'] += (2 * ($tmpwidth - 10));
2008  }
2009 
2010  $rank = $rank + 10;
2011  $this->cols['qty'] = array(
2012  'rank' => $rank,
2013  'width' => 16, // in mm
2014  'status' => true,
2015  'title' => array(
2016  'textkey' => 'Qty'
2017  ),
2018  'border-left' => true, // add left line separator
2019  );
2020 
2021  $rank = $rank + 10;
2022  $this->cols['unit'] = array(
2023  'rank' => $rank,
2024  'width' => 11, // in mm
2025  'status' => false,
2026  'title' => array(
2027  'textkey' => 'Unit'
2028  ),
2029  'border-left' => true, // add left line separator
2030  );
2031  if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
2032  $this->cols['unit']['status'] = true;
2033  }
2034 
2035  $rank = $rank + 10;
2036  $this->cols['discount'] = array(
2037  'rank' => $rank,
2038  'width' => 13, // in mm
2039  'status' => false,
2040  'title' => array(
2041  'textkey' => 'ReductionShort'
2042  ),
2043  'border-left' => true, // add left line separator
2044  );
2045  if ($this->atleastonediscount) {
2046  $this->cols['discount']['status'] = true;
2047  }
2048 
2049  $rank = $rank + 1000; // add a big offset to be sure is the last col because default extrafield rank is 100
2050  $this->cols['totalexcltax'] = array(
2051  'rank' => $rank,
2052  'width' => 26, // in mm
2053  'status' => empty($conf->global->PDF_PROPAL_HIDE_PRICE_EXCL_TAX) ? true : false,
2054  'title' => array(
2055  'textkey' => 'TotalHTShort'
2056  ),
2057  'border-left' => true, // add left line separator
2058  );
2059 
2060  $rank = $rank + 1010; // add a big offset to be sure is the last col because default extrafield rank is 100
2061  $this->cols['totalincltax'] = array(
2062  'rank' => $rank,
2063  'width' => 26, // in mm
2064  'status' => empty($conf->global->PDF_PROPAL_SHOW_PRICE_INCL_TAX) ? false : true,
2065  'title' => array(
2066  'textkey' => 'TotalTTCShort'
2067  ),
2068  'border-left' => true, // add left line separator
2069  );
2070 
2071  // Add extrafields cols
2072  if (!empty($object->lines)) {
2073  $line = reset($object->lines);
2074  $this->defineColumnExtrafield($line, $outputlangs, $hidedetails);
2075  }
2076 
2077  $parameters = array(
2078  'object' => $object,
2079  'outputlangs' => $outputlangs,
2080  'hidedetails' => $hidedetails,
2081  'hidedesc' => $hidedesc,
2082  'hideref' => $hideref
2083  );
2084 
2085  $reshook = $hookmanager->executeHooks('defineColumnField', $parameters, $this); // Note that $object may have been modified by hook
2086  if ($reshook < 0) {
2087  setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
2088  } elseif (empty($reshook)) {
2089  $this->cols = array_replace($this->cols, $hookmanager->resArray); // array_replace is used to preserve keys
2090  } else {
2091  $this->cols = $hookmanager->resArray;
2092  }
2093  }
2094 }
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:48
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.
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).
dolChmod($filepath, $newmask='')
Change mod of a file.
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...
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
dol_htmlentitiesbr($stringtoencode, $nl2brmode=0, $pagecodefrom='UTF-8', $removelasteolbr=1)
This function is called to encode a string into a HTML string but differs from htmlentities because a...
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
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:2520
pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line total excluding tax.
Definition: pdf.lib.php:2275
pdf_getPDFFontSize($outputlangs)
Return font size to use for PDF generation.
Definition: pdf.lib.php:289
pdf_getFormat(Translate $outputlangs=null, $mode='setup')
Return array with format properties of default PDF format.
Definition: pdf.lib.php:85
pdf_getHeightForLogo($logo, $url=false)
Return height to use for Logo onto PDF.
Definition: pdf.lib.php:314
pdf_getlinetotalwithtax($object, $i, $outputlangs, $hidedetails=0)
Return line total including tax.
Definition: pdf.lib.php:2331
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_getlineupexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line unit price excluding tax.
Definition: pdf.lib.php:1892
pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails=0)
Return line vat rate.
Definition: pdf.lib.php:1830
pdf_getlineunit($object, $i, $outputlangs, $hidedetails=0, $hookmanager=false)
Return line unit.
Definition: pdf.lib.php:2138
pdfGetHeightForHtmlContent(&$pdf, $htmlcontent)
Function to try to calculate height of a HTML Content.
Definition: pdf.lib.php:339
pdf_pagehead(&$pdf, $outputlangs, $page_height)
Show header of page for PDF generation.
Definition: pdf.lib.php:721
pdf_writeLinkedObjects(&$pdf, $object, $outputlangs, $posx, $posy, $w, $h, $align, $default_font_size)
Show linked objects for PDF generation.
Definition: pdf.lib.php:1333
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_getPDFFont($outputlangs)
Return font name to use for PDF generation.
Definition: pdf.lib.php:266
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
pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails=0)
Return line remise percent.
Definition: pdf.lib.php:2181
pdf_getlineqty($object, $i, $outputlangs, $hidedetails=0)
Return line quantity.
Definition: pdf.lib.php:1977
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
pdf_getInstance($format='', $metric='mm', $pagetype='P')
Return a PDF instance object.
Definition: pdf.lib.php:127
pdfBuildThirdpartyName($thirdparty, Translate $outputlangs, $includealias=0)
Returns the name of the thirdparty.
Definition: pdf.lib.php:387
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition: repair.php:120
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition: repair.php:123