dolibarr  20.0.0-beta
pdf_zenith.modules.php
1 <?php
2 /* Copyright (C) 2004-2014 Laurent Destailleur <eldy@users.sourceforge.net>
3  * Copyright (C) 2005-2011 Regis Houssin <regis.houssin@inodbox.com>
4  * Copyright (C) 2007 Franky Van Liedekerke <franky.van.liedekerke@telenet.be>
5  * Copyright (C) 2010-2014 Juanjo Menent <jmenent@2byte.es>
6  * Copyright (C) 2015 Marcos García <marcosgdf@gmail.com>
7  * Copyright (C) 2017 Ferran Marcet <fmarcet@2byte.es>
8  * Copyright (C) 2018-2024 Frédéric France <frederic.france@free.fr>
9  * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 3 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program. If not, see <https://www.gnu.org/licenses/>.
23  * or see https://www.gnu.org/
24  */
25 
32 require_once DOL_DOCUMENT_ROOT.'/core/modules/supplier_proposal/modules_supplier_proposal.php';
33 require_once DOL_DOCUMENT_ROOT.'/supplier_proposal/class/supplier_proposal.class.php';
34 require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
35 require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
36 require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
37 require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
38 
39 
44 {
48  public $db;
49 
53  public $name;
54 
58  public $description;
59 
63  public $update_main_doc_field;
64 
68  public $type;
69 
74  public $version = 'dolibarr';
75 
76 
82  public function __construct($db)
83  {
84  global $conf, $langs, $mysoc;
85 
86  // Load translation files required by the page
87  $langs->loadLangs(array("main", "bills"));
88 
89  $this->db = $db;
90  $this->name = "zenith";
91  $this->description = $langs->trans('DocModelZenithDescription');
92  $this->update_main_doc_field = 1; // Save the name of generated file as the main doc when generating a doc with this template
93 
94  // Page size for A4 format
95  $this->type = 'pdf';
96  $formatarray = pdf_getFormat();
97  $this->page_largeur = $formatarray['width'];
98  $this->page_hauteur = $formatarray['height'];
99  $this->format = array($this->page_largeur, $this->page_hauteur);
100  $this->marge_gauche = getDolGlobalInt('MAIN_PDF_MARGIN_LEFT', 10);
101  $this->marge_droite = getDolGlobalInt('MAIN_PDF_MARGIN_RIGHT', 10);
102  $this->marge_haute = getDolGlobalInt('MAIN_PDF_MARGIN_TOP', 10);
103  $this->marge_basse = getDolGlobalInt('MAIN_PDF_MARGIN_BOTTOM', 10);
104 
105  $this->option_logo = 1; // Display logo
106  $this->option_tva = 1; // Manage the vat option FACTURE_TVAOPTION
107  $this->option_modereg = 1; // Display payment mode
108  $this->option_condreg = 1; // Display payment terms
109  $this->option_multilang = 1; //Available in several languages
110  $this->option_escompte = 0; // Displays if there has been a discount
111  $this->option_credit_note = 0; // Support credit notes
112  $this->option_freetext = 1; // Support add of a personalised text
113  $this->option_draft_watermark = 1; // Support add of a watermark on drafts
114 
115  // Get source company
116  $this->emetteur = $mysoc;
117  if (empty($this->emetteur->country_code)) {
118  $this->emetteur->country_code = substr($langs->defaultlang, -2); // By default, if was not defined
119  }
120 
121  // Define position of columns
122  $this->posxdesc = $this->marge_gauche + 1; // For module retrocompatibility support during PDF transition: TODO remove this at the end
123 
124  $this->tabTitleHeight = 5; // default height
125 
126  $this->tva = array();
127  $this->tva_array = array();
128  $this->localtax1 = array();
129  $this->localtax2 = array();
130  $this->atleastoneratenotnull = 0;
131  $this->atleastonediscount = 0;
132  }
133 
134 
135  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
147  public function write_file($object, $outputlangs = null, $srctemplatepath = '', $hidedetails = 0, $hidedesc = 0, $hideref = 0)
148  {
149  // phpcs:enable
150  global $user, $langs, $conf, $hookmanager, $mysoc, $nblines;
151 
152  if (!is_object($outputlangs)) {
153  $outputlangs = $langs;
154  }
155  // For backward compatibility with FPDF, force output charset to ISO, because FPDF expect text to be encoded in ISO
156  if (getDolGlobalString('MAIN_USE_FPDF')) {
157  $outputlangs->charset_output = 'ISO-8859-1';
158  }
159 
160  // Load translation files required by the page
161  $outputlangs->loadLangs(array("main", "supplier_proposal", "companies", "bills", "dict", "products"));
162 
163  global $outputlangsbis;
164  $outputlangsbis = null;
165  if (getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE') && $outputlangs->defaultlang != getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE')) {
166  $outputlangsbis = new Translate('', $conf);
167  $outputlangsbis->setDefaultLang(getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE'));
168  $outputlangsbis->loadLangs(array("main", "supplier_proposal", "companies", "bills", "dict", "products"));
169  }
170 
171  $nblines = count($object->lines);
172 
173  $hidetop = 0;
174  if (getDolGlobalString('MAIN_PDF_DISABLE_COL_HEAD_TITLE')) {
175  $hidetop = getDolGlobalString('MAIN_PDF_DISABLE_COL_HEAD_TITLE');
176  }
177 
178  // Loop on each lines to detect if there is at least one image to show
179  $realpatharray = array();
180  if (getDolGlobalString('MAIN_GENERATE_SUPPLIER_PROPOSAL_WITH_PICTURE')) {
181  for ($i = 0; $i < $nblines; $i++) {
182  if (empty($object->lines[$i]->fk_product)) {
183  continue;
184  }
185 
186  $objphoto = new Product($this->db);
187  $objphoto->fetch($object->lines[$i]->fk_product);
188 
189  if (getDolGlobalInt('PRODUCT_USE_OLD_PATH_FOR_PHOTO')) {
190  $pdir = get_exdir($objphoto->id, 2, 0, 0, $objphoto, 'product').$object->lines[$i]->fk_product."/photos/";
191  $dir = $conf->product->dir_output.'/'.$pdir;
192  } else {
193  $pdir = get_exdir($objphoto->id, 0, 0, 0, $objphoto, 'product');
194  $dir = $conf->product->dir_output.'/'.$pdir;
195  }
196 
197  $realpath = '';
198  foreach ($objphoto->liste_photos($dir, 1) as $key => $obj) {
199  if (!getDolGlobalInt('CAT_HIGH_QUALITY_IMAGES')) { // If CAT_HIGH_QUALITY_IMAGES not defined, we use thumb if defined and then original photo
200  if ($obj['photo_vignette']) {
201  $filename = $obj['photo_vignette'];
202  } else {
203  $filename = $obj['photo'];
204  }
205  } else {
206  $filename = $obj['photo'];
207  }
208  $realpath = $dir.$filename;
209  break;
210  }
211 
212  if ($realpath) {
213  $realpatharray[$i] = $realpath;
214  }
215  }
216  }
217  if (count($realpatharray) == 0) {
218  $this->posxpicture = $this->posxtva;
219  }
220 
221  if ($conf->supplier_proposal->dir_output) {
222  $object->fetch_thirdparty();
223 
224  $deja_regle = 0;
225  $amount_credit_notes_included = 0;
226  $amount_deposits_included = 0;
227  //$amount_credit_notes_included = $object->getSumCreditNotesUsed();
228  //$amount_deposits_included = $object->getSumDepositsUsed();
229 
230  // Definition of $dir and $file
231  if ($object->specimen) {
232  $dir = $conf->supplier_proposal->dir_output;
233  $file = $dir."/SPECIMEN.pdf";
234  } else {
235  $objectref = dol_sanitizeFileName($object->ref);
236  $objectrefsupplier = dol_sanitizeFileName($object->ref_supplier);
237  $dir = $conf->supplier_proposal->dir_output.'/'.$objectref;
238  $file = $dir."/".$objectref.".pdf";
239  if (getDolGlobalString('SUPPLIER_REF_IN_NAME')) {
240  $file = $dir."/".$objectref.($objectrefsupplier ? "_".$objectrefsupplier : "").".pdf";
241  }
242  }
243 
244  if (!file_exists($dir)) {
245  if (dol_mkdir($dir) < 0) {
246  $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
247  return 0;
248  }
249  }
250 
251  if (file_exists($dir)) {
252  // Add pdfgeneration hook
253  if (!is_object($hookmanager)) {
254  include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
255  $hookmanager = new HookManager($this->db);
256  }
257  $hookmanager->initHooks(array('pdfgeneration'));
258  $parameters = array('file' => $file, 'object' => $object, 'outputlangs' => $outputlangs);
259  global $action;
260  $reshook = $hookmanager->executeHooks('beforePDFCreation', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
261 
262  $nblines = count($object->lines);
263 
264  $pdf = pdf_getInstance($this->format);
265  $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance
266  $heightforinfotot = 50; // Height reserved to output the info and total part
267  $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
268  $heightforfooter = $this->marge_basse + 8; // Height reserved to output the footer (value include bottom margin)
269  if (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS')) {
270  $heightforfooter += 6;
271  }
272  $pdf->SetAutoPageBreak(1, 0);
273 
274  if (class_exists('TCPDF')) {
275  $pdf->setPrintHeader(false);
276  $pdf->setPrintFooter(false);
277  }
278  $pdf->SetFont(pdf_getPDFFont($outputlangs));
279  // Set path to the background PDF File
280  if (getDolGlobalString('MAIN_ADD_PDF_BACKGROUND')) {
281  $pagecount = $pdf->setSourceFile($conf->mycompany->dir_output.'/' . getDolGlobalString('MAIN_ADD_PDF_BACKGROUND'));
282  $tplidx = $pdf->importPage(1);
283  }
284 
285  $pdf->Open();
286  $pagenb = 0;
287  $pdf->SetDrawColor(128, 128, 128);
288 
289  $pdf->SetTitle($outputlangs->convToOutputCharset($object->ref));
290  $pdf->SetSubject($outputlangs->transnoentities("SupplierProposal"));
291  $pdf->SetCreator("Dolibarr ".DOL_VERSION);
292  $pdf->SetAuthor($outputlangs->convToOutputCharset($user->getFullName($outputlangs)));
293  $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("SupplierProposal")." ".$outputlangs->convToOutputCharset($object->thirdparty->name));
294  if (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) {
295  $pdf->SetCompression(false);
296  }
297 
298  // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
299  $pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite); // Left, Top, Right
300 
301  // Does we have at least one line with discount $this->atleastonediscount
302  foreach ($object->lines as $line) {
303  if ($line->remise_percent) {
304  $this->atleastonediscount = true;
305  break;
306  }
307  }
308 
309  // New page
310  $pdf->AddPage();
311  if (!empty($tplidx)) {
312  $pdf->useTemplate($tplidx);
313  }
314  $pagenb++;
315  $top_shift = $this->_pagehead($pdf, $object, 1, $outputlangs);
316  $pdf->SetFont('', '', $default_font_size - 1);
317  $pdf->MultiCell(0, 3, ''); // Set interline to 3
318  $pdf->SetTextColor(0, 0, 0);
319 
320  $tab_top = 90 + $top_shift;
321  $tab_top_newpage = (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD') ? 42 + $top_shift : 10);
322 
323  $tab_height = $this->page_hauteur - $tab_top - $heightforfooter - $heightforfreetext;
324 
325  // Incoterm
326  if (isModEnabled('incoterm')) {
327  $desc_incoterms = $object->getIncotermsForPDF();
328  if ($desc_incoterms) {
329  $tab_top -= 2;
330 
331  $pdf->SetFont('', '', $default_font_size - 1);
332  $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top - 1, dol_htmlentitiesbr($desc_incoterms), 0, 1);
333  $nexY = $pdf->GetY();
334  $height_incoterms = $nexY - $tab_top;
335 
336  // Rect takes a length in 3rd parameter
337  $pdf->SetDrawColor(192, 192, 192);
338  $pdf->Rect($this->marge_gauche, $tab_top - 1, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $height_incoterms + 1);
339 
340  $tab_top = $nexY + 6;
341  }
342  }
343 
344  // Affiche notes
345  $notetoshow = empty($object->note_public) ? '' : $object->note_public;
346 
347  // Extrafields in note
348  $extranote = $this->getExtrafieldsInHtml($object, $outputlangs);
349  if (!empty($extranote)) {
350  $notetoshow = dol_concatdesc($notetoshow, $extranote);
351  }
352 
353  $pagenb = $pdf->getPage();
354  if ($notetoshow) {
355  $tab_width = $this->page_largeur - $this->marge_gauche - $this->marge_droite;
356  $pageposbeforenote = $pagenb;
357 
358  $substitutionarray = pdf_getSubstitutionArray($outputlangs, null, $object);
359  complete_substitutions_array($substitutionarray, $outputlangs, $object);
360  $notetoshow = make_substitutions($notetoshow, $substitutionarray, $outputlangs);
361  $notetoshow = convertBackOfficeMediasLinksToPublicLinks($notetoshow);
362 
363  $tab_top -= 2;
364 
365  $pdf->startTransaction();
366 
367  $pdf->SetFont('', '', $default_font_size - 1);
368  $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top, dol_htmlentitiesbr($notetoshow), 0, 1);
369  // Description
370  $pageposafternote = $pdf->getPage();
371  $posyafter = $pdf->GetY();
372 
373  if ($pageposafternote > $pageposbeforenote) {
374  $pdf->rollbackTransaction(true);
375 
376  // prepar pages to receive notes
377  while ($pagenb < $pageposafternote) {
378  $pdf->AddPage();
379  $pagenb++;
380  if (!empty($tplidx)) {
381  $pdf->useTemplate($tplidx);
382  }
383  if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
384  $this->_pagehead($pdf, $object, 0, $outputlangs);
385  }
386  // $this->_pagefoot($pdf,$object,$outputlangs,1);
387  $pdf->setTopMargin($tab_top_newpage);
388  // The only function to edit the bottom margin of current page to set it.
389  $pdf->setPageOrientation('', 1, $heightforfooter + $heightforfreetext);
390  }
391 
392  // back to start
393  $pdf->setPage($pageposbeforenote);
394  $pdf->setPageOrientation('', 1, $heightforfooter + $heightforfreetext);
395  $pdf->SetFont('', '', $default_font_size - 1);
396  $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top, dol_htmlentitiesbr($notetoshow), 0, 1);
397  $pageposafternote = $pdf->getPage();
398 
399  $posyafter = $pdf->GetY();
400 
401  if ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + 20))) { // There is no space left for total+free text
402  $pdf->AddPage('', '', true);
403  $pagenb++;
404  $pageposafternote++;
405  $pdf->setPage($pageposafternote);
406  $pdf->setTopMargin($tab_top_newpage);
407  // The only function to edit the bottom margin of current page to set it.
408  $pdf->setPageOrientation('', 1, $heightforfooter + $heightforfreetext);
409  //$posyafter = $tab_top_newpage;
410  }
411 
412 
413  // apply note frame to previous pages
414  $i = $pageposbeforenote;
415  while ($i < $pageposafternote) {
416  $pdf->setPage($i);
417 
418 
419  $pdf->SetDrawColor(128, 128, 128);
420  // Draw note frame
421  if ($i > $pageposbeforenote) {
422  $height_note = $this->page_hauteur - ($tab_top_newpage + $heightforfooter);
423  $pdf->Rect($this->marge_gauche, $tab_top_newpage - 1, $tab_width, $height_note + 1);
424  } else {
425  $height_note = $this->page_hauteur - ($tab_top + $heightforfooter);
426  $pdf->Rect($this->marge_gauche, $tab_top - 1, $tab_width, $height_note + 1);
427  }
428 
429  // Add footer
430  $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it.
431  $this->_pagefoot($pdf, $object, $outputlangs, 1);
432 
433  $i++;
434  }
435 
436  // apply note frame to last page
437  $pdf->setPage($pageposafternote);
438  if (!empty($tplidx)) {
439  $pdf->useTemplate($tplidx);
440  }
441  if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
442  $this->_pagehead($pdf, $object, 0, $outputlangs);
443  }
444  $height_note = $posyafter - $tab_top_newpage;
445  $pdf->Rect($this->marge_gauche, $tab_top_newpage - 1, $tab_width, $height_note + 1);
446  } else {
447  // No pagebreak
448  $pdf->commitTransaction();
449  $posyafter = $pdf->GetY();
450  $height_note = $posyafter - $tab_top;
451  $pdf->Rect($this->marge_gauche, $tab_top - 1, $tab_width, $height_note + 1);
452 
453 
454  if ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + 20))) {
455  // not enough space, need to add page
456  $pdf->AddPage('', '', true);
457  $pagenb++;
458  $pageposafternote++;
459  $pdf->setPage($pageposafternote);
460  if (!empty($tplidx)) {
461  $pdf->useTemplate($tplidx);
462  }
463  if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
464  $this->_pagehead($pdf, $object, 0, $outputlangs);
465  }
466 
467  $posyafter = $tab_top_newpage;
468  }
469  }
470 
471  $tab_height = $tab_height - $height_note;
472  $tab_top = $posyafter + 6;
473  } else {
474  $height_note = 0;
475  }
476 
477  // Use new auto column system
478  $this->prepareArrayColumnField($object, $outputlangs, $hidedetails, $hidedesc, $hideref);
479 
480  $nexY = $tab_top + $this->tabTitleHeight;
481 
482  // Loop on each lines
483  $pageposbeforeprintlines = $pdf->getPage();
484  $pagenb = $pageposbeforeprintlines;
485  for ($i = 0; $i < $nblines; $i++) {
486  $curY = $nexY;
487  $pdf->SetFont('', '', $default_font_size - 1); // Into loop to work with multipage
488  $pdf->SetTextColor(0, 0, 0);
489 
490  // Define size of image if we need it
491  $imglinesize = array();
492  if (!empty($realpatharray[$i])) {
493  $imglinesize = pdf_getSizeForImage($realpatharray[$i]);
494  }
495 
496  $pdf->setTopMargin($tab_top_newpage);
497  $pdf->setPageOrientation('', 1, $heightforfooter + $heightforfreetext + $heightforinfotot); // The only function to edit the bottom margin of current page to set it.
498  $pageposbefore = $pdf->getPage();
499 
500  $showpricebeforepagebreak = 1;
501  $posYAfterImage = 0;
502  $posYAfterDescription = 0;
503 
504  // We start with Photo of product line
505  if ($this->getColumnStatus('photo')) {
506  // We start with Photo of product line
507  if (isset($imglinesize['width']) && isset($imglinesize['height']) && ($curY + $imglinesize['height']) > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforinfotot))) { // If photo too high, we moved completely on new page
508  $pdf->AddPage('', '', true);
509  if (!empty($tplidx)) {
510  $pdf->useTemplate($tplidx);
511  }
512  $pdf->setPage($pageposbefore + 1);
513 
514  $curY = $tab_top_newpage;
515 
516  // Allows data in the first page if description is long enough to break in multiples pages
517  if (getDolGlobalString('MAIN_PDF_DATA_ON_FIRST_PAGE')) {
518  $showpricebeforepagebreak = 1;
519  } else {
520  $showpricebeforepagebreak = 0;
521  }
522  }
523 
524  if (!empty($this->cols['photo']) && isset($imglinesize['width']) && isset($imglinesize['height'])) {
525  $pdf->Image($realpatharray[$i], $this->getColumnContentXStart('photo'), $curY + 1, $imglinesize['width'], $imglinesize['height'], '', '', '', 2, 300); // Use 300 dpi
526  // $pdf->Image does not increase value return by getY, so we save it manually
527  $posYAfterImage = $curY + $imglinesize['height'];
528  }
529  }
530  // Description of product line
531  $curX = $this->posxdesc - 1;
532  $showpricebeforepagebreak = 1;
533 
534  if ($this->getColumnStatus('desc')) {
535  $pdf->startTransaction();
536  $this->printColDescContent($pdf, $curY, 'desc', $object, $i, $outputlangs, $hideref, $hidedesc, 1);
537 
538  $pageposafter = $pdf->getPage();
539  if ($pageposafter > $pageposbefore) { // There is a pagebreak
540  $pdf->rollbackTransaction(true);
541 
542  $this->printColDescContent($pdf, $curY, 'desc', $object, $i, $outputlangs, $hideref, $hidedesc, 1);
543 
544  $pageposafter = $pdf->getPage();
545  $posyafter = $pdf->GetY();
546  if ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforinfotot))) { // There is no space left for total+free text
547  if ($i == ($nblines - 1)) { // No more lines, and no space left to show total, so we create a new page
548  $pdf->AddPage('', '', true);
549  if (!empty($tplidx)) {
550  $pdf->useTemplate($tplidx);
551  }
552  //if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) $this->_pagehead($pdf, $object, 0, $outputlangs);
553  $pdf->setPage($pageposafter + 1);
554  }
555  } else {
556  // We found a page break
557  // Allows data in the first page if description is long enough to break in multiples pages
558  if (getDolGlobalString('MAIN_PDF_DATA_ON_FIRST_PAGE')) {
559  $showpricebeforepagebreak = 1;
560  } else {
561  $showpricebeforepagebreak = 0;
562  }
563  }
564  } else { // No pagebreak
565  $pdf->commitTransaction();
566  }
567  $posYAfterDescription = $pdf->GetY();
568  }
569 
570  $nexY = $pdf->GetY();
571  $pageposafter = $pdf->getPage();
572  $pdf->setPage($pageposbefore);
573  $pdf->setTopMargin($this->marge_haute);
574  $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it.
575 
576  // We suppose that a too long description is moved completely on next page
577  if ($pageposafter > $pageposbefore && empty($showpricebeforepagebreak)) {
578  $pdf->setPage($pageposafter);
579  $curY = $tab_top_newpage;
580  }
581 
582  $pdf->SetFont('', '', $default_font_size - 1); // On repositionne la police par default
583 
584  // VAT Rate
585  if ($this->getColumnStatus('vat')) {
586  $vat_rate = pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails);
587  $this->printStdColumnContent($pdf, $curY, 'vat', $vat_rate);
588  $nexY = max($pdf->GetY(), $nexY);
589  }
590 
591  // Unit price before discount
592  if ($this->getColumnStatus('subprice')) {
593  $up_excl_tax = pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails);
594  $this->printStdColumnContent($pdf, $curY, 'subprice', $up_excl_tax);
595  $nexY = max($pdf->GetY(), $nexY);
596  }
597 
598  // Quantity
599  // Enough for 6 chars
600  if ($this->getColumnStatus('qty')) {
601  $qty = pdf_getlineqty($object, $i, $outputlangs, $hidedetails);
602  $this->printStdColumnContent($pdf, $curY, 'qty', $qty);
603  $nexY = max($pdf->GetY(), $nexY);
604  }
605 
606 
607  // Unit
608  if ($this->getColumnStatus('unit')) {
609  $unit = pdf_getlineunit($object, $i, $outputlangs, $hidedetails);
610  $this->printStdColumnContent($pdf, $curY, 'unit', $unit);
611  $nexY = max($pdf->GetY(), $nexY);
612  }
613 
614  // Discount on line
615  if ($this->getColumnStatus('discount') && $object->lines[$i]->remise_percent) {
616  $remise_percent = pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails);
617  $this->printStdColumnContent($pdf, $curY, 'discount', $remise_percent);
618  $nexY = max($pdf->GetY(), $nexY);
619  }
620 
621  // Total HT line
622  if ($this->getColumnStatus('totalexcltax')) {
623  $total_excl_tax = pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails);
624  $this->printStdColumnContent($pdf, $curY, 'totalexcltax', $total_excl_tax);
625  $nexY = max($pdf->GetY(), $nexY);
626  }
627 
628  // Extrafields
629  if (!empty($object->lines[$i]->array_options)) {
630  foreach ($object->lines[$i]->array_options as $extrafieldColKey => $extrafieldValue) {
631  if ($this->getColumnStatus($extrafieldColKey)) {
632  $extrafieldValue = $this->getExtrafieldContent($object->lines[$i], $extrafieldColKey, $outputlangs);
633  $this->printStdColumnContent($pdf, $curY, $extrafieldColKey, $extrafieldValue);
634  $nexY = max($pdf->GetY(), $nexY);
635  }
636  }
637  }
638 
639  $parameters = array(
640  'object' => $object,
641  'i' => $i,
642  'pdf' => & $pdf,
643  'curY' => & $curY,
644  'nexY' => & $nexY,
645  'outputlangs' => $outputlangs,
646  'hidedetails' => $hidedetails
647  );
648  $reshook = $hookmanager->executeHooks('printPDFline', $parameters, $this); // Note that $object may have been modified by hook
649 
650 
651  // Collecte des totaux par valeur de tva dans $this->tva["taux"]=total_tva
652  if (isModEnabled("multicurrency") && $object->multicurrency_tx != 1) {
653  $tvaligne = $object->lines[$i]->multicurrency_total_tva;
654  } else {
655  $tvaligne = $object->lines[$i]->total_tva;
656  }
657 
658  $localtax1ligne = $object->lines[$i]->total_localtax1;
659  $localtax2ligne = $object->lines[$i]->total_localtax2;
660  $localtax1_rate = $object->lines[$i]->localtax1_tx;
661  $localtax2_rate = $object->lines[$i]->localtax2_tx;
662  $localtax1_type = $object->lines[$i]->localtax1_type;
663  $localtax2_type = $object->lines[$i]->localtax2_type;
664 
665  // TODO remise_percent is an obsolete field for object parent
666  /*if (!empty($object->remise_percent)) {
667  $tvaligne -= ($tvaligne * $object->remise_percent) / 100;
668  }
669  if (!empty($object->remise_percent)) {
670  $localtax1ligne -= ($localtax1ligne * $object->remise_percent) / 100;
671  }
672  if (!empty($object->remise_percent)) {
673  $localtax2ligne -= ($localtax2ligne * $object->remise_percent) / 100;
674  }*/
675 
676  $vatrate = (string) $object->lines[$i]->tva_tx;
677 
678  // Retrieve type from database for backward compatibility with old records
679  if ((!isset($localtax1_type) || $localtax1_type == '' || !isset($localtax2_type) || $localtax2_type == '') // if tax type not defined
680  && (!empty($localtax1_rate) || !empty($localtax2_rate))) { // and there is local tax
681  $localtaxtmp_array = getLocalTaxesFromRate($vatrate, 0, $mysoc, $object->thirdparty);
682  $localtax1_type = isset($localtaxtmp_array[0]) ? $localtaxtmp_array[0] : '';
683  $localtax2_type = isset($localtaxtmp_array[2]) ? $localtaxtmp_array[2] : '';
684  }
685 
686  // retrieve global local tax
687  if ($localtax1_type && $localtax1ligne != 0) {
688  if (empty($this->localtax1[$localtax1_type][$localtax1_rate])) {
689  $this->localtax1[$localtax1_type][$localtax1_rate] = $localtax1ligne;
690  } else {
691  $this->localtax1[$localtax1_type][$localtax1_rate] += $localtax1ligne;
692  }
693  }
694  if ($localtax2_type && $localtax2ligne != 0) {
695  if (empty($this->localtax2[$localtax2_type][$localtax2_rate])) {
696  $this->localtax2[$localtax2_type][$localtax2_rate] = $localtax2ligne;
697  } else {
698  $this->localtax2[$localtax2_type][$localtax2_rate] += $localtax2ligne;
699  }
700  }
701 
702  if (($object->lines[$i]->info_bits & 0x01) == 0x01) {
703  $vatrate .= '*';
704  }
705 
706  // Fill $this->tva and $this->tva_array
707  if (!isset($this->tva[$vatrate])) {
708  $this->tva[$vatrate] = 0;
709  }
710  $this->tva[$vatrate] += $tvaligne;
711  $vatcode = $object->lines[$i]->vat_src_code;
712  if (empty($this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'])) {
713  $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'] = 0;
714  }
715  $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')] = array('vatrate' => $vatrate, 'vatcode' => $vatcode, 'amount' => $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'] + $tvaligne);
716 
717  if ($posYAfterImage > $posYAfterDescription) {
718  $nexY = $posYAfterImage;
719  }
720 
721  // Add line
722  if (getDolGlobalString('MAIN_PDF_DASH_BETWEEN_LINES') && $i < ($nblines - 1)) {
723  $pdf->setPage($pageposafter);
724  $pdf->SetLineStyle(array('dash' => '1,1', 'color' => array(80, 80, 80)));
725  //$pdf->SetDrawColor(190,190,200);
726  $pdf->line($this->marge_gauche, $nexY, $this->page_largeur - $this->marge_droite, $nexY);
727  $pdf->SetLineStyle(array('dash' => 0));
728  }
729 
730  // Detect if some page were added automatically and output _tableau for past pages
731  while ($pagenb < $pageposafter) {
732  $pdf->setPage($pagenb);
733  if ($pagenb == $pageposbeforeprintlines) {
734  $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, $hidetop, 1, $object->multicurrency_code);
735  } else {
736  $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code);
737  }
738  $this->_pagefoot($pdf, $object, $outputlangs, 1);
739  $pagenb++;
740  $pdf->setPage($pagenb);
741  $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it.
742  if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
743  $this->_pagehead($pdf, $object, 0, $outputlangs);
744  }
745  if (!empty($tplidx)) {
746  $pdf->useTemplate($tplidx);
747  }
748  }
749  if (isset($object->lines[$i + 1]->pagebreak) && $object->lines[$i + 1]->pagebreak) {
750  if ($pagenb == $pageposafter) {
751  $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, $hidetop, 1, $object->multicurrency_code);
752  } else {
753  $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code);
754  }
755  $this->_pagefoot($pdf, $object, $outputlangs, 1);
756  // New page
757  $pdf->AddPage();
758  if (!empty($tplidx)) {
759  $pdf->useTemplate($tplidx);
760  }
761  $pagenb++;
762  if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
763  $this->_pagehead($pdf, $object, 0, $outputlangs);
764  }
765  }
766  }
767 
768  // Show square
769  if ($pagenb == $pageposbeforeprintlines) {
770  $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, $hidetop, 0, $object->multicurrency_code);
771  $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
772  } else {
773  $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 1, 0, $object->multicurrency_code);
774  $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
775  }
776 
777  // Affiche zone infos
778  $posy = $this->_tableau_info($pdf, $object, $bottomlasttab, $outputlangs);
779 
780  // Affiche zone totaux
781  $posy = $this->_tableau_tot($pdf, $object, $deja_regle, $bottomlasttab, $outputlangs);
782 
783  // Affiche zone versements
784  if ($deja_regle || $amount_credit_notes_included || $amount_deposits_included) {
785  $posy = $this->_tableau_versements($pdf, $object, $posy, $outputlangs);
786  }
787 
788  // Pied de page
789  $this->_pagefoot($pdf, $object, $outputlangs);
790  if (method_exists($pdf, 'AliasNbPages')) {
791  $pdf->AliasNbPages();
792  }
793 
794  $pdf->Close();
795 
796  $pdf->Output($file, 'F');
797 
798  // Add pdfgeneration hook
799  $hookmanager->initHooks(array('pdfgeneration'));
800  $parameters = array('file' => $file, 'object' => $object, 'outputlangs' => $outputlangs);
801  global $action;
802  $reshook = $hookmanager->executeHooks('afterPDFCreation', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
803  if ($reshook < 0) {
804  $this->error = $hookmanager->error;
805  $this->errors = $hookmanager->errors;
806  }
807 
808  dolChmod($file);
809 
810  $this->result = array('fullpath' => $file);
811 
812  return 1; // No error
813  } else {
814  $this->error = $langs->trans("ErrorCanNotCreateDir", $dir);
815  return 0;
816  }
817  } else {
818  $this->error = $langs->trans("ErrorConstantNotDefined", "SUPPLIER_OUTPUTDIR");
819  return 0;
820  }
821  }
822 
823  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
824  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
834  protected function _tableau_versements(&$pdf, $object, $posy, $outputlangs)
835  {
836  // phpcs:enable
837  return 1;
838  }
839 
840  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
841  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
851  protected function _tableau_info(&$pdf, $object, $posy, $outputlangs)
852  {
853  // phpcs:enable
854  global $conf, $mysoc;
855  $default_font_size = pdf_getPDFFontSize($outputlangs);
856 
857  $diffsizetitle = (!getDolGlobalString('PDF_DIFFSIZE_TITLE') ? 3 : $conf->global->PDF_DIFFSIZE_TITLE);
858 
859  // If France, show VAT mention if not applicable
860  if ($this->emetteur->country_code == 'FR' && empty($mysoc->tva_assuj)) {
861  $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
862  $pdf->SetXY($this->marge_gauche, $posy);
863  $pdf->MultiCell(100, 3, $outputlangs->transnoentities("VATIsNotUsedForInvoice"), 0, 'L', 0);
864 
865  $posy = $pdf->GetY() + 4;
866  }
867 
868  $posxval = 52;
869 
870  // Show payments conditions
871  if (!empty($object->cond_reglement_code) || $object->cond_reglement) {
872  $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
873  $pdf->SetXY($this->marge_gauche, $posy);
874  $titre = $outputlangs->transnoentities("PaymentConditions").':';
875  $pdf->MultiCell(80, 4, $titre, 0, 'L');
876 
877  $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
878  $pdf->SetXY($posxval, $posy);
879  $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);
880  $lib_condition_paiement = str_replace('\n', "\n", $lib_condition_paiement);
881  $pdf->MultiCell(80, 4, $lib_condition_paiement, 0, 'L');
882 
883  $posy = $pdf->GetY() + 3;
884  }
885 
886  // Show payment mode
887  if (!empty($object->mode_reglement_code)) {
888  $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
889  $pdf->SetXY($this->marge_gauche, $posy);
890  $titre = $outputlangs->transnoentities("PaymentMode").':';
891  $pdf->MultiCell(80, 5, $titre, 0, 'L');
892 
893  $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
894  $pdf->SetXY($posxval, $posy);
895  $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);
896  $pdf->MultiCell(80, 5, $lib_mode_reg, 0, 'L');
897 
898  $posy = $pdf->GetY() + 2;
899  }
900 
901 
902  return $posy;
903  }
904 
905  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
906  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
917  protected function _tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs)
918  {
919  // phpcs:enable
920  global $conf, $mysoc;
921 
922  $default_font_size = pdf_getPDFFontSize($outputlangs);
923 
924  $tab2_top = $posy;
925  $tab2_hl = 4;
926  $pdf->SetFont('', '', $default_font_size - 1);
927 
928  // Tableau total
929  $col1x = 120;
930  $col2x = 170;
931  if ($this->page_largeur < 210) { // To work with US executive format
932  $col2x -= 20;
933  }
934  $largcol2 = ($this->page_largeur - $this->marge_droite - $col2x);
935 
936  $useborder = 0;
937  $index = 0;
938 
939  // Total HT
940  $pdf->SetFillColor(255, 255, 255);
941  $pdf->SetXY($col1x, $tab2_top);
942  $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalHT"), 0, 'L', 1);
943 
944  $total_ht = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? $object->multicurrency_total_ht : $object->total_ht);
945  $pdf->SetXY($col2x, $tab2_top);
946  $pdf->MultiCell($largcol2, $tab2_hl, price($total_ht + (!empty($object->remise) ? $object->remise : 0)), 0, 'R', 1);
947 
948  // Show VAT by rates and total
949  $pdf->SetFillColor(248, 248, 248);
950 
951  $this->atleastoneratenotnull = 0;
952  foreach ($this->tva as $tvakey => $tvaval) {
953  if ($tvakey > 0) { // On affiche pas taux 0
954  $this->atleastoneratenotnull++;
955 
956  $index++;
957  $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
958 
959  $tvacompl = '';
960 
961  if (preg_match('/\*/', $tvakey)) {
962  $tvakey = str_replace('*', '', $tvakey);
963  $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
964  }
965 
966  $totalvat = $outputlangs->transcountrynoentities("TotalVAT", $mysoc->country_code).' ';
967  $totalvat .= vatrate($tvakey, 1).$tvacompl;
968  $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1);
969 
970  $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
971  $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval), 0, 'R', 1);
972  }
973  }
974  if (!$this->atleastoneratenotnull) { // If no vat at all
975  $index++;
976  $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
977  $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transcountrynoentities("TotalVAT", $mysoc->country_code), 0, 'L', 1);
978 
979  $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
980  $pdf->MultiCell($largcol2, $tab2_hl, price($object->total_tva), 0, 'R', 1);
981 
982  // Total LocalTax1
983  if (getDolGlobalString('FACTURE_LOCAL_TAX1_OPTION') == 'localtax1on' && $object->total_localtax1 > 0) {
984  $index++;
985  $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
986  $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transcountrynoentities("TotalLT1", $mysoc->country_code), 0, 'L', 1);
987  $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
988  $pdf->MultiCell($largcol2, $tab2_hl, price($object->total_localtax1), $useborder, 'R', 1);
989  }
990 
991  // Total LocalTax2
992  if (getDolGlobalString('FACTURE_LOCAL_TAX2_OPTION') == 'localtax2on' && $object->total_localtax2 > 0) {
993  $index++;
994  $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
995  $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transcountrynoentities("TotalLT2", $mysoc->country_code), 0, 'L', 1);
996  $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
997  $pdf->MultiCell($largcol2, $tab2_hl, price($object->total_localtax2), $useborder, 'R', 1);
998  }
999  } else {
1000  //if (!empty($conf->global->FACTURE_LOCAL_TAX1_OPTION) && $conf->global->FACTURE_LOCAL_TAX1_OPTION=='localtax1on')
1001  //{
1002  //Local tax 1
1003  foreach ($this->localtax1 as $localtax_type => $localtax_rate) {
1004  if (in_array((string) $localtax_type, array('2', '4', '6'))) {
1005  continue;
1006  }
1007 
1008  foreach ($localtax_rate as $tvakey => $tvaval) {
1009  if ($tvakey != 0) { // On affiche pas taux 0
1010  //$this->atleastoneratenotnull++;
1011 
1012  $index++;
1013  $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1014 
1015  $tvacompl = '';
1016  if (preg_match('/\*/', $tvakey)) {
1017  $tvakey = str_replace('*', '', $tvakey);
1018  $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1019  }
1020  $totalvat = $outputlangs->transcountrynoentities("TotalLT1", $mysoc->country_code).' ';
1021  $totalvat .= vatrate(abs($tvakey), 1).$tvacompl;
1022  $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1);
1023 
1024  $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1025  $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1);
1026  }
1027  }
1028  }
1029 
1030  //if (!empty($conf->global->FACTURE_LOCAL_TAX2_OPTION) && $conf->global->FACTURE_LOCAL_TAX2_OPTION=='localtax2on')
1031  //{
1032  //Local tax 2
1033  foreach ($this->localtax2 as $localtax_type => $localtax_rate) {
1034  if (in_array((string) $localtax_type, array('2', '4', '6'))) {
1035  continue;
1036  }
1037 
1038  foreach ($localtax_rate as $tvakey => $tvaval) {
1039  if ($tvakey != 0) { // On affiche pas taux 0
1040  //$this->atleastoneratenotnull++;
1041 
1042  $index++;
1043  $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1044 
1045  $tvacompl = '';
1046  if (preg_match('/\*/', $tvakey)) {
1047  $tvakey = str_replace('*', '', $tvakey);
1048  $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1049  }
1050  $totalvat = $outputlangs->transcountrynoentities("TotalLT2", $mysoc->country_code).' ';
1051  $totalvat .= vatrate(abs($tvakey), 1).$tvacompl;
1052  $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1);
1053 
1054  $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1055  $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval), 0, 'R', 1);
1056  }
1057  }
1058  }
1059  }
1060 
1061  // Total TTC
1062  $index++;
1063  $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1064  $pdf->SetTextColor(0, 0, 60);
1065  $pdf->SetFillColor(224, 224, 224);
1066  $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalTTC"), $useborder, 'L', 1);
1067 
1068  $total_ttc = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1) ? $object->multicurrency_total_ttc : $object->total_ttc;
1069  $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1070  $pdf->MultiCell($largcol2, $tab2_hl, price($total_ttc), $useborder, 'R', 1);
1071  $pdf->SetFont('', '', $default_font_size - 1);
1072  $pdf->SetTextColor(0, 0, 0);
1073 
1074  $creditnoteamount = 0;
1075  $depositsamount = 0;
1076  //$creditnoteamount=$object->getSumCreditNotesUsed();
1077  //$depositsamount=$object->getSumDepositsUsed();
1078  //print "x".$creditnoteamount."-".$depositsamount;exit;
1079  $resteapayer = price2num($total_ttc - $deja_regle - $creditnoteamount - $depositsamount, 'MT');
1080  if (!empty($object->paye)) {
1081  $resteapayer = 0;
1082  }
1083 
1084  if ($deja_regle > 0) {
1085  // Already paid + Deposits
1086  $index++;
1087 
1088  $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1089  $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("AlreadyPaid"), 0, 'L', 0);
1090  $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1091  $pdf->MultiCell($largcol2, $tab2_hl, price($deja_regle), 0, 'R', 0);
1092 
1093  $index++;
1094  $pdf->SetTextColor(0, 0, 60);
1095  $pdf->SetFillColor(224, 224, 224);
1096  $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1097  $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("RemainderToPay"), $useborder, 'L', 1);
1098 
1099  $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1100  $pdf->MultiCell($largcol2, $tab2_hl, price($resteapayer), $useborder, 'R', 1);
1101 
1102  $pdf->SetFont('', '', $default_font_size - 1);
1103  $pdf->SetTextColor(0, 0, 0);
1104  }
1105 
1106  $index++;
1107  return ($tab2_top + ($tab2_hl * $index));
1108  }
1109 
1110  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1124  protected function _tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop = 0, $hidebottom = 0, $currency = '')
1125  {
1126  global $conf;
1127 
1128  // Force to disable hidetop and hidebottom
1129  $hidebottom = 0;
1130  if ($hidetop) {
1131  $hidetop = -1;
1132  }
1133 
1134  $currency = !empty($currency) ? $currency : $conf->currency;
1135  $default_font_size = pdf_getPDFFontSize($outputlangs);
1136 
1137  // Amount in (at tab_top - 1)
1138  $pdf->SetTextColor(0, 0, 0);
1139  $pdf->SetFont('', '', $default_font_size - 2);
1140 
1141  if (empty($hidetop)) {
1142  $titre = $outputlangs->transnoentities("AmountInCurrency", $outputlangs->transnoentitiesnoconv("Currency".$currency));
1143  $pdf->SetXY($this->page_largeur - $this->marge_droite - ($pdf->GetStringWidth($titre) + 3), $tab_top - 4);
1144  $pdf->MultiCell(($pdf->GetStringWidth($titre) + 3), 2, $titre);
1145 
1146  //$conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR='230,230,230';
1147  if (getDolGlobalString('MAIN_PDF_TITLE_BACKGROUND_COLOR')) {
1148  $pdf->Rect($this->marge_gauche, $tab_top, $this->page_largeur - $this->marge_droite - $this->marge_gauche, $this->tabTitleHeight, 'F', null, explode(',', getDolGlobalString('MAIN_PDF_TITLE_BACKGROUND_COLOR')));
1149  }
1150  }
1151 
1152  $pdf->SetDrawColor(128, 128, 128);
1153  $pdf->SetFont('', '', $default_font_size - 1);
1154 
1155  // Output Rect
1156  $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
1157 
1158  $this->pdfTabTitles($pdf, $tab_top, $tab_height, $outputlangs, $hidetop);
1159 
1160  if (empty($hidetop)) {
1161  $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
1162  }
1163  }
1164 
1165  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1175  protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs)
1176  {
1177  global $langs, $conf, $mysoc;
1178 
1179  $ltrdirection = 'L';
1180  if ($outputlangs->trans("DIRECTION") == 'rtl') {
1181  $ltrdirection = 'R';
1182  }
1183 
1184  // Load translation files required by the page
1185  $outputlangs->loadLangs(array("main", "supplier_proposal", "companies", "bills", "sendings"));
1186 
1187  $default_font_size = pdf_getPDFFontSize($outputlangs);
1188 
1189  // Do not add the BACKGROUND as this is for suppliers
1190  //pdf_pagehead($pdf,$outputlangs,$this->page_hauteur);
1191 
1192  //Affiche le filigrane brouillon - Print Draft Watermark
1193  /*if($object->statut==0 && getDolGlobalString('COMMANDE_DRAFT_WATERMARK'))
1194  {
1195  pdf_watermark($pdf,$outputlangs,$this->page_hauteur,$this->page_largeur,'mm',getDolGlobalString('COMMANDE_DRAFT_WATERMARK'));
1196  }*/
1197  //Print content
1198 
1199  $pdf->SetTextColor(0, 0, 60);
1200  $pdf->SetFont('', 'B', $default_font_size + 3);
1201 
1202  $posx = $this->page_largeur - $this->marge_droite - 100;
1203  $posy = $this->marge_haute;
1204 
1205  $pdf->SetXY($this->marge_gauche, $posy);
1206 
1207  // Logo
1208  if (!getDolGlobalInt('PDF_DISABLE_MYCOMPANY_LOGO')) {
1209  if ($this->emetteur->logo) {
1210  $logodir = $conf->mycompany->dir_output;
1211  if (!empty($conf->mycompany->multidir_output[$object->entity])) {
1212  $logodir = $conf->mycompany->multidir_output[$object->entity];
1213  }
1214  if (!getDolGlobalInt('MAIN_PDF_USE_LARGE_LOGO')) {
1215  $logo = $logodir.'/logos/thumbs/'.$this->emetteur->logo_small;
1216  } else {
1217  $logo = $logodir.'/logos/'.$this->emetteur->logo;
1218  }
1219  if (is_readable($logo)) {
1220  $height = pdf_getHeightForLogo($logo);
1221  $pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto)
1222  } else {
1223  $pdf->SetTextColor(200, 0, 0);
1224  $pdf->SetFont('', 'B', $default_font_size - 2);
1225  $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound", $logo), 0, 'L');
1226  $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorGoToGlobalSetup"), 0, 'L');
1227  }
1228  } else {
1229  $text = $this->emetteur->name;
1230  $pdf->MultiCell(100, 4, $outputlangs->convToOutputCharset($text), 0, $ltrdirection);
1231  }
1232  }
1233 
1234  $pdf->SetFont('', 'B', $default_font_size + 3);
1235  $pdf->SetXY($posx, $posy);
1236  $pdf->SetTextColor(0, 0, 60);
1237  $title = $outputlangs->transnoentities("SupplierProposal")." ".$outputlangs->convToOutputCharset($object->ref);
1238  $pdf->MultiCell(100, 3, $title, '', 'R');
1239  $posy += 1;
1240 
1241  if ($object->ref_supplier) {
1242  $posy += 4;
1243  $pdf->SetFont('', 'B', $default_font_size);
1244  $pdf->SetXY($posx, $posy);
1245  $pdf->SetTextColor(0, 0, 60);
1246  $pdf->MultiCell(100, 3, $outputlangs->transnoentities("RefSupplier")." : ".$outputlangs->convToOutputCharset($object->ref_supplier), '', 'R');
1247  $posy += 1;
1248  }
1249 
1250  $pdf->SetFont('', '', $default_font_size - 1);
1251 
1252  if (getDolGlobalString('PDF_SHOW_PROJECT_TITLE')) {
1253  $object->fetch_projet();
1254  if (!empty($object->project->ref)) {
1255  $posy += 3;
1256  $pdf->SetXY($posx, $posy);
1257  $pdf->SetTextColor(0, 0, 60);
1258  $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Project")." : ".(empty($object->project->title) ? '' : $object->project->title), '', 'R');
1259  }
1260  }
1261 
1262  if (getDolGlobalString('PDF_SHOW_PROJECT')) {
1263  $object->fetch_projet();
1264  if (!empty($object->project->ref)) {
1265  $outputlangs->load("projects");
1266  $posy += 4;
1267  $pdf->SetXY($posx, $posy);
1268  $langs->load("projects");
1269  $pdf->SetTextColor(0, 0, 60);
1270  $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Project")." : ".(empty($object->project->ref) ? '' : $object->project->ref), '', 'R');
1271  }
1272  }
1273 
1274  if (!empty($object->date)) {
1275  $posy += 5;
1276  $pdf->SetXY($posx, $posy);
1277  $pdf->SetTextColor(0, 0, 60);
1278  $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Date")." : ".dol_print_date($object->date, "day", false, $outputlangs, true), '', 'R');
1279  } else {
1280  $posy += 5;
1281  $pdf->SetXY($posx, $posy);
1282  $pdf->SetTextColor(255, 0, 0);
1283  $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Draft"), '', 'R');
1284  }
1285 
1286  $pdf->SetTextColor(0, 0, 60);
1287  $usehourmin = 'day';
1288  if (getDolGlobalString('SUPPLIER_PROPOSAL_USE_HOUR_FOR_DELIVERY_DATE')) {
1289  $usehourmin = 'dayhour';
1290  }
1291  if (!empty($object->delivery_date)) {
1292  $posy += 4;
1293  $pdf->SetXY($posx - 90, $posy);
1294  $pdf->MultiCell(190, 3, $outputlangs->transnoentities("DateDeliveryPlanned")." : ".dol_print_date($object->delivery_date, $usehourmin, false, $outputlangs, true), '', 'R');
1295  }
1296 
1297  if ($object->thirdparty->code_fournisseur) {
1298  $posy += 4;
1299  $pdf->SetXY($posx, $posy);
1300  $pdf->SetTextColor(0, 0, 60);
1301  $pdf->MultiCell(100, 3, $outputlangs->transnoentities("SupplierCode")." : ".$outputlangs->transnoentities($object->thirdparty->code_fournisseur), '', 'R');
1302  }
1303 
1304  // Get contact
1305  if (getDolGlobalString('DOC_SHOW_FIRST_SALES_REP')) {
1306  $arrayidcontact = $object->getIdContact('internal', 'SALESREPFOLL');
1307  if (count($arrayidcontact) > 0) {
1308  $usertmp = new User($this->db);
1309  $usertmp->fetch($arrayidcontact[0]);
1310  $posy += 4;
1311  $pdf->SetXY($posx, $posy);
1312  $pdf->SetTextColor(0, 0, 60);
1313  $pdf->MultiCell(100, 3, $langs->trans("BuyerName")." : ".$usertmp->getFullName($langs), '', 'R');
1314  }
1315  }
1316 
1317  $posy += 1;
1318  $pdf->SetTextColor(0, 0, 60);
1319 
1320  $top_shift = 0;
1321  // Show list of linked objects
1322  $current_y = $pdf->getY();
1323  $posy = pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, 100, 3, 'R', $default_font_size);
1324  if ($current_y < $pdf->getY()) {
1325  $top_shift = $pdf->getY() - $current_y;
1326  }
1327 
1328  if ($showaddress) {
1329  // Sender properties
1330  $carac_emetteur = '';
1331  // Add internal contact of object if defined
1332  $arrayidcontact = $object->getIdContact('internal', 'SALESREPFOLL');
1333  if (count($arrayidcontact) > 0) {
1334  $object->fetch_user($arrayidcontact[0]);
1335  $labelbeforecontactname = ($outputlangs->transnoentities("FromContactName") != 'FromContactName' ? $outputlangs->transnoentities("FromContactName") : $outputlangs->transnoentities("Name"));
1336  $carac_emetteur .= ($carac_emetteur ? "\n" : '').$labelbeforecontactname.": ".$outputlangs->convToOutputCharset($object->user->getFullName($outputlangs));
1337  $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') || getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ' (' : '';
1338  $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') && !empty($object->user->office_phone)) ? $object->user->office_phone : '';
1339  $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') && getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ', ' : '';
1340  $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT') && !empty($object->user->email)) ? $object->user->email : '';
1341  $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') || getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ')' : '';
1342  $carac_emetteur .= "\n";
1343  }
1344 
1345  $carac_emetteur .= pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, '', 0, 'source', $object);
1346 
1347  // Show sender
1348  $posy = 42 + $top_shift;
1349  $posx = $this->marge_gauche;
1350  if (getDolGlobalString('MAIN_INVERT_SENDER_RECIPIENT')) {
1351  $posx = $this->page_largeur - $this->marge_droite - 80;
1352  }
1353  $hautcadre = 40;
1354 
1355  // Show sender frame
1356  $pdf->SetTextColor(0, 0, 0);
1357  $pdf->SetFont('', '', $default_font_size - 2);
1358  $pdf->SetXY($posx, $posy - 5);
1359  $pdf->MultiCell(80, 5, $outputlangs->transnoentities("BillFrom"), 0, $ltrdirection);
1360  $pdf->SetXY($posx, $posy);
1361  $pdf->SetFillColor(230, 230, 230);
1362  $pdf->MultiCell(82, $hautcadre, "", 0, 'R', 1);
1363  $pdf->SetTextColor(0, 0, 60);
1364 
1365  // Show sender name
1366  $pdf->SetXY($posx + 2, $posy + 3);
1367  $pdf->SetFont('', 'B', $default_font_size);
1368  $pdf->MultiCell(80, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, $ltrdirection);
1369  $posy = $pdf->getY();
1370 
1371  // Show sender information
1372  $pdf->SetXY($posx + 2, $posy);
1373  $pdf->SetFont('', '', $default_font_size - 1);
1374  $pdf->MultiCell(80, 4, $carac_emetteur, 0, $ltrdirection);
1375 
1376 
1377 
1378  // If CUSTOMER contact defined on proposal, we use it. Note: Even if this is a supplier object, the code for external contat that follow order is 'CUSTOMER'
1379  $usecontact = false;
1380  $arrayidcontact = $object->getIdContact('external', 'CUSTOMER');
1381  if (count($arrayidcontact) > 0) {
1382  $usecontact = true;
1383  $result = $object->fetch_contact($arrayidcontact[0]);
1384  }
1385 
1386  // Recipient name
1387  if ($usecontact && ($object->contact->socid != $object->thirdparty->id && (!isset($conf->global->MAIN_USE_COMPANY_NAME_OF_CONTACT) || getDolGlobalString('MAIN_USE_COMPANY_NAME_OF_CONTACT')))) {
1388  $thirdparty = $object->contact;
1389  } else {
1390  $thirdparty = $object->thirdparty;
1391  }
1392 
1393  $carac_client_name = pdfBuildThirdpartyName($thirdparty, $outputlangs);
1394 
1395  $carac_client = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, ($usecontact ? $object->contact : ''), $usecontact, 'target', $object);
1396 
1397  // Show recipient
1398  $widthrecbox = 100;
1399  if ($this->page_largeur < 210) {
1400  $widthrecbox = 84; // To work with US executive format
1401  }
1402  $posy = 42 + $top_shift;
1403  $posx = $this->page_largeur - $this->marge_droite - $widthrecbox;
1404  if (getDolGlobalString('MAIN_INVERT_SENDER_RECIPIENT')) {
1405  $posx = $this->marge_gauche;
1406  }
1407 
1408  // Show recipient frame
1409  $pdf->SetTextColor(0, 0, 0);
1410  $pdf->SetFont('', '', $default_font_size - 2);
1411  $pdf->SetXY($posx + 2, $posy - 5);
1412  $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillTo"), 0, $ltrdirection);
1413  $pdf->Rect($posx, $posy, $widthrecbox, $hautcadre);
1414 
1415  // Show recipient name
1416  $pdf->SetXY($posx + 2, $posy + 3);
1417  $pdf->SetFont('', 'B', $default_font_size);
1418  // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
1419  $pdf->MultiCell($widthrecbox, 4, $carac_client_name, 0, $ltrdirection);
1420 
1421  $posy = $pdf->getY();
1422 
1423  // Show recipient information
1424  $pdf->SetFont('', '', $default_font_size - 1);
1425  $pdf->SetXY($posx + 2, $posy);
1426  // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
1427  $pdf->MultiCell($widthrecbox, 4, $carac_client, 0, $ltrdirection);
1428  }
1429 
1430  return $top_shift;
1431  }
1432 
1433  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1443  protected function _pagefoot(&$pdf, $object, $outputlangs, $hidefreetext = 0)
1444  {
1445  $showdetails = getDolGlobalInt('MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS', 0);
1446  return pdf_pagefoot($pdf, $outputlangs, 'SUPPLIER_PROPOSAL_FREE_TEXT', $this->emetteur, $this->marge_basse, $this->marge_gauche, $this->page_hauteur, $object, $showdetails, $hidefreetext);
1447  }
1448 
1449 
1450 
1461  public function defineColumnField($object, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0)
1462  {
1463  global $conf, $hookmanager;
1464 
1465  // Default field style for content
1466  $this->defaultContentsFieldsStyle = array(
1467  'align' => 'R', // R,C,L
1468  'padding' => array(1, 0.5, 1, 0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1469  );
1470 
1471  // Default field style for content
1472  $this->defaultTitlesFieldsStyle = array(
1473  'align' => 'C', // R,C,L
1474  'padding' => array(0.5, 0, 0.5, 0), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1475  );
1476 
1477  $rank = 0; // do not use negative rank
1478  $this->cols['desc'] = array(
1479  'rank' => $rank,
1480  'width' => false, // only for desc
1481  'status' => true,
1482  'title' => array(
1483  'textkey' => 'Designation', // use lang key is useful in somme case with module
1484  'align' => 'L',
1485  // 'textkey' => 'yourLangKey', // if there is no label, yourLangKey will be translated to replace label
1486  // 'label' => ' ', // the final label
1487  'padding' => array(0.5, 0.5, 0.5, 0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1488  ),
1489  'content' => array(
1490  'align' => 'L',
1491  'padding' => array(1, 0.5, 1, 1.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1492  ),
1493  );
1494 
1495  $rank = $rank + 10;
1496  $this->cols['photo'] = array(
1497  'rank' => $rank,
1498  'width' => getDolGlobalInt('MAIN_DOCUMENTS_WITH_PICTURE_WIDTH', 20), // in mm
1499  'status' => false,
1500  'title' => array(
1501  'textkey' => 'Photo',
1502  'label' => ' '
1503  ),
1504  'content' => array(
1505  'padding' => array(0, 0, 0, 0), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1506  ),
1507  'border-left' => false, // remove left line separator
1508  );
1509 
1510  if (getDolGlobalString('MAIN_GENERATE_SUPPLIER_PROPOSAL_WITH_PICTURE')) {
1511  $this->cols['photo']['status'] = true;
1512  }
1513 
1514 
1515  $rank = $rank + 10;
1516  $this->cols['vat'] = array(
1517  'rank' => $rank,
1518  'status' => false,
1519  'width' => 16, // in mm
1520  'title' => array(
1521  'textkey' => 'VAT'
1522  ),
1523  'border-left' => true, // add left line separator
1524  );
1525 
1526  if (!getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT') && !getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_COLUMN')) {
1527  $this->cols['vat']['status'] = true;
1528  }
1529 
1530  $rank = $rank + 10;
1531  $this->cols['subprice'] = array(
1532  'rank' => $rank,
1533  'width' => 19, // in mm
1534  'status' => false,
1535  'title' => array(
1536  'textkey' => 'PriceUHT'
1537  ),
1538  'border-left' => true, // add left line separator
1539  );
1540 
1541  if (!getDolGlobalString('MAIN_GENERATE_DOCUMENTS_SUPPLIER_PROPOSAL_WITHOUT_UNIT_PRICE')) {
1542  $this->cols['subprice']['status'] = true;
1543  }
1544 
1545  $rank = $rank + 10;
1546  $this->cols['qty'] = array(
1547  'rank' => $rank,
1548  'width' => 16, // in mm
1549  'status' => true,
1550  'title' => array(
1551  'textkey' => 'Qty'
1552  ),
1553  'border-left' => true, // add left line separator
1554  );
1555 
1556  $rank = $rank + 10;
1557  $this->cols['unit'] = array(
1558  'rank' => $rank,
1559  'width' => 11, // in mm
1560  'status' => false,
1561  'title' => array(
1562  'textkey' => 'Unit'
1563  ),
1564  'border-left' => true, // add left line separator
1565  );
1566  if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
1567  $this->cols['unit']['status'] = true;
1568  }
1569 
1570  $rank = $rank + 10;
1571  $this->cols['discount'] = array(
1572  'rank' => $rank,
1573  'width' => 13, // in mm
1574  'status' => false,
1575  'title' => array(
1576  'textkey' => 'ReductionShort'
1577  ),
1578  'border-left' => true, // add left line separator
1579  );
1580  if ($this->atleastonediscount) {
1581  $this->cols['discount']['status'] = true;
1582  }
1583 
1584  $rank = $rank + 1000; // add a big offset to be sure is the last col because default extrafield rank is 100
1585  $this->cols['totalexcltax'] = array(
1586  'rank' => $rank,
1587  'width' => 26, // in mm
1588  'status' => false,
1589  'title' => array(
1590  'textkey' => 'TotalHT'
1591  ),
1592  'border-left' => true, // add left line separator
1593  );
1594 
1595  if (!getDolGlobalString('MAIN_GENERATE_DOCUMENTS_SUPPLIER_PROPOSAL_WITHOUT_TOTAL_COLUMN')) {
1596  $this->cols['totalexcltax']['status'] = true;
1597  }
1598 
1599  // Add extrafields cols
1600  if (!empty($object->lines)) {
1601  $line = reset($object->lines);
1602  $this->defineColumnExtrafield($line, $outputlangs, $hidedetails);
1603  }
1604 
1605  $parameters = array(
1606  'object' => $object,
1607  'outputlangs' => $outputlangs,
1608  'hidedetails' => $hidedetails,
1609  'hidedesc' => $hidedesc,
1610  'hideref' => $hideref
1611  );
1612 
1613  $reshook = $hookmanager->executeHooks('defineColumnField', $parameters, $this); // Note that $object may have been modified by hook
1614  if ($reshook < 0) {
1615  setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1616  } elseif (empty($reshook)) {
1617  // @phan-suppress-next-line PhanPluginSuspiciousParamOrderInternal
1618  $this->cols = array_replace($this->cols, $hookmanager->resArray); // array_replace is used to preserve keys
1619  } else {
1620  $this->cols = $hookmanager->resArray;
1621  }
1622  }
1623 }
if($user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition: card.php:58
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.
Perent class of the Proposal models.
Class to manage products or services.
Class to manage translations.
Class to manage Dolibarr users.
Definition: user.class.php:50
Class to generate the supplier proposals with the zenith model.
_pagehead(&$pdf, $object, $showaddress, $outputlangs)
Show top header of page.
_tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop=0, $hidebottom=0, $currency='')
Show table for lines.
_tableau_info(&$pdf, $object, $posy, $outputlangs)
Show miscellaneous information (payment mode, payment term, ...)
__construct($db)
Constructor.
_pagefoot(&$pdf, $object, $outputlangs, $hidefreetext=0)
Show footer of page.
_tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs)
Show total to pay.
defineColumnField($object, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0)
Define Array Column Field.
_tableau_versements(&$pdf, $object, $posy, $outputlangs)
Show payments table.
write_file($object, $outputlangs=null, $srctemplatepath='', $hidedetails=0, $hidedesc=0, $hideref=0)
Function to build pdf onto disk.
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 formatted for view output Used into pdf and HTML pages.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
dolChmod($filepath, $newmask='')
Change mod of a file.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
getLocalTaxesFromRate($vatrate, $local, $buyer, $seller, $firstparamisid=0)
Get type and rate of localtaxes for a particular vat rate/country of a thirdparty.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
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_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_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:2620
pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line total excluding tax.
Definition: pdf.lib.php:2369
pdf_getPDFFontSize($outputlangs)
Return font size to use for PDF generation.
Definition: pdf.lib.php:290
pdf_getFormat(Translate $outputlangs=null, $mode='setup')
Return array with format properties of default PDF format.
Definition: pdf.lib.php:86
pdf_getHeightForLogo($logo, $url=false)
Return height to use for Logo onto PDF.
Definition: pdf.lib.php:315
pdf_pagefoot(&$pdf, $outputlangs, $paramfreetext, $fromcompany, $marge_basse, $marge_gauche, $page_hauteur, $object, $showdetails=0, $hidefreetext=0, $page_largeur=0, $watermark='')
Show footer of page for PDF generation.
Definition: pdf.lib.php:1020
pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line unit price excluding tax.
Definition: pdf.lib.php:1987
pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails=0)
Return line vat rate.
Definition: pdf.lib.php:1925
pdf_writeLinkedObjects(&$pdf, $object, $outputlangs, $posx, $posy, $w, $h, $align, $default_font_size)
Show linked objects for PDF generation.
Definition: pdf.lib.php:1394
pdf_getPDFFont($outputlangs)
Return font name to use for PDF generation.
Definition: pdf.lib.php:267
pdf_build_address($outputlangs, $sourcecompany, $targetcompany='', $targetcontact='', $usecontact=0, $mode='source', $object=null)
Return a string with full address formatted for output on PDF documents.
Definition: pdf.lib.php:436
pdf_getlineunit($object, $i, $outputlangs, $hidedetails=0)
Return line unit.
Definition: pdf.lib.php:2232
pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails=0)
Return line remise percent.
Definition: pdf.lib.php:2275
pdf_getlineqty($object, $i, $outputlangs, $hidedetails=0)
Return line quantity.
Definition: pdf.lib.php:2072
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:769
pdf_getInstance($format='', $metric='mm', $pagetype='P')
Return a PDF instance object.
Definition: pdf.lib.php:128
pdfBuildThirdpartyName($thirdparty, Translate $outputlangs, $includealias=0)
Returns the name of the thirdparty.
Definition: pdf.lib.php:388
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition: repair.php:123
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition: repair.php:126