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