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