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