dolibarr 22.0.5
pdf_einstein.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-2013 Juanjo Menent <jmenent@2byte.es>
6 * Copyright (C) 2012 Christophe Battarel <christophe.battarel@altairis.fr>
7 * Copyright (C) 2012 Cedric Salvador <csalvador@gpcsolutions.fr>
8 * Copyright (C) 2015 Marcos García <marcosgdf@gmail.com>
9 * Copyright (C) 2017-2018 Ferran Marcet <fmarcet@2byte.es>
10 * Copyright (C) 2018-2025 Frédéric France <frederic.france@free.fr>
11 * Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
12 * Copyright (C) 2024 Nick Fragoulis
13 * Copyright (C) 2024 Alexandre Spangaro <alexandre@inovea-conseil.com>
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 3 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program. If not, see <https://www.gnu.org/licenses/>.
27 * or see https://www.gnu.org/
28 */
29
36require_once DOL_DOCUMENT_ROOT.'/core/modules/commande/modules_commande.php';
37require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
38require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
39require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
40require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
41
42
47{
51 public $db;
52
56 public $entity;
57
61 public $name;
62
66 public $description;
67
71 public $update_main_doc_field;
72
76 public $type;
77
82 public $version = 'dolibarr';
83
84
90 public function __construct(DoliDB $db)
91 {
92 global $conf, $langs, $mysoc;
93
94 // Translations
95 $langs->loadLangs(array("main", "bills", "products"));
96
97 $this->db = $db;
98 $this->name = "einstein";
99 $this->description = $langs->trans('PDFEinsteinDescription');
100 $this->update_main_doc_field = 1; // Save the name of generated file as the main doc when generating a doc with this template
101
102 // Dimension page
103 $this->type = 'pdf';
104 $formatarray = pdf_getFormat();
105 $this->page_largeur = $formatarray['width'];
106 $this->page_hauteur = $formatarray['height'];
107 $this->format = array($this->page_largeur, $this->page_hauteur);
108 $this->marge_gauche = getDolGlobalInt('MAIN_PDF_MARGIN_LEFT', 10);
109 $this->marge_droite = getDolGlobalInt('MAIN_PDF_MARGIN_RIGHT', 10);
110 $this->marge_haute = getDolGlobalInt('MAIN_PDF_MARGIN_TOP', 10);
111 $this->marge_basse = getDolGlobalInt('MAIN_PDF_MARGIN_BOTTOM', 10);
112 $this->corner_radius = getDolGlobalInt('MAIN_PDF_FRAME_CORNER_RADIUS', 0);
113 $this->option_logo = 1; // Display logo
114 $this->option_tva = 1; // Manage the vat option FACTURE_TVAOPTION
115 $this->option_modereg = 1; // Display payment mode
116 $this->option_condreg = 1; // Display payment terms
117 $this->option_multilang = 1; // Available in several languages
118 $this->option_escompte = 0; // Displays if there has been a discount
119 $this->option_credit_note = 0; // Support credit notes
120 $this->option_freetext = 1; // Support add of a personalised text
121 $this->option_draft_watermark = 1; // Support add of a watermark on drafts
122 $this->watermark = '';
123
124 // Define position of columns
125 $this->posxdesc = $this->marge_gauche + 1;
126 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
127 $this->posxtva = 101;
128 $this->posxup = 118;
129 $this->posxqty = 135;
130 $this->posxunit = 151;
131 } else {
132 $this->posxtva = 106;
133 $this->posxup = 122;
134 $this->posxqty = 145;
135 $this->posxunit = 162;
136 }
137 $this->posxdiscount = 162;
138 $this->postotalht = 174;
139 if (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT') || getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_COLUMN')) {
140 $this->posxtva = $this->posxup;
141 }
142 $this->posxpicture = $this->posxtva - getDolGlobalInt('MAIN_DOCUMENTS_WITH_PICTURE_WIDTH', 20); // width of images
143 if ($this->page_largeur < 210) { // To work with US executive format
144 $this->posxpicture -= 20;
145 $this->posxtva -= 20;
146 $this->posxup -= 20;
147 $this->posxqty -= 20;
148 $this->posxunit -= 20;
149 $this->posxdiscount -= 20;
150 $this->postotalht -= 20;
151 }
152
153 $this->tva = array();
154 $this->tva_array = array();
155 $this->localtax1 = array();
156 $this->localtax2 = array();
157 $this->atleastoneratenotnull = 0;
158 $this->atleastonediscount = 0;
159
160 if ($mysoc === null) {
161 dol_syslog(get_class($this).'::__construct() Global $mysoc should not be null.'. getCallerInfoString(), LOG_ERR);
162 return;
163 }
164
165 // Get source company
166 $this->emetteur = $mysoc;
167 if (empty($this->emetteur->country_code)) {
168 $this->emetteur->country_code = substr($langs->defaultlang, -2); // By default, if was not defined
169 }
170 }
171
172 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
184 public function write_file($object, $outputlangs, $srctemplatepath = '', $hidedetails = 0, $hidedesc = 0, $hideref = 0)
185 {
186 // phpcs:enable
187 global $user, $langs, $conf, $mysoc, $db, $hookmanager, $nblines;
188
189 if (!is_object($outputlangs)) {
190 $outputlangs = $langs;
191 }
192 // For backward compatibility with FPDF, force output charset to ISO, because FPDF expect text to be encoded in ISO
193 if (getDolGlobalString('MAIN_USE_FPDF')) {
194 $outputlangs->charset_output = 'ISO-8859-1';
195 }
196
197 // Load translation files required by the page
198 $outputlangs->loadLangs(array("main", "dict", "companies", "bills", "products", "orders", "deliveries", "compta"));
199
200 // Show Draft Watermark
201 if ($object->statut == $object::STATUS_DRAFT && getDolGlobalString('COMMANDE_DRAFT_WATERMARK')) {
202 $this->watermark = getDolGlobalString('COMMANDE_DRAFT_WATERMARK');
203 }
204
205 global $outputlangsbis;
206 $outputlangsbis = null;
207 if (getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE') && $outputlangs->defaultlang != getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE')) {
208 $outputlangsbis = new Translate('', $conf);
209 $outputlangsbis->setDefaultLang(getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE'));
210 $outputlangsbis->loadLangs(array("main", "dict", "companies", "bills", "products", "orders", "deliveries", "compta"));
211 }
212
213 $nblines = count($object->lines);
214
215 if ($conf->commande->multidir_output[$conf->entity]) {
216 $object->fetch_thirdparty();
217
218 $deja_regle = 0;
219
220 // Definition of $dir and $file
221 if ($object->specimen) {
222 $dir = $conf->commande->multidir_output[$conf->entity];
223 $file = $dir."/SPECIMEN.pdf";
224 } else {
225 // Possibility to use suffix for proforma
226 $suffix = '';
227 if (getDolGlobalString('PROFORMA_PDF_WITH_SUFFIX')) {
228 $suffix = (GETPOST('model') == 'proforma') ? getDolGlobalString('PROFORMA_PDF_WITH_SUFFIX') : '';
229 $suffix = dol_sanitizeFileName($suffix);
230 }
231
232 $objectref = dol_sanitizeFileName($object->ref);
233 $dir = $conf->commande->multidir_output[$object->entity]."/".$objectref;
234 $file = $dir."/".$objectref.$suffix.".pdf";
235 }
236
237 if (!file_exists($dir)) {
238 if (dol_mkdir($dir) < 0) {
239 $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
240 return 0;
241 }
242 }
243
244 if (file_exists($dir)) {
245 // Add pdfgeneration hook
246 if (!is_object($hookmanager)) {
247 include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
248 $hookmanager = new HookManager($this->db);
249 }
250 $hookmanager->initHooks(array('pdfgeneration'));
251 $parameters = array('file' => $file, 'object' => $object, 'outputlangs' => $outputlangs);
252 global $action;
253 $reshook = $hookmanager->executeHooks('beforePDFCreation', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
254
255 // Set nblines with the new command lines content after hook
256 $nblines = count($object->lines);
257
258 // Create pdf instance
259 $pdf = pdf_getInstance($this->format);
260 $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance
261 $pdf->setAutoPageBreak(true, 0);
262
263 $heightforinfotot = 40; // Height reserved to output the info and total part
264 $heightforfreetext = getDolGlobalInt('MAIN_PDF_FREETEXT_HEIGHT', 5); // Height reserved to output the free text on last page
265 $heightforfooter = $this->marge_basse + 8; // Height reserved to output the footer (value include bottom margin)
266 if (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS')) {
267 $heightforfooter += 6;
268 }
269
270 if (class_exists('TCPDF')) {
271 $pdf->setPrintHeader(false);
272 $pdf->setPrintFooter(false);
273 }
274 $pdf->SetFont(pdf_getPDFFont($outputlangs));
275 // Set path to the background PDF File
276 if (getDolGlobalString('MAIN_ADD_PDF_BACKGROUND')) {
277 $logodir = $conf->mycompany->dir_output;
278 if (!empty($conf->mycompany->multidir_output[$object->entity])) {
279 $logodir = $conf->mycompany->multidir_output[$object->entity];
280 }
281 $pagecount = $pdf->setSourceFile($logodir.'/' . getDolGlobalString('MAIN_ADD_PDF_BACKGROUND'));
282 $tplidx = $pdf->importPage(1);
283 }
284
285 $pdf->Open();
286 $pagenb = 0;
287 $pdf->SetDrawColor(128, 128, 128);
288
289 $pdf->SetTitle($outputlangs->convToOutputCharset($object->ref));
290 $pdf->SetSubject($outputlangs->transnoentities("PdfOrderTitle"));
291 $pdf->SetCreator("Dolibarr ".DOL_VERSION);
292 $pdf->SetAuthor($outputlangs->convToOutputCharset($user->getFullName($outputlangs)));
293 $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("PdfOrderTitle")." ".$outputlangs->convToOutputCharset($object->thirdparty->name));
294 if (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) {
295 $pdf->SetCompression(false);
296 }
297
298 // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
299 $pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite); // Left, Top, Right
300
301 // Set $this->atleastonediscount if you have at least one discount
302 for ($i = 0; $i < $nblines; $i++) {
303 if ($object->lines[$i]->remise_percent) {
304 $this->atleastonediscount++;
305 }
306 }
307 if (empty($this->atleastonediscount)) {
308 $delta = ($this->postotalht - $this->posxdiscount);
309 $this->posxpicture += $delta;
310 $this->posxtva += $delta;
311 $this->posxup += $delta;
312 $this->posxqty += $delta;
313 $this->posxunit += $delta;
314 $this->posxdiscount += $delta;
315 // post of fields after are not modified, stay at same position
316 }
317
318 // New page
319 $pdf->AddPage();
320 if (!empty($tplidx)) {
321 $pdf->useTemplate($tplidx);
322 }
323 $pagenb++;
324 $pagehead = $this->_pagehead($pdf, $object, 1, $outputlangs, (is_object($outputlangsbis) ? $outputlangsbis : null));
325 $top_shift = $pagehead['top_shift'];
326 $shipp_shift = $pagehead['shipp_shift'];
327 $pdf->SetFont('', '', $default_font_size - 1);
328 $pdf->MultiCell(0, 3, ''); // Set interline to 3
329 $pdf->SetTextColor(0, 0, 0);
330
331 $tab_top = 90 + $top_shift + $shipp_shift;
332 $tab_top_newpage = (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD') ? 42 + $top_shift : 10);
333
334 // Incoterm
335 $height_incoterms = 0;
336 if (isModEnabled('incoterm')) {
337 $desc_incoterms = $object->getIncotermsForPDF();
338 if ($desc_incoterms) {
339 $tab_top -= 2;
340
341 $pdf->SetFont('', '', $default_font_size - 1);
342 $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top - 1, dol_htmlentitiesbr($desc_incoterms), 0, 1);
343 $nexY = $pdf->GetY();
344 $height_incoterms = $nexY - $tab_top;
345
346 // Rect takes a length in 3rd parameter
347 $pdf->SetDrawColor(192, 192, 192);
348 $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');
349
350 $tab_top = $nexY + 6;
351 }
352 }
353
354 // Displays notes
355 $notetoshow = empty($object->note_public) ? '' : $object->note_public;
356 if (getDolGlobalString('MAIN_ADD_SALE_REP_SIGNATURE_IN_NOTE')) {
357 // Get first sale rep
358 if (is_object($object->thirdparty)) {
359 $salereparray = $object->thirdparty->getSalesRepresentatives($user);
360 $salerepobj = new User($this->db);
361 $salerepobj->fetch($salereparray[0]['id']);
362 if (!empty($salerepobj->signature)) {
363 $notetoshow = dol_concatdesc($notetoshow, $salerepobj->signature);
364 }
365 }
366 }
367 // Extrafields in note
368 $extranote = $this->getExtrafieldsInHtml($object, $outputlangs);
369 if (!empty($extranote)) {
370 $notetoshow = dol_concatdesc((string) $notetoshow, $extranote);
371 }
372
373 if ($notetoshow) {
374 $tab_top -= 2;
375
376 $substitutionarray = pdf_getSubstitutionArray($outputlangs, null, $object);
377 complete_substitutions_array($substitutionarray, $outputlangs, $object);
378 $notetoshow = make_substitutions($notetoshow, $substitutionarray, $outputlangs);
379 $notetoshow = convertBackOfficeMediasLinksToPublicLinks($notetoshow);
380
381 $pdf->SetFont('', '', $default_font_size - 1);
382 $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top - 1, dol_htmlentitiesbr($notetoshow), 0, 1);
383 $nexY = $pdf->GetY();
384 $height_note = $nexY - $tab_top;
385
386 // Rect takes a length in 3rd parameter
387 $pdf->SetDrawColor(192, 192, 192);
388 $pdf->RoundedRect($this->marge_gauche, $tab_top - 1, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $height_note + 1, $this->corner_radius, '1234', 'D');
389
390 $tab_top = $nexY + 6;
391 }
392
393 $iniY = $tab_top + 7;
394 $curY = $tab_top + 7;
395 $nexY = $tab_top + 7;
396
397 // Loop on each lines
398 for ($i = 0; $i < $nblines; $i++) {
399 $curY = $nexY;
400 $pdf->SetFont('', '', $default_font_size - 1); // Into loop to work with multipage
401 $pdf->SetTextColor(0, 0, 0);
402
403 $pdf->setTopMargin($tab_top_newpage);
404 $pdf->setPageOrientation('', true, $heightforfooter + $heightforfreetext + $heightforinfotot); // The only function to edit the bottom margin of current page to set it.
405 $pageposbefore = $pdf->getPage();
406
407 // Description of product line
408 $curX = $this->posxdesc - 1;
409
410 $showpricebeforepagebreak = 1;
411
412 $pdf->startTransaction();
413 pdf_writelinedesc($pdf, $object, $i, $outputlangs, $this->posxtva - $curX, 3, $curX, $curY, $hideref, $hidedesc);
414 $pageposafter = $pdf->getPage();
415 if ($pageposafter > $pageposbefore) { // There is a pagebreak
416 $pdf->rollbackTransaction(true);
417 $pageposafter = $pageposbefore;
418 //print $pageposafter.'-'.$pageposbefore;exit;
419 $pdf->setPageOrientation('', true, $heightforfooter); // The only function to edit the bottom margin of current page to set it.
420 pdf_writelinedesc($pdf, $object, $i, $outputlangs, $this->posxtva - $curX, 4, $curX, $curY, $hideref, $hidedesc);
421 $pageposafter = $pdf->getPage();
422 $posyafter = $pdf->GetY();
423 if ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforinfotot))) { // There is no space left for total+free text
424 if ($i == ($nblines - 1)) { // No more lines, and no space left to show total, so we create a new page
425 $pdf->AddPage('', '', true);
426 if (!empty($tplidx)) {
427 $pdf->useTemplate($tplidx);
428 }
429 if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
430 $this->_pagehead($pdf, $object, 0, $outputlangs);
431 }
432 $pdf->setPage($pageposafter + 1);
433 }
434 } else {
435 // We found a page break
436 // Allows data in the first page if description is long enough to break in multiples pages
437 if (getDolGlobalString('MAIN_PDF_DATA_ON_FIRST_PAGE')) {
438 $showpricebeforepagebreak = 1;
439 } else {
440 $showpricebeforepagebreak = 0;
441 }
442 }
443 } else { // No pagebreak
444 $pdf->commitTransaction();
445 }
446 $posYAfterDescription = $pdf->GetY();
447
448 $nexY = $pdf->GetY();
449 $pageposafter = $pdf->getPage();
450
451 $pdf->setPage($pageposbefore);
452 $pdf->setTopMargin($this->marge_haute);
453 $pdf->setPageOrientation('', true, 0); // The only function to edit the bottom margin of current page to set it.
454
455 // We suppose that a too long description is moved completely on next page
456 if ($pageposafter > $pageposbefore && empty($showpricebeforepagebreak)) {
457 $pdf->setPage($pageposafter);
458 $curY = $tab_top_newpage;
459 }
460
461 $pdf->SetFont('', '', $default_font_size - 1); // We reposition the default font
462
463 // VAT Rate
464 if (!getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT') && !getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_COLUMN')) {
465 $vat_rate = pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails);
466 $pdf->SetXY($this->posxtva - 5, $curY);
467 $pdf->MultiCell($this->posxup - $this->posxtva + 4, 3, $vat_rate, 0, 'R');
468 }
469
470 // Unit price before discount
471 $up_excl_tax = pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails);
472 $pdf->SetXY($this->posxup, $curY);
473 $pdf->MultiCell($this->posxqty - $this->posxup - 0.8, 3, $up_excl_tax, 0, 'R', false);
474
475 // Quantity
476 $qty = pdf_getlineqty($object, $i, $outputlangs, $hidedetails);
477 $pdf->SetXY($this->posxqty, $curY);
478 $pdf->MultiCell($this->posxunit - $this->posxqty - 0.8, 4, $qty, 0, 'R'); // Enough for 6 chars
479
480 // Unit
481 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
482 $unit = pdf_getlineunit($object, $i, $outputlangs, $hidedetails);
483 $pdf->SetXY($this->posxunit, $curY);
484 $pdf->MultiCell($this->posxdiscount - $this->posxunit - 0.8, 4, $unit, 0, 'L');
485 }
486
487 // Discount on line
488 $pdf->SetXY($this->posxdiscount, $curY);
489 if ($object->lines[$i]->remise_percent) {
490 $pdf->SetXY($this->posxdiscount - 2, $curY);
491 $remise_percent = pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails);
492 $pdf->MultiCell($this->postotalht - $this->posxdiscount + 2, 3, $remise_percent, 0, 'R');
493 }
494
495 // Total HT line
496 $total_excl_tax = pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails);
497 $pdf->SetXY($this->postotalht, $curY);
498 $pdf->MultiCell($this->page_largeur - $this->marge_droite - $this->postotalht, 3, $total_excl_tax, 0, 'R', false);
499
500 // Collection of totals by value of vat in $this->vat["rate"] = total_tva
501 if (isModEnabled("multicurrency") && $object->multicurrency_tx != 1) {
502 $tvaligne = $object->lines[$i]->multicurrency_total_tva;
503 } else {
504 $tvaligne = $object->lines[$i]->total_tva;
505 }
506
507 $localtax1ligne = $object->lines[$i]->total_localtax1;
508 $localtax2ligne = $object->lines[$i]->total_localtax2;
509 $localtax1_rate = $object->lines[$i]->localtax1_tx;
510 $localtax2_rate = $object->lines[$i]->localtax2_tx;
511 $localtax1_type = $object->lines[$i]->localtax1_type;
512 $localtax2_type = $object->lines[$i]->localtax2_type;
513
514 // TODO remise_percent is an obsolete field for object parent
515 /*if ($object->remise_percent) {
516 $tvaligne -= ($tvaligne * $object->remise_percent) / 100;
517 }
518 if ($object->remise_percent) {
519 $localtax1ligne -= ($localtax1ligne * $object->remise_percent) / 100;
520 }
521 if ($object->remise_percent) {
522 $localtax2ligne -= ($localtax2ligne * $object->remise_percent) / 100;
523 }*/
524
525 $vatrate = (string) $object->lines[$i]->tva_tx;
526
527 // Retrieve type from database for backward compatibility with old records
528 if ((!isset($localtax1_type) || $localtax1_type == '' || !isset($localtax2_type) || $localtax2_type == '') // if tax type not defined
529 && (!empty($localtax1_rate) || !empty($localtax2_rate))) { // and there is local tax
530 $localtaxtmp_array = getLocalTaxesFromRate($vatrate, 0, $object->thirdparty, $mysoc);
531 $localtax1_type = isset($localtaxtmp_array[0]) ? $localtaxtmp_array[0] : '';
532 $localtax2_type = isset($localtaxtmp_array[2]) ? $localtaxtmp_array[2] : '';
533 }
534
535 // retrieve global local tax
536 if ($localtax1_type && $localtax1ligne != 0) {
537 if (empty($this->localtax1[$localtax1_type][$localtax1_rate])) {
538 $this->localtax1[$localtax1_type][$localtax1_rate] = $localtax1ligne;
539 } else {
540 $this->localtax1[$localtax1_type][$localtax1_rate] += $localtax1ligne;
541 }
542 }
543 if ($localtax2_type && $localtax2ligne != 0) {
544 if (empty($this->localtax2[$localtax2_type][$localtax2_rate])) {
545 $this->localtax2[$localtax2_type][$localtax2_rate] = $localtax2ligne;
546 } else {
547 $this->localtax2[$localtax2_type][$localtax2_rate] += $localtax2ligne;
548 }
549 }
550
551 if (($object->lines[$i]->info_bits & 0x01) == 0x01) {
552 $vatrate .= '*';
553 }
554
555 // Fill $this->tva and $this->tva_array
556 if (!isset($this->tva[$vatrate])) {
557 $this->tva[$vatrate] = 0;
558 }
559 $this->tva[$vatrate] += $tvaligne;
560 $vatcode = $object->lines[$i]->vat_src_code;
561 if (empty($this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'])) {
562 $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'] = 0;
563 }
564 $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')] = array('vatrate' => $vatrate, 'vatcode' => $vatcode, 'amount' => $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'] + $tvaligne);
565
566 // Add line
567 if (getDolGlobalString('MAIN_PDF_DASH_BETWEEN_LINES') && $i < ($nblines - 1)) {
568 $pdf->setPage($pageposafter);
569 $pdf->SetLineStyle(array('dash' => '1,1', 'color' => array(80, 80, 80)));
570 //$pdf->SetDrawColor(190,190,200);
571 $pdf->line($this->marge_gauche, $nexY + 1, $this->page_largeur - $this->marge_droite, $nexY + 1);
572 $pdf->SetLineStyle(array('dash' => 0));
573 }
574
575 $nexY += 2; // Add space between lines
576
577 // Detect if some page were added automatically and output _tableau for past pages
578 while ($pagenb < $pageposafter) {
579 $pdf->setPage($pagenb);
580 if ($pagenb == 1) {
581 $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1, $object->multicurrency_code);
582 } else {
583 $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code);
584 }
585 $this->_pagefoot($pdf, $object, $outputlangs, 1);
586 $pagenb++;
587 $pdf->setPage($pagenb);
588 $pdf->setPageOrientation('', true, 0); // The only function to edit the bottom margin of current page to set it.
589 if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
590 $this->_pagehead($pdf, $object, 0, $outputlangs);
591 }
592 if (!empty($tplidx)) {
593 $pdf->useTemplate($tplidx);
594 }
595 }
596 if (isset($object->lines[$i + 1]->pagebreak) && $object->lines[$i + 1]->pagebreak) { // @phan-suppress-current-line PhanUndeclaredProperty
597 if ($pagenb == 1) {
598 $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1, $object->multicurrency_code);
599 } else {
600 $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code);
601 }
602 $this->_pagefoot($pdf, $object, $outputlangs, 1);
603 // New page
604 $pdf->AddPage();
605 if (!empty($tplidx)) {
606 $pdf->useTemplate($tplidx);
607 }
608 $pagenb++;
609 if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
610 $this->_pagehead($pdf, $object, 0, $outputlangs);
611 }
612 }
613 }
614
615 // Show square
616 if ($pagenb == 1) {
617 $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 0, 0, $object->multicurrency_code);
618 } else {
619 $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 1, 0, $object->multicurrency_code);
620 }
621 $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
622
623 // Display infos area
624 $posy = $this->_tableau_info($pdf, $object, $bottomlasttab, $outputlangs);
625
626 // Display total zone
627 $posy = $this->_tableau_tot($pdf, $object, $deja_regle, $bottomlasttab, $outputlangs);
628
629 // Affiche zone versements
630 /*
631 if ($deja_regle)
632 {
633 $posy=$this->_tableau_versements($pdf, $object, $posy, $outputlangs);
634 }
635 */
636
637 // Pied de page
638 $this->_pagefoot($pdf, $object, $outputlangs);
639 if (method_exists($pdf, 'AliasNbPages')) {
640 $pdf->AliasNbPages(); // @phan-suppress-current-line PhanUndeclaredMethod
641 }
642
643 // Add terms to sale
644 if (getDolGlobalString("MAIN_INFO_ORDER_TERMSOFSALE") && getDolGlobalInt('MAIN_PDF_ADD_TERMSOFSALE_ORDER')) {
645 $termsofsalefilename = getDolGlobalString('MAIN_INFO_ORDER_TERMSOFSALE');
646 $termsofsale = $conf->order->dir_output.'/'.$termsofsalefilename;
647 if (!empty($conf->order->multidir_output[$conf->entity])) {
648 $termsofsale = $conf->order->multidir_output[$conf->entity].'/'.$termsofsalefilename;
649 }
650 if (file_exists($termsofsale) && is_readable($termsofsale)) {
651 $pagecount = $pdf->setSourceFile($termsofsale);
652 for ($i = 1; $i <= $pagecount; $i++) {
653 $tplIdx = $pdf->importPage($i);
654 if ($tplIdx !== false) {
655 $s = $pdf->getTemplatesize($tplIdx);
656 $pdf->AddPage($s['h'] > $s['w'] ? 'P' : 'L');
657 $pdf->useTemplate($tplIdx);
658 } else {
659 setEventMessages(null, array($termsofsale.' cannot be added, probably protected PDF'), 'warnings');
660 }
661 }
662 }
663 }
664
665 $pdf->Close();
666
667 $pdf->Output($file, 'F');
668
669 // Add pdfgeneration hook
670 $hookmanager->initHooks(array('pdfgeneration'));
671 $parameters = array('file' => $file, 'object' => $object, 'outputlangs' => $outputlangs);
672 global $action;
673 $reshook = $hookmanager->executeHooks('afterPDFCreation', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
674 if ($reshook < 0) {
675 $this->error = $hookmanager->error;
676 $this->errors = $hookmanager->errors;
677 }
678
679 dolChmod($file);
680
681 $this->result = array('fullpath' => $file);
682
683 return 1; // No error
684 } else {
685 $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
686 return 0;
687 }
688 } else {
689 $this->error = $langs->transnoentities("ErrorConstantNotDefined", "COMMANDE_OUTPUTDIR");
690 return 0;
691 }
692 }
693
694 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
695 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
705 protected function _tableau_versements(&$pdf, $object, $posy, $outputlangs)
706 {
707 // phpcs:enable
708 return 1;
709 }
710
711 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
712 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
722 protected function _tableau_info(&$pdf, $object, $posy, $outputlangs)
723 {
724 // phpcs:enable
725 global $conf, $mysoc;
726 $default_font_size = pdf_getPDFFontSize($outputlangs);
727
728 $pdf->SetFont('', '', $default_font_size - 1);
729
730 $diffsizetitle = getDolGlobalInt('PDF_DIFFSIZE_TITLE', 3);
731
732 // If France, show VAT mention if not applicable
733 if ($this->emetteur->country_code == 'FR' && empty($mysoc->tva_assuj)) {
734 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
735 $pdf->SetXY($this->marge_gauche, $posy);
736 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("VATIsNotUsedForInvoice"), 0, 'L', false);
737
738 $posy = $pdf->GetY() + 4;
739 }
740
741 $posxval = 52;
742
743 $diffsizetitle = getDolGlobalInt('PDF_DIFFSIZE_TITLE', 3);
744
745 // Show payments conditions
746 if ($object->cond_reglement_code || $object->cond_reglement) {
747 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
748 $pdf->SetXY($this->marge_gauche, $posy);
749 $titre = $outputlangs->transnoentities("PaymentConditions").':';
750 $pdf->MultiCell(43, 4, $titre, 0, 'L');
751
752 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
753 $pdf->SetXY($posxval, $posy);
754 $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);
755 $lib_condition_paiement = str_replace('\n', "\n", $lib_condition_paiement);
756 if ($object->deposit_percent > 0) {
757 $lib_condition_paiement = str_replace('__DEPOSIT_PERCENT__', (string) $object->deposit_percent, $lib_condition_paiement);
758 }
759 $pdf->MultiCell(67, 4, $lib_condition_paiement, 0, 'L');
760
761 $posy = $pdf->GetY() + 3;
762 }
763
764 // Check a payment mode is defined
765 /* Not used with orders
766 if (empty($object->mode_reglement_code)
767 && ! $conf->global->FACTURE_CHQ_NUMBER
768 && ! $conf->global->FACTURE_RIB_NUMBER)
769 {
770 $pdf->SetXY($this->marge_gauche, $posy);
771 $pdf->SetTextColor(200,0,0);
772 $pdf->SetFont('','B', $default_font_size - 2);
773 $pdf->MultiCell(80, 3, $outputlangs->transnoentities("ErrorNoPaiementModeConfigured"),0,'L',0);
774 $pdf->SetTextColor(0,0,0);
775
776 $posy=$pdf->GetY()+1;
777 }
778 */
779 /* TODO
780 else if (!empty($object->availability_code))
781 {
782 $pdf->SetXY($this->marge_gauche, $posy);
783 $pdf->SetTextColor(200,0,0);
784 $pdf->SetFont('','B', $default_font_size - 2);
785 $pdf->MultiCell(80, 3, $outputlangs->transnoentities("AvailabilityPeriod").': '.,0,'L',0);
786 $pdf->SetTextColor(0,0,0);
787
788 $posy=$pdf->GetY()+1;
789 }*/
790
791 // Show planned date of delivery
792 if (!empty($object->delivery_date)) {
793 $outputlangs->load("sendings");
794 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
795 $pdf->SetXY($this->marge_gauche, $posy);
796 $titre = $outputlangs->transnoentities("DateDeliveryPlanned").':';
797 $pdf->MultiCell(80, 4, $titre, 0, 'L');
798 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
799 $pdf->SetXY($posxval, $posy);
800 $dlp = dol_print_date($object->delivery_date, "daytext", false, $outputlangs, true);
801 $pdf->MultiCell(80, 4, $dlp, 0, 'L');
802
803 $posy = $pdf->GetY() + 1;
804 } elseif ($object->availability_code || $object->availability) {
805 // Show availability conditions
806 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
807 $pdf->SetXY($this->marge_gauche, $posy);
808 $titre = $outputlangs->transnoentities("AvailabilityPeriod").':';
809 $pdf->MultiCell(80, 4, $titre, 0, 'L');
810 $pdf->SetTextColor(0, 0, 0);
811 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
812 $pdf->SetXY($posxval, $posy);
813 $lib_availability = $outputlangs->transnoentities("AvailabilityType".$object->availability_code) != 'AvailabilityType'.$object->availability_code ? $outputlangs->transnoentities("AvailabilityType".$object->availability_code) : $outputlangs->convToOutputCharset(isset($object->availability) ? $object->availability : '');
814 $lib_availability = str_replace('\n', "\n", $lib_availability);
815 $pdf->MultiCell(80, 4, $lib_availability, 0, 'L');
816
817 $posy = $pdf->GetY() + 1;
818 }
819
820 // Show payment mode
821 if ($object->mode_reglement_code
822 && $object->mode_reglement_code != 'CHQ'
823 && $object->mode_reglement_code != 'VIR') {
824 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
825 $pdf->SetXY($this->marge_gauche, $posy);
826 $titre = $outputlangs->transnoentities("PaymentMode").':';
827 $pdf->MultiCell(80, 5, $titre, 0, 'L');
828
829 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
830 $pdf->SetXY($posxval, $posy);
831 $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);
832 $pdf->MultiCell(80, 5, $lib_mode_reg, 0, 'L');
833
834 $posy = $pdf->GetY() + 2;
835 }
836
837 // Show payment mode CHQ
838 if (empty($object->mode_reglement_code) || $object->mode_reglement_code == 'CHQ') {
839 // Si mode reglement non force ou si force a CHQ
840 if (getDolGlobalString('FACTURE_CHQ_NUMBER')) {
841 if (getDolGlobalInt('FACTURE_CHQ_NUMBER') > 0) {
842 $account = new Account($this->db);
843 $account->fetch(getDolGlobalInt('FACTURE_CHQ_NUMBER'));
844
845 $pdf->SetXY($this->marge_gauche, $posy);
846 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
847 $pdf->MultiCell(100, 3, $outputlangs->transnoentities('PaymentByChequeOrderedTo', $account->owner_name), 0, 'L', false);
848 $posy = $pdf->GetY() + 1;
849
850 if (!getDolGlobalString('MAIN_PDF_HIDE_CHQ_ADDRESS')) {
851 $pdf->SetXY($this->marge_gauche, $posy);
852 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
853 $pdf->MultiCell(100, 3, $outputlangs->convToOutputCharset($account->owner_address), 0, 'L', false);
854 $posy = $pdf->GetY() + 2;
855 }
856 }
857 if ($conf->global->FACTURE_CHQ_NUMBER == -1) {
858 $pdf->SetXY($this->marge_gauche, $posy);
859 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
860 $pdf->MultiCell(100, 3, $outputlangs->transnoentities('PaymentByChequeOrderedTo', $this->emetteur->name), 0, 'L', false);
861 $posy = $pdf->GetY() + 1;
862
863 if (!getDolGlobalString('MAIN_PDF_HIDE_CHQ_ADDRESS')) {
864 $pdf->SetXY($this->marge_gauche, $posy);
865 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
866 $pdf->MultiCell(100, 3, $outputlangs->convToOutputCharset($this->emetteur->getFullAddress()), 0, 'L', false);
867 $posy = $pdf->GetY() + 2;
868 }
869 }
870 }
871 }
872
873 // If payment mode not forced or forced to VIR, show payment with BAN
874 if (empty($object->mode_reglement_code) || $object->mode_reglement_code == 'VIR') {
875 if ($object->fk_account > 0 || $object->fk_bank > 0 || getDolGlobalInt('FACTURE_RIB_NUMBER')) {
876 $bankid = ($object->fk_account <= 0 ? $conf->global->FACTURE_RIB_NUMBER : $object->fk_account);
877 if ($object->fk_bank > 0) {
878 $bankid = $object->fk_bank; // For backward compatibility when object->fk_account is forced with object->fk_bank
879 }
880 $account = new Account($this->db);
881 $account->fetch($bankid);
882
883 $curx = $this->marge_gauche;
884 $cury = $posy;
885
886 $posy = pdf_bank($pdf, $outputlangs, $curx, $cury, $account, 0, $default_font_size);
887
888 $posy += 2;
889 }
890 }
891
892 return $posy;
893 }
894
895 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
896 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
908 protected function _tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs, $outputlangsbis = null)
909 {
910 // phpcs:enable
911 global $conf, $mysoc, $hookmanager;
912
913 $default_font_size = pdf_getPDFFontSize($outputlangs);
914
915 if (getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE') && $outputlangs->defaultlang != getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE')) {
916 $outputlangsbis = new Translate('', $conf);
917 $outputlangsbis->setDefaultLang(getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE'));
918 $outputlangsbis->loadLangs(array("main", "dict", "companies", "bills", "products", "propal"));
919 $default_font_size--;
920 }
921
922 $tab2_top = $posy;
923 $tab2_hl = 4;
924 $pdf->SetFont('', '', $default_font_size - 1);
925
926 // Total table
927 $col1x = 120;
928 $col2x = 170;
929 if ($this->page_largeur < 210) { // To work with US executive format
930 $col2x -= 20;
931 }
932 $largcol2 = ($this->page_largeur - $this->marge_droite - $col2x);
933
934 $useborder = 0;
935 $index = 0;
936
937 // Get Total HT
938 $total_ht = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1 ? $object->multicurrency_total_ht : $object->total_ht);
939
940 // Total discount
941 $total_discount_on_lines = 0;
942 $multicurrency_total_discount_on_lines = 0;
943 foreach ($object->lines as $i => $line) {
944 $resdiscount = pdfGetLineTotalDiscountAmount($object, $i, $outputlangs, 2);
945 $multicurrency_resdiscount = pdfGetLineTotalDiscountAmount($object, $i, $outputlangs, 2, 1);
946
947 $total_discount_on_lines += (is_numeric($resdiscount) ? $resdiscount : 0);
948 $multicurrency_total_discount_on_lines += (is_numeric($multicurrency_resdiscount) ? $multicurrency_resdiscount : 0);
949 // If line was a negative line, we do not count the discount as a discount
950 if ($line->total_ht < 0) {
951 $total_discount_on_lines += -$line->total_ht;
952 $multicurrency_total_discount_on_lines += -$line->multicurrency_total_ht;
953 }
954 }
955
956 if ($total_discount_on_lines > 0) {
957 // Show total NET before discount
958 $pdf->SetFillColor(255, 255, 255);
959 $pdf->SetXY($col1x, $tab2_top);
960 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalHTBeforeDiscount").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transnoentities("TotalHTBeforeDiscount") : ''), 0, 'L', true);
961 $pdf->SetXY($col2x, $tab2_top);
962
963 $total_before_discount_to_show = ((isModEnabled("multicurrency") && $object->multicurrency_tx != 1) ? ($object->multicurrency_total_ht + $multicurrency_total_discount_on_lines) : ($object->total_ht + $total_discount_on_lines));
964 $pdf->MultiCell($largcol2, $tab2_hl, price($total_before_discount_to_show, 0, $outputlangs), 0, 'R', true);
965
966 $index++;
967
968 $pdf->SetFillColor(255, 255, 255);
969 $pdf->SetXY($col1x, $tab2_top + $tab2_hl);
970 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalDiscount").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transnoentities("TotalDiscount") : ''), 0, 'L', true);
971 $pdf->SetXY($col2x, $tab2_top + $tab2_hl);
972
973 $total_discount_to_show = ((isModEnabled("multicurrency") && $object->multicurrency_tx != 1) ? $multicurrency_total_discount_on_lines : $total_discount_on_lines);
974 $pdf->MultiCell($largcol2, $tab2_hl, price($total_discount_to_show, 0, $outputlangs), 0, 'R', true);
975
976 $index++;
977 }
978
979 // Total HT
980 $pdf->SetFillColor(255, 255, 255);
981 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
982 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalHT").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transnoentities("TotalHT") : ''), 0, 'L', true);
983
984 $total_ht = ((isModEnabled("multicurrency") && $object->multicurrency_tx != 1) ? $object->multicurrency_total_ht : $object->total_ht);
985 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
986 $pdf->MultiCell($largcol2, $tab2_hl, price($total_ht + (!empty($object->remise) ? $object->remise : 0), 0, $outputlangs), 0, 'R', true);
987
988 // Show VAT by rates and total
989 $pdf->SetFillColor(248, 248, 248);
990
991 $total_ttc = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1) ? $object->multicurrency_total_ttc : $object->total_ttc;
992
993 $this->atleastoneratenotnull = 0;
994 if (!getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT')) {
995 $tvaisnull = (!empty($this->tva) && count($this->tva) == 1 && isset($this->tva['0.000']) && is_float($this->tva['0.000']));
996 if (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_IFNULL') && $tvaisnull) {
997 // Nothing to do
998 } else {
999 //Local tax 1 before VAT
1000 foreach ($this->localtax1 as $localtax_type => $localtax_rate) {
1001 if (in_array((string) $localtax_type, array('1', '3', '5'))) {
1002 continue;
1003 }
1004 foreach ($localtax_rate as $tvakey => $tvaval) {
1005 if ($tvakey != 0) { // On affiche pas taux 0
1006 //$this->atleastoneratenotnull++;
1007
1008 $index++;
1009 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1010
1011 $tvacompl = '';
1012 if (preg_match('/\*/', (string) $tvakey)) {
1013 $tvakey = str_replace('*', '', (string) $tvakey);
1014 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1015 }
1016 $totalvat = $outputlangs->transcountrynoentities("TotalLT1", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalLT1", $mysoc->country_code) : '');
1017 $totalvat .= ' ';
1018
1019 if (getDolGlobalString('PDF_LOCALTAX1_LABEL_IS_CODE_OR_RATE') == 'nocodenorate') {
1020 $totalvat .= $tvacompl;
1021 } else {
1022 $totalvat .= vatrate((string) abs((float) $tvakey), true).$tvacompl;
1023 }
1024
1025 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1026
1027 $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval);
1028
1029 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1030 $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', true);
1031 }
1032 }
1033 }
1034
1035 //Local tax 2 before VAT
1036 foreach ($this->localtax2 as $localtax_type => $localtax_rate) {
1037 if (in_array((string) $localtax_type, array('1', '3', '5'))) {
1038 continue;
1039 }
1040 foreach ($localtax_rate as $tvakey => $tvaval) {
1041 if ($tvakey != 0) { // On affiche pas taux 0
1042 //$this->atleastoneratenotnull++;
1043
1044 $index++;
1045 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1046
1047 $tvacompl = '';
1048 if (preg_match('/\*/', (string) $tvakey)) {
1049 $tvakey = str_replace('*', '', (string) $tvakey);
1050 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1051 }
1052 $totalvat = $outputlangs->transcountrynoentities("TotalLT2", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalLT2", $mysoc->country_code) : '');
1053 $totalvat .= ' ';
1054
1055 if (getDolGlobalString('PDF_LOCALTAX2_LABEL_IS_CODE_OR_RATE') == 'nocodenorate') {
1056 $totalvat .= $tvacompl;
1057 } else {
1058 $totalvat .= vatrate((string) abs((float) $tvakey), true).$tvacompl;
1059 }
1060
1061 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1062
1063 $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval);
1064
1065 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1066 $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', true);
1067 }
1068 }
1069 }
1070
1071 // VAT
1072 foreach ($this->tva_array as $tvakey => $tvaval) {
1073 if ($tvakey != 0) { // On affiche pas taux 0
1074 $this->atleastoneratenotnull++;
1075
1076 $index++;
1077 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1078
1079 $tvacompl = '';
1080 if (preg_match('/\*/', $tvakey)) {
1081 $tvakey = str_replace('*', '', $tvakey);
1082 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1083 }
1084 $totalvat = $outputlangs->transcountrynoentities("TotalVAT", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalVAT", $mysoc->country_code) : '');
1085 $totalvat .= ' ';
1086 if (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'rateonly') {
1087 $totalvat .= vatrate((string) $tvaval['vatrate'], true).$tvacompl;
1088 } elseif (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'codeonly') {
1089 $totalvat .= $tvaval['vatcode'].$tvacompl;
1090 } elseif (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'nocodenorate') {
1091 $totalvat .= $tvacompl;
1092 } else {
1093 $totalvat .= vatrate((string) $tvaval['vatrate'], true).($tvaval['vatcode'] ? ' ('.$tvaval['vatcode'].')' : '').$tvacompl;
1094 }
1095 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1096
1097 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1098 $pdf->MultiCell($largcol2, $tab2_hl, price(price2num($tvaval['amount'], 'MT'), 0, $outputlangs), 0, 'R', true);
1099 }
1100 }
1101
1102 //Local tax 1 after VAT
1103 //if (getDolGlobalString('FACTURE_LOCAL_TAX1_OPTION') && getDolGlobalString('FACTURE_LOCAL_TAX1_OPTION() == 'localtax1on')
1104 //{
1105 foreach ($this->localtax1 as $localtax_type => $localtax_rate) {
1106 if (in_array((string) $localtax_type, array('2', '4', '6'))) {
1107 continue;
1108 }
1109
1110 foreach ($localtax_rate as $tvakey => $tvaval) {
1111 if ($tvakey != 0) { // On affiche pas taux 0
1112 //$this->atleastoneratenotnull++;
1113
1114 $index++;
1115 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1116
1117 $tvacompl = '';
1118 if (preg_match('/\*/', (string) $tvakey)) {
1119 $tvakey = str_replace('*', '', (string) $tvakey);
1120 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1121 }
1122 $totalvat = $outputlangs->transcountrynoentities("TotalLT1", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalLT1", $mysoc->country_code) : '');
1123 $totalvat .= ' ';
1124
1125 if (getDolGlobalString('PDF_LOCALTAX1_LABEL_IS_CODE_OR_RATE') == 'nocodenorate') {
1126 $totalvat .= $tvacompl;
1127 } else {
1128 $totalvat .= vatrate((string) abs((float) $tvakey), true).$tvacompl;
1129 }
1130
1131 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1132
1133 $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval);
1134
1135 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1136 $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', true);
1137 }
1138 }
1139 }
1140 //}
1141 //Local tax 2 after VAT
1142 //if (getDolGlobalString('FACTURE_LOCAL_TAX2_OPTION') && getDolGlobalString('FATURE_LOCAL_TAX2_OPTION') == 'localtax2on')
1143 //{
1144 foreach ($this->localtax2 as $localtax_type => $localtax_rate) {
1145 if (in_array((string) $localtax_type, array('2', '4', '6'))) {
1146 continue;
1147 }
1148
1149 foreach ($localtax_rate as $tvakey => $tvaval) {
1150 // retrieve global local tax
1151 if ($tvakey != 0) { // On affiche pas taux 0
1152 //$this->atleastoneratenotnull++;
1153
1154 $index++;
1155 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1156
1157 $tvacompl = '';
1158 if (preg_match('/\*/', (string) $tvakey)) {
1159 $tvakey = str_replace('*', '', (string) $tvakey);
1160 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1161 }
1162 $totalvat = $outputlangs->transcountrynoentities("TotalLT2", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalLT2", $mysoc->country_code) : '');
1163 $totalvat .= ' ';
1164
1165 if (getDolGlobalString('PDF_LOCALTAX2_LABEL_IS_CODE_OR_RATE') == 'nocodenorate') {
1166 $totalvat .= $tvacompl;
1167 } else {
1168 $totalvat .= vatrate((string) abs((float) $tvakey), true).$tvacompl;
1169 }
1170
1171 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1172
1173 $total_localtax = ((isModEnabled("multicurrency") && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval);
1174
1175 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1176 $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', true);
1177 }
1178 }
1179 }
1180 //}
1181
1182 // Total TTC
1183 $index++;
1184 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1185 $pdf->SetTextColor(0, 0, 60);
1186 $pdf->SetFillColor(224, 224, 224);
1187 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalTTC").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalTTC", $mysoc->country_code) : ''), $useborder, 'L', true);
1188
1189 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1190 $pdf->MultiCell($largcol2, $tab2_hl, price($total_ttc, 0, $outputlangs), $useborder, 'R', true);
1191 }
1192 }
1193
1194 $pdf->SetTextColor(0, 0, 0);
1195
1196 $creditnoteamount = 0;
1197 $depositsamount = 0;
1198 //$creditnoteamount=$object->getSumCreditNotesUsed();
1199 //$depositsamount=$object->getSumDepositsUsed();
1200 //print "x".$creditnoteamount."-".$depositsamount;exit;
1201 $resteapayer = price2num($total_ttc - $deja_regle - $creditnoteamount - $depositsamount, 'MT');
1202 if (!empty($object->paye)) {
1203 $resteapayer = 0;
1204 }
1205
1206 if ($deja_regle > 0) {
1207 // Already paid + Deposits
1208 $index++;
1209
1210 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1211 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("AlreadyPaid").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transnoentities("AlreadyPaid") : ''), 0, 'L', false);
1212 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1213 $pdf->MultiCell($largcol2, $tab2_hl, price($deja_regle, 0, $outputlangs), 0, 'R', false);
1214
1215 $index++;
1216 $pdf->SetTextColor(0, 0, 60);
1217 $pdf->SetFillColor(224, 224, 224);
1218 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1219 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("RemainderToPay").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transnoentities("AlreadyPaid") : ''), $useborder, 'L', true);
1220
1221 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1222 $pdf->MultiCell($largcol2, $tab2_hl, price($resteapayer, 0, $outputlangs), $useborder, 'R', true);
1223
1224 $pdf->SetFont('', '', $default_font_size - 1);
1225 $pdf->SetTextColor(0, 0, 0);
1226 }
1227
1228 $index++;
1229 return ($tab2_top + ($tab2_hl * $index));
1230 }
1231
1232 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1247 protected function _tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop = 0, $hidebottom = 0, $currency = '', $outputlangsbis = null)
1248 {
1249 global $conf;
1250
1251 // Force to disable hidetop and hidebottom
1252 $hidebottom = 0;
1253 if ($hidetop) {
1254 $hidetop = -1;
1255 }
1256
1257 $currency = !empty($currency) ? $currency : $conf->currency;
1258 $default_font_size = pdf_getPDFFontSize($outputlangs);
1259
1260 // Amount in (at tab_top - 1)
1261 $pdf->SetTextColor(0, 0, 0);
1262 $pdf->SetFont('', '', $default_font_size - 2);
1263
1264 if (empty($hidetop)) {
1265 $titre = $outputlangs->transnoentities("AmountInCurrency", $outputlangs->transnoentitiesnoconv("Currency".$currency));
1266 if (getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE') && is_object($outputlangsbis)) {
1267 $titre .= ' - '.$outputlangsbis->transnoentities("AmountInCurrency", $outputlangsbis->transnoentitiesnoconv("Currency".$currency));
1268 }
1269
1270 $pdf->SetXY($this->page_largeur - $this->marge_droite - ($pdf->GetStringWidth($titre) + 3), $tab_top - 4);
1271 $pdf->MultiCell(($pdf->GetStringWidth($titre) + 3), 2, $titre);
1272
1273 //$conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR='230,230,230';
1274 if (getDolGlobalString('MAIN_PDF_TITLE_BACKGROUND_COLOR')) {
1275 $pdf->RoundedRect($this->marge_gauche, $tab_top, $this->page_largeur - $this->marge_droite - $this->marge_gauche, 5, $this->corner_radius, '1001', 'F', array(), explode(',', getDolGlobalString('MAIN_PDF_TITLE_BACKGROUND_COLOR')));
1276 }
1277 }
1278
1279 $pdf->SetDrawColor(128, 128, 128);
1280 $pdf->SetFont('', '', $default_font_size - 1);
1281
1282 // Output Rect
1283 $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
1284
1285 if (empty($hidetop)) {
1286 $pdf->line($this->marge_gauche, $tab_top + 5, $this->page_largeur - $this->marge_droite, $tab_top + 5); // line takes a position y in 2nd parameter and 4th parameter
1287
1288 $pdf->SetXY($this->posxdesc - 1, $tab_top + 1);
1289 $pdf->MultiCell(108, 2, $outputlangs->transnoentities("Designation"), '', 'L');
1290 }
1291
1292 if (!getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT') && !getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_COLUMN')) {
1293 $pdf->line($this->posxtva - 1, $tab_top, $this->posxtva - 1, $tab_top + $tab_height);
1294 if (empty($hidetop)) {
1295 $pdf->SetXY($this->posxtva - 3, $tab_top + 1);
1296 $pdf->MultiCell($this->posxup - $this->posxtva + 3, 2, $outputlangs->transnoentities("VAT"), '', 'C');
1297 }
1298 }
1299
1300 $pdf->line($this->posxup - 1, $tab_top, $this->posxup - 1, $tab_top + $tab_height);
1301 if (empty($hidetop)) {
1302 $pdf->SetXY($this->posxup - 1, $tab_top + 1);
1303 $pdf->MultiCell($this->posxqty - $this->posxup - 1, 2, $outputlangs->transnoentities("PriceUHT"), '', 'C');
1304 }
1305
1306 $pdf->line($this->posxqty - 1, $tab_top, $this->posxqty - 1, $tab_top + $tab_height);
1307 if (empty($hidetop)) {
1308 $pdf->SetXY($this->posxqty - 1, $tab_top + 1);
1309 $pdf->MultiCell($this->posxunit - $this->posxqty - 1, 2, $outputlangs->transnoentities("Qty"), '', 'C');
1310 }
1311
1312 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
1313 $pdf->line($this->posxunit - 1, $tab_top, $this->posxunit - 1, $tab_top + $tab_height);
1314 if (empty($hidetop)) {
1315 $pdf->SetXY($this->posxunit - 1, $tab_top + 1);
1316 $pdf->MultiCell($this->posxdiscount - $this->posxunit - 1, 2, $outputlangs->transnoentities("Unit"), '', 'C');
1317 }
1318 }
1319
1320 $pdf->line($this->posxdiscount - 1, $tab_top, $this->posxdiscount - 1, $tab_top + $tab_height);
1321 if (empty($hidetop)) {
1322 if ($this->atleastonediscount) {
1323 $pdf->SetXY($this->posxdiscount - 1, $tab_top + 1);
1324 $pdf->MultiCell($this->postotalht - $this->posxdiscount + 1, 2, $outputlangs->transnoentities("ReductionShort"), '', 'C');
1325 }
1326 }
1327
1328 if ($this->atleastonediscount) {
1329 $pdf->line($this->postotalht, $tab_top, $this->postotalht, $tab_top + $tab_height);
1330 }
1331 if (empty($hidetop)) {
1332 $pdf->SetXY($this->postotalht - 1, $tab_top + 1);
1333 $pdf->MultiCell(30, 2, $outputlangs->transnoentities("TotalHTShort"), '', 'C');
1334 }
1335 }
1336
1337 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1338 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1350 protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $outputlangsbis = null, $titlekey = "PdfOrderTitle")
1351 {
1352 // phpcs:enable
1353 global $conf, $langs, $hookmanager;
1354
1355 $ltrdirection = 'L';
1356 if ($outputlangs->trans("DIRECTION") == 'rtl') {
1357 $ltrdirection = 'R';
1358 }
1359
1360 // Load traductions files required by page
1361 $outputlangs->loadLangs(array("main", "bills", "propal", "orders", "companies"));
1362
1363 $default_font_size = pdf_getPDFFontSize($outputlangs);
1364
1365 pdf_pagehead($pdf, $outputlangs, $this->page_hauteur);
1366
1367 $pdf->SetTextColor(0, 0, 60);
1368 $pdf->SetFont('', 'B', $default_font_size + 3);
1369
1370 $w = 100;
1371
1372 $posy = $this->marge_haute;
1373 $posx = $this->page_largeur - $this->marge_droite - $w;
1374
1375 $pdf->SetXY($this->marge_gauche, $posy);
1376
1377 // Logo
1378 if (!getDolGlobalInt('PDF_DISABLE_MYCOMPANY_LOGO')) {
1379 if ($this->emetteur->logo) {
1380 $logodir = $conf->mycompany->dir_output;
1381 if (!empty($conf->mycompany->multidir_output[$object->entity])) {
1382 $logodir = $conf->mycompany->multidir_output[$object->entity];
1383 }
1384 if (!getDolGlobalInt('MAIN_PDF_USE_LARGE_LOGO')) {
1385 $logo = $logodir.'/logos/thumbs/'.$this->emetteur->logo_small;
1386 } else {
1387 $logo = $logodir.'/logos/'.$this->emetteur->logo;
1388 }
1389 if (is_readable($logo)) {
1390 $height = pdf_getHeightForLogo($logo);
1391 $pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto)
1392 } else {
1393 $pdf->SetTextColor(200, 0, 0);
1394 $pdf->SetFont('', 'B', $default_font_size - 2);
1395 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound", $logo), 0, 'L');
1396 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ErrorGoToGlobalSetup"), 0, 'L');
1397 }
1398 } else {
1399 $text = $this->emetteur->name;
1400 $pdf->MultiCell($w, 4, $outputlangs->convToOutputCharset($text), 0, $ltrdirection);
1401 }
1402 }
1403
1404 $pdf->SetFont('', 'B', $default_font_size + 3);
1405 $pdf->SetXY($posx, $posy);
1406 $pdf->SetTextColor(0, 0, 60);
1407 $title = $outputlangs->transnoentities($titlekey);
1408 $title .= ' '.$outputlangs->convToOutputCharset($object->ref);
1409 if ($object->statut == $object::STATUS_DRAFT) {
1410 $pdf->SetTextColor(128, 0, 0);
1411 $title .= ' - '.$outputlangs->transnoentities("NotValidated");
1412 }
1413 $pdf->MultiCell($w, 3, $title, '', 'R');
1414
1415 $pdf->SetFont('', 'B', $default_font_size);
1416
1417 /*
1418 $posy += 5;
1419 $pdf->SetXY($posx, $posy);
1420 $pdf->SetTextColor(0, 0, 60);
1421 $pdf->MultiCell(100, 4, $outputlangs->transnoentities("Ref")." : ".$outputlangs->convToOutputCharset($object->ref), '', 'R');
1422 */
1423
1424 $posy += 3;
1425 $pdf->SetFont('', '', $default_font_size - 1);
1426
1427 if ($object->ref_client) {
1428 $posy += 5;
1429 $pdf->SetXY($posx, $posy);
1430 $pdf->SetTextColor(0, 0, 60);
1431 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("RefCustomer")." : ".$outputlangs->convToOutputCharset($object->ref_client), '', 'R');
1432 }
1433
1434 if (getDolGlobalString('PDF_SHOW_PROJECT_TITLE')) {
1435 $object->fetchProject();
1436 if (!empty($object->project->ref)) {
1437 $posy = $pdf->GetY();
1438 $pdf->SetXY($posx, $posy);
1439 $pdf->SetTextColor(0, 0, 60);
1440 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("Project")." : ".(empty($object->project->title) ? '' : $object->project->title), '', 'R');
1441 }
1442 }
1443
1444 if (getDolGlobalString('PDF_SHOW_PROJECT')) {
1445 $object->fetchProject();
1446 if (!empty($object->project->ref)) {
1447 $outputlangs->load("projects");
1448 $posy = $pdf->GetY();
1449 $pdf->SetXY($posx, $posy);
1450 $pdf->SetTextColor(0, 0, 60);
1451 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("RefProject")." : ".(empty($object->project->ref) ? '' : $object->project->ref), '', 'R');
1452 }
1453 }
1454
1455 $posy = $pdf->GetY();
1456 $pdf->SetXY($posx, $posy);
1457 $pdf->SetTextColor(0, 0, 60);
1458 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("OrderDate")." : ".dol_print_date($object->date, "day", false, $outputlangs, true), '', 'R');
1459
1460 if (!getDolGlobalString('MAIN_PDF_HIDE_CUSTOMER_CODE') && !empty($object->thirdparty->code_client)) {
1461 $posy = $pdf->GetY();
1462 $pdf->SetXY($posx, $posy);
1463 $pdf->SetTextColor(0, 0, 60);
1464 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("CustomerCode")." : ".$outputlangs->transnoentities($object->thirdparty->code_client), '', 'R');
1465 }
1466
1467 if (!getDolGlobalString('MAIN_PDF_HIDE_CUSTOMER_ACCOUNTING_CODE') && !empty($object->thirdparty->code_compta_client)) {
1468 $posy += 4;
1469 $pdf->SetXY($posx, $posy);
1470 $pdf->SetTextColor(0, 0, 60);
1471 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("CustomerAccountancyCode")." : ".$outputlangs->transnoentities($object->thirdparty->code_compta_client), '', 'R');
1472 }
1473
1474 // Get contact
1475 if (getDolGlobalString('DOC_SHOW_FIRST_SALES_REP')) {
1476 $arrayidcontact = $object->getIdContact('internal', 'SALESREPFOLL');
1477 if (count($arrayidcontact) > 0) {
1478 $usertmp = new User($this->db);
1479 $usertmp->fetch($arrayidcontact[0]);
1480 $posy += 4;
1481 $pdf->SetXY($posx, $posy);
1482 $pdf->SetTextColor(0, 0, 60);
1483 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R');
1484 }
1485 }
1486
1487 $posy += 2;
1488
1489 $top_shift = 0;
1490 $shipp_shift = 0;
1491 // Show list of linked objects
1492 $current_y = $pdf->getY();
1493 $posy = pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, $w, 3, 'R', $default_font_size);
1494 if ($current_y < $pdf->getY()) {
1495 $top_shift = $pdf->getY() - $current_y;
1496 }
1497
1498 if ($showaddress) {
1499 // Sender properties
1500 $carac_emetteur = '';
1501 // Add internal contact of object if defined
1502 $arrayidcontact = $object->getIdContact('internal', 'SALESREPFOLL');
1503 if (count($arrayidcontact) > 0) {
1504 $object->fetch_user($arrayidcontact[0]);
1505 $labelbeforecontactname = ($outputlangs->transnoentities("FromContactName") != 'FromContactName' ? $outputlangs->transnoentities("FromContactName") : $outputlangs->transnoentities("Name"));
1506 $carac_emetteur .= ($carac_emetteur ? "\n" : '').$labelbeforecontactname." ".$outputlangs->convToOutputCharset($object->user->getFullName($outputlangs));
1507 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') || getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ' (' : '';
1508 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') && !empty($object->user->office_phone)) ? $object->user->office_phone : '';
1509 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') && getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ', ' : '';
1510 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT') && !empty($object->user->email)) ? $object->user->email : '';
1511 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') || getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ')' : '';
1512 $carac_emetteur .= "\n";
1513 }
1514
1515 $carac_emetteur .= pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, '', 0, 'source', $object);
1516
1517 // Show sender
1518 $posy = 42 + $top_shift;
1519 $posx = $this->marge_gauche;
1520 if (getDolGlobalString('MAIN_INVERT_SENDER_RECIPIENT')) {
1521 $posx = $this->page_largeur - $this->marge_droite - 80;
1522 }
1523 $hautcadre = 40;
1524
1525 // Show sender frame
1526 if (!getDolGlobalString('MAIN_PDF_NO_SENDER_FRAME')) {
1527 $pdf->SetTextColor(0, 0, 0);
1528 $pdf->SetFont('', '', $default_font_size - 2);
1529 $pdf->SetXY($posx, $posy - 5);
1530 $pdf->MultiCell(80, 5, $outputlangs->transnoentities("BillFrom"), 0, $ltrdirection);
1531 $pdf->SetXY($posx, $posy);
1532 $pdf->SetFillColor(230, 230, 230);
1533 $pdf->RoundedRect($posx, $posy, 82, $hautcadre, $this->corner_radius, '1234', 'F');
1534 $pdf->SetTextColor(0, 0, 60);
1535 }
1536
1537 // Show sender name
1538 if (!getDolGlobalString('MAIN_PDF_HIDE_SENDER_NAME')) {
1539 $pdf->SetXY($posx + 2, $posy + 3);
1540 $pdf->SetFont('', 'B', $default_font_size);
1541 $pdf->MultiCell(80, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, $ltrdirection);
1542 $posy = $pdf->getY();
1543 }
1544
1545 // Show sender information
1546 $pdf->SetXY($posx + 2, $posy);
1547 $pdf->SetFont('', '', $default_font_size - 1);
1548 $pdf->MultiCell(80, 4, $carac_emetteur, 0, 'L');
1549
1550
1551 // If CUSTOMER contact defined, we use it
1552 $usecontact = false;
1553 $arrayidcontact = $object->getIdContact('external', 'CUSTOMER');
1554 if (count($arrayidcontact) > 0) {
1555 $usecontact = true;
1556 $result = $object->fetch_contact($arrayidcontact[0]);
1557 }
1558
1559 // Recipient name
1560 if ($usecontact && ($object->contact->socid != $object->thirdparty->id && (!isset($conf->global->MAIN_USE_COMPANY_NAME_OF_CONTACT) || getDolGlobalString('MAIN_USE_COMPANY_NAME_OF_CONTACT')))) {
1561 $thirdparty = $object->contact;
1562 } else {
1563 $thirdparty = $object->thirdparty;
1564 }
1565
1566 $carac_client_name = pdfBuildThirdpartyName($thirdparty, $outputlangs);
1567
1568 $mode = 'target';
1569 $carac_client = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, ($usecontact ? $object->contact : ''), ($usecontact ? 1 : 0), $mode, $object);
1570
1571 // Show recipient
1572 $widthrecbox = getDolGlobalString('MAIN_PDF_USE_ISO_LOCATION') ? 92 : 100;
1573 if ($this->page_largeur < 210) {
1574 $widthrecbox = 84; // To work with US executive format
1575 }
1576 $posy = getDolGlobalString('MAIN_PDF_USE_ISO_LOCATION') ? 40 : 42;
1577 $posy += $top_shift;
1578 $posx = $this->page_largeur - $this->marge_droite - $widthrecbox;
1579 if (getDolGlobalString('MAIN_INVERT_SENDER_RECIPIENT')) {
1580 $posx = $this->marge_gauche;
1581 }
1582
1583 // Show recipient frame
1584 if (!getDolGlobalString('MAIN_PDF_NO_RECIPENT_FRAME')) {
1585 $pdf->SetTextColor(0, 0, 0);
1586 $pdf->SetFont('', '', $default_font_size - 2);
1587 $pdf->SetXY($posx + 2, $posy - 5);
1588 $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillTo"), 0, $ltrdirection);
1589 $pdf->RoundedRect($posx, $posy, $widthrecbox, $hautcadre, $this->corner_radius, '1234', 'D');
1590 }
1591
1592 // Show recipient name
1593 $pdf->SetXY($posx + 2, $posy + 3);
1594 $pdf->SetFont('', 'B', $default_font_size);
1595 // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
1596 $pdf->MultiCell($widthrecbox, 2, $carac_client_name, 0, $ltrdirection);
1597
1598 $posy = $pdf->getY();
1599
1600 // Show recipient information
1601 $pdf->SetFont('', '', $default_font_size - 1);
1602 $pdf->SetXY($posx + 2, $posy);
1603 // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
1604 $pdf->MultiCell($widthrecbox, 4, $carac_client, 0, $ltrdirection);
1605
1606 // Show shipping address
1607 if (getDolGlobalInt('SALES_ORDER_SHOW_SHIPPING_ADDRESS')) {
1608 $idaddressshipping = $object->getIdContact('external', 'SHIPPING');
1609
1610 if (!empty($idaddressshipping)) {
1611 $contactshipping = $object->fetch_Contact($idaddressshipping[0]);
1612 $companystatic = new Societe($this->db);
1613 $companystatic->fetch($object->contact->fk_soc);
1614 $carac_client_name_shipping = pdfBuildThirdpartyName($object->contact, $outputlangs);
1615 $carac_client_shipping = pdf_build_address($outputlangs, $this->emetteur, $companystatic, $object->contact, 1, 'target', $object);
1616 } else {
1617 $carac_client_name_shipping = pdfBuildThirdpartyName($object->thirdparty, $outputlangs);
1618 $carac_client_shipping = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, '', 0, 'target', $object);
1619 }
1620 if (!empty($carac_client_shipping)) {
1621 $posy += $hautcadre;
1622
1623 $hautcadre -= 10; // Height for the shipping address does not need to be as high as main box
1624
1625 // Show shipping frame
1626 $pdf->SetXY($posx + 2, $posy - 5);
1627 $pdf->SetFont('', '', $default_font_size - 2);
1628 $pdf->MultiCell($widthrecbox, 0, $outputlangs->transnoentities('ShippingTo'), 0, 'L', false);
1629 $pdf->RoundedRect($posx, $posy, $widthrecbox, $hautcadre, $this->corner_radius, '1234', 'D');
1630
1631 // Show shipping name
1632 $pdf->SetXY($posx + 2, $posy + 1);
1633 $pdf->SetFont('', 'B', $default_font_size);
1634 $pdf->MultiCell($widthrecbox - 2, 2, $carac_client_name_shipping, '', 'L');
1635
1636 $posy = $pdf->getY();
1637
1638 // Show shipping information
1639 $pdf->SetXY($posx + 2, $posy);
1640 $pdf->SetFont('', '', $default_font_size - 1);
1641 $pdf->MultiCell($widthrecbox - 2, 2, $carac_client_shipping, '', 'L');
1642
1643 $shipp_shift += $hautcadre + 10;
1644 }
1645 }
1646 }
1647
1648 $pdf->SetTextColor(0, 0, 0);
1649
1650 $pagehead = array('top_shift' => $top_shift, 'shipp_shift' => $shipp_shift);
1651
1652 return $pagehead;
1653 }
1654
1655 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1656 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1666 protected function _pagefoot(&$pdf, $object, $outputlangs, $hidefreetext = 0)
1667 {
1668 // phpcs:enable
1669 $showdetails = getDolGlobalInt('MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS', 0);
1670 return pdf_pagefoot($pdf, $outputlangs, 'ORDER_FREE_TEXT', $this->emetteur, $this->marge_basse, $this->marge_gauche, $this->page_hauteur, $object, $showdetails, $hidefreetext, $this->page_largeur, $this->watermark);
1671 }
1672}
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:67
Class to manage bank accounts.
printRoundedRect($pdf, $x, $y, $w, $h, $r, $hidetop=0, $hidebottom=0, $style='D')
Print a rounded rectangle on the PDF.
Class to manage Dolibarr database access.
Class to manage hooks.
Parent class for orders models.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage translations.
Class to manage Dolibarr users.
Class to generate PDF orders with template Einstein.
_pagehead(&$pdf, $object, $showaddress, $outputlangs, $outputlangsbis=null, $titlekey="PdfOrderTitle")
Show top header of page.
_tableau_info(&$pdf, $object, $posy, $outputlangs)
Show miscellaneous information (payment mode, payment term, ...)
_tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs, $outputlangsbis=null)
Show total to pay.
__construct(DoliDB $db)
Constructor.
_tableau_versements(&$pdf, $object, $posy, $outputlangs)
Show payments table.
_tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop=0, $hidebottom=0, $currency='', $outputlangsbis=null)
Show table for lines.
_pagefoot(&$pdf, $object, $outputlangs, $hidefreetext=0)
Show footer of page.
write_file($object, $outputlangs, $srctemplatepath='', $hidedetails=0, $hidedesc=0, $hideref=0)
Function to build pdf onto disk.
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.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
dolChmod($filepath, $newmask='')
Change mod of a file.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
getLocalTaxesFromRate($vatrate, $local, $buyer, $seller, $firstparamisid=0)
Get type and rate of localtaxes for a particular vat rate/country of a thirdparty.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_concatdesc($text1, $text2, $forxml=false, $invert=false)
Concat 2 descriptions with a new line between them (second operand after first one with appropriate n...
complete_substitutions_array(&$substitutionarray, $outputlangs, $object=null, $parameters=null, $callfunc="completesubstitutionarray")
Complete the $substitutionarray with more entries coming from external module that had set the "subst...
make_substitutions($text, $substitutionarray, $outputlangs=null, $converttextinhtmlifnecessary=0)
Make substitution into a text string, replacing keys with vals from $substitutionarray (oldval=>newva...
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_htmlentitiesbr($stringtoencode, $nl2brmode=0, $pagecodefrom='UTF-8', $removelasteolbr=1)
This function is called to encode a string into a HTML string but differs from htmlentities because a...
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0)
Clean a string to use it as a file name.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
Definition member.php:79
pdf_writelinedesc(&$pdf, $object, $i, $outputlangs, $w, $h, $posx, $posy, $hideref=0, $hidedesc=0, $issupplierline=0, $align='J')
Output line description into PDF.
Definition pdf.lib.php:1463
pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line total excluding tax.
Definition pdf.lib.php:2462
pdf_getFormat($outputlangs=null, $mode='setup')
Return array with format properties of default PDF format.
Definition pdf.lib.php:87
pdfGetLineTotalDiscountAmount($object, $i, $outputlangs, $hidedetails=0, $multicurrency=0)
Return line total amount discount.
Definition pdf.lib.php:2763
pdf_getPDFFontSize($outputlangs)
Return font size to use for PDF generation.
Definition pdf.lib.php:289
pdf_getHeightForLogo($logo, $url=false)
Return height to use for Logo onto PDF.
Definition pdf.lib.php:314
pdf_pagefoot(&$pdf, $outputlangs, $paramfreetext, $fromcompany, $marge_basse, $marge_gauche, $page_hauteur, $object, $showdetails=0, $hidefreetext=0, $page_largeur=0, $watermark='')
Show footer of page for PDF generation.
Definition pdf.lib.php:1047
pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line unit price excluding tax.
Definition pdf.lib.php:2080
pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails=0)
Return line vat rate.
Definition pdf.lib.php:2018
pdf_pagehead(&$pdf, $outputlangs, $page_height)
Show header of page for PDF generation.
Definition pdf.lib.php:742
pdf_writeLinkedObjects(&$pdf, $object, $outputlangs, $posx, $posy, $w, $h, $align, $default_font_size)
Show linked objects for PDF generation.
Definition pdf.lib.php:1425
pdf_bank(&$pdf, $outputlangs, $curx, $cury, $account, $onlynumber=0, $default_font_size=10)
Show bank information for PDF generation.
Definition pdf.lib.php:863
pdf_getPDFFont($outputlangs)
Return font name to use for PDF generation.
Definition pdf.lib.php:266
pdf_build_address($outputlangs, $sourcecompany, $targetcompany='', $targetcontact='', $usecontact=0, $mode='source', $object=null)
Return a string with full address formatted for output on PDF documents.
Definition pdf.lib.php:439
pdf_getlineunit($object, $i, $outputlangs, $hidedetails=0)
Return line unit.
Definition pdf.lib.php:2325
pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails=0)
Return line remise percent.
Definition pdf.lib.php:2368
pdf_getlineqty($object, $i, $outputlangs, $hidedetails=0)
Return line quantity.
Definition pdf.lib.php:2165
pdf_getSubstitutionArray($outputlangs, $exclude=null, $object=null, $onlykey=0, $include=null)
Return array of possible substitutions for PDF content (without external module substitutions).
Definition pdf.lib.php:778
pdf_getInstance($format='', $metric='mm', $pagetype='P')
Return a PDF instance object.
Definition pdf.lib.php:129
pdfBuildThirdpartyName($thirdparty, Translate $outputlangs, $includealias=0)
Returns the name of the thirdparty.
Definition pdf.lib.php:391
if(preg_match('/(crypted|dolcrypt):/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition repair.php:158
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:161