dolibarr 25.0.0-alpha
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 = 80 + $this->marge_haute + $top_shift + $shipp_shift;
335 $tab_top_newpage = (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD') ? 32 + $this->marge_haute + $top_shift : $this->marge_haute);
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 $vatrate = (string) $object->lines[$i]->tva_tx;
518
519 // Retrieve type from database for backward compatibility with old records
520 if ((!isset($localtax1_type) || $localtax1_type == '' || !isset($localtax2_type) || $localtax2_type == '') // if tax type not defined
521 && (!empty($localtax1_rate) || !empty($localtax2_rate))) { // and there is local tax
522 $localtaxtmp_array = getLocalTaxesFromRate($vatrate, 0, $object->thirdparty, $mysoc);
523 $localtax1_type = isset($localtaxtmp_array[0]) ? $localtaxtmp_array[0] : '';
524 $localtax2_type = isset($localtaxtmp_array[2]) ? $localtaxtmp_array[2] : '';
525 }
526
527 // retrieve global local tax
528 if ($localtax1_type && $localtax1ligne != 0) {
529 if (empty($this->localtax1[$localtax1_type][$localtax1_rate])) {
530 $this->localtax1[$localtax1_type][$localtax1_rate] = $localtax1ligne;
531 } else {
532 $this->localtax1[$localtax1_type][$localtax1_rate] += $localtax1ligne;
533 }
534 }
535 if ($localtax2_type && $localtax2ligne != 0) {
536 if (empty($this->localtax2[$localtax2_type][$localtax2_rate])) {
537 $this->localtax2[$localtax2_type][$localtax2_rate] = $localtax2ligne;
538 } else {
539 $this->localtax2[$localtax2_type][$localtax2_rate] += $localtax2ligne;
540 }
541 }
542
543 if (($object->lines[$i]->info_bits & 0x01) == 0x01) {
544 $vatrate .= '*';
545 }
546
547 // Fill $this->tva and $this->tva_array
548 if (!isset($this->tva[$vatrate])) {
549 $this->tva[$vatrate] = 0;
550 }
551 $this->tva[$vatrate] += $tvaligne;
552 $vatcode = $object->lines[$i]->vat_src_code;
553 if (empty($this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'])) {
554 $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'] = 0;
555 }
556 $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')] = array('vatrate' => $vatrate, 'vatcode' => $vatcode, 'amount' => $this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'] + $tvaligne);
557
558 // Add line
559 if (getDolGlobalString('MAIN_PDF_DASH_BETWEEN_LINES') && $i < ($nblines - 1)) {
560 $pdf->setPage($pageposafter);
561 $pdf->SetLineStyle(array('dash' => '1,1', 'color' => array(80, 80, 80)));
562 //$pdf->SetDrawColor(190,190,200);
563 $pdf->line($this->marge_gauche, $nexY + 1, $this->page_largeur - $this->marge_droite, $nexY + 1);
564 $pdf->SetLineStyle(array('dash' => 0));
565 }
566
567 $nexY += 2; // Add space between lines
568
569 // Detect if some page were added automatically and output _tableau for past pages
570 while ($pagenb < $pageposafter) {
571 $pdf->setPage($pagenb);
572 if ($pagenb == 1) {
573 $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1, $object->multicurrency_code);
574 } else {
575 $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code);
576 }
577 $this->_pagefoot($pdf, $object, $outputlangs, 1);
578 $pagenb++;
579 $pdf->setPage($pagenb);
580 $pdf->setPageOrientation('', true, 0); // The only function to edit the bottom margin of current page to set it.
581 if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
582 $this->_pagehead($pdf, $object, 0, $outputlangs);
583 }
584 if (!empty($tplidx)) {
585 $pdf->useTemplate($tplidx);
586 }
587 }
588 if (isset($object->lines[$i + 1]->pagebreak) && $object->lines[$i + 1]->pagebreak) { // @phan-suppress-current-line PhanUndeclaredProperty
589 if ($pagenb == 1) {
590 $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1, $object->multicurrency_code);
591 } else {
592 $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code);
593 }
594 $this->_pagefoot($pdf, $object, $outputlangs, 1);
595 // New page
596 $pdf->AddPage();
597 if (!empty($tplidx)) {
598 $pdf->useTemplate($tplidx);
599 }
600 $pagenb++;
601 if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
602 $this->_pagehead($pdf, $object, 0, $outputlangs);
603 }
604 }
605 }
606
607 // Show square
608 if ($pagenb == 1) {
609 $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 0, 0, $object->multicurrency_code);
610 } else {
611 $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 1, 0, $object->multicurrency_code);
612 }
613 $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
614
615 // Display infos area
616 $posy = $this->_tableau_info($pdf, $object, $bottomlasttab, $outputlangs);
617
618 // Display total zone
619 $posy = $this->_tableau_tot($pdf, $object, $deja_regle, $bottomlasttab, $outputlangs);
620
621 // Affiche zone versements
622 /*
623 if ($deja_regle)
624 {
625 $posy=$this->_tableau_versements($pdf, $object, $posy, $outputlangs);
626 }
627 */
628
629 // Pied de page
630 $this->_pagefoot($pdf, $object, $outputlangs);
631 if (method_exists($pdf, 'AliasNbPages')) {
632 $pdf->AliasNbPages(); // @phan-suppress-current-line PhanUndeclaredMethod
633 }
634
635 // Add terms to sale
636 $termsofsalefilename = getDolGlobalString('MAIN_INFO_ORDER_TERMSOFSALE');
637 if (getDolGlobalInt('MAIN_PDF_ADD_TERMSOFSALE_ORDER') && $termsofsalefilename) {
638 $termsofsale = $conf->order->dir_output.'/'.$termsofsalefilename;
639 if (!empty($conf->order->multidir_output[$conf->entity])) {
640 $termsofsale = $conf->order->multidir_output[$conf->entity].'/'.$termsofsalefilename;
641 }
642 if (file_exists($termsofsale) && is_readable($termsofsale)) {
643 $pagecount = $pdf->setSourceFile($termsofsale);
644 for ($i = 1; $i <= $pagecount; $i++) {
645 $tplIdx = $pdf->importPage($i);
646 if ($tplIdx !== false) {
647 $s = $pdf->getTemplatesize($tplIdx);
648 $pdf->AddPage($s['h'] > $s['w'] ? 'P' : 'L');
649 $pdf->useTemplate($tplIdx);
650 } else {
651 setEventMessages(null, array($termsofsale.' cannot be added, probably protected PDF'), 'warnings');
652 }
653 }
654 }
655 }
656
657 $pdf->Close();
658
659 $pdf->Output($file, 'F');
660
661 // Add pdfgeneration hook
662 $hookmanager->initHooks(array('pdfgeneration'));
663 $parameters = array('file' => $file, 'object' => $object, 'outputlangs' => $outputlangs);
664 global $action;
665 $reshook = $hookmanager->executeHooks('afterPDFCreation', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
666 $this->warnings = $hookmanager->warnings;
667 if ($reshook < 0) {
668 $this->error = $hookmanager->error;
669 $this->errors = $hookmanager->errors;
670 dolChmod($file);
671 return -1;
672 }
673
674 dolChmod($file);
675
676 $this->result = array('fullpath' => $file);
677
678 return 1; // No error
679 } else {
680 $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
681 return 0;
682 }
683 } else {
684 $this->error = $langs->transnoentities("ErrorConstantNotDefined", "COMMANDE_OUTPUTDIR");
685 return 0;
686 }
687 }
688
689 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
690 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
700 protected function _tableau_versements(&$pdf, $object, $posy, $outputlangs)
701 {
702 // phpcs:enable
703 return 1;
704 }
705
706 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
707 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
717 protected function _tableau_info(&$pdf, $object, $posy, $outputlangs)
718 {
719 // phpcs:enable
720 global $conf, $mysoc;
721 $default_font_size = pdf_getPDFFontSize($outputlangs);
722
723 $pdf->SetFont('', '', $default_font_size - 1);
724
725 $diffsizetitle = getDolGlobalInt('PDF_DIFFSIZE_TITLE', 3);
726
727 // If France, show VAT mention if not applicable
728 if ($this->emetteur->country_code == 'FR' && empty($mysoc->tva_assuj)) {
729 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
730 $pdf->SetXY($this->marge_gauche, $posy);
731 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("VATIsNotUsedForInvoice"), 0, 'L', false);
732
733 $posy = $pdf->GetY() + 4;
734 }
735
736 $posxval = 52;
737
738 $diffsizetitle = getDolGlobalInt('PDF_DIFFSIZE_TITLE', 3);
739
740 // Show payments conditions
741 if ($object->cond_reglement_code || $object->cond_reglement) {
742 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
743 $pdf->SetXY($this->marge_gauche, $posy);
744 $titre = $outputlangs->transnoentities("PaymentConditions").':';
745 $pdf->MultiCell(43, 4, $titre, 0, 'L');
746
747 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
748 $pdf->SetXY($posxval, $posy);
749 $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);
750 $lib_condition_paiement = str_replace('\n', "\n", $lib_condition_paiement);
751 if ($object->deposit_percent > 0) {
752 $lib_condition_paiement = str_replace('__DEPOSIT_PERCENT__', (string) $object->deposit_percent, $lib_condition_paiement);
753 }
754 $pdf->MultiCell(67, 4, $lib_condition_paiement, 0, 'L');
755
756 $posy = $pdf->GetY() + 3;
757 }
758
759 // Check a payment mode is defined
760 /* Not used with orders
761 if (empty($object->mode_reglement_code)
762 && ! $conf->global->FACTURE_CHQ_NUMBER
763 && ! $conf->global->FACTURE_RIB_NUMBER)
764 {
765 $pdf->SetXY($this->marge_gauche, $posy);
766 $pdf->SetTextColor(200,0,0);
767 $pdf->SetFont('','B', $default_font_size - 2);
768 $pdf->MultiCell(80, 3, $outputlangs->transnoentities("ErrorNoPaiementModeConfigured"),0,'L',0);
769 $pdf->SetTextColor(0,0,0);
770
771 $posy=$pdf->GetY()+1;
772 }
773 */
774 /* TODO
775 else if (!empty($object->availability_code))
776 {
777 $pdf->SetXY($this->marge_gauche, $posy);
778 $pdf->SetTextColor(200,0,0);
779 $pdf->SetFont('','B', $default_font_size - 2);
780 $pdf->MultiCell(80, 3, $outputlangs->transnoentities("AvailabilityPeriod").': '.,0,'L',0);
781 $pdf->SetTextColor(0,0,0);
782
783 $posy=$pdf->GetY()+1;
784 }*/
785
786 // Show planned date of delivery
787 if (!empty($object->delivery_date)) {
788 $outputlangs->load("sendings");
789 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
790 $pdf->SetXY($this->marge_gauche, $posy);
791 $titre = $outputlangs->transnoentities("DateDeliveryPlanned").':';
792 $pdf->MultiCell(80, 4, $titre, 0, 'L');
793 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
794 $pdf->SetXY($posxval, $posy);
795 $dlp = dol_print_date($object->delivery_date, "daytext", false, $outputlangs, true);
796 $pdf->MultiCell(80, 4, $dlp, 0, 'L');
797
798 $posy = $pdf->GetY() + 1;
799 } elseif ($object->availability_code || $object->availability) {
800 // Show availability conditions
801 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
802 $pdf->SetXY($this->marge_gauche, $posy);
803 $titre = $outputlangs->transnoentities("AvailabilityPeriod").':';
804 $pdf->MultiCell(80, 4, $titre, 0, 'L');
805 $pdf->SetTextColor(0, 0, 0);
806 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
807 $pdf->SetXY($posxval, $posy);
808 $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 : '');
809 $lib_availability = str_replace('\n', "\n", $lib_availability);
810 $pdf->MultiCell(80, 4, $lib_availability, 0, 'L');
811
812 $posy = $pdf->GetY() + 1;
813 }
814
815 // Show payment mode
816 if ($object->mode_reglement_code
817 && $object->mode_reglement_code != 'CHQ'
818 && $object->mode_reglement_code != 'VIR') {
819 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
820 $pdf->SetXY($this->marge_gauche, $posy);
821 $titre = $outputlangs->transnoentities("PaymentMode").':';
822 $pdf->MultiCell(80, 5, $titre, 0, 'L');
823
824 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
825 $pdf->SetXY($posxval, $posy);
826 $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);
827 $pdf->MultiCell(80, 5, $lib_mode_reg, 0, 'L');
828
829 $posy = $pdf->GetY() + 2;
830 }
831
832 // Show payment mode CHQ
833 if (empty($object->mode_reglement_code) || $object->mode_reglement_code == 'CHQ') {
834 // Si mode reglement non force ou si force a CHQ
835 if (getDolGlobalString('FACTURE_CHQ_NUMBER')) {
836 if (getDolGlobalInt('FACTURE_CHQ_NUMBER') > 0) {
837 $account = new Account($this->db);
838 $account->fetch(getDolGlobalInt('FACTURE_CHQ_NUMBER'));
839
840 $pdf->SetXY($this->marge_gauche, $posy);
841 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
842 $pdf->MultiCell(100, 3, $outputlangs->transnoentities('PaymentByChequeOrderedTo', $account->owner_name), 0, 'L', false);
843 $posy = $pdf->GetY() + 1;
844
845 if (!getDolGlobalString('MAIN_PDF_HIDE_CHQ_ADDRESS')) {
846 $pdf->SetXY($this->marge_gauche, $posy);
847 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
848 $pdf->MultiCell(100, 3, $outputlangs->convToOutputCharset($account->owner_address), 0, 'L', false);
849 $posy = $pdf->GetY() + 2;
850 }
851 }
852 if (getDolGlobalString('FACTURE_CHQ_NUMBER') == -1) {
853 $pdf->SetXY($this->marge_gauche, $posy);
854 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
855 $pdf->MultiCell(100, 3, $outputlangs->transnoentities('PaymentByChequeOrderedTo', $this->emetteur->name), 0, 'L', false);
856 $posy = $pdf->GetY() + 1;
857
858 if (!getDolGlobalString('MAIN_PDF_HIDE_CHQ_ADDRESS')) {
859 $pdf->SetXY($this->marge_gauche, $posy);
860 $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
861 $pdf->MultiCell(100, 3, $outputlangs->convToOutputCharset($this->emetteur->getFullAddress()), 0, 'L', false);
862 $posy = $pdf->GetY() + 2;
863 }
864 }
865 }
866 }
867
868 // If payment mode not forced or forced to VIR, show payment with BAN
869 if (empty($object->mode_reglement_code) || $object->mode_reglement_code == 'VIR') {
870 if ($object->fk_account > 0 || $object->fk_bank > 0 || getDolGlobalInt('FACTURE_RIB_NUMBER')) {
871 $bankid = ($object->fk_account <= 0 ? $conf->global->FACTURE_RIB_NUMBER : $object->fk_account);
872 if ($object->fk_bank > 0) {
873 $bankid = $object->fk_bank; // For backward compatibility when object->fk_account is forced with object->fk_bank
874 }
875 $account = new Account($this->db);
876 $account->fetch($bankid);
877
878 $curx = $this->marge_gauche;
879 $cury = $posy;
880
881 $posy = pdf_bank($pdf, $outputlangs, $curx, $cury, $account, 0, $default_font_size);
882
883 $posy += 2;
884 }
885 }
886
887 return $posy;
888 }
889
890 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
891 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
903 protected function _tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs, $outputlangsbis = null)
904 {
905 // phpcs:enable
906 global $conf, $mysoc, $hookmanager;
907
908 $default_font_size = pdf_getPDFFontSize($outputlangs);
909
910 if (getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE') && $outputlangs->defaultlang != getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE')) {
911 $outputlangsbis = new Translate('', $conf);
912 $outputlangsbis->setDefaultLang(getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE'));
913 $outputlangsbis->loadLangs(array("main", "dict", "companies", "bills", "products", "propal", "sendings"));
914 $default_font_size--;
915 }
916
917 $tab2_top = $posy;
918 $tab2_hl = 4;
919 $pdf->SetFont('', '', $default_font_size - 1);
920
921 // Total table
922 $col1x = 120;
923 $col2x = 170;
924 if ($this->page_largeur < 210) { // To work with US executive format
925 $col2x -= 20;
926 }
927 $largcol2 = ($this->page_largeur - $this->marge_droite - $col2x);
928
929 $useborder = 0;
930 $index = 0;
931
932 // Get Total HT
933 $total_ht = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1 ? $object->multicurrency_total_ht : $object->total_ht);
934
935 // Total discount
936 $total_discount_on_lines = 0;
937 $multicurrency_total_discount_on_lines = 0;
938 foreach ($object->lines as $i => $line) {
939 $resdiscount = pdfGetLineTotalDiscountAmount($object, $i, $outputlangs, 2);
940 $multicurrency_resdiscount = pdfGetLineTotalDiscountAmount($object, $i, $outputlangs, 2, 1);
941
942 $total_discount_on_lines += (is_numeric($resdiscount) ? $resdiscount : 0);
943 $multicurrency_total_discount_on_lines += (is_numeric($multicurrency_resdiscount) ? $multicurrency_resdiscount : 0);
944 // If line was a negative line, we do not count the discount as a discount
945 if ($line->total_ht < 0) {
946 $total_discount_on_lines += -$line->total_ht;
947 $multicurrency_total_discount_on_lines += -$line->multicurrency_total_ht;
948 }
949 }
950
951 if ($total_discount_on_lines > 0) {
952 if ($this->showAmountBeforeDiscount) {
953 // Show total NET before discount
954 $pdf->SetFillColor(255, 255, 255);
955 $pdf->SetXY($col1x, $tab2_top);
956 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalHTBeforeDiscount") . (is_object($outputlangsbis) ? ' / ' . $outputlangsbis->transnoentities("TotalHTBeforeDiscount") : ''), 0, 'L', true);
957 $pdf->SetXY($col2x, $tab2_top);
958
959 $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));
960 $pdf->MultiCell($largcol2, $tab2_hl, price($total_before_discount_to_show, 0, $outputlangs), 0, 'R', true);
961
962 $index++;
963 }
964
965 if ($this->showDiscountAmount) {
966 $pdf->SetFillColor(255, 255, 255);
967 $pdf->SetXY($col1x, $tab2_top + $tab2_hl);
968 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalDiscount") . (is_object($outputlangsbis) ? ' / ' . $outputlangsbis->transnoentities("TotalDiscount") : ''), 0, 'L', true);
969 $pdf->SetXY($col2x, $tab2_top + $tab2_hl);
970
971 $total_discount_to_show = ((isModEnabled("multicurrency") && $object->multicurrency_tx != 1) ? $multicurrency_total_discount_on_lines : $total_discount_on_lines);
972 $pdf->MultiCell($largcol2, $tab2_hl, price($total_discount_to_show, 0, $outputlangs), 0, 'R', true);
973
974 $index++;
975 }
976 }
977
978 // Total HT
979 $pdf->SetFillColor(255, 255, 255);
980 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
981 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalHT").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transnoentities("TotalHT") : ''), 0, 'L', true);
982
983 $total_ht = ((isModEnabled("multicurrency") && $object->multicurrency_tx != 1) ? $object->multicurrency_total_ht : $object->total_ht);
984 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
985 $pdf->MultiCell($largcol2, $tab2_hl, price($total_ht + (!empty($object->remise) ? $object->remise : 0), 0, $outputlangs), 0, 'R', true);
986
987 // Show VAT by rates and total
988 $pdf->SetFillColor(248, 248, 248);
989
990 $total_ttc = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1) ? $object->multicurrency_total_ttc : $object->total_ttc;
991
992 $this->atleastoneratenotnull = 0;
993 if (!getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT')) {
994 $tvaisnull = (!empty($this->tva) && count($this->tva) == 1 && isset($this->tva['0.000']) && is_float($this->tva['0.000']));
995 if (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_IFNULL') && $tvaisnull) {
996 // Nothing to do
997 } else {
998 //Local tax 1 before VAT
999 foreach ($this->localtax1 as $localtax_type => $localtax_rate) {
1000 if (in_array((string) $localtax_type, array('1', '3', '5'))) {
1001 continue;
1002 }
1003 foreach ($localtax_rate as $tvakey => $tvaval) {
1004 if ($tvakey != 0) { // On affiche pas taux 0
1005 //$this->atleastoneratenotnull++;
1006
1007 $index++;
1008 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1009
1010 $tvacompl = '';
1011 if (preg_match('/\*/', (string) $tvakey)) {
1012 $tvakey = str_replace('*', '', (string) $tvakey);
1013 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1014 }
1015 $totalvat = $outputlangs->transcountrynoentities("TotalLT1", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalLT1", $mysoc->country_code) : '');
1016 $totalvat .= ' ';
1017
1018 if (getDolGlobalString('PDF_LOCALTAX1_LABEL_IS_CODE_OR_RATE') == 'nocodenorate') {
1019 $totalvat .= $tvacompl;
1020 } else {
1021 $totalvat .= vatrate((string) abs((float) $tvakey), true).$tvacompl;
1022 }
1023
1024 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1025
1026 $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval);
1027
1028 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1029 $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', true);
1030 }
1031 }
1032 }
1033
1034 //Local tax 2 before VAT
1035 foreach ($this->localtax2 as $localtax_type => $localtax_rate) {
1036 if (in_array((string) $localtax_type, array('1', '3', '5'))) {
1037 continue;
1038 }
1039 foreach ($localtax_rate as $tvakey => $tvaval) {
1040 if ($tvakey != 0) { // On affiche pas taux 0
1041 //$this->atleastoneratenotnull++;
1042
1043 $index++;
1044 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1045
1046 $tvacompl = '';
1047 if (preg_match('/\*/', (string) $tvakey)) {
1048 $tvakey = str_replace('*', '', (string) $tvakey);
1049 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1050 }
1051 $totalvat = $outputlangs->transcountrynoentities("TotalLT2", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalLT2", $mysoc->country_code) : '');
1052 $totalvat .= ' ';
1053
1054 if (getDolGlobalString('PDF_LOCALTAX2_LABEL_IS_CODE_OR_RATE') == 'nocodenorate') {
1055 $totalvat .= $tvacompl;
1056 } else {
1057 $totalvat .= vatrate((string) abs((float) $tvakey), true).$tvacompl;
1058 }
1059
1060 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1061
1062 $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval);
1063
1064 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1065 $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', true);
1066 }
1067 }
1068 }
1069
1070 // VAT
1071 foreach ($this->tva_array as $tvakey => $tvaval) {
1072 if ($tvakey != 0) { // On affiche pas taux 0
1073 $this->atleastoneratenotnull++;
1074
1075 $index++;
1076 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1077
1078 $tvacompl = '';
1079 if (preg_match('/\*/', $tvakey)) {
1080 $tvakey = str_replace('*', '', $tvakey);
1081 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1082 }
1083 $totalvat = $outputlangs->transcountrynoentities("TotalVAT", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalVAT", $mysoc->country_code) : '');
1084 $totalvat .= ' ';
1085 if (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'rateonly') {
1086 $totalvat .= vatrate((string) $tvaval['vatrate'], true).$tvacompl;
1087 } elseif (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'codeonly') {
1088 $totalvat .= $tvaval['vatcode'].$tvacompl;
1089 } elseif (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'nocodenorate') {
1090 $totalvat .= $tvacompl;
1091 } else {
1092 $totalvat .= vatrate((string) $tvaval['vatrate'], true).($tvaval['vatcode'] ? ' ('.$tvaval['vatcode'].')' : '').$tvacompl;
1093 }
1094 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1095
1096 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1097 $pdf->MultiCell($largcol2, $tab2_hl, price(price2num($tvaval['amount'], 'MT'), 0, $outputlangs), 0, 'R', true);
1098 }
1099 }
1100
1101 //Local tax 1 after VAT
1102 //if (getDolGlobalString('FACTURE_LOCAL_TAX1_OPTION') && getDolGlobalString('FACTURE_LOCAL_TAX1_OPTION() == 'localtax1on')
1103 //{
1104 foreach ($this->localtax1 as $localtax_type => $localtax_rate) {
1105 if (in_array((string) $localtax_type, array('2', '4', '6'))) {
1106 continue;
1107 }
1108
1109 foreach ($localtax_rate as $tvakey => $tvaval) {
1110 if ($tvakey != 0) { // On affiche pas taux 0
1111 //$this->atleastoneratenotnull++;
1112
1113 $index++;
1114 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1115
1116 $tvacompl = '';
1117 if (preg_match('/\*/', (string) $tvakey)) {
1118 $tvakey = str_replace('*', '', (string) $tvakey);
1119 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1120 }
1121 $totalvat = $outputlangs->transcountrynoentities("TotalLT1", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalLT1", $mysoc->country_code) : '');
1122 $totalvat .= ' ';
1123
1124 if (getDolGlobalString('PDF_LOCALTAX1_LABEL_IS_CODE_OR_RATE') == 'nocodenorate') {
1125 $totalvat .= $tvacompl;
1126 } else {
1127 $totalvat .= vatrate((string) abs((float) $tvakey), true).$tvacompl;
1128 }
1129
1130 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1131
1132 $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval);
1133
1134 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1135 $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', true);
1136 }
1137 }
1138 }
1139 //}
1140 //Local tax 2 after VAT
1141 //if (getDolGlobalString('FACTURE_LOCAL_TAX2_OPTION') && getDolGlobalString('FATURE_LOCAL_TAX2_OPTION') == 'localtax2on')
1142 //{
1143 foreach ($this->localtax2 as $localtax_type => $localtax_rate) {
1144 if (in_array((string) $localtax_type, array('2', '4', '6'))) {
1145 continue;
1146 }
1147
1148 foreach ($localtax_rate as $tvakey => $tvaval) {
1149 // retrieve global local tax
1150 if ($tvakey != 0) { // On affiche pas taux 0
1151 //$this->atleastoneratenotnull++;
1152
1153 $index++;
1154 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1155
1156 $tvacompl = '';
1157 if (preg_match('/\*/', (string) $tvakey)) {
1158 $tvakey = str_replace('*', '', (string) $tvakey);
1159 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1160 }
1161 $totalvat = $outputlangs->transcountrynoentities("TotalLT2", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalLT2", $mysoc->country_code) : '');
1162 $totalvat .= ' ';
1163
1164 if (getDolGlobalString('PDF_LOCALTAX2_LABEL_IS_CODE_OR_RATE') == 'nocodenorate') {
1165 $totalvat .= $tvacompl;
1166 } else {
1167 $totalvat .= vatrate((string) abs((float) $tvakey), true).$tvacompl;
1168 }
1169
1170 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1171
1172 $total_localtax = ((isModEnabled("multicurrency") && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval);
1173
1174 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1175 $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', true);
1176 }
1177 }
1178 }
1179 //}
1180
1181 // Total TTC
1182 $index++;
1183 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1184 $pdf->SetTextColor(0, 0, 60);
1185 $pdf->SetFillColor(224, 224, 224);
1186 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalTTC").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalTTC", $mysoc->country_code) : ''), $useborder, 'L', true);
1187
1188 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1189 $pdf->MultiCell($largcol2, $tab2_hl, price($total_ttc, 0, $outputlangs), $useborder, 'R', true);
1190 }
1191 }
1192
1193 $pdf->SetTextColor(0, 0, 0);
1194
1195 $creditnoteamount = 0;
1196 $depositsamount = 0;
1197 //$creditnoteamount=$object->getSumCreditNotesUsed();
1198 //$depositsamount=$object->getSumDepositsUsed();
1199 //print "x".$creditnoteamount."-".$depositsamount;exit;
1200 $resteapayer = price2num($total_ttc - $deja_regle - $creditnoteamount - $depositsamount, 'MT');
1201 if (!empty($object->paye)) {
1202 $resteapayer = 0;
1203 }
1204
1205 if ($deja_regle > 0) {
1206 // Already paid + Deposits
1207 $index++;
1208
1209 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1210 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("AlreadyPaid").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transnoentities("AlreadyPaid") : ''), 0, 'L', false);
1211 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1212 $pdf->MultiCell($largcol2, $tab2_hl, price($deja_regle, 0, $outputlangs), 0, 'R', false);
1213
1214 $index++;
1215 $pdf->SetTextColor(0, 0, 60);
1216 $pdf->SetFillColor(224, 224, 224);
1217 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1218 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("RemainderToPay").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transnoentities("AlreadyPaid") : ''), $useborder, 'L', true);
1219
1220 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1221 $pdf->MultiCell($largcol2, $tab2_hl, price($resteapayer, 0, $outputlangs), $useborder, 'R', true);
1222
1223 $pdf->SetFont('', '', $default_font_size - 1);
1224 $pdf->SetTextColor(0, 0, 0);
1225 }
1226
1227 $index++;
1228 return ($tab2_top + ($tab2_hl * $index));
1229 }
1230
1231 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1246 protected function _tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop = 0, $hidebottom = 0, $currency = '', $outputlangsbis = null)
1247 {
1248 global $conf;
1249
1250 // Force to disable hidetop and hidebottom
1251 $hidebottom = 0;
1252 if ($hidetop) {
1253 $hidetop = -1;
1254 }
1255
1256 $currency = !empty($currency) ? $currency : getDolCurrency();
1257 $default_font_size = pdf_getPDFFontSize($outputlangs);
1258
1259 // Amount in (at tab_top - 1)
1260 $pdf->SetTextColor(0, 0, 0);
1261 $pdf->SetFont('', '', $default_font_size - 2);
1262
1263 if (empty($hidetop)) {
1264 $titre = $outputlangs->transnoentities("AmountInCurrency", $outputlangs->transnoentitiesnoconv("Currency".$currency));
1265 if (getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE') && is_object($outputlangsbis)) {
1266 $titre .= ' - '.$outputlangsbis->transnoentities("AmountInCurrency", $outputlangsbis->transnoentitiesnoconv("Currency".$currency));
1267 }
1268
1269 $pdf->SetXY($this->page_largeur - $this->marge_droite - ($pdf->GetStringWidth($titre) + 3), $tab_top - 4);
1270 $pdf->MultiCell(($pdf->GetStringWidth($titre) + 3), 2, $titre);
1271
1272 //$conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR='230,230,230';
1273 if (getDolGlobalString('MAIN_PDF_TITLE_BACKGROUND_COLOR')) {
1274 $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')));
1275 }
1276 }
1277
1278 $pdf->SetDrawColor(128, 128, 128);
1279 $pdf->SetFont('', '', $default_font_size - 1);
1280
1281 // Output Rect
1282 $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
1283
1284 if (empty($hidetop)) {
1285 $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
1286
1287 $pdf->SetXY($this->posxdesc - 1, $tab_top + 1);
1288 $pdf->MultiCell(108, 2, $outputlangs->transnoentities("Designation"), '', 'L');
1289 }
1290
1291 if (!getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT') && !getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_COLUMN')) {
1292 $pdf->line($this->posxtva - 1, $tab_top, $this->posxtva - 1, $tab_top + $tab_height);
1293 if (empty($hidetop)) {
1294 $pdf->SetXY($this->posxtva - 3, $tab_top + 1);
1295 $pdf->MultiCell($this->posxup - $this->posxtva + 3, 2, $outputlangs->transnoentities("VAT"), '', 'C');
1296 }
1297 }
1298
1299 $pdf->line($this->posxup - 1, $tab_top, $this->posxup - 1, $tab_top + $tab_height);
1300 if (empty($hidetop)) {
1301 $pdf->SetXY($this->posxup - 1, $tab_top + 1);
1302 $pdf->MultiCell($this->posxqty - $this->posxup - 1, 2, $outputlangs->transnoentities("PriceUHT"), '', 'C');
1303 }
1304
1305 $pdf->line($this->posxqty - 1, $tab_top, $this->posxqty - 1, $tab_top + $tab_height);
1306 if (empty($hidetop)) {
1307 $pdf->SetXY($this->posxqty - 1, $tab_top + 1);
1308 $pdf->MultiCell($this->posxunit - $this->posxqty - 1, 2, $outputlangs->transnoentities("Qty"), '', 'C');
1309 }
1310
1311 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
1312 $pdf->line($this->posxunit - 1, $tab_top, $this->posxunit - 1, $tab_top + $tab_height);
1313 if (empty($hidetop)) {
1314 $pdf->SetXY($this->posxunit - 1, $tab_top + 1);
1315 $pdf->MultiCell($this->posxdiscount - $this->posxunit - 1, 2, $outputlangs->transnoentities("Unit"), '', 'C');
1316 }
1317 }
1318
1319 $pdf->line($this->posxdiscount - 1, $tab_top, $this->posxdiscount - 1, $tab_top + $tab_height);
1320 if (empty($hidetop)) {
1321 if ($this->atleastonediscount) {
1322 $pdf->SetXY($this->posxdiscount - 1, $tab_top + 1);
1323 $pdf->MultiCell($this->postotalht - $this->posxdiscount + 1, 2, $outputlangs->transnoentities("ReductionShort"), '', 'C');
1324 }
1325 }
1326
1327 if ($this->atleastonediscount) {
1328 $pdf->line($this->postotalht, $tab_top, $this->postotalht, $tab_top + $tab_height);
1329 }
1330 if (empty($hidetop)) {
1331 $pdf->SetXY($this->postotalht - 1, $tab_top + 1);
1332 $pdf->MultiCell(30, 2, $outputlangs->transnoentities("TotalHTShort"), '', 'C');
1333 }
1334 }
1335
1336 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1337 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1349 protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $outputlangsbis = null, $titlekey = "PdfOrderTitle")
1350 {
1351 // phpcs:enable
1352 global $conf, $langs, $hookmanager;
1353
1354 $ltrdirection = 'L';
1355 if ($outputlangs->trans("DIRECTION") == 'rtl') {
1356 $ltrdirection = 'R';
1357 }
1358
1359 // Load traductions files required by page
1360 $outputlangs->loadLangs(array("main", "bills", "propal", "orders", "companies"));
1361
1362 $default_font_size = pdf_getPDFFontSize($outputlangs);
1363
1364 pdf_pagehead($pdf, $outputlangs, $this->page_hauteur);
1365
1366 $pdf->SetTextColor(0, 0, 60);
1367 $pdf->SetFont('', 'B', $default_font_size + 3);
1368
1369 $w = 100;
1370
1371 $posy = $this->marge_haute;
1372 $posx = $this->page_largeur - $this->marge_droite - $w;
1373
1374 $pdf->SetXY($this->marge_gauche, $posy);
1375
1376 // Logo
1377 $logodir = $conf->mycompany->dir_output;
1378 if (!empty($conf->mycompany->multidir_output[$object->entity ?? $conf->entity])) {
1379 $logodir = $conf->mycompany->multidir_output[$object->entity ?? $conf->entity];
1380 }
1381 pdf_writeLogoOrCompanyName($pdf, $outputlangs, $this->emetteur, $logodir, $this->marge_gauche, $posy, $w, $default_font_size, $ltrdirection);
1382
1383 $pdf->SetFont('', 'B', $default_font_size + 3);
1384 $pdf->SetXY($posx, $posy);
1385 $pdf->SetTextColor(0, 0, 60);
1386 $title = $outputlangs->transnoentities($titlekey);
1387 $title .= ' '.$outputlangs->convToOutputCharset($object->ref);
1388 if ($object->statut == $object::STATUS_DRAFT) {
1389 $pdf->SetTextColor(128, 0, 0);
1390 $title .= ' - '.$outputlangs->transnoentities("NotValidated");
1391 }
1392 $pdf->MultiCell($w, 3, $title, '', 'R');
1393
1394 $pdf->SetFont('', 'B', $default_font_size);
1395
1396 /*
1397 $posy += 5;
1398 $pdf->SetXY($posx, $posy);
1399 $pdf->SetTextColor(0, 0, 60);
1400 $pdf->MultiCell(100, 4, $outputlangs->transnoentities("Ref")." : ".$outputlangs->convToOutputCharset($object->ref), '', 'R');
1401 */
1402
1403 $posy += 3;
1404 $pdf->SetFont('', '', $default_font_size - 1);
1405
1406 if ($object->ref_client) {
1407 $posy += 5;
1408 $pdf->SetXY($posx, $posy);
1409 $pdf->SetTextColor(0, 0, 60);
1410 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("RefCustomer")." : ".$outputlangs->convToOutputCharset($object->ref_client), '', 'R');
1411 }
1412
1413 if (getDolGlobalString('PDF_SHOW_PROJECT_TITLE')) {
1414 $object->fetchProject();
1415 if (!empty($object->project->ref)) {
1416 $posy = $pdf->GetY();
1417 $pdf->SetXY($posx, $posy);
1418 $pdf->SetTextColor(0, 0, 60);
1419 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("Project")." : ".(empty($object->project->title) ? '' : $object->project->title), '', 'R');
1420 }
1421 }
1422
1423 if (getDolGlobalString('PDF_SHOW_PROJECT')) {
1424 $object->fetchProject();
1425 if (!empty($object->project->ref)) {
1426 $outputlangs->load("projects");
1427 $posy = $pdf->GetY();
1428 $pdf->SetXY($posx, $posy);
1429 $pdf->SetTextColor(0, 0, 60);
1430 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("RefProject")." : ".(empty($object->project->ref) ? '' : $object->project->ref), '', 'R');
1431 }
1432 }
1433
1434 $posy = $pdf->GetY();
1435 $pdf->SetXY($posx, $posy);
1436 $pdf->SetTextColor(0, 0, 60);
1437 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("OrderDate")." : ".dol_print_date($object->date, "day", false, $outputlangs, true), '', 'R');
1438
1439 if (!getDolGlobalString('MAIN_PDF_HIDE_CUSTOMER_CODE') && !empty($object->thirdparty->code_client)) {
1440 $posy = $pdf->GetY();
1441 $pdf->SetXY($posx, $posy);
1442 $pdf->SetTextColor(0, 0, 60);
1443 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("CustomerCode")." : ".$outputlangs->transnoentities((string) $object->thirdparty->code_client), '', 'R');
1444 }
1445
1446 if (!getDolGlobalString('MAIN_PDF_HIDE_CUSTOMER_ACCOUNTING_CODE') && !empty($object->thirdparty->code_compta_client)) {
1447 $posy += 4;
1448 $pdf->SetXY($posx, $posy);
1449 $pdf->SetTextColor(0, 0, 60);
1450 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("CustomerAccountancyCode")." : ".$outputlangs->transnoentities((string) $object->thirdparty->code_compta_client), '', 'R');
1451 }
1452
1453 // Get contact
1454 if (getDolGlobalString('DOC_SHOW_FIRST_SALES_REP')) {
1455 $arrayidcontact = $object->getIdContact('internal', 'SALESREPFOLL');
1456 if (count($arrayidcontact) > 0) {
1457 $usertmp = new User($this->db);
1458 $usertmp->fetch($arrayidcontact[0]);
1459 $posy += 4;
1460 $pdf->SetXY($posx, $posy);
1461 $pdf->SetTextColor(0, 0, 60);
1462 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R');
1463 }
1464 }
1465
1466 $posy += 2;
1467
1468 $top_shift = 0;
1469 $shipp_shift = 0;
1470 // Show list of linked objects
1471 $current_y = $pdf->getY();
1472 $posy = pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, $w, 3, 'R', $default_font_size);
1473 if ($current_y < $pdf->getY()) {
1474 $top_shift = $pdf->getY() - $current_y;
1475 }
1476
1477 if ($showaddress) {
1478 // Sender properties
1479 $carac_emetteur = '';
1480 // Add internal contact of object if defined
1481 $arrayidcontact = $object->getIdContact('internal', 'SALESREPFOLL');
1482 if (count($arrayidcontact) > 0) {
1483 $object->fetch_user($arrayidcontact[0]);
1484 $labelbeforecontactname = ($outputlangs->transnoentities("FromContactName") != 'FromContactName' ? $outputlangs->transnoentities("FromContactName") : $outputlangs->transnoentities("Name"));
1485 $carac_emetteur .= ($carac_emetteur ? "\n" : '').$labelbeforecontactname." ".$outputlangs->convToOutputCharset($object->user->getFullName($outputlangs));
1486 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') || getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ' (' : '';
1487 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') && !empty($object->user->office_phone)) ? $object->user->office_phone : '';
1488 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') && getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ', ' : '';
1489 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT') && !empty($object->user->email)) ? $object->user->email : '';
1490 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') || getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ')' : '';
1491 $carac_emetteur .= "\n";
1492 }
1493
1494 $carac_emetteur .= pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, '', 0, 'source', $object);
1495
1496 // Show sender
1497 $posy = 32 + $top_shift + $this->marge_haute;
1498 $posx = $this->marge_gauche;
1499 if (getDolGlobalString('MAIN_INVERT_SENDER_RECIPIENT')) {
1500 $posx = $this->page_largeur - $this->marge_droite - 80;
1501 }
1502 $hautcadre = 40;
1503
1504 // Show sender frame
1505 if (!getDolGlobalString('MAIN_PDF_NO_SENDER_FRAME')) {
1506 $pdf->SetTextColor(0, 0, 0);
1507 $pdf->SetFont('', '', $default_font_size - 2);
1508 $pdf->SetXY($posx, $posy - 5);
1509 $pdf->MultiCell(80, 5, $outputlangs->transnoentities("BillFrom"), 0, $ltrdirection);
1510 $pdf->SetXY($posx, $posy);
1511 $pdf->SetFillColor(230, 230, 230);
1512 $pdf->RoundedRect($posx, $posy, 82, $hautcadre, $this->corner_radius, '1234', 'F');
1513 $pdf->SetTextColor(0, 0, 60);
1514 }
1515
1516 // Show sender name
1517 if (!getDolGlobalString('MAIN_PDF_HIDE_SENDER_NAME')) {
1518 $pdf->SetXY($posx + 2, $posy + 3);
1519 $pdf->SetFont('', 'B', $default_font_size);
1520 $pdf->MultiCell(80, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, $ltrdirection);
1521 $posy = $pdf->getY();
1522 }
1523
1524 // Show sender information
1525 $pdf->SetXY($posx + 2, $posy);
1526 $pdf->SetFont('', '', $default_font_size - 1);
1527 $pdf->MultiCell(80, 4, $carac_emetteur, 0, 'L');
1528
1529
1530 // If CUSTOMER contact defined, we use it
1531 $usecontact = false;
1532 $arrayidcontact = $object->getIdContact('external', 'CUSTOMER');
1533 if (count($arrayidcontact) > 0) {
1534 $usecontact = true;
1535 $result = $object->fetch_contact($arrayidcontact[0]);
1536 }
1537
1538 // Recipient name
1539 if ($usecontact && ($object->contact->socid != $object->thirdparty->id && (!isset($conf->global->MAIN_USE_COMPANY_NAME_OF_CONTACT) || getDolGlobalString('MAIN_USE_COMPANY_NAME_OF_CONTACT')))) {
1540 $thirdparty = $object->contact;
1541 } else {
1542 $thirdparty = $object->thirdparty;
1543 }
1544
1545 $carac_client_name = pdfBuildThirdpartyName($thirdparty, $outputlangs);
1546
1547 $mode = 'target';
1548 $carac_client = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, ($usecontact ? $object->contact : ''), ($usecontact ? 1 : 0), $mode, $object);
1549
1550 // Show recipient
1551 $widthrecbox = getDolGlobalString('MAIN_PDF_USE_ISO_LOCATION') ? 92 : 100;
1552 if ($this->page_largeur < 210) {
1553 $widthrecbox = 84; // To work with US executive format
1554 }
1555 $posy = getDolGlobalString('MAIN_PDF_USE_ISO_LOCATION') ? 30 : 32;
1556 $posy += $top_shift + $this->marge_haute;
1557 $posx = $this->page_largeur - $this->marge_droite - $widthrecbox;
1558 if (getDolGlobalString('MAIN_INVERT_SENDER_RECIPIENT')) {
1559 $posx = $this->marge_gauche;
1560 }
1561
1562 // Show recipient frame
1563 if (!getDolGlobalString('MAIN_PDF_NO_RECIPENT_FRAME')) {
1564 $pdf->SetTextColor(0, 0, 0);
1565 $pdf->SetFont('', '', $default_font_size - 2);
1566 $pdf->SetXY($posx + 2, $posy - 5);
1567 $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillTo"), 0, $ltrdirection);
1568 $pdf->RoundedRect($posx, $posy, $widthrecbox, $hautcadre, $this->corner_radius, '1234', 'D');
1569 }
1570
1571 // Show recipient name
1572 $pdf->SetXY($posx + 2, $posy + 3);
1573 $pdf->SetFont('', 'B', $default_font_size);
1574 // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
1575 $pdf->MultiCell($widthrecbox, 2, $carac_client_name, 0, $ltrdirection);
1576
1577 $posy = $pdf->getY();
1578
1579 // Show recipient information
1580 $pdf->SetFont('', '', $default_font_size - 1);
1581 $pdf->SetXY($posx + 2, $posy);
1582 // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
1583 $pdf->MultiCell($widthrecbox, 4, $carac_client, 0, $ltrdirection);
1584
1585 // Show shipping address
1586 if (getDolGlobalInt('SALES_ORDER_SHOW_SHIPPING_ADDRESS')) {
1587 $idaddressshipping = $object->getIdContact('external', 'SHIPPING');
1588
1589 if (!empty($idaddressshipping)) {
1590 $contactshipping = $object->fetch_Contact($idaddressshipping[0]);
1591 $companystatic = new Societe($this->db);
1592 $companystatic->fetch($object->contact->fk_soc);
1593 $carac_client_name_shipping = pdfBuildThirdpartyName($object->contact, $outputlangs);
1594 $carac_client_shipping = pdf_build_address($outputlangs, $this->emetteur, $companystatic, $object->contact, 1, 'target', $object);
1595 } else {
1596 $carac_client_name_shipping = pdfBuildThirdpartyName($object->thirdparty, $outputlangs);
1597 $carac_client_shipping = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, '', 0, 'target', $object);
1598 }
1599 if (!empty($carac_client_shipping)) {
1600 $posy += $hautcadre;
1601
1602 $hautcadre -= 10; // Height for the shipping address does not need to be as high as main box
1603
1604 // Show shipping frame
1605 $pdf->SetXY($posx + 2, $posy - 5);
1606 $pdf->SetFont('', '', $default_font_size - 2);
1607 $pdf->MultiCell($widthrecbox, 0, $outputlangs->transnoentities('ShippingTo'), 0, 'L', false);
1608 $pdf->RoundedRect($posx, $posy, $widthrecbox, $hautcadre, $this->corner_radius, '1234', 'D');
1609
1610 // Show shipping name
1611 $pdf->SetXY($posx + 2, $posy + 1);
1612 $pdf->SetFont('', 'B', $default_font_size);
1613 $pdf->MultiCell($widthrecbox - 2, 2, $carac_client_name_shipping, '', 'L');
1614
1615 $posy = $pdf->getY();
1616
1617 // Show shipping information
1618 $pdf->SetXY($posx + 2, $posy);
1619 $pdf->SetFont('', '', $default_font_size - 1);
1620 $pdf->MultiCell($widthrecbox - 2, 2, $carac_client_shipping, '', 'L');
1621
1622 $shipp_shift += $hautcadre + 10;
1623 }
1624 }
1625 }
1626
1627 $pdf->SetTextColor(0, 0, 0);
1628
1629 $pagehead = array('top_shift' => $top_shift, 'shipp_shift' => $shipp_shift);
1630
1631 return $pagehead;
1632 }
1633
1634 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1635 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1645 protected function _pagefoot(&$pdf, $object, $outputlangs, $hidefreetext = 0)
1646 {
1647 // phpcs:enable
1648 $showdetails = getDolGlobalInt('MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS', 0);
1649 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);
1650 }
1651}
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...
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.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0, $nodefault=0)
Return value of a param into GET or POST supervariable.
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...
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)
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
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
pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line total excluding tax.
Definition pdf.lib.php:2918
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:3249
pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, $w, $h, $align, $default_font_size)
Show linked objects for PDF generation.
Definition pdf.lib.php:1851
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:1282
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:1889
pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line unit price excluding tax.
Definition pdf.lib.php:2507
pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails=0)
Return line vat rate.
Definition pdf.lib.php:2445
pdf_pagehead($pdf, $outputlangs, $page_height)
Show header of page for PDF generation.
Definition pdf.lib.php:790
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:1464
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:479
pdf_writeLogoOrCompanyName($pdf, $outputlangs, $emetteur, $logodir, $posx, $posy, $w, $default_font_size, $align)
Output company logo on top-left of a PDF page header, or the company name as fallback text if no logo...
Definition pdf.lib.php:349
pdf_getlineunit($object, $i, $outputlangs, $hidedetails=0)
Return line unit.
Definition pdf.lib.php:2752
pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails=0)
Return line remise percent.
Definition pdf.lib.php:2795
pdf_getlineqty($object, $i, $outputlangs, $hidedetails=0)
Return line quantity.
Definition pdf.lib.php:2592
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:1178
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:434
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