dolibarr 23.0.3
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", "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", "sendings", "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 ?? $conf->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 ?? $conf->entity])) {
279 $logodir = $conf->mycompany->multidir_output[$object->entity ?? $conf->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 $termsofsalefilename = getDolGlobalString('MAIN_INFO_ORDER_TERMSOFSALE');
645 if (getDolGlobalInt('MAIN_PDF_ADD_TERMSOFSALE_ORDER') && $termsofsalefilename) {
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 $this->warnings = $hookmanager->warnings;
675 if ($reshook < 0) {
676 $this->error = $hookmanager->error;
677 $this->errors = $hookmanager->errors;
678 dolChmod($file);
679 return -1;
680 }
681
682 dolChmod($file);
683
684 $this->result = array('fullpath' => $file);
685
686 return 1; // No error
687 } else {
688 $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
689 return 0;
690 }
691 } else {
692 $this->error = $langs->transnoentities("ErrorConstantNotDefined", "COMMANDE_OUTPUTDIR");
693 return 0;
694 }
695 }
696
697 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
698 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
708 protected function _tableau_versements(&$pdf, $object, $posy, $outputlangs)
709 {
710 // phpcs:enable
711 return 1;
712 }
713
714 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
715 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
725 protected function _tableau_info(&$pdf, $object, $posy, $outputlangs)
726 {
727 // phpcs:enable
728 global $conf, $mysoc;
729 $default_font_size = pdf_getPDFFontSize($outputlangs);
730
731 $pdf->SetFont('', '', $default_font_size - 1);
732
733 $diffsizetitle = getDolGlobalInt('PDF_DIFFSIZE_TITLE', 3);
734
735 // If France, show VAT mention if not applicable
736 if ($this->emetteur->country_code == 'FR' && empty($mysoc->tva_assuj)) {
737 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
738 $pdf->SetXY($this->marge_gauche, $posy);
739 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("VATIsNotUsedForInvoice"), 0, 'L', false);
740
741 $posy = $pdf->GetY() + 4;
742 }
743
744 $posxval = 52;
745
746 $diffsizetitle = getDolGlobalInt('PDF_DIFFSIZE_TITLE', 3);
747
748 // Show payments conditions
749 if ($object->cond_reglement_code || $object->cond_reglement) {
750 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
751 $pdf->SetXY($this->marge_gauche, $posy);
752 $titre = $outputlangs->transnoentities("PaymentConditions").':';
753 $pdf->MultiCell(43, 4, $titre, 0, 'L');
754
755 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
756 $pdf->SetXY($posxval, $posy);
757 $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);
758 $lib_condition_paiement = str_replace('\n', "\n", $lib_condition_paiement);
759 if ($object->deposit_percent > 0) {
760 $lib_condition_paiement = str_replace('__DEPOSIT_PERCENT__', (string) $object->deposit_percent, $lib_condition_paiement);
761 }
762 $pdf->MultiCell(67, 4, $lib_condition_paiement, 0, 'L');
763
764 $posy = $pdf->GetY() + 3;
765 }
766
767 // Check a payment mode is defined
768 /* Not used with orders
769 if (empty($object->mode_reglement_code)
770 && ! $conf->global->FACTURE_CHQ_NUMBER
771 && ! $conf->global->FACTURE_RIB_NUMBER)
772 {
773 $pdf->SetXY($this->marge_gauche, $posy);
774 $pdf->SetTextColor(200,0,0);
775 $pdf->SetFont('','B', $default_font_size - 2);
776 $pdf->MultiCell(80, 3, $outputlangs->transnoentities("ErrorNoPaiementModeConfigured"),0,'L',0);
777 $pdf->SetTextColor(0,0,0);
778
779 $posy=$pdf->GetY()+1;
780 }
781 */
782 /* TODO
783 else if (!empty($object->availability_code))
784 {
785 $pdf->SetXY($this->marge_gauche, $posy);
786 $pdf->SetTextColor(200,0,0);
787 $pdf->SetFont('','B', $default_font_size - 2);
788 $pdf->MultiCell(80, 3, $outputlangs->transnoentities("AvailabilityPeriod").': '.,0,'L',0);
789 $pdf->SetTextColor(0,0,0);
790
791 $posy=$pdf->GetY()+1;
792 }*/
793
794 // Show planned date of delivery
795 if (!empty($object->delivery_date)) {
796 $outputlangs->load("sendings");
797 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
798 $pdf->SetXY($this->marge_gauche, $posy);
799 $titre = $outputlangs->transnoentities("DateDeliveryPlanned").':';
800 $pdf->MultiCell(80, 4, $titre, 0, 'L');
801 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
802 $pdf->SetXY($posxval, $posy);
803 $dlp = dol_print_date($object->delivery_date, "daytext", false, $outputlangs, true);
804 $pdf->MultiCell(80, 4, $dlp, 0, 'L');
805
806 $posy = $pdf->GetY() + 1;
807 } elseif ($object->availability_code || $object->availability) {
808 // Show availability conditions
809 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
810 $pdf->SetXY($this->marge_gauche, $posy);
811 $titre = $outputlangs->transnoentities("AvailabilityPeriod").':';
812 $pdf->MultiCell(80, 4, $titre, 0, 'L');
813 $pdf->SetTextColor(0, 0, 0);
814 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
815 $pdf->SetXY($posxval, $posy);
816 $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 : '');
817 $lib_availability = str_replace('\n', "\n", $lib_availability);
818 $pdf->MultiCell(80, 4, $lib_availability, 0, 'L');
819
820 $posy = $pdf->GetY() + 1;
821 }
822
823 // Show payment mode
824 if ($object->mode_reglement_code
825 && $object->mode_reglement_code != 'CHQ'
826 && $object->mode_reglement_code != 'VIR') {
827 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
828 $pdf->SetXY($this->marge_gauche, $posy);
829 $titre = $outputlangs->transnoentities("PaymentMode").':';
830 $pdf->MultiCell(80, 5, $titre, 0, 'L');
831
832 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
833 $pdf->SetXY($posxval, $posy);
834 $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);
835 $pdf->MultiCell(80, 5, $lib_mode_reg, 0, 'L');
836
837 $posy = $pdf->GetY() + 2;
838 }
839
840 // Show payment mode CHQ
841 if (empty($object->mode_reglement_code) || $object->mode_reglement_code == 'CHQ') {
842 // Si mode reglement non force ou si force a CHQ
843 if (getDolGlobalString('FACTURE_CHQ_NUMBER')) {
844 if (getDolGlobalInt('FACTURE_CHQ_NUMBER') > 0) {
845 $account = new Account($this->db);
846 $account->fetch(getDolGlobalInt('FACTURE_CHQ_NUMBER'));
847
848 $pdf->SetXY($this->marge_gauche, $posy);
849 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
850 $pdf->MultiCell(100, 3, $outputlangs->transnoentities('PaymentByChequeOrderedTo', $account->owner_name), 0, 'L', false);
851 $posy = $pdf->GetY() + 1;
852
853 if (!getDolGlobalString('MAIN_PDF_HIDE_CHQ_ADDRESS')) {
854 $pdf->SetXY($this->marge_gauche, $posy);
855 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
856 $pdf->MultiCell(100, 3, $outputlangs->convToOutputCharset($account->owner_address), 0, 'L', false);
857 $posy = $pdf->GetY() + 2;
858 }
859 }
860 if (getDolGlobalString('FACTURE_CHQ_NUMBER') == -1) {
861 $pdf->SetXY($this->marge_gauche, $posy);
862 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
863 $pdf->MultiCell(100, 3, $outputlangs->transnoentities('PaymentByChequeOrderedTo', $this->emetteur->name), 0, 'L', false);
864 $posy = $pdf->GetY() + 1;
865
866 if (!getDolGlobalString('MAIN_PDF_HIDE_CHQ_ADDRESS')) {
867 $pdf->SetXY($this->marge_gauche, $posy);
868 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
869 $pdf->MultiCell(100, 3, $outputlangs->convToOutputCharset($this->emetteur->getFullAddress()), 0, 'L', false);
870 $posy = $pdf->GetY() + 2;
871 }
872 }
873 }
874 }
875
876 // If payment mode not forced or forced to VIR, show payment with BAN
877 if (empty($object->mode_reglement_code) || $object->mode_reglement_code == 'VIR') {
878 if ($object->fk_account > 0 || $object->fk_bank > 0 || getDolGlobalInt('FACTURE_RIB_NUMBER')) {
879 $bankid = ($object->fk_account <= 0 ? $conf->global->FACTURE_RIB_NUMBER : $object->fk_account);
880 if ($object->fk_bank > 0) {
881 $bankid = $object->fk_bank; // For backward compatibility when object->fk_account is forced with object->fk_bank
882 }
883 $account = new Account($this->db);
884 $account->fetch($bankid);
885
886 $curx = $this->marge_gauche;
887 $cury = $posy;
888
889 $posy = pdf_bank($pdf, $outputlangs, $curx, $cury, $account, 0, $default_font_size);
890
891 $posy += 2;
892 }
893 }
894
895 return $posy;
896 }
897
898 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
899 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
911 protected function _tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs, $outputlangsbis = null)
912 {
913 // phpcs:enable
914 global $conf, $mysoc, $hookmanager;
915
916 $default_font_size = pdf_getPDFFontSize($outputlangs);
917
918 if (getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE') && $outputlangs->defaultlang != getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE')) {
919 $outputlangsbis = new Translate('', $conf);
920 $outputlangsbis->setDefaultLang(getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE'));
921 $outputlangsbis->loadLangs(array("main", "dict", "companies", "bills", "products", "propal", "sendings"));
922 $default_font_size--;
923 }
924
925 $tab2_top = $posy;
926 $tab2_hl = 4;
927 $pdf->SetFont('', '', $default_font_size - 1);
928
929 // Total table
930 $col1x = 120;
931 $col2x = 170;
932 if ($this->page_largeur < 210) { // To work with US executive format
933 $col2x -= 20;
934 }
935 $largcol2 = ($this->page_largeur - $this->marge_droite - $col2x);
936
937 $useborder = 0;
938 $index = 0;
939
940 // Get Total HT
941 $total_ht = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1 ? $object->multicurrency_total_ht : $object->total_ht);
942
943 // Total discount
944 $total_discount_on_lines = 0;
945 $multicurrency_total_discount_on_lines = 0;
946 foreach ($object->lines as $i => $line) {
947 $resdiscount = pdfGetLineTotalDiscountAmount($object, $i, $outputlangs, 2);
948 $multicurrency_resdiscount = pdfGetLineTotalDiscountAmount($object, $i, $outputlangs, 2, 1);
949
950 $total_discount_on_lines += (is_numeric($resdiscount) ? $resdiscount : 0);
951 $multicurrency_total_discount_on_lines += (is_numeric($multicurrency_resdiscount) ? $multicurrency_resdiscount : 0);
952 // If line was a negative line, we do not count the discount as a discount
953 if ($line->total_ht < 0) {
954 $total_discount_on_lines += -$line->total_ht;
955 $multicurrency_total_discount_on_lines += -$line->multicurrency_total_ht;
956 }
957 }
958
959 if ($total_discount_on_lines > 0) {
960 // Show total NET before discount
961 $pdf->SetFillColor(255, 255, 255);
962 $pdf->SetXY($col1x, $tab2_top);
963 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalHTBeforeDiscount").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transnoentities("TotalHTBeforeDiscount") : ''), 0, 'L', true);
964 $pdf->SetXY($col2x, $tab2_top);
965
966 $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));
967 $pdf->MultiCell($largcol2, $tab2_hl, price($total_before_discount_to_show, 0, $outputlangs), 0, 'R', true);
968
969 $index++;
970
971 $pdf->SetFillColor(255, 255, 255);
972 $pdf->SetXY($col1x, $tab2_top + $tab2_hl);
973 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalDiscount").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transnoentities("TotalDiscount") : ''), 0, 'L', true);
974 $pdf->SetXY($col2x, $tab2_top + $tab2_hl);
975
976 $total_discount_to_show = ((isModEnabled("multicurrency") && $object->multicurrency_tx != 1) ? $multicurrency_total_discount_on_lines : $total_discount_on_lines);
977 $pdf->MultiCell($largcol2, $tab2_hl, price($total_discount_to_show, 0, $outputlangs), 0, 'R', true);
978
979 $index++;
980 }
981
982 // Total HT
983 $pdf->SetFillColor(255, 255, 255);
984 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
985 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalHT").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transnoentities("TotalHT") : ''), 0, 'L', true);
986
987 $total_ht = ((isModEnabled("multicurrency") && $object->multicurrency_tx != 1) ? $object->multicurrency_total_ht : $object->total_ht);
988 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
989 $pdf->MultiCell($largcol2, $tab2_hl, price($total_ht + (!empty($object->remise) ? $object->remise : 0), 0, $outputlangs), 0, 'R', true);
990
991 // Show VAT by rates and total
992 $pdf->SetFillColor(248, 248, 248);
993
994 $total_ttc = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1) ? $object->multicurrency_total_ttc : $object->total_ttc;
995
996 $this->atleastoneratenotnull = 0;
997 if (!getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT')) {
998 $tvaisnull = (!empty($this->tva) && count($this->tva) == 1 && isset($this->tva['0.000']) && is_float($this->tva['0.000']));
999 if (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_IFNULL') && $tvaisnull) {
1000 // Nothing to do
1001 } else {
1002 //Local tax 1 before VAT
1003 foreach ($this->localtax1 as $localtax_type => $localtax_rate) {
1004 if (in_array((string) $localtax_type, array('1', '3', '5'))) {
1005 continue;
1006 }
1007 foreach ($localtax_rate as $tvakey => $tvaval) {
1008 if ($tvakey != 0) { // On affiche pas taux 0
1009 //$this->atleastoneratenotnull++;
1010
1011 $index++;
1012 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1013
1014 $tvacompl = '';
1015 if (preg_match('/\*/', (string) $tvakey)) {
1016 $tvakey = str_replace('*', '', (string) $tvakey);
1017 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1018 }
1019 $totalvat = $outputlangs->transcountrynoentities("TotalLT1", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalLT1", $mysoc->country_code) : '');
1020 $totalvat .= ' ';
1021
1022 if (getDolGlobalString('PDF_LOCALTAX1_LABEL_IS_CODE_OR_RATE') == 'nocodenorate') {
1023 $totalvat .= $tvacompl;
1024 } else {
1025 $totalvat .= vatrate((string) abs((float) $tvakey), true).$tvacompl;
1026 }
1027
1028 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1029
1030 $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval);
1031
1032 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1033 $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', true);
1034 }
1035 }
1036 }
1037
1038 //Local tax 2 before VAT
1039 foreach ($this->localtax2 as $localtax_type => $localtax_rate) {
1040 if (in_array((string) $localtax_type, array('1', '3', '5'))) {
1041 continue;
1042 }
1043 foreach ($localtax_rate as $tvakey => $tvaval) {
1044 if ($tvakey != 0) { // On affiche pas taux 0
1045 //$this->atleastoneratenotnull++;
1046
1047 $index++;
1048 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1049
1050 $tvacompl = '';
1051 if (preg_match('/\*/', (string) $tvakey)) {
1052 $tvakey = str_replace('*', '', (string) $tvakey);
1053 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1054 }
1055 $totalvat = $outputlangs->transcountrynoentities("TotalLT2", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalLT2", $mysoc->country_code) : '');
1056 $totalvat .= ' ';
1057
1058 if (getDolGlobalString('PDF_LOCALTAX2_LABEL_IS_CODE_OR_RATE') == 'nocodenorate') {
1059 $totalvat .= $tvacompl;
1060 } else {
1061 $totalvat .= vatrate((string) abs((float) $tvakey), true).$tvacompl;
1062 }
1063
1064 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1065
1066 $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval);
1067
1068 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1069 $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', true);
1070 }
1071 }
1072 }
1073
1074 // VAT
1075 foreach ($this->tva_array as $tvakey => $tvaval) {
1076 if ($tvakey != 0) { // On affiche pas taux 0
1077 $this->atleastoneratenotnull++;
1078
1079 $index++;
1080 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1081
1082 $tvacompl = '';
1083 if (preg_match('/\*/', $tvakey)) {
1084 $tvakey = str_replace('*', '', $tvakey);
1085 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1086 }
1087 $totalvat = $outputlangs->transcountrynoentities("TotalVAT", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalVAT", $mysoc->country_code) : '');
1088 $totalvat .= ' ';
1089 if (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'rateonly') {
1090 $totalvat .= vatrate((string) $tvaval['vatrate'], true).$tvacompl;
1091 } elseif (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'codeonly') {
1092 $totalvat .= $tvaval['vatcode'].$tvacompl;
1093 } elseif (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'nocodenorate') {
1094 $totalvat .= $tvacompl;
1095 } else {
1096 $totalvat .= vatrate((string) $tvaval['vatrate'], true).($tvaval['vatcode'] ? ' ('.$tvaval['vatcode'].')' : '').$tvacompl;
1097 }
1098 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1099
1100 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1101 $pdf->MultiCell($largcol2, $tab2_hl, price(price2num($tvaval['amount'], 'MT'), 0, $outputlangs), 0, 'R', true);
1102 }
1103 }
1104
1105 //Local tax 1 after VAT
1106 //if (getDolGlobalString('FACTURE_LOCAL_TAX1_OPTION') && getDolGlobalString('FACTURE_LOCAL_TAX1_OPTION() == 'localtax1on')
1107 //{
1108 foreach ($this->localtax1 as $localtax_type => $localtax_rate) {
1109 if (in_array((string) $localtax_type, array('2', '4', '6'))) {
1110 continue;
1111 }
1112
1113 foreach ($localtax_rate as $tvakey => $tvaval) {
1114 if ($tvakey != 0) { // On affiche pas taux 0
1115 //$this->atleastoneratenotnull++;
1116
1117 $index++;
1118 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1119
1120 $tvacompl = '';
1121 if (preg_match('/\*/', (string) $tvakey)) {
1122 $tvakey = str_replace('*', '', (string) $tvakey);
1123 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1124 }
1125 $totalvat = $outputlangs->transcountrynoentities("TotalLT1", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalLT1", $mysoc->country_code) : '');
1126 $totalvat .= ' ';
1127
1128 if (getDolGlobalString('PDF_LOCALTAX1_LABEL_IS_CODE_OR_RATE') == 'nocodenorate') {
1129 $totalvat .= $tvacompl;
1130 } else {
1131 $totalvat .= vatrate((string) abs((float) $tvakey), true).$tvacompl;
1132 }
1133
1134 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1135
1136 $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval);
1137
1138 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1139 $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', true);
1140 }
1141 }
1142 }
1143 //}
1144 //Local tax 2 after VAT
1145 //if (getDolGlobalString('FACTURE_LOCAL_TAX2_OPTION') && getDolGlobalString('FATURE_LOCAL_TAX2_OPTION') == 'localtax2on')
1146 //{
1147 foreach ($this->localtax2 as $localtax_type => $localtax_rate) {
1148 if (in_array((string) $localtax_type, array('2', '4', '6'))) {
1149 continue;
1150 }
1151
1152 foreach ($localtax_rate as $tvakey => $tvaval) {
1153 // retrieve global local tax
1154 if ($tvakey != 0) { // On affiche pas taux 0
1155 //$this->atleastoneratenotnull++;
1156
1157 $index++;
1158 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1159
1160 $tvacompl = '';
1161 if (preg_match('/\*/', (string) $tvakey)) {
1162 $tvakey = str_replace('*', '', (string) $tvakey);
1163 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1164 }
1165 $totalvat = $outputlangs->transcountrynoentities("TotalLT2", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalLT2", $mysoc->country_code) : '');
1166 $totalvat .= ' ';
1167
1168 if (getDolGlobalString('PDF_LOCALTAX2_LABEL_IS_CODE_OR_RATE') == 'nocodenorate') {
1169 $totalvat .= $tvacompl;
1170 } else {
1171 $totalvat .= vatrate((string) abs((float) $tvakey), true).$tvacompl;
1172 }
1173
1174 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1175
1176 $total_localtax = ((isModEnabled("multicurrency") && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval);
1177
1178 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1179 $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', true);
1180 }
1181 }
1182 }
1183 //}
1184
1185 // Total TTC
1186 $index++;
1187 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1188 $pdf->SetTextColor(0, 0, 60);
1189 $pdf->SetFillColor(224, 224, 224);
1190 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalTTC").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalTTC", $mysoc->country_code) : ''), $useborder, 'L', true);
1191
1192 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1193 $pdf->MultiCell($largcol2, $tab2_hl, price($total_ttc, 0, $outputlangs), $useborder, 'R', true);
1194 }
1195 }
1196
1197 $pdf->SetTextColor(0, 0, 0);
1198
1199 $creditnoteamount = 0;
1200 $depositsamount = 0;
1201 //$creditnoteamount=$object->getSumCreditNotesUsed();
1202 //$depositsamount=$object->getSumDepositsUsed();
1203 //print "x".$creditnoteamount."-".$depositsamount;exit;
1204 $resteapayer = price2num($total_ttc - $deja_regle - $creditnoteamount - $depositsamount, 'MT');
1205 if (!empty($object->paye)) {
1206 $resteapayer = 0;
1207 }
1208
1209 if ($deja_regle > 0) {
1210 // Already paid + Deposits
1211 $index++;
1212
1213 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1214 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("AlreadyPaid").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transnoentities("AlreadyPaid") : ''), 0, 'L', false);
1215 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1216 $pdf->MultiCell($largcol2, $tab2_hl, price($deja_regle, 0, $outputlangs), 0, 'R', false);
1217
1218 $index++;
1219 $pdf->SetTextColor(0, 0, 60);
1220 $pdf->SetFillColor(224, 224, 224);
1221 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1222 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("RemainderToPay").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transnoentities("AlreadyPaid") : ''), $useborder, 'L', true);
1223
1224 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1225 $pdf->MultiCell($largcol2, $tab2_hl, price($resteapayer, 0, $outputlangs), $useborder, 'R', true);
1226
1227 $pdf->SetFont('', '', $default_font_size - 1);
1228 $pdf->SetTextColor(0, 0, 0);
1229 }
1230
1231 $index++;
1232 return ($tab2_top + ($tab2_hl * $index));
1233 }
1234
1235 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1250 protected function _tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop = 0, $hidebottom = 0, $currency = '', $outputlangsbis = null)
1251 {
1252 global $conf;
1253
1254 // Force to disable hidetop and hidebottom
1255 $hidebottom = 0;
1256 if ($hidetop) {
1257 $hidetop = -1;
1258 }
1259
1260 $currency = !empty($currency) ? $currency : getDolCurrency();
1261 $default_font_size = pdf_getPDFFontSize($outputlangs);
1262
1263 // Amount in (at tab_top - 1)
1264 $pdf->SetTextColor(0, 0, 0);
1265 $pdf->SetFont('', '', $default_font_size - 2);
1266
1267 if (empty($hidetop)) {
1268 $titre = $outputlangs->transnoentities("AmountInCurrency", $outputlangs->transnoentitiesnoconv("Currency".$currency));
1269 if (getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE') && is_object($outputlangsbis)) {
1270 $titre .= ' - '.$outputlangsbis->transnoentities("AmountInCurrency", $outputlangsbis->transnoentitiesnoconv("Currency".$currency));
1271 }
1272
1273 $pdf->SetXY($this->page_largeur - $this->marge_droite - ($pdf->GetStringWidth($titre) + 3), $tab_top - 4);
1274 $pdf->MultiCell(($pdf->GetStringWidth($titre) + 3), 2, $titre);
1275
1276 //$conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR='230,230,230';
1277 if (getDolGlobalString('MAIN_PDF_TITLE_BACKGROUND_COLOR')) {
1278 $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')));
1279 }
1280 }
1281
1282 $pdf->SetDrawColor(128, 128, 128);
1283 $pdf->SetFont('', '', $default_font_size - 1);
1284
1285 // Output Rect
1286 $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
1287
1288 if (empty($hidetop)) {
1289 $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
1290
1291 $pdf->SetXY($this->posxdesc - 1, $tab_top + 1);
1292 $pdf->MultiCell(108, 2, $outputlangs->transnoentities("Designation"), '', 'L');
1293 }
1294
1295 if (!getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT') && !getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_COLUMN')) {
1296 $pdf->line($this->posxtva - 1, $tab_top, $this->posxtva - 1, $tab_top + $tab_height);
1297 if (empty($hidetop)) {
1298 $pdf->SetXY($this->posxtva - 3, $tab_top + 1);
1299 $pdf->MultiCell($this->posxup - $this->posxtva + 3, 2, $outputlangs->transnoentities("VAT"), '', 'C');
1300 }
1301 }
1302
1303 $pdf->line($this->posxup - 1, $tab_top, $this->posxup - 1, $tab_top + $tab_height);
1304 if (empty($hidetop)) {
1305 $pdf->SetXY($this->posxup - 1, $tab_top + 1);
1306 $pdf->MultiCell($this->posxqty - $this->posxup - 1, 2, $outputlangs->transnoentities("PriceUHT"), '', 'C');
1307 }
1308
1309 $pdf->line($this->posxqty - 1, $tab_top, $this->posxqty - 1, $tab_top + $tab_height);
1310 if (empty($hidetop)) {
1311 $pdf->SetXY($this->posxqty - 1, $tab_top + 1);
1312 $pdf->MultiCell($this->posxunit - $this->posxqty - 1, 2, $outputlangs->transnoentities("Qty"), '', 'C');
1313 }
1314
1315 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
1316 $pdf->line($this->posxunit - 1, $tab_top, $this->posxunit - 1, $tab_top + $tab_height);
1317 if (empty($hidetop)) {
1318 $pdf->SetXY($this->posxunit - 1, $tab_top + 1);
1319 $pdf->MultiCell($this->posxdiscount - $this->posxunit - 1, 2, $outputlangs->transnoentities("Unit"), '', 'C');
1320 }
1321 }
1322
1323 $pdf->line($this->posxdiscount - 1, $tab_top, $this->posxdiscount - 1, $tab_top + $tab_height);
1324 if (empty($hidetop)) {
1325 if ($this->atleastonediscount) {
1326 $pdf->SetXY($this->posxdiscount - 1, $tab_top + 1);
1327 $pdf->MultiCell($this->postotalht - $this->posxdiscount + 1, 2, $outputlangs->transnoentities("ReductionShort"), '', 'C');
1328 }
1329 }
1330
1331 if ($this->atleastonediscount) {
1332 $pdf->line($this->postotalht, $tab_top, $this->postotalht, $tab_top + $tab_height);
1333 }
1334 if (empty($hidetop)) {
1335 $pdf->SetXY($this->postotalht - 1, $tab_top + 1);
1336 $pdf->MultiCell(30, 2, $outputlangs->transnoentities("TotalHTShort"), '', 'C');
1337 }
1338 }
1339
1340 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1341 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1353 protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $outputlangsbis = null, $titlekey = "PdfOrderTitle")
1354 {
1355 // phpcs:enable
1356 global $conf, $langs, $hookmanager;
1357
1358 $ltrdirection = 'L';
1359 if ($outputlangs->trans("DIRECTION") == 'rtl') {
1360 $ltrdirection = 'R';
1361 }
1362
1363 // Load traductions files required by page
1364 $outputlangs->loadLangs(array("main", "bills", "propal", "orders", "companies"));
1365
1366 $default_font_size = pdf_getPDFFontSize($outputlangs);
1367
1368 pdf_pagehead($pdf, $outputlangs, $this->page_hauteur);
1369
1370 $pdf->SetTextColor(0, 0, 60);
1371 $pdf->SetFont('', 'B', $default_font_size + 3);
1372
1373 $w = 100;
1374
1375 $posy = $this->marge_haute;
1376 $posx = $this->page_largeur - $this->marge_droite - $w;
1377
1378 $pdf->SetXY($this->marge_gauche, $posy);
1379
1380 // Logo
1381 if (!getDolGlobalInt('PDF_DISABLE_MYCOMPANY_LOGO')) {
1382 if ($this->emetteur->logo) {
1383 $logodir = $conf->mycompany->dir_output;
1384 if (!empty($conf->mycompany->multidir_output[$object->entity ?? $conf->entity])) {
1385 $logodir = $conf->mycompany->multidir_output[$object->entity ?? $conf->entity];
1386 }
1387 if (!getDolGlobalInt('MAIN_PDF_USE_LARGE_LOGO')) {
1388 $logo = $logodir.'/logos/thumbs/'.$this->emetteur->logo_small;
1389 } else {
1390 $logo = $logodir.'/logos/'.$this->emetteur->logo;
1391 }
1392 if (is_readable($logo)) {
1393 $height = pdf_getHeightForLogo($logo);
1394 $pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto)
1395 } else {
1396 $pdf->SetTextColor(200, 0, 0);
1397 $pdf->SetFont('', 'B', $default_font_size - 2);
1398 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound", $logo), 0, 'L');
1399 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ErrorGoToGlobalSetup"), 0, 'L');
1400 }
1401 } else {
1402 $text = $this->emetteur->name;
1403 $pdf->MultiCell($w, 4, $outputlangs->convToOutputCharset($text), 0, $ltrdirection);
1404 }
1405 }
1406
1407 $pdf->SetFont('', 'B', $default_font_size + 3);
1408 $pdf->SetXY($posx, $posy);
1409 $pdf->SetTextColor(0, 0, 60);
1410 $title = $outputlangs->transnoentities($titlekey);
1411 $title .= ' '.$outputlangs->convToOutputCharset($object->ref);
1412 if ($object->statut == $object::STATUS_DRAFT) {
1413 $pdf->SetTextColor(128, 0, 0);
1414 $title .= ' - '.$outputlangs->transnoentities("NotValidated");
1415 }
1416 $pdf->MultiCell($w, 3, $title, '', 'R');
1417
1418 $pdf->SetFont('', 'B', $default_font_size);
1419
1420 /*
1421 $posy += 5;
1422 $pdf->SetXY($posx, $posy);
1423 $pdf->SetTextColor(0, 0, 60);
1424 $pdf->MultiCell(100, 4, $outputlangs->transnoentities("Ref")." : ".$outputlangs->convToOutputCharset($object->ref), '', 'R');
1425 */
1426
1427 $posy += 3;
1428 $pdf->SetFont('', '', $default_font_size - 1);
1429
1430 if ($object->ref_client) {
1431 $posy += 5;
1432 $pdf->SetXY($posx, $posy);
1433 $pdf->SetTextColor(0, 0, 60);
1434 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("RefCustomer")." : ".$outputlangs->convToOutputCharset($object->ref_client), '', 'R');
1435 }
1436
1437 if (getDolGlobalString('PDF_SHOW_PROJECT_TITLE')) {
1438 $object->fetchProject();
1439 if (!empty($object->project->ref)) {
1440 $posy = $pdf->GetY();
1441 $pdf->SetXY($posx, $posy);
1442 $pdf->SetTextColor(0, 0, 60);
1443 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("Project")." : ".(empty($object->project->title) ? '' : $object->project->title), '', 'R');
1444 }
1445 }
1446
1447 if (getDolGlobalString('PDF_SHOW_PROJECT')) {
1448 $object->fetchProject();
1449 if (!empty($object->project->ref)) {
1450 $outputlangs->load("projects");
1451 $posy = $pdf->GetY();
1452 $pdf->SetXY($posx, $posy);
1453 $pdf->SetTextColor(0, 0, 60);
1454 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("RefProject")." : ".(empty($object->project->ref) ? '' : $object->project->ref), '', 'R');
1455 }
1456 }
1457
1458 $posy = $pdf->GetY();
1459 $pdf->SetXY($posx, $posy);
1460 $pdf->SetTextColor(0, 0, 60);
1461 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("OrderDate")." : ".dol_print_date($object->date, "day", false, $outputlangs, true), '', 'R');
1462
1463 if (!getDolGlobalString('MAIN_PDF_HIDE_CUSTOMER_CODE') && !empty($object->thirdparty->code_client)) {
1464 $posy = $pdf->GetY();
1465 $pdf->SetXY($posx, $posy);
1466 $pdf->SetTextColor(0, 0, 60);
1467 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("CustomerCode")." : ".$outputlangs->transnoentities($object->thirdparty->code_client), '', 'R');
1468 }
1469
1470 if (!getDolGlobalString('MAIN_PDF_HIDE_CUSTOMER_ACCOUNTING_CODE') && !empty($object->thirdparty->code_compta_client)) {
1471 $posy += 4;
1472 $pdf->SetXY($posx, $posy);
1473 $pdf->SetTextColor(0, 0, 60);
1474 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("CustomerAccountancyCode")." : ".$outputlangs->transnoentities($object->thirdparty->code_compta_client), '', 'R');
1475 }
1476
1477 // Get contact
1478 if (getDolGlobalString('DOC_SHOW_FIRST_SALES_REP')) {
1479 $arrayidcontact = $object->getIdContact('internal', 'SALESREPFOLL');
1480 if (count($arrayidcontact) > 0) {
1481 $usertmp = new User($this->db);
1482 $usertmp->fetch($arrayidcontact[0]);
1483 $posy += 4;
1484 $pdf->SetXY($posx, $posy);
1485 $pdf->SetTextColor(0, 0, 60);
1486 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R');
1487 }
1488 }
1489
1490 $posy += 2;
1491
1492 $top_shift = 0;
1493 $shipp_shift = 0;
1494 // Show list of linked objects
1495 $current_y = $pdf->getY();
1496 $posy = pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, $w, 3, 'R', $default_font_size);
1497 if ($current_y < $pdf->getY()) {
1498 $top_shift = $pdf->getY() - $current_y;
1499 }
1500
1501 if ($showaddress) {
1502 // Sender properties
1503 $carac_emetteur = '';
1504 // Add internal contact of object if defined
1505 $arrayidcontact = $object->getIdContact('internal', 'SALESREPFOLL');
1506 if (count($arrayidcontact) > 0) {
1507 $object->fetch_user($arrayidcontact[0]);
1508 $labelbeforecontactname = ($outputlangs->transnoentities("FromContactName") != 'FromContactName' ? $outputlangs->transnoentities("FromContactName") : $outputlangs->transnoentities("Name"));
1509 $carac_emetteur .= ($carac_emetteur ? "\n" : '').$labelbeforecontactname." ".$outputlangs->convToOutputCharset($object->user->getFullName($outputlangs));
1510 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') || getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ' (' : '';
1511 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') && !empty($object->user->office_phone)) ? $object->user->office_phone : '';
1512 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') && getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ', ' : '';
1513 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT') && !empty($object->user->email)) ? $object->user->email : '';
1514 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') || getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ')' : '';
1515 $carac_emetteur .= "\n";
1516 }
1517
1518 $carac_emetteur .= pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, '', 0, 'source', $object);
1519
1520 // Show sender
1521 $posy = 42 + $top_shift;
1522 $posx = $this->marge_gauche;
1523 if (getDolGlobalString('MAIN_INVERT_SENDER_RECIPIENT')) {
1524 $posx = $this->page_largeur - $this->marge_droite - 80;
1525 }
1526 $hautcadre = 40;
1527
1528 // Show sender frame
1529 if (!getDolGlobalString('MAIN_PDF_NO_SENDER_FRAME')) {
1530 $pdf->SetTextColor(0, 0, 0);
1531 $pdf->SetFont('', '', $default_font_size - 2);
1532 $pdf->SetXY($posx, $posy - 5);
1533 $pdf->MultiCell(80, 5, $outputlangs->transnoentities("BillFrom"), 0, $ltrdirection);
1534 $pdf->SetXY($posx, $posy);
1535 $pdf->SetFillColor(230, 230, 230);
1536 $pdf->RoundedRect($posx, $posy, 82, $hautcadre, $this->corner_radius, '1234', 'F');
1537 $pdf->SetTextColor(0, 0, 60);
1538 }
1539
1540 // Show sender name
1541 if (!getDolGlobalString('MAIN_PDF_HIDE_SENDER_NAME')) {
1542 $pdf->SetXY($posx + 2, $posy + 3);
1543 $pdf->SetFont('', 'B', $default_font_size);
1544 $pdf->MultiCell(80, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, $ltrdirection);
1545 $posy = $pdf->getY();
1546 }
1547
1548 // Show sender information
1549 $pdf->SetXY($posx + 2, $posy);
1550 $pdf->SetFont('', '', $default_font_size - 1);
1551 $pdf->MultiCell(80, 4, $carac_emetteur, 0, 'L');
1552
1553
1554 // If CUSTOMER contact defined, we use it
1555 $usecontact = false;
1556 $arrayidcontact = $object->getIdContact('external', 'CUSTOMER');
1557 if (count($arrayidcontact) > 0) {
1558 $usecontact = true;
1559 $result = $object->fetch_contact($arrayidcontact[0]);
1560 }
1561
1562 // Recipient name
1563 if ($usecontact && ($object->contact->socid != $object->thirdparty->id && (!isset($conf->global->MAIN_USE_COMPANY_NAME_OF_CONTACT) || getDolGlobalString('MAIN_USE_COMPANY_NAME_OF_CONTACT')))) {
1564 $thirdparty = $object->contact;
1565 } else {
1566 $thirdparty = $object->thirdparty;
1567 }
1568
1569 $carac_client_name = pdfBuildThirdpartyName($thirdparty, $outputlangs);
1570
1571 $mode = 'target';
1572 $carac_client = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, ($usecontact ? $object->contact : ''), ($usecontact ? 1 : 0), $mode, $object);
1573
1574 // Show recipient
1575 $widthrecbox = getDolGlobalString('MAIN_PDF_USE_ISO_LOCATION') ? 92 : 100;
1576 if ($this->page_largeur < 210) {
1577 $widthrecbox = 84; // To work with US executive format
1578 }
1579 $posy = getDolGlobalString('MAIN_PDF_USE_ISO_LOCATION') ? 40 : 42;
1580 $posy += $top_shift;
1581 $posx = $this->page_largeur - $this->marge_droite - $widthrecbox;
1582 if (getDolGlobalString('MAIN_INVERT_SENDER_RECIPIENT')) {
1583 $posx = $this->marge_gauche;
1584 }
1585
1586 // Show recipient frame
1587 if (!getDolGlobalString('MAIN_PDF_NO_RECIPENT_FRAME')) {
1588 $pdf->SetTextColor(0, 0, 0);
1589 $pdf->SetFont('', '', $default_font_size - 2);
1590 $pdf->SetXY($posx + 2, $posy - 5);
1591 $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillTo"), 0, $ltrdirection);
1592 $pdf->RoundedRect($posx, $posy, $widthrecbox, $hautcadre, $this->corner_radius, '1234', 'D');
1593 }
1594
1595 // Show recipient name
1596 $pdf->SetXY($posx + 2, $posy + 3);
1597 $pdf->SetFont('', 'B', $default_font_size);
1598 // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
1599 $pdf->MultiCell($widthrecbox, 2, $carac_client_name, 0, $ltrdirection);
1600
1601 $posy = $pdf->getY();
1602
1603 // Show recipient information
1604 $pdf->SetFont('', '', $default_font_size - 1);
1605 $pdf->SetXY($posx + 2, $posy);
1606 // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
1607 $pdf->MultiCell($widthrecbox, 4, $carac_client, 0, $ltrdirection);
1608
1609 // Show shipping address
1610 if (getDolGlobalInt('SALES_ORDER_SHOW_SHIPPING_ADDRESS')) {
1611 $idaddressshipping = $object->getIdContact('external', 'SHIPPING');
1612
1613 if (!empty($idaddressshipping)) {
1614 $contactshipping = $object->fetch_Contact($idaddressshipping[0]);
1615 $companystatic = new Societe($this->db);
1616 $companystatic->fetch($object->contact->fk_soc);
1617 $carac_client_name_shipping = pdfBuildThirdpartyName($object->contact, $outputlangs);
1618 $carac_client_shipping = pdf_build_address($outputlangs, $this->emetteur, $companystatic, $object->contact, 1, 'target', $object);
1619 } else {
1620 $carac_client_name_shipping = pdfBuildThirdpartyName($object->thirdparty, $outputlangs);
1621 $carac_client_shipping = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, '', 0, 'target', $object);
1622 }
1623 if (!empty($carac_client_shipping)) {
1624 $posy += $hautcadre;
1625
1626 $hautcadre -= 10; // Height for the shipping address does not need to be as high as main box
1627
1628 // Show shipping frame
1629 $pdf->SetXY($posx + 2, $posy - 5);
1630 $pdf->SetFont('', '', $default_font_size - 2);
1631 $pdf->MultiCell($widthrecbox, 0, $outputlangs->transnoentities('ShippingTo'), 0, 'L', false);
1632 $pdf->RoundedRect($posx, $posy, $widthrecbox, $hautcadre, $this->corner_radius, '1234', 'D');
1633
1634 // Show shipping name
1635 $pdf->SetXY($posx + 2, $posy + 1);
1636 $pdf->SetFont('', 'B', $default_font_size);
1637 $pdf->MultiCell($widthrecbox - 2, 2, $carac_client_name_shipping, '', 'L');
1638
1639 $posy = $pdf->getY();
1640
1641 // Show shipping information
1642 $pdf->SetXY($posx + 2, $posy);
1643 $pdf->SetFont('', '', $default_font_size - 1);
1644 $pdf->MultiCell($widthrecbox - 2, 2, $carac_client_shipping, '', 'L');
1645
1646 $shipp_shift += $hautcadre + 10;
1647 }
1648 }
1649 }
1650
1651 $pdf->SetTextColor(0, 0, 0);
1652
1653 $pagehead = array('top_shift' => $top_shift, 'shipp_shift' => $shipp_shift);
1654
1655 return $pagehead;
1656 }
1657
1658 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1659 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1669 protected function _pagefoot(&$pdf, $object, $outputlangs, $hidefreetext = 0)
1670 {
1671 // phpcs:enable
1672 $showdetails = getDolGlobalInt('MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS', 0);
1673 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);
1674 }
1675}
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
Class to manage bank accounts.
printRoundedRect($pdf, $x, $y, $w, $h, $r, $hidetop=0, $hidebottom=0, $style='D')
Print a rounded rectangle on the PDF.
Class to manage 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.
global $mysoc
print $script_file $mode $langs defaultlang(is_numeric($duration_value) ? " delay=". $duration_value :"").(is_numeric($duration_value2) ? " after cd cd cd description as description
Only used if Module[ID]Desc translation string is not found.
if(!function_exists( 'dolEscapeXML')) convertBackOfficeMediasLinksToPublicLinks($notetoshow)
Convert links to local wrapper to medias files into a string into a public external URL readable on i...
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
vatrate($rate, $addpercent=false, $info_bits=0, $usestarfornpr=0, $html=0)
Return a string with VAT rate label formatted for view output Used into pdf and HTML pages.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
getCallerInfoString()
Get caller info as a string that can be appended to a log message.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
dolChmod($filepath, $newmask='')
Change mod of a file.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
getLocalTaxesFromRate($vatrate, $local, $buyer, $seller, $firstparamisid=0)
Get type and rate of localtaxes for a particular vat rate/country of a thirdparty.
dol_concatdesc($text1, $text2, $forxml=false, $invert=false)
Concat 2 descriptions with a new line between them (second operand after first one with appropriate n...
getDolCurrency()
Return the main currency ('EUR', 'USD', ...)
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_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
dol_htmlentitiesbr($stringtoencode, $nl2brmode=0, $pagecodefrom='UTF-8', $removelasteolbr=1)
This function is called to encode a string into a HTML string but differs from htmlentities because a...
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
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_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:1535
pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line total excluding tax.
Definition pdf.lib.php:2550
pdf_getFormat($outputlangs=null, $mode='setup')
Return array with format properties of default PDF format.
Definition pdf.lib.php:87
pdfGetLineTotalDiscountAmount($object, $i, $outputlangs, $hidedetails=0, $multicurrency=0)
Return line total amount discount.
Definition pdf.lib.php:2881
pdf_getPDFFontSize($outputlangs)
Return font size to use for PDF generation.
Definition pdf.lib.php:289
pdf_getHeightForLogo($logo, $url=false)
Return height to use for Logo onto PDF.
Definition pdf.lib.php:312
pdf_pagefoot(&$pdf, $outputlangs, $paramfreetext, $fromcompany, $marge_basse, $marge_gauche, $page_hauteur, $object, $showdetails=0, $hidefreetext=0, $page_largeur=0, $watermark='')
Show footer of page for PDF generation.
Definition pdf.lib.php:1110
pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line unit price excluding tax.
Definition pdf.lib.php:2153
pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails=0)
Return line vat rate.
Definition pdf.lib.php:2091
pdf_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:1497
pdf_bank(&$pdf, $outputlangs, $curx, $cury, $account, $onlynumber=0, $default_font_size=10)
Show bank information for PDF generation.
Definition pdf.lib.php:928
pdf_getPDFFont($outputlangs)
Return font name to use for PDF generation.
Definition pdf.lib.php:268
pdf_build_address($outputlangs, $sourcecompany, $targetcompany='', $targetcontact='', $usecontact=0, $mode='source', $object=null)
Return a string with full address formatted for output on PDF documents.
Definition pdf.lib.php:433
pdf_getlineunit($object, $i, $outputlangs, $hidedetails=0)
Return line unit.
Definition pdf.lib.php:2398
pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails=0)
Return line remise percent.
Definition pdf.lib.php:2441
pdf_getlineqty($object, $i, $outputlangs, $hidedetails=0)
Return line quantity.
Definition pdf.lib.php:2238
pdf_getSubstitutionArray($outputlangs, $exclude=null, $object=null, $onlykey=0, $include=null)
Return array of possible substitutions for PDF content (without external module substitutions).
Definition pdf.lib.php:824
pdf_getInstance($format='', $metric='mm', $pagetype='P')
Return a PDF instance object.
Definition pdf.lib.php:129
pdfBuildThirdpartyName($thirdparty, Translate $outputlangs, $includealias=0)
Returns the name of the thirdparty.
Definition pdf.lib.php:388
if(preg_match('/(crypted|dolcrypt):/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
'integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]',...
Definition repair.php:125
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:128