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