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