dolibarr 24.0.1
pdf_cyan.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-2015 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-2026 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 Alexandre Spangaro <alexandre@inovea-conseil.com>
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 3 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program. If not, see <https://www.gnu.org/licenses/>.
28 * or see https://www.gnu.org/
29 */
30
36require_once DOL_DOCUMENT_ROOT.'/core/modules/propale/modules_propale.php';
37require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
38require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
39require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
40require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
41
46{
50 public $db;
51
55 public $name;
56
60 public $description;
61
65 public $update_main_doc_field;
66
70 public $type;
71
76 public $version = 'dolibarr';
77
81 public $cols;
82
88 public function __construct($db)
89 {
90 global $langs, $mysoc;
91
92 // Translations
93 $langs->loadLangs(array("main", "bills"));
94
95 $this->db = $db;
96 $this->name = "cyan";
97 $this->description = $langs->trans('DocModelCyanDescription');
98 $this->update_main_doc_field = 1; // Save the name of generated file as the main doc when generating a doc with this template
99
100 // Dimension page
101 $this->type = 'pdf';
102 $formatarray = pdf_getFormat();
103 $this->page_largeur = $formatarray['width'];
104 $this->page_hauteur = $formatarray['height'];
105 $this->format = array($this->page_largeur, $this->page_hauteur);
106 $this->marge_gauche = getDolGlobalInt('MAIN_PDF_MARGIN_LEFT', 10);
107 $this->marge_droite = getDolGlobalInt('MAIN_PDF_MARGIN_RIGHT', 10);
108 $this->marge_haute = getDolGlobalInt('MAIN_PDF_MARGIN_TOP', 10);
109 $this->marge_basse = getDolGlobalInt('MAIN_PDF_MARGIN_BOTTOM', 10);
110 $this->corner_radius = getDolGlobalInt('MAIN_PDF_FRAME_CORNER_RADIUS', 0);
111 $this->option_logo = 1; // Display logo
112 $this->option_tva = 1; // Manage the vat option FACTURE_TVAOPTION
113 $this->option_modereg = 1; // Display payment mode
114 $this->option_condreg = 1; // Display payment terms
115 $this->option_multilang = 1; // Available in several languages
116 $this->option_escompte = 0; // Displays if there has been a discount
117 $this->option_credit_note = 0; // Support credit notes
118 $this->option_freetext = 1; // Support add of a personalised text
119 $this->option_draft_watermark = 1; // Support add of a watermark on drafts
120 $this->watermark = '';
121
122 // Define position of columns
123 $this->posxdesc = $this->marge_gauche + 1; // used for notes and other stuff
124
125
126 $this->tabTitleHeight = 5; // default height
127
128 // Use new system for position of columns, view $this->defineColumnField()
129
130 $this->tva = array();
131 $this->tva_array = array();
132 $this->localtax1 = array();
133 $this->localtax2 = array();
134 $this->atleastoneratenotnull = 0;
135 $this->atleastonediscount = 0;
136
137 $this->showAmountBeforeDiscount = getDolGlobalInt('MAIN_HIDE_AMOUNT_BEFORE_DISCOUNT') || getDolGlobalInt('MAIN_HIDE_AMOUNT_BEFORE_DISCOUNT_PROPALE') ? 0 : 1;
138 $this->showDiscountAmount = getDolGlobalInt('MAIN_HIDE_AMOUNT_DISCOUNT') || getDolGlobalInt('MAIN_HIDE_AMOUNT_BEFORE_DISCOUNT_PROPALE') ? 0 : 1;
139
140
141 if ($mysoc === null) {
142 dol_syslog(get_class($this).'::__construct() Global $mysoc should not be null.'. getCallerInfoString(), LOG_ERR);
143 return;
144 }
145
146 // Get source company
147 $this->emetteur = $mysoc;
148 if (empty($this->emetteur->country_code)) {
149 $this->emetteur->country_code = substr($langs->defaultlang, -2); // By default, if was not defined
150 }
151 }
152
153 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
165 public function write_file($object, $outputlangs, $srctemplatepath = '', $hidedetails = 0, $hidedesc = 0, $hideref = 0)
166 {
167 // phpcs:enable
168 global $user, $langs, $conf, $mysoc, $db, $hookmanager, $nblines;
169
170 dol_syslog("write_file outputlangs->defaultlang=".(is_object($outputlangs) ? $outputlangs->defaultlang : 'null'));
171
172 if (!is_object($outputlangs)) {
173 $outputlangs = $langs;
174 }
175 // For backward compatibility with FPDF, force output charset to ISO, because FPDF expect text to be encoded in ISO
176 if (getDolGlobalString('MAIN_USE_FPDF')) {
177 $outputlangs->charset_output = 'ISO-8859-1';
178 }
179
180 // Load translation files required by page
181 $langfiles = array("main", "dict", "companies", "bills", "products", "propal", "compta");
182 $outputlangs->loadLangs($langfiles);
183
184 // Show Draft Watermark
185 if ($object->status == $object::STATUS_DRAFT && getDolGlobalString('PROPALE_DRAFT_WATERMARK')) {
186 $this->watermark = getDolGlobalString('PROPALE_DRAFT_WATERMARK');
187 }
188
189 global $outputlangsbis;
190 $outputlangsbis = null;
191 if (getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE') && $outputlangs->defaultlang != getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE')) {
192 $outputlangsbis = new Translate('', $conf);
193 $outputlangsbis->setDefaultLang(getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE'));
194 $outputlangsbis->loadLangs($langfiles);
195 }
196
197 $nblines = count($object->lines);
198
199 $hidetop = getDolGlobalInt('MAIN_PDF_DISABLE_COL_HEAD_TITLE');
200
201 // Loop on each lines to detect if there is at least one image to show
202 $realpatharray = array();
203 $this->atleastonephoto = false;
204 if (getDolGlobalString('MAIN_GENERATE_PROPOSALS_WITH_PICTURE')) {
205 $objphoto = new Product($this->db);
206
207 for ($i = 0; $i < $nblines; $i++) {
208 if (empty($object->lines[$i]->fk_product)) {
209 continue;
210 }
211
212 $objphoto->fetch($object->lines[$i]->fk_product);
213 //var_dump($objphoto->ref);exit;
214 $pdir = array();
215 if (getDolGlobalInt('PRODUCT_USE_OLD_PATH_FOR_PHOTO')) {
216 $pdir[0] = get_exdir($objphoto->id, 2, 0, 0, $objphoto, 'product').$objphoto->id."/photos/";
217 $pdir[1] = get_exdir(0, 0, 0, 0, $objphoto, 'product').dol_sanitizeFileName($objphoto->ref).'/';
218 } else {
219 $pdir[0] = get_exdir(0, 0, 0, 0, $objphoto, 'product'); // default
220 $pdir[1] = get_exdir($objphoto->id, 2, 0, 0, $objphoto, 'product').$objphoto->id."/photos/"; // alternative
221 }
222
223 $realpath = '';
224 $arephoto = false;
225 foreach ($pdir as $midir) {
226 if (!$arephoto) {
227 $entity = $objphoto->entity;
228 if ($entity !== null && $conf->entity != $entity) {
229 $dir = $conf->product->multidir_output[$entity].'/'.$midir; //Check repertories of current entities
230 } else {
231 $dir = $conf->product->dir_output.'/'.$midir; //Check repertory of the current product
232 }
233
234 foreach ($objphoto->liste_photos($dir, 1) as $key => $obj) {
235 if (!getDolGlobalInt('CAT_HIGH_QUALITY_IMAGES')) { // If CAT_HIGH_QUALITY_IMAGES not defined, we use thumb if defined and then original photo
236 if ($obj['photo_vignette']) {
237 $filename = $obj['photo_vignette'];
238 } else {
239 $filename = $obj['photo'];
240 }
241 } else {
242 $filename = $obj['photo'];
243 }
244
245 $realpath = $dir.$filename;
246 $arephoto = true;
247 $this->atleastonephoto = true;
248 }
249 }
250 }
251
252 if ($realpath && $arephoto) {
253 $realpatharray[$i] = $realpath;
254 }
255 }
256 }
257
258 if (count($realpatharray) == 0) {
259 $this->posxpicture = $this->posxtva;
260 }
261
262 if ($conf->propal->multidir_output[$conf->entity]) {
263 $object->fetch_thirdparty();
264
265 $deja_regle = 0;
266
267 // Definition of $dir and $file
268 if ($object->specimen) {
269 $dir = $conf->propal->multidir_output[$conf->entity];
270 $file = $dir."/SPECIMEN.pdf";
271 } else {
272 $objectref = dol_sanitizeFileName($object->ref);
273 $dir = $conf->propal->multidir_output[$object->entity ?? $conf->entity]."/".$objectref;
274 $file = $dir."/".$objectref.".pdf";
275 }
276
277 if (!file_exists($dir)) {
278 if (dol_mkdir($dir) < 0) {
279 $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
280 return 0;
281 }
282 }
283
284 if (file_exists($dir)) {
285 // Add pdfgeneration hook
286 if (!is_object($hookmanager)) {
287 include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
288 $hookmanager = new HookManager($this->db);
289 }
290 $hookmanager->initHooks(array('pdfgeneration'));
291 $parameters = array('file' => $file, 'object' => $object, 'outputlangs' => $outputlangs);
292 global $action;
293 $reshook = $hookmanager->executeHooks('beforePDFCreation', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
294
295 // Set nblines with the new content of lines after hook
296 $nblines = count($object->lines);
297 //$nbpayments = count($object->getListOfPayments());
298
299 // Create pdf instance
300 $pdf = pdf_getInstance($this->format);
301 $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance
302 $pdf->setAutoPageBreak(true, 0);
303
304 if (class_exists('TCPDF')) {
305 $pdf->setPrintHeader(false);
306 $pdf->setPrintFooter(false);
307 }
308 $pdf->SetFont(pdf_getPDFFont($outputlangs));
309 // Set path to the background PDF File
310 if (getDolGlobalString('MAIN_ADD_PDF_BACKGROUND')) {
311 $logodir = $conf->mycompany->dir_output;
312 if (!empty($conf->mycompany->multidir_output[$object->entity ?? $conf->entity])) {
313 $logodir = $conf->mycompany->multidir_output[$object->entity ?? $conf->entity];
314 }
315 $pagecount = $pdf->setSourceFile($logodir.'/' . getDolGlobalString('MAIN_ADD_PDF_BACKGROUND'));
316 $tplidx = $pdf->importPage(1);
317 }
318
319 $pdf->Open();
320 $pagenb = 0;
321 $pdf->SetDrawColor(128, 128, 128);
322
323 $pdf->SetTitle($outputlangs->convToOutputCharset($object->ref));
324 $pdf->SetSubject($outputlangs->transnoentities("PdfCommercialProposalTitle"));
325 $pdf->SetCreator("Dolibarr ".DOL_VERSION);
326 $pdf->SetAuthor($outputlangs->convToOutputCharset($user->getAnonymisableFullName($outputlangs)));
327 $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("PdfCommercialProposalTitle")." ".$outputlangs->convToOutputCharset($object->thirdparty->name));
328 if (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) {
329 $pdf->SetCompression(false);
330 }
331
332 // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
333 $pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite); // Left, Top, Right
334
335 // Set $this->atleastonediscount if you have at least one discount
336 for ($i = 0; $i < $nblines; $i++) {
337 if ($object->lines[$i]->remise_percent) {
338 $this->atleastonediscount++;
339 }
340 }
341
342
343 // New page
344 $pdf->AddPage();
345 if (!empty($tplidx)) {
346 $pdf->useTemplate($tplidx);
347 }
348 $pagenb++;
349
350 $heightforinfotot = 40; // Height reserved to output the info and total part
351 $heightforsignature = !getDolGlobalString('PROPAL_DISABLE_SIGNATURE') ? (pdfGetHeightForHtmlContent($pdf, $outputlangs->transnoentities("ProposalCustomerSignature")) + 10) : 0;
352 $heightforfreetext = getDolGlobalInt('MAIN_PDF_FREETEXT_HEIGHT', 5); // Height reserved to output the free text on last page
353 $heightforfooter = $this->marge_basse + (!getDolGlobalString('MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS') ? 12 : 22); // Height reserved to output the footer (value include bottom margin)
354 //print $heightforinfotot + $heightforsignature + $heightforfreetext + $heightforfooter;exit;
355
356 $save_note_public = $object->note_public; // Because $object->note_public may be modified by _pagehead() that calls pdf_writeLinkedObjects() that calls ... that modify $object->note_private
357
358 $top_shift = $this->_pagehead($pdf, $object, 1, $outputlangs, $outputlangsbis);
359 $pdf->SetFont('', '', $default_font_size - 1);
360 $pdf->MultiCell(0, 3, ''); // Set interline to 3
361 $pdf->SetTextColor(0, 0, 0);
362
363
364 $tab_top = 80 + $this->marge_haute + $top_shift;
365 $tab_top_newpage = (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD') ? 32 + $this->marge_haute + $top_shift : $this->marge_haute);
366 if (!$hidetop && getDolGlobalInt('MAIN_PDF_ENABLE_COL_HEAD_TITLE_REPEAT')) {
367 // TODO : make this hidden conf the default behavior for each PDF when each PDF managed this new Display
368 $tab_top_newpage += $this->tabTitleHeight;
369 }
370
371 $nexY = $tab_top;
372
373 // Incoterm
374 $height_incoterms = 0;
375 if (isModEnabled('incoterm')) {
376 $desc_incoterms = $object->getIncotermsForPDF();
377 if ($desc_incoterms) {
378 $tab_top -= 2;
379
380 $pdf->SetFont('', '', $default_font_size - 1);
381 $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top - 1, dol_htmlentitiesbr($desc_incoterms), 0, 1);
382 $nexY = max($pdf->GetY(), $nexY);
383 $height_incoterms = $nexY - $tab_top;
384
385 // Rect takes a length in 3rd parameter
386 $pdf->SetDrawColor(192, 192, 192);
387 $pdf->RoundedRect($this->marge_gauche, $tab_top - 1, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $height_incoterms + 3, $this->corner_radius, '1234', 'D');
388
389 $tab_top = $nexY + 6;
390 $height_incoterms += 4;
391 }
392 }
393
394 // Displays notes
395 $notetoshow = empty($object->note_public) ? '' : $object->note_public;
396 if (getDolGlobalString('MAIN_ADD_SALE_REP_SIGNATURE_IN_NOTE')) {
397 // Get first sale rep
398 if (is_object($object->thirdparty)) {
399 $salereparray = $object->thirdparty->getSalesRepresentatives($user);
400 $salerepobj = new User($this->db);
401 $salerepobj->fetch($salereparray[0]['id']);
402 if (!empty($salerepobj->signature)) {
403 $notetoshow = dol_concatdesc($notetoshow, $salerepobj->signature);
404 }
405 }
406 }
407
408 $object->note_public = $save_note_public; // Now that we have output the note_public, we can restore it to initial value.
409
410 // Extrafields in note
411 $extranote = $this->getExtrafieldsInHtml($object, $outputlangs);
412 if (!empty($extranote)) {
413 $notetoshow = dol_concatdesc((string) $notetoshow, $extranote);
414 }
415
416 if (getDolGlobalString('MAIN_ADD_CREATOR_IN_NOTE') && $object->user_author_id > 0) {
417 $tmpuser = new User($this->db);
418 $tmpuser->fetch($object->user_author_id);
419
420 $creator_info = $langs->trans("CaseFollowedBy").' '.$tmpuser->getFullName($langs);
421 if ($tmpuser->email) {
422 $creator_info .= ', '.$langs->trans("EMail").': '.$tmpuser->email;
423 }
424 if ($tmpuser->office_phone) {
425 $creator_info .= ', '.$langs->trans("Phone").': '.$tmpuser->office_phone;
426 }
427
428 $notetoshow = dol_concatdesc((string) $notetoshow, $creator_info);
429 }
430
431 $tab_height = $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforsignature - $heightforfooter;
432
433 $pagenb = $pdf->getPage();
434 if ($notetoshow) {
435 $tab_top -= 2;
436
437 $tab_width = $this->page_largeur - $this->marge_gauche - $this->marge_droite;
438 $pageposbeforenote = $pagenb;
439
440 $substitutionarray = pdf_getSubstitutionArray($outputlangs, null, $object);
441 complete_substitutions_array($substitutionarray, $outputlangs, $object);
442 $notetoshow = make_substitutions($notetoshow, $substitutionarray, $outputlangs);
443 $notetoshow = convertBackOfficeMediasLinksToPublicLinks($notetoshow);
444
445 $pdf->startTransaction();
446
447 $pdf->SetFont('', '', $default_font_size - 1);
448 $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top, dol_htmlentitiesbr($notetoshow), 0, 1);
449 // Description
450 $pageposafternote = $pdf->getPage();
451 $posyafter = $pdf->GetY();
452
453 if ($pageposafternote > $pageposbeforenote) {
454 $pdf->rollbackTransaction(true);
455
456 // prepare pages to receive notes
457 while ($pagenb < $pageposafternote) {
458 $pdf->AddPage();
459 $pagenb++;
460 if (!empty($tplidx)) {
461 $pdf->useTemplate($tplidx);
462 }
463 if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
464 $this->_pagehead($pdf, $object, 0, $outputlangs);
465 }
466 // $this->_pagefoot($pdf,$object,$outputlangs,1);
467 $pdf->setTopMargin($tab_top_newpage);
468 // The only function to edit the bottom margin of current page to set it.
469 $pdf->setPageOrientation('', true, $heightforfooter + $heightforfreetext);
470 }
471
472 // back to start
473 $pdf->setPage($pageposbeforenote);
474 $pdf->setPageOrientation('', true, $heightforfooter + $heightforfreetext);
475 $pdf->SetFont('', '', $default_font_size - 1);
476 $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top, dol_htmlentitiesbr($notetoshow), 0, 1);
477 $pageposafternote = $pdf->getPage();
478
479 $posyafter = $pdf->GetY();
480
481 if ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + 20))) { // There is no space left for total+free text
482 $pdf->AddPage('', '', true);
483 $pagenb++;
484 $pageposafternote++;
485 $pdf->setPage($pageposafternote);
486 $pdf->setTopMargin($tab_top_newpage);
487 // The only function to edit the bottom margin of current page to set it.
488 $pdf->setPageOrientation('', true, $heightforfooter + $heightforfreetext);
489 //$posyafter = $tab_top_newpage;
490 }
491
492
493 // apply note frame to previous pages
494 $i = $pageposbeforenote;
495 while ($i < $pageposafternote) {
496 $pdf->setPage($i);
497
498
499 $pdf->SetDrawColor(128, 128, 128);
500 // Draw note frame
501 if ($i > $pageposbeforenote) {
502 $height_note = $this->page_hauteur - ($tab_top_newpage + $heightforfooter);
503 $pdf->RoundedRect($this->marge_gauche, $tab_top_newpage - 1, $tab_width, $height_note + 2, $this->corner_radius, '1234', 'D');
504 } else {
505 $height_note = $this->page_hauteur - ($tab_top + $heightforfooter);
506 $pdf->RoundedRect($this->marge_gauche, $tab_top - 1, $tab_width, $height_note + 2, $this->corner_radius, '1234', 'D');
507 }
508
509 // Add footer
510 $pdf->setPageOrientation('', true, 0); // The only function to edit the bottom margin of current page to set it.
511 $this->_pagefoot($pdf, $object, $outputlangs, 1);
512
513 $i++;
514 }
515
516 // apply note frame to last page
517 $pdf->setPage($pageposafternote);
518 if (!empty($tplidx)) {
519 $pdf->useTemplate($tplidx);
520 }
521 if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
522 $this->_pagehead($pdf, $object, 0, $outputlangs);
523 }
524 $height_note = $posyafter - $tab_top_newpage;
525 $pdf->RoundedRect($this->marge_gauche, $tab_top_newpage - 1, $tab_width, $height_note + 2, $this->corner_radius, '1234', 'D');
526 } else {
527 // No pagebreak
528 $pdf->commitTransaction();
529 $posyafter = $pdf->GetY();
530 $height_note = $posyafter - $tab_top;
531 $pdf->RoundedRect($this->marge_gauche, $tab_top - 1, $tab_width, $height_note + 2, $this->corner_radius, '1234', 'D');
532
533
534 if ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + 20))) {
535 // not enough space, need to add page
536 $pdf->AddPage('', '', true);
537 $pagenb++;
538 $pageposafternote++;
539 $pdf->setPage($pageposafternote);
540 if (!empty($tplidx)) {
541 $pdf->useTemplate($tplidx);
542 }
543 if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
544 $this->_pagehead($pdf, $object, 0, $outputlangs);
545 }
546
547 $posyafter = $tab_top_newpage;
548 }
549 }
550 $tab_height -= $height_note;
551 $tab_top = $posyafter + 6;
552 } else {
553 $height_note = 0;
554 }
555
556 // Use new auto column system
557 $this->prepareArrayColumnField($object, $outputlangs, $hidedetails, $hidedesc, $hideref);
558
559 // Table simulation to know the height of the title line
560 $pdf->startTransaction();
561 $this->pdfTabTitles($pdf, $tab_top, $tab_height, $outputlangs, $hidetop);
562 $pdf->rollbackTransaction(true);
563
564 $nexY = $tab_top + $this->tabTitleHeight;
565
566 // Loop on each lines
567 $pageposbeforeprintlines = $pdf->getPage();
568 $pagenb = $pageposbeforeprintlines;
569
570 $pdf_sub_options = array();
571 $pdf_sub_options['titleshowuponpdf'] = 1;
572 $pdf_sub_options['titleshowtotalexludingvatonpdf'] = 1;
573
574 $hidenextline = 0;
575
576 for ($i = 0; $i < $nblines; $i++) {
577 $linePosition = $i + 1;
578 $curY = $nexY;
579
580 $sub_options = $object->lines[$i]->extraparams["subtotal"] ?? array();
581
582
583 if ($object->lines[$i]->special_code == SUBTOTALS_SPECIAL_CODE) {
584 $level = $object->lines[$i]->qty;
585 if ($sub_options) {
586 $hidenextline = 0;
587 if (isset($sub_options['titleshowuponpdf'])) {
588 $pdf_sub_options['titleshowuponpdf'] = isset($pdf_sub_options['titleshowuponpdf']) && $pdf_sub_options['titleshowuponpdf'] < $level ? $pdf_sub_options['titleshowuponpdf'] : $level;
589 } elseif (isset($pdf_sub_options['titleshowuponpdf']) && abs($level) <= $pdf_sub_options['titleshowuponpdf']) {
590 unset($pdf_sub_options['titleshowuponpdf']);
591 }
592 if (isset($sub_options['titleshowtotalexludingvatonpdf'])) {
593 $pdf_sub_options['titleshowtotalexludingvatonpdf'] = isset($pdf_sub_options['titleshowtotalexludingvatonpdf']) && $pdf_sub_options['titleshowtotalexludingvatonpdf'] < $level ? $pdf_sub_options['titleshowtotalexludingvatonpdf'] : $level;
594 } elseif (isset($pdf_sub_options['titleshowtotalexludingvatonpdf']) && abs($level) <= $pdf_sub_options['titleshowtotalexludingvatonpdf']) {
595 unset($pdf_sub_options['titleshowtotalexludingvatonpdf']);
596 }
597 } else {
598 if (isset($pdf_sub_options['titleshowuponpdf']) && abs($level) <= $pdf_sub_options['titleshowuponpdf']) {
599 unset($pdf_sub_options['titleshowuponpdf']);
600 }
601 if (isset($pdf_sub_options['titleshowtotalexludingvatonpdf']) && abs($level) <= $pdf_sub_options['titleshowtotalexludingvatonpdf']) {
602 unset($pdf_sub_options['titleshowtotalexludingvatonpdf']);
603 }
604 }
605 }
606
607 if ($object->lines[$i]->special_code == SUBTOTALS_SPECIAL_CODE && isset($sub_options['subtotalshowtotalexludingvatonpdf']) && getDolGlobalString('SUBTOTAL_HIDE_LINES_UNDER_TITLE')) { // TODO Use $sub_options['titlehidelinesundertitle'] instead of SUBTOTAL_HIDE_LINES_UNDER_TITLE
608 $hidenextline = 0;
609 $pdf_sub_options = array();
610 $pdf_sub_options['titleshowuponpdf'] = 1;
611 $pdf_sub_options['titleshowtotalexludingvatonpdf'] = 1;
612 }
613
614 if ($hidenextline) {
615 $linePosition--;
616 } else {
617 if (($curY + 6) > ($this->page_hauteur - $heightforfooter) || isset($sub_options['titleforcepagebreak']) && !($pdf->getNumPages() == 1 && $curY == $tab_top + $this->tabTitleHeight)) {
618 $object->lines[$i]->pagebreak = true;
619 }
620
621 // in First Check line page break and add page if needed
622 if (isset($object->lines[$i]->pagebreak) && $object->lines[$i]->pagebreak) {
623 // New page
624 $pdf->AddPage();
625 if (!empty($tplidx)) {
626 $pdf->useTemplate($tplidx);
627 }
628
629 $pdf->setPage($pdf->getNumPages());
630 $nexY = $curY = $tab_top_newpage;
631 }
632
633 $this->resetAfterColsLinePositionsData($nexY, $pdf->getPage());
634
635 $pdf->SetFont('', '', $default_font_size - 1); // Into loop to work with multipage
636 $pdf->SetTextColor(0, 0, 0);
637
638 // Define size of image if we need it
639 $imglinesize = array();
640 if (!empty($realpatharray[$i])) {
641 $imglinesize = pdf_getSizeForImage($realpatharray[$i]);
642 }
643
644 $pdf->setTopMargin($tab_top_newpage);
645 $pdf->setPageOrientation('', true, $heightforfooter); // The only function to edit the bottom margin of current page to set it.
646 $pageposbefore = $pdf->getPage();
647 $curYBefore = $curY;
648
649 // Allows data in the first page if description is long enough to break in multiples pages
650 $showpricebeforepagebreak = getDolGlobalInt('MAIN_PDF_DATA_ON_FIRST_PAGE');
651
652 $posYAfterImage = 0;
653
654 if ($this->getColumnStatus('photo')) {
655 // We start with Photo of product line
656 $imageTopMargin = 1;
657 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
658 $pdf->AddPage('', '', true);
659 if (!empty($tplidx)) {
660 $pdf->useTemplate($tplidx);
661 }
662 $pdf->setPage($pageposbefore + 1);
663 $pdf->setPageOrientation('', true, $heightforfooter); // The only function to edit the bottom margin of current page to set it.
664 $curY = $tab_top_newpage;
665 $showpricebeforepagebreak = 0;
666 }
667
668 $pdf->setPageOrientation('', false, $heightforfooter + $heightforfreetext); // The only function to edit the bottom margin of current page to set it.
669 // @phan-suppress-next-line PhanTypeMismatchProperty
670 if (!empty($this->cols['photo']) && isset($imglinesize['width']) && isset($imglinesize['height'])) {
671 $pdf->Image($realpatharray[$i], $this->getColumnContentXStart('photo'), $curY + $imageTopMargin, $imglinesize['width'], $imglinesize['height'], '', '', '', 2, 300); // Use 300 dpi
672 // $pdf->Image does not increase value return by getY, so we save it manually
673 $posYAfterImage = $curY + $imglinesize['height'];
674
675 $this->setAfterColsLinePositionsData('photo', $posYAfterImage, $pdf->getPage());
676 }
677 }
678
679 // restore Page orientation for text
680 $pdf->setPageOrientation('', true, $heightforfooter); // The only function to edit the bottom margin of current page to set it.
681
682 if ($this->getColumnStatus('desc')) {
683 if ($object->lines[$i]->special_code != SUBTOTALS_SPECIAL_CODE) {
684 $this->printColDescContent($pdf, $curY, 'desc', $object, $i, $outputlangs, $hideref, $hidedesc);
685 $this->setAfterColsLinePositionsData('desc', $pdf->GetY(), $pdf->getPage());
686 } else {
687 $bg_color = colorStringToArray(getDolGlobalString("SUBTOTAL_BACK_COLOR_LEVEL_".abs($object->lines[$i]->qty), 'ffffff'));
688 pdf_render_subtotals($pdf, $this, $curY, $object, $i, $outputlangs, $hideref, $hidedesc, $bg_color, true, true);
689 }
690 }
691
692 $afterPosData = $this->getMaxAfterColsLinePositionsData();
693 $pdf->setPage($pageposbefore);
694 $pdf->setTopMargin($this->marge_haute);
695 $curY = $curYBefore;
696 $pdf->setPageOrientation('', false, $heightforfooter); // The only function to edit the bottom margin of current page to set it.
697
698
699 // We suppose that a too long description or photo were moved completely on next page
700 if ($afterPosData['page'] > $pageposbefore && (empty($showpricebeforepagebreak) || ($curY + 4) > ($this->page_hauteur - $heightforfooter))) {
701 $pdf->setPage($afterPosData['page']);
702 $curY = $tab_top_newpage;
703 }
704
705 $pdf->SetFont('', '', $default_font_size - 1); // We reposition the default font
706
707
708 // # of line
709 if ($this->getColumnStatus('position')) {
710 $this->printStdColumnContent($pdf, $curY, 'position', strval($linePosition));
711 }
712
713 // VAT Rate
714 if ($this->getColumnStatus('vat') && $object->lines[$i]->special_code != SUBTOTALS_SPECIAL_CODE) {
715 $vat_rate = pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails);
716 $this->printStdColumnContent($pdf, $curY, 'vat', $vat_rate);
717 }
718
719 // Unit price before discount
720 if ($this->getColumnStatus('subprice') && $object->lines[$i]->special_code != SUBTOTALS_SPECIAL_CODE && isset($pdf_sub_options['titleshowuponpdf'])) {
721 $up_excl_tax = pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails);
722 $this->printStdColumnContent($pdf, $curY, 'subprice', $up_excl_tax);
723 }
724
725 // Quantity
726 // Enough for 6 chars
727 if ($this->getColumnStatus('qty') && $object->lines[$i]->special_code != SUBTOTALS_SPECIAL_CODE) {
728 $qty = pdf_getlineqty($object, $i, $outputlangs, $hidedetails);
729 $this->printStdColumnContent($pdf, $curY, 'qty', $qty);
730 }
731
732
733 // Unit
734 if ($this->getColumnStatus('unit') && $object->lines[$i]->special_code != SUBTOTALS_SPECIAL_CODE) {
735 $unit = pdf_getlineunit($object, $i, $outputlangs, $hidedetails);
736 $this->printStdColumnContent($pdf, $curY, 'unit', $unit);
737 }
738
739 // Discount on line
740 if ($this->getColumnStatus('discount') && $object->lines[$i]->special_code != SUBTOTALS_SPECIAL_CODE && $object->lines[$i]->remise_percent) {
741 $remise_percent = pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails);
742 $this->printStdColumnContent($pdf, $curY, 'discount', $remise_percent);
743 }
744
745 // Total excl tax line (HT)
746 if ($this->getColumnStatus('totalexcltax')) {
747 if ($object->lines[$i]->special_code != SUBTOTALS_SPECIAL_CODE && isset($pdf_sub_options['titleshowtotalexludingvatonpdf'])) {
748 $total_excl_tax = pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails);
749 $this->printStdColumnContent($pdf, $curY, 'totalexcltax', $total_excl_tax);
750 } elseif ($object->lines[$i]->qty < 0 && isset($sub_options['subtotalshowtotalexludingvatonpdf'])) {
751 if (isModEnabled('multicurrency') && $object->multicurrency_code != $conf->currency) {
752 $total_excl_tax = $object->getSubtotalLineMulticurrencyAmount($object->lines[$i]);
753 } else {
754 $total_excl_tax = $object->getSubtotalLineAmount($object->lines[$i]);
755 }
756 $this->printStdColumnContent($pdf, $curY, 'totalexcltax', $total_excl_tax);
757 }
758 }
759
760 // Total with tax line (TTC)
761 if ($this->getColumnStatus('totalincltax')) {
762 $total_incl_tax = pdf_getlinetotalwithtax($object, $i, $outputlangs, $hidedetails);
763 $this->printStdColumnContent($pdf, $curY, 'totalincltax', $total_incl_tax);
764 }
765
766 // Extrafields
767 if (!empty($object->lines[$i]->array_options)) {
768 foreach ($object->lines[$i]->array_options as $extrafieldColKey => $extrafieldValue) {
769 if ($this->getColumnStatus($extrafieldColKey)) {
770 $extrafieldValue = $this->getExtrafieldContent($object->lines[$i], $extrafieldColKey, $outputlangs);
771 $this->printStdColumnContent($pdf, $curY, $extrafieldColKey, $extrafieldValue);
772
773 $this->setAfterColsLinePositionsData('options_'.$extrafieldColKey, $pdf->GetY(), $pdf->getPage());
774 }
775 }
776 }
777
778 $afterPosData = $this->getMaxAfterColsLinePositionsData();
779 $parameters = array(
780 'object' => $object,
781 'i' => $i,
782 'pdf' => & $pdf,
783 'curY' => & $curY,
784 'nexY' => & $afterPosData['y'], // for backward module hook compatibility Y will be accessible by $object->getMaxAfterColsLinePositionsData()
785 'outputlangs' => $outputlangs,
786 'hidedetails' => $hidedetails
787 );
788 $reshook = $hookmanager->executeHooks('printPDFline', $parameters, $this); // Note that $object may have been modified by hook
789 }
790
791 // Collection of totals by value of vat in $this->tva["rate"] = total_tva
792 if (isModEnabled("multicurrency") && $object->multicurrency_tx != 1) {
793 $tvaligne = $object->lines[$i]->multicurrency_total_tva;
794 } else {
795 $tvaligne = $object->lines[$i]->total_tva;
796 }
797
798 $localtax1ligne = $object->lines[$i]->total_localtax1;
799 $localtax2ligne = $object->lines[$i]->total_localtax2;
800 $localtax1_rate = $object->lines[$i]->localtax1_tx;
801 $localtax2_rate = $object->lines[$i]->localtax2_tx;
802 $localtax1_type = $object->lines[$i]->localtax1_type;
803 $localtax2_type = $object->lines[$i]->localtax2_type;
804
805 // TODO remise_percent is an obsolete field for object parent
806 /*if ($object->remise_percent) {
807 $tvaligne -= ($tvaligne * $object->remise_percent) / 100;
808 }
809 if ($object->remise_percent) {
810 $localtax1ligne -= ($localtax1ligne * $object->remise_percent) / 100;
811 }
812 if ($object->remise_percent) {
813 $localtax2ligne -= ($localtax2ligne * $object->remise_percent) / 100;
814 }*/
815
816 $vatrate = (string) $object->lines[$i]->tva_tx;
817
818 // Retrieve type from database for backward compatibility with old records
819 if ((!isset($localtax1_type) || $localtax1_type == '' || !isset($localtax2_type) || $localtax2_type == '') // if tax type not defined
820 && (!empty($localtax1_rate) || !empty($localtax2_rate))) { // and there is local tax
821 $localtaxtmp_array = getLocalTaxesFromRate($vatrate, 0, $object->thirdparty, $mysoc);
822 $localtax1_type = isset($localtaxtmp_array[0]) ? $localtaxtmp_array[0] : '';
823 $localtax2_type = isset($localtaxtmp_array[2]) ? $localtaxtmp_array[2] : '';
824 }
825
826 // retrieve global local tax
827 if ($localtax1_type && $localtax1ligne != 0) {
828 if (empty($this->localtax1[$localtax1_type][$localtax1_rate])) {
829 $this->localtax1[$localtax1_type][$localtax1_rate] = $localtax1ligne;
830 } else {
831 $this->localtax1[$localtax1_type][$localtax1_rate] += $localtax1ligne;
832 }
833 }
834 if ($localtax2_type && $localtax2ligne != 0) {
835 if (empty($this->localtax2[$localtax2_type][$localtax2_rate])) {
836 $this->localtax2[$localtax2_type][$localtax2_rate] = $localtax2ligne;
837 } else {
838 $this->localtax2[$localtax2_type][$localtax2_rate] += $localtax2ligne;
839 }
840 }
841
842 if (($object->lines[$i]->info_bits & 0x01) == 0x01) {
843 $vatrate .= '*';
844 }
845
846 // Fill $this->tva and $this->tva_array
847 if (!isset($this->tva[$vatrate])) {
848 $this->tva[$vatrate] = 0;
849 }
850 $this->tva[$vatrate] += $tvaligne;
851 $vatcode = $object->lines[$i]->vat_src_code;
852 if (empty($this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'])) {
853 $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'] = 0;
854 }
855 $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')] = array('vatrate' => $vatrate, 'vatcode' => $vatcode, 'amount' => $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'] + $tvaligne);
856
857
858 if (!$hidenextline) {
859 $afterPosData = $this->getMaxAfterColsLinePositionsData();
860 $pdf->setPage($afterPosData['page']);
861 $nexY = $afterPosData['y'];
862
863 // Add line
864 if (getDolGlobalString('MAIN_PDF_DASH_BETWEEN_LINES') && $i < ($nblines - 1) && $afterPosData['y'] < $this->page_hauteur - $heightforfooter - 5) {
865 $pdf->SetLineStyle(array('dash' => '1,1', 'color' => array(80, 80, 80)));
866 //$pdf->SetDrawColor(190,190,200);
867 $pdf->line($this->marge_gauche, $nexY, $this->page_largeur - $this->marge_droite, $nexY);
868 $pdf->SetLineStyle(array('dash' => 0));
869 }
870 }
871
872 if ($object->lines[$i]->special_code == SUBTOTALS_SPECIAL_CODE && (isset($sub_options['titleshowuponpdf']) || isset($sub_options['titleshowtotalexludingvatonpdf'])) && getDolGlobalString('SUBTOTAL_HIDE_LINES_UNDER_TITLE')) { // TODO Use $sub_options['titlehidelinesundertitle'] instead of SUBTOTAL_HIDE_LINES_UNDER_TITLE
873 $hidenextline = 1;
874 }
875
876 $nexY += 0; // Add space between lines
877 }
878
879
880 // Add last page for document footer if there are not enough size left
881 $afterPosData = $this->getMaxAfterColsLinePositionsData();
882 if (isset($afterPosData['y']) && $afterPosData['y'] > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforsignature + $heightforinfotot))) {
883 $pdf->AddPage();
884 if (!empty($tplidx)) {
885 $pdf->useTemplate($tplidx);
886 }
887 $pagenb++;
888 $pdf->setPage($pagenb);
889 }
890
891 // Draw table frames and columns borders
892 $drawTabNumbPage = $pdf->getNumPages();
893 for ($i = $pageposbeforeprintlines; $i <= $drawTabNumbPage; $i++) {
894 $pdf->setPage($i);
895 // reset page orientation each loop to override it if it was changed
896 $pdf->setPageOrientation('', false, 0); // The only function to edit the bottom margin of current page to set it.
897
898 $drawTabHideTop = $hidetop;
899 $drawTabTop = $tab_top_newpage;
900 $drawTabBottom = $this->page_hauteur - $heightforfooter;
901 $hideBottom = 0; // TODO understand why it change to 1 or 0 during process
902
903 if ($i == $pageposbeforeprintlines) {
904 // first page need to start after notes
905 $drawTabTop = $tab_top;
906 } elseif (!$drawTabHideTop) {
907 if (getDolGlobalInt('MAIN_PDF_ENABLE_COL_HEAD_TITLE_REPEAT')) {
908 $drawTabTop -= $this->tabTitleHeight;
909 } else {
910 $drawTabHideTop = 1;
911 }
912 }
913
914 // last page need to include document footer
915 if ($i == $pdf->getNumPages()) {
916 // remove document footer height to tab bottom position
917 $drawTabBottom -= $heightforsignature + $heightforfreetext + $heightforinfotot;
918 }
919
920 $drawTabHeight = $drawTabBottom - $drawTabTop;
921 $this->_tableau($pdf, $drawTabTop, $drawTabHeight, 0, $outputlangs, $drawTabHideTop, $hideBottom, $object->multicurrency_code, $outputlangsbis);
922
923 $hideFreeText = $i != $pdf->getNumPages() ? 1 : 0; // Display free text only in last page
924 $this->_pagefoot($pdf, $object, $outputlangs, $hideFreeText);
925
926 $pdf->setPage($i); // in case of _pagefoot or _tableau change it
927
928 // reset page orientation each loop to override it if it was changed by _pagefoot or _tableau change it
929 $pdf->setPageOrientation('', true, 0); // The only function to edit the bottom margin of current page to set it.
930
931 // Don't print head on first page ($pageposbeforeprintlines) because already added previously
932 if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD') && $i != $pageposbeforeprintlines) {
933 $this->_pagehead($pdf, $object, 0, $outputlangs);
934 }
935 if (!empty($tplidx)) {
936 $pdf->useTemplate($tplidx);
937 }
938 }
939
940 // reset text color before print footers
941 $pdf->SetTextColor(0, 0, 0);
942
943 $pdf->setPage($pdf->getNumPages());
944
945 $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforsignature - $heightforfooter + 1;
946
947 // Display infos area
948 $posy = $this->drawInfoTable($pdf, $object, $bottomlasttab, $outputlangs);
949
950 // Display total zone
951 $posy = $this->drawTotalTable($pdf, $object, 0, $bottomlasttab, $outputlangs);
952
953 // Customer signature area
954 if (!getDolGlobalString('PROPAL_DISABLE_SIGNATURE')) {
955 $posy = $this->drawSignatureArea($pdf, $object, $posy, $outputlangs);
956
957 // Rewrite keywords to add a tag with the numero of page that contains the signature section
958 $keywords = $outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("PdfCommercialProposalTitle")." ".$outputlangs->convToOutputCharset($object->thirdparty->name);
959 $pdf->SetKeyWords($keywords." PAGESIGN=".$pdf->getPage());
960 }
961
962 // Add number of pages in footer
963 if (method_exists($pdf, 'AliasNbPages')) {
964 $pdf->AliasNbPages(); // @phan-suppress-current-line PhanUndeclaredMethod
965 }
966
967 // Add terms to sale
968 $termsofsalefilename = getDolGlobalString('MAIN_INFO_PROPAL_TERMSOFSALE');
969 if (getDolGlobalInt('MAIN_PDF_ADD_TERMSOFSALE_PROPAL') && $termsofsalefilename) {
970 $termsofsale = $conf->propal->dir_output.'/'.$termsofsalefilename;
971 if (!empty($conf->propal->multidir_output[$object->entity ?? $conf->entity])) {
972 $termsofsale = $conf->propal->multidir_output[$object->entity ?? $conf->entity].'/'.$termsofsalefilename;
973 }
974 if (file_exists($termsofsale) && is_readable($termsofsale)) {
975 $pagecount = $pdf->setSourceFile($termsofsale);
976 for ($i = 1; $i <= $pagecount; $i++) {
977 $tplIdx = $pdf->importPage($i);
978 if ($tplIdx !== false) {
979 $s = $pdf->getTemplatesize($tplIdx);
980 $pdf->AddPage($s['h'] > $s['w'] ? 'P' : 'L');
981 $pdf->useTemplate($tplIdx);
982 } else {
983 setEventMessages(null, array($termsofsale.' cannot be added, probably protected PDF'), 'warnings');
984 }
985 }
986 }
987 }
988
989 //If propal merge product PDF is active
990 if (getDolGlobalString('PRODUIT_PDF_MERGE_PROPAL')) {
991 require_once DOL_DOCUMENT_ROOT.'/product/class/propalmergepdfproduct.class.php';
992
993 $already_merged = array();
994 foreach ($object->lines as $line) {
995 if (!empty($line->fk_product) && !(in_array($line->fk_product, $already_merged))) {
996 // Find the desired PDF
997 $filetomerge = new Propalmergepdfproduct($this->db);
998
999 if (getDolGlobalInt('MAIN_MULTILANGS')) {
1000 $filetomerge->fetch_by_product($line->fk_product, $outputlangs->defaultlang);
1001 } else {
1002 $filetomerge->fetch_by_product($line->fk_product);
1003 }
1004
1005 $already_merged[] = $line->fk_product;
1006
1007 $product = new Product($this->db);
1008 $product->fetch($line->fk_product);
1009
1010 if ($product->entity != $conf->entity) {
1011 $entity_product_file = $product->entity;
1012 } else {
1013 $entity_product_file = $conf->entity;
1014 }
1015
1016 // If PDF is selected and file is not empty
1017 if (count($filetomerge->lines) > 0) {
1018 foreach ($filetomerge->lines as $linefile) {
1019 if (!empty($linefile->id) && !empty($linefile->file_name)) {
1020 $filetomerge_dir = null;
1021 if (getDolGlobalInt('PRODUCT_USE_OLD_PATH_FOR_PHOTO')) {
1022 if (isModEnabled("product")) {
1023 $filetomerge_dir = $conf->product->multidir_output[$entity_product_file ?? $conf->entity].'/'.get_exdir($product->id, 2, 0, 0, $product, 'product').$product->id."/photos";
1024 } elseif (isModEnabled("service")) {
1025 $filetomerge_dir = $conf->service->multidir_output[$entity_product_file ?? $conf->entity].'/'.get_exdir($product->id, 2, 0, 0, $product, 'product').$product->id."/photos";
1026 }
1027 } else {
1028 if (isModEnabled("product")) {
1029 $filetomerge_dir = $conf->product->multidir_output[$entity_product_file ?? $conf->entity].'/'.get_exdir(0, 0, 0, 0, $product, 'product');
1030 } elseif (isModEnabled("service")) {
1031 $filetomerge_dir = $conf->service->multidir_output[$entity_product_file ?? $conf->entity].'/'.get_exdir(0, 0, 0, 0, $product, 'product');
1032 }
1033 }
1034
1035 dol_syslog(get_class($this).':: upload_dir='.$filetomerge_dir, $filetomerge_dir === null ? LOG_ERR : LOG_DEBUG);
1036 if ($filetomerge_dir === null) {
1037 // Skip loop
1038 continue;
1039 }
1040
1041 $infile = $filetomerge_dir.'/'.$linefile->file_name;
1042 if (file_exists($infile) && is_readable($infile)) {
1043 $pagecount = $pdf->setSourceFile($infile);
1044 for ($i = 1; $i <= $pagecount; $i++) {
1045 $tplIdx = $pdf->importPage($i);
1046 if ($tplIdx !== false) {
1047 $s = $pdf->getTemplatesize($tplIdx);
1048 $pdf->AddPage($s['h'] > $s['w'] ? 'P' : 'L');
1049 $pdf->useTemplate($tplIdx);
1050 } else {
1051 setEventMessages(null, array($infile.' cannot be added, probably protected PDF'), 'warnings');
1052 }
1053 }
1054 }
1055 }
1056 }
1057 }
1058 }
1059 }
1060 }
1061
1062 $pdf->Close();
1063
1064 $pdf->Output($file, 'F');
1065
1066 //Add pdfgeneration hook
1067 $hookmanager->initHooks(array('pdfgeneration'));
1068 $parameters = array('file' => $file, 'object' => $object, 'outputlangs' => $outputlangs);
1069 global $action;
1070 $reshook = $hookmanager->executeHooks('afterPDFCreation', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1071 $this->warnings = $hookmanager->warnings;
1072 if ($reshook < 0) {
1073 $this->error = $hookmanager->error;
1074 $this->errors = $hookmanager->errors;
1075 dolChmod($file);
1076 return -1;
1077 }
1078
1079 dolChmod($file);
1080
1081 $this->result = array('fullpath' => $file);
1082
1083 return 1; // No error
1084 } else {
1085 $this->error = $langs->trans("ErrorCanNotCreateDir", $dir);
1086 return 0;
1087 }
1088 } else {
1089 $this->error = $langs->trans("ErrorConstantNotDefined", "PROP_OUTPUTDIR");
1090 return 0;
1091 }
1092 }
1093
1103 public function drawInfoTable(&$pdf, $object, $posy, $outputlangs)
1104 {
1105 global $mysoc;
1106
1107 $default_font_size = pdf_getPDFFontSize($outputlangs);
1108
1109 $pdf->SetFont('', '', $default_font_size - 1);
1110
1111 $diffsizetitle = getDolGlobalInt('PDF_DIFFSIZE_TITLE', 3);
1112
1113 // If France, show VAT mention if not applicable
1114 if ($this->emetteur->country_code == 'FR' && empty($mysoc->tva_assuj)) {
1115 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
1116 $pdf->SetXY($this->marge_gauche, $posy);
1117 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("VATIsNotUsedForInvoice"), 0, 'L', false);
1118
1119 $posy = $pdf->GetY() + 4;
1120 }
1121
1122 $posxval = 52;
1123 if (getDolGlobalString('MAIN_PDF_DELIVERY_DATE_TEXT')) {
1124 $displaydate = "daytext";
1125 } else {
1126 $displaydate = "day";
1127 }
1128
1129 // Show shipping date
1130 if (!empty($object->delivery_date)) {
1131 $outputlangs->load("sendings");
1132 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
1133 $pdf->SetXY($this->marge_gauche, $posy);
1134 $titre = $outputlangs->transnoentities("DateDeliveryPlanned").':';
1135 $pdf->MultiCell(80, 4, $titre, 0, 'L');
1136 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
1137 $pdf->SetXY($posxval, $posy);
1138 $dlp = dol_print_date($object->delivery_date, $displaydate, false, $outputlangs, true);
1139 $pdf->MultiCell(80, 4, $dlp, 0, 'L');
1140
1141 $posy = $pdf->GetY() + 1;
1142 } elseif ($object->availability_code || $object->availability) { // Show availability conditions
1143 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
1144 $pdf->SetXY($this->marge_gauche, $posy);
1145 $titre = $outputlangs->transnoentities("AvailabilityPeriod").':';
1146 $pdf->MultiCell(80, 4, $titre, 0, 'L');
1147 $pdf->SetTextColor(0, 0, 0);
1148 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
1149 $pdf->SetXY($posxval, $posy);
1150 $lib_availability = ($outputlangs->transnoentities("AvailabilityType".$object->availability_code) != 'AvailabilityType'.$object->availability_code) ? $outputlangs->transnoentities("AvailabilityType".$object->availability_code) : $outputlangs->convToOutputCharset($object->availability);
1151 $lib_availability = str_replace('\n', "\n", $lib_availability);
1152 $pdf->MultiCell(80, 4, $lib_availability, 0, 'L');
1153
1154 $posy = $pdf->GetY() + 1;
1155 }
1156
1157 // Show delivery mode
1158 if (!getDolGlobalString('PROPOSAL_PDF_HIDE_DELIVERYMODE') && $object->shipping_method_id > 0) {
1159 $outputlangs->load("sendings");
1160
1161 $shipping_method_id = $object->shipping_method_id;
1162 if (getDolGlobalString('SOCIETE_ASK_FOR_SHIPPING_METHOD') && !empty($this->emetteur->shipping_method_id)) {
1163 $shipping_method_id = $this->emetteur->shipping_method_id;
1164 }
1165 $shipping_method_code = dol_getIdFromCode($this->db, (string) $shipping_method_id, 'c_shipment_mode', 'rowid', 'code');
1166 $shipping_method_label = dol_getIdFromCode($this->db, (string) $shipping_method_id, 'c_shipment_mode', 'rowid', 'libelle');
1167
1168 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
1169 $pdf->SetXY($this->marge_gauche, $posy);
1170 $titre = $outputlangs->transnoentities("SendingMethod").':';
1171 $pdf->MultiCell(43, 4, $titre, 0, 'L');
1172
1173 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
1174 $pdf->SetXY($posxval, $posy);
1175 $lib_condition_paiement = ($outputlangs->transnoentities("SendingMethod".strtoupper($shipping_method_code)) != "SendingMethod".strtoupper($shipping_method_code)) ? $outputlangs->trans("SendingMethod".strtoupper($shipping_method_code)) : $shipping_method_label;
1176 $lib_condition_paiement = str_replace('\n', "\n", $lib_condition_paiement);
1177 $pdf->MultiCell(67, 4, $lib_condition_paiement, 0, 'L');
1178
1179 $posy = $pdf->GetY() + 1;
1180 }
1181
1182 // Show payments conditions
1183 if (!getDolGlobalString('PROPOSAL_PDF_HIDE_PAYMENTTERM') && $object->cond_reglement_code) {
1184 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
1185 $pdf->SetXY($this->marge_gauche, $posy);
1186 $titre = $outputlangs->transnoentities("PaymentConditions").':';
1187 $pdf->MultiCell(43, 4, $titre, 0, 'L');
1188
1189 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
1190 $pdf->SetXY($posxval, $posy);
1191 $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);
1192 $lib_condition_paiement = str_replace('\n', "\n", $lib_condition_paiement);
1193 if ($object->deposit_percent > 0) {
1194 $lib_condition_paiement = str_replace('__DEPOSIT_PERCENT__', $object->deposit_percent, $lib_condition_paiement);
1195 }
1196 $pdf->MultiCell(67, 4, $lib_condition_paiement, 0, 'L');
1197
1198 $posy = $pdf->GetY() + 3;
1199 }
1200
1201 if (!getDolGlobalString('PROPOSAL_PDF_HIDE_PAYMENTMODE')) {
1202 // Show payment mode
1203 if ($object->mode_reglement_code
1204 && $object->mode_reglement_code != 'CHQ'
1205 && $object->mode_reglement_code != 'VIR') {
1206 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
1207 $pdf->SetXY($this->marge_gauche, $posy);
1208 $titre = $outputlangs->transnoentities("PaymentMode").':';
1209 $pdf->MultiCell(80, 5, $titre, 0, 'L');
1210 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
1211 $pdf->SetXY($posxval, $posy);
1212 $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);
1213 $pdf->MultiCell(80, 5, $lib_mode_reg, 0, 'L');
1214
1215 $posy = $pdf->GetY() + 2;
1216 }
1217
1218 // Show payment mode CHQ
1219 if (empty($object->mode_reglement_code) || $object->mode_reglement_code == 'CHQ') {
1220 // Si mode reglement non force ou si force a CHQ
1221 if (getDolGlobalInt('FACTURE_CHQ_NUMBER')) {
1222 if (getDolGlobalInt('FACTURE_CHQ_NUMBER') > 0) {
1223 $account = new Account($this->db);
1224 $account->fetch(getDolGlobalInt('FACTURE_CHQ_NUMBER'));
1225
1226 $pdf->SetXY($this->marge_gauche, $posy);
1227 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
1228 $pdf->MultiCell(100, 3, $outputlangs->transnoentities('PaymentByChequeOrderedTo', $account->owner_name), 0, 'L', false);
1229 $posy = $pdf->GetY() + 1;
1230
1231 if (!getDolGlobalString('MAIN_PDF_HIDE_CHQ_ADDRESS')) {
1232 $pdf->SetXY($this->marge_gauche, $posy);
1233 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
1234 $pdf->MultiCell(100, 3, $outputlangs->convToOutputCharset($account->owner_address), 0, 'L', false);
1235 $posy = $pdf->GetY() + 2;
1236 }
1237 }
1238 if (getDolGlobalInt('FACTURE_CHQ_NUMBER') == -1) {
1239 $pdf->SetXY($this->marge_gauche, $posy);
1240 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
1241 $pdf->MultiCell(100, 3, $outputlangs->transnoentities('PaymentByChequeOrderedTo', $this->emetteur->name), 0, 'L', false);
1242 $posy = $pdf->GetY() + 1;
1243
1244 if (!getDolGlobalString('MAIN_PDF_HIDE_CHQ_ADDRESS')) {
1245 $pdf->SetXY($this->marge_gauche, $posy);
1246 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
1247 $pdf->MultiCell(100, 3, $outputlangs->convToOutputCharset($this->emetteur->getFullAddress()), 0, 'L', false);
1248 $posy = $pdf->GetY() + 2;
1249 }
1250 }
1251 }
1252 }
1253
1254 // If payment mode not forced or forced to VIR, show payment with BAN
1255 if (empty($object->mode_reglement_code) || $object->mode_reglement_code == 'VIR') {
1256 if ($object->fk_account > 0 || $object->fk_bank > 0 || getDolGlobalInt('FACTURE_RIB_NUMBER')) {
1257 $bankid = ($object->fk_account <= 0 ? getDolGlobalInt('FACTURE_RIB_NUMBER') : $object->fk_account);
1258 if ($object->fk_bank > 0) {
1259 $bankid = $object->fk_bank; // For backward compatibility when object->fk_account is forced with object->fk_bank
1260 }
1261 $account = new Account($this->db);
1262 $account->fetch((int) $bankid);
1263
1264 $curx = $this->marge_gauche;
1265 $cury = $posy;
1266
1267 $posy = pdf_bank($pdf, $outputlangs, $curx, $cury, $account, 0, $default_font_size);
1268
1269 $posy += 2;
1270 }
1271 }
1272 }
1273
1274 return $posy;
1275 }
1276
1277
1289 protected function drawTotalTable(&$pdf, $object, $deja_regle, $posy, $outputlangs, $outputlangsbis = null)
1290 {
1291 global $conf, $mysoc, $hookmanager;
1292
1293 $default_font_size = pdf_getPDFFontSize($outputlangs);
1294
1295 if (getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE') && $outputlangs->defaultlang != getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE')) {
1296 $outputlangsbis = new Translate('', $conf);
1297 $outputlangsbis->setDefaultLang(getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE'));
1298 $outputlangsbis->loadLangs(array("main", "dict", "companies", "bills", "products", "propal"));
1299 $default_font_size--;
1300 }
1301
1302 $tab2_top = $posy;
1303 $tab2_hl = 4;
1304 $pdf->SetFont('', '', $default_font_size - 1);
1305
1306 // Total table
1307 $col1x = 120;
1308 $col2x = 170;
1309 if ($this->page_largeur < 210) { // To work with US executive format
1310 $col2x -= 20;
1311 }
1312 $largcol2 = ($this->page_largeur - $this->marge_droite - $col2x);
1313
1314 $useborder = 0;
1315 $index = 0;
1316
1317 // Get Total HT
1318 $total_ht = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1 ? $object->multicurrency_total_ht : $object->total_ht);
1319
1320 // Total discount
1321 $total_discount_on_lines = 0;
1322 $multicurrency_total_discount_on_lines = 0;
1323 foreach ($object->lines as $i => $line) {
1324 $resdiscount = pdfGetLineTotalDiscountAmount($object, $i, $outputlangs, 2);
1325 $multicurrency_resdiscount = pdfGetLineTotalDiscountAmount($object, $i, $outputlangs, 2, 1);
1326
1327 $total_discount_on_lines += (is_numeric($resdiscount) ? $resdiscount : 0);
1328 $multicurrency_total_discount_on_lines += (is_numeric($multicurrency_resdiscount) ? $multicurrency_resdiscount : 0);
1329 // If line was a negative line, we do not count the discount as a discount
1330 if ($line->total_ht < 0) {
1331 $total_discount_on_lines += -$line->total_ht;
1332 $multicurrency_total_discount_on_lines += -$line->multicurrency_total_ht;
1333 }
1334 }
1335
1336 if ($total_discount_on_lines > 0) {
1337 if ($this->showAmountBeforeDiscount) {
1338 // Show total NET before discount
1339 $pdf->SetFillColor(255, 255, 255);
1340 $pdf->SetXY($col1x, $tab2_top);
1341 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalHTBeforeDiscount") . (is_object($outputlangsbis) ? ' / ' . $outputlangsbis->transnoentities("TotalHTBeforeDiscount") : ''), 0, 'L', true);
1342 $pdf->SetXY($col2x, $tab2_top);
1343
1344 $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));
1345 $pdf->MultiCell($largcol2, $tab2_hl, price($total_before_discount_to_show, 0, $outputlangs), 0, 'R', true);
1346
1347 $index++;
1348 }
1349
1350 if ($this->showDiscountAmount) {
1351 $pdf->SetFillColor(255, 255, 255);
1352 $pdf->SetXY($col1x, $tab2_top + $tab2_hl);
1353 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalDiscount") . (is_object($outputlangsbis) ? ' / ' . $outputlangsbis->transnoentities("TotalDiscount") : ''), 0, 'L', true);
1354 $pdf->SetXY($col2x, $tab2_top + $tab2_hl);
1355
1356 $total_discount_to_show = ((isModEnabled("multicurrency") && $object->multicurrency_tx != 1) ? $multicurrency_total_discount_on_lines : $total_discount_on_lines);
1357 $pdf->MultiCell($largcol2, $tab2_hl, price($total_discount_to_show, 0, $outputlangs), 0, 'R', true);
1358
1359 $index++;
1360 }
1361 }
1362
1363 // Total HT
1364 $pdf->SetFillColor(255, 255, 255);
1365 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1366 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalHT").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transnoentities("TotalHT") : ''), 0, 'L', true);
1367
1368 $total_ht = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? $object->multicurrency_total_ht : $object->total_ht);
1369 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1370 $pdf->MultiCell($largcol2, $tab2_hl, price($total_ht + (!empty($object->remise) ? $object->remise : 0), 0, $outputlangs), 0, 'R', true);
1371
1372 // Show VAT by rates and total
1373 $pdf->SetFillColor(248, 248, 248);
1374
1375 $total_ttc = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1) ? $object->multicurrency_total_ttc : $object->total_ttc;
1376 $total_ttc_origin = $object->total_ttc;
1377
1378 $this->atleastoneratenotnull = 0;
1379 if (!getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT')) {
1380 $tvaisnull = (!empty($this->tva) && count($this->tva) == 1 && isset($this->tva['0.000']) && is_float($this->tva['0.000']));
1381 if (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_IFNULL') && $tvaisnull) {
1382 // Nothing to do
1383 } else {
1384 //Local tax 1 before VAT
1385 //if (getDolGlobalString('FACTURE_LOCAL_TAX1_OPTION') && getDolGlobalString('FACTURE_LOCAL_TAX1_OPTION') == 'localtax1on')
1386 //{
1387 foreach ($this->localtax1 as $localtax_type => $localtax_rate) {
1388 if (in_array((string) $localtax_type, array('1', '3', '5'))) {
1389 continue;
1390 }
1391
1392 foreach ($localtax_rate as $tvakey => $tvaval) {
1393 if ($tvakey != 0) { // On affiche pas taux 0
1394 //$this->atleastoneratenotnull++;
1395
1396 $index++;
1397 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1398
1399 $tvacompl = '';
1400 if (preg_match('/\*/', $tvakey)) {
1401 $tvakey = str_replace('*', '', $tvakey);
1402 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1403 }
1404 $totalvat = $outputlangs->transcountrynoentities("TotalLT1", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalLT1", $mysoc->country_code) : '');
1405 $totalvat .= ' ';
1406 $totalvat .= vatrate((string) abs((float) $tvakey), true).$tvacompl;
1407 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1408
1409 $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval);
1410
1411 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1412 $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', true);
1413 }
1414 }
1415 }
1416 //}
1417 //Local tax 2 before VAT
1418 //if (getDolGlobalString('FACTURE_LOCAL_TAX2_OPTION') && getDolGlobalString('FACTURE_LOCAL_TAX2_OPTION') == 'localtax2on')
1419 //{
1420 foreach ($this->localtax2 as $localtax_type => $localtax_rate) {
1421 if (in_array((string) $localtax_type, array('1', '3', '5'))) {
1422 continue;
1423 }
1424
1425 foreach ($localtax_rate as $tvakey => $tvaval) {
1426 if ($tvakey != 0) { // On affiche pas taux 0
1427 //$this->atleastoneratenotnull++;
1428
1429 $index++;
1430 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1431
1432 $tvacompl = '';
1433 if (preg_match('/\*/', $tvakey)) {
1434 $tvakey = str_replace('*', '', $tvakey);
1435 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1436 }
1437 $totalvat = $outputlangs->transcountrynoentities("TotalLT2", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalLT2", $mysoc->country_code) : '');
1438 $totalvat .= ' ';
1439 $totalvat .= vatrate((string) abs((float) $tvakey), true).$tvacompl;
1440 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1441
1442 $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval);
1443
1444 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1445 $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', true);
1446 }
1447 }
1448 }
1449 //}
1450
1451 // VAT
1452 foreach ($this->tva as $tvakey => $tvaval) {
1453 if ($tvakey != 0) { // On affiche pas taux 0
1454 $this->atleastoneratenotnull++;
1455
1456 $index++;
1457 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1458
1459 $tvacompl = '';
1460 if (preg_match('/\*/', $tvakey)) {
1461 $tvakey = str_replace('*', '', $tvakey);
1462 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1463 }
1464 $totalvat = $outputlangs->transcountrynoentities("TotalVAT", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalVAT", $mysoc->country_code) : '');
1465 $totalvat .= ' ';
1466 $totalvat .= vatrate($tvakey, true).$tvacompl;
1467 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1468
1469 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1470 $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', true);
1471 }
1472 }
1473
1474 //Local tax 1 after VAT
1475 //if (getDolGlobalString('FACTURE_LOCAL_TAX1_OPTION') && getDolGlobalString('FACTURE_LOCAL_TAX1_OPTION') == 'localtax1on')
1476 //{
1477 foreach ($this->localtax1 as $localtax_type => $localtax_rate) {
1478 if (in_array((string) $localtax_type, array('2', '4', '6'))) {
1479 continue;
1480 }
1481
1482 foreach ($localtax_rate as $tvakey => $tvaval) {
1483 if ($tvakey != 0) { // On affiche pas taux 0
1484 //$this->atleastoneratenotnull++;
1485
1486 $index++;
1487 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1488
1489 $tvacompl = '';
1490 if (preg_match('/\*/', $tvakey)) {
1491 $tvakey = str_replace('*', '', $tvakey);
1492 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1493 }
1494 $totalvat = $outputlangs->transcountrynoentities("TotalLT1", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalLT1", $mysoc->country_code) : '');
1495 $totalvat .= ' ';
1496
1497 $totalvat .= vatrate((string) abs((float) $tvakey), true).$tvacompl;
1498 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1499
1500 $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval);
1501
1502 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1503 $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', true);
1504 }
1505 }
1506 }
1507 //}
1508 //Local tax 2 after VAT
1509 //if (getDolGlobalString('FACTURE_LOCAL_TAX2_OPTION') && getDolGlobalString('FACTURE_LOCAL_TAX2_OPTION') == 'localtax2on')
1510 //{
1511 foreach ($this->localtax2 as $localtax_type => $localtax_rate) {
1512 if (in_array((string) $localtax_type, array('2', '4', '6'))) {
1513 continue;
1514 }
1515
1516 foreach ($localtax_rate as $tvakey => $tvaval) {
1517 // retrieve global local tax
1518 if ($tvakey != 0) { // On affiche pas taux 0
1519 //$this->atleastoneratenotnull++;
1520
1521 $index++;
1522 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1523
1524 $tvacompl = '';
1525 if (preg_match('/\*/', $tvakey)) {
1526 $tvakey = str_replace('*', '', $tvakey);
1527 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1528 }
1529 $totalvat = $outputlangs->transcountrynoentities("TotalLT2", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalLT2", $mysoc->country_code) : '');
1530 $totalvat .= ' ';
1531
1532 if (getDolGlobalString('PDF_LOCALTAX2_LABEL_IS_CODE_OR_RATE') == 'nocodenorate') {
1533 $totalvat .= $tvacompl;
1534 } else {
1535 $totalvat .= vatrate((string) abs((float) $tvakey), true).$tvacompl;
1536 }
1537
1538 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1539
1540 $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval);
1541
1542 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1543 $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', true);
1544 }
1545 }
1546 }
1547 //}
1548
1549 // Total TTC
1550 $index++;
1551 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1552 $pdf->SetTextColor(0, 0, 60);
1553 $pdf->SetFillColor(224, 224, 224);
1554 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalTTC").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transnoentities("TotalTTC") : ''), $useborder, 'L', true);
1555
1556 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1557 if (!isModEnabled("multicurrency") || $object->multicurrency_tx == 1 || getDolGlobalInt('MULTICURRENCY_SHOW_ALSO_MAIN_CURRENCY_ON_PDF') == 0) {
1558 $pdf->MultiCell($largcol2, $tab2_hl, price($total_ttc, 0, $outputlangs), $useborder, 'R', true);
1559 } else {
1560 $pdf->MultiCell($largcol2, $tab2_hl, price($total_ttc, 0, $outputlangs), $useborder, 'R', true);
1561
1562 //$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');
1563 $index++;
1564 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1565 $pdf->SetTextColor(0, 0, 60);
1566 $pdf->SetFillColor(224, 224, 224);
1567 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalTTC").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transnoentities("TotalTTC") : '').' ('.$outputlangs->getCurrencySymbol($mysoc->currency_code).')', $useborder, 'L', true);
1568
1569 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1570 $pdf->MultiCell($largcol2, $tab2_hl, price($total_ttc_origin, 0, $outputlangs, 1, -1, -1, $mysoc->currency_code), $useborder, 'L', true);
1571 }
1572 }
1573 }
1574
1575 $pdf->SetTextColor(0, 0, 0);
1576
1577 $resteapayer = 0;
1578 /*
1579 $resteapayer = $object->total_ttc - $deja_regle;
1580 if (!empty($object->paye)) $resteapayer=0;
1581 */
1582
1583 if ($deja_regle > 0) {
1584 // Already paid + Deposits
1585 $index++;
1586
1587 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1588 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("AlreadyPaid").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transnoentities("AlreadyPaid") : ''), 0, 'L', false);
1589
1590 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1591 $pdf->MultiCell($largcol2, $tab2_hl, price($deja_regle, 0, $outputlangs), 0, 'R', false);
1592
1593 /*
1594 if ($object->close_code == 'discount_vat') {
1595 $index++;
1596 $pdf->SetFillColor(255,255,255);
1597
1598 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1599 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("EscompteOfferedShort"), $useborder, 'L', 1);
1600
1601 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1602 $pdf->MultiCell($largcol2, $tab2_hl, price($object->total_ttc - $deja_regle, 0, $outputlangs), $useborder, 'R', 1);
1603
1604 $resteapayer=0;
1605 }
1606 */
1607
1608 $index++;
1609 $pdf->SetTextColor(0, 0, 60);
1610 $pdf->SetFillColor(224, 224, 224);
1611 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1612 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("RemainderToPay").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transnoentities("RemainderToPay") : ''), $useborder, 'L', true);
1613
1614 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1615 $pdf->MultiCell($largcol2, $tab2_hl, price($resteapayer, 0, $outputlangs), $useborder, 'R', true);
1616
1617 $pdf->SetFont('', '', $default_font_size - 1);
1618 $pdf->SetTextColor(0, 0, 0);
1619 }
1620
1621 $parameters = array('pdf' => &$pdf, 'object' => &$object, 'outputlangs' => $outputlangs, 'index' => &$index, 'posy' => $posy);
1622
1623 $reshook = $hookmanager->executeHooks('afterPDFTotalTable', $parameters, $this); // Note that $action and $object may have been modified by some hooks
1624 if ($reshook < 0) {
1625 $this->error = $hookmanager->error;
1626 $this->errors = $hookmanager->errors;
1627 }
1628
1629 $index++;
1630 return ($tab2_top + ($tab2_hl * $index));
1631 }
1632
1633 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1648 protected function _tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop = 0, $hidebottom = 0, $currency = '', $outputlangsbis = null)
1649 {
1650 global $conf;
1651
1652 // Force to disable hidetop and hidebottom
1653 $hidebottom = 0;
1654 if ($hidetop) {
1655 $hidetop = -1;
1656 }
1657
1658 $currency = !empty($currency) ? $currency : $conf->currency;
1659 $default_font_size = pdf_getPDFFontSize($outputlangs);
1660
1661 // Amount in (at tab_top - 1)
1662 $pdf->SetTextColor(0, 0, 0);
1663 $pdf->SetFont('', '', $default_font_size - 2);
1664
1665 if (empty($hidetop)) {
1666 $titre = $outputlangs->transnoentities("AmountInCurrency", $outputlangs->transnoentitiesnoconv("Currency".$currency));
1667 if (getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE') && is_object($outputlangsbis)) {
1668 $titre .= ' - '.$outputlangsbis->transnoentities("AmountInCurrency", $outputlangsbis->transnoentitiesnoconv("Currency".$currency));
1669 }
1670
1671 $pdf->SetXY($this->page_largeur - $this->marge_droite - ($pdf->GetStringWidth($titre) + 3), $tab_top - 4);
1672 $pdf->MultiCell(($pdf->GetStringWidth($titre) + 3), 2, $titre);
1673
1674 //$conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR='230,230,230';
1675 if (getDolGlobalString('MAIN_PDF_TITLE_BACKGROUND_COLOR')) {
1676 $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')));
1677 }
1678 }
1679
1680 $pdf->SetDrawColor(128, 128, 128);
1681 $pdf->SetFont('', '', $default_font_size - 1);
1682
1683 // Output Rect
1684 $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
1685
1686 if (getDolGlobalString('MAIN_PDF_TITLE_TEXT_COLOR')) {
1687 $arrayColorTextTitle = explode(',', getDolGlobalString('MAIN_PDF_TITLE_TEXT_COLOR'));
1688 $pdf->SetTextColor((float) $arrayColorTextTitle[0], (float) $arrayColorTextTitle[1], (float) $arrayColorTextTitle[2]);
1689 }
1690
1691 $this->pdfTabTitles($pdf, $tab_top, $tab_height, $outputlangs, $hidetop);
1692
1693 if (getDolGlobalString('MAIN_PDF_TITLE_TEXT_COLOR')) {
1694 $pdf->SetTextColor(0, 0, 0);
1695 }
1696
1697 if (empty($hidetop)) {
1698 $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
1699 }
1700 }
1701
1702 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1713 protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $outputlangsbis = null)
1714 {
1715 global $conf, $langs;
1716
1717 $ltrdirection = 'L';
1718 if ($outputlangs->trans("DIRECTION") == 'rtl') {
1719 $ltrdirection = 'R';
1720 }
1721
1722 // Load traductions files required by page
1723 $outputlangs->loadLangs(array("main", "propal", "companies", "bills"));
1724
1725 $default_font_size = pdf_getPDFFontSize($outputlangs);
1726
1727 pdf_pagehead($pdf, $outputlangs, $this->page_hauteur);
1728
1729 $pdf->SetTextColor(0, 0, 60);
1730 $pdf->SetFont('', 'B', $default_font_size + 3);
1731
1732 $w = 100;
1733
1734 $posy = $this->marge_haute;
1735 $posx = $this->page_largeur - $this->marge_droite - $w;
1736
1737 $pdf->SetXY($this->marge_gauche, $posy);
1738
1739 // Logo
1740 if (!getDolGlobalInt('PDF_DISABLE_MYCOMPANY_LOGO')) {
1741 if ($this->emetteur->logo) {
1742 $logodir = $conf->mycompany->dir_output;
1743 if (!empty($conf->mycompany->multidir_output[$object->entity ?? $conf->entity])) {
1744 $logodir = $conf->mycompany->multidir_output[$object->entity ?? $conf->entity];
1745 }
1746 if (!getDolGlobalInt('MAIN_PDF_USE_LARGE_LOGO')) {
1747 $logo = $logodir.'/logos/thumbs/'.$this->emetteur->logo_small;
1748 } else {
1749 $logo = $logodir.'/logos/'.$this->emetteur->logo;
1750 }
1751 if (is_readable($logo)) {
1752 $height = pdf_getHeightForLogo($logo);
1753 $pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto)
1754 } else {
1755 $pdf->SetTextColor(200, 0, 0);
1756 $pdf->SetFont('', 'B', $default_font_size - 2);
1757 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound", $logo), 0, 'L');
1758 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ErrorGoToGlobalSetup"), 0, 'L');
1759 }
1760 } else {
1761 $text = $this->emetteur->name;
1762 $pdf->MultiCell($w, 4, $outputlangs->convToOutputCharset($text), 0, $ltrdirection);
1763 }
1764 }
1765
1766 $pdf->SetFont('', 'B', $default_font_size + 3);
1767 $pdf->SetXY($posx, $posy);
1768 $pdf->SetTextColor(0, 0, 60);
1769 $title = $outputlangs->transnoentities("PdfCommercialProposalTitle");
1770 $title .= ' '.$outputlangs->convToOutputCharset($object->ref);
1771 if ($object->status == $object::STATUS_DRAFT) {
1772 $pdf->SetTextColor(128, 0, 0);
1773 $title .= ' - '.$outputlangs->transnoentities("NotValidated");
1774 }
1775
1776 $pdf->MultiCell($w, 4, $title, '', 'R');
1777
1778 $pdf->SetFont('', 'B', $default_font_size);
1779
1780 /*
1781 $posy += 5;
1782 $pdf->SetXY($posx, $posy);
1783 $pdf->SetTextColor(0, 0, 60);
1784 $textref = $outputlangs->transnoentities("Ref")." : ".$outputlangs->convToOutputCharset($object->ref);
1785 if ($object->status == $object::STATUS_DRAFT) {
1786 $pdf->SetTextColor(128, 0, 0);
1787 $textref .= ' - '.$outputlangs->transnoentities("NotValidated");
1788 }
1789 $pdf->MultiCell($w, 4, $textref, '', 'R');
1790 */
1791
1792 $posy += 3;
1793 $pdf->SetFont('', '', $default_font_size - 2);
1794
1795 $ref_customer = $object->ref_customer ?: $object->ref_client;
1796 if ($ref_customer) {
1797 $posy += 4;
1798 $pdf->SetXY($posx, $posy);
1799 $pdf->SetTextColor(0, 0, 60);
1800 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("RefCustomer")." : ".dol_trunc($outputlangs->convToOutputCharset($ref_customer), 65), '', 'R');
1801 }
1802
1803 if (getDolGlobalString('PDF_SHOW_PROJECT_TITLE')) {
1804 $object->fetchProject();
1805 if (!empty($object->project->title)) {
1806 $posy += 3;
1807 $pdf->SetXY($posx, $posy);
1808 $pdf->SetTextColor(0, 0, 60);
1809 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("Project")." : ". dol_trunc($object->project->title, 50), '', 'R');
1810 }
1811 }
1812
1813 if (getDolGlobalString('PDF_SHOW_PROJECT')) {
1814 $object->fetchProject();
1815 if (!empty($object->project->ref)) {
1816 $outputlangs->load("projects");
1817 $posy += 3;
1818 $pdf->SetXY($posx, $posy);
1819 $pdf->SetTextColor(0, 0, 60);
1820 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("RefProject")." : ". $object->project->ref, '', 'R');
1821 }
1822 }
1823
1824 if (getDolGlobalString('MAIN_PDF_DATE_TEXT')) {
1825 $displaydate = "daytext";
1826 } else {
1827 $displaydate = "day";
1828 }
1829
1830 //$posy += 4;
1831 $posy = $pdf->getY();
1832 $pdf->SetXY($posx, $posy);
1833 $pdf->SetTextColor(0, 0, 60);
1834 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("Date")." : ".dol_print_date($object->date, $displaydate, false, $outputlangs, true), '', 'R');
1835
1836 $posy += 4;
1837 $pdf->SetXY($posx, $posy);
1838 $pdf->SetTextColor(0, 0, 60);
1839
1840 $title = $outputlangs->transnoentities("DateEndPropal");
1841 if (getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE') && is_object($outputlangsbis)) {
1842 $title .= ' - '.$outputlangsbis->transnoentities("DateEndPropal");
1843 }
1844 $pdf->MultiCell($w, 3, $title." : ".dol_print_date($object->fin_validite, $displaydate, false, $outputlangs, true), '', 'R');
1845
1846 if (!getDolGlobalString('MAIN_PDF_HIDE_CUSTOMER_CODE') && $object->thirdparty->code_client) {
1847 $posy += 4;
1848 $pdf->SetXY($posx, $posy);
1849 $pdf->SetTextColor(0, 0, 60);
1850 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("CustomerCode")." : ".$outputlangs->transnoentities((string) $object->thirdparty->code_client), '', 'R');
1851 }
1852
1853 if (!getDolGlobalString('MAIN_PDF_HIDE_CUSTOMER_ACCOUNTING_CODE') && $object->thirdparty->code_compta_client) {
1854 $posy += 4;
1855 $pdf->SetXY($posx, $posy);
1856 $pdf->SetTextColor(0, 0, 60);
1857 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("CustomerAccountancyCode")." : ".$outputlangs->transnoentities((string) $object->thirdparty->code_compta_client), '', 'R');
1858 }
1859
1860 // Get contact
1861 if (getDolGlobalString('DOC_SHOW_FIRST_SALES_REP')) {
1862 $arrayidcontact = $object->getIdContact('internal', 'SALESREPFOLL');
1863 if (count($arrayidcontact) > 0) {
1864 $usertmp = new User($this->db);
1865 $usertmp->fetch($arrayidcontact[0]);
1866 $posy += 4;
1867 $pdf->SetXY($posx, $posy);
1868 $pdf->SetTextColor(0, 0, 60);
1869 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R');
1870 }
1871 }
1872
1873 $posy += 2;
1874 $shipp_shift = 0;
1875 $top_shift = 0;
1876 // Show list of linked objects
1877 $current_y = $pdf->getY();
1878 $posy = pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, $w, 3, 'R', $default_font_size); // May modify $object->note_public
1879 if ($current_y < $pdf->getY()) {
1880 $top_shift = $pdf->getY() - $current_y;
1881 }
1882
1883 if ($showaddress) {
1884 // Sender properties
1885 $carac_emetteur = '';
1886 // Add internal contact of object if defined
1887 $arrayidcontact = $object->getIdContact('internal', 'SALESREPFOLL');
1888 if (count($arrayidcontact) > 0) {
1889 $object->fetch_user($arrayidcontact[0]);
1890 $labelbeforecontactname = ($outputlangs->transnoentities("FromContactName") != 'FromContactName' ? $outputlangs->transnoentities("FromContactName") : $outputlangs->transnoentities("Name"));
1891 $carac_emetteur .= $labelbeforecontactname." ".$outputlangs->convToOutputCharset($object->user->getFullName($outputlangs));
1892 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') || getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ' (' : '';
1893 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') && !empty($object->user->office_phone)) ? $object->user->office_phone : '';
1894 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') && getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ', ' : '';
1895 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT') && !empty($object->user->email)) ? $object->user->email : '';
1896 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') || getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ')' : '';
1897 $carac_emetteur .= "\n";
1898 }
1899
1900 $carac_emetteur .= pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, '', 0, 'source', $object);
1901
1902 // Show sender
1903 $posy = getDolGlobalString('MAIN_PDF_USE_ISO_LOCATION') ? 30 : 32;
1904 $posy += $top_shift + $this->marge_haute;
1905 $posx = $this->marge_gauche;
1906 if (getDolGlobalString('MAIN_INVERT_SENDER_RECIPIENT')) {
1907 $posx = $this->page_largeur - $this->marge_droite - 80;
1908 }
1909
1910 $hautcadre = getDolGlobalString('MAIN_PDF_USE_ISO_LOCATION') ? 38 : 40;
1911 $widthrecbox = getDolGlobalString('MAIN_PDF_USE_ISO_LOCATION') ? 92 : 82;
1912
1913
1914 // Show sender frame
1915 if (!getDolGlobalString('MAIN_PDF_NO_SENDER_FRAME')) {
1916 $pdf->SetTextColor(0, 0, 0);
1917 $pdf->SetFont('', '', $default_font_size - 2);
1918 $pdf->SetXY($posx, $posy - 5);
1919 $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillFrom"), 0, $ltrdirection);
1920 $pdf->SetXY($posx, $posy);
1921 $pdf->SetFillColor(230, 230, 230);
1922 $pdf->RoundedRect($posx, $posy, $widthrecbox, $hautcadre, $this->corner_radius, '1234', 'F');
1923 $pdf->SetTextColor(0, 0, 60);
1924 }
1925
1926 // Show sender name
1927 if (!getDolGlobalString('MAIN_PDF_HIDE_SENDER_NAME')) {
1928 $pdf->SetXY($posx + 2, $posy + 3);
1929 $pdf->SetFont('', 'B', $default_font_size);
1930 $pdf->MultiCell($widthrecbox - 2, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, $ltrdirection);
1931 $posy = $pdf->getY();
1932 }
1933
1934 // Show sender information
1935 $pdf->SetXY($posx + 2, $posy);
1936 $pdf->SetFont('', '', $default_font_size - 1);
1937 $pdf->MultiCell($widthrecbox - 2, 4, $carac_emetteur, 0, $ltrdirection);
1938
1939
1940 // If CUSTOMER contact defined, we use it
1941 $usecontact = false;
1942 $arrayidcontact = $object->getIdContact('external', 'CUSTOMER');
1943 if (count($arrayidcontact) > 0) {
1944 $usecontact = true;
1945 $result = $object->fetch_contact($arrayidcontact[0]);
1946 }
1947
1948 // Recipient name
1949 if ($usecontact && ($object->contact->socid != $object->thirdparty->id && (!isset($conf->global->MAIN_USE_COMPANY_NAME_OF_CONTACT) || getDolGlobalString('MAIN_USE_COMPANY_NAME_OF_CONTACT')))) {
1950 $thirdparty = $object->contact;
1951 } else {
1952 $thirdparty = $object->thirdparty;
1953 }
1954
1955 $carac_client_name = pdfBuildThirdpartyName($thirdparty, $outputlangs);
1956
1957 $mode = 'target';
1958 $carac_client = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, ($usecontact ? $object->contact : ''), ($usecontact ? 1 : 0), $mode, $object);
1959
1960 // Show recipient
1961 $widthrecbox = getDolGlobalString('MAIN_PDF_USE_ISO_LOCATION') ? 92 : 100;
1962 if ($this->page_largeur < 210) {
1963 $widthrecbox = 84; // To work with US executive format
1964 }
1965 $posy = getDolGlobalString('MAIN_PDF_USE_ISO_LOCATION') ? 30 + $this->marge_haute : 32 + $this->marge_haute;
1966 $posy += $top_shift;
1967 $posx = $this->page_largeur - $this->marge_droite - $widthrecbox;
1968 if (getDolGlobalString('MAIN_INVERT_SENDER_RECIPIENT')) {
1969 $posx = $this->marge_gauche;
1970 }
1971
1972 // Show recipient frame
1973 if (!getDolGlobalString('MAIN_PDF_NO_RECIPENT_FRAME')) {
1974 $pdf->SetTextColor(0, 0, 0);
1975 $pdf->SetFont('', '', $default_font_size - 2);
1976 $pdf->SetXY($posx + 2, $posy - 5);
1977 $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillTo"), 0, $ltrdirection);
1978 $pdf->RoundedRect($posx, $posy, $widthrecbox, $hautcadre, $this->corner_radius, '1234', 'D');
1979 }
1980
1981 // Show recipient name
1982 $pdf->SetXY($posx + 2, $posy + 3);
1983 $pdf->SetFont('', 'B', $default_font_size);
1984 // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
1985 $pdf->MultiCell($widthrecbox, 2, $carac_client_name, 0, $ltrdirection);
1986
1987 $posy = $pdf->getY();
1988
1989 // Show recipient information
1990 $pdf->SetFont('', '', $default_font_size - 1);
1991 $pdf->SetXY($posx + 2, $posy);
1992 // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
1993 $pdf->MultiCell($widthrecbox, 4, $carac_client, 0, $ltrdirection);
1994 // Show shipping/delivery addressAdd commentMore actions
1995 if (getDolGlobalInt('PROPOSAL_SHOW_SHIPPING_ADDRESS')) {
1996 $idaddressshipping = $object->getIdContact('external', 'SHIPPING');
1997
1998 if (!empty($idaddressshipping)) {
1999 $contactshipping = $object->fetch_Contact($idaddressshipping[0]);
2000 $companystatic = new Societe($this->db);
2001 $companystatic->fetch($object->contact->fk_soc);
2002 $carac_client_name_shipping = pdfBuildThirdpartyName($object->contact, $outputlangs);
2003 $carac_client_shipping = pdf_build_address($outputlangs, $this->emetteur, $companystatic, $object->contact, 1, 'target', $object);
2004 } else {
2005 $carac_client_name_shipping = pdfBuildThirdpartyName($object->thirdparty, $outputlangs);
2006 $carac_client_shipping = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, '', 0, 'target', $object);
2007 }
2008 if (!empty($carac_client_shipping)) {
2009 $posy += $hautcadre;
2010
2011 $hautcadre -= 5; // Height for the shipping address does not need to be as high as main box
2012
2013 // Show shipping frame
2014 $pdf->SetXY($posx + 2, $posy - 5);
2015 $pdf->SetFont('', '', $default_font_size - 2);
2016 $pdf->MultiCell($widthrecbox, 0, $outputlangs->transnoentities('ShippingTo'), 0, 'L', false);
2017 $pdf->RoundedRect($posx, $posy, $widthrecbox, $hautcadre, $this->corner_radius, '1234', 'D');
2018
2019 // Show shipping name
2020 $pdf->SetXY($posx + 2, $posy + 3);
2021 $pdf->SetFont('', 'B', $default_font_size);
2022 $pdf->MultiCell($widthrecbox - 2, 2, $carac_client_name_shipping, '', 'L');
2023
2024 $posy = $pdf->getY();
2025
2026 // Show shipping information
2027 $pdf->SetXY($posx + 2, $posy);
2028 $pdf->SetFont('', '', $default_font_size - 1);
2029 $pdf->MultiCell($widthrecbox - 2, 2, $carac_client_shipping, '', 'L');
2030
2031 $shipp_shift += $hautcadre + 10;
2032 }
2033 }
2034 }
2035 $pdf->SetTextColor(0, 0, 0);
2036 return $shipp_shift;
2037 }
2038
2039 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
2049 protected function _pagefoot(&$pdf, $object, $outputlangs, $hidefreetext = 0)
2050 {
2051 $showdetails = getDolGlobalInt('MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS', 0);
2052 return pdf_pagefoot($pdf, $outputlangs, 'PROPOSAL_FREE_TEXT', $this->emetteur, $this->marge_basse, $this->marge_gauche, $this->page_hauteur, $object, $showdetails, $hidefreetext, $this->page_largeur, $this->watermark);
2053 }
2054
2064 protected function drawSignatureArea(&$pdf, $object, $posy, $outputlangs)
2065 {
2066 $default_font_size = pdf_getPDFFontSize($outputlangs);
2067 $tab_top = $posy + 4;
2068 $tab_hl = 4;
2069
2070 $posx = 120;
2071 $largcol = ($this->page_largeur - $this->marge_droite - $posx);
2072
2073 // Total HT
2074 $pdf->SetFillColor(255, 255, 255);
2075 $pdf->SetXY($posx, $tab_top);
2076 $pdf->SetFont('', '', $default_font_size - 2);
2077 $pdf->MultiCell($largcol, $tab_hl, $outputlangs->transnoentities("ProposalCustomerSignature"), 0, 'L', true);
2078
2079 $pdf->SetXY($posx, $tab_top + $tab_hl + 3);
2080 //$pdf->MultiCell($largcol, $tab_hl * 3, '', 1, 'R');
2081 $pdf->RoundedRect($posx, $tab_top + $tab_hl + 3, $largcol, $tab_hl * 3, $this->corner_radius, '1234', 'D');
2082
2083
2084 if (getDolGlobalString('MAIN_PDF_PROPAL_USE_ELECTRONIC_SIGNING')) {
2085 // Can be retrieve with getSignatureAppearanceArray()
2086 // Can be also detected by putting the mouse over the area when using evince pdf reader
2087 $pdf->addEmptySignatureAppearance($posx, $tab_top + $tab_hl + 3, $largcol, $tab_hl * 3);
2088 }
2089
2090 return ($tab_hl * 7);
2091 }
2092
2093
2104 public function defineColumnField($object, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0)
2105 {
2106 global $hookmanager;
2107
2108 // Default field style for content
2109 $this->defaultContentsFieldsStyle = array(
2110 'align' => 'R', // R,C,L
2111 'padding' => array(1, 0.5, 1, 0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
2112 );
2113
2114 // Default field style for content
2115 $this->defaultTitlesFieldsStyle = array(
2116 'align' => 'C', // R,C,L
2117 'padding' => array(0.5, 0, 0.5, 0), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
2118 );
2119
2120 /*
2121 * For example
2122 $this->cols['theColKey'] = array(
2123 'rank' => $rank, // int : use for ordering columns
2124 'width' => 20, // the column width in mm
2125 'title' => array(
2126 'textkey' => 'yourLangKey', // if there is no label, yourLangKey will be translated to replace label
2127 'label' => ' ', // the final label : used fore final generated text
2128 'align' => 'L', // text alignment : R,C,L
2129 'padding' => array(0.5,0.5,0.5,0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
2130 ),
2131 'content' => array(
2132 'align' => 'L', // text alignment : R,C,L
2133 'padding' => array(0.5,0.5,0.5,0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
2134 ),
2135 );
2136 */
2137
2138 $rank = 0; // do not use negative rank
2139 $this->cols['position'] = array(
2140 'rank' => $rank,
2141 'width' => 10,
2142 'status' => getDolGlobalInt('PDF_CYAN_ADD_POSITION') ? true : (getDolGlobalInt('PDF_ADD_POSITION') ? true : false),
2143 'title' => array(
2144 'textkey' => '#', // use lang key is useful in some case with module
2145 'align' => 'C',
2146 // 'textkey' => 'yourLangKey', // if there is no label, yourLangKey will be translated to replace label
2147 // 'label' => ' ', // the final label
2148 'padding' => array(0.5, 0.5, 0.5, 0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
2149 ),
2150 'content' => array(
2151 'align' => 'C',
2152 'padding' => array(1, 0.5, 1, 1.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
2153 ),
2154 );
2155
2156 $rank = 5; // do not use negative rank
2157 $this->cols['desc'] = array(
2158 'rank' => $rank,
2159 'width' => false, // only for desc
2160 'status' => true,
2161 'title' => array(
2162 'textkey' => 'Designation', // use lang key is useful in some case with module
2163 'align' => 'L',
2164 // 'textkey' => 'yourLangKey', // if there is no label, yourLangKey will be translated to replace label
2165 // 'label' => ' ', // the final label
2166 'padding' => array(0.5, 0.5, 0.5, 0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
2167 ),
2168 'content' => array(
2169 'align' => 'L',
2170 'padding' => array(1, 0.5, 1, 1.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
2171 ),
2172 );
2173
2174 // Image of product
2175 $rank += 10;
2176 $this->cols['photo'] = array(
2177 'rank' => $rank,
2178 'width' => getDolGlobalInt('MAIN_DOCUMENTS_WITH_PICTURE_WIDTH', 20), // in mm
2179 'status' => false,
2180 'title' => array(
2181 'textkey' => 'Photo',
2182 'label' => ' '
2183 ),
2184 'content' => array(
2185 'padding' => array(0, 0, 0, 0), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
2186 ),
2187 'border-left' => false, // remove left line separator
2188 );
2189
2190 if (getDolGlobalString('MAIN_GENERATE_PROPOSALS_WITH_PICTURE') && !empty($this->atleastonephoto)) {
2191 $this->cols['photo']['status'] = true;
2192 $this->cols['photo']['border-left'] = true;
2193 }
2194
2195
2196 $rank += 10;
2197 $this->cols['vat'] = array(
2198 'rank' => $rank,
2199 'status' => false,
2200 'width' => 16, // in mm
2201 'title' => array(
2202 'textkey' => 'VAT'
2203 ),
2204 'border-left' => true, // add left line separator
2205 );
2206
2207 if (!getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT') && !getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_COLUMN')) {
2208 $this->cols['vat']['status'] = true;
2209 }
2210
2211 $rank += 10;
2212 $this->cols['subprice'] = array(
2213 'rank' => $rank,
2214 'width' => 19, // in mm
2215 'status' => true,
2216 'title' => array(
2217 'textkey' => 'PriceUHT'
2218 ),
2219 'border-left' => true, // add left line separator
2220 );
2221
2222 // Adapt dynamically the width of subprice, if text is too long.
2223 $tmpwidth = 0;
2224 $nblines = count($object->lines);
2225 for ($i = 0; $i < $nblines; $i++) {
2226 $tmpwidth2 = dol_strlen(dol_string_nohtmltag(pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails)));
2227 $tmpwidth = max($tmpwidth, $tmpwidth2);
2228 }
2229 if ($tmpwidth > 10) {
2230 $this->cols['subprice']['width'] += (2 * ($tmpwidth - 10));
2231 }
2232
2233 $rank += 10;
2234 $this->cols['qty'] = array(
2235 'rank' => $rank,
2236 'width' => 16, // in mm
2237 'status' => true,
2238 'title' => array(
2239 'textkey' => 'Qty'
2240 ),
2241 'border-left' => true, // add left line separator
2242 );
2243
2244 $rank += 10;
2245 $this->cols['unit'] = array(
2246 'rank' => $rank,
2247 'width' => 11, // in mm
2248 'status' => false,
2249 'title' => array(
2250 'textkey' => 'Unit'
2251 ),
2252 'border-left' => true, // add left line separator
2253 );
2254 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
2255 $this->cols['unit']['status'] = true;
2256 }
2257
2258 $rank += 10;
2259 $this->cols['discount'] = array(
2260 'rank' => $rank,
2261 'width' => 13, // in mm
2262 'status' => false,
2263 'title' => array(
2264 'textkey' => 'ReductionShort'
2265 ),
2266 'border-left' => true, // add left line separator
2267 );
2268 if ($this->atleastonediscount) {
2269 $this->cols['discount']['status'] = true;
2270 }
2271
2272 $rank += 1000; // add a big offset to be sure is the last col because default extrafield rank is 100
2273 $this->cols['totalexcltax'] = array(
2274 'rank' => $rank,
2275 'width' => 26, // in mm
2276 'status' => !getDolGlobalString('PDF_PROPAL_HIDE_PRICE_EXCL_TAX'),
2277 'title' => array(
2278 'textkey' => 'TotalHTShort'
2279 ),
2280 'border-left' => true, // add left line separator
2281 );
2282
2283 $rank += 1010; // add a big offset to be sure is the last col because default extrafield rank is 100
2284 $this->cols['totalincltax'] = array(
2285 'rank' => $rank,
2286 'width' => 26, // in mm
2287 'status' => getDolGlobalBool('PDF_PROPAL_SHOW_PRICE_INCL_TAX'),
2288 'title' => array(
2289 'textkey' => 'TotalTTCShort'
2290 ),
2291 'border-left' => true, // add left line separator
2292 );
2293
2294 // Add extrafields cols
2295 if (!empty($object->lines)) {
2296 $line = reset($object->lines);
2297 $this->defineColumnExtrafield($line, $outputlangs, $hidedetails);
2298 }
2299
2300 $parameters = array(
2301 'object' => $object,
2302 'outputlangs' => $outputlangs,
2303 'hidedetails' => $hidedetails,
2304 'hidedesc' => $hidedesc,
2305 'hideref' => $hideref
2306 );
2307
2308 $reshook = $hookmanager->executeHooks('defineColumnField', $parameters, $this); // Note that $object may have been modified by hook
2309 if ($reshook < 0) {
2310 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
2311 } elseif (empty($reshook)) {
2312 // @phan-suppress-next-line PhanPluginSuspiciousParamOrderInternal
2313 $this->cols = array_replace($this->cols, $hookmanager->resArray); // array_replace is used to preserve keys
2314 } else {
2315 $this->cols = $hookmanager->resArray;
2316 }
2317 }
2318}
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
Class to manage bank accounts.
prepareArrayColumnField($object, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0)
Prepare Array Column Field.
getColumnStatus($colKey)
get column status from column key
printStdColumnContent($pdf, &$curY, $colKey, $columnText='')
print standard column content
pdfTabTitles(&$pdf, $tab_top, $tab_height, $outputlangs, $hidetop=0)
Print standard column content.
printColDescContent($pdf, &$curY, $colKey, $object, $i, $outputlangs, $hideref=0, $hidedesc=0, $issupplierline=0)
print description column content
getMaxAfterColsLinePositionsData()
Get position in PDF after col display.
getColumnContentXStart($colKey)
get column content X (abscissa) left position from column key
setAfterColsLinePositionsData(string $colId, float $y, int $pageNumb)
Used for to set afterColsLinePositions var in a pdf draw line loop.
getExtrafieldContent($object, $extrafieldKey, $outputlangs=null)
get extrafield content for pdf writeHtmlCell compatibility usage for PDF line columns and object note...
printRoundedRect($pdf, $x, $y, $w, $h, $r, $hidetop=0, $hidebottom=0, $style='D')
Print a rounded rectangle on the PDF.
resetAfterColsLinePositionsData(float $y, int $pageNumb)
Used for reset afterColsLinePositions var in start of a new pdf draw line loop.
defineColumnExtrafield($object, $outputlangs, $hidedetails=0)
Define Array Column Field for extrafields.
Class to manage hooks.
Class mere des modeles de propale.
Class to manage products or services.
Put here description of your class.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage translations.
Class to manage Dolibarr users.
Class to generate PDF proposal Cyan.
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.
_tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop=0, $hidebottom=0, $currency='', $outputlangsbis=null)
Show table for lines.
__construct($db)
Constructor.
_pagefoot(&$pdf, $object, $outputlangs, $hidefreetext=0)
Show footer of page.
_pagehead(&$pdf, $object, $showaddress, $outputlangs, $outputlangsbis=null)
Show top header of page.
write_file($object, $outputlangs, $srctemplatepath='', $hidedetails=0, $hidedesc=0, $hideref=0)
Function to build pdf onto disk.
drawSignatureArea(&$pdf, $object, $posy, $outputlangs)
Show area for the customer to sign.
drawInfoTable(&$pdf, $object, $posy, $outputlangs)
Show miscellaneous information (payment mode, payment term, ...)
global $mysoc
print $script_file $mode $langs defaultlang(is_numeric($duration_value) ? " delay=". $duration_value :"").(is_numeric($duration_value2) ? " after cd cd cd description as description
Only used if Module[ID]Desc translation string is not found.
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
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,...
dol_getIdFromCode($db, $key, $tablename, $fieldkey='code', $fieldid='id', $entityfilter=0, $filters='', $useCache=true)
Return an id or code from a code or id.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
vatrate($rate, $addpercent=false, $info_bits=0, $usestarfornpr=0, $html=0)
Return a string with VAT rate label formatted for view output Used into pdf and HTML pages.
dol_string_nohtmltag($stringtoclean, $removelinefeed=1, $pagecodeto='UTF-8', $strip_tags=0, $removedoublespaces=1)
Clean a string from all HTML tags and entities.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
getCallerInfoString()
Get caller info as a string that can be appended to a log message.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
dolChmod($filepath, $newmask='')
Change mod of a file.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
getLocalTaxesFromRate($vatrate, $local, $buyer, $seller, $firstparamisid=0)
Get type and rate of localtaxes for a particular vat rate/country of a thirdparty.
dol_concatdesc($text1, $text2, $forxml=false, $invert=false)
Concat 2 descriptions with a new line between them (second operand after first one with appropriate n...
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...
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
getDolGlobalBool($key, $default=false)
Return a Dolibarr global constant boolean value.
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '...' if string larger than length.
dol_htmlentitiesbr($stringtoencode, $nl2brmode=0, $pagecodefrom='UTF-8', $removelasteolbr=1)
This function is called to encode a string into a HTML string but differs from htmlentities because a...
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
get_exdir($num, $level, $alpha, $withoutslash, $object, $modulepart='')
Return a path to have a the directory according to object where files are stored.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
print $langs trans("Show") . '< td style="' . $timeColor . '" align="center"> s</td > badge status0 badge status4 badge status3 Error badge status8< td align="center">< span class="badge ' . $badge . '"></span ></td >< td align="center">< a href="#" class="button button-small" onclick="openLogModal(this)" data-req="' . dol_escape_htmltag($reqSafe) . '" data-res="' . dol_escape_htmltag($resSafe) . '" data-err="' . dol_escape_htmltag($errSafe) . '">< span class="fa fa-search-plus"></span ></a ></td ></tr >< tr >< td colspan="' . $colspan . '" class="opacitymedium"></td ></tr ></table ></div ></form > logModal none logModal none s a JSON string
buildzip.php
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:3192
pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line total excluding tax.
Definition pdf.lib.php:2893
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:3224
pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, $w, $h, $align, $default_font_size)
Show linked objects for PDF generation.
Definition pdf.lib.php:1810
pdf_getPDFFontSize($outputlangs)
Return font size to use for PDF generation.
Definition pdf.lib.php:294
pdf_bank($pdf, $outputlangs, $curx, $cury, $account, $onlynumber=0, $default_font_size=10)
Show bank information for PDF generation.
Definition pdf.lib.php:1241
pdf_getHeightForLogo($logo, $url=false)
Return height to use for Logo onto PDF.
Definition pdf.lib.php:317
pdf_getlinetotalwithtax($object, $i, $outputlangs, $hidedetails=0)
Return line total including tax.
Definition pdf.lib.php:2943
pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line unit price excluding tax.
Definition pdf.lib.php:2482
pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails=0)
Return line vat rate.
Definition pdf.lib.php:2420
pdf_pagehead($pdf, $outputlangs, $page_height)
Show header of page for PDF generation.
Definition pdf.lib.php:749
pdfGetHeightForHtmlContent($pdf, $htmlcontent)
Function to try to calculate height of a HTML Content.
Definition pdf.lib.php:342
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:1423
pdf_getPDFFont($outputlangs)
Return font name to use for PDF generation.
Definition pdf.lib.php:273
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:3322
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:438
pdf_getlineunit($object, $i, $outputlangs, $hidedetails=0)
Return line unit.
Definition pdf.lib.php:2727
pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails=0)
Return line remise percent.
Definition pdf.lib.php:2770
pdf_getlineqty($object, $i, $outputlangs, $hidedetails=0)
Return line quantity.
Definition pdf.lib.php:2567
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:1137
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:393
if(preg_match('/(crypted|dolcrypt):/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
'integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]',...
Definition repair.php:130
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:133