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