dolibarr 24.0.0-beta
pdf_azur.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-2018 Ferran Marcet <fmarcet@2byte.es>
10 * Copyright (C) 2018-2026 Frédéric France <frederic.france@free.fr>
11 * Copyright (C) 2019 Pierre Ardoin <mapiolca@me.com>
12 * Copyright (C) 2021-2024 Anthony Berton <anthony.berton@bb2a.fr>
13 * Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
14 * Copyright (C) 2024 Nick Fragoulis
15 * Copyright (C) 2024 Alexandre Spangaro <alexandre@inovea-conseil.com>
16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 3 of the License, or
20 * (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program. If not, see <https://www.gnu.org/licenses/>.
29 * or see https://www.gnu.org/
30 */
31
38require_once DOL_DOCUMENT_ROOT.'/core/modules/propale/modules_propale.php';
39require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
40require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
41require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
42require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
43
44
49{
53 public $db;
54
58 public $entity;
59
63 public $name;
64
68 public $description;
69
73 public $update_main_doc_field;
74
78 public $type;
79
84 public $version = 'dolibarr';
85
86
92 public function __construct($db)
93 {
94 global $langs, $mysoc;
95
96 // Translations
97 $langs->loadLangs(array("main", "bills"));
98
99 $this->db = $db;
100 $this->name = "azur";
101 $this->description = $langs->trans('DocModelAzurDescription');
102 $this->update_main_doc_field = 1; // Save the name of generated file as the main doc when generating a doc with this template
103
104 // Dimension page
105 $this->type = 'pdf';
106 $formatarray = pdf_getFormat();
107 $this->page_largeur = $formatarray['width'];
108 $this->page_hauteur = $formatarray['height'];
109 $this->format = array($this->page_largeur, $this->page_hauteur);
110 $this->marge_gauche = getDolGlobalInt('MAIN_PDF_MARGIN_LEFT', 10);
111 $this->marge_droite = getDolGlobalInt('MAIN_PDF_MARGIN_RIGHT', 10);
112 $this->marge_haute = getDolGlobalInt('MAIN_PDF_MARGIN_TOP', 10);
113 $this->marge_basse = getDolGlobalInt('MAIN_PDF_MARGIN_BOTTOM', 10);
114 $this->corner_radius = getDolGlobalInt('MAIN_PDF_FRAME_CORNER_RADIUS', 0);
115 $this->option_logo = 1; // Display logo
116 $this->option_tva = 1; // Manage the vat option FACTURE_TVAOPTION
117 $this->option_modereg = 1; // Display payment mode
118 $this->option_condreg = 1; // Display payment terms
119 $this->option_multilang = 1; // Available in several languages
120 $this->option_escompte = 0; // Displays if there has been a discount
121 $this->option_credit_note = 0; // Support credit notes
122 $this->option_freetext = 1; // Support add of a personalised text
123 $this->option_draft_watermark = 1; // Support add of a watermark on drafts
124 $this->watermark = '';
125
126 // Define position of columns
127 $this->posxdesc = $this->marge_gauche + 1;
128 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
129 $this->posxtva = 101;
130 $this->posxup = 118;
131 $this->posxqty = 135;
132 $this->posxunit = 151;
133 } else {
134 $this->posxtva = 106;
135 $this->posxup = 122;
136 $this->posxqty = 145;
137 $this->posxunit = 162;
138 }
139 $this->posxdiscount = 162;
140 $this->postotalht = 174;
141 if (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT') || getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_COLUMN')) {
142 $this->posxtva = $this->posxup;
143 }
144 $this->posxpicture = $this->posxtva - getDolGlobalInt('MAIN_DOCUMENTS_WITH_PICTURE_WIDTH', 20); // width of images
145 if ($this->page_largeur < 210) { // To work with US executive format
146 $this->posxpicture -= 20;
147 $this->posxtva -= 20;
148 $this->posxup -= 20;
149 $this->posxqty -= 20;
150 $this->posxunit -= 20;
151 $this->posxdiscount -= 20;
152 $this->postotalht -= 20;
153 }
154
155 $this->tva = array();
156 $this->tva_array = array();
157 $this->localtax1 = array();
158 $this->localtax2 = array();
159 $this->atleastoneratenotnull = 0;
160 $this->atleastonediscount = 0;
161
162 $this->showAmountBeforeDiscount = getDolGlobalInt('MAIN_HIDE_AMOUNT_BEFORE_DISCOUNT') || getDolGlobalInt('MAIN_HIDE_AMOUNT_BEFORE_DISCOUNT_PROPALE') ? 0 : 1;
163 $this->showDiscountAmount = getDolGlobalInt('MAIN_HIDE_AMOUNT_DISCOUNT') || getDolGlobalInt('MAIN_HIDE_AMOUNT_BEFORE_DISCOUNT_PROPALE') ? 0 : 1;
164
165 if ($mysoc === null) {
166 dol_syslog(get_class($this).'::__construct() Global $mysoc should not be null.'. getCallerInfoString(), LOG_ERR);
167 return;
168 }
169
170 // Get source company
171 $this->emetteur = $mysoc;
172 if (empty($this->emetteur->country_code)) {
173 $this->emetteur->country_code = substr($langs->defaultlang, -2); // By default, if was not defined
174 }
175 }
176
177 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
189 public function write_file($object, $outputlangs, $srctemplatepath = '', $hidedetails = 0, $hidedesc = 0, $hideref = 0)
190 {
191 // phpcs:enable
192 global $user, $langs, $conf, $mysoc, $db, $hookmanager, $nblines;
193
194 dol_syslog("write_file outputlangs->defaultlang=".(is_object($outputlangs) ? $outputlangs->defaultlang : 'null'));
195
196 if (!is_object($outputlangs)) {
197 $outputlangs = $langs;
198 }
199 // For backward compatibility with FPDF, force output charset to ISO, because FPDF expect text to be encoded in ISO
200 if (getDolGlobalString('MAIN_USE_FPDF')) {
201 $outputlangs->charset_output = 'ISO-8859-1';
202 }
203
204 // Load translation files required by page
205 $langfiles = array("main", "dict", "companies", "bills", "propal", "products", "compta");
206 $outputlangs->loadLangs($langfiles);
207
208 global $outputlangsbis;
209 $outputlangsbis = null;
210 if (getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE') && $outputlangs->defaultlang != getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE')) {
211 $outputlangsbis = new Translate('', $conf);
212 $outputlangsbis->setDefaultLang(getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE'));
213 $outputlangsbis->loadLangs($langfiles);
214 }
215
216 // Show Draft Watermark
217 if ($object->statut == $object::STATUS_DRAFT && getDolGlobalString('PROPALE_DRAFT_WATERMARK')) {
218 $this->watermark = getDolGlobalString('PROPALE_DRAFT_WATERMARK');
219 }
220
221 $nblines = count($object->lines);
222
223 // Loop on each lines to detect if there is at least one image to show
224 $realpatharray = array();
225 $this->atleastonephoto = false;
226 if (getDolGlobalString('MAIN_GENERATE_PROPOSALS_WITH_PICTURE')) {
227 $objphoto = new Product($this->db);
228
229 for ($i = 0; $i < $nblines; $i++) {
230 if (empty($object->lines[$i]->fk_product)) {
231 continue;
232 }
233
234 $objphoto->fetch($object->lines[$i]->fk_product);
235 //var_dump($objphoto->ref);exit;
236 $pdir = array();
237 if (getDolGlobalInt('PRODUCT_USE_OLD_PATH_FOR_PHOTO')) {
238 $pdir[0] = get_exdir($objphoto->id, 2, 0, 0, $objphoto, 'product').$objphoto->id."/photos/";
239 $pdir[1] = get_exdir(0, 0, 0, 0, $objphoto, 'product').dol_sanitizeFileName($objphoto->ref).'/';
240 } else {
241 $pdir[0] = get_exdir(0, 0, 0, 0, $objphoto, 'product'); // default
242 $pdir[1] = get_exdir($objphoto->id, 2, 0, 0, $objphoto, 'product').$objphoto->id."/photos/"; // alternative
243 }
244
245 $arephoto = false;
246 $realpath = '';
247 foreach ($pdir as $midir) {
248 if (!$arephoto) {
249 $entity = $objphoto->entity;
250 if ($entity !== null && $conf->entity != $entity) {
251 $dir = $conf->product->multidir_output[$entity].'/'.$midir; //Check repertories of current entities
252 } else {
253 $dir = $conf->product->dir_output.'/'.$midir; //Check repertory of the current product
254 }
255 foreach ($objphoto->liste_photos($dir, 1) as $key => $obj) {
256 if (!getDolGlobalInt('CAT_HIGH_QUALITY_IMAGES')) { // If CAT_HIGH_QUALITY_IMAGES not defined, we use thumb if defined and then original photo
257 if ($obj['photo_vignette']) {
258 $filename = $obj['photo_vignette'];
259 } else {
260 $filename = $obj['photo'];
261 }
262 } else {
263 $filename = $obj['photo'];
264 }
265
266 $realpath = $dir.$filename;
267 $arephoto = true;
268 $this->atleastonephoto = true;
269 }
270 }
271 }
272
273 if ($realpath && $arephoto) {
274 $realpatharray[$i] = $realpath;
275 }
276 }
277 }
278
279 if (count($realpatharray) == 0) {
280 $this->posxpicture = $this->posxtva;
281 }
282
283 if ($conf->propal->multidir_output[$conf->entity]) {
284 $object->fetch_thirdparty();
285
286 $deja_regle = 0;
287
288 // Definition of $dir and $file
289 if ($object->specimen) {
290 $dir = $conf->propal->multidir_output[$conf->entity];
291 $file = $dir."/SPECIMEN.pdf";
292 } else {
293 $objectref = dol_sanitizeFileName($object->ref);
294 $dir = $conf->propal->multidir_output[$object->entity ?? $conf->entity]."/".$objectref;
295 $file = $dir."/".$objectref.".pdf";
296 }
297
298 if (!file_exists($dir)) {
299 if (dol_mkdir($dir) < 0) {
300 $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
301 return 0;
302 }
303 }
304
305 if (file_exists($dir)) {
306 // Add pdfgeneration hook
307 if (!is_object($hookmanager)) {
308 include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
309 $hookmanager = new HookManager($this->db);
310 }
311 $hookmanager->initHooks(array('pdfgeneration'));
312 $parameters = array('file' => $file, 'object' => $object, 'outputlangs' => $outputlangs);
313 global $action;
314 $reshook = $hookmanager->executeHooks('beforePDFCreation', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
315
316 // Set nblines with the new content of lines after hook
317 $nblines = count($object->lines);
318 //$nbpayments = count($object->getListOfPayments());
319
320 // Create pdf instance
321 $pdf = pdf_getInstance($this->format);
322 $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance
323 $pdf->setAutoPageBreak(true, 0);
324
325 if (class_exists('TCPDF')) {
326 $pdf->setPrintHeader(false);
327 $pdf->setPrintFooter(false);
328 }
329 $pdf->SetFont(pdf_getPDFFont($outputlangs));
330 // Set path to the background PDF File
331 if (getDolGlobalString('MAIN_ADD_PDF_BACKGROUND')) {
332 $logodir = $conf->mycompany->dir_output;
333 if (!empty($conf->mycompany->multidir_output[$object->entity ?? $conf->entity])) {
334 $logodir = $conf->mycompany->multidir_output[$object->entity ?? $conf->entity];
335 }
336 $pagecount = $pdf->setSourceFile($logodir.'/' . getDolGlobalString('MAIN_ADD_PDF_BACKGROUND'));
337 $tplidx = $pdf->importPage(1);
338 }
339
340 $pdf->Open();
341 $pagenb = 0;
342 $pdf->SetDrawColor(128, 128, 128);
343
344 $pdf->SetTitle($outputlangs->convToOutputCharset($object->ref));
345 $pdf->SetSubject($outputlangs->transnoentities("PdfCommercialProposalTitle"));
346 $pdf->SetCreator("Dolibarr ".DOL_VERSION);
347 $pdf->SetAuthor($outputlangs->convToOutputCharset($user->getAnonymisableFullName($outputlangs)));
348 $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("PdfCommercialProposalTitle")." ".$outputlangs->convToOutputCharset($object->thirdparty->name));
349 if (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) {
350 $pdf->SetCompression(false);
351 }
352
353 // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
354 $pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite); // Left, Top, Right
355
356 // Set $this->atleastonediscount if you have at least one discount
357 for ($i = 0; $i < $nblines; $i++) {
358 if ($object->lines[$i]->remise_percent) {
359 $this->atleastonediscount++;
360 }
361 }
362 if (empty($this->atleastonediscount)) {
363 $delta = ($this->postotalht - $this->posxdiscount);
364 $this->posxpicture += $delta;
365 $this->posxtva += $delta;
366 $this->posxup += $delta;
367 $this->posxqty += $delta;
368 $this->posxunit += $delta;
369 $this->posxdiscount += $delta;
370 // post of fields after are not modified, stay at same position
371 }
372
373 // New page
374 $pdf->AddPage();
375 if (!empty($tplidx)) {
376 $pdf->useTemplate($tplidx);
377 }
378 $pagenb++;
379
380 $heightforinfotot = 40; // Height reserved to output the info and total part
381 $heightforsignature = !getDolGlobalString('PROPAL_DISABLE_SIGNATURE') ? (pdfGetHeightForHtmlContent($pdf, $outputlangs->transnoentities("ProposalCustomerSignature")) + 10) : 0;
382 $heightforfreetext = getDolGlobalInt('MAIN_PDF_FREETEXT_HEIGHT', 5); // Height reserved to output the free text on last page
383 $heightforfooter = $this->marge_basse + 8; // Height reserved to output the footer (value include bottom margin)
384 if (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS')) {
385 $heightforfooter += 6;
386 }
387 //print $heightforinfotot + $heightforsignature + $heightforfreetext + $heightforfooter;exit;
388
389 $top_shift = $this->_pagehead($pdf, $object, 1, $outputlangs, $outputlangsbis);
390 $pdf->SetFont('', '', $default_font_size - 1);
391 $pdf->MultiCell(0, 3, ''); // Set interline to 3
392 $pdf->SetTextColor(0, 0, 0);
393
394
395 $tab_top = 90 + $top_shift;
396 $tab_top_newpage = (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD') ? 42 + $top_shift : 10);
397
398 // Incoterm
399 $height_incoterms = 0;
400 if (isModEnabled('incoterm')) {
401 $desc_incoterms = $object->getIncotermsForPDF();
402 if ($desc_incoterms) {
403 $tab_top -= 2;
404
405 $pdf->SetFont('', '', $default_font_size - 1);
406 $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top - 1, dol_htmlentitiesbr($desc_incoterms), 0, 1);
407 $nexY = $pdf->GetY();
408 $height_incoterms = $nexY - $tab_top;
409
410 // Rect takes a length in 3rd parameter
411 $pdf->SetDrawColor(192, 192, 192);
412 $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');
413
414 $tab_top = $nexY + 6;
415 $height_incoterms += 4;
416 }
417 }
418
419 // Displays notes
420 $notetoshow = empty($object->note_public) ? '' : $object->note_public;
421 if (getDolGlobalString('MAIN_ADD_SALE_REP_SIGNATURE_IN_NOTE')) {
422 // Get first sale rep
423 if (is_object($object->thirdparty)) {
424 $salereparray = $object->thirdparty->getSalesRepresentatives($user);
425 $salerepobj = new User($this->db);
426 $salerepobj->fetch($salereparray[0]['id']);
427 if (!empty($salerepobj->signature)) {
428 $notetoshow = dol_concatdesc($notetoshow, $salerepobj->signature);
429 }
430 }
431 }
432 // Extrafields in note
433 $extranote = $this->getExtrafieldsInHtml($object, $outputlangs);
434 if (!empty($extranote)) {
435 $notetoshow = dol_concatdesc((string) $notetoshow, $extranote);
436 }
437 if (getDolGlobalString('MAIN_ADD_CREATOR_IN_NOTE') && $object->user_author_id > 0) {
438 $tmpuser = new User($this->db);
439 $tmpuser->fetch($object->user_author_id);
440
441
442 $creator_info = $langs->trans("CaseFollowedBy").' '.$tmpuser->getFullName($langs);
443 if ($tmpuser->email) {
444 $creator_info .= ', '.$langs->trans("EMail").': '.$tmpuser->email;
445 }
446 if ($tmpuser->office_phone) {
447 $creator_info .= ', '.$langs->trans("Phone").': '.$tmpuser->office_phone;
448 }
449
450 $notetoshow = dol_concatdesc((string) $notetoshow, $creator_info);
451 }
452
453 if ($notetoshow) {
454 $tab_top -= 2;
455
456 $substitutionarray = pdf_getSubstitutionArray($outputlangs, null, $object);
457 complete_substitutions_array($substitutionarray, $outputlangs, $object);
458 $notetoshow = make_substitutions($notetoshow, $substitutionarray, $outputlangs);
459 $notetoshow = convertBackOfficeMediasLinksToPublicLinks($notetoshow);
460
461 $pdf->SetFont('', '', $default_font_size - 1);
462 $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top - 1, dol_htmlentitiesbr($notetoshow), 0, 1);
463 $nexY = $pdf->GetY();
464 $height_note = $nexY - $tab_top;
465
466 // Rect takes a length in 3rd parameter
467 $pdf->SetDrawColor(192, 192, 192);
468 $pdf->RoundedRect($this->marge_gauche, $tab_top - 1, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $height_note + 2, $this->corner_radius, '1234', 'D');
469
470 $tab_top = $nexY + 6;
471 }
472
473 $iniY = $tab_top + 7;
474 $curY = $tab_top + 7;
475 $nexY = $tab_top + 7;
476
477 // Loop on each lines
478 for ($i = 0; $i < $nblines; $i++) {
479 $curY = $nexY;
480 $pdf->SetFont('', '', $default_font_size - 1); // Into loop to work with multipage
481 $pdf->SetTextColor(0, 0, 0);
482
483 // Define size of image if we need it
484 $imglinesize = array();
485 if (!empty($realpatharray[$i])) {
486 $imglinesize = pdf_getSizeForImage($realpatharray[$i]);
487 }
488
489 $pdf->setTopMargin($tab_top_newpage);
490 $pdf->setPageOrientation('', true, $heightforfooter + $heightforfreetext + $heightforsignature + $heightforinfotot); // The only function to edit the bottom margin of current page to set it.
491 $pageposbefore = $pdf->getPage();
492
493 $showpricebeforepagebreak = 1;
494 $posYAfterImage = 0;
495 $posYAfterDescription = 0;
496
497 // We start with Photo of product line
498 if (isset($imglinesize['width']) && isset($imglinesize['height']) && ($curY + $imglinesize['height']) > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforsignature + $heightforinfotot))) { // If photo too high, we moved completely on new page
499 $pdf->AddPage('', '', true);
500 if (!empty($tplidx)) {
501 $pdf->useTemplate($tplidx);
502 }
503 if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
504 $this->_pagehead($pdf, $object, 0, $outputlangs);
505 }
506 $pdf->setPage($pageposbefore + 1);
507
508 $curY = $tab_top_newpage;
509
510 // Allows data in the first page if description is long enough to break in multiples pages
511 if (getDolGlobalString('MAIN_PDF_DATA_ON_FIRST_PAGE')) {
512 $showpricebeforepagebreak = 1;
513 } else {
514 $showpricebeforepagebreak = 0;
515 }
516 }
517
518 if (isset($imglinesize['width']) && isset($imglinesize['height'])) {
519 $curX = $this->posxpicture - 1;
520 $pdf->Image($realpatharray[$i], $curX + (($this->posxtva - $this->posxpicture - $imglinesize['width']) / 2), $curY, $imglinesize['width'], $imglinesize['height'], '', '', '', 2, 300); // Use 300 dpi
521 // $pdf->Image does not increase value return by getY, so we save it manually
522 $posYAfterImage = $curY + $imglinesize['height'];
523 }
524
525 // Description of product line
526 $curX = $this->posxdesc - 1;
527
528 $pdf->startTransaction();
529 pdf_writelinedesc($pdf, $object, $i, $outputlangs, $this->posxpicture - $curX, 3, $curX, $curY, $hideref, $hidedesc);
530 $pageposafter = $pdf->getPage();
531 if ($pageposafter > $pageposbefore) { // There is a pagebreak
532 $pdf->rollbackTransaction(true);
533 $pageposafter = $pageposbefore;
534 //print $pageposafter.'-'.$pageposbefore;exit;
535 $pdf->setPageOrientation('', true, $heightforfooter); // The only function to edit the bottom margin of current page to set it.
536 pdf_writelinedesc($pdf, $object, $i, $outputlangs, $this->posxpicture - $curX, 3, $curX, $curY, $hideref, $hidedesc);
537
538 $pageposafter = $pdf->getPage();
539 $posyafter = $pdf->GetY();
540 //var_dump($posyafter); var_dump(($this->page_hauteur - ($heightforfooter+$heightforfreetext+$heightforinfotot))); exit;
541 if ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforsignature + $heightforinfotot))) { // There is no space left for total+free text
542 if ($i == ($nblines - 1)) { // No more lines, and no space left to show total, so we create a new page
543 $pdf->AddPage('', '', true);
544 if (!empty($tplidx)) {
545 $pdf->useTemplate($tplidx);
546 }
547 if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
548 $this->_pagehead($pdf, $object, 0, $outputlangs);
549 }
550 $pdf->setPage($pageposafter + 1);
551 }
552 } else {
553 // We found a page break
554
555 // Allows data in the first page if description is long enough to break in multiples pages
556 if (getDolGlobalString('MAIN_PDF_DATA_ON_FIRST_PAGE')) {
557 $showpricebeforepagebreak = 1;
558 } else {
559 $showpricebeforepagebreak = 0;
560 }
561 }
562 } else { // No pagebreak
563 $pdf->commitTransaction();
564 }
565 $posYAfterDescription = $pdf->GetY();
566
567 $nexY = $pdf->GetY();
568 $pageposafter = $pdf->getPage();
569
570 $pdf->setPage($pageposbefore);
571 $pdf->setTopMargin($this->marge_haute);
572 $pdf->setPageOrientation('', true, 0); // The only function to edit the bottom margin of current page to set it.
573
574 // We suppose that a too long description or photo were moved completely on next page
575 if ($pageposafter > $pageposbefore && empty($showpricebeforepagebreak)) {
576 $pdf->setPage($pageposafter);
577 $curY = $tab_top_newpage;
578 }
579
580 $pdf->SetFont('', '', $default_font_size - 1); // On repositionne la police par default
581
582 // VAT Rate
583 if (!getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT') && !getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_COLUMN')) {
584 $vat_rate = pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails);
585 $pdf->SetXY($this->posxtva - 5, $curY);
586 $pdf->MultiCell($this->posxup - $this->posxtva + 4, 3, $vat_rate, 0, 'R');
587 }
588
589 // Unit price before discount
590 $up_excl_tax = pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails);
591 $pdf->SetXY($this->posxup, $curY);
592 $pdf->MultiCell($this->posxqty - $this->posxup - 0.8, 3, $up_excl_tax, 0, 'R', false);
593
594 // Quantity
595 $qty = pdf_getlineqty($object, $i, $outputlangs, $hidedetails);
596 $pdf->SetXY($this->posxqty, $curY);
597 $pdf->MultiCell($this->posxunit - $this->posxqty - 0.8, 4, $qty, 0, 'R'); // Enough for 6 chars
598
599 // Unit
600 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
601 $unit = pdf_getlineunit($object, $i, $outputlangs, $hidedetails);
602 $pdf->SetXY($this->posxunit, $curY);
603 $pdf->MultiCell($this->posxdiscount - $this->posxunit - 0.8, 4, $unit, 0, 'L');
604 }
605
606 // Discount on line
607 $pdf->SetXY($this->posxdiscount, $curY);
608 if ($object->lines[$i]->remise_percent) {
609 $pdf->SetXY($this->posxdiscount - 2, $curY);
610 $remise_percent = pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails);
611 $pdf->MultiCell($this->postotalht - $this->posxdiscount + 2, 3, $remise_percent, 0, 'R');
612 }
613
614 // Total HT line
615 $total_excl_tax = pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails);
616 $pdf->SetXY($this->postotalht, $curY);
617 $pdf->MultiCell($this->page_largeur - $this->marge_droite - $this->postotalht, 3, $total_excl_tax, 0, 'R', false);
618
619 // // Collect total by value of vat rate into $this->tva["taux"]=total_tva
620 if (isModEnabled("multicurrency") && $object->multicurrency_tx != 1) {
621 $tvaligne = $object->lines[$i]->multicurrency_total_tva;
622 } else {
623 $tvaligne = $object->lines[$i]->total_tva;
624 }
625
626 $localtax1ligne = $object->lines[$i]->total_localtax1;
627 $localtax2ligne = $object->lines[$i]->total_localtax2;
628 $localtax1_rate = $object->lines[$i]->localtax1_tx;
629 $localtax2_rate = $object->lines[$i]->localtax2_tx;
630 $localtax1_type = $object->lines[$i]->localtax1_type;
631 $localtax2_type = $object->lines[$i]->localtax2_type;
632
633 // TODO remise_percent is an obsolete field for object parent
634 /*if ($object->remise_percent) {
635 $tvaligne -= ($tvaligne * $object->remise_percent) / 100;
636 }
637 if ($object->remise_percent) {
638 $localtax1ligne -= ($localtax1ligne * $object->remise_percent) / 100;
639 }
640 if ($object->remise_percent) {
641 $localtax2ligne -= ($localtax2ligne * $object->remise_percent) / 100;
642 }*/
643
644 $vatrate = (string) $object->lines[$i]->tva_tx;
645
646 // Retrieve type from database for backward compatibility with old records
647 if ((!isset($localtax1_type) || $localtax1_type == '' || !isset($localtax2_type) || $localtax2_type == '') // if tax type not defined
648 && (!empty($localtax1_rate) || !empty($localtax2_rate))) { // and there is local tax
649 $localtaxtmp_array = getLocalTaxesFromRate($vatrate, 0, $object->thirdparty, $mysoc);
650 $localtax1_type = isset($localtaxtmp_array[0]) ? $localtaxtmp_array[0] : '';
651 $localtax2_type = isset($localtaxtmp_array[2]) ? $localtaxtmp_array[2] : '';
652 }
653
654 // retrieve global local tax
655 if ($localtax1_type && $localtax1ligne != 0) {
656 if (empty($this->localtax1[$localtax1_type][$localtax1_rate])) {
657 $this->localtax1[$localtax1_type][$localtax1_rate] = $localtax1ligne;
658 } else {
659 $this->localtax1[$localtax1_type][$localtax1_rate] += $localtax1ligne;
660 }
661 }
662 if ($localtax2_type && $localtax2ligne != 0) {
663 if (empty($this->localtax2[$localtax2_type][$localtax2_rate])) {
664 $this->localtax2[$localtax2_type][$localtax2_rate] = $localtax2ligne;
665 } else {
666 $this->localtax2[$localtax2_type][$localtax2_rate] += $localtax2ligne;
667 }
668 }
669
670 if (($object->lines[$i]->info_bits & 0x01) == 0x01) {
671 $vatrate .= '*';
672 }
673
674 // Fill $this->tva and $this->tva_array
675 if (!isset($this->tva[$vatrate])) {
676 $this->tva[$vatrate] = 0;
677 }
678 $this->tva[$vatrate] += $tvaligne;
679 $vatcode = $object->lines[$i]->vat_src_code;
680 if (empty($this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'])) {
681 $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'] = 0;
682 }
683 $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')] = array('vatrate' => $vatrate, 'vatcode' => $vatcode, 'amount' => $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'] + $tvaligne);
684
685 if ($posYAfterImage > $posYAfterDescription) {
686 $nexY = $posYAfterImage;
687 }
688
689 // Add line
690 if (getDolGlobalString('MAIN_PDF_DASH_BETWEEN_LINES') && $i < ($nblines - 1)) {
691 $pdf->setPage($pageposafter);
692 $pdf->SetLineStyle(array('dash' => '1,1', 'color' => array(80, 80, 80)));
693 //$pdf->SetDrawColor(190,190,200);
694 $pdf->line($this->marge_gauche, $nexY + 1, $this->page_largeur - $this->marge_droite, $nexY + 1);
695 $pdf->SetLineStyle(array('dash' => 0));
696 }
697
698 $nexY += 2; // Add space between lines
699
700 // Detect if some page were added automatically and output _tableau for past pages
701 while ($pagenb < $pageposafter) {
702 $pdf->setPage($pagenb);
703 if ($pagenb == 1) {
704 $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1, $object->multicurrency_code);
705 } else {
706 $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code);
707 }
708 $this->_pagefoot($pdf, $object, $outputlangs, 1);
709 $pagenb++;
710 $pdf->setPage($pagenb);
711 $pdf->setPageOrientation('', true, 0); // The only function to edit the bottom margin of current page to set it.
712 if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
713 $this->_pagehead($pdf, $object, 0, $outputlangs);
714 }
715 if (!empty($tplidx)) {
716 $pdf->useTemplate($tplidx);
717 }
718 }
719 if (isset($object->lines[$i + 1]->pagebreak) && $object->lines[$i + 1]->pagebreak) { // @phan-suppress-current-line PhanUndeclaredProperty
720 if ($pagenb == 1) {
721 $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1, $object->multicurrency_code);
722 } else {
723 $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code);
724 }
725 $this->_pagefoot($pdf, $object, $outputlangs, 1);
726 // New page
727 $pdf->AddPage();
728 if (!empty($tplidx)) {
729 $pdf->useTemplate($tplidx);
730 }
731 $pagenb++;
732 if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
733 $this->_pagehead($pdf, $object, 0, $outputlangs);
734 }
735 }
736 }
737
738 // Show square
739 if ($pagenb == 1) {
740 $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforsignature - $heightforfooter, 0, $outputlangs, 0, 0, $object->multicurrency_code);
741 $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforsignature - $heightforfooter + 1;
742 } else {
743 $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforsignature - $heightforfooter, 0, $outputlangs, 1, 0, $object->multicurrency_code);
744 $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforsignature - $heightforfooter + 1;
745 }
746
747 // Affiche zone infos
748 $posy = $this->_tableau_info($pdf, $object, $bottomlasttab, $outputlangs);
749
750 // Affiche zone totaux
751 $posy = $this->_tableau_tot($pdf, $object, 0, $bottomlasttab, $outputlangs);
752
753 // Affiche zone versements
754 /*
755 if ($deja_regle || $amount_credit_notes_included || $amount_deposits_included)
756 {
757 $posy=$this->_tableau_versements($pdf, $object, $posy, $outputlangs);
758 }
759 */
760
761 // Customer signature area
762 if (!getDolGlobalString('PROPAL_DISABLE_SIGNATURE')) {
763 $posy = $this->_signature_area($pdf, $object, $posy, $outputlangs);
764
765 // Rewrite keywords to add a tag with the numero of page that contains the signature section
766 $keywords = $outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("PdfCommercialProposalTitle")." ".$outputlangs->convToOutputCharset($object->thirdparty->name);
767 $pdf->SetKeyWords($keywords." PAGESIGN=".$pdf->getPage());
768 }
769
770 // Pied de page
771 $this->_pagefoot($pdf, $object, $outputlangs);
772 if (method_exists($pdf, 'AliasNbPages')) {
773 $pdf->AliasNbPages(); // @phan-suppress-current-line PhanUndeclaredMethod
774 }
775
776 // Add terms to sale
777 $termsofsalefilename = getDolGlobalString('MAIN_INFO_PROPAL_TERMSOFSALE');
778 if (getDolGlobalInt('MAIN_PDF_ADD_TERMSOFSALE_PROPAL') && $termsofsalefilename) {
779 $termsofsale = $conf->propal->dir_output.'/'.$termsofsalefilename;
780 if (!empty($conf->propal->multidir_output[$object->entity ?? $conf->entity])) {
781 $termsofsale = $conf->propal->multidir_output[$object->entity ?? $conf->entity].'/'.$termsofsalefilename;
782 }
783 if (file_exists($termsofsale) && is_readable($termsofsale)) {
784 $pagecount = $pdf->setSourceFile($termsofsale);
785 for ($i = 1; $i <= $pagecount; $i++) {
786 $tplIdx = $pdf->importPage($i);
787 if ($tplIdx !== false) {
788 $s = $pdf->getTemplatesize($tplIdx);
789 $pdf->AddPage($s['h'] > $s['w'] ? 'P' : 'L');
790 $pdf->useTemplate($tplIdx);
791 } else {
792 setEventMessages(null, array($termsofsale.' cannot be added, probably protected PDF'), 'warnings');
793 }
794 }
795 }
796 }
797
798 //If propal merge product PDF is active
799 if (getDolGlobalString('PRODUIT_PDF_MERGE_PROPAL')) {
800 require_once DOL_DOCUMENT_ROOT.'/product/class/propalmergepdfproduct.class.php';
801
802 $already_merged = array();
803 foreach ($object->lines as $line) {
804 if (!empty($line->fk_product) && !(in_array($line->fk_product, $already_merged))) {
805 // Find the desired PDF
806 $filetomerge = new Propalmergepdfproduct($this->db);
807
808 if (getDolGlobalInt('MAIN_MULTILANGS')) {
809 $filetomerge->fetch_by_product($line->fk_product, $outputlangs->defaultlang);
810 } else {
811 $filetomerge->fetch_by_product($line->fk_product);
812 }
813
814 $already_merged[] = $line->fk_product;
815
816 $product = new Product($this->db);
817 $product->fetch($line->fk_product);
818
819 if ($product->entity != $conf->entity) {
820 $entity_product_file = $product->entity;
821 } else {
822 $entity_product_file = $conf->entity;
823 }
824
825 // If PDF is selected and file is not empty
826 if (count($filetomerge->lines) > 0) {
827 foreach ($filetomerge->lines as $linefile) {
828 $filetomerge_dir = null;
829 if (!empty($linefile->id) && !empty($linefile->file_name)) {
830 if (getDolGlobalInt('PRODUCT_USE_OLD_PATH_FOR_PHOTO')) {
831 if (isModEnabled("product")) {
832 $filetomerge_dir = $conf->product->multidir_output[$entity_product_file ?? $conf->entity].'/'.get_exdir($product->id, 2, 0, 0, $product, 'product').$product->id."/photos";
833 } elseif (isModEnabled("service")) {
834 $filetomerge_dir = $conf->service->multidir_output[$entity_product_file ?? $conf->entity].'/'.get_exdir($product->id, 2, 0, 0, $product, 'product').$product->id."/photos";
835 }
836 } else {
837 if (isModEnabled("product")) {
838 $filetomerge_dir = $conf->product->multidir_output[$entity_product_file ?? $conf->entity].'/'.get_exdir(0, 0, 0, 0, $product, 'product');
839 } elseif (isModEnabled("service")) {
840 $filetomerge_dir = $conf->service->multidir_output[$entity_product_file ?? $conf->entity].'/'.get_exdir(0, 0, 0, 0, $product, 'product');
841 }
842 }
843
844 dol_syslog(get_class($this).':: upload_dir='.$filetomerge_dir, $filetomerge_dir === null ? LOG_ERR : LOG_DEBUG);
845 if ($filetomerge_dir === null) {
846 // Skip loop
847 continue;
848 }
849
850 $infile = $filetomerge_dir.'/'.$linefile->file_name;
851 if (file_exists($infile) && is_readable($infile)) {
852 $pagecount = $pdf->setSourceFile($infile);
853 for ($i = 1; $i <= $pagecount; $i++) {
854 $tplIdx = $pdf->importPage($i);
855 if ($tplIdx !== false) {
856 $s = $pdf->getTemplatesize($tplIdx);
857 $pdf->AddPage($s['h'] > $s['w'] ? 'P' : 'L');
858 $pdf->useTemplate($tplIdx);
859 } else {
860 setEventMessages(null, array($infile.' cannot be added, probably protected PDF'), 'warnings');
861 }
862 }
863 }
864 }
865 }
866 }
867 }
868 }
869 }
870
871 $pdf->Close();
872
873 $pdf->Output($file, 'F');
874
875 //Add pdfgeneration hook
876 $hookmanager->initHooks(array('pdfgeneration'));
877 $parameters = array('file' => $file, 'object' => $object, 'outputlangs' => $outputlangs);
878 global $action;
879 $reshook = $hookmanager->executeHooks('afterPDFCreation', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
880 $this->warnings = $hookmanager->warnings;
881 if ($reshook < 0) {
882 $this->error = $hookmanager->error;
883 $this->errors = $hookmanager->errors;
884 dolChmod($file);
885 return -1;
886 }
887
888 dolChmod($file);
889
890 $this->result = array('fullpath' => $file);
891
892 return 1; // No error
893 } else {
894 $this->error = $langs->trans("ErrorCanNotCreateDir", $dir);
895 return 0;
896 }
897 } else {
898 $this->error = $langs->trans("ErrorConstantNotDefined", "PROP_OUTPUTDIR");
899 return 0;
900 }
901 }
902
903 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
904 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
914 protected function _tableau_versements(&$pdf, $object, $posy, $outputlangs)
915 {
916 // phpcs:enable
917 return 1;
918 }
919
920 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
921 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
931 protected function _tableau_info(&$pdf, $object, $posy, $outputlangs)
932 {
933 // phpcs:enable
934 global $conf, $mysoc;
935 $default_font_size = pdf_getPDFFontSize($outputlangs);
936
937 $pdf->SetFont('', '', $default_font_size - 1);
938
939 $diffsizetitle = getDolGlobalInt('PDF_DIFFSIZE_TITLE', 3);
940
941 // If France, show VAT mention if not applicable
942 if ($this->emetteur->country_code == 'FR' && empty($mysoc->tva_assuj)) {
943 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
944 $pdf->SetXY($this->marge_gauche, $posy);
945 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("VATIsNotUsedForInvoice"), 0, 'L', false);
946
947 $posy = $pdf->GetY() + 4;
948 }
949
950 $posxval = 52;
951 if (getDolGlobalString('MAIN_PDF_DELIVERY_DATE_TEXT')) {
952 $displaydate = "daytext";
953 } else {
954 $displaydate = "day";
955 }
956
957 // Show shipping date
958 if (!empty($object->delivery_date)) {
959 $outputlangs->load("sendings");
960 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
961 $pdf->SetXY($this->marge_gauche, $posy);
962 $titre = $outputlangs->transnoentities("DateDeliveryPlanned").':';
963 $pdf->MultiCell(80, 4, $titre, 0, 'L');
964 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
965 $pdf->SetXY($posxval, $posy);
966 $dlp = dol_print_date($object->delivery_date, $displaydate, false, $outputlangs, true);
967 $pdf->MultiCell(80, 4, $dlp, 0, 'L');
968
969 $posy = $pdf->GetY() + 1;
970 } elseif ($object->availability_code || $object->availability) { // Show availability conditions
971 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
972 $pdf->SetXY($this->marge_gauche, $posy);
973 $titre = $outputlangs->transnoentities("AvailabilityPeriod").':';
974 $pdf->MultiCell(80, 4, $titre, 0, 'L');
975 $pdf->SetTextColor(0, 0, 0);
976 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
977 $pdf->SetXY($posxval, $posy);
978 $lib_availability = ($outputlangs->transnoentities("AvailabilityType".$object->availability_code) != 'AvailabilityType'.$object->availability_code) ? $outputlangs->transnoentities("AvailabilityType".$object->availability_code) : $outputlangs->convToOutputCharset($object->availability);
979 $lib_availability = str_replace('\n', "\n", $lib_availability);
980 $pdf->MultiCell(80, 4, $lib_availability, 0, 'L');
981
982 $posy = $pdf->GetY() + 1;
983 }
984
985 // Show delivery mode
986 if (!getDolGlobalString('PROPOSAL_PDF_HIDE_DELIVERYMODE') && $object->shipping_method_id > 0) {
987 $outputlangs->load("sendings");
988
989 $shipping_method_id = $object->shipping_method_id;
990 if (getDolGlobalString('SOCIETE_ASK_FOR_SHIPPING_METHOD') && !empty($this->emetteur->shipping_method_id)) {
991 $shipping_method_id = $this->emetteur->shipping_method_id;
992 }
993 $shipping_method_code = dol_getIdFromCode($this->db, (string) $shipping_method_id, 'c_shipment_mode', 'rowid', 'code');
994 $shipping_method_label = dol_getIdFromCode($this->db, (string) $shipping_method_id, 'c_shipment_mode', 'rowid', 'libelle');
995
996 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
997 $pdf->SetXY($this->marge_gauche, $posy);
998 $titre = $outputlangs->transnoentities("SendingMethod").':';
999 $pdf->MultiCell(43, 4, $titre, 0, 'L');
1000
1001 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
1002 $pdf->SetXY($posxval, $posy);
1003 $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;
1004 $lib_condition_paiement = str_replace('\n', "\n", $lib_condition_paiement);
1005 $pdf->MultiCell(67, 4, $lib_condition_paiement, 0, 'L');
1006
1007 $posy = $pdf->GetY() + 1;
1008 }
1009
1010 // Show payments conditions
1011 if (!getDolGlobalString('PROPOSAL_PDF_HIDE_PAYMENTTERM') && $object->cond_reglement_code) {
1012 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
1013 $pdf->SetXY($this->marge_gauche, $posy);
1014 $titre = $outputlangs->transnoentities("PaymentConditions").':';
1015 $pdf->MultiCell(43, 4, $titre, 0, 'L');
1016
1017 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
1018 $pdf->SetXY($posxval, $posy);
1019 $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);
1020 $lib_condition_paiement = str_replace('\n', "\n", $lib_condition_paiement);
1021 if ($object->deposit_percent > 0) {
1022 $lib_condition_paiement = str_replace('__DEPOSIT_PERCENT__', $object->deposit_percent, $lib_condition_paiement);
1023 }
1024 $pdf->MultiCell(67, 4, $lib_condition_paiement, 0, 'L');
1025
1026 $posy = $pdf->GetY() + 3;
1027 }
1028
1029 if (!getDolGlobalString('PROPOSAL_PDF_HIDE_PAYMENTMODE')) {
1030 // Show payment mode
1031 if ($object->mode_reglement_code
1032 && $object->mode_reglement_code != 'CHQ'
1033 && $object->mode_reglement_code != 'VIR') {
1034 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
1035 $pdf->SetXY($this->marge_gauche, $posy);
1036 $titre = $outputlangs->transnoentities("PaymentMode").':';
1037 $pdf->MultiCell(80, 5, $titre, 0, 'L');
1038 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
1039 $pdf->SetXY($posxval, $posy);
1040 $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);
1041 $pdf->MultiCell(80, 5, $lib_mode_reg, 0, 'L');
1042
1043 $posy = $pdf->GetY() + 2;
1044 }
1045
1046 // Show payment mode CHQ
1047 if (empty($object->mode_reglement_code) || $object->mode_reglement_code == 'CHQ') {
1048 // Si mode reglement non force ou si force a CHQ
1049 if (getDolGlobalInt('FACTURE_CHQ_NUMBER')) {
1050 if (getDolGlobalInt('FACTURE_CHQ_NUMBER') > 0) {
1051 $account = new Account($this->db);
1052 $account->fetch(getDolGlobalInt('FACTURE_CHQ_NUMBER'));
1053
1054 $pdf->SetXY($this->marge_gauche, $posy);
1055 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
1056 $pdf->MultiCell(100, 3, $outputlangs->transnoentities('PaymentByChequeOrderedTo', $account->owner_name), 0, 'L', false);
1057 $posy = $pdf->GetY() + 1;
1058
1059 if (!getDolGlobalString('MAIN_PDF_HIDE_CHQ_ADDRESS')) {
1060 $pdf->SetXY($this->marge_gauche, $posy);
1061 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
1062 $pdf->MultiCell(100, 3, $outputlangs->convToOutputCharset($account->owner_address), 0, 'L', false);
1063 $posy = $pdf->GetY() + 2;
1064 }
1065 }
1066 if (getDolGlobalInt('FACTURE_CHQ_NUMBER') == -1) {
1067 $pdf->SetXY($this->marge_gauche, $posy);
1068 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
1069 $pdf->MultiCell(100, 3, $outputlangs->transnoentities('PaymentByChequeOrderedTo', $this->emetteur->name), 0, 'L', false);
1070 $posy = $pdf->GetY() + 1;
1071
1072 if (!getDolGlobalString('MAIN_PDF_HIDE_CHQ_ADDRESS')) {
1073 $pdf->SetXY($this->marge_gauche, $posy);
1074 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
1075 $pdf->MultiCell(100, 3, $outputlangs->convToOutputCharset($this->emetteur->getFullAddress()), 0, 'L', false);
1076 $posy = $pdf->GetY() + 2;
1077 }
1078 }
1079 }
1080 }
1081
1082 // If payment mode not forced or forced to VIR, show payment with BAN
1083 if (empty($object->mode_reglement_code) || $object->mode_reglement_code == 'VIR') {
1084 if (!empty($object->fk_account) || !empty($object->fk_bank) || getDolGlobalInt('FACTURE_RIB_NUMBER')) {
1085 $bankid = (empty($object->fk_account) ? getDolGlobalInt('FACTURE_RIB_NUMBER') : $object->fk_account);
1086 if (!empty($object->fk_bank) && $object->fk_bank > 0) {
1087 $bankid = $object->fk_bank; // For backward compatibility when object->fk_account is forced with object->fk_bank
1088 }
1089 $account = new Account($this->db);
1090 $account->fetch((int) $bankid);
1091
1092 $curx = $this->marge_gauche;
1093 $cury = $posy;
1094
1095 $posy = pdf_bank($pdf, $outputlangs, $curx, $cury, $account, 0, $default_font_size);
1096
1097 $posy += 2;
1098 }
1099 }
1100 }
1101
1102 return $posy;
1103 }
1104
1105 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1106 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1118 protected function _tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs, $outputlangsbis = null)
1119 {
1120 // phpcs:enable
1121 global $mysoc;
1122
1123 $default_font_size = pdf_getPDFFontSize($outputlangs);
1124
1125 $tab2_top = $posy;
1126 $tab2_hl = 4;
1127 $pdf->SetFont('', '', $default_font_size - 1);
1128
1129 // Total table
1130 $col1x = 120;
1131 $col2x = 170;
1132 if ($this->page_largeur < 210) { // To work with US executive format
1133 $col2x -= 20;
1134 }
1135 $largcol2 = ($this->page_largeur - $this->marge_droite - $col2x);
1136
1137 $useborder = 0;
1138 $index = 0;
1139
1140 // Get Total HT
1141 $total_ht = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1 ? $object->multicurrency_total_ht : $object->total_ht);
1142
1143 // Total discount
1144 $total_discount_on_lines = 0;
1145 $multicurrency_total_discount_on_lines = 0;
1146 foreach ($object->lines as $i => $line) {
1147 $resdiscount = pdfGetLineTotalDiscountAmount($object, $i, $outputlangs, 2);
1148 $multicurrency_resdiscount = pdfGetLineTotalDiscountAmount($object, $i, $outputlangs, 2, 1);
1149
1150 $total_discount_on_lines += (is_numeric($resdiscount) ? $resdiscount : 0);
1151 $multicurrency_total_discount_on_lines += (is_numeric($multicurrency_resdiscount) ? $multicurrency_resdiscount : 0);
1152 // If line was a negative line, we do not count the discount as a discount
1153 if ($line->total_ht < 0) {
1154 $total_discount_on_lines += -$line->total_ht;
1155 $multicurrency_total_discount_on_lines += -$line->multicurrency_total_ht;
1156 }
1157 }
1158
1159 if ($total_discount_on_lines > 0) {
1160 if ($this->showAmountBeforeDiscount) {
1161 // Show total NET before discount
1162 $pdf->SetFillColor(255, 255, 255);
1163 $pdf->SetXY($col1x, $tab2_top);
1164 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalHTBeforeDiscount") . (is_object($outputlangsbis) ? ' / ' . $outputlangsbis->transnoentities("TotalHTBeforeDiscount") : ''), 0, 'L', true);
1165 $pdf->SetXY($col2x, $tab2_top);
1166
1167 $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));
1168 $pdf->MultiCell($largcol2, $tab2_hl, price($total_before_discount_to_show, 0, $outputlangs), 0, 'R', true);
1169
1170 $index++;
1171 }
1172
1173 if ($this->showDiscountAmount) {
1174 $pdf->SetFillColor(255, 255, 255);
1175 $pdf->SetXY($col1x, $tab2_top + $tab2_hl);
1176 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalDiscount") . (is_object($outputlangsbis) ? ' / ' . $outputlangsbis->transnoentities("TotalDiscount") : ''), 0, 'L', true);
1177 $pdf->SetXY($col2x, $tab2_top + $tab2_hl);
1178
1179 $total_discount_to_show = ((isModEnabled("multicurrency") && $object->multicurrency_tx != 1) ? $multicurrency_total_discount_on_lines : $total_discount_on_lines);
1180 $pdf->MultiCell($largcol2, $tab2_hl, price($total_discount_to_show, 0, $outputlangs), 0, 'R', true);
1181
1182 $index++;
1183 }
1184 }
1185
1186 // Total HT
1187 $pdf->SetFillColor(255, 255, 255);
1188 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1189 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalHT"), 0, 'L', true);
1190
1191 $total_ht = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? $object->multicurrency_total_ht : $object->total_ht);
1192 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1193 $pdf->MultiCell($largcol2, $tab2_hl, price($total_ht + (!empty($object->remise) ? $object->remise : 0), 0, $outputlangs), 0, 'R', true);
1194
1195 // Show VAT by rates and total
1196 $pdf->SetFillColor(248, 248, 248);
1197
1198 $total_ttc = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1) ? $object->multicurrency_total_ttc : $object->total_ttc;
1199
1200 $this->atleastoneratenotnull = 0;
1201 if (!getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT')) {
1202 $tvaisnull = (!empty($this->tva) && count($this->tva) == 1 && isset($this->tva['0.000']) && is_float($this->tva['0.000']));
1203 if (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_IFNULL') && $tvaisnull) {
1204 // Nothing to do
1205 } else {
1206 //Local tax 1 before VAT
1207 foreach ($this->localtax1 as $localtax_type => $localtax_rate) {
1208 if (in_array((string) $localtax_type, array('1', '3', '5'))) {
1209 continue;
1210 }
1211
1212 foreach ($localtax_rate as $tvakey => $tvaval) {
1213 if ($tvakey != 0) { // On affiche pas taux 0
1214 //$this->atleastoneratenotnull++;
1215
1216 $index++;
1217 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1218
1219 $tvacompl = '';
1220 if (preg_match('/\*/', $tvakey)) {
1221 $tvakey = str_replace('*', '', $tvakey);
1222 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1223 }
1224 $totalvat = $outputlangs->transcountrynoentities("TotalLT1", $mysoc->country_code).' ';
1225
1226 if (getDolGlobalString('PDF_LOCALTAX1_LABEL_IS_CODE_OR_RATE') == 'nocodenorate') {
1227 $totalvat .= $tvacompl;
1228 } else {
1229 $totalvat .= vatrate((string) abs((float) $tvakey), true).$tvacompl;
1230 }
1231
1232 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1233
1234 $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval);
1235
1236 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1237 $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', true);
1238 }
1239 }
1240 }
1241
1242 //Local tax 2 before VAT
1243 foreach ($this->localtax2 as $localtax_type => $localtax_rate) {
1244 if (in_array((string) $localtax_type, array('1', '3', '5'))) {
1245 continue;
1246 }
1247
1248 foreach ($localtax_rate as $tvakey => $tvaval) {
1249 if ($tvakey != 0) { // On affiche pas taux 0
1250 //$this->atleastoneratenotnull++;
1251
1252 $index++;
1253 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1254
1255 $tvacompl = '';
1256 if (preg_match('/\*/', $tvakey)) {
1257 $tvakey = str_replace('*', '', $tvakey);
1258 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1259 }
1260 $totalvat = $outputlangs->transcountrynoentities("TotalLT2", $mysoc->country_code).' ';
1261
1262 if (getDolGlobalString('PDF_LOCALTAX2_LABEL_IS_CODE_OR_RATE') == 'nocodenorate') {
1263 $totalvat .= $tvacompl;
1264 } else {
1265 $totalvat .= vatrate((string) abs((float) $tvakey), true).$tvacompl;
1266 }
1267
1268 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1269
1270 $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval);
1271
1272 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1273 $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', true);
1274 }
1275 }
1276 }
1277
1278 // VAT
1279 foreach ($this->tva_array as $tvakey => $tvaval) {
1280 if ($tvakey != 0) { // On affiche pas taux 0
1281 $this->atleastoneratenotnull++;
1282
1283 $index++;
1284 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1285
1286 $tvacompl = '';
1287 if (preg_match('/\*/', $tvakey)) {
1288 $tvakey = str_replace('*', '', $tvakey);
1289 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1290 }
1291 $totalvat = $outputlangs->transcountrynoentities("TotalVAT", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalVAT", $mysoc->country_code) : '');
1292 $totalvat .= ' ';
1293 if (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'rateonly') {
1294 $totalvat .= vatrate((string) $tvaval['vatrate'], true).$tvacompl;
1295 } elseif (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'codeonly') {
1296 $totalvat .= $tvaval['vatcode'].$tvacompl;
1297 } elseif (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'nocodenorate') {
1298 $totalvat .= $tvacompl;
1299 } else {
1300 $totalvat .= vatrate((string) $tvaval['vatrate'], true).($tvaval['vatcode'] ? ' ('.$tvaval['vatcode'].')' : '').$tvacompl;
1301 }
1302 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1303
1304 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1305 $pdf->MultiCell($largcol2, $tab2_hl, price(price2num($tvaval['amount'], 'MT'), 0, $outputlangs), 0, 'R', true);
1306 }
1307 }
1308
1309 //Local tax 1 after VAT
1310 foreach ($this->localtax1 as $localtax_type => $localtax_rate) {
1311 if (in_array((string) $localtax_type, array('2', '4', '6'))) {
1312 continue;
1313 }
1314
1315 foreach ($localtax_rate as $tvakey => $tvaval) {
1316 if ($tvakey != 0) { // On affiche pas taux 0
1317 //$this->atleastoneratenotnull++;
1318
1319 $index++;
1320 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1321
1322 $tvacompl = '';
1323 if (preg_match('/\*/', $tvakey)) {
1324 $tvakey = str_replace('*', '', $tvakey);
1325 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1326 }
1327 $totalvat = $outputlangs->transcountrynoentities("TotalLT1", $mysoc->country_code).' ';
1328
1329 if (getDolGlobalString('PDF_LOCALTAX1_LABEL_IS_CODE_OR_RATE') == 'nocodenorate') {
1330 $totalvat .= $tvacompl;
1331 } else {
1332 $totalvat .= vatrate((string) abs((float) $tvakey), true).$tvacompl;
1333 }
1334
1335 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1336
1337 $total_localtax = ((isModEnabled("multicurrency") && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval);
1338
1339 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1340 $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', true);
1341 }
1342 }
1343 }
1344
1345 //Local tax 2 after VAT
1346 foreach ($this->localtax2 as $localtax_type => $localtax_rate) {
1347 if (in_array((string) $localtax_type, array('2', '4', '6'))) {
1348 continue;
1349 }
1350
1351 foreach ($localtax_rate as $tvakey => $tvaval) {
1352 // retrieve global local tax
1353 if ($tvakey != 0) { // On affiche pas taux 0
1354 //$this->atleastoneratenotnull++;
1355
1356 $index++;
1357 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1358
1359 $tvacompl = '';
1360 if (preg_match('/\*/', $tvakey)) {
1361 $tvakey = str_replace('*', '', $tvakey);
1362 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1363 }
1364 $totalvat = $outputlangs->transcountrynoentities("TotalLT2", $mysoc->country_code).' ';
1365
1366 if (getDolGlobalString('PDF_LOCALTAX2_LABEL_IS_CODE_OR_RATE') == 'nocodenorate') {
1367 $totalvat .= $tvacompl;
1368 } else {
1369 $totalvat .= vatrate((string) abs((float) $tvakey), true).$tvacompl;
1370 }
1371
1372 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1373
1374 $total_localtax = ((isModEnabled("multicurrency") && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval);
1375
1376 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1377 $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', true);
1378 }
1379 }
1380 }
1381 //}
1382
1383 // Total TTC
1384 $index++;
1385 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1386 $pdf->SetTextColor(0, 0, 60);
1387 $pdf->SetFillColor(224, 224, 224);
1388 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalTTC"), $useborder, 'L', true);
1389
1390 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1391 $pdf->MultiCell($largcol2, $tab2_hl, price($total_ttc, 0, $outputlangs), $useborder, 'R', true);
1392 }
1393 }
1394
1395 $pdf->SetTextColor(0, 0, 0);
1396
1397 $resteapayer = 0;
1398 /*
1399 $resteapayer = $object->total_ttc - $deja_regle;
1400 if (!empty($object->paye)) $resteapayer=0;
1401 */
1402
1403 if ($deja_regle > 0) {
1404 $index++;
1405
1406 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1407 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("AlreadyPaid"), 0, 'L', false);
1408
1409 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1410 $pdf->MultiCell($largcol2, $tab2_hl, price($deja_regle, 0, $outputlangs), 0, 'R', false);
1411
1412 /*
1413 if ($object->close_code == 'discount_vat') {
1414 $index++;
1415 $pdf->SetFillColor(255,255,255);
1416
1417 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1418 $pdf->MultiCell($col2x-$col1x, $tab2_hl, $outputlangs->transnoentities("EscompteOfferedShort"), $useborder, 'L', 1);
1419
1420 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1421 $pdf->MultiCell($largcol2, $tab2_hl, price($object->total_ttc - $deja_regle, 0, $outputlangs), $useborder, 'R', 1);
1422
1423 $resteapayer=0;
1424 }
1425 */
1426
1427 $index++;
1428 $pdf->SetTextColor(0, 0, 60);
1429 $pdf->SetFillColor(224, 224, 224);
1430 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1431 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("RemainderToPay"), $useborder, 'L', true);
1432
1433 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1434 $pdf->MultiCell($largcol2, $tab2_hl, price($resteapayer, 0, $outputlangs), $useborder, 'R', true);
1435
1436 $pdf->SetFont('', '', $default_font_size - 1);
1437 $pdf->SetTextColor(0, 0, 0);
1438 }
1439
1440 $index++;
1441 return ($tab2_top + ($tab2_hl * $index));
1442 }
1443
1444 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1458 protected function _tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop = 0, $hidebottom = 0, $currency = '')
1459 {
1460 global $conf;
1461
1462 // Force to disable hidetop and hidebottom
1463 $hidebottom = 0;
1464 if ($hidetop) {
1465 $hidetop = -1;
1466 }
1467
1468 $currency = !empty($currency) ? $currency : $conf->currency;
1469 $default_font_size = pdf_getPDFFontSize($outputlangs);
1470
1471 // Amount in (at tab_top - 1)
1472 $pdf->SetTextColor(0, 0, 0);
1473 $pdf->SetFont('', '', $default_font_size - 2);
1474
1475 if (empty($hidetop)) {
1476 $titre = $outputlangs->transnoentities("AmountInCurrency", $outputlangs->transnoentitiesnoconv("Currency".$currency));
1477 $pdf->SetXY($this->page_largeur - $this->marge_droite - ($pdf->GetStringWidth($titre) + 3), $tab_top - 4);
1478 $pdf->MultiCell(($pdf->GetStringWidth($titre) + 3), 2, $titre);
1479
1480 //$conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR='230,230,230';
1481 if (getDolGlobalString('MAIN_PDF_TITLE_BACKGROUND_COLOR')) {
1482 $pdf->RoundedRect($this->marge_gauche, $tab_top, $this->page_largeur - $this->marge_droite - $this->marge_gauche, 5, $this->corner_radius, '1001', 'F', array(), explode(',', getDolGlobalString('MAIN_PDF_TITLE_BACKGROUND_COLOR')));
1483 }
1484 }
1485
1486 $pdf->SetDrawColor(128, 128, 128);
1487 $pdf->SetFont('', '', $default_font_size - 1);
1488
1489 // Output Rect
1490 $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
1491
1492 if (empty($hidetop)) {
1493 $pdf->line($this->marge_gauche, $tab_top + 5, $this->page_largeur - $this->marge_droite, $tab_top + 5); // line takes a position y in 2nd parameter and 4th parameter
1494
1495 $pdf->SetXY($this->posxdesc - 1, $tab_top + 1);
1496 $pdf->MultiCell(108, 2, $outputlangs->transnoentities("Designation"), '', 'L');
1497 }
1498
1499 if (getDolGlobalString('MAIN_GENERATE_PROPOSALS_WITH_PICTURE')) {
1500 $pdf->line($this->posxpicture - 1, $tab_top, $this->posxpicture - 1, $tab_top + $tab_height);
1501 //if (empty($hidetop)) {
1502 //$pdf->SetXY($this->posxpicture-1, $tab_top+1);
1503 //$pdf->MultiCell($this->posxtva-$this->posxpicture-1,2, $outputlangs->transnoentities("Photo"),'','C');
1504 //}
1505 }
1506
1507 if (!getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT') && !getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_COLUMN')) {
1508 $pdf->line($this->posxtva - 1, $tab_top, $this->posxtva - 1, $tab_top + $tab_height);
1509 if (empty($hidetop)) {
1510 // Not do -3 and +3 instead of -1 -1 to have more space for text 'Sales tax'
1511 $pdf->SetXY($this->posxtva - 3, $tab_top + 1);
1512 $pdf->MultiCell($this->posxup - $this->posxtva + 3, 2, $outputlangs->transnoentities("VAT"), '', 'C');
1513 }
1514 }
1515
1516 $pdf->line($this->posxup - 1, $tab_top, $this->posxup - 1, $tab_top + $tab_height);
1517 if (empty($hidetop)) {
1518 $pdf->SetXY($this->posxup - 1, $tab_top + 1);
1519 $pdf->MultiCell($this->posxqty - $this->posxup - 1, 2, $outputlangs->transnoentities("PriceUHT"), '', 'C');
1520 }
1521
1522 $pdf->line($this->posxqty - 1, $tab_top, $this->posxqty - 1, $tab_top + $tab_height);
1523 if (empty($hidetop)) {
1524 $pdf->SetXY($this->posxqty - 1, $tab_top + 1);
1525 $pdf->MultiCell($this->posxunit - $this->posxqty - 1, 2, $outputlangs->transnoentities("Qty"), '', 'C');
1526 }
1527
1528 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
1529 $pdf->line($this->posxunit - 1, $tab_top, $this->posxunit - 1, $tab_top + $tab_height);
1530 if (empty($hidetop)) {
1531 $pdf->SetXY($this->posxunit - 1, $tab_top + 1);
1532 $pdf->MultiCell(
1533 $this->posxdiscount - $this->posxunit - 1,
1534 2,
1535 $outputlangs->transnoentities("Unit"),
1536 '',
1537 'C'
1538 );
1539 }
1540 }
1541
1542 $pdf->line($this->posxdiscount - 1, $tab_top, $this->posxdiscount - 1, $tab_top + $tab_height);
1543 if (empty($hidetop)) {
1544 if ($this->atleastonediscount) {
1545 $pdf->SetXY($this->posxdiscount - 1, $tab_top + 1);
1546 $pdf->MultiCell($this->postotalht - $this->posxdiscount + 1, 2, $outputlangs->transnoentities("ReductionShort"), '', 'C');
1547 }
1548 }
1549 if ($this->atleastonediscount) {
1550 $pdf->line($this->postotalht, $tab_top, $this->postotalht, $tab_top + $tab_height);
1551 }
1552 if (empty($hidetop)) {
1553 $pdf->SetXY($this->postotalht - 1, $tab_top + 1);
1554 $pdf->MultiCell(30, 2, $outputlangs->transnoentities("TotalHTShort"), '', 'C');
1555 }
1556 }
1557
1558 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1569 protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $outputlangsbis = null)
1570 {
1571 global $conf, $langs;
1572
1573 $ltrdirection = 'L';
1574 if ($outputlangs->trans("DIRECTION") == 'rtl') {
1575 $ltrdirection = 'R';
1576 }
1577
1578 // Load traductions files required by page
1579 $outputlangs->loadLangs(array("main", "propal", "companies", "bills"));
1580
1581 $default_font_size = pdf_getPDFFontSize($outputlangs);
1582
1583 pdf_pagehead($pdf, $outputlangs, $this->page_hauteur);
1584
1585 $pdf->SetTextColor(0, 0, 60);
1586 $pdf->SetFont('', 'B', $default_font_size + 3);
1587
1588 $w = 100;
1589
1590 $posy = $this->marge_haute;
1591 $posx = $this->page_largeur - $this->marge_droite - $w;
1592
1593 $pdf->SetXY($this->marge_gauche, $posy);
1594
1595 // Logo
1596 if (!getDolGlobalInt('PDF_DISABLE_MYCOMPANY_LOGO')) {
1597 if ($this->emetteur->logo) {
1598 $logodir = $conf->mycompany->dir_output;
1599 if (!empty($conf->mycompany->multidir_output[$object->entity ?? $conf->entity])) {
1600 $logodir = $conf->mycompany->multidir_output[$object->entity ?? $conf->entity];
1601 }
1602 if (!getDolGlobalInt('MAIN_PDF_USE_LARGE_LOGO')) {
1603 $logo = $logodir.'/logos/thumbs/'.$this->emetteur->logo_small;
1604 } else {
1605 $logo = $logodir.'/logos/'.$this->emetteur->logo;
1606 }
1607 if (is_readable($logo)) {
1608 $height = pdf_getHeightForLogo($logo);
1609 $pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto)
1610 } else {
1611 $pdf->SetTextColor(200, 0, 0);
1612 $pdf->SetFont('', 'B', $default_font_size - 2);
1613 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound", $logo), 0, 'L');
1614 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ErrorGoToGlobalSetup"), 0, 'L');
1615 }
1616 } else {
1617 $text = $this->emetteur->name;
1618 $pdf->MultiCell($w, 4, $outputlangs->convToOutputCharset($text), 0, $ltrdirection);
1619 }
1620 }
1621
1622 $pdf->SetFont('', 'B', $default_font_size + 3);
1623 $pdf->SetXY($posx, $posy);
1624 $pdf->SetTextColor(0, 0, 60);
1625 $title = $outputlangs->transnoentities("PdfCommercialProposalTitle");
1626 $title .= ' '.$outputlangs->convToOutputCharset($object->ref);
1627 if ($object->statut == $object::STATUS_DRAFT) {
1628 $pdf->SetTextColor(128, 0, 0);
1629 $title .= ' - '.$outputlangs->transnoentities("NotValidated");
1630 }
1631 $pdf->MultiCell($w, 4, $title, '', 'R');
1632
1633 $pdf->SetFont('', 'B', $default_font_size);
1634
1635 /*
1636 $posy += 5;
1637 $pdf->SetXY($posx, $posy);
1638 $pdf->SetTextColor(0, 0, 60);
1639 $pdf->MultiCell(100, 4, $outputlangs->transnoentities("Ref")." : ".$outputlangs->convToOutputCharset($object->ref), '', 'R');
1640 */
1641
1642 $posy += 3;
1643 $pdf->SetFont('', '', $default_font_size - 2);
1644
1645 $ref_customer = $object->ref_customer ?: $object->ref_client;
1646 if ($ref_customer) {
1647 $posy += 4;
1648 $pdf->SetXY($posx, $posy);
1649 $pdf->SetTextColor(0, 0, 60);
1650 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("RefCustomer")." : ".$outputlangs->convToOutputCharset($ref_customer), '', 'R');
1651 }
1652
1653 if (getDolGlobalString('PDF_SHOW_PROJECT_TITLE')) {
1654 $object->fetchProject();
1655 if (!empty($object->project->title)) {
1656 $posy += 3;
1657 $pdf->SetXY($posx, $posy);
1658 $pdf->SetTextColor(0, 0, 60);
1659 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("Project")." : ". $object->project->title, '', 'R');
1660 }
1661 }
1662
1663 if (getDolGlobalString('PDF_SHOW_PROJECT')) {
1664 $object->fetchProject();
1665 if (!empty($object->project->ref)) {
1666 $outputlangs->load("projects");
1667 $posy += 3;
1668 $pdf->SetXY($posx, $posy);
1669 $pdf->SetTextColor(0, 0, 60);
1670 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("RefProject")." : ". $object->project->ref, '', 'R');
1671 }
1672 }
1673
1674 if (getDolGlobalString('MAIN_PDF_DATE_TEXT')) {
1675 $displaydate = "daytext";
1676 } else {
1677 $displaydate = "day";
1678 }
1679
1680 //$posy += 4;
1681 $posy = $pdf->getY();
1682 $pdf->SetXY($posx, $posy);
1683 $pdf->SetTextColor(0, 0, 60);
1684 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("DatePropal")." : ".dol_print_date($object->date, $displaydate, false, $outputlangs, true), '', 'R');
1685
1686 $posy += 4;
1687 $pdf->SetXY($posx, $posy);
1688 $pdf->SetTextColor(0, 0, 60);
1689 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("DateEndPropal")." : ".dol_print_date($object->fin_validite, $displaydate, false, $outputlangs, true), '', 'R');
1690
1691 if (!getDolGlobalString('MAIN_PDF_HIDE_CUSTOMER_CODE') && $object->thirdparty->code_client) {
1692 $posy += 4;
1693 $pdf->SetXY($posx, $posy);
1694 $pdf->SetTextColor(0, 0, 60);
1695 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("CustomerCode")." : ".$outputlangs->transnoentities((string) $object->thirdparty->code_client), '', 'R');
1696 }
1697
1698 if (!getDolGlobalString('MAIN_PDF_HIDE_CUSTOMER_ACCOUNTING_CODE') && $object->thirdparty->code_compta_client) {
1699 $posy += 4;
1700 $pdf->SetXY($posx, $posy);
1701 $pdf->SetTextColor(0, 0, 60);
1702 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("CustomerAccountancyCode")." : ".$outputlangs->transnoentities((string) $object->thirdparty->code_compta_client), '', 'R');
1703 }
1704
1705 // Get contact
1706 if (getDolGlobalString('DOC_SHOW_FIRST_SALES_REP')) {
1707 $arrayidcontact = $object->getIdContact('internal', 'SALESREPFOLL');
1708 if (count($arrayidcontact) > 0) {
1709 $usertmp = new User($this->db);
1710 $usertmp->fetch($arrayidcontact[0]);
1711 $posy += 4;
1712 $pdf->SetXY($posx, $posy);
1713 $pdf->SetTextColor(0, 0, 60);
1714 $pdf->MultiCell($w, 3, $outputlangs->trans("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R');
1715 }
1716 }
1717
1718 $posy += 2;
1719
1720 $top_shift = 0;
1721 // Show list of linked objects
1722 $current_y = $pdf->getY();
1723 $posy = pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, $w, 3, 'R', $default_font_size);
1724 if ($current_y < $pdf->getY()) {
1725 $top_shift = $pdf->getY() - $current_y;
1726 }
1727
1728 if ($showaddress) {
1729 // Sender properties
1730 $carac_emetteur = '';
1731 // Add internal contact of object if defined
1732 $arrayidcontact = $object->getIdContact('internal', 'SALESREPFOLL');
1733 if (count($arrayidcontact) > 0) {
1734 $object->fetch_user($arrayidcontact[0]);
1735 $labelbeforecontactname = ($outputlangs->transnoentities("FromContactName") != 'FromContactName' ? $outputlangs->transnoentities("FromContactName") : $outputlangs->transnoentities("Name"));
1736 $carac_emetteur .= $labelbeforecontactname." ".$outputlangs->convToOutputCharset($object->user->getFullName($outputlangs));
1737 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') || getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ' (' : '';
1738 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') && !empty($object->user->office_phone)) ? $object->user->office_phone : '';
1739 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') && getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ', ' : '';
1740 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT') && !empty($object->user->email)) ? $object->user->email : '';
1741 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') || getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ')' : '';
1742 $carac_emetteur .= "\n";
1743 }
1744
1745 $carac_emetteur .= pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, '', 0, 'source', $object);
1746
1747 // Show sender
1748 $posy = 42 + $top_shift;
1749 $posx = $this->marge_gauche;
1750 if (getDolGlobalString('MAIN_INVERT_SENDER_RECIPIENT')) {
1751 $posx = $this->page_largeur - $this->marge_droite - 80;
1752 }
1753 $hautcadre = 40;
1754
1755 // Show sender frame
1756 if (!getDolGlobalString('MAIN_PDF_NO_SENDER_FRAME')) {
1757 $pdf->SetTextColor(0, 0, 0);
1758 $pdf->SetFont('', '', $default_font_size - 2);
1759 $pdf->SetXY($posx, $posy - 5);
1760 $pdf->MultiCell(80, 5, $outputlangs->transnoentities("BillFrom"), 0, $ltrdirection);
1761 $pdf->SetXY($posx, $posy);
1762 $pdf->SetFillColor(230, 230, 230);
1763 $pdf->RoundedRect($posx, $posy, 82, $hautcadre, $this->corner_radius, '1234', 'F');
1764 $pdf->SetTextColor(0, 0, 60);
1765 }
1766
1767 // Show company name
1768 if (!getDolGlobalString('MAIN_PDF_HIDE_SENDER_NAME')) {
1769 $pdf->SetXY($posx + 2, $posy + 3);
1770 $pdf->SetFont('', 'B', $default_font_size);
1771 $pdf->MultiCell(80, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, $ltrdirection);
1772 $posy = $pdf->getY();
1773 }
1774
1775 // Show sender information
1776 $pdf->SetXY($posx + 2, $posy);
1777 $pdf->SetFont('', '', $default_font_size - 1);
1778 $pdf->MultiCell(80, 4, $carac_emetteur, 0, $ltrdirection);
1779
1780
1781 // If CUSTOMER contact defined, we use it
1782 $usecontact = false;
1783 $arrayidcontact = $object->getIdContact('external', 'CUSTOMER');
1784 if (count($arrayidcontact) > 0) {
1785 $usecontact = true;
1786 $result = $object->fetch_contact($arrayidcontact[0]);
1787 }
1788
1789 // Recipient name
1790 if ($usecontact && ($object->contact->socid != $object->thirdparty->id && (!isset($conf->global->MAIN_USE_COMPANY_NAME_OF_CONTACT) || getDolGlobalString('MAIN_USE_COMPANY_NAME_OF_CONTACT')))) {
1791 $thirdparty = $object->contact;
1792 } else {
1793 $thirdparty = $object->thirdparty;
1794 }
1795
1796 $carac_client_name = pdfBuildThirdpartyName($thirdparty, $outputlangs);
1797
1798 $mode = 'target';
1799 $carac_client = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, ($usecontact ? $object->contact : ''), ($usecontact ? 1 : 0), $mode, $object);
1800
1801 // Show recipient
1802 $widthrecbox = 100;
1803 if ($this->page_largeur < 210) {
1804 $widthrecbox = 84; // To work with US executive format
1805 }
1806 $posy = 42 + $top_shift;
1807 $posx = $this->page_largeur - $this->marge_droite - $widthrecbox;
1808 if (getDolGlobalString('MAIN_INVERT_SENDER_RECIPIENT')) {
1809 $posx = $this->marge_gauche;
1810 }
1811
1812 // Show recipient frame
1813 if (!getDolGlobalString('MAIN_PDF_NO_RECIPENT_FRAME')) {
1814 $pdf->SetTextColor(0, 0, 0);
1815 $pdf->SetFont('', '', $default_font_size - 2);
1816 $pdf->SetXY($posx + 2, $posy - 5);
1817 $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillTo"), 0, $ltrdirection);
1818 $pdf->RoundedRect($posx, $posy, $widthrecbox, $hautcadre, $this->corner_radius, '1234', 'D');
1819 }
1820
1821 // Show recipient name
1822 $pdf->SetXY($posx + 2, $posy + 3);
1823 $pdf->SetFont('', 'B', $default_font_size);
1824 // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
1825 $pdf->MultiCell($widthrecbox, 4, $carac_client_name, 0, $ltrdirection);
1826
1827 $posy = $pdf->getY();
1828
1829 // Show recipient information
1830 $pdf->SetFont('', '', $default_font_size - 1);
1831 $pdf->SetXY($posx + 2, $posy);
1832 // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
1833 $pdf->MultiCell($widthrecbox, 4, $carac_client, 0, $ltrdirection);
1834 }
1835
1836 $pdf->SetTextColor(0, 0, 0);
1837
1838 return $top_shift;
1839 }
1840
1841 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1851 protected function _pagefoot(&$pdf, $object, $outputlangs, $hidefreetext = 0)
1852 {
1853 $showdetails = getDolGlobalInt('MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS', 0);
1854 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);
1855 }
1856
1857 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1858 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1868 protected function _signature_area(&$pdf, $object, $posy, $outputlangs)
1869 {
1870 // phpcs:enable
1871 $default_font_size = pdf_getPDFFontSize($outputlangs);
1872 $tab_top = $posy + 4;
1873 $tab_hl = 4;
1874
1875 $posx = 120;
1876 $largcol = ($this->page_largeur - $this->marge_droite - $posx);
1877
1878 // Total HT
1879 $pdf->SetFillColor(255, 255, 255);
1880 $pdf->SetXY($posx, $tab_top);
1881 $pdf->SetFont('', '', $default_font_size - 2);
1882 $pdf->MultiCell($largcol, $tab_hl, $outputlangs->transnoentities("ProposalCustomerSignature"), 0, 'L', true);
1883
1884 $pdf->SetXY($posx, $tab_top + $tab_hl + 3);
1885 //$pdf->MultiCell($largcol, $tab_hl * 3, '', 1, 'R');
1886 $pdf->RoundedRect($posx, $tab_top + $tab_hl + 3, $largcol, $tab_hl * 3, $this->corner_radius, '1234', 'D');
1887 if (getDolGlobalString('MAIN_PDF_PROPAL_USE_ELECTRONIC_SIGNING')) {
1888 // Can be retrieve with getSignatureAppearanceArray()
1889 // Can be also detected by putting the mouse over the area when using evince pdf reader
1890 $pdf->addEmptySignatureAppearance($posx, $tab_top + $tab_hl, $largcol, $tab_hl * 3);
1891 }
1892
1893 return ($tab_hl * 7);
1894 }
1895}
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
Class to manage bank accounts.
printRoundedRect($pdf, $x, $y, $w, $h, $r, $hidetop=0, $hidebottom=0, $style='D')
Print a rounded rectangle on the PDF.
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 Azur.
_tableau_info(&$pdf, $object, $posy, $outputlangs)
Show miscellaneous information (payment mode, payment term, ...)
__construct($db)
Constructor.
_pagehead(&$pdf, $object, $showaddress, $outputlangs, $outputlangsbis=null)
Show top header of page.
_signature_area(&$pdf, $object, $posy, $outputlangs)
Show area for the customer to sign.
_tableau_versements(&$pdf, $object, $posy, $outputlangs)
Show payments table.
_tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop=0, $hidebottom=0, $currency='')
Show table for lines.
write_file($object, $outputlangs, $srctemplatepath='', $hidedetails=0, $hidedesc=0, $hideref=0)
Function to build pdf onto disk.
_pagefoot(&$pdf, $object, $outputlangs, $hidefreetext=0)
Show footer of page.
_tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs, $outputlangsbis=null)
Show total to pay.
global $mysoc
print $script_file $mode $langs defaultlang(is_numeric($duration_value) ? " delay=". $duration_value :"").(is_numeric($duration_value2) ? " after cd cd cd description as description
Only used if Module[ID]Desc translation string is not found.
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!function_exists( 'dolEscapeXML')) convertBackOfficeMediasLinksToPublicLinks($notetoshow)
Convert links to local wrapper to medias files into a string into a public external URL readable on i...
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.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
getCallerInfoString()
Get caller info as a string that can be appended to a log message.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
dolChmod($filepath, $newmask='')
Change mod of a file.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
getLocalTaxesFromRate($vatrate, $local, $buyer, $seller, $firstparamisid=0)
Get type and rate of localtaxes for a particular vat rate/country of a thirdparty.
dol_concatdesc($text1, $text2, $forxml=false, $invert=false)
Concat 2 descriptions with a new line between them (second operand after first one with appropriate n...
complete_substitutions_array(&$substitutionarray, $outputlangs, $object=null, $parameters=null, $callfunc="completesubstitutionarray")
Complete the $substitutionarray with more entries coming from external module that had set the "subst...
make_substitutions($text, $substitutionarray, $outputlangs=null, $converttextinhtmlifnecessary=0)
Make substitution into a text string, replacing keys with vals from $substitutionarray (oldval=>newva...
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
dol_htmlentitiesbr($stringtoencode, $nl2brmode=0, $pagecodefrom='UTF-8', $removelasteolbr=1)
This function is called to encode a string into a HTML string but differs from htmlentities because a...
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
get_exdir($num, $level, $alpha, $withoutslash, $object, $modulepart='')
Return a path to have a the directory according to object where files are stored.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
print $langs trans("Show") . '< td style="' . $timeColor . '" align="center"> s</td > badge status0 badge status4 badge status3 Error badge status8< td align="center">< span class="badge ' . $badge . '"></span ></td >< td align="center">< a href="#" class="button button-small" onclick="openLogModal(this)" data-req="' . dol_escape_htmltag($reqSafe) . '" data-res="' . dol_escape_htmltag($resSafe) . '" data-err="' . dol_escape_htmltag($errSafe) . '">< span class="fa fa-search-plus"></span ></a ></td ></tr >< tr >< td colspan="' . $colspan . '" class="opacitymedium"></td ></tr ></table ></div ></form > logModal none logModal none s a JSON string
buildzip.php
pdf_getSizeForImage($realpath)
Return dimensions to use for images onto PDF checking that width and height are not higher than maxim...
Definition pdf.lib.php:3160
pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line total excluding tax.
Definition pdf.lib.php:2861
pdf_getFormat($outputlangs=null, $mode='setup')
Return array with format properties of default PDF format.
Definition pdf.lib.php:87
pdfGetLineTotalDiscountAmount($object, $i, $outputlangs, $hidedetails=0, $multicurrency=0)
Return line total amount discount.
Definition pdf.lib.php:3192
pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, $w, $h, $align, $default_font_size)
Show linked objects for PDF generation.
Definition pdf.lib.php:1808
pdf_getPDFFontSize($outputlangs)
Return font size to use for PDF generation.
Definition pdf.lib.php:294
pdf_bank($pdf, $outputlangs, $curx, $cury, $account, $onlynumber=0, $default_font_size=10)
Show bank information for PDF generation.
Definition pdf.lib.php:1239
pdf_writelinedesc($pdf, $object, $i, $outputlangs, $w, $h, $posx, $posy, $hideref=0, $hidedesc=0, $issupplierline=0, $align='J')
Output line description into PDF.
Definition pdf.lib.php:1846
pdf_getHeightForLogo($logo, $url=false)
Return height to use for Logo onto PDF.
Definition pdf.lib.php:317
pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line unit price excluding tax.
Definition pdf.lib.php:2464
pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails=0)
Return line vat rate.
Definition pdf.lib.php:2402
pdf_pagehead($pdf, $outputlangs, $page_height)
Show header of page for PDF generation.
Definition pdf.lib.php:747
pdfGetHeightForHtmlContent($pdf, $htmlcontent)
Function to try to calculate height of a HTML Content.
Definition pdf.lib.php:342
pdf_pagefoot($pdf, $outputlangs, $paramfreetext, $fromcompany, $marge_basse, $marge_gauche, $page_hauteur, $object, $showdetails=0, $hidefreetext=0, $page_largeur=0, $watermark='')
Show footer of page for PDF generation.
Definition pdf.lib.php:1421
pdf_getPDFFont($outputlangs)
Return font name to use for PDF generation.
Definition pdf.lib.php:273
pdf_build_address($outputlangs, $sourcecompany, $targetcompany='', $targetcontact='', $usecontact=0, $mode='source', $object=null)
Return a string with full address formatted for output on PDF documents.
Definition pdf.lib.php:438
pdf_getlineunit($object, $i, $outputlangs, $hidedetails=0)
Return line unit.
Definition pdf.lib.php:2709
pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails=0)
Return line remise percent.
Definition pdf.lib.php:2752
pdf_getlineqty($object, $i, $outputlangs, $hidedetails=0)
Return line quantity.
Definition pdf.lib.php:2549
pdf_getSubstitutionArray($outputlangs, $exclude=null, $object=null, $onlykey=0, $include=null)
Return array of possible substitutions for PDF content (without external module substitutions).
Definition pdf.lib.php:1135
pdf_getInstance($format='', $metric='mm', $pagetype='P')
Return a PDF instance object.
Definition pdf.lib.php:129
pdfBuildThirdpartyName($thirdparty, Translate $outputlangs, $includealias=0)
Returns the name of the thirdparty.
Definition pdf.lib.php:393
if(preg_match('/(crypted|dolcrypt):/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
'integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]',...
Definition repair.php:130
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:133