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