dolibarr 23.0.3
pdf_zenith.modules.php
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-2025 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->getFullName($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 // Loop on each lines
489 $pageposbeforeprintlines = $pdf->getPage();
490 $pagenb = $pageposbeforeprintlines;
491 for ($i = 0; $i < $nblines; $i++) {
492 $curY = $nexY;
493 $pdf->SetFont('', '', $default_font_size - 1); // Into loop to work with multipage
494 $pdf->SetTextColor(0, 0, 0);
495
496 // Define size of image if we need it
497 $imglinesize = array();
498 if (!empty($realpatharray[$i])) {
499 $imglinesize = pdf_getSizeForImage($realpatharray[$i]);
500 }
501
502 $pdf->setTopMargin($tab_top_newpage);
503 $pdf->setPageOrientation('', true, $heightforfooter + $heightforfreetext + $heightforinfotot); // The only function to edit the bottom margin of current page to set it.
504 $pageposbefore = $pdf->getPage();
505
506 $showpricebeforepagebreak = 1;
507 $posYAfterImage = 0;
508 $posYAfterDescription = 0;
509
510 // We start with Photo of product line
511 if ($this->getColumnStatus('photo')) {
512 // We start with Photo of product line
513 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
514 $pdf->AddPage('', '', true);
515 if (!empty($tplidx)) {
516 $pdf->useTemplate($tplidx);
517 }
518 $pdf->setPage($pageposbefore + 1);
519
520 $curY = $tab_top_newpage;
521
522 // Allows data in the first page if description is long enough to break in multiples pages
523 if (getDolGlobalString('MAIN_PDF_DATA_ON_FIRST_PAGE')) {
524 $showpricebeforepagebreak = 1;
525 } else {
526 $showpricebeforepagebreak = 0;
527 }
528 }
529
530 if (!empty($this->cols['photo']) && isset($imglinesize['width']) && isset($imglinesize['height'])) {
531 $pdf->Image($realpatharray[$i], $this->getColumnContentXStart('photo'), $curY + 1, $imglinesize['width'], $imglinesize['height'], '', '', '', 2, 300); // Use 300 dpi
532 // $pdf->Image does not increase value return by getY, so we save it manually
533 $posYAfterImage = $curY + $imglinesize['height'];
534 }
535 }
536 // Description of product line
537 $curX = $this->posxdesc - 1;
538 $showpricebeforepagebreak = 1;
539
540 if ($this->getColumnStatus('desc')) {
541 $pdf->startTransaction();
542 $this->printColDescContent($pdf, $curY, 'desc', $object, $i, $outputlangs, $hideref, $hidedesc, 1);
543
544 $pageposafter = $pdf->getPage();
545 if ($pageposafter > $pageposbefore) { // There is a pagebreak
546 $pdf->rollbackTransaction(true);
547
548 $this->printColDescContent($pdf, $curY, 'desc', $object, $i, $outputlangs, $hideref, $hidedesc, 1);
549
550 $pageposafter = $pdf->getPage();
551 $posyafter = $pdf->GetY();
552 if ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforinfotot))) { // There is no space left for total+free text
553 if ($i == ($nblines - 1)) { // No more lines, and no space left to show total, so we create a new page
554 $pdf->AddPage('', '', true);
555 if (!empty($tplidx)) {
556 $pdf->useTemplate($tplidx);
557 }
558 //if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) $this->_pagehead($pdf, $object, 0, $outputlangs);
559 $pdf->setPage($pageposafter + 1);
560 }
561 } else {
562 // We found a page break
563 // Allows data in the first page if description is long enough to break in multiples pages
564 if (getDolGlobalString('MAIN_PDF_DATA_ON_FIRST_PAGE')) {
565 $showpricebeforepagebreak = 1;
566 } else {
567 $showpricebeforepagebreak = 0;
568 }
569 }
570 } else { // No pagebreak
571 $pdf->commitTransaction();
572 }
573 $posYAfterDescription = $pdf->GetY();
574 }
575
576 $nexY = $pdf->GetY();
577 $pageposafter = $pdf->getPage();
578 $pdf->setPage($pageposbefore);
579 $pdf->setTopMargin($this->marge_haute);
580 $pdf->setPageOrientation('', true, 0); // The only function to edit the bottom margin of current page to set it.
581
582 // We suppose that a too long description is moved completely on next page
583 if ($pageposafter > $pageposbefore && empty($showpricebeforepagebreak)) {
584 $pdf->setPage($pageposafter);
585 $curY = $tab_top_newpage;
586 }
587
588 $pdf->SetFont('', '', $default_font_size - 1); // On repositionne la police par default
589
590 // VAT Rate
591 if ($this->getColumnStatus('vat')) {
592 $vat_rate = pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails);
593 $this->printStdColumnContent($pdf, $curY, 'vat', $vat_rate);
594 $nexY = max($pdf->GetY(), $nexY);
595 }
596
597 // Unit price before discount
598 if ($this->getColumnStatus('subprice')) {
599 $up_excl_tax = pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails);
600 $this->printStdColumnContent($pdf, $curY, 'subprice', $up_excl_tax);
601 $nexY = max($pdf->GetY(), $nexY);
602 }
603
604 // Quantity
605 // Enough for 6 chars
606 if ($this->getColumnStatus('qty')) {
607 $qty = pdf_getlineqty($object, $i, $outputlangs, $hidedetails);
608 $this->printStdColumnContent($pdf, $curY, 'qty', $qty);
609 $nexY = max($pdf->GetY(), $nexY);
610 }
611
612
613 // Unit
614 if ($this->getColumnStatus('unit')) {
615 $unit = pdf_getlineunit($object, $i, $outputlangs, $hidedetails);
616 $this->printStdColumnContent($pdf, $curY, 'unit', $unit);
617 $nexY = max($pdf->GetY(), $nexY);
618 }
619
620 // Discount on line
621 if ($this->getColumnStatus('discount') && $object->lines[$i]->remise_percent) {
622 $remise_percent = pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails);
623 $this->printStdColumnContent($pdf, $curY, 'discount', $remise_percent);
624 $nexY = max($pdf->GetY(), $nexY);
625 }
626
627 // Total HT line
628 if ($this->getColumnStatus('totalexcltax')) {
629 $total_excl_tax = pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails);
630 $this->printStdColumnContent($pdf, $curY, 'totalexcltax', $total_excl_tax);
631 $nexY = max($pdf->GetY(), $nexY);
632 }
633
634 // Extrafields
635 if (!empty($object->lines[$i]->array_options)) {
636 foreach ($object->lines[$i]->array_options as $extrafieldColKey => $extrafieldValue) {
637 if ($this->getColumnStatus($extrafieldColKey)) {
638 $extrafieldValue = $this->getExtrafieldContent($object->lines[$i], $extrafieldColKey, $outputlangs);
639 $this->printStdColumnContent($pdf, $curY, $extrafieldColKey, $extrafieldValue);
640 $nexY = max($pdf->GetY(), $nexY);
641 }
642 }
643 }
644
645 $parameters = array(
646 'object' => $object,
647 'i' => $i,
648 'pdf' => & $pdf,
649 'curY' => & $curY,
650 'nexY' => & $nexY,
651 'outputlangs' => $outputlangs,
652 'hidedetails' => $hidedetails
653 );
654 $reshook = $hookmanager->executeHooks('printPDFline', $parameters, $this); // Note that $object may have been modified by hook
655
656
657 // Collecte des totaux par valeur de tva dans $this->tva["taux"]=total_tva
658 if (isModEnabled("multicurrency") && $object->multicurrency_tx != 1) {
659 $tvaligne = $object->lines[$i]->multicurrency_total_tva;
660 } else {
661 $tvaligne = $object->lines[$i]->total_tva;
662 }
663
664 $localtax1ligne = $object->lines[$i]->total_localtax1;
665 $localtax2ligne = $object->lines[$i]->total_localtax2;
666 $localtax1_rate = $object->lines[$i]->localtax1_tx;
667 $localtax2_rate = $object->lines[$i]->localtax2_tx;
668 $localtax1_type = $object->lines[$i]->localtax1_type;
669 $localtax2_type = $object->lines[$i]->localtax2_type;
670
671 // TODO remise_percent is an obsolete field for object parent
672 /*if (!empty($object->remise_percent)) {
673 $tvaligne -= ($tvaligne * $object->remise_percent) / 100;
674 }
675 if (!empty($object->remise_percent)) {
676 $localtax1ligne -= ($localtax1ligne * $object->remise_percent) / 100;
677 }
678 if (!empty($object->remise_percent)) {
679 $localtax2ligne -= ($localtax2ligne * $object->remise_percent) / 100;
680 }*/
681
682 $vatrate = (string) $object->lines[$i]->tva_tx;
683
684 // Retrieve type from database for backward compatibility with old records
685 if ((!isset($localtax1_type) || $localtax1_type == '' || !isset($localtax2_type) || $localtax2_type == '') // if tax type not defined
686 && (!empty($localtax1_rate) || !empty($localtax2_rate))) { // and there is local tax
687 $localtaxtmp_array = getLocalTaxesFromRate($vatrate, 0, $mysoc, $object->thirdparty);
688 $localtax1_type = isset($localtaxtmp_array[0]) ? $localtaxtmp_array[0] : '';
689 $localtax2_type = isset($localtaxtmp_array[2]) ? $localtaxtmp_array[2] : '';
690 }
691
692 // retrieve global local tax
693 if ($localtax1_type && $localtax1ligne != 0) {
694 if (empty($this->localtax1[$localtax1_type][$localtax1_rate])) {
695 $this->localtax1[$localtax1_type][$localtax1_rate] = $localtax1ligne;
696 } else {
697 $this->localtax1[$localtax1_type][$localtax1_rate] += $localtax1ligne;
698 }
699 }
700 if ($localtax2_type && $localtax2ligne != 0) {
701 if (empty($this->localtax2[$localtax2_type][$localtax2_rate])) {
702 $this->localtax2[$localtax2_type][$localtax2_rate] = (float) $localtax2ligne;
703 } else {
704 $this->localtax2[$localtax2_type][$localtax2_rate] += $localtax2ligne;
705 }
706 }
707
708 if (($object->lines[$i]->info_bits & 0x01) == 0x01) {
709 $vatrate .= '*';
710 }
711
712 // Fill $this->tva and $this->tva_array
713 if (!isset($this->tva[$vatrate])) {
714 $this->tva[$vatrate] = 0;
715 }
716 $this->tva[$vatrate] += $tvaligne;
717 $vatcode = $object->lines[$i]->vat_src_code;
718 if (empty($this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'])) {
719 $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'] = 0;
720 }
721 $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')] = array('vatrate' => $vatrate, 'vatcode' => $vatcode, 'amount' => $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'] + $tvaligne);
722
723 if ($posYAfterImage > $posYAfterDescription) {
724 $nexY = $posYAfterImage;
725 }
726
727 // Add line
728 if (getDolGlobalString('MAIN_PDF_DASH_BETWEEN_LINES') && $i < ($nblines - 1)) {
729 $pdf->setPage($pageposafter);
730 $pdf->SetLineStyle(array('dash' => '1,1', 'color' => array(80, 80, 80)));
731 //$pdf->SetDrawColor(190,190,200);
732 $pdf->line($this->marge_gauche, $nexY, $this->page_largeur - $this->marge_droite, $nexY);
733 $pdf->SetLineStyle(array('dash' => 0));
734 }
735
736 // Detect if some page were added automatically and output _tableau for past pages
737 while ($pagenb < $pageposafter) {
738 $pdf->setPage($pagenb);
739 if ($pagenb == $pageposbeforeprintlines) {
740 $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, $hidetop, 1, $object->multicurrency_code);
741 } else {
742 $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code);
743 }
744 $this->_pagefoot($pdf, $object, $outputlangs, 1);
745 $pagenb++;
746 $pdf->setPage($pagenb);
747 $pdf->setPageOrientation('', true, 0); // The only function to edit the bottom margin of current page to set it.
748 if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
749 $this->_pagehead($pdf, $object, 0, $outputlangs);
750 }
751 if (!empty($tplidx)) {
752 $pdf->useTemplate($tplidx);
753 }
754 }
755 if (isset($object->lines[$i + 1]->pagebreak) && $object->lines[$i + 1]->pagebreak) { // @phan-suppress-current-line PhanUndeclaredProperty
756 if ($pagenb == $pageposafter) {
757 $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, $hidetop, 1, $object->multicurrency_code);
758 } else {
759 $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code);
760 }
761 $this->_pagefoot($pdf, $object, $outputlangs, 1);
762 // New page
763 $pdf->AddPage();
764 if (!empty($tplidx)) {
765 $pdf->useTemplate($tplidx);
766 }
767 $pagenb++;
768 if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
769 $this->_pagehead($pdf, $object, 0, $outputlangs);
770 }
771 }
772 }
773
774 // Show square
775 if ($pagenb == $pageposbeforeprintlines) {
776 $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, $hidetop, 0, $object->multicurrency_code);
777 $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
778 } else {
779 $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 1, 0, $object->multicurrency_code);
780 $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
781 }
782
783 // Affiche zone infos
784 $posy = $this->_tableau_info($pdf, $object, $bottomlasttab, $outputlangs);
785
786 // Affiche zone totaux
787 $posy = $this->_tableau_tot($pdf, $object, $deja_regle, $bottomlasttab, $outputlangs);
788
789 // Affiche zone versements
790 if ($deja_regle || $amount_credit_notes_included || $amount_deposits_included) {
791 $posy = $this->_tableau_versements($pdf, $object, $posy, $outputlangs);
792 }
793
794 // Pied de page
795 $this->_pagefoot($pdf, $object, $outputlangs);
796 if (method_exists($pdf, 'AliasNbPages')) {
797 $pdf->AliasNbPages(); // @phan-suppress-current-line PhanUndeclaredMethod
798 }
799
800 $pdf->Close();
801
802 $pdf->Output($file, 'F');
803
804 // Add pdfgeneration hook
805 $hookmanager->initHooks(array('pdfgeneration'));
806 $parameters = array('file' => $file, 'object' => $object, 'outputlangs' => $outputlangs);
807 global $action;
808 $reshook = $hookmanager->executeHooks('afterPDFCreation', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
809 $this->warnings = $hookmanager->warnings;
810 if ($reshook < 0) {
811 $this->error = $hookmanager->error;
812 $this->errors = $hookmanager->errors;
813 dolChmod($file);
814 return -1;
815 }
816
817 dolChmod($file);
818
819 $this->result = array('fullpath' => $file);
820
821 return 1; // No error
822 } else {
823 $this->error = $langs->trans("ErrorCanNotCreateDir", $dir);
824 return 0;
825 }
826 } else {
827 $this->error = $langs->trans("ErrorConstantNotDefined", "SUPPLIER_OUTPUTDIR");
828 return 0;
829 }
830 }
831
832 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
833 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
843 protected function _tableau_versements(&$pdf, $object, $posy, $outputlangs)
844 {
845 // phpcs:enable
846 return 1;
847 }
848
849 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
850 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
860 protected function _tableau_info(&$pdf, $object, $posy, $outputlangs)
861 {
862 // phpcs:enable
863 global $conf, $mysoc;
864 $default_font_size = pdf_getPDFFontSize($outputlangs);
865
866 $diffsizetitle = getDolGlobalInt('PDF_DIFFSIZE_TITLE', 3);
867
868 // If France, show VAT mention if not applicable
869 if ($this->emetteur->country_code == 'FR' && empty($mysoc->tva_assuj)) {
870 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
871 $pdf->SetXY($this->marge_gauche, $posy);
872 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("VATIsNotUsedForInvoice"), 0, 'L', false);
873
874 $posy = $pdf->GetY() + 4;
875 }
876
877 $posxval = 52;
878
879 // Show payments conditions
880 if (!empty($object->cond_reglement_code) || $object->cond_reglement) {
881 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
882 $pdf->SetXY($this->marge_gauche, $posy);
883 $titre = $outputlangs->transnoentities("PaymentConditions").':';
884 $pdf->MultiCell(80, 4, $titre, 0, 'L');
885
886 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
887 $pdf->SetXY($posxval, $posy);
888 $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);
889 $lib_condition_paiement = str_replace('\n', "\n", $lib_condition_paiement);
890 if ($object->deposit_percent > 0) {
891 $lib_condition_paiement = str_replace('__DEPOSIT_PERCENT__', $object->deposit_percent, $lib_condition_paiement);
892 }
893 $pdf->MultiCell(80, 4, $lib_condition_paiement, 0, 'L');
894
895 $posy = $pdf->GetY() + 3;
896 }
897
898 // Show payment mode
899 if (!empty($object->mode_reglement_code)) {
900 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
901 $pdf->SetXY($this->marge_gauche, $posy);
902 $titre = $outputlangs->transnoentities("PaymentMode").':';
903 $pdf->MultiCell(80, 5, $titre, 0, 'L');
904
905 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
906 $pdf->SetXY($posxval, $posy);
907 $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);
908 $pdf->MultiCell(80, 5, $lib_mode_reg, 0, 'L');
909
910 $posy = $pdf->GetY() + 2;
911 }
912
913
914 return $posy;
915 }
916
917 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
918 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
929 protected function _tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs)
930 {
931 // phpcs:enable
932 global $conf, $mysoc;
933
934 $default_font_size = pdf_getPDFFontSize($outputlangs);
935
936 $tab2_top = $posy;
937 $tab2_hl = 4;
938 $pdf->SetFont('', '', $default_font_size - 1);
939
940 // Tableau total
941 $col1x = 120;
942 $col2x = 170;
943 if ($this->page_largeur < 210) { // To work with US executive format
944 $col2x -= 20;
945 }
946 $largcol2 = ($this->page_largeur - $this->marge_droite - $col2x);
947
948 $useborder = 0;
949 $index = 0;
950
951 // Total HT
952 $pdf->SetFillColor(255, 255, 255);
953 $pdf->SetXY($col1x, $tab2_top);
954 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalHT"), 0, 'L', true);
955
956 $total_ht = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? $object->multicurrency_total_ht : $object->total_ht);
957 $pdf->SetXY($col2x, $tab2_top);
958 $pdf->MultiCell($largcol2, $tab2_hl, price($total_ht + (!empty($object->remise) ? $object->remise : 0)), 0, 'R', true);
959
960 // Show VAT by rates and total
961 $pdf->SetFillColor(248, 248, 248);
962
963 $this->atleastoneratenotnull = 0;
964 foreach ($this->tva as $tvakey => $tvaval) {
965 if ($tvakey > 0) { // On affiche pas taux 0
966 $this->atleastoneratenotnull++;
967
968 $index++;
969 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
970
971 $tvacompl = '';
972
973 if (preg_match('/\*/', $tvakey)) {
974 $tvakey = str_replace('*', '', $tvakey);
975 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
976 }
977
978 $totalvat = $outputlangs->transcountrynoentities("TotalVAT", $mysoc->country_code).' ';
979 $totalvat .= vatrate($tvakey, true).$tvacompl;
980 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
981
982 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
983 $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval), 0, 'R', true);
984 }
985 }
986 if (!$this->atleastoneratenotnull) { // If no vat at all
987 $index++;
988 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
989 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transcountrynoentities("TotalVAT", $mysoc->country_code), 0, 'L', true);
990
991 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
992 $pdf->MultiCell($largcol2, $tab2_hl, price($object->total_tva), 0, 'R', true);
993
994 // Total LocalTax1
995 if (getDolGlobalString('FACTURE_LOCAL_TAX1_OPTION') == 'localtax1on' && $object->total_localtax1 > 0) {
996 $index++;
997 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
998 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transcountrynoentities("TotalLT1", $mysoc->country_code), 0, 'L', true);
999 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1000 $pdf->MultiCell($largcol2, $tab2_hl, price($object->total_localtax1), $useborder, 'R', true);
1001 }
1002
1003 // Total LocalTax2
1004 if (getDolGlobalString('FACTURE_LOCAL_TAX2_OPTION') == 'localtax2on' && $object->total_localtax2 > 0) {
1005 $index++;
1006 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1007 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transcountrynoentities("TotalLT2", $mysoc->country_code), 0, 'L', true);
1008 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1009 $pdf->MultiCell($largcol2, $tab2_hl, price($object->total_localtax2), $useborder, 'R', true);
1010 }
1011 } else {
1012 //if (getDolGlobalString('FACTURE_LOCAL_TAX1_OPTION') && getDolGlobalString('FACTURE_LOCAL_TAX1_OPTION') == 'localtax1on')
1013 //{
1014 //Local tax 1
1015 foreach ($this->localtax1 as $localtax_type => $localtax_rate) {
1016 if (in_array((string) $localtax_type, array('2', '4', '6'))) {
1017 continue;
1018 }
1019
1020 foreach ($localtax_rate as $tvakey => $tvaval) {
1021 if ($tvakey != 0) { // On affiche pas taux 0
1022 //$this->atleastoneratenotnull++;
1023
1024 $index++;
1025 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1026
1027 $tvacompl = '';
1028 if (preg_match('/\*/', $tvakey)) {
1029 $tvakey = str_replace('*', '', $tvakey);
1030 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1031 }
1032 $totalvat = $outputlangs->transcountrynoentities("TotalLT1", $mysoc->country_code).' ';
1033 $totalvat .= vatrate((string) abs((float) $tvakey), true).$tvacompl;
1034 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1035
1036 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1037 $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', true);
1038 }
1039 }
1040 }
1041
1042 //if (getDolGlobalString('FACTURE_LOCAL_TAX2_OPTION') && getDolGlobalString('FACTURE_LOCAL_TAX2_OPTION') == 'localtax2on')
1043 //{
1044 //Local tax 2
1045 foreach ($this->localtax2 as $localtax_type => $localtax_rate) {
1046 if (in_array((string) $localtax_type, array('2', '4', '6'))) {
1047 continue;
1048 }
1049
1050 foreach ($localtax_rate as $tvakey => $tvaval) {
1051 if ($tvakey != 0) { // On affiche pas taux 0
1052 //$this->atleastoneratenotnull++;
1053
1054 $index++;
1055 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1056
1057 $tvacompl = '';
1058 if (preg_match('/\*/', $tvakey)) {
1059 $tvakey = str_replace('*', '', $tvakey);
1060 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1061 }
1062 $totalvat = $outputlangs->transcountrynoentities("TotalLT2", $mysoc->country_code).' ';
1063 $totalvat .= vatrate((string) abs((float) $tvakey), true).$tvacompl;
1064 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1065
1066 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1067 $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval), 0, 'R', true);
1068 }
1069 }
1070 }
1071 }
1072
1073 // Total TTC
1074 $index++;
1075 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1076 $pdf->SetTextColor(0, 0, 60);
1077 $pdf->SetFillColor(224, 224, 224);
1078 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalTTC"), $useborder, 'L', true);
1079
1080 $total_ttc = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1) ? $object->multicurrency_total_ttc : $object->total_ttc;
1081 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1082 $pdf->MultiCell($largcol2, $tab2_hl, price($total_ttc), $useborder, 'R', true);
1083 $pdf->SetFont('', '', $default_font_size - 1);
1084 $pdf->SetTextColor(0, 0, 0);
1085
1086 $creditnoteamount = 0;
1087 $depositsamount = 0;
1088 //$creditnoteamount=$object->getSumCreditNotesUsed();
1089 //$depositsamount=$object->getSumDepositsUsed();
1090 //print "x".$creditnoteamount."-".$depositsamount;exit;
1091 $resteapayer = price2num($total_ttc - $deja_regle - $creditnoteamount - $depositsamount, 'MT');
1092 if (!empty($object->paye)) {
1093 $resteapayer = 0;
1094 }
1095
1096 if ($deja_regle > 0) {
1097 // Already paid + Deposits
1098 $index++;
1099
1100 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1101 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("AlreadyPaid"), 0, 'L', false);
1102 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1103 $pdf->MultiCell($largcol2, $tab2_hl, price($deja_regle), 0, 'R', false);
1104
1105 $index++;
1106 $pdf->SetTextColor(0, 0, 60);
1107 $pdf->SetFillColor(224, 224, 224);
1108 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1109 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("RemainderToPay"), $useborder, 'L', true);
1110
1111 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1112 $pdf->MultiCell($largcol2, $tab2_hl, price($resteapayer), $useborder, 'R', true);
1113
1114 $pdf->SetFont('', '', $default_font_size - 1);
1115 $pdf->SetTextColor(0, 0, 0);
1116 }
1117
1118 $index++;
1119 return ($tab2_top + ($tab2_hl * $index));
1120 }
1121
1122 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1136 protected function _tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop = 0, $hidebottom = 0, $currency = '')
1137 {
1138 global $conf;
1139
1140 // Force to disable hidetop and hidebottom
1141 $hidebottom = 0;
1142 if ($hidetop) {
1143 $hidetop = -1;
1144 }
1145
1146 $currency = !empty($currency) ? $currency : $conf->currency;
1147 $default_font_size = pdf_getPDFFontSize($outputlangs);
1148
1149 // Amount in (at tab_top - 1)
1150 $pdf->SetTextColor(0, 0, 0);
1151 $pdf->SetFont('', '', $default_font_size - 2);
1152
1153 if (empty($hidetop)) {
1154 $titre = $outputlangs->transnoentities("AmountInCurrency", $outputlangs->transnoentitiesnoconv("Currency".$currency));
1155 $pdf->SetXY($this->page_largeur - $this->marge_droite - ($pdf->GetStringWidth($titre) + 3), $tab_top - 4);
1156 $pdf->MultiCell(($pdf->GetStringWidth($titre) + 3), 2, $titre);
1157
1158 //$conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR='230,230,230';
1159 if (getDolGlobalString('MAIN_PDF_TITLE_BACKGROUND_COLOR')) {
1160 $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')));
1161 }
1162 }
1163
1164 $pdf->SetDrawColor(128, 128, 128);
1165 $pdf->SetFont('', '', $default_font_size - 1);
1166
1167 // Output Rect
1168 $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
1169
1170 $this->pdfTabTitles($pdf, $tab_top, $tab_height, $outputlangs, $hidetop);
1171
1172 if (empty($hidetop)) {
1173 $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
1174 }
1175 }
1176
1177 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1187 protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs)
1188 {
1189 global $langs, $conf, $mysoc;
1190
1191 $ltrdirection = 'L';
1192 if ($outputlangs->trans("DIRECTION") == 'rtl') {
1193 $ltrdirection = 'R';
1194 }
1195
1196 // Load translation files required by the page
1197 $outputlangs->loadLangs(array("main", "supplier_proposal", "companies", "bills", "sendings"));
1198
1199 $default_font_size = pdf_getPDFFontSize($outputlangs);
1200
1201 // Do not add the BACKGROUND as this is for suppliers
1202 //pdf_pagehead($pdf,$outputlangs,$this->page_hauteur);
1203
1204 //Affiche le filigrane brouillon - Print Draft Watermark
1205 /*if($object->statut==0 && getDolGlobalString('COMMANDE_DRAFT_WATERMARK'))
1206 {
1207 pdf_watermark($pdf,$outputlangs,$this->page_hauteur,$this->page_largeur,'mm',getDolGlobalString('COMMANDE_DRAFT_WATERMARK'));
1208 }*/
1209 //Print content
1210
1211 $pdf->SetTextColor(0, 0, 60);
1212 $pdf->SetFont('', 'B', $default_font_size + 3);
1213
1214 $posx = $this->page_largeur - $this->marge_droite - 100;
1215 $posy = $this->marge_haute;
1216
1217 $pdf->SetXY($this->marge_gauche, $posy);
1218
1219 // Logo
1220 if (!getDolGlobalInt('PDF_DISABLE_MYCOMPANY_LOGO')) {
1221 if ($this->emetteur->logo) {
1222 $logodir = $conf->mycompany->dir_output;
1223 if (!empty($conf->mycompany->multidir_output[$object->entity ?? $conf->entity])) {
1224 $logodir = $conf->mycompany->multidir_output[$object->entity ?? $conf->entity];
1225 }
1226 if (!getDolGlobalInt('MAIN_PDF_USE_LARGE_LOGO')) {
1227 $logo = $logodir.'/logos/thumbs/'.$this->emetteur->logo_small;
1228 } else {
1229 $logo = $logodir.'/logos/'.$this->emetteur->logo;
1230 }
1231 if (is_readable($logo)) {
1232 $height = pdf_getHeightForLogo($logo);
1233 $pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto)
1234 } else {
1235 $pdf->SetTextColor(200, 0, 0);
1236 $pdf->SetFont('', 'B', $default_font_size - 2);
1237 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound", $logo), 0, 'L');
1238 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorGoToGlobalSetup"), 0, 'L');
1239 }
1240 } else {
1241 $text = $this->emetteur->name;
1242 $pdf->MultiCell(100, 4, $outputlangs->convToOutputCharset($text), 0, $ltrdirection);
1243 }
1244 }
1245
1246 $pdf->SetFont('', 'B', $default_font_size + 3);
1247 $pdf->SetXY($posx, $posy);
1248 $pdf->SetTextColor(0, 0, 60);
1249 $title = $outputlangs->transnoentities("SupplierProposal")." ".$outputlangs->convToOutputCharset($object->ref);
1250 $pdf->MultiCell(100, 3, $title, '', 'R');
1251 $posy += 1;
1252
1253 if ($object->ref_supplier) {
1254 $posy += 4;
1255 $pdf->SetFont('', 'B', $default_font_size);
1256 $pdf->SetXY($posx, $posy);
1257 $pdf->SetTextColor(0, 0, 60);
1258 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("RefSupplier")." : ".$outputlangs->convToOutputCharset($object->ref_supplier), '', 'R');
1259 $posy += 1;
1260 }
1261
1262 $pdf->SetFont('', '', $default_font_size - 1);
1263
1264 if (getDolGlobalString('PDF_SHOW_PROJECT_TITLE')) {
1265 $object->fetchProject();
1266 if (!empty($object->project->ref)) {
1267 $posy += 3;
1268 $pdf->SetXY($posx, $posy);
1269 $pdf->SetTextColor(0, 0, 60);
1270 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Project")." : ".(empty($object->project->title) ? '' : $object->project->title), '', 'R');
1271 }
1272 }
1273
1274 if (getDolGlobalString('PDF_SHOW_PROJECT')) {
1275 $object->fetchProject();
1276 if (!empty($object->project->ref)) {
1277 $outputlangs->load("projects");
1278 $posy += 4;
1279 $pdf->SetXY($posx, $posy);
1280 $langs->load("projects");
1281 $pdf->SetTextColor(0, 0, 60);
1282 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Project")." : ".(empty($object->project->ref) ? '' : $object->project->ref), '', 'R');
1283 }
1284 }
1285
1286 if (!empty($object->date)) {
1287 $posy += 5;
1288 $pdf->SetXY($posx, $posy);
1289 $pdf->SetTextColor(0, 0, 60);
1290 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Date")." : ".dol_print_date($object->date, "day", false, $outputlangs, true), '', 'R');
1291 } else {
1292 $posy += 5;
1293 $pdf->SetXY($posx, $posy);
1294 $pdf->SetTextColor(255, 0, 0);
1295 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Draft"), '', 'R');
1296 }
1297
1298 $pdf->SetTextColor(0, 0, 60);
1299 $usehourmin = 'day';
1300 if (getDolGlobalString('SUPPLIER_PROPOSAL_USE_HOUR_FOR_DELIVERY_DATE')) {
1301 $usehourmin = 'dayhour';
1302 }
1303 if (!empty($object->delivery_date)) {
1304 $posy += 4;
1305 $pdf->SetXY($posx - 90, $posy);
1306 $pdf->MultiCell(190, 3, $outputlangs->transnoentities("DateDeliveryPlanned")." : ".dol_print_date($object->delivery_date, $usehourmin, false, $outputlangs, true), '', 'R');
1307 }
1308
1309 if ($object->thirdparty->code_fournisseur) {
1310 $posy += 4;
1311 $pdf->SetXY($posx, $posy);
1312 $pdf->SetTextColor(0, 0, 60);
1313 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("SupplierCode")." : ".$outputlangs->transnoentities($object->thirdparty->code_fournisseur), '', 'R');
1314 }
1315
1316 // Get contact
1317 if (getDolGlobalString('DOC_SHOW_FIRST_SALES_REP')) {
1318 $arrayidcontact = $object->getIdContact('internal', 'SALESREPFOLL');
1319
1320 if (is_array($arrayidcontact) && count($arrayidcontact) > 0) {
1321 $usertmp = new User($this->db);
1322 $usertmp->fetch($arrayidcontact[0]);
1323 $posy += 4;
1324 $pdf->SetXY($posx, $posy);
1325 $pdf->SetTextColor(0, 0, 60);
1326 $pdf->MultiCell(100, 3, $langs->trans("BuyerName")." : ".$usertmp->getFullName($langs), '', 'R');
1327 }
1328 }
1329
1330 $posy += 1;
1331 $pdf->SetTextColor(0, 0, 60);
1332
1333 $top_shift = 0;
1334 // Show list of linked objects
1335 $current_y = $pdf->getY();
1336 $posy = pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, 100, 3, 'R', $default_font_size);
1337 if ($current_y < $pdf->getY()) {
1338 $top_shift = $pdf->getY() - $current_y;
1339 }
1340
1341 if ($showaddress) {
1342 // Sender properties
1343 $carac_emetteur = '';
1344 // Add internal contact of object if defined
1345 $arrayidcontact = $object->getIdContact('internal', 'SALESREPFOLL');
1346 if (count($arrayidcontact) > 0) {
1347 $object->fetch_user($arrayidcontact[0]);
1348 $labelbeforecontactname = ($outputlangs->transnoentities("FromContactName") != 'FromContactName' ? $outputlangs->transnoentities("FromContactName") : $outputlangs->transnoentities("Name"));
1349 $carac_emetteur .= ($carac_emetteur ? "\n" : '').$labelbeforecontactname.": ".$outputlangs->convToOutputCharset($object->user->getFullName($outputlangs));
1350 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') || getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ' (' : '';
1351 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') && !empty($object->user->office_phone)) ? $object->user->office_phone : '';
1352 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') && getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ', ' : '';
1353 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT') && !empty($object->user->email)) ? $object->user->email : '';
1354 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') || getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ')' : '';
1355 $carac_emetteur .= "\n";
1356 }
1357
1358 $carac_emetteur .= pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, '', 0, 'source', $object);
1359
1360 // Show sender
1361 $posy = 42 + $top_shift;
1362 $posx = $this->marge_gauche;
1363 if (getDolGlobalString('MAIN_INVERT_SENDER_RECIPIENT')) {
1364 $posx = $this->page_largeur - $this->marge_droite - 80;
1365 }
1366 $hautcadre = 40;
1367
1368 // Show sender frame
1369 $pdf->SetTextColor(0, 0, 0);
1370 $pdf->SetFont('', '', $default_font_size - 2);
1371 $pdf->SetXY($posx, $posy - 5);
1372 $pdf->MultiCell(80, 5, $outputlangs->transnoentities("BillFrom"), 0, $ltrdirection);
1373 $pdf->SetXY($posx, $posy);
1374 $pdf->SetFillColor(230, 230, 230);
1375 $pdf->RoundedRect($posx, $posy, 82, $hautcadre, $this->corner_radius, '1234', 'F');
1376 $pdf->SetTextColor(0, 0, 60);
1377
1378 // Show sender name
1379 $pdf->SetXY($posx + 2, $posy + 3);
1380 $pdf->SetFont('', 'B', $default_font_size);
1381 $pdf->MultiCell(80, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, $ltrdirection);
1382 $posy = $pdf->getY();
1383
1384 // Show sender information
1385 $pdf->SetXY($posx + 2, $posy);
1386 $pdf->SetFont('', '', $default_font_size - 1);
1387 $pdf->MultiCell(80, 4, $carac_emetteur, 0, $ltrdirection);
1388
1389
1390
1391 // If SUPPLIER/SERVICE contact defined on proposal, we use it. Note: Even if this is a supplier object, the code for external contact that follow order is 'SERVICE'
1392 $usecontact = false;
1393 if (!getDolGlobalInt('SUPPLIER_PROPOSAL_ADD_BILLING_CONTACT')) {
1394 $arrayidcontact = $object->getIdContact('external', 'SERVICE');
1395 } else {
1396 $arrayidcontact = array_merge($object->getIdContact('external', 'SERVICE'), $object->getIdContact('external', 'BILLING'));
1397 }
1398 if (is_array($arrayidcontact) && count($arrayidcontact) > 0) {
1399 $usecontact = true;
1400 $result = $object->fetch_contact($arrayidcontact[0]);
1401 }
1402
1403 // Recipient name
1404 if ($usecontact && ($object->contact->socid != $object->thirdparty->id && (!isset($conf->global->MAIN_USE_COMPANY_NAME_OF_CONTACT) || getDolGlobalString('MAIN_USE_COMPANY_NAME_OF_CONTACT')))) {
1405 $thirdparty = $object->contact;
1406 } else {
1407 $thirdparty = $object->thirdparty;
1408 }
1409
1410 $carac_client_name = pdfBuildThirdpartyName($thirdparty, $outputlangs);
1411
1412 $carac_client = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, ($usecontact ? $object->contact : ''), ($usecontact ? 1 : 0), 'target', $object);
1413
1414 // Show recipient
1415 $widthrecbox = 100;
1416 if ($this->page_largeur < 210) {
1417 $widthrecbox = 84; // To work with US executive format
1418 }
1419 $posy = 42 + $top_shift;
1420 $posx = $this->page_largeur - $this->marge_droite - $widthrecbox;
1421 if (getDolGlobalString('MAIN_INVERT_SENDER_RECIPIENT')) {
1422 $posx = $this->marge_gauche;
1423 }
1424
1425 // Show recipient frame
1426 $pdf->SetTextColor(0, 0, 0);
1427 $pdf->SetFont('', '', $default_font_size - 2);
1428 $pdf->SetXY($posx + 2, $posy - 5);
1429 $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillTo"), 0, $ltrdirection);
1430 $pdf->RoundedRect($posx, $posy, $widthrecbox, $hautcadre, $this->corner_radius, '1234', 'D');
1431
1432 // Show recipient name
1433 $pdf->SetXY($posx + 2, $posy + 3);
1434 $pdf->SetFont('', 'B', $default_font_size);
1435 // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
1436 $pdf->MultiCell($widthrecbox, 4, $carac_client_name, 0, $ltrdirection);
1437
1438 $posy = $pdf->getY();
1439
1440 // Show recipient information
1441 $pdf->SetFont('', '', $default_font_size - 1);
1442 $pdf->SetXY($posx + 2, $posy);
1443 // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
1444 $pdf->MultiCell($widthrecbox, 4, $carac_client, 0, $ltrdirection);
1445 }
1446
1447 return $top_shift;
1448 }
1449
1450 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1460 protected function _pagefoot(&$pdf, $object, $outputlangs, $hidefreetext = 0)
1461 {
1462 $showdetails = getDolGlobalInt('MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS', 0);
1463 return pdf_pagefoot($pdf, $outputlangs, 'SUPPLIER_PROPOSAL_FREE_TEXT', $this->emetteur, $this->marge_basse, $this->marge_gauche, $this->page_hauteur, $object, $showdetails, $hidefreetext);
1464 }
1465
1466
1467
1478 public function defineColumnField($object, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0)
1479 {
1480 global $hookmanager;
1481
1482 // Default field style for content
1483 $this->defaultContentsFieldsStyle = array(
1484 'align' => 'R', // R,C,L
1485 'padding' => array(1, 0.5, 1, 0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1486 );
1487
1488 // Default field style for content
1489 $this->defaultTitlesFieldsStyle = array(
1490 'align' => 'C', // R,C,L
1491 'padding' => array(0.5, 0, 0.5, 0), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1492 );
1493
1494 $rank = 0; // do not use negative rank
1495 $this->cols['desc'] = array(
1496 'rank' => $rank,
1497 'width' => false, // only for desc
1498 'status' => true,
1499 'title' => array(
1500 'textkey' => 'Designation', // use lang key is useful in some case with module
1501 'align' => 'L',
1502 // 'textkey' => 'yourLangKey', // if there is no label, yourLangKey will be translated to replace label
1503 // 'label' => ' ', // the final label
1504 'padding' => array(0.5, 0.5, 0.5, 0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1505 ),
1506 'content' => array(
1507 'align' => 'L',
1508 'padding' => array(1, 0.5, 1, 1.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1509 ),
1510 );
1511
1512 $rank += 10;
1513 $this->cols['photo'] = array(
1514 'rank' => $rank,
1515 'width' => getDolGlobalInt('MAIN_DOCUMENTS_WITH_PICTURE_WIDTH', 20), // in mm
1516 'status' => false,
1517 'title' => array(
1518 'textkey' => 'Photo',
1519 'label' => ' '
1520 ),
1521 'content' => array(
1522 'padding' => array(0, 0, 0, 0), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1523 ),
1524 'border-left' => false, // remove left line separator
1525 );
1526
1527 if (getDolGlobalString('MAIN_GENERATE_SUPPLIER_PROPOSAL_WITH_PICTURE')) {
1528 $this->cols['photo']['status'] = true;
1529 }
1530
1531
1532 $rank += 10;
1533 $this->cols['vat'] = array(
1534 'rank' => $rank,
1535 'status' => false,
1536 'width' => 16, // in mm
1537 'title' => array(
1538 'textkey' => 'VAT'
1539 ),
1540 'border-left' => true, // add left line separator
1541 );
1542
1543 if (!getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT') && !getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_COLUMN')) {
1544 $this->cols['vat']['status'] = true;
1545 }
1546
1547 $rank += 10;
1548 $this->cols['subprice'] = array(
1549 'rank' => $rank,
1550 'width' => 19, // in mm
1551 'status' => false,
1552 'title' => array(
1553 'textkey' => 'PriceUHT'
1554 ),
1555 'border-left' => true, // add left line separator
1556 );
1557
1558 if (!getDolGlobalString('MAIN_GENERATE_DOCUMENTS_SUPPLIER_PROPOSAL_WITHOUT_UNIT_PRICE')) {
1559 $this->cols['subprice']['status'] = true;
1560 }
1561
1562 $rank += 10;
1563 $this->cols['qty'] = array(
1564 'rank' => $rank,
1565 'width' => 16, // in mm
1566 'status' => true,
1567 'title' => array(
1568 'textkey' => 'Qty'
1569 ),
1570 'border-left' => true, // add left line separator
1571 );
1572
1573 $rank += 10;
1574 $this->cols['unit'] = array(
1575 'rank' => $rank,
1576 'width' => 11, // in mm
1577 'status' => false,
1578 'title' => array(
1579 'textkey' => 'Unit'
1580 ),
1581 'border-left' => true, // add left line separator
1582 );
1583 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
1584 $this->cols['unit']['status'] = true;
1585 }
1586
1587 $rank += 10;
1588 $this->cols['discount'] = array(
1589 'rank' => $rank,
1590 'width' => 13, // in mm
1591 'status' => false,
1592 'title' => array(
1593 'textkey' => 'ReductionShort'
1594 ),
1595 'border-left' => true, // add left line separator
1596 );
1597 if ($this->atleastonediscount) {
1598 $this->cols['discount']['status'] = true;
1599 }
1600
1601 $rank += 1000; // add a big offset to be sure is the last col because default extrafield rank is 100
1602 $this->cols['totalexcltax'] = array(
1603 'rank' => $rank,
1604 'width' => 26, // in mm
1605 'status' => false,
1606 'title' => array(
1607 'textkey' => 'TotalHT'
1608 ),
1609 'border-left' => true, // add left line separator
1610 );
1611
1612 if (!getDolGlobalString('MAIN_GENERATE_DOCUMENTS_SUPPLIER_PROPOSAL_WITHOUT_TOTAL_COLUMN')) {
1613 $this->cols['totalexcltax']['status'] = true;
1614 }
1615
1616 // Add extrafields cols
1617 if (!empty($object->lines)) {
1618 $line = reset($object->lines);
1619 $this->defineColumnExtrafield($line, $outputlangs, $hidedetails);
1620 }
1621
1622 $parameters = array(
1623 'object' => $object,
1624 'outputlangs' => $outputlangs,
1625 'hidedetails' => $hidedetails,
1626 'hidedesc' => $hidedesc,
1627 'hideref' => $hideref
1628 );
1629
1630 $reshook = $hookmanager->executeHooks('defineColumnField', $parameters, $this); // Note that $object may have been modified by hook
1631 if ($reshook < 0) {
1632 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1633 } elseif (empty($reshook)) {
1634 // @phan-suppress-next-line PhanPluginSuspiciousParamOrderInternal
1635 $this->cols = array_replace($this->cols, $hookmanager->resArray); // array_replace is used to preserve keys
1636 } else {
1637 $this->cols = $hookmanager->resArray;
1638 }
1639 }
1640}
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(!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)
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:2849
pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line total excluding tax.
Definition pdf.lib.php:2550
pdf_getFormat($outputlangs=null, $mode='setup')
Return array with format properties of default PDF format.
Definition pdf.lib.php:87
pdf_getPDFFontSize($outputlangs)
Return font size to use for PDF generation.
Definition pdf.lib.php:289
pdf_getHeightForLogo($logo, $url=false)
Return height to use for Logo onto PDF.
Definition pdf.lib.php:312
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:1110
pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line unit price excluding tax.
Definition pdf.lib.php:2153
pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails=0)
Return line vat rate.
Definition pdf.lib.php:2091
pdf_writeLinkedObjects(&$pdf, $object, $outputlangs, $posx, $posy, $w, $h, $align, $default_font_size)
Show linked objects for PDF generation.
Definition pdf.lib.php:1497
pdf_getPDFFont($outputlangs)
Return font name to use for PDF generation.
Definition pdf.lib.php:268
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:433
pdf_getlineunit($object, $i, $outputlangs, $hidedetails=0)
Return line unit.
Definition pdf.lib.php:2398
pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails=0)
Return line remise percent.
Definition pdf.lib.php:2441
pdf_getlineqty($object, $i, $outputlangs, $hidedetails=0)
Return line quantity.
Definition pdf.lib.php:2238
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:824
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:388
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:125
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:128