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