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