dolibarr 24.0.0-beta
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 = 90 + $top_shift;
365 $tab_top_newpage = (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD') ? 42 + $top_shift : 10);
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 for ($i = 0; $i < $nblines; $i++) {
575 $linePosition = $i + 1;
576 $curY = $nexY;
577
578 $sub_options = $object->lines[$i]->extraparams["subtotal"] ?? array();
579
580 if ($object->lines[$i]->special_code == SUBTOTALS_SPECIAL_CODE) {
581 $level = $object->lines[$i]->qty;
582 if ($sub_options) {
583 if (isset($sub_options['titleshowuponpdf'])) {
584 $pdf_sub_options['titleshowuponpdf'] = isset($pdf_sub_options['titleshowuponpdf']) && $pdf_sub_options['titleshowuponpdf'] < $level ? $pdf_sub_options['titleshowuponpdf'] : $level;
585 } elseif (isset($pdf_sub_options['titleshowuponpdf']) && abs($level) <= $pdf_sub_options['titleshowuponpdf']) {
586 unset($pdf_sub_options['titleshowuponpdf']);
587 }
588 if (isset($sub_options['titleshowtotalexludingvatonpdf'])) {
589 $pdf_sub_options['titleshowtotalexludingvatonpdf'] = isset($pdf_sub_options['titleshowtotalexludingvatonpdf']) && $pdf_sub_options['titleshowtotalexludingvatonpdf'] < $level ? $pdf_sub_options['titleshowtotalexludingvatonpdf'] : $level;
590 } elseif (isset($pdf_sub_options['titleshowtotalexludingvatonpdf']) && abs($level) <= $pdf_sub_options['titleshowtotalexludingvatonpdf']) {
591 unset($pdf_sub_options['titleshowtotalexludingvatonpdf']);
592 }
593 } else {
594 if (isset($pdf_sub_options['titleshowuponpdf']) && abs($level) <= $pdf_sub_options['titleshowuponpdf']) {
595 unset($pdf_sub_options['titleshowuponpdf']);
596 }
597 if (isset($pdf_sub_options['titleshowtotalexludingvatonpdf']) && abs($level) <= $pdf_sub_options['titleshowtotalexludingvatonpdf']) {
598 unset($pdf_sub_options['titleshowtotalexludingvatonpdf']);
599 }
600 }
601 }
602
603 if (($curY + 6) > ($this->page_hauteur - $heightforfooter) || isset($sub_options['titleforcepagebreak']) && !($pdf->getNumPages() == 1 && $curY == $tab_top + $this->tabTitleHeight)) {
604 $object->lines[$i]->pagebreak = true;
605 }
606
607 // in First Check line page break and add page if needed
608 if (isset($object->lines[$i]->pagebreak) && $object->lines[$i]->pagebreak) {
609 // New page
610 $pdf->AddPage();
611 if (!empty($tplidx)) {
612 $pdf->useTemplate($tplidx);
613 }
614
615 $pdf->setPage($pdf->getNumPages());
616 $nexY = $curY = $tab_top_newpage;
617 }
618
619 $this->resetAfterColsLinePositionsData($nexY, $pdf->getPage());
620
621 $pdf->SetFont('', '', $default_font_size - 1); // Into loop to work with multipage
622 $pdf->SetTextColor(0, 0, 0);
623
624 // Define size of image if we need it
625 $imglinesize = array();
626 if (!empty($realpatharray[$i])) {
627 $imglinesize = pdf_getSizeForImage($realpatharray[$i]);
628 }
629
630 $pdf->setTopMargin($tab_top_newpage);
631 $pdf->setPageOrientation('', true, $heightforfooter); // The only function to edit the bottom margin of current page to set it.
632 $pageposbefore = $pdf->getPage();
633 $curYBefore = $curY;
634
635 // Allows data in the first page if description is long enough to break in multiples pages
636 $showpricebeforepagebreak = getDolGlobalInt('MAIN_PDF_DATA_ON_FIRST_PAGE');
637
638 $posYAfterImage = 0;
639
640 if ($this->getColumnStatus('photo')) {
641 // We start with Photo of product line
642 $imageTopMargin = 1;
643 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
644 $pdf->AddPage('', '', true);
645 if (!empty($tplidx)) {
646 $pdf->useTemplate($tplidx);
647 }
648 $pdf->setPage($pageposbefore + 1);
649 $pdf->setPageOrientation('', true, $heightforfooter); // The only function to edit the bottom margin of current page to set it.
650 $curY = $tab_top_newpage;
651 $showpricebeforepagebreak = 0;
652 }
653
654 $pdf->setPageOrientation('', false, $heightforfooter + $heightforfreetext); // The only function to edit the bottom margin of current page to set it.
655 // @phan-suppress-next-line PhanTypeMismatchProperty
656 if (!empty($this->cols['photo']) && isset($imglinesize['width']) && isset($imglinesize['height'])) {
657 $pdf->Image($realpatharray[$i], $this->getColumnContentXStart('photo'), $curY + $imageTopMargin, $imglinesize['width'], $imglinesize['height'], '', '', '', 2, 300); // Use 300 dpi
658 // $pdf->Image does not increase value return by getY, so we save it manually
659 $posYAfterImage = $curY + $imglinesize['height'];
660
661 $this->setAfterColsLinePositionsData('photo', $posYAfterImage, $pdf->getPage());
662 }
663 }
664
665 // restore Page orientation for text
666 $pdf->setPageOrientation('', true, $heightforfooter); // The only function to edit the bottom margin of current page to set it.
667
668 if ($this->getColumnStatus('desc')) {
669 if ($object->lines[$i]->special_code != SUBTOTALS_SPECIAL_CODE) {
670 $this->printColDescContent($pdf, $curY, 'desc', $object, $i, $outputlangs, $hideref, $hidedesc);
671 $this->setAfterColsLinePositionsData('desc', $pdf->GetY(), $pdf->getPage());
672 } else {
673 $bg_color = colorStringToArray(getDolGlobalString("SUBTOTAL_BACK_COLOR_LEVEL_".abs($object->lines[$i]->qty)));
674 pdf_render_subtotals($pdf, $this, $curY, $object, $i, $outputlangs, $hideref, $hidedesc, $bg_color, true, true);
675 }
676 }
677
678 $afterPosData = $this->getMaxAfterColsLinePositionsData();
679 $pdf->setPage($pageposbefore);
680 $pdf->setTopMargin($this->marge_haute);
681 $curY = $curYBefore;
682 $pdf->setPageOrientation('', false, $heightforfooter); // The only function to edit the bottom margin of current page to set it.
683
684
685 // We suppose that a too long description or photo were moved completely on next page
686 if ($afterPosData['page'] > $pageposbefore && (empty($showpricebeforepagebreak) || ($curY + 4) > ($this->page_hauteur - $heightforfooter))) {
687 $pdf->setPage($afterPosData['page']);
688 $curY = $tab_top_newpage;
689 }
690
691 $pdf->SetFont('', '', $default_font_size - 1); // We reposition the default font
692
693
694 // # of line
695 if ($this->getColumnStatus('position')) {
696 $this->printStdColumnContent($pdf, $curY, 'position', strval($linePosition));
697 }
698
699 // VAT Rate
700 if ($this->getColumnStatus('vat') && $object->lines[$i]->special_code != SUBTOTALS_SPECIAL_CODE) {
701 $vat_rate = pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails);
702 $this->printStdColumnContent($pdf, $curY, 'vat', $vat_rate);
703 }
704
705 // Unit price before discount
706 if ($this->getColumnStatus('subprice') && $object->lines[$i]->special_code != SUBTOTALS_SPECIAL_CODE && isset($pdf_sub_options['titleshowuponpdf'])) {
707 $up_excl_tax = pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails);
708 $this->printStdColumnContent($pdf, $curY, 'subprice', $up_excl_tax);
709 }
710
711 // Quantity
712 // Enough for 6 chars
713 if ($this->getColumnStatus('qty') && $object->lines[$i]->special_code != SUBTOTALS_SPECIAL_CODE) {
714 $qty = pdf_getlineqty($object, $i, $outputlangs, $hidedetails);
715 $this->printStdColumnContent($pdf, $curY, 'qty', $qty);
716 }
717
718
719 // Unit
720 if ($this->getColumnStatus('unit') && $object->lines[$i]->special_code != SUBTOTALS_SPECIAL_CODE) {
721 $unit = pdf_getlineunit($object, $i, $outputlangs, $hidedetails);
722 $this->printStdColumnContent($pdf, $curY, 'unit', $unit);
723 }
724
725 // Discount on line
726 if ($this->getColumnStatus('discount') && $object->lines[$i]->special_code != SUBTOTALS_SPECIAL_CODE && $object->lines[$i]->remise_percent) {
727 $remise_percent = pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails);
728 $this->printStdColumnContent($pdf, $curY, 'discount', $remise_percent);
729 }
730
731 // Total excl tax line (HT)
732 if ($this->getColumnStatus('totalexcltax')) {
733 if ($object->lines[$i]->special_code != SUBTOTALS_SPECIAL_CODE && isset($pdf_sub_options['titleshowtotalexludingvatonpdf'])) {
734 $total_excl_tax = pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails);
735 $this->printStdColumnContent($pdf, $curY, 'totalexcltax', $total_excl_tax);
736 } elseif ($object->lines[$i]->qty < 0 && isset($sub_options['subtotalshowtotalexludingvatonpdf'])) {
737 if (isModEnabled('multicurrency') && $object->multicurrency_code != $conf->currency) {
738 $total_excl_tax = $object->getSubtotalLineMulticurrencyAmount($object->lines[$i]);
739 } else {
740 $total_excl_tax = $object->getSubtotalLineAmount($object->lines[$i]);
741 }
742 $this->printStdColumnContent($pdf, $curY, 'totalexcltax', $total_excl_tax);
743 }
744 }
745
746 // Total with tax line (TTC)
747 if ($this->getColumnStatus('totalincltax')) {
748 $total_incl_tax = pdf_getlinetotalwithtax($object, $i, $outputlangs, $hidedetails);
749 $this->printStdColumnContent($pdf, $curY, 'totalincltax', $total_incl_tax);
750 }
751
752 // Extrafields
753 if (!empty($object->lines[$i]->array_options)) {
754 foreach ($object->lines[$i]->array_options as $extrafieldColKey => $extrafieldValue) {
755 if ($this->getColumnStatus($extrafieldColKey)) {
756 $extrafieldValue = $this->getExtrafieldContent($object->lines[$i], $extrafieldColKey, $outputlangs);
757 $this->printStdColumnContent($pdf, $curY, $extrafieldColKey, $extrafieldValue);
758
759 $this->setAfterColsLinePositionsData('options_'.$extrafieldColKey, $pdf->GetY(), $pdf->getPage());
760 }
761 }
762 }
763
764 $afterPosData = $this->getMaxAfterColsLinePositionsData();
765 $parameters = array(
766 'object' => $object,
767 'i' => $i,
768 'pdf' => & $pdf,
769 'curY' => & $curY,
770 'nexY' => & $afterPosData['y'], // for backward module hook compatibility Y will be accessible by $object->getMaxAfterColsLinePositionsData()
771 'outputlangs' => $outputlangs,
772 'hidedetails' => $hidedetails
773 );
774 $reshook = $hookmanager->executeHooks('printPDFline', $parameters, $this); // Note that $object may have been modified by hook
775
776
777 // Collection of totals by value of vat in $this->tva["rate"] = total_tva
778 if (isModEnabled("multicurrency") && $object->multicurrency_tx != 1) {
779 $tvaligne = $object->lines[$i]->multicurrency_total_tva;
780 } else {
781 $tvaligne = $object->lines[$i]->total_tva;
782 }
783
784 $localtax1ligne = $object->lines[$i]->total_localtax1;
785 $localtax2ligne = $object->lines[$i]->total_localtax2;
786 $localtax1_rate = $object->lines[$i]->localtax1_tx;
787 $localtax2_rate = $object->lines[$i]->localtax2_tx;
788 $localtax1_type = $object->lines[$i]->localtax1_type;
789 $localtax2_type = $object->lines[$i]->localtax2_type;
790
791 // TODO remise_percent is an obsolete field for object parent
792 /*if ($object->remise_percent) {
793 $tvaligne -= ($tvaligne * $object->remise_percent) / 100;
794 }
795 if ($object->remise_percent) {
796 $localtax1ligne -= ($localtax1ligne * $object->remise_percent) / 100;
797 }
798 if ($object->remise_percent) {
799 $localtax2ligne -= ($localtax2ligne * $object->remise_percent) / 100;
800 }*/
801
802 $vatrate = (string) $object->lines[$i]->tva_tx;
803
804 // Retrieve type from database for backward compatibility with old records
805 if ((!isset($localtax1_type) || $localtax1_type == '' || !isset($localtax2_type) || $localtax2_type == '') // if tax type not defined
806 && (!empty($localtax1_rate) || !empty($localtax2_rate))) { // and there is local tax
807 $localtaxtmp_array = getLocalTaxesFromRate($vatrate, 0, $object->thirdparty, $mysoc);
808 $localtax1_type = isset($localtaxtmp_array[0]) ? $localtaxtmp_array[0] : '';
809 $localtax2_type = isset($localtaxtmp_array[2]) ? $localtaxtmp_array[2] : '';
810 }
811
812 // retrieve global local tax
813 if ($localtax1_type && $localtax1ligne != 0) {
814 if (empty($this->localtax1[$localtax1_type][$localtax1_rate])) {
815 $this->localtax1[$localtax1_type][$localtax1_rate] = $localtax1ligne;
816 } else {
817 $this->localtax1[$localtax1_type][$localtax1_rate] += $localtax1ligne;
818 }
819 }
820 if ($localtax2_type && $localtax2ligne != 0) {
821 if (empty($this->localtax2[$localtax2_type][$localtax2_rate])) {
822 $this->localtax2[$localtax2_type][$localtax2_rate] = $localtax2ligne;
823 } else {
824 $this->localtax2[$localtax2_type][$localtax2_rate] += $localtax2ligne;
825 }
826 }
827
828 if (($object->lines[$i]->info_bits & 0x01) == 0x01) {
829 $vatrate .= '*';
830 }
831
832 // Fill $this->tva and $this->tva_array
833 if (!isset($this->tva[$vatrate])) {
834 $this->tva[$vatrate] = 0;
835 }
836 $this->tva[$vatrate] += $tvaligne;
837 $vatcode = $object->lines[$i]->vat_src_code;
838 if (empty($this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'])) {
839 $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'] = 0;
840 }
841 $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')] = array('vatrate' => $vatrate, 'vatcode' => $vatcode, 'amount' => $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'] + $tvaligne);
842
843
844
845 $afterPosData = $this->getMaxAfterColsLinePositionsData();
846 $pdf->setPage($afterPosData['page']);
847 $nexY = $afterPosData['y'];
848
849 // Add line
850 if (getDolGlobalString('MAIN_PDF_DASH_BETWEEN_LINES') && $i < ($nblines - 1) && $afterPosData['y'] < $this->page_hauteur - $heightforfooter - 5) {
851 $pdf->SetLineStyle(array('dash' => '1,1', 'color' => array(80, 80, 80)));
852 //$pdf->SetDrawColor(190,190,200);
853 $pdf->line($this->marge_gauche, $nexY, $this->page_largeur - $this->marge_droite, $nexY);
854 $pdf->SetLineStyle(array('dash' => 0));
855 }
856
857 $nexY += 0; // Add space between lines
858 }
859
860
861 // Add last page for document footer if there are not enough size left
862 $afterPosData = $this->getMaxAfterColsLinePositionsData();
863 if (isset($afterPosData['y']) && $afterPosData['y'] > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforsignature + $heightforinfotot))) {
864 $pdf->AddPage();
865 if (!empty($tplidx)) {
866 $pdf->useTemplate($tplidx);
867 }
868 $pagenb++;
869 $pdf->setPage($pagenb);
870 }
871
872 // Draw table frames and columns borders
873 $drawTabNumbPage = $pdf->getNumPages();
874 for ($i = $pageposbeforeprintlines; $i <= $drawTabNumbPage; $i++) {
875 $pdf->setPage($i);
876 // reset page orientation each loop to override it if it was changed
877 $pdf->setPageOrientation('', false, 0); // The only function to edit the bottom margin of current page to set it.
878
879 $drawTabHideTop = $hidetop;
880 $drawTabTop = $tab_top_newpage;
881 $drawTabBottom = $this->page_hauteur - $heightforfooter;
882 $hideBottom = 0; // TODO understand why it change to 1 or 0 during process
883
884 if ($i == $pageposbeforeprintlines) {
885 // first page need to start after notes
886 $drawTabTop = $tab_top;
887 } elseif (!$drawTabHideTop) {
888 if (getDolGlobalInt('MAIN_PDF_ENABLE_COL_HEAD_TITLE_REPEAT')) {
889 $drawTabTop -= $this->tabTitleHeight;
890 } else {
891 $drawTabHideTop = 1;
892 }
893 }
894
895 // last page need to include document footer
896 if ($i == $pdf->getNumPages()) {
897 // remove document footer height to tab bottom position
898 $drawTabBottom -= $heightforsignature + $heightforfreetext + $heightforinfotot;
899 }
900
901 $drawTabHeight = $drawTabBottom - $drawTabTop;
902 $this->_tableau($pdf, $drawTabTop, $drawTabHeight, 0, $outputlangs, $drawTabHideTop, $hideBottom, $object->multicurrency_code, $outputlangsbis);
903
904 $hideFreeText = $i != $pdf->getNumPages() ? 1 : 0; // Display free text only in last page
905 $this->_pagefoot($pdf, $object, $outputlangs, $hideFreeText);
906
907 $pdf->setPage($i); // in case of _pagefoot or _tableau change it
908
909 // reset page orientation each loop to override it if it was changed by _pagefoot or _tableau change it
910 $pdf->setPageOrientation('', true, 0); // The only function to edit the bottom margin of current page to set it.
911
912 // Don't print head on first page ($pageposbeforeprintlines) because already added previously
913 if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD') && $i != $pageposbeforeprintlines) {
914 $this->_pagehead($pdf, $object, 0, $outputlangs);
915 }
916 if (!empty($tplidx)) {
917 $pdf->useTemplate($tplidx);
918 }
919 }
920
921 // reset text color before print footers
922 $pdf->SetTextColor(0, 0, 0);
923
924 $pdf->setPage($pdf->getNumPages());
925
926 $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforsignature - $heightforfooter + 1;
927
928 // Display infos area
929 $posy = $this->drawInfoTable($pdf, $object, $bottomlasttab, $outputlangs);
930
931 // Display total zone
932 $posy = $this->drawTotalTable($pdf, $object, 0, $bottomlasttab, $outputlangs);
933
934 // Customer signature area
935 if (!getDolGlobalString('PROPAL_DISABLE_SIGNATURE')) {
936 $posy = $this->drawSignatureArea($pdf, $object, $posy, $outputlangs);
937
938 // Rewrite keywords to add a tag with the numero of page that contains the signature section
939 $keywords = $outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("PdfCommercialProposalTitle")." ".$outputlangs->convToOutputCharset($object->thirdparty->name);
940 $pdf->SetKeyWords($keywords." PAGESIGN=".$pdf->getPage());
941 }
942
943 // Add number of pages in footer
944 if (method_exists($pdf, 'AliasNbPages')) {
945 $pdf->AliasNbPages(); // @phan-suppress-current-line PhanUndeclaredMethod
946 }
947
948 // Add terms to sale
949 $termsofsalefilename = getDolGlobalString('MAIN_INFO_PROPAL_TERMSOFSALE');
950 if (getDolGlobalInt('MAIN_PDF_ADD_TERMSOFSALE_PROPAL') && $termsofsalefilename) {
951 $termsofsale = $conf->propal->dir_output.'/'.$termsofsalefilename;
952 if (!empty($conf->propal->multidir_output[$object->entity ?? $conf->entity])) {
953 $termsofsale = $conf->propal->multidir_output[$object->entity ?? $conf->entity].'/'.$termsofsalefilename;
954 }
955 if (file_exists($termsofsale) && is_readable($termsofsale)) {
956 $pagecount = $pdf->setSourceFile($termsofsale);
957 for ($i = 1; $i <= $pagecount; $i++) {
958 $tplIdx = $pdf->importPage($i);
959 if ($tplIdx !== false) {
960 $s = $pdf->getTemplatesize($tplIdx);
961 $pdf->AddPage($s['h'] > $s['w'] ? 'P' : 'L');
962 $pdf->useTemplate($tplIdx);
963 } else {
964 setEventMessages(null, array($termsofsale.' cannot be added, probably protected PDF'), 'warnings');
965 }
966 }
967 }
968 }
969
970 //If propal merge product PDF is active
971 if (getDolGlobalString('PRODUIT_PDF_MERGE_PROPAL')) {
972 require_once DOL_DOCUMENT_ROOT.'/product/class/propalmergepdfproduct.class.php';
973
974 $already_merged = array();
975 foreach ($object->lines as $line) {
976 if (!empty($line->fk_product) && !(in_array($line->fk_product, $already_merged))) {
977 // Find the desired PDF
978 $filetomerge = new Propalmergepdfproduct($this->db);
979
980 if (getDolGlobalInt('MAIN_MULTILANGS')) {
981 $filetomerge->fetch_by_product($line->fk_product, $outputlangs->defaultlang);
982 } else {
983 $filetomerge->fetch_by_product($line->fk_product);
984 }
985
986 $already_merged[] = $line->fk_product;
987
988 $product = new Product($this->db);
989 $product->fetch($line->fk_product);
990
991 if ($product->entity != $conf->entity) {
992 $entity_product_file = $product->entity;
993 } else {
994 $entity_product_file = $conf->entity;
995 }
996
997 // If PDF is selected and file is not empty
998 if (count($filetomerge->lines) > 0) {
999 foreach ($filetomerge->lines as $linefile) {
1000 if (!empty($linefile->id) && !empty($linefile->file_name)) {
1001 $filetomerge_dir = null;
1002 if (getDolGlobalInt('PRODUCT_USE_OLD_PATH_FOR_PHOTO')) {
1003 if (isModEnabled("product")) {
1004 $filetomerge_dir = $conf->product->multidir_output[$entity_product_file ?? $conf->entity].'/'.get_exdir($product->id, 2, 0, 0, $product, 'product').$product->id."/photos";
1005 } elseif (isModEnabled("service")) {
1006 $filetomerge_dir = $conf->service->multidir_output[$entity_product_file ?? $conf->entity].'/'.get_exdir($product->id, 2, 0, 0, $product, 'product').$product->id."/photos";
1007 }
1008 } else {
1009 if (isModEnabled("product")) {
1010 $filetomerge_dir = $conf->product->multidir_output[$entity_product_file ?? $conf->entity].'/'.get_exdir(0, 0, 0, 0, $product, 'product');
1011 } elseif (isModEnabled("service")) {
1012 $filetomerge_dir = $conf->service->multidir_output[$entity_product_file ?? $conf->entity].'/'.get_exdir(0, 0, 0, 0, $product, 'product');
1013 }
1014 }
1015
1016 dol_syslog(get_class($this).':: upload_dir='.$filetomerge_dir, $filetomerge_dir === null ? LOG_ERR : LOG_DEBUG);
1017 if ($filetomerge_dir === null) {
1018 // Skip loop
1019 continue;
1020 }
1021
1022 $infile = $filetomerge_dir.'/'.$linefile->file_name;
1023 if (file_exists($infile) && is_readable($infile)) {
1024 $pagecount = $pdf->setSourceFile($infile);
1025 for ($i = 1; $i <= $pagecount; $i++) {
1026 $tplIdx = $pdf->importPage($i);
1027 if ($tplIdx !== false) {
1028 $s = $pdf->getTemplatesize($tplIdx);
1029 $pdf->AddPage($s['h'] > $s['w'] ? 'P' : 'L');
1030 $pdf->useTemplate($tplIdx);
1031 } else {
1032 setEventMessages(null, array($infile.' cannot be added, probably protected PDF'), 'warnings');
1033 }
1034 }
1035 }
1036 }
1037 }
1038 }
1039 }
1040 }
1041 }
1042
1043 $pdf->Close();
1044
1045 $pdf->Output($file, 'F');
1046
1047 //Add pdfgeneration hook
1048 $hookmanager->initHooks(array('pdfgeneration'));
1049 $parameters = array('file' => $file, 'object' => $object, 'outputlangs' => $outputlangs);
1050 global $action;
1051 $reshook = $hookmanager->executeHooks('afterPDFCreation', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1052 $this->warnings = $hookmanager->warnings;
1053 if ($reshook < 0) {
1054 $this->error = $hookmanager->error;
1055 $this->errors = $hookmanager->errors;
1056 dolChmod($file);
1057 return -1;
1058 }
1059
1060 dolChmod($file);
1061
1062 $this->result = array('fullpath' => $file);
1063
1064 return 1; // No error
1065 } else {
1066 $this->error = $langs->trans("ErrorCanNotCreateDir", $dir);
1067 return 0;
1068 }
1069 } else {
1070 $this->error = $langs->trans("ErrorConstantNotDefined", "PROP_OUTPUTDIR");
1071 return 0;
1072 }
1073 }
1074
1084 public function drawInfoTable(&$pdf, $object, $posy, $outputlangs)
1085 {
1086 global $mysoc;
1087
1088 $default_font_size = pdf_getPDFFontSize($outputlangs);
1089
1090 $pdf->SetFont('', '', $default_font_size - 1);
1091
1092 $diffsizetitle = getDolGlobalInt('PDF_DIFFSIZE_TITLE', 3);
1093
1094 // If France, show VAT mention if not applicable
1095 if ($this->emetteur->country_code == 'FR' && empty($mysoc->tva_assuj)) {
1096 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
1097 $pdf->SetXY($this->marge_gauche, $posy);
1098 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("VATIsNotUsedForInvoice"), 0, 'L', false);
1099
1100 $posy = $pdf->GetY() + 4;
1101 }
1102
1103 $posxval = 52;
1104 if (getDolGlobalString('MAIN_PDF_DELIVERY_DATE_TEXT')) {
1105 $displaydate = "daytext";
1106 } else {
1107 $displaydate = "day";
1108 }
1109
1110 // Show shipping date
1111 if (!empty($object->delivery_date)) {
1112 $outputlangs->load("sendings");
1113 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
1114 $pdf->SetXY($this->marge_gauche, $posy);
1115 $titre = $outputlangs->transnoentities("DateDeliveryPlanned").':';
1116 $pdf->MultiCell(80, 4, $titre, 0, 'L');
1117 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
1118 $pdf->SetXY($posxval, $posy);
1119 $dlp = dol_print_date($object->delivery_date, $displaydate, false, $outputlangs, true);
1120 $pdf->MultiCell(80, 4, $dlp, 0, 'L');
1121
1122 $posy = $pdf->GetY() + 1;
1123 } elseif ($object->availability_code || $object->availability) { // Show availability conditions
1124 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
1125 $pdf->SetXY($this->marge_gauche, $posy);
1126 $titre = $outputlangs->transnoentities("AvailabilityPeriod").':';
1127 $pdf->MultiCell(80, 4, $titre, 0, 'L');
1128 $pdf->SetTextColor(0, 0, 0);
1129 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
1130 $pdf->SetXY($posxval, $posy);
1131 $lib_availability = ($outputlangs->transnoentities("AvailabilityType".$object->availability_code) != 'AvailabilityType'.$object->availability_code) ? $outputlangs->transnoentities("AvailabilityType".$object->availability_code) : $outputlangs->convToOutputCharset($object->availability);
1132 $lib_availability = str_replace('\n', "\n", $lib_availability);
1133 $pdf->MultiCell(80, 4, $lib_availability, 0, 'L');
1134
1135 $posy = $pdf->GetY() + 1;
1136 }
1137
1138 // Show delivery mode
1139 if (!getDolGlobalString('PROPOSAL_PDF_HIDE_DELIVERYMODE') && $object->shipping_method_id > 0) {
1140 $outputlangs->load("sendings");
1141
1142 $shipping_method_id = $object->shipping_method_id;
1143 if (getDolGlobalString('SOCIETE_ASK_FOR_SHIPPING_METHOD') && !empty($this->emetteur->shipping_method_id)) {
1144 $shipping_method_id = $this->emetteur->shipping_method_id;
1145 }
1146 $shipping_method_code = dol_getIdFromCode($this->db, (string) $shipping_method_id, 'c_shipment_mode', 'rowid', 'code');
1147 $shipping_method_label = dol_getIdFromCode($this->db, (string) $shipping_method_id, 'c_shipment_mode', 'rowid', 'libelle');
1148
1149 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
1150 $pdf->SetXY($this->marge_gauche, $posy);
1151 $titre = $outputlangs->transnoentities("SendingMethod").':';
1152 $pdf->MultiCell(43, 4, $titre, 0, 'L');
1153
1154 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
1155 $pdf->SetXY($posxval, $posy);
1156 $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;
1157 $lib_condition_paiement = str_replace('\n', "\n", $lib_condition_paiement);
1158 $pdf->MultiCell(67, 4, $lib_condition_paiement, 0, 'L');
1159
1160 $posy = $pdf->GetY() + 1;
1161 }
1162
1163 // Show payments conditions
1164 if (!getDolGlobalString('PROPOSAL_PDF_HIDE_PAYMENTTERM') && $object->cond_reglement_code) {
1165 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
1166 $pdf->SetXY($this->marge_gauche, $posy);
1167 $titre = $outputlangs->transnoentities("PaymentConditions").':';
1168 $pdf->MultiCell(43, 4, $titre, 0, 'L');
1169
1170 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
1171 $pdf->SetXY($posxval, $posy);
1172 $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);
1173 $lib_condition_paiement = str_replace('\n', "\n", $lib_condition_paiement);
1174 if ($object->deposit_percent > 0) {
1175 $lib_condition_paiement = str_replace('__DEPOSIT_PERCENT__', $object->deposit_percent, $lib_condition_paiement);
1176 }
1177 $pdf->MultiCell(67, 4, $lib_condition_paiement, 0, 'L');
1178
1179 $posy = $pdf->GetY() + 3;
1180 }
1181
1182 if (!getDolGlobalString('PROPOSAL_PDF_HIDE_PAYMENTMODE')) {
1183 // Show payment mode
1184 if ($object->mode_reglement_code
1185 && $object->mode_reglement_code != 'CHQ'
1186 && $object->mode_reglement_code != 'VIR') {
1187 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
1188 $pdf->SetXY($this->marge_gauche, $posy);
1189 $titre = $outputlangs->transnoentities("PaymentMode").':';
1190 $pdf->MultiCell(80, 5, $titre, 0, 'L');
1191 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
1192 $pdf->SetXY($posxval, $posy);
1193 $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);
1194 $pdf->MultiCell(80, 5, $lib_mode_reg, 0, 'L');
1195
1196 $posy = $pdf->GetY() + 2;
1197 }
1198
1199 // Show payment mode CHQ
1200 if (empty($object->mode_reglement_code) || $object->mode_reglement_code == 'CHQ') {
1201 // Si mode reglement non force ou si force a CHQ
1202 if (getDolGlobalInt('FACTURE_CHQ_NUMBER')) {
1203 if (getDolGlobalInt('FACTURE_CHQ_NUMBER') > 0) {
1204 $account = new Account($this->db);
1205 $account->fetch(getDolGlobalInt('FACTURE_CHQ_NUMBER'));
1206
1207 $pdf->SetXY($this->marge_gauche, $posy);
1208 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
1209 $pdf->MultiCell(100, 3, $outputlangs->transnoentities('PaymentByChequeOrderedTo', $account->owner_name), 0, 'L', false);
1210 $posy = $pdf->GetY() + 1;
1211
1212 if (!getDolGlobalString('MAIN_PDF_HIDE_CHQ_ADDRESS')) {
1213 $pdf->SetXY($this->marge_gauche, $posy);
1214 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
1215 $pdf->MultiCell(100, 3, $outputlangs->convToOutputCharset($account->owner_address), 0, 'L', false);
1216 $posy = $pdf->GetY() + 2;
1217 }
1218 }
1219 if (getDolGlobalInt('FACTURE_CHQ_NUMBER') == -1) {
1220 $pdf->SetXY($this->marge_gauche, $posy);
1221 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
1222 $pdf->MultiCell(100, 3, $outputlangs->transnoentities('PaymentByChequeOrderedTo', $this->emetteur->name), 0, 'L', false);
1223 $posy = $pdf->GetY() + 1;
1224
1225 if (!getDolGlobalString('MAIN_PDF_HIDE_CHQ_ADDRESS')) {
1226 $pdf->SetXY($this->marge_gauche, $posy);
1227 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
1228 $pdf->MultiCell(100, 3, $outputlangs->convToOutputCharset($this->emetteur->getFullAddress()), 0, 'L', false);
1229 $posy = $pdf->GetY() + 2;
1230 }
1231 }
1232 }
1233 }
1234
1235 // If payment mode not forced or forced to VIR, show payment with BAN
1236 if (empty($object->mode_reglement_code) || $object->mode_reglement_code == 'VIR') {
1237 if ($object->fk_account > 0 || $object->fk_bank > 0 || getDolGlobalInt('FACTURE_RIB_NUMBER')) {
1238 $bankid = ($object->fk_account <= 0 ? getDolGlobalInt('FACTURE_RIB_NUMBER') : $object->fk_account);
1239 if ($object->fk_bank > 0) {
1240 $bankid = $object->fk_bank; // For backward compatibility when object->fk_account is forced with object->fk_bank
1241 }
1242 $account = new Account($this->db);
1243 $account->fetch((int) $bankid);
1244
1245 $curx = $this->marge_gauche;
1246 $cury = $posy;
1247
1248 $posy = pdf_bank($pdf, $outputlangs, $curx, $cury, $account, 0, $default_font_size);
1249
1250 $posy += 2;
1251 }
1252 }
1253 }
1254
1255 return $posy;
1256 }
1257
1258
1270 protected function drawTotalTable(&$pdf, $object, $deja_regle, $posy, $outputlangs, $outputlangsbis = null)
1271 {
1272 global $conf, $mysoc, $hookmanager;
1273
1274 $default_font_size = pdf_getPDFFontSize($outputlangs);
1275
1276 if (getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE') && $outputlangs->defaultlang != getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE')) {
1277 $outputlangsbis = new Translate('', $conf);
1278 $outputlangsbis->setDefaultLang(getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE'));
1279 $outputlangsbis->loadLangs(array("main", "dict", "companies", "bills", "products", "propal"));
1280 $default_font_size--;
1281 }
1282
1283 $tab2_top = $posy;
1284 $tab2_hl = 4;
1285 $pdf->SetFont('', '', $default_font_size - 1);
1286
1287 // Total table
1288 $col1x = 120;
1289 $col2x = 170;
1290 if ($this->page_largeur < 210) { // To work with US executive format
1291 $col2x -= 20;
1292 }
1293 $largcol2 = ($this->page_largeur - $this->marge_droite - $col2x);
1294
1295 $useborder = 0;
1296 $index = 0;
1297
1298 // Get Total HT
1299 $total_ht = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1 ? $object->multicurrency_total_ht : $object->total_ht);
1300
1301 // Total discount
1302 $total_discount_on_lines = 0;
1303 $multicurrency_total_discount_on_lines = 0;
1304 foreach ($object->lines as $i => $line) {
1305 $resdiscount = pdfGetLineTotalDiscountAmount($object, $i, $outputlangs, 2);
1306 $multicurrency_resdiscount = pdfGetLineTotalDiscountAmount($object, $i, $outputlangs, 2, 1);
1307
1308 $total_discount_on_lines += (is_numeric($resdiscount) ? $resdiscount : 0);
1309 $multicurrency_total_discount_on_lines += (is_numeric($multicurrency_resdiscount) ? $multicurrency_resdiscount : 0);
1310 // If line was a negative line, we do not count the discount as a discount
1311 if ($line->total_ht < 0) {
1312 $total_discount_on_lines += -$line->total_ht;
1313 $multicurrency_total_discount_on_lines += -$line->multicurrency_total_ht;
1314 }
1315 }
1316
1317 if ($total_discount_on_lines > 0) {
1318 if ($this->showAmountBeforeDiscount) {
1319 // Show total NET before discount
1320 $pdf->SetFillColor(255, 255, 255);
1321 $pdf->SetXY($col1x, $tab2_top);
1322 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalHTBeforeDiscount") . (is_object($outputlangsbis) ? ' / ' . $outputlangsbis->transnoentities("TotalHTBeforeDiscount") : ''), 0, 'L', true);
1323 $pdf->SetXY($col2x, $tab2_top);
1324
1325 $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));
1326 $pdf->MultiCell($largcol2, $tab2_hl, price($total_before_discount_to_show, 0, $outputlangs), 0, 'R', true);
1327
1328 $index++;
1329 }
1330
1331 if ($this->showDiscountAmount) {
1332 $pdf->SetFillColor(255, 255, 255);
1333 $pdf->SetXY($col1x, $tab2_top + $tab2_hl);
1334 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalDiscount") . (is_object($outputlangsbis) ? ' / ' . $outputlangsbis->transnoentities("TotalDiscount") : ''), 0, 'L', true);
1335 $pdf->SetXY($col2x, $tab2_top + $tab2_hl);
1336
1337 $total_discount_to_show = ((isModEnabled("multicurrency") && $object->multicurrency_tx != 1) ? $multicurrency_total_discount_on_lines : $total_discount_on_lines);
1338 $pdf->MultiCell($largcol2, $tab2_hl, price($total_discount_to_show, 0, $outputlangs), 0, 'R', true);
1339
1340 $index++;
1341 }
1342 }
1343
1344 // Total HT
1345 $pdf->SetFillColor(255, 255, 255);
1346 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1347 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalHT").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transnoentities("TotalHT") : ''), 0, 'L', true);
1348
1349 $total_ht = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? $object->multicurrency_total_ht : $object->total_ht);
1350 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1351 $pdf->MultiCell($largcol2, $tab2_hl, price($total_ht + (!empty($object->remise) ? $object->remise : 0), 0, $outputlangs), 0, 'R', true);
1352
1353 // Show VAT by rates and total
1354 $pdf->SetFillColor(248, 248, 248);
1355
1356 $total_ttc = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1) ? $object->multicurrency_total_ttc : $object->total_ttc;
1357 $total_ttc_origin = $object->total_ttc;
1358
1359 $this->atleastoneratenotnull = 0;
1360 if (!getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT')) {
1361 $tvaisnull = (!empty($this->tva) && count($this->tva) == 1 && isset($this->tva['0.000']) && is_float($this->tva['0.000']));
1362 if (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_IFNULL') && $tvaisnull) {
1363 // Nothing to do
1364 } else {
1365 //Local tax 1 before VAT
1366 //if (getDolGlobalString('FACTURE_LOCAL_TAX1_OPTION') && getDolGlobalString('FACTURE_LOCAL_TAX1_OPTION') == 'localtax1on')
1367 //{
1368 foreach ($this->localtax1 as $localtax_type => $localtax_rate) {
1369 if (in_array((string) $localtax_type, array('1', '3', '5'))) {
1370 continue;
1371 }
1372
1373 foreach ($localtax_rate as $tvakey => $tvaval) {
1374 if ($tvakey != 0) { // On affiche pas taux 0
1375 //$this->atleastoneratenotnull++;
1376
1377 $index++;
1378 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1379
1380 $tvacompl = '';
1381 if (preg_match('/\*/', $tvakey)) {
1382 $tvakey = str_replace('*', '', $tvakey);
1383 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1384 }
1385 $totalvat = $outputlangs->transcountrynoentities("TotalLT1", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalLT1", $mysoc->country_code) : '');
1386 $totalvat .= ' ';
1387 $totalvat .= vatrate((string) abs((float) $tvakey), true).$tvacompl;
1388 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1389
1390 $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval);
1391
1392 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1393 $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', true);
1394 }
1395 }
1396 }
1397 //}
1398 //Local tax 2 before VAT
1399 //if (getDolGlobalString('FACTURE_LOCAL_TAX2_OPTION') && getDolGlobalString('FACTURE_LOCAL_TAX2_OPTION') == 'localtax2on')
1400 //{
1401 foreach ($this->localtax2 as $localtax_type => $localtax_rate) {
1402 if (in_array((string) $localtax_type, array('1', '3', '5'))) {
1403 continue;
1404 }
1405
1406 foreach ($localtax_rate as $tvakey => $tvaval) {
1407 if ($tvakey != 0) { // On affiche pas taux 0
1408 //$this->atleastoneratenotnull++;
1409
1410 $index++;
1411 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1412
1413 $tvacompl = '';
1414 if (preg_match('/\*/', $tvakey)) {
1415 $tvakey = str_replace('*', '', $tvakey);
1416 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1417 }
1418 $totalvat = $outputlangs->transcountrynoentities("TotalLT2", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalLT2", $mysoc->country_code) : '');
1419 $totalvat .= ' ';
1420 $totalvat .= vatrate((string) abs((float) $tvakey), true).$tvacompl;
1421 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1422
1423 $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval);
1424
1425 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1426 $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', true);
1427 }
1428 }
1429 }
1430 //}
1431
1432 // VAT
1433 foreach ($this->tva as $tvakey => $tvaval) {
1434 if ($tvakey != 0) { // On affiche pas taux 0
1435 $this->atleastoneratenotnull++;
1436
1437 $index++;
1438 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1439
1440 $tvacompl = '';
1441 if (preg_match('/\*/', $tvakey)) {
1442 $tvakey = str_replace('*', '', $tvakey);
1443 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1444 }
1445 $totalvat = $outputlangs->transcountrynoentities("TotalVAT", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalVAT", $mysoc->country_code) : '');
1446 $totalvat .= ' ';
1447 $totalvat .= vatrate($tvakey, true).$tvacompl;
1448 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1449
1450 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1451 $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', true);
1452 }
1453 }
1454
1455 //Local tax 1 after VAT
1456 //if (getDolGlobalString('FACTURE_LOCAL_TAX1_OPTION') && getDolGlobalString('FACTURE_LOCAL_TAX1_OPTION') == 'localtax1on')
1457 //{
1458 foreach ($this->localtax1 as $localtax_type => $localtax_rate) {
1459 if (in_array((string) $localtax_type, array('2', '4', '6'))) {
1460 continue;
1461 }
1462
1463 foreach ($localtax_rate as $tvakey => $tvaval) {
1464 if ($tvakey != 0) { // On affiche pas taux 0
1465 //$this->atleastoneratenotnull++;
1466
1467 $index++;
1468 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1469
1470 $tvacompl = '';
1471 if (preg_match('/\*/', $tvakey)) {
1472 $tvakey = str_replace('*', '', $tvakey);
1473 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1474 }
1475 $totalvat = $outputlangs->transcountrynoentities("TotalLT1", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalLT1", $mysoc->country_code) : '');
1476 $totalvat .= ' ';
1477
1478 $totalvat .= vatrate((string) abs((float) $tvakey), true).$tvacompl;
1479 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1480
1481 $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval);
1482
1483 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1484 $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', true);
1485 }
1486 }
1487 }
1488 //}
1489 //Local tax 2 after VAT
1490 //if (getDolGlobalString('FACTURE_LOCAL_TAX2_OPTION') && getDolGlobalString('FACTURE_LOCAL_TAX2_OPTION') == 'localtax2on')
1491 //{
1492 foreach ($this->localtax2 as $localtax_type => $localtax_rate) {
1493 if (in_array((string) $localtax_type, array('2', '4', '6'))) {
1494 continue;
1495 }
1496
1497 foreach ($localtax_rate as $tvakey => $tvaval) {
1498 // retrieve global local tax
1499 if ($tvakey != 0) { // On affiche pas taux 0
1500 //$this->atleastoneratenotnull++;
1501
1502 $index++;
1503 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1504
1505 $tvacompl = '';
1506 if (preg_match('/\*/', $tvakey)) {
1507 $tvakey = str_replace('*', '', $tvakey);
1508 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1509 }
1510 $totalvat = $outputlangs->transcountrynoentities("TotalLT2", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalLT2", $mysoc->country_code) : '');
1511 $totalvat .= ' ';
1512
1513 if (getDolGlobalString('PDF_LOCALTAX2_LABEL_IS_CODE_OR_RATE') == 'nocodenorate') {
1514 $totalvat .= $tvacompl;
1515 } else {
1516 $totalvat .= vatrate((string) abs((float) $tvakey), true).$tvacompl;
1517 }
1518
1519 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1520
1521 $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval);
1522
1523 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1524 $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', true);
1525 }
1526 }
1527 }
1528 //}
1529
1530 // Total TTC
1531 $index++;
1532 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1533 $pdf->SetTextColor(0, 0, 60);
1534 $pdf->SetFillColor(224, 224, 224);
1535 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalTTC").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transnoentities("TotalTTC") : ''), $useborder, 'L', true);
1536
1537 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1538 if (!isModEnabled("multicurrency") || $object->multicurrency_tx == 1 || getDolGlobalInt('MULTICURRENCY_SHOW_ALSO_MAIN_CURRENCY_ON_PDF') == 0) {
1539 $pdf->MultiCell($largcol2, $tab2_hl, price($total_ttc, 0, $outputlangs), $useborder, 'R', true);
1540 } else {
1541 $pdf->MultiCell($largcol2, $tab2_hl, price($total_ttc, 0, $outputlangs), $useborder, 'R', true);
1542
1543 //$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');
1544 $index++;
1545 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1546 $pdf->SetTextColor(0, 0, 60);
1547 $pdf->SetFillColor(224, 224, 224);
1548 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalTTC").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transnoentities("TotalTTC") : '').' ('.$outputlangs->getCurrencySymbol($mysoc->currency_code).')', $useborder, 'L', true);
1549
1550 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1551 $pdf->MultiCell($largcol2, $tab2_hl, price($total_ttc_origin, 0, $outputlangs, 1, -1, -1, $mysoc->currency_code), $useborder, 'L', true);
1552 }
1553 }
1554 }
1555
1556 $pdf->SetTextColor(0, 0, 0);
1557
1558 $resteapayer = 0;
1559 /*
1560 $resteapayer = $object->total_ttc - $deja_regle;
1561 if (!empty($object->paye)) $resteapayer=0;
1562 */
1563
1564 if ($deja_regle > 0) {
1565 // Already paid + Deposits
1566 $index++;
1567
1568 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1569 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("AlreadyPaid").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transnoentities("AlreadyPaid") : ''), 0, 'L', false);
1570
1571 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1572 $pdf->MultiCell($largcol2, $tab2_hl, price($deja_regle, 0, $outputlangs), 0, 'R', false);
1573
1574 /*
1575 if ($object->close_code == 'discount_vat') {
1576 $index++;
1577 $pdf->SetFillColor(255,255,255);
1578
1579 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1580 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("EscompteOfferedShort"), $useborder, 'L', 1);
1581
1582 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1583 $pdf->MultiCell($largcol2, $tab2_hl, price($object->total_ttc - $deja_regle, 0, $outputlangs), $useborder, 'R', 1);
1584
1585 $resteapayer=0;
1586 }
1587 */
1588
1589 $index++;
1590 $pdf->SetTextColor(0, 0, 60);
1591 $pdf->SetFillColor(224, 224, 224);
1592 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1593 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("RemainderToPay").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transnoentities("RemainderToPay") : ''), $useborder, 'L', true);
1594
1595 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1596 $pdf->MultiCell($largcol2, $tab2_hl, price($resteapayer, 0, $outputlangs), $useborder, 'R', true);
1597
1598 $pdf->SetFont('', '', $default_font_size - 1);
1599 $pdf->SetTextColor(0, 0, 0);
1600 }
1601
1602 $parameters = array('pdf' => &$pdf, 'object' => &$object, 'outputlangs' => $outputlangs, 'index' => &$index, 'posy' => $posy);
1603
1604 $reshook = $hookmanager->executeHooks('afterPDFTotalTable', $parameters, $this); // Note that $action and $object may have been modified by some hooks
1605 if ($reshook < 0) {
1606 $this->error = $hookmanager->error;
1607 $this->errors = $hookmanager->errors;
1608 }
1609
1610 $index++;
1611 return ($tab2_top + ($tab2_hl * $index));
1612 }
1613
1614 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1629 protected function _tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop = 0, $hidebottom = 0, $currency = '', $outputlangsbis = null)
1630 {
1631 global $conf;
1632
1633 // Force to disable hidetop and hidebottom
1634 $hidebottom = 0;
1635 if ($hidetop) {
1636 $hidetop = -1;
1637 }
1638
1639 $currency = !empty($currency) ? $currency : $conf->currency;
1640 $default_font_size = pdf_getPDFFontSize($outputlangs);
1641
1642 // Amount in (at tab_top - 1)
1643 $pdf->SetTextColor(0, 0, 0);
1644 $pdf->SetFont('', '', $default_font_size - 2);
1645
1646 if (empty($hidetop)) {
1647 $titre = $outputlangs->transnoentities("AmountInCurrency", $outputlangs->transnoentitiesnoconv("Currency".$currency));
1648 if (getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE') && is_object($outputlangsbis)) {
1649 $titre .= ' - '.$outputlangsbis->transnoentities("AmountInCurrency", $outputlangsbis->transnoentitiesnoconv("Currency".$currency));
1650 }
1651
1652 $pdf->SetXY($this->page_largeur - $this->marge_droite - ($pdf->GetStringWidth($titre) + 3), $tab_top - 4);
1653 $pdf->MultiCell(($pdf->GetStringWidth($titre) + 3), 2, $titre);
1654
1655 //$conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR='230,230,230';
1656 if (getDolGlobalString('MAIN_PDF_TITLE_BACKGROUND_COLOR')) {
1657 $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')));
1658 }
1659 }
1660
1661 $pdf->SetDrawColor(128, 128, 128);
1662 $pdf->SetFont('', '', $default_font_size - 1);
1663
1664 // Output Rect
1665 $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
1666
1667 if (getDolGlobalString('MAIN_PDF_TITLE_TEXT_COLOR')) {
1668 $arrayColorTextTitle = explode(',', getDolGlobalString('MAIN_PDF_TITLE_TEXT_COLOR'));
1669 $pdf->SetTextColor((float) $arrayColorTextTitle[0], (float) $arrayColorTextTitle[1], (float) $arrayColorTextTitle[2]);
1670 }
1671
1672 $this->pdfTabTitles($pdf, $tab_top, $tab_height, $outputlangs, $hidetop);
1673
1674 if (getDolGlobalString('MAIN_PDF_TITLE_TEXT_COLOR')) {
1675 $pdf->SetTextColor(0, 0, 0);
1676 }
1677
1678 if (empty($hidetop)) {
1679 $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
1680 }
1681 }
1682
1683 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1694 protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $outputlangsbis = null)
1695 {
1696 global $conf, $langs;
1697
1698 $ltrdirection = 'L';
1699 if ($outputlangs->trans("DIRECTION") == 'rtl') {
1700 $ltrdirection = 'R';
1701 }
1702
1703 // Load traductions files required by page
1704 $outputlangs->loadLangs(array("main", "propal", "companies", "bills"));
1705
1706 $default_font_size = pdf_getPDFFontSize($outputlangs);
1707
1708 pdf_pagehead($pdf, $outputlangs, $this->page_hauteur);
1709
1710 $pdf->SetTextColor(0, 0, 60);
1711 $pdf->SetFont('', 'B', $default_font_size + 3);
1712
1713 $w = 100;
1714
1715 $posy = $this->marge_haute;
1716 $posx = $this->page_largeur - $this->marge_droite - $w;
1717
1718 $pdf->SetXY($this->marge_gauche, $posy);
1719
1720 // Logo
1721 if (!getDolGlobalInt('PDF_DISABLE_MYCOMPANY_LOGO')) {
1722 if ($this->emetteur->logo) {
1723 $logodir = $conf->mycompany->dir_output;
1724 if (!empty($conf->mycompany->multidir_output[$object->entity ?? $conf->entity])) {
1725 $logodir = $conf->mycompany->multidir_output[$object->entity ?? $conf->entity];
1726 }
1727 if (!getDolGlobalInt('MAIN_PDF_USE_LARGE_LOGO')) {
1728 $logo = $logodir.'/logos/thumbs/'.$this->emetteur->logo_small;
1729 } else {
1730 $logo = $logodir.'/logos/'.$this->emetteur->logo;
1731 }
1732 if (is_readable($logo)) {
1733 $height = pdf_getHeightForLogo($logo);
1734 $pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto)
1735 } else {
1736 $pdf->SetTextColor(200, 0, 0);
1737 $pdf->SetFont('', 'B', $default_font_size - 2);
1738 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound", $logo), 0, 'L');
1739 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ErrorGoToGlobalSetup"), 0, 'L');
1740 }
1741 } else {
1742 $text = $this->emetteur->name;
1743 $pdf->MultiCell($w, 4, $outputlangs->convToOutputCharset($text), 0, $ltrdirection);
1744 }
1745 }
1746
1747 $pdf->SetFont('', 'B', $default_font_size + 3);
1748 $pdf->SetXY($posx, $posy);
1749 $pdf->SetTextColor(0, 0, 60);
1750 $title = $outputlangs->transnoentities("PdfCommercialProposalTitle");
1751 $title .= ' '.$outputlangs->convToOutputCharset($object->ref);
1752 if ($object->status == $object::STATUS_DRAFT) {
1753 $pdf->SetTextColor(128, 0, 0);
1754 $title .= ' - '.$outputlangs->transnoentities("NotValidated");
1755 }
1756
1757 $pdf->MultiCell($w, 4, $title, '', 'R');
1758
1759 $pdf->SetFont('', 'B', $default_font_size);
1760
1761 /*
1762 $posy += 5;
1763 $pdf->SetXY($posx, $posy);
1764 $pdf->SetTextColor(0, 0, 60);
1765 $textref = $outputlangs->transnoentities("Ref")." : ".$outputlangs->convToOutputCharset($object->ref);
1766 if ($object->status == $object::STATUS_DRAFT) {
1767 $pdf->SetTextColor(128, 0, 0);
1768 $textref .= ' - '.$outputlangs->transnoentities("NotValidated");
1769 }
1770 $pdf->MultiCell($w, 4, $textref, '', 'R');
1771 */
1772
1773 $posy += 3;
1774 $pdf->SetFont('', '', $default_font_size - 2);
1775
1776 $ref_customer = $object->ref_customer ?: $object->ref_client;
1777 if ($ref_customer) {
1778 $posy += 4;
1779 $pdf->SetXY($posx, $posy);
1780 $pdf->SetTextColor(0, 0, 60);
1781 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("RefCustomer")." : ".dol_trunc($outputlangs->convToOutputCharset($ref_customer), 65), '', 'R');
1782 }
1783
1784 if (getDolGlobalString('PDF_SHOW_PROJECT_TITLE')) {
1785 $object->fetchProject();
1786 if (!empty($object->project->title)) {
1787 $posy += 3;
1788 $pdf->SetXY($posx, $posy);
1789 $pdf->SetTextColor(0, 0, 60);
1790 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("Project")." : ". $object->project->title, '', 'R');
1791 }
1792 }
1793
1794 if (getDolGlobalString('PDF_SHOW_PROJECT')) {
1795 $object->fetchProject();
1796 if (!empty($object->project->ref)) {
1797 $outputlangs->load("projects");
1798 $posy += 3;
1799 $pdf->SetXY($posx, $posy);
1800 $pdf->SetTextColor(0, 0, 60);
1801 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("RefProject")." : ". $object->project->ref, '', 'R');
1802 }
1803 }
1804
1805 if (getDolGlobalString('MAIN_PDF_DATE_TEXT')) {
1806 $displaydate = "daytext";
1807 } else {
1808 $displaydate = "day";
1809 }
1810
1811 //$posy += 4;
1812 $posy = $pdf->getY();
1813 $pdf->SetXY($posx, $posy);
1814 $pdf->SetTextColor(0, 0, 60);
1815 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("Date")." : ".dol_print_date($object->date, $displaydate, false, $outputlangs, true), '', 'R');
1816
1817 $posy += 4;
1818 $pdf->SetXY($posx, $posy);
1819 $pdf->SetTextColor(0, 0, 60);
1820
1821 $title = $outputlangs->transnoentities("DateEndPropal");
1822 if (getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE') && is_object($outputlangsbis)) {
1823 $title .= ' - '.$outputlangsbis->transnoentities("DateEndPropal");
1824 }
1825 $pdf->MultiCell($w, 3, $title." : ".dol_print_date($object->fin_validite, $displaydate, false, $outputlangs, true), '', 'R');
1826
1827 if (!getDolGlobalString('MAIN_PDF_HIDE_CUSTOMER_CODE') && $object->thirdparty->code_client) {
1828 $posy += 4;
1829 $pdf->SetXY($posx, $posy);
1830 $pdf->SetTextColor(0, 0, 60);
1831 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("CustomerCode")." : ".$outputlangs->transnoentities((string) $object->thirdparty->code_client), '', 'R');
1832 }
1833
1834 if (!getDolGlobalString('MAIN_PDF_HIDE_CUSTOMER_ACCOUNTING_CODE') && $object->thirdparty->code_compta_client) {
1835 $posy += 4;
1836 $pdf->SetXY($posx, $posy);
1837 $pdf->SetTextColor(0, 0, 60);
1838 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("CustomerAccountancyCode")." : ".$outputlangs->transnoentities((string) $object->thirdparty->code_compta_client), '', 'R');
1839 }
1840
1841 // Get contact
1842 if (getDolGlobalString('DOC_SHOW_FIRST_SALES_REP')) {
1843 $arrayidcontact = $object->getIdContact('internal', 'SALESREPFOLL');
1844 if (count($arrayidcontact) > 0) {
1845 $usertmp = new User($this->db);
1846 $usertmp->fetch($arrayidcontact[0]);
1847 $posy += 4;
1848 $pdf->SetXY($posx, $posy);
1849 $pdf->SetTextColor(0, 0, 60);
1850 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R');
1851 }
1852 }
1853
1854 $posy += 2;
1855 $shipp_shift = 0;
1856 $top_shift = 0;
1857 // Show list of linked objects
1858 $current_y = $pdf->getY();
1859 $posy = pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, $w, 3, 'R', $default_font_size); // May modify $object->note_public
1860 if ($current_y < $pdf->getY()) {
1861 $top_shift = $pdf->getY() - $current_y;
1862 }
1863
1864 if ($showaddress) {
1865 // Sender properties
1866 $carac_emetteur = '';
1867 // Add internal contact of object if defined
1868 $arrayidcontact = $object->getIdContact('internal', 'SALESREPFOLL');
1869 if (count($arrayidcontact) > 0) {
1870 $object->fetch_user($arrayidcontact[0]);
1871 $labelbeforecontactname = ($outputlangs->transnoentities("FromContactName") != 'FromContactName' ? $outputlangs->transnoentities("FromContactName") : $outputlangs->transnoentities("Name"));
1872 $carac_emetteur .= $labelbeforecontactname." ".$outputlangs->convToOutputCharset($object->user->getFullName($outputlangs));
1873 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') || getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ' (' : '';
1874 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') && !empty($object->user->office_phone)) ? $object->user->office_phone : '';
1875 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') && getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ', ' : '';
1876 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT') && !empty($object->user->email)) ? $object->user->email : '';
1877 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') || getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ')' : '';
1878 $carac_emetteur .= "\n";
1879 }
1880
1881 $carac_emetteur .= pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, '', 0, 'source', $object);
1882
1883 // Show sender
1884 $posy = getDolGlobalString('MAIN_PDF_USE_ISO_LOCATION') ? 40 : 42;
1885 $posy += $top_shift;
1886 $posx = $this->marge_gauche;
1887 if (getDolGlobalString('MAIN_INVERT_SENDER_RECIPIENT')) {
1888 $posx = $this->page_largeur - $this->marge_droite - 80;
1889 }
1890
1891 $hautcadre = getDolGlobalString('MAIN_PDF_USE_ISO_LOCATION') ? 38 : 40;
1892 $widthrecbox = getDolGlobalString('MAIN_PDF_USE_ISO_LOCATION') ? 92 : 82;
1893
1894
1895 // Show sender frame
1896 if (!getDolGlobalString('MAIN_PDF_NO_SENDER_FRAME')) {
1897 $pdf->SetTextColor(0, 0, 0);
1898 $pdf->SetFont('', '', $default_font_size - 2);
1899 $pdf->SetXY($posx, $posy - 5);
1900 $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillFrom"), 0, $ltrdirection);
1901 $pdf->SetXY($posx, $posy);
1902 $pdf->SetFillColor(230, 230, 230);
1903 $pdf->RoundedRect($posx, $posy, $widthrecbox, $hautcadre, $this->corner_radius, '1234', 'F');
1904 $pdf->SetTextColor(0, 0, 60);
1905 }
1906
1907 // Show sender name
1908 if (!getDolGlobalString('MAIN_PDF_HIDE_SENDER_NAME')) {
1909 $pdf->SetXY($posx + 2, $posy + 3);
1910 $pdf->SetFont('', 'B', $default_font_size);
1911 $pdf->MultiCell($widthrecbox - 2, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, $ltrdirection);
1912 $posy = $pdf->getY();
1913 }
1914
1915 // Show sender information
1916 $pdf->SetXY($posx + 2, $posy);
1917 $pdf->SetFont('', '', $default_font_size - 1);
1918 $pdf->MultiCell($widthrecbox - 2, 4, $carac_emetteur, 0, $ltrdirection);
1919
1920
1921 // If CUSTOMER contact defined, we use it
1922 $usecontact = false;
1923 $arrayidcontact = $object->getIdContact('external', 'CUSTOMER');
1924 if (count($arrayidcontact) > 0) {
1925 $usecontact = true;
1926 $result = $object->fetch_contact($arrayidcontact[0]);
1927 }
1928
1929 // Recipient name
1930 if ($usecontact && ($object->contact->socid != $object->thirdparty->id && (!isset($conf->global->MAIN_USE_COMPANY_NAME_OF_CONTACT) || getDolGlobalString('MAIN_USE_COMPANY_NAME_OF_CONTACT')))) {
1931 $thirdparty = $object->contact;
1932 } else {
1933 $thirdparty = $object->thirdparty;
1934 }
1935
1936 $carac_client_name = pdfBuildThirdpartyName($thirdparty, $outputlangs);
1937
1938 $mode = 'target';
1939 $carac_client = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, ($usecontact ? $object->contact : ''), ($usecontact ? 1 : 0), $mode, $object);
1940
1941 // Show recipient
1942 $widthrecbox = getDolGlobalString('MAIN_PDF_USE_ISO_LOCATION') ? 92 : 100;
1943 if ($this->page_largeur < 210) {
1944 $widthrecbox = 84; // To work with US executive format
1945 }
1946 $posy = getDolGlobalString('MAIN_PDF_USE_ISO_LOCATION') ? 40 : 42;
1947 $posy += $top_shift;
1948 $posx = $this->page_largeur - $this->marge_droite - $widthrecbox;
1949 if (getDolGlobalString('MAIN_INVERT_SENDER_RECIPIENT')) {
1950 $posx = $this->marge_gauche;
1951 }
1952
1953 // Show recipient frame
1954 if (!getDolGlobalString('MAIN_PDF_NO_RECIPENT_FRAME')) {
1955 $pdf->SetTextColor(0, 0, 0);
1956 $pdf->SetFont('', '', $default_font_size - 2);
1957 $pdf->SetXY($posx + 2, $posy - 5);
1958 $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillTo"), 0, $ltrdirection);
1959 $pdf->RoundedRect($posx, $posy, $widthrecbox, $hautcadre, $this->corner_radius, '1234', 'D');
1960 }
1961
1962 // Show recipient name
1963 $pdf->SetXY($posx + 2, $posy + 3);
1964 $pdf->SetFont('', 'B', $default_font_size);
1965 // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
1966 $pdf->MultiCell($widthrecbox, 2, $carac_client_name, 0, $ltrdirection);
1967
1968 $posy = $pdf->getY();
1969
1970 // Show recipient information
1971 $pdf->SetFont('', '', $default_font_size - 1);
1972 $pdf->SetXY($posx + 2, $posy);
1973 // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
1974 $pdf->MultiCell($widthrecbox, 4, $carac_client, 0, $ltrdirection);
1975 // Show shipping/delivery addressAdd commentMore actions
1976 if (getDolGlobalInt('PROPOSAL_SHOW_SHIPPING_ADDRESS')) {
1977 $idaddressshipping = $object->getIdContact('external', 'SHIPPING');
1978
1979 if (!empty($idaddressshipping)) {
1980 $contactshipping = $object->fetch_Contact($idaddressshipping[0]);
1981 $companystatic = new Societe($this->db);
1982 $companystatic->fetch($object->contact->fk_soc);
1983 $carac_client_name_shipping = pdfBuildThirdpartyName($object->contact, $outputlangs);
1984 $carac_client_shipping = pdf_build_address($outputlangs, $this->emetteur, $companystatic, $object->contact, 1, 'target', $object);
1985 } else {
1986 $carac_client_name_shipping = pdfBuildThirdpartyName($object->thirdparty, $outputlangs);
1987 $carac_client_shipping = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, '', 0, 'target', $object);
1988 }
1989 if (!empty($carac_client_shipping)) {
1990 $posy += $hautcadre;
1991
1992 $hautcadre -= 5; // Height for the shipping address does not need to be as high as main box
1993
1994 // Show shipping frame
1995 $pdf->SetXY($posx + 2, $posy - 5);
1996 $pdf->SetFont('', '', $default_font_size - 2);
1997 $pdf->MultiCell($widthrecbox, 0, $outputlangs->transnoentities('ShippingTo'), 0, 'L', false);
1998 $pdf->RoundedRect($posx, $posy, $widthrecbox, $hautcadre, $this->corner_radius, '1234', 'D');
1999
2000 // Show shipping name
2001 $pdf->SetXY($posx + 2, $posy + 3);
2002 $pdf->SetFont('', 'B', $default_font_size);
2003 $pdf->MultiCell($widthrecbox - 2, 2, $carac_client_name_shipping, '', 'L');
2004
2005 $posy = $pdf->getY();
2006
2007 // Show shipping information
2008 $pdf->SetXY($posx + 2, $posy);
2009 $pdf->SetFont('', '', $default_font_size - 1);
2010 $pdf->MultiCell($widthrecbox - 2, 2, $carac_client_shipping, '', 'L');
2011
2012 $shipp_shift += $hautcadre + 10;
2013 }
2014 }
2015 }
2016 $pdf->SetTextColor(0, 0, 0);
2017 return $shipp_shift;
2018 }
2019
2020 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
2030 protected function _pagefoot(&$pdf, $object, $outputlangs, $hidefreetext = 0)
2031 {
2032 $showdetails = getDolGlobalInt('MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS', 0);
2033 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);
2034 }
2035
2045 protected function drawSignatureArea(&$pdf, $object, $posy, $outputlangs)
2046 {
2047 $default_font_size = pdf_getPDFFontSize($outputlangs);
2048 $tab_top = $posy + 4;
2049 $tab_hl = 4;
2050
2051 $posx = 120;
2052 $largcol = ($this->page_largeur - $this->marge_droite - $posx);
2053
2054 // Total HT
2055 $pdf->SetFillColor(255, 255, 255);
2056 $pdf->SetXY($posx, $tab_top);
2057 $pdf->SetFont('', '', $default_font_size - 2);
2058 $pdf->MultiCell($largcol, $tab_hl, $outputlangs->transnoentities("ProposalCustomerSignature"), 0, 'L', true);
2059
2060 $pdf->SetXY($posx, $tab_top + $tab_hl + 3);
2061 //$pdf->MultiCell($largcol, $tab_hl * 3, '', 1, 'R');
2062 $pdf->RoundedRect($posx, $tab_top + $tab_hl + 3, $largcol, $tab_hl * 3, $this->corner_radius, '1234', 'D');
2063
2064
2065 if (getDolGlobalString('MAIN_PDF_PROPAL_USE_ELECTRONIC_SIGNING')) {
2066 // Can be retrieve with getSignatureAppearanceArray()
2067 // Can be also detected by putting the mouse over the area when using evince pdf reader
2068 $pdf->addEmptySignatureAppearance($posx, $tab_top + $tab_hl + 3, $largcol, $tab_hl * 3);
2069 }
2070
2071 return ($tab_hl * 7);
2072 }
2073
2074
2085 public function defineColumnField($object, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0)
2086 {
2087 global $hookmanager;
2088
2089 // Default field style for content
2090 $this->defaultContentsFieldsStyle = array(
2091 'align' => 'R', // R,C,L
2092 'padding' => array(1, 0.5, 1, 0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
2093 );
2094
2095 // Default field style for content
2096 $this->defaultTitlesFieldsStyle = array(
2097 'align' => 'C', // R,C,L
2098 'padding' => array(0.5, 0, 0.5, 0), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
2099 );
2100
2101 /*
2102 * For example
2103 $this->cols['theColKey'] = array(
2104 'rank' => $rank, // int : use for ordering columns
2105 'width' => 20, // the column width in mm
2106 'title' => array(
2107 'textkey' => 'yourLangKey', // if there is no label, yourLangKey will be translated to replace label
2108 'label' => ' ', // the final label : used fore final generated text
2109 'align' => 'L', // text alignment : R,C,L
2110 'padding' => array(0.5,0.5,0.5,0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
2111 ),
2112 'content' => array(
2113 'align' => 'L', // text alignment : R,C,L
2114 'padding' => array(0.5,0.5,0.5,0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
2115 ),
2116 );
2117 */
2118
2119 $rank = 0; // do not use negative rank
2120 $this->cols['position'] = array(
2121 'rank' => $rank,
2122 'width' => 10,
2123 'status' => getDolGlobalInt('PDF_CYAN_ADD_POSITION') ? true : (getDolGlobalInt('PDF_ADD_POSITION') ? true : false),
2124 'title' => array(
2125 'textkey' => '#', // use lang key is useful in some case with module
2126 'align' => 'C',
2127 // 'textkey' => 'yourLangKey', // if there is no label, yourLangKey will be translated to replace label
2128 // 'label' => ' ', // the final label
2129 'padding' => array(0.5, 0.5, 0.5, 0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
2130 ),
2131 'content' => array(
2132 'align' => 'C',
2133 'padding' => array(1, 0.5, 1, 1.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
2134 ),
2135 );
2136
2137 $rank = 5; // do not use negative rank
2138 $this->cols['desc'] = array(
2139 'rank' => $rank,
2140 'width' => false, // only for desc
2141 'status' => true,
2142 'title' => array(
2143 'textkey' => 'Designation', // use lang key is useful in some case with module
2144 'align' => 'L',
2145 // 'textkey' => 'yourLangKey', // if there is no label, yourLangKey will be translated to replace label
2146 // 'label' => ' ', // the final label
2147 'padding' => array(0.5, 0.5, 0.5, 0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
2148 ),
2149 'content' => array(
2150 'align' => 'L',
2151 'padding' => array(1, 0.5, 1, 1.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
2152 ),
2153 );
2154
2155 // Image of product
2156 $rank += 10;
2157 $this->cols['photo'] = array(
2158 'rank' => $rank,
2159 'width' => getDolGlobalInt('MAIN_DOCUMENTS_WITH_PICTURE_WIDTH', 20), // in mm
2160 'status' => false,
2161 'title' => array(
2162 'textkey' => 'Photo',
2163 'label' => ' '
2164 ),
2165 'content' => array(
2166 'padding' => array(0, 0, 0, 0), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
2167 ),
2168 'border-left' => false, // remove left line separator
2169 );
2170
2171 if (getDolGlobalString('MAIN_GENERATE_PROPOSALS_WITH_PICTURE') && !empty($this->atleastonephoto)) {
2172 $this->cols['photo']['status'] = true;
2173 $this->cols['photo']['border-left'] = true;
2174 }
2175
2176
2177 $rank += 10;
2178 $this->cols['vat'] = array(
2179 'rank' => $rank,
2180 'status' => false,
2181 'width' => 16, // in mm
2182 'title' => array(
2183 'textkey' => 'VAT'
2184 ),
2185 'border-left' => true, // add left line separator
2186 );
2187
2188 if (!getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT') && !getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_COLUMN')) {
2189 $this->cols['vat']['status'] = true;
2190 }
2191
2192 $rank += 10;
2193 $this->cols['subprice'] = array(
2194 'rank' => $rank,
2195 'width' => 19, // in mm
2196 'status' => true,
2197 'title' => array(
2198 'textkey' => 'PriceUHT'
2199 ),
2200 'border-left' => true, // add left line separator
2201 );
2202
2203 // Adapt dynamically the width of subprice, if text is too long.
2204 $tmpwidth = 0;
2205 $nblines = count($object->lines);
2206 for ($i = 0; $i < $nblines; $i++) {
2207 $tmpwidth2 = dol_strlen(dol_string_nohtmltag(pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails)));
2208 $tmpwidth = max($tmpwidth, $tmpwidth2);
2209 }
2210 if ($tmpwidth > 10) {
2211 $this->cols['subprice']['width'] += (2 * ($tmpwidth - 10));
2212 }
2213
2214 $rank += 10;
2215 $this->cols['qty'] = array(
2216 'rank' => $rank,
2217 'width' => 16, // in mm
2218 'status' => true,
2219 'title' => array(
2220 'textkey' => 'Qty'
2221 ),
2222 'border-left' => true, // add left line separator
2223 );
2224
2225 $rank += 10;
2226 $this->cols['unit'] = array(
2227 'rank' => $rank,
2228 'width' => 11, // in mm
2229 'status' => false,
2230 'title' => array(
2231 'textkey' => 'Unit'
2232 ),
2233 'border-left' => true, // add left line separator
2234 );
2235 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
2236 $this->cols['unit']['status'] = true;
2237 }
2238
2239 $rank += 10;
2240 $this->cols['discount'] = array(
2241 'rank' => $rank,
2242 'width' => 13, // in mm
2243 'status' => false,
2244 'title' => array(
2245 'textkey' => 'ReductionShort'
2246 ),
2247 'border-left' => true, // add left line separator
2248 );
2249 if ($this->atleastonediscount) {
2250 $this->cols['discount']['status'] = true;
2251 }
2252
2253 $rank += 1000; // add a big offset to be sure is the last col because default extrafield rank is 100
2254 $this->cols['totalexcltax'] = array(
2255 'rank' => $rank,
2256 'width' => 26, // in mm
2257 'status' => !getDolGlobalString('PDF_PROPAL_HIDE_PRICE_EXCL_TAX'),
2258 'title' => array(
2259 'textkey' => 'TotalHTShort'
2260 ),
2261 'border-left' => true, // add left line separator
2262 );
2263
2264 $rank += 1010; // add a big offset to be sure is the last col because default extrafield rank is 100
2265 $this->cols['totalincltax'] = array(
2266 'rank' => $rank,
2267 'width' => 26, // in mm
2268 'status' => getDolGlobalBool('PDF_PROPAL_SHOW_PRICE_INCL_TAX'),
2269 'title' => array(
2270 'textkey' => 'TotalTTCShort'
2271 ),
2272 'border-left' => true, // add left line separator
2273 );
2274
2275 // Add extrafields cols
2276 if (!empty($object->lines)) {
2277 $line = reset($object->lines);
2278 $this->defineColumnExtrafield($line, $outputlangs, $hidedetails);
2279 }
2280
2281 $parameters = array(
2282 'object' => $object,
2283 'outputlangs' => $outputlangs,
2284 'hidedetails' => $hidedetails,
2285 'hidedesc' => $hidedesc,
2286 'hideref' => $hideref
2287 );
2288
2289 $reshook = $hookmanager->executeHooks('defineColumnField', $parameters, $this); // Note that $object may have been modified by hook
2290 if ($reshook < 0) {
2291 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
2292 } elseif (empty($reshook)) {
2293 // @phan-suppress-next-line PhanPluginSuspiciousParamOrderInternal
2294 $this->cols = array_replace($this->cols, $hookmanager->resArray); // array_replace is used to preserve keys
2295 } else {
2296 $this->cols = $hookmanager->resArray;
2297 }
2298 }
2299}
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
Class to manage bank accounts.
prepareArrayColumnField($object, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0)
Prepare Array Column Field.
getColumnStatus($colKey)
get column status from column key
printStdColumnContent($pdf, &$curY, $colKey, $columnText='')
print standard column content
pdfTabTitles(&$pdf, $tab_top, $tab_height, $outputlangs, $hidetop=0)
Print standard column content.
printColDescContent($pdf, &$curY, $colKey, $object, $i, $outputlangs, $hideref=0, $hidedesc=0, $issupplierline=0)
print description column content
getMaxAfterColsLinePositionsData()
Get position in PDF after col display.
getColumnContentXStart($colKey)
get column content X (abscissa) left position from column key
setAfterColsLinePositionsData(string $colId, float $y, int $pageNumb)
Used for to set afterColsLinePositions var in a pdf draw line loop.
getExtrafieldContent($object, $extrafieldKey, $outputlangs=null)
get extrafield content for pdf writeHtmlCell compatibility usage for PDF line columns and object note...
printRoundedRect($pdf, $x, $y, $w, $h, $r, $hidetop=0, $hidebottom=0, $style='D')
Print a rounded rectangle on the PDF.
resetAfterColsLinePositionsData(float $y, int $pageNumb)
Used for reset afterColsLinePositions var in start of a new pdf draw line loop.
defineColumnExtrafield($object, $outputlangs, $hidedetails=0)
Define Array Column Field for extrafields.
Class to manage hooks.
Class mere des modeles de propale.
Class to manage products or services.
Put here description of your class.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage translations.
Class to manage Dolibarr users.
Class to generate PDF proposal Cyan.
drawTotalTable(&$pdf, $object, $deja_regle, $posy, $outputlangs, $outputlangsbis=null)
Show total to pay.
defineColumnField($object, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0)
Define Array Column Field.
_tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop=0, $hidebottom=0, $currency='', $outputlangsbis=null)
Show table for lines.
__construct($db)
Constructor.
_pagefoot(&$pdf, $object, $outputlangs, $hidefreetext=0)
Show footer of page.
_pagehead(&$pdf, $object, $showaddress, $outputlangs, $outputlangsbis=null)
Show top header of page.
write_file($object, $outputlangs, $srctemplatepath='', $hidedetails=0, $hidedesc=0, $hideref=0)
Function to build pdf onto disk.
drawSignatureArea(&$pdf, $object, $posy, $outputlangs)
Show area for the customer to sign.
drawInfoTable(&$pdf, $object, $posy, $outputlangs)
Show miscellaneous information (payment mode, payment term, ...)
global $mysoc
print $script_file $mode $langs defaultlang(is_numeric($duration_value) ? " delay=". $duration_value :"").(is_numeric($duration_value2) ? " after cd cd cd description as description
Only used if Module[ID]Desc translation string is not found.
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!function_exists( 'dolEscapeXML')) convertBackOfficeMediasLinksToPublicLinks($notetoshow)
Convert links to local wrapper to medias files into a string into a public external URL readable on i...
colorStringToArray($stringcolor, $colorifnotfound=array(88, 88, 88))
Convert a string RGB value ('FFFFFF', '255,255,255') into an array RGB array(255,255,...
dol_getIdFromCode($db, $key, $tablename, $fieldkey='code', $fieldid='id', $entityfilter=0, $filters='', $useCache=true)
Return an id or code from a code or id.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
vatrate($rate, $addpercent=false, $info_bits=0, $usestarfornpr=0, $html=0)
Return a string with VAT rate label formatted for view output Used into pdf and HTML pages.
dol_string_nohtmltag($stringtoclean, $removelinefeed=1, $pagecodeto='UTF-8', $strip_tags=0, $removedoublespaces=1)
Clean a string from all HTML tags and entities.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
getCallerInfoString()
Get caller info as a string that can be appended to a log message.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
dolChmod($filepath, $newmask='')
Change mod of a file.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
getLocalTaxesFromRate($vatrate, $local, $buyer, $seller, $firstparamisid=0)
Get type and rate of localtaxes for a particular vat rate/country of a thirdparty.
dol_concatdesc($text1, $text2, $forxml=false, $invert=false)
Concat 2 descriptions with a new line between them (second operand after first one with appropriate n...
complete_substitutions_array(&$substitutionarray, $outputlangs, $object=null, $parameters=null, $callfunc="completesubstitutionarray")
Complete the $substitutionarray with more entries coming from external module that had set the "subst...
make_substitutions($text, $substitutionarray, $outputlangs=null, $converttextinhtmlifnecessary=0)
Make substitution into a text string, replacing keys with vals from $substitutionarray (oldval=>newva...
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
getDolGlobalBool($key, $default=false)
Return a Dolibarr global constant boolean value.
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
dol_htmlentitiesbr($stringtoencode, $nl2brmode=0, $pagecodefrom='UTF-8', $removelasteolbr=1)
This function is called to encode a string into a HTML string but differs from htmlentities because a...
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
get_exdir($num, $level, $alpha, $withoutslash, $object, $modulepart='')
Return a path to have a the directory according to object where files are stored.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
print $langs trans("Show") . '< td style="' . $timeColor . '" align="center"> s</td > badge status0 badge status4 badge status3 Error badge status8< td align="center">< span class="badge ' . $badge . '"></span ></td >< td align="center">< a href="#" class="button button-small" onclick="openLogModal(this)" data-req="' . dol_escape_htmltag($reqSafe) . '" data-res="' . dol_escape_htmltag($resSafe) . '" data-err="' . dol_escape_htmltag($errSafe) . '">< span class="fa fa-search-plus"></span ></a ></td ></tr >< tr >< td colspan="' . $colspan . '" class="opacitymedium"></td ></tr ></table ></div ></form > logModal none logModal none s a JSON string
buildzip.php
pdf_getSizeForImage($realpath)
Return dimensions to use for images onto PDF checking that width and height are not higher than maxim...
Definition pdf.lib.php:3160
pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line total excluding tax.
Definition pdf.lib.php:2861
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:3192
pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, $w, $h, $align, $default_font_size)
Show linked objects for PDF generation.
Definition pdf.lib.php:1808
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:1239
pdf_getHeightForLogo($logo, $url=false)
Return height to use for Logo onto PDF.
Definition pdf.lib.php:317
pdf_getlinetotalwithtax($object, $i, $outputlangs, $hidedetails=0)
Return line total including tax.
Definition pdf.lib.php:2911
pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line unit price excluding tax.
Definition pdf.lib.php:2464
pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails=0)
Return line vat rate.
Definition pdf.lib.php:2402
pdf_pagehead($pdf, $outputlangs, $page_height)
Show header of page for PDF generation.
Definition pdf.lib.php:747
pdfGetHeightForHtmlContent($pdf, $htmlcontent)
Function to try to calculate height of a HTML Content.
Definition pdf.lib.php:342
pdf_pagefoot($pdf, $outputlangs, $paramfreetext, $fromcompany, $marge_basse, $marge_gauche, $page_hauteur, $object, $showdetails=0, $hidefreetext=0, $page_largeur=0, $watermark='')
Show footer of page for PDF generation.
Definition pdf.lib.php:1421
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:3288
pdf_build_address($outputlangs, $sourcecompany, $targetcompany='', $targetcontact='', $usecontact=0, $mode='source', $object=null)
Return a string with full address formatted for output on PDF documents.
Definition pdf.lib.php:438
pdf_getlineunit($object, $i, $outputlangs, $hidedetails=0)
Return line unit.
Definition pdf.lib.php:2709
pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails=0)
Return line remise percent.
Definition pdf.lib.php:2752
pdf_getlineqty($object, $i, $outputlangs, $hidedetails=0)
Return line quantity.
Definition pdf.lib.php:2549
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:1135
pdf_getInstance($format='', $metric='mm', $pagetype='P')
Return a PDF instance object.
Definition pdf.lib.php:129
pdfBuildThirdpartyName($thirdparty, Translate $outputlangs, $includealias=0)
Returns the name of the thirdparty.
Definition pdf.lib.php:393
if(preg_match('/(crypted|dolcrypt):/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
'integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]',...
Definition repair.php:130
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:133