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