dolibarr 24.0.0-beta
pdf_zenith.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-2011 Regis Houssin <regis.houssin@inodbox.com>
4 * Copyright (C) 2007 Franky Van Liedekerke <franky.van.liedekerke@telenet.be>
5 * Copyright (C) 2010-2014 Juanjo Menent <jmenent@2byte.es>
6 * Copyright (C) 2015 Marcos García <marcosgdf@gmail.com>
7 * Copyright (C) 2017 Ferran Marcet <fmarcet@2byte.es>
8 * Copyright (C) 2018-2026 Frédéric France <frederic.france@free.fr>
9 * Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
10 * Copyright (C) 2024 Nick Fragoulis
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 3 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program. If not, see <https://www.gnu.org/licenses/>.
24 * or see https://www.gnu.org/
25 */
26
33require_once DOL_DOCUMENT_ROOT.'/core/modules/supplier_proposal/modules_supplier_proposal.php';
34require_once DOL_DOCUMENT_ROOT.'/supplier_proposal/class/supplier_proposal.class.php';
35require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
36require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
37require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
38require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
39
40
45{
49 public $db;
50
54 public $name;
55
59 public $description;
60
64 public $update_main_doc_field;
65
69 public $type;
70
75 public $version = 'dolibarr';
76
77
83 public function __construct($db)
84 {
85 global $conf, $langs, $mysoc;
86
87 // Load translation files required by the page
88 $langs->loadLangs(array("main", "bills"));
89
90 $this->db = $db;
91 $this->name = "zenith";
92 $this->description = $langs->trans('DocModelZenithDescription');
93 $this->update_main_doc_field = 1; // Save the name of generated file as the main doc when generating a doc with this template
94
95 // Page size for A4 format
96 $this->type = 'pdf';
97 $formatarray = pdf_getFormat();
98 $this->page_largeur = $formatarray['width'];
99 $this->page_hauteur = $formatarray['height'];
100 $this->format = array($this->page_largeur, $this->page_hauteur);
101 $this->marge_gauche = getDolGlobalInt('MAIN_PDF_MARGIN_LEFT', 10);
102 $this->marge_droite = getDolGlobalInt('MAIN_PDF_MARGIN_RIGHT', 10);
103 $this->marge_haute = getDolGlobalInt('MAIN_PDF_MARGIN_TOP', 10);
104 $this->marge_basse = getDolGlobalInt('MAIN_PDF_MARGIN_BOTTOM', 10);
105 $this->corner_radius = getDolGlobalInt('MAIN_PDF_FRAME_CORNER_RADIUS', 0);
106 $this->option_logo = 1; // Display logo
107 $this->option_tva = 1; // Manage the vat option FACTURE_TVAOPTION
108 $this->option_modereg = 1; // Display payment mode
109 $this->option_condreg = 1; // Display payment terms
110 $this->option_multilang = 1; //Available in several languages
111 $this->option_escompte = 0; // Displays if there has been a discount
112 $this->option_credit_note = 0; // Support credit notes
113 $this->option_freetext = 1; // Support add of a personalised text
114 $this->option_draft_watermark = 1; // Support add of a watermark on drafts
115
116 // Define position of columns
117 $this->posxdesc = $this->marge_gauche + 1; // For module retrocompatibility support during PDF transition: TODO remove this at the end
118
119 $this->tabTitleHeight = 5; // default height
120
121 $this->tva = array();
122 $this->tva_array = array();
123 $this->localtax1 = array();
124 $this->localtax2 = array();
125 $this->atleastoneratenotnull = 0;
126 $this->atleastonediscount = 0;
127
128 if ($mysoc === null) {
129 dol_syslog(get_class($this).'::__construct() Global $mysoc should not be null.'. getCallerInfoString(), LOG_ERR);
130 return;
131 }
132
133 // Get source company
134 $this->emetteur = $mysoc;
135 if (empty($this->emetteur->country_code)) {
136 $this->emetteur->country_code = substr($langs->defaultlang, -2); // By default, if was not defined
137 }
138 }
139
140
141 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
153 public function write_file($object, $outputlangs, $srctemplatepath = '', $hidedetails = 0, $hidedesc = 0, $hideref = 0)
154 {
155 // phpcs:enable
156 global $user, $langs, $conf, $hookmanager, $mysoc, $nblines;
157
158 if (!is_object($outputlangs)) {
159 $outputlangs = $langs;
160 }
161 // For backward compatibility with FPDF, force output charset to ISO, because FPDF expect text to be encoded in ISO
162 if (getDolGlobalString('MAIN_USE_FPDF')) {
163 $outputlangs->charset_output = 'ISO-8859-1';
164 }
165
166 // Load translation files required by the page
167 $outputlangs->loadLangs(array("main", "supplier_proposal", "companies", "bills", "dict", "products"));
168
169 global $outputlangsbis;
170 $outputlangsbis = null;
171 if (getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE') && $outputlangs->defaultlang != getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE')) {
172 $outputlangsbis = new Translate('', $conf);
173 $outputlangsbis->setDefaultLang(getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE'));
174 $outputlangsbis->loadLangs(array("main", "supplier_proposal", "companies", "bills", "dict", "products"));
175 }
176
177 $nblines = count($object->lines);
178
179 $hidetop = 0;
180 if (getDolGlobalString('MAIN_PDF_DISABLE_COL_HEAD_TITLE')) {
181 $hidetop = getDolGlobalString('MAIN_PDF_DISABLE_COL_HEAD_TITLE');
182 }
183
184 // Loop on each lines to detect if there is at least one image to show
185 $realpatharray = array();
186 if (getDolGlobalString('MAIN_GENERATE_SUPPLIER_PROPOSAL_WITH_PICTURE')) {
187 for ($i = 0; $i < $nblines; $i++) {
188 if (empty($object->lines[$i]->fk_product)) {
189 continue;
190 }
191
192 $objphoto = new Product($this->db);
193 $objphoto->fetch($object->lines[$i]->fk_product);
194
195 if (getDolGlobalInt('PRODUCT_USE_OLD_PATH_FOR_PHOTO')) {
196 $pdir = get_exdir($objphoto->id, 2, 0, 0, $objphoto, 'product').$object->lines[$i]->fk_product."/photos/";
197 $dir = $conf->product->dir_output.'/'.$pdir;
198 } else {
199 $pdir = get_exdir($objphoto->id, 0, 0, 0, $objphoto, 'product');
200 $dir = $conf->product->dir_output.'/'.$pdir;
201 }
202
203 $realpath = '';
204 foreach ($objphoto->liste_photos($dir, 1) as $key => $obj) {
205 if (!getDolGlobalInt('CAT_HIGH_QUALITY_IMAGES')) { // If CAT_HIGH_QUALITY_IMAGES not defined, we use thumb if defined and then original photo
206 if ($obj['photo_vignette']) {
207 $filename = $obj['photo_vignette'];
208 } else {
209 $filename = $obj['photo'];
210 }
211 } else {
212 $filename = $obj['photo'];
213 }
214 $realpath = $dir.$filename;
215 break;
216 }
217
218 if ($realpath) {
219 $realpatharray[$i] = $realpath;
220 }
221 }
222 }
223 if (count($realpatharray) == 0) {
224 $this->posxpicture = $this->posxtva;
225 }
226
227 if ($conf->supplier_proposal->dir_output) {
228 $object->fetch_thirdparty();
229
230 $deja_regle = 0;
231 $amount_credit_notes_included = 0;
232 $amount_deposits_included = 0;
233 //$amount_credit_notes_included = $object->getSumCreditNotesUsed();
234 //$amount_deposits_included = $object->getSumDepositsUsed();
235
236 // Definition of $dir and $file
237 if ($object->specimen) {
238 $dir = $conf->supplier_proposal->dir_output;
239 $file = $dir."/SPECIMEN.pdf";
240 } else {
241 $objectref = dol_sanitizeFileName($object->ref);
242 $objectrefsupplier = dol_sanitizeFileName($object->ref_supplier);
243 $dir = $conf->supplier_proposal->dir_output.'/'.$objectref;
244 $file = $dir."/".$objectref.".pdf";
245 if (getDolGlobalString('SUPPLIER_REF_IN_NAME')) {
246 $file = $dir."/".$objectref.($objectrefsupplier ? "_".$objectrefsupplier : "").".pdf";
247 }
248 }
249
250 if (!file_exists($dir)) {
251 if (dol_mkdir($dir) < 0) {
252 $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
253 return 0;
254 }
255 }
256
257 if (file_exists($dir)) {
258 // Add pdfgeneration hook
259 if (!is_object($hookmanager)) {
260 include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
261 $hookmanager = new HookManager($this->db);
262 }
263 $hookmanager->initHooks(array('pdfgeneration'));
264 $parameters = array('file' => $file, 'object' => $object, 'outputlangs' => $outputlangs);
265 global $action;
266 $reshook = $hookmanager->executeHooks('beforePDFCreation', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
267
268 $nblines = count($object->lines);
269
270 $pdf = pdf_getInstance($this->format);
271 $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance
272 $heightforinfotot = 50; // Height reserved to output the info and total part
273 $heightforfreetext = getDolGlobalInt('MAIN_PDF_FREETEXT_HEIGHT', 5); // Height reserved to output the free text on last page
274 $heightforfooter = $this->marge_basse + 8; // Height reserved to output the footer (value include bottom margin)
275 if (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS')) {
276 $heightforfooter += 6;
277 }
278 $pdf->setAutoPageBreak(true, 0);
279
280 if (class_exists('TCPDF')) {
281 $pdf->setPrintHeader(false);
282 $pdf->setPrintFooter(false);
283 }
284 $pdf->SetFont(pdf_getPDFFont($outputlangs));
285 // Set path to the background PDF File
286 if (getDolGlobalString('MAIN_ADD_PDF_BACKGROUND')) {
287 $pagecount = $pdf->setSourceFile($conf->mycompany->dir_output.'/' . getDolGlobalString('MAIN_ADD_PDF_BACKGROUND'));
288 $tplidx = $pdf->importPage(1);
289 }
290
291 $pdf->Open();
292 $pagenb = 0;
293 $pdf->SetDrawColor(128, 128, 128);
294
295 $pdf->SetTitle($outputlangs->convToOutputCharset($object->ref));
296 $pdf->SetSubject($outputlangs->transnoentities("SupplierProposal"));
297 $pdf->SetCreator("Dolibarr ".DOL_VERSION);
298 $pdf->SetAuthor($outputlangs->convToOutputCharset($user->getAnonymisableFullName($outputlangs)));
299 $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("SupplierProposal")." ".$outputlangs->convToOutputCharset($object->thirdparty->name));
300 if (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) {
301 $pdf->SetCompression(false);
302 }
303
304 // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
305 $pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite); // Left, Top, Right
306
307 // Does we have at least one line with discount $this->atleastonediscount
308 foreach ($object->lines as $line) {
309 if ($line->remise_percent) {
310 $this->atleastonediscount = true;
311 break;
312 }
313 }
314
315 // New page
316 $pdf->AddPage();
317 if (!empty($tplidx)) {
318 $pdf->useTemplate($tplidx);
319 }
320 $pagenb++;
321 $top_shift = $this->_pagehead($pdf, $object, 1, $outputlangs);
322 $pdf->SetFont('', '', $default_font_size - 1);
323 $pdf->MultiCell(0, 3, ''); // Set interline to 3
324 $pdf->SetTextColor(0, 0, 0);
325
326 $tab_top = 90 + $top_shift;
327 $tab_top_newpage = (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD') ? 42 + $top_shift : 10);
328
329 $tab_height = $this->page_hauteur - $tab_top - $heightforfooter - $heightforfreetext;
330
331 // Incoterm
332 if (isModEnabled('incoterm')) {
333 $desc_incoterms = $object->getIncotermsForPDF();
334 if ($desc_incoterms) {
335 $tab_top -= 2;
336
337 $pdf->SetFont('', '', $default_font_size - 1);
338 $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top - 1, dol_htmlentitiesbr($desc_incoterms), 0, 1);
339 $nexY = $pdf->GetY();
340 $height_incoterms = $nexY - $tab_top;
341
342 // Rect takes a length in 3rd parameter
343 $pdf->SetDrawColor(192, 192, 192);
344 $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');
345
346 $tab_top = $nexY + 6;
347 }
348 }
349
350 // Affiche notes
351 $notetoshow = empty($object->note_public) ? '' : $object->note_public;
352
353 // Extrafields in note
354 $extranote = $this->getExtrafieldsInHtml($object, $outputlangs);
355 if (!empty($extranote)) {
356 $notetoshow = dol_concatdesc($notetoshow, $extranote);
357 }
358
359 $pagenb = $pdf->getPage();
360 if ($notetoshow) {
361 $tab_width = $this->page_largeur - $this->marge_gauche - $this->marge_droite;
362 $pageposbeforenote = $pagenb;
363
364 $substitutionarray = pdf_getSubstitutionArray($outputlangs, null, $object);
365 complete_substitutions_array($substitutionarray, $outputlangs, $object);
366 $notetoshow = make_substitutions($notetoshow, $substitutionarray, $outputlangs);
367 $notetoshow = convertBackOfficeMediasLinksToPublicLinks($notetoshow);
368
369 $tab_top -= 2;
370
371 $pdf->startTransaction();
372
373 $pdf->SetFont('', '', $default_font_size - 1);
374 $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top, dol_htmlentitiesbr($notetoshow), 0, 1);
375 // Description
376 $pageposafternote = $pdf->getPage();
377 $posyafter = $pdf->GetY();
378
379 if ($pageposafternote > $pageposbeforenote) {
380 $pdf->rollbackTransaction(true);
381
382 // prepar pages to receive notes
383 while ($pagenb < $pageposafternote) {
384 $pdf->AddPage();
385 $pagenb++;
386 if (!empty($tplidx)) {
387 $pdf->useTemplate($tplidx);
388 }
389 if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
390 $this->_pagehead($pdf, $object, 0, $outputlangs);
391 }
392 // $this->_pagefoot($pdf,$object,$outputlangs,1);
393 $pdf->setTopMargin($tab_top_newpage);
394 // The only function to edit the bottom margin of current page to set it.
395 $pdf->setPageOrientation('', true, $heightforfooter + $heightforfreetext);
396 }
397
398 // back to start
399 $pdf->setPage($pageposbeforenote);
400 $pdf->setPageOrientation('', true, $heightforfooter + $heightforfreetext);
401 $pdf->SetFont('', '', $default_font_size - 1);
402 $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top, dol_htmlentitiesbr($notetoshow), 0, 1);
403 $pageposafternote = $pdf->getPage();
404
405 $posyafter = $pdf->GetY();
406
407 if ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + 20))) { // There is no space left for total+free text
408 $pdf->AddPage('', '', true);
409 $pagenb++;
410 $pageposafternote++;
411 $pdf->setPage($pageposafternote);
412 $pdf->setTopMargin($tab_top_newpage);
413 // The only function to edit the bottom margin of current page to set it.
414 $pdf->setPageOrientation('', true, $heightforfooter + $heightforfreetext);
415 //$posyafter = $tab_top_newpage;
416 }
417
418
419 // apply note frame to previous pages
420 $i = $pageposbeforenote;
421 while ($i < $pageposafternote) {
422 $pdf->setPage($i);
423
424
425 $pdf->SetDrawColor(128, 128, 128);
426 // Draw note frame
427 if ($i > $pageposbeforenote) {
428 $height_note = $this->page_hauteur - ($tab_top_newpage + $heightforfooter);
429 $pdf->RoundedRect($this->marge_gauche, $tab_top_newpage - 1, $tab_width, $height_note + 2, $this->corner_radius, '1234', 'D');
430 } else {
431 $height_note = $this->page_hauteur - ($tab_top + $heightforfooter);
432 $pdf->RoundedRect($this->marge_gauche, $tab_top - 1, $tab_width, $height_note + 2, $this->corner_radius, '1234', 'D');
433 }
434
435 // Add footer
436 $pdf->setPageOrientation('', true, 0); // The only function to edit the bottom margin of current page to set it.
437 $this->_pagefoot($pdf, $object, $outputlangs, 1);
438
439 $i++;
440 }
441
442 // apply note frame to last page
443 $pdf->setPage($pageposafternote);
444 if (!empty($tplidx)) {
445 $pdf->useTemplate($tplidx);
446 }
447 if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
448 $this->_pagehead($pdf, $object, 0, $outputlangs);
449 }
450 $height_note = $posyafter - $tab_top_newpage;
451 $pdf->RoundedRect($this->marge_gauche, $tab_top_newpage - 1, $tab_width, $height_note + 2, $this->corner_radius, '1234', 'D');
452 } else {
453 // No pagebreak
454 $pdf->commitTransaction();
455 $posyafter = $pdf->GetY();
456 $height_note = $posyafter - $tab_top;
457 $pdf->RoundedRect($this->marge_gauche, $tab_top - 1, $tab_width, $height_note + 2, $this->corner_radius, '1234', 'D');
458
459
460 if ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + 20))) {
461 // not enough space, need to add page
462 $pdf->AddPage('', '', true);
463 $pagenb++;
464 $pageposafternote++;
465 $pdf->setPage($pageposafternote);
466 if (!empty($tplidx)) {
467 $pdf->useTemplate($tplidx);
468 }
469 if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
470 $this->_pagehead($pdf, $object, 0, $outputlangs);
471 }
472
473 $posyafter = $tab_top_newpage;
474 }
475 }
476
477 $tab_height -= $height_note;
478 $tab_top = $posyafter + 6;
479 } else {
480 $height_note = 0;
481 }
482
483 // Use new auto column system
484 $this->prepareArrayColumnField($object, $outputlangs, $hidedetails, $hidedesc, $hideref);
485
486 $nexY = $tab_top + $this->tabTitleHeight;
487
488 $pageposbeforeprintlines = $pdf->getPage();
489 $pagenb = $pageposbeforeprintlines;
490 $pdf_sub_options = [
491 'titleshowuponpdf' => 1,
492 'titleshowtotalexludingvatonpdf' => 1,
493 ];
494
495 // Loop on each lines
496 for ($i = 0; $i < $nblines; $i++) {
497 $sub_options = $object->lines[$i]->extraparams["subtotal"] ?? array();
498
499 if ($object->lines[$i]->special_code == SUBTOTALS_SPECIAL_CODE) {
500 $level = $object->lines[$i]->qty;
501 if ($sub_options) {
502 if (isset($sub_options['titleshowuponpdf'])) {
503 $pdf_sub_options['titleshowuponpdf'] = isset($pdf_sub_options['titleshowuponpdf']) && $pdf_sub_options['titleshowuponpdf'] < $level ? $pdf_sub_options['titleshowuponpdf'] : $level;
504 } elseif (isset($pdf_sub_options['titleshowuponpdf']) && abs($level) <= $pdf_sub_options['titleshowuponpdf']) {
505 unset($pdf_sub_options['titleshowuponpdf']);
506 }
507 if (isset($sub_options['titleshowtotalexludingvatonpdf'])) {
508 $pdf_sub_options['titleshowtotalexludingvatonpdf'] = isset($pdf_sub_options['titleshowtotalexludingvatonpdf']) && $pdf_sub_options['titleshowtotalexludingvatonpdf'] < $level ? $pdf_sub_options['titleshowtotalexludingvatonpdf'] : $level;
509 } elseif (isset($pdf_sub_options['titleshowtotalexludingvatonpdf']) && abs($level) <= $pdf_sub_options['titleshowtotalexludingvatonpdf']) {
510 unset($pdf_sub_options['titleshowtotalexludingvatonpdf']);
511 }
512 } else {
513 if (isset($pdf_sub_options['titleshowuponpdf']) && abs($level) <= $pdf_sub_options['titleshowuponpdf']) {
514 unset($pdf_sub_options['titleshowuponpdf']);
515 }
516 if (isset($pdf_sub_options['titleshowtotalexludingvatonpdf']) && abs($level) <= $pdf_sub_options['titleshowtotalexludingvatonpdf']) {
517 unset($pdf_sub_options['titleshowtotalexludingvatonpdf']);
518 }
519 }
520 }
521 $curY = $nexY;
522 $pdf->SetFont('', '', $default_font_size - 1); // Into loop to work with multipage
523 $pdf->SetTextColor(0, 0, 0);
524
525 // Define size of image if we need it
526 $imglinesize = array();
527 if (!empty($realpatharray[$i])) {
528 $imglinesize = pdf_getSizeForImage($realpatharray[$i]);
529 }
530
531 $pdf->setTopMargin($tab_top_newpage);
532 $pdf->setPageOrientation('', true, $heightforfooter + $heightforfreetext + $heightforinfotot); // The only function to edit the bottom margin of current page to set it.
533 $pageposbefore = $pdf->getPage();
534
535 $showpricebeforepagebreak = 1;
536 $posYAfterImage = 0;
537 $posYAfterDescription = 0;
538
539 // We start with Photo of product line
540 if ($this->getColumnStatus('photo')) {
541 // We start with Photo of product line
542 if (isset($imglinesize['width']) && isset($imglinesize['height']) && ($curY + $imglinesize['height']) > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforinfotot))) { // If photo too high, we moved completely on new page
543 $pdf->AddPage('', '', true);
544 if (!empty($tplidx)) {
545 $pdf->useTemplate($tplidx);
546 }
547 $pdf->setPage($pageposbefore + 1);
548
549 $curY = $tab_top_newpage;
550
551 // Allows data in the first page if description is long enough to break in multiples pages
552 if (getDolGlobalString('MAIN_PDF_DATA_ON_FIRST_PAGE')) {
553 $showpricebeforepagebreak = 1;
554 } else {
555 $showpricebeforepagebreak = 0;
556 }
557 }
558
559 if (!empty($this->cols['photo']) && isset($imglinesize['width']) && isset($imglinesize['height'])) {
560 $pdf->Image($realpatharray[$i], $this->getColumnContentXStart('photo'), $curY + 1, $imglinesize['width'], $imglinesize['height'], '', '', '', 2, 300); // Use 300 dpi
561 // $pdf->Image does not increase value return by getY, so we save it manually
562 $posYAfterImage = $curY + $imglinesize['height'];
563 }
564 }
565 // Description of product line
566 $curX = $this->posxdesc - 1;
567 $showpricebeforepagebreak = 1;
568
569 if ($this->getColumnStatus('desc')) {
570 $pdf->startTransaction();
571 $this->printColDescContent($pdf, $curY, 'desc', $object, $i, $outputlangs, $hideref, $hidedesc, 1);
572
573 $pageposafter = $pdf->getPage();
574 if ($pageposafter > $pageposbefore) { // There is a pagebreak
575 $pdf->rollbackTransaction(true);
576
577 $this->printColDescContent($pdf, $curY, 'desc', $object, $i, $outputlangs, $hideref, $hidedesc, 1);
578
579 $pageposafter = $pdf->getPage();
580 $posyafter = $pdf->GetY();
581 if ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforinfotot))) { // There is no space left for total+free text
582 if ($i == ($nblines - 1)) { // No more lines, and no space left to show total, so we create a new page
583 $pdf->AddPage('', '', true);
584 if (!empty($tplidx)) {
585 $pdf->useTemplate($tplidx);
586 }
587 //if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) $this->_pagehead($pdf, $object, 0, $outputlangs);
588 $pdf->setPage($pageposafter + 1);
589 }
590 } else {
591 // We found a page break
592 // Allows data in the first page if description is long enough to break in multiples pages
593 if (getDolGlobalString('MAIN_PDF_DATA_ON_FIRST_PAGE')) {
594 $showpricebeforepagebreak = 1;
595 } else {
596 $showpricebeforepagebreak = 0;
597 }
598 }
599 } else { // No pagebreak
600 $pdf->commitTransaction();
601 }
602 $posYAfterDescription = $pdf->GetY();
603 }
604
605 $nexY = $pdf->GetY();
606 $pageposafter = $pdf->getPage();
607 $pdf->setPage($pageposbefore);
608 $pdf->setTopMargin($this->marge_haute);
609 $pdf->setPageOrientation('', true, 0); // The only function to edit the bottom margin of current page to set it.
610
611 // We suppose that a too long description is moved completely on next page
612 if ($pageposafter > $pageposbefore && empty($showpricebeforepagebreak)) {
613 $pdf->setPage($pageposafter);
614 $curY = $tab_top_newpage;
615 }
616
617 $pdf->SetFont('', '', $default_font_size - 1); // On repositionne la police par default
618
619 // VAT Rate
620 if ($this->getColumnStatus('vat') && $object->lines[$i]->special_code != SUBTOTALS_SPECIAL_CODE) {
621 $vat_rate = pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails);
622 $this->printStdColumnContent($pdf, $curY, 'vat', $vat_rate);
623 $nexY = max($pdf->GetY(), $nexY);
624 }
625
626 // Unit price before discount
627 if ($this->getColumnStatus('subprice') && $object->lines[$i]->special_code != SUBTOTALS_SPECIAL_CODE && isset($pdf_sub_options['titleshowuponpdf'])) {
628 $up_excl_tax = pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails);
629 $this->printStdColumnContent($pdf, $curY, 'subprice', $up_excl_tax);
630 $nexY = max($pdf->GetY(), $nexY);
631 }
632
633 // Quantity
634 // Enough for 6 chars
635 if ($this->getColumnStatus('qty') && $object->lines[$i]->special_code != SUBTOTALS_SPECIAL_CODE) {
636 $qty = pdf_getlineqty($object, $i, $outputlangs, $hidedetails);
637 $this->printStdColumnContent($pdf, $curY, 'qty', $qty);
638 $nexY = max($pdf->GetY(), $nexY);
639 }
640
641
642 // Unit
643 if ($this->getColumnStatus('unit') && $object->lines[$i]->special_code != SUBTOTALS_SPECIAL_CODE) {
644 $unit = pdf_getlineunit($object, $i, $outputlangs, $hidedetails);
645 $this->printStdColumnContent($pdf, $curY, 'unit', $unit);
646 $nexY = max($pdf->GetY(), $nexY);
647 }
648
649 // Discount on line
650 if ($this->getColumnStatus('discount') && $object->lines[$i]->remise_percent && $object->lines[$i]->special_code != SUBTOTALS_SPECIAL_CODE) {
651 $remise_percent = pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails);
652 $this->printStdColumnContent($pdf, $curY, 'discount', $remise_percent);
653 $nexY = max($pdf->GetY(), $nexY);
654 }
655
656 // Total HT line
657 if ($this->getColumnStatus('totalexcltax')) {
658 if ($object->lines[$i]->special_code != SUBTOTALS_SPECIAL_CODE && isset($pdf_sub_options['titleshowtotalexludingvatonpdf'])) {
659 $total_excl_tax = pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails);
660 $this->printStdColumnContent($pdf, $curY, 'totalexcltax', $total_excl_tax);
661 } elseif ($object->lines[$i]->qty < 0 && isset($sub_options['subtotalshowtotalexludingvatonpdf'])) {
662 if (isModEnabled('multicurrency') && $object->multicurrency_code != $conf->currency) {
663 $total_excl_tax = $object->getSubtotalLineMulticurrencyAmount($object->lines[$i]);
664 } else {
665 $total_excl_tax = $object->getSubtotalLineAmount($object->lines[$i]);
666 }
667 $this->printStdColumnContent($pdf, $curY, 'totalexcltax', $total_excl_tax);
668 }
669 $nexY = max($pdf->GetY(), $nexY);
670 }
671
672 // Extrafields
673 if (!empty($object->lines[$i]->array_options)) {
674 foreach ($object->lines[$i]->array_options as $extrafieldColKey => $extrafieldValue) {
675 if ($this->getColumnStatus($extrafieldColKey)) {
676 $extrafieldValue = $this->getExtrafieldContent($object->lines[$i], $extrafieldColKey, $outputlangs);
677 $this->printStdColumnContent($pdf, $curY, $extrafieldColKey, $extrafieldValue);
678 $nexY = max($pdf->GetY(), $nexY);
679 }
680 }
681 }
682
683 $parameters = array(
684 'object' => $object,
685 'i' => $i,
686 'pdf' => & $pdf,
687 'curY' => & $curY,
688 'nexY' => & $nexY,
689 'outputlangs' => $outputlangs,
690 'hidedetails' => $hidedetails
691 );
692 $reshook = $hookmanager->executeHooks('printPDFline', $parameters, $this); // Note that $object may have been modified by hook
693
694
695 // // Collect total by value of vat rate into $this->tva["taux"]=total_tva
696 if (isModEnabled("multicurrency") && $object->multicurrency_tx != 1) {
697 $tvaligne = $object->lines[$i]->multicurrency_total_tva;
698 } else {
699 $tvaligne = $object->lines[$i]->total_tva;
700 }
701
702 $localtax1ligne = $object->lines[$i]->total_localtax1;
703 $localtax2ligne = $object->lines[$i]->total_localtax2;
704 $localtax1_rate = $object->lines[$i]->localtax1_tx;
705 $localtax2_rate = $object->lines[$i]->localtax2_tx;
706 $localtax1_type = $object->lines[$i]->localtax1_type;
707 $localtax2_type = $object->lines[$i]->localtax2_type;
708
709 // TODO remise_percent is an obsolete field for object parent
710 /*if (!empty($object->remise_percent)) {
711 $tvaligne -= ($tvaligne * $object->remise_percent) / 100;
712 }
713 if (!empty($object->remise_percent)) {
714 $localtax1ligne -= ($localtax1ligne * $object->remise_percent) / 100;
715 }
716 if (!empty($object->remise_percent)) {
717 $localtax2ligne -= ($localtax2ligne * $object->remise_percent) / 100;
718 }*/
719
720 $vatrate = (string) $object->lines[$i]->tva_tx;
721
722 // Retrieve type from database for backward compatibility with old records
723 if ((!isset($localtax1_type) || $localtax1_type == '' || !isset($localtax2_type) || $localtax2_type == '') // if tax type not defined
724 && (!empty($localtax1_rate) || !empty($localtax2_rate))) { // and there is local tax
725 $localtaxtmp_array = getLocalTaxesFromRate($vatrate, 0, $mysoc, $object->thirdparty);
726 $localtax1_type = isset($localtaxtmp_array[0]) ? $localtaxtmp_array[0] : '';
727 $localtax2_type = isset($localtaxtmp_array[2]) ? $localtaxtmp_array[2] : '';
728 }
729
730 // retrieve global local tax
731 if ($localtax1_type && $localtax1ligne != 0) {
732 if (empty($this->localtax1[$localtax1_type][$localtax1_rate])) {
733 $this->localtax1[$localtax1_type][$localtax1_rate] = $localtax1ligne;
734 } else {
735 $this->localtax1[$localtax1_type][$localtax1_rate] += $localtax1ligne;
736 }
737 }
738 if ($localtax2_type && $localtax2ligne != 0) {
739 if (empty($this->localtax2[$localtax2_type][$localtax2_rate])) {
740 $this->localtax2[$localtax2_type][$localtax2_rate] = (float) $localtax2ligne;
741 } else {
742 $this->localtax2[$localtax2_type][$localtax2_rate] += $localtax2ligne;
743 }
744 }
745
746 if (($object->lines[$i]->info_bits & 0x01) == 0x01) {
747 $vatrate .= '*';
748 }
749
750 // Fill $this->tva and $this->tva_array
751 if (!isset($this->tva[$vatrate])) {
752 $this->tva[$vatrate] = 0;
753 }
754 $this->tva[$vatrate] += $tvaligne;
755 $vatcode = $object->lines[$i]->vat_src_code;
756 if (empty($this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'])) {
757 $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'] = 0;
758 }
759 $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')] = array('vatrate' => $vatrate, 'vatcode' => $vatcode, 'amount' => $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'] + $tvaligne);
760
761 if ($posYAfterImage > $posYAfterDescription) {
762 $nexY = $posYAfterImage;
763 }
764
765 // Add line
766 if (getDolGlobalString('MAIN_PDF_DASH_BETWEEN_LINES') && $i < ($nblines - 1)) {
767 $pdf->setPage($pageposafter);
768 $pdf->SetLineStyle(array('dash' => '1,1', 'color' => array(80, 80, 80)));
769 //$pdf->SetDrawColor(190,190,200);
770 $pdf->line($this->marge_gauche, $nexY, $this->page_largeur - $this->marge_droite, $nexY);
771 $pdf->SetLineStyle(array('dash' => 0));
772 }
773
774 // Detect if some page were added automatically and output _tableau for past pages
775 while ($pagenb < $pageposafter) {
776 $pdf->setPage($pagenb);
777 if ($pagenb == $pageposbeforeprintlines) {
778 $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, $hidetop, 1, $object->multicurrency_code);
779 } else {
780 $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code);
781 }
782 $this->_pagefoot($pdf, $object, $outputlangs, 1);
783 $pagenb++;
784 $pdf->setPage($pagenb);
785 $pdf->setPageOrientation('', true, 0); // The only function to edit the bottom margin of current page to set it.
786 if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
787 $this->_pagehead($pdf, $object, 0, $outputlangs);
788 }
789 if (!empty($tplidx)) {
790 $pdf->useTemplate($tplidx);
791 }
792 }
793 if (isset($object->lines[$i + 1]->pagebreak) && $object->lines[$i + 1]->pagebreak) { // @phan-suppress-current-line PhanUndeclaredProperty
794 if ($pagenb == $pageposafter) {
795 $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, $hidetop, 1, $object->multicurrency_code);
796 } else {
797 $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code);
798 }
799 $this->_pagefoot($pdf, $object, $outputlangs, 1);
800 // New page
801 $pdf->AddPage();
802 if (!empty($tplidx)) {
803 $pdf->useTemplate($tplidx);
804 }
805 $pagenb++;
806 if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
807 $this->_pagehead($pdf, $object, 0, $outputlangs);
808 }
809 }
810 }
811
812 // Show square
813 if ($pagenb == $pageposbeforeprintlines) {
814 $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, $hidetop, 0, $object->multicurrency_code);
815 $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
816 } else {
817 $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 1, 0, $object->multicurrency_code);
818 $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
819 }
820
821 // Affiche zone infos
822 $posy = $this->_tableau_info($pdf, $object, $bottomlasttab, $outputlangs);
823
824 // Affiche zone totaux
825 $posy = $this->_tableau_tot($pdf, $object, $deja_regle, $bottomlasttab, $outputlangs);
826
827 // Affiche zone versements
828 if ($deja_regle || $amount_credit_notes_included || $amount_deposits_included) {
829 $posy = $this->_tableau_versements($pdf, $object, $posy, $outputlangs);
830 }
831
832 // Pied de page
833 $this->_pagefoot($pdf, $object, $outputlangs);
834 if (method_exists($pdf, 'AliasNbPages')) {
835 $pdf->AliasNbPages(); // @phan-suppress-current-line PhanUndeclaredMethod
836 }
837
838 $pdf->Close();
839
840 $pdf->Output($file, 'F');
841
842 // Add pdfgeneration hook
843 $hookmanager->initHooks(array('pdfgeneration'));
844 $parameters = array('file' => $file, 'object' => $object, 'outputlangs' => $outputlangs);
845 global $action;
846 $reshook = $hookmanager->executeHooks('afterPDFCreation', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
847 $this->warnings = $hookmanager->warnings;
848 if ($reshook < 0) {
849 $this->error = $hookmanager->error;
850 $this->errors = $hookmanager->errors;
851 dolChmod($file);
852 return -1;
853 }
854
855 dolChmod($file);
856
857 $this->result = array('fullpath' => $file);
858
859 return 1; // No error
860 } else {
861 $this->error = $langs->trans("ErrorCanNotCreateDir", $dir);
862 return 0;
863 }
864 } else {
865 $this->error = $langs->trans("ErrorConstantNotDefined", "SUPPLIER_OUTPUTDIR");
866 return 0;
867 }
868 }
869
870 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
871 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
881 protected function _tableau_versements(&$pdf, $object, $posy, $outputlangs)
882 {
883 // phpcs:enable
884 return 1;
885 }
886
887 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
888 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
898 protected function _tableau_info(&$pdf, $object, $posy, $outputlangs)
899 {
900 // phpcs:enable
901 global $conf, $mysoc;
902 $default_font_size = pdf_getPDFFontSize($outputlangs);
903
904 $diffsizetitle = getDolGlobalInt('PDF_DIFFSIZE_TITLE', 3);
905
906 // If France, show VAT mention if not applicable
907 if ($this->emetteur->country_code == 'FR' && empty($mysoc->tva_assuj)) {
908 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
909 $pdf->SetXY($this->marge_gauche, $posy);
910 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("VATIsNotUsedForInvoice"), 0, 'L', false);
911
912 $posy = $pdf->GetY() + 4;
913 }
914
915 $posxval = 52;
916
917 // Show payments conditions
918 if (!empty($object->cond_reglement_code) || $object->cond_reglement) {
919 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
920 $pdf->SetXY($this->marge_gauche, $posy);
921 $titre = $outputlangs->transnoentities("PaymentConditions").':';
922 $pdf->MultiCell(80, 4, $titre, 0, 'L');
923
924 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
925 $pdf->SetXY($posxval, $posy);
926 $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);
927 $lib_condition_paiement = str_replace('\n', "\n", $lib_condition_paiement);
928 if ($object->deposit_percent > 0) {
929 $lib_condition_paiement = str_replace('__DEPOSIT_PERCENT__', $object->deposit_percent, $lib_condition_paiement);
930 }
931 $pdf->MultiCell(80, 4, $lib_condition_paiement, 0, 'L');
932
933 $posy = $pdf->GetY() + 3;
934 }
935
936 // Show payment mode
937 if (!empty($object->mode_reglement_code)) {
938 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
939 $pdf->SetXY($this->marge_gauche, $posy);
940 $titre = $outputlangs->transnoentities("PaymentMode").':';
941 $pdf->MultiCell(80, 5, $titre, 0, 'L');
942
943 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
944 $pdf->SetXY($posxval, $posy);
945 $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);
946 $pdf->MultiCell(80, 5, $lib_mode_reg, 0, 'L');
947
948 $posy = $pdf->GetY() + 2;
949 }
950
951
952 return $posy;
953 }
954
955 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
956 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
967 protected function _tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs)
968 {
969 // phpcs:enable
970 global $conf, $mysoc;
971
972 $default_font_size = pdf_getPDFFontSize($outputlangs);
973
974 $tab2_top = $posy;
975 $tab2_hl = 4;
976 $pdf->SetFont('', '', $default_font_size - 1);
977
978 // Tableau total
979 $col1x = 120;
980 $col2x = 170;
981 if ($this->page_largeur < 210) { // To work with US executive format
982 $col2x -= 20;
983 }
984 $largcol2 = ($this->page_largeur - $this->marge_droite - $col2x);
985
986 $useborder = 0;
987 $index = 0;
988
989 // Total HT
990 $pdf->SetFillColor(255, 255, 255);
991 $pdf->SetXY($col1x, $tab2_top);
992 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalHT"), 0, 'L', true);
993
994 $total_ht = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? $object->multicurrency_total_ht : $object->total_ht);
995 $pdf->SetXY($col2x, $tab2_top);
996 $pdf->MultiCell($largcol2, $tab2_hl, price($total_ht + (!empty($object->remise) ? $object->remise : 0)), 0, 'R', true);
997
998 // Show VAT by rates and total
999 $pdf->SetFillColor(248, 248, 248);
1000
1001 $this->atleastoneratenotnull = 0;
1002 foreach ($this->tva as $tvakey => $tvaval) {
1003 if ($tvakey > 0) { // On affiche pas taux 0
1004 $this->atleastoneratenotnull++;
1005
1006 $index++;
1007 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1008
1009 $tvacompl = '';
1010
1011 if (preg_match('/\*/', $tvakey)) {
1012 $tvakey = str_replace('*', '', $tvakey);
1013 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1014 }
1015
1016 $totalvat = $outputlangs->transcountrynoentities("TotalVAT", $mysoc->country_code).' ';
1017 $totalvat .= vatrate($tvakey, true).$tvacompl;
1018 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1019
1020 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1021 $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval), 0, 'R', true);
1022 }
1023 }
1024 if (!$this->atleastoneratenotnull) { // If no vat at all
1025 $index++;
1026 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1027 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transcountrynoentities("TotalVAT", $mysoc->country_code), 0, 'L', true);
1028
1029 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1030 $pdf->MultiCell($largcol2, $tab2_hl, price($object->total_tva), 0, 'R', true);
1031
1032 // Total LocalTax1
1033 if (getDolGlobalString('FACTURE_LOCAL_TAX1_OPTION') == 'localtax1on' && $object->total_localtax1 > 0) {
1034 $index++;
1035 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1036 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transcountrynoentities("TotalLT1", $mysoc->country_code), 0, 'L', true);
1037 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1038 $pdf->MultiCell($largcol2, $tab2_hl, price($object->total_localtax1), $useborder, 'R', true);
1039 }
1040
1041 // Total LocalTax2
1042 if (getDolGlobalString('FACTURE_LOCAL_TAX2_OPTION') == 'localtax2on' && $object->total_localtax2 > 0) {
1043 $index++;
1044 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1045 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transcountrynoentities("TotalLT2", $mysoc->country_code), 0, 'L', true);
1046 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1047 $pdf->MultiCell($largcol2, $tab2_hl, price($object->total_localtax2), $useborder, 'R', true);
1048 }
1049 } else {
1050 //if (getDolGlobalString('FACTURE_LOCAL_TAX1_OPTION') && getDolGlobalString('FACTURE_LOCAL_TAX1_OPTION') == 'localtax1on')
1051 //{
1052 //Local tax 1
1053 foreach ($this->localtax1 as $localtax_type => $localtax_rate) {
1054 if (in_array((string) $localtax_type, array('2', '4', '6'))) {
1055 continue;
1056 }
1057
1058 foreach ($localtax_rate as $tvakey => $tvaval) {
1059 if ($tvakey != 0) { // On affiche pas taux 0
1060 //$this->atleastoneratenotnull++;
1061
1062 $index++;
1063 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1064
1065 $tvacompl = '';
1066 if (preg_match('/\*/', $tvakey)) {
1067 $tvakey = str_replace('*', '', $tvakey);
1068 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1069 }
1070 $totalvat = $outputlangs->transcountrynoentities("TotalLT1", $mysoc->country_code).' ';
1071 $totalvat .= vatrate((string) abs((float) $tvakey), true).$tvacompl;
1072 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1073
1074 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1075 $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', true);
1076 }
1077 }
1078 }
1079
1080 //if (getDolGlobalString('FACTURE_LOCAL_TAX2_OPTION') && getDolGlobalString('FACTURE_LOCAL_TAX2_OPTION') == 'localtax2on')
1081 //{
1082 //Local tax 2
1083 foreach ($this->localtax2 as $localtax_type => $localtax_rate) {
1084 if (in_array((string) $localtax_type, array('2', '4', '6'))) {
1085 continue;
1086 }
1087
1088 foreach ($localtax_rate as $tvakey => $tvaval) {
1089 if ($tvakey != 0) { // On affiche pas taux 0
1090 //$this->atleastoneratenotnull++;
1091
1092 $index++;
1093 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1094
1095 $tvacompl = '';
1096 if (preg_match('/\*/', $tvakey)) {
1097 $tvakey = str_replace('*', '', $tvakey);
1098 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1099 }
1100 $totalvat = $outputlangs->transcountrynoentities("TotalLT2", $mysoc->country_code).' ';
1101 $totalvat .= vatrate((string) abs((float) $tvakey), true).$tvacompl;
1102 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1103
1104 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1105 $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval), 0, 'R', true);
1106 }
1107 }
1108 }
1109 }
1110
1111 // Total TTC
1112 $index++;
1113 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1114 $pdf->SetTextColor(0, 0, 60);
1115 $pdf->SetFillColor(224, 224, 224);
1116 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalTTC"), $useborder, 'L', true);
1117
1118 $total_ttc = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1) ? $object->multicurrency_total_ttc : $object->total_ttc;
1119 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1120 $pdf->MultiCell($largcol2, $tab2_hl, price($total_ttc), $useborder, 'R', true);
1121 $pdf->SetFont('', '', $default_font_size - 1);
1122 $pdf->SetTextColor(0, 0, 0);
1123
1124 $creditnoteamount = 0;
1125 $depositsamount = 0;
1126 //$creditnoteamount=$object->getSumCreditNotesUsed();
1127 //$depositsamount=$object->getSumDepositsUsed();
1128 //print "x".$creditnoteamount."-".$depositsamount;exit;
1129 $resteapayer = price2num($total_ttc - $deja_regle - $creditnoteamount - $depositsamount, 'MT');
1130 if (!empty($object->paye)) {
1131 $resteapayer = 0;
1132 }
1133
1134 if ($deja_regle > 0) {
1135 // Already paid + Deposits
1136 $index++;
1137
1138 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1139 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("AlreadyPaid"), 0, 'L', false);
1140 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1141 $pdf->MultiCell($largcol2, $tab2_hl, price($deja_regle), 0, 'R', false);
1142
1143 $index++;
1144 $pdf->SetTextColor(0, 0, 60);
1145 $pdf->SetFillColor(224, 224, 224);
1146 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1147 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("RemainderToPay"), $useborder, 'L', true);
1148
1149 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1150 $pdf->MultiCell($largcol2, $tab2_hl, price($resteapayer), $useborder, 'R', true);
1151
1152 $pdf->SetFont('', '', $default_font_size - 1);
1153 $pdf->SetTextColor(0, 0, 0);
1154 }
1155
1156 $index++;
1157 return ($tab2_top + ($tab2_hl * $index));
1158 }
1159
1160 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1174 protected function _tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop = 0, $hidebottom = 0, $currency = '')
1175 {
1176 global $conf;
1177
1178 // Force to disable hidetop and hidebottom
1179 $hidebottom = 0;
1180 if ($hidetop) {
1181 $hidetop = -1;
1182 }
1183
1184 $currency = !empty($currency) ? $currency : $conf->currency;
1185 $default_font_size = pdf_getPDFFontSize($outputlangs);
1186
1187 // Amount in (at tab_top - 1)
1188 $pdf->SetTextColor(0, 0, 0);
1189 $pdf->SetFont('', '', $default_font_size - 2);
1190
1191 if (empty($hidetop)) {
1192 $titre = $outputlangs->transnoentities("AmountInCurrency", $outputlangs->transnoentitiesnoconv("Currency".$currency));
1193 $pdf->SetXY($this->page_largeur - $this->marge_droite - ($pdf->GetStringWidth($titre) + 3), $tab_top - 4);
1194 $pdf->MultiCell(($pdf->GetStringWidth($titre) + 3), 2, $titre);
1195
1196 //$conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR='230,230,230';
1197 if (getDolGlobalString('MAIN_PDF_TITLE_BACKGROUND_COLOR')) {
1198 $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')));
1199 }
1200 }
1201
1202 $pdf->SetDrawColor(128, 128, 128);
1203 $pdf->SetFont('', '', $default_font_size - 1);
1204
1205 // Output Rect
1206 $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
1207
1208 $this->pdfTabTitles($pdf, $tab_top, $tab_height, $outputlangs, $hidetop);
1209
1210 if (empty($hidetop)) {
1211 $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
1212 }
1213 }
1214
1215 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1225 protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs)
1226 {
1227 global $langs, $conf, $mysoc;
1228
1229 $ltrdirection = 'L';
1230 if ($outputlangs->trans("DIRECTION") == 'rtl') {
1231 $ltrdirection = 'R';
1232 }
1233
1234 // Load translation files required by the page
1235 $outputlangs->loadLangs(array("main", "supplier_proposal", "companies", "bills", "sendings"));
1236
1237 $default_font_size = pdf_getPDFFontSize($outputlangs);
1238
1239 // Do not add the BACKGROUND as this is for suppliers
1240 //pdf_pagehead($pdf,$outputlangs,$this->page_hauteur);
1241
1242 //Affiche le filigrane brouillon - Print Draft Watermark
1243 /*if($object->statut==0 && getDolGlobalString('COMMANDE_DRAFT_WATERMARK'))
1244 {
1245 pdf_watermark($pdf,$outputlangs,$this->page_hauteur,$this->page_largeur,'mm',getDolGlobalString('COMMANDE_DRAFT_WATERMARK'));
1246 }*/
1247 //Print content
1248
1249 $pdf->SetTextColor(0, 0, 60);
1250 $pdf->SetFont('', 'B', $default_font_size + 3);
1251
1252 $posx = $this->page_largeur - $this->marge_droite - 100;
1253 $posy = $this->marge_haute;
1254
1255 $pdf->SetXY($this->marge_gauche, $posy);
1256
1257 // Logo
1258 if (!getDolGlobalInt('PDF_DISABLE_MYCOMPANY_LOGO')) {
1259 if ($this->emetteur->logo) {
1260 $logodir = $conf->mycompany->dir_output;
1261 if (!empty($conf->mycompany->multidir_output[$object->entity ?? $conf->entity])) {
1262 $logodir = $conf->mycompany->multidir_output[$object->entity ?? $conf->entity];
1263 }
1264 if (!getDolGlobalInt('MAIN_PDF_USE_LARGE_LOGO')) {
1265 $logo = $logodir.'/logos/thumbs/'.$this->emetteur->logo_small;
1266 } else {
1267 $logo = $logodir.'/logos/'.$this->emetteur->logo;
1268 }
1269 if (is_readable($logo)) {
1270 $height = pdf_getHeightForLogo($logo);
1271 $pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto)
1272 } else {
1273 $pdf->SetTextColor(200, 0, 0);
1274 $pdf->SetFont('', 'B', $default_font_size - 2);
1275 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound", $logo), 0, 'L');
1276 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorGoToGlobalSetup"), 0, 'L');
1277 }
1278 } else {
1279 $text = $this->emetteur->name;
1280 $pdf->MultiCell(100, 4, $outputlangs->convToOutputCharset($text), 0, $ltrdirection);
1281 }
1282 }
1283
1284 $pdf->SetFont('', 'B', $default_font_size + 3);
1285 $pdf->SetXY($posx, $posy);
1286 $pdf->SetTextColor(0, 0, 60);
1287 $title = $outputlangs->transnoentities("SupplierProposal")." ".$outputlangs->convToOutputCharset($object->ref);
1288 $pdf->MultiCell(100, 3, $title, '', 'R');
1289 $posy += 1;
1290
1291 if ($object->ref_supplier) {
1292 $posy += 4;
1293 $pdf->SetFont('', 'B', $default_font_size);
1294 $pdf->SetXY($posx, $posy);
1295 $pdf->SetTextColor(0, 0, 60);
1296 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("RefSupplier")." : ".$outputlangs->convToOutputCharset($object->ref_supplier), '', 'R');
1297 $posy += 1;
1298 }
1299
1300 $pdf->SetFont('', '', $default_font_size - 1);
1301
1302 if (getDolGlobalString('PDF_SHOW_PROJECT_TITLE')) {
1303 $object->fetchProject();
1304 if (!empty($object->project->ref)) {
1305 $posy += 3;
1306 $pdf->SetXY($posx, $posy);
1307 $pdf->SetTextColor(0, 0, 60);
1308 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Project")." : ".(empty($object->project->title) ? '' : $object->project->title), '', 'R');
1309 }
1310 }
1311
1312 if (getDolGlobalString('PDF_SHOW_PROJECT')) {
1313 $object->fetchProject();
1314 if (!empty($object->project->ref)) {
1315 $outputlangs->load("projects");
1316 $posy += 4;
1317 $pdf->SetXY($posx, $posy);
1318 $langs->load("projects");
1319 $pdf->SetTextColor(0, 0, 60);
1320 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Project")." : ".(empty($object->project->ref) ? '' : $object->project->ref), '', 'R');
1321 }
1322 }
1323
1324 if (!empty($object->date)) {
1325 $posy += 5;
1326 $pdf->SetXY($posx, $posy);
1327 $pdf->SetTextColor(0, 0, 60);
1328 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Date")." : ".dol_print_date($object->date, "day", false, $outputlangs, true), '', 'R');
1329 } else {
1330 $posy += 5;
1331 $pdf->SetXY($posx, $posy);
1332 $pdf->SetTextColor(255, 0, 0);
1333 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Draft"), '', 'R');
1334 }
1335
1336 $pdf->SetTextColor(0, 0, 60);
1337 $usehourmin = 'day';
1338 if (getDolGlobalString('SUPPLIER_PROPOSAL_USE_HOUR_FOR_DELIVERY_DATE')) {
1339 $usehourmin = 'dayhour';
1340 }
1341 if (!empty($object->delivery_date)) {
1342 $posy += 4;
1343 $pdf->SetXY($posx - 90, $posy);
1344 $pdf->MultiCell(190, 3, $outputlangs->transnoentities("DateDeliveryPlanned")." : ".dol_print_date($object->delivery_date, $usehourmin, false, $outputlangs, true), '', 'R');
1345 }
1346
1347 if ($object->thirdparty->code_fournisseur) {
1348 $posy += 4;
1349 $pdf->SetXY($posx, $posy);
1350 $pdf->SetTextColor(0, 0, 60);
1351 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("SupplierCode")." : ".$outputlangs->transnoentities((string) $object->thirdparty->code_fournisseur), '', 'R');
1352 }
1353
1354 // Get contact
1355 if (getDolGlobalString('DOC_SHOW_FIRST_SALES_REP')) {
1356 $arrayidcontact = $object->getIdContact('internal', 'SALESREPFOLL');
1357
1358 if (is_array($arrayidcontact) && count($arrayidcontact) > 0) {
1359 $usertmp = new User($this->db);
1360 $usertmp->fetch($arrayidcontact[0]);
1361 $posy += 4;
1362 $pdf->SetXY($posx, $posy);
1363 $pdf->SetTextColor(0, 0, 60);
1364 $pdf->MultiCell(100, 3, $langs->trans("BuyerName")." : ".$usertmp->getFullName($langs), '', 'R');
1365 }
1366 }
1367
1368 $posy += 1;
1369 $pdf->SetTextColor(0, 0, 60);
1370
1371 $top_shift = 0;
1372 // Show list of linked objects
1373 $current_y = $pdf->getY();
1374 $posy = pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, 100, 3, 'R', $default_font_size);
1375 if ($current_y < $pdf->getY()) {
1376 $top_shift = $pdf->getY() - $current_y;
1377 }
1378
1379 if ($showaddress) {
1380 // Sender properties
1381 $carac_emetteur = '';
1382 // Add internal contact of object if defined
1383 $arrayidcontact = $object->getIdContact('internal', 'SALESREPFOLL');
1384 if (count($arrayidcontact) > 0) {
1385 $object->fetch_user($arrayidcontact[0]);
1386 $labelbeforecontactname = ($outputlangs->transnoentities("FromContactName") != 'FromContactName' ? $outputlangs->transnoentities("FromContactName") : $outputlangs->transnoentities("Name"));
1387 $carac_emetteur .= ($carac_emetteur ? "\n" : '').$labelbeforecontactname.": ".$outputlangs->convToOutputCharset($object->user->getFullName($outputlangs));
1388 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') || getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ' (' : '';
1389 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') && !empty($object->user->office_phone)) ? $object->user->office_phone : '';
1390 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') && getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ', ' : '';
1391 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT') && !empty($object->user->email)) ? $object->user->email : '';
1392 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') || getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ')' : '';
1393 $carac_emetteur .= "\n";
1394 }
1395
1396 $carac_emetteur .= pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, '', 0, 'source', $object);
1397
1398 // Show sender
1399 $posy = 42 + $top_shift;
1400 $posx = $this->marge_gauche;
1401 if (getDolGlobalString('MAIN_INVERT_SENDER_RECIPIENT')) {
1402 $posx = $this->page_largeur - $this->marge_droite - 80;
1403 }
1404 $hautcadre = 40;
1405
1406 // Show sender frame
1407 $pdf->SetTextColor(0, 0, 0);
1408 $pdf->SetFont('', '', $default_font_size - 2);
1409 $pdf->SetXY($posx, $posy - 5);
1410 $pdf->MultiCell(80, 5, $outputlangs->transnoentities("BillFrom"), 0, $ltrdirection);
1411 $pdf->SetXY($posx, $posy);
1412 $pdf->SetFillColor(230, 230, 230);
1413 $pdf->RoundedRect($posx, $posy, 82, $hautcadre, $this->corner_radius, '1234', 'F');
1414 $pdf->SetTextColor(0, 0, 60);
1415
1416 // Show sender name
1417 $pdf->SetXY($posx + 2, $posy + 3);
1418 $pdf->SetFont('', 'B', $default_font_size);
1419 $pdf->MultiCell(80, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, $ltrdirection);
1420 $posy = $pdf->getY();
1421
1422 // Show sender information
1423 $pdf->SetXY($posx + 2, $posy);
1424 $pdf->SetFont('', '', $default_font_size - 1);
1425 $pdf->MultiCell(80, 4, $carac_emetteur, 0, $ltrdirection);
1426
1427
1428
1429 // If CUSTOMER contact defined on proposal, we use it. Note: Even if this is a supplier object, the code for external contact that follow-up a supplier proposal is 'CUSTOMER'
1430 $usecontact = false;
1431 if (!getDolGlobalInt('SUPPLIER_PROPOSAL_ADD_BILLING_CONTACT')) {
1432 $arrayidcontact = $object->getIdContact('external', 'CUSTOMER');
1433 } else {
1434 $arrayidcontact = array_merge($object->getIdContact('external', 'CUSTOMER'), $object->getIdContact('external', 'BILLING'));
1435 }
1436 if (is_array($arrayidcontact) && count($arrayidcontact) > 0) {
1437 $usecontact = true;
1438 $result = $object->fetch_contact($arrayidcontact[0]);
1439 }
1440
1441 // Recipient name
1442 if ($usecontact && ($object->contact->socid != $object->thirdparty->id && (!isset($conf->global->MAIN_USE_COMPANY_NAME_OF_CONTACT) || getDolGlobalString('MAIN_USE_COMPANY_NAME_OF_CONTACT')))) {
1443 $thirdparty = $object->contact;
1444 } else {
1445 $thirdparty = $object->thirdparty;
1446 }
1447
1448 $carac_client_name = pdfBuildThirdpartyName($thirdparty, $outputlangs);
1449
1450 $carac_client = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, ($usecontact ? $object->contact : ''), ($usecontact ? 1 : 0), 'target', $object);
1451
1452 // Show recipient
1453 $widthrecbox = 100;
1454 if ($this->page_largeur < 210) {
1455 $widthrecbox = 84; // To work with US executive format
1456 }
1457 $posy = 42 + $top_shift;
1458 $posx = $this->page_largeur - $this->marge_droite - $widthrecbox;
1459 if (getDolGlobalString('MAIN_INVERT_SENDER_RECIPIENT')) {
1460 $posx = $this->marge_gauche;
1461 }
1462
1463 // Show recipient frame
1464 $pdf->SetTextColor(0, 0, 0);
1465 $pdf->SetFont('', '', $default_font_size - 2);
1466 $pdf->SetXY($posx + 2, $posy - 5);
1467 $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillTo"), 0, $ltrdirection);
1468 $pdf->RoundedRect($posx, $posy, $widthrecbox, $hautcadre, $this->corner_radius, '1234', 'D');
1469
1470 // Show recipient name
1471 $pdf->SetXY($posx + 2, $posy + 3);
1472 $pdf->SetFont('', 'B', $default_font_size);
1473 // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
1474 $pdf->MultiCell($widthrecbox, 4, $carac_client_name, 0, $ltrdirection);
1475
1476 $posy = $pdf->getY();
1477
1478 // Show recipient information
1479 $pdf->SetFont('', '', $default_font_size - 1);
1480 $pdf->SetXY($posx + 2, $posy);
1481 // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
1482 $pdf->MultiCell($widthrecbox, 4, $carac_client, 0, $ltrdirection);
1483 }
1484
1485 return $top_shift;
1486 }
1487
1488 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1498 protected function _pagefoot(&$pdf, $object, $outputlangs, $hidefreetext = 0)
1499 {
1500 $showdetails = getDolGlobalInt('MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS', 0);
1501 return pdf_pagefoot($pdf, $outputlangs, 'SUPPLIER_PROPOSAL_FREE_TEXT', $this->emetteur, $this->marge_basse, $this->marge_gauche, $this->page_hauteur, $object, $showdetails, $hidefreetext);
1502 }
1503
1504
1505
1516 public function defineColumnField($object, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0)
1517 {
1518 global $hookmanager;
1519
1520 // Default field style for content
1521 $this->defaultContentsFieldsStyle = array(
1522 'align' => 'R', // R,C,L
1523 'padding' => array(1, 0.5, 1, 0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1524 );
1525
1526 // Default field style for content
1527 $this->defaultTitlesFieldsStyle = array(
1528 'align' => 'C', // R,C,L
1529 'padding' => array(0.5, 0, 0.5, 0), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1530 );
1531
1532 $rank = 0; // do not use negative rank
1533 $this->cols['desc'] = array(
1534 'rank' => $rank,
1535 'width' => false, // only for desc
1536 'status' => true,
1537 'title' => array(
1538 'textkey' => 'Designation', // use lang key is useful in some case with module
1539 'align' => 'L',
1540 // 'textkey' => 'yourLangKey', // if there is no label, yourLangKey will be translated to replace label
1541 // 'label' => ' ', // the final label
1542 'padding' => array(0.5, 0.5, 0.5, 0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1543 ),
1544 'content' => array(
1545 'align' => 'L',
1546 'padding' => array(1, 0.5, 1, 1.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1547 ),
1548 );
1549
1550 $rank += 10;
1551 $this->cols['photo'] = array(
1552 'rank' => $rank,
1553 'width' => getDolGlobalInt('MAIN_DOCUMENTS_WITH_PICTURE_WIDTH', 20), // in mm
1554 'status' => false,
1555 'title' => array(
1556 'textkey' => 'Photo',
1557 'label' => ' '
1558 ),
1559 'content' => array(
1560 'padding' => array(0, 0, 0, 0), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1561 ),
1562 'border-left' => false, // remove left line separator
1563 );
1564
1565 if (getDolGlobalString('MAIN_GENERATE_SUPPLIER_PROPOSAL_WITH_PICTURE')) {
1566 $this->cols['photo']['status'] = true;
1567 }
1568
1569
1570 $rank += 10;
1571 $this->cols['vat'] = array(
1572 'rank' => $rank,
1573 'status' => false,
1574 'width' => 16, // in mm
1575 'title' => array(
1576 'textkey' => 'VAT'
1577 ),
1578 'border-left' => true, // add left line separator
1579 );
1580
1581 if (!getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT') && !getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_COLUMN')) {
1582 $this->cols['vat']['status'] = true;
1583 }
1584
1585 $rank += 10;
1586 $this->cols['subprice'] = array(
1587 'rank' => $rank,
1588 'width' => 19, // in mm
1589 'status' => false,
1590 'title' => array(
1591 'textkey' => 'PriceUHT'
1592 ),
1593 'border-left' => true, // add left line separator
1594 );
1595
1596 if (!getDolGlobalString('MAIN_GENERATE_DOCUMENTS_SUPPLIER_PROPOSAL_WITHOUT_UNIT_PRICE')) {
1597 $this->cols['subprice']['status'] = true;
1598 }
1599
1600 $rank += 10;
1601 $this->cols['qty'] = array(
1602 'rank' => $rank,
1603 'width' => 16, // in mm
1604 'status' => true,
1605 'title' => array(
1606 'textkey' => 'Qty'
1607 ),
1608 'border-left' => true, // add left line separator
1609 );
1610
1611 $rank += 10;
1612 $this->cols['unit'] = array(
1613 'rank' => $rank,
1614 'width' => 11, // in mm
1615 'status' => false,
1616 'title' => array(
1617 'textkey' => 'Unit'
1618 ),
1619 'border-left' => true, // add left line separator
1620 );
1621 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
1622 $this->cols['unit']['status'] = true;
1623 }
1624
1625 $rank += 10;
1626 $this->cols['discount'] = array(
1627 'rank' => $rank,
1628 'width' => 13, // in mm
1629 'status' => false,
1630 'title' => array(
1631 'textkey' => 'ReductionShort'
1632 ),
1633 'border-left' => true, // add left line separator
1634 );
1635 if ($this->atleastonediscount) {
1636 $this->cols['discount']['status'] = true;
1637 }
1638
1639 $rank += 1000; // add a big offset to be sure is the last col because default extrafield rank is 100
1640 $this->cols['totalexcltax'] = array(
1641 'rank' => $rank,
1642 'width' => 26, // in mm
1643 'status' => false,
1644 'title' => array(
1645 'textkey' => 'TotalHT'
1646 ),
1647 'border-left' => true, // add left line separator
1648 );
1649
1650 if (!getDolGlobalString('MAIN_GENERATE_DOCUMENTS_SUPPLIER_PROPOSAL_WITHOUT_TOTAL_COLUMN')) {
1651 $this->cols['totalexcltax']['status'] = true;
1652 }
1653
1654 // Add extrafields cols
1655 if (!empty($object->lines)) {
1656 $line = reset($object->lines);
1657 $this->defineColumnExtrafield($line, $outputlangs, $hidedetails);
1658 }
1659
1660 $parameters = array(
1661 'object' => $object,
1662 'outputlangs' => $outputlangs,
1663 'hidedetails' => $hidedetails,
1664 'hidedesc' => $hidedesc,
1665 'hideref' => $hideref
1666 );
1667
1668 $reshook = $hookmanager->executeHooks('defineColumnField', $parameters, $this); // Note that $object may have been modified by hook
1669 if ($reshook < 0) {
1670 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1671 } elseif (empty($reshook)) {
1672 // @phan-suppress-next-line PhanPluginSuspiciousParamOrderInternal
1673 $this->cols = array_replace($this->cols, $hookmanager->resArray); // array_replace is used to preserve keys
1674 } else {
1675 $this->cols = $hookmanager->resArray;
1676 }
1677 }
1678}
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
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
getColumnContentXStart($colKey)
get column content X (abscissa) left position from column key
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.
defineColumnExtrafield($object, $outputlangs, $hidedetails=0)
Define Array Column Field for extrafields.
Class to manage hooks.
Perent class of the Proposal models.
Class to manage products or services.
Class to manage translations.
Class to manage Dolibarr users.
Class to generate the supplier proposals with the zenith model.
_pagehead(&$pdf, $object, $showaddress, $outputlangs)
Show top header of page.
_tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop=0, $hidebottom=0, $currency='')
Show table for lines.
_tableau_info(&$pdf, $object, $posy, $outputlangs)
Show miscellaneous information (payment mode, payment term, ...)
write_file($object, $outputlangs, $srctemplatepath='', $hidedetails=0, $hidedesc=0, $hideref=0)
Function to build pdf onto disk.
__construct($db)
Constructor.
_pagefoot(&$pdf, $object, $outputlangs, $hidefreetext=0)
Show footer of page.
_tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs)
Show total to pay.
defineColumnField($object, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0)
Define Array Column Field.
_tableau_versements(&$pdf, $object, $posy, $outputlangs)
Show payments table.
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...
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
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_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_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