pdf_crabe::_tableau_versements_header()   A
last analyzed

Complexity

Conditions 2

Size

Total Lines 25
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 17
nop 8
dl 0
loc 25
rs 9.7
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/* Copyright (C) 2004-2014  Laurent Destailleur <[email protected]>
4
 * Copyright (C) 2005-2012	Regis Houssin		<[email protected]>
5
 * Copyright (C) 2008		Raphael Bertrand		<[email protected]>
6
 * Copyright (C) 2010-2014	Juanjo Menent		<[email protected]>
7
 * Copyright (C) 2012		Christophe Battarel	<[email protected]>
8
 * Copyright (C) 2012		Cédric Salvador		<[email protected]>
9
 * Copyright (C) 2012-2014	Raphaël Doursenaud	<[email protected]>
10
 * Copyright (C) 2015		Marcos García		<[email protected]>
11
 * Copyright (C) 2017-2018	Ferran Marcet		<[email protected]>
12
 * Copyright (C) 2018-2024  Frédéric France     <[email protected]>
13
 * Copyright (C) 2022		Anthony Berton		<[email protected]>
14
 * Copyright (C) 2022		Charlene Benke		<[email protected]>
15
 * Copyright (C) 2024		MDW							<[email protected]>
16
 * Copyright (C) 2024       Rafael San José             <[email protected]>
17
 *
18
 * This program is free software; you can redistribute it and/or modify
19
 * it under the terms of the GNU General Public License as published by
20
 * the Free Software Foundation; either version 3 of the License, or
21
 * (at your option) any later version.
22
 *
23
 * This program is distributed in the hope that it will be useful,
24
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26
 * GNU General Public License for more details.
27
 *
28
 * You should have received a copy of the GNU General Public License
29
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
30
 * or see https://www.gnu.org/
31
 */
32
33
use Dolibarr\Code\Compta\Classes\Account;
34
use Dolibarr\Code\Compta\Classes\Facture;
35
use Dolibarr\Code\Core\Classes\HookManager;
36
use Dolibarr\Code\Core\Classes\Translate;
37
use Dolibarr\Code\Facture\Classes\ModelePDFFactures;
38
use Dolibarr\Code\Product\Classes\Product;
39
use Dolibarr\Code\Societe\Classes\CompanyBankAccount;
40
use Dolibarr\Code\Societe\Classes\Societe;
41
use Dolibarr\Code\User\Classes\User;
42
use Dolibarr\Lib\ViewMain;
43
44
/**
45
 *  \file       htdocs/core/modules/facture/doc/pdf_crabe.modules.php
46
 *  \ingroup    invoice
47
 *  \brief      File of class to generate customers invoices from crabe model
48
 */
49
50
require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/company.lib.php';
51
require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/functions2.lib.php';
52
require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/pdf.lib.php';
53
54
/**
55
 *  Class to generate the customer invoice PDF with template Crabe
56
 */
57
class pdf_crabe extends ModelePDFFactures
58
{
59
    /**
60
     * @var DoliDB Database handler
61
     */
62
    public $db;
63
64
    /**
65
     * @var string model name
66
     */
67
    public $name;
68
69
    /**
70
     * @var string model description (short text)
71
     */
72
    public $description;
73
74
    /**
75
     * @var int     Save the name of generated file as the main doc when generating a doc with this template
76
     */
77
    public $update_main_doc_field;
78
79
    /**
80
     * @var string document type
81
     */
82
    public $type;
83
84
    /**
85
     * Dolibarr version of the loaded document
86
     * @var string
87
     */
88
    public $version = 'dolibarr';
89
90
    /**
91
     * @var bool Situation invoice type
92
     */
93
    public $situationinvoice;
94
95
    /**
96
     * @var float X position for the situation progress column
97
     */
98
    public $posxprogress;
99
100
    /**
101
     * @var int Category of operation
102
     */
103
    public $categoryOfOperation = -1; // unknown by default
104
105
106
    /**
107
     *  Constructor
108
     *
109
     * @param DoliDB $db Database handler
110
     */
111
    public function __construct($db)
112
    {
113
        global $conf, $langs, $mysoc;
114
115
        // Translations
116
        $langs->loadLangs(array("main", "bills"));
117
118
        $this->db = $db;
119
        $this->name = "crabe";
120
        $this->description = $langs->trans('PDFCrabeDescription');
121
        $this->update_main_doc_field = 1; // Save the name of generated file as the main doc when generating a doc with this template
122
123
        // Dimension page
124
        $this->type = 'pdf';
125
        $formatarray = pdf_getFormat();
126
        $this->page_largeur = $formatarray['width'];
127
        $this->page_hauteur = $formatarray['height'];
128
        $this->format = array($this->page_largeur, $this->page_hauteur);
129
        $this->marge_gauche = getDolGlobalInt('MAIN_PDF_MARGIN_LEFT', 10);
130
        $this->marge_droite = getDolGlobalInt('MAIN_PDF_MARGIN_RIGHT', 10);
131
        $this->marge_haute = getDolGlobalInt('MAIN_PDF_MARGIN_TOP', 10);
132
        $this->marge_basse = getDolGlobalInt('MAIN_PDF_MARGIN_BOTTOM', 10);
133
134
        $this->option_logo = 1; // Display logo
135
        $this->option_tva = 1; // Manage the vat option FACTURE_TVAOPTION
136
        $this->option_modereg = 1; // Display payment mode
137
        $this->option_condreg = 1; // Display payment terms
138
        $this->option_multilang = 1; // Available in several languages
139
        $this->option_escompte = 1; // Displays if there has been a discount
140
        $this->option_credit_note = 1; // Support credit notes
141
        $this->option_freetext = 1; // Support add of a personalised text
142
        $this->option_draft_watermark = 1; // Support add of a watermark on drafts
143
        $this->watermark = '';
144
145
        // Get source company
146
        $this->emetteur = $mysoc;
147
        if (empty($this->emetteur->country_code)) {
148
            $this->emetteur->country_code = substr($langs->defaultlang, -2); // By default, if was not defined
149
        }
150
151
        // Define position of columns
152
        $this->posxdesc = $this->marge_gauche + 1;
153
        if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
154
            $this->posxtva = 101;
155
            $this->posxup = 118;
156
            $this->posxqty = 135;
157
            $this->posxunit = 151;
158
        } else {
159
            $this->posxtva = 106;
160
            $this->posxup = 122;
161
            $this->posxqty = 145;
162
            $this->posxunit = 162;
163
        }
164
        $this->posxprogress = 151; // Only displayed for situation invoices
165
        $this->posxdiscount = 162;
166
        $this->posxprogress = 174;
167
        $this->postotalht = 174;
168
        if (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT') || getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_COLUMN')) {
169
            $this->posxtva = $this->posxup;
170
        }
171
        $this->posxpicture = $this->posxtva - getDolGlobalInt('MAIN_DOCUMENTS_WITH_PICTURE_WIDTH', 20); // width of images
172
        if ($this->page_largeur < 210) { // To work with US executive format
173
            $this->posxpicture -= 20;
174
            $this->posxtva -= 20;
175
            $this->posxup -= 20;
176
            $this->posxqty -= 20;
177
            $this->posxunit -= 20;
178
            $this->posxdiscount -= 20;
179
            $this->posxprogress -= 20;
180
            $this->postotalht -= 20;
181
        }
182
183
        $this->tva = array();
184
        $this->tva_array = array();
185
        $this->localtax1 = array();
186
        $this->localtax2 = array();
187
        $this->atleastoneratenotnull = 0;
188
        $this->atleastonediscount = 0;
189
        $this->situationinvoice = false;
190
    }
191
192
193
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
194
195
    /**
196
     *  Function to build pdf onto disk
197
     *
198
     * @param Facture $object Object to generate
199
     * @param Translate $outputlangs Lang output object
200
     * @param string $srctemplatepath Full path of source filename for generator using a template file
201
     * @param int $hidedetails Do not show line details
202
     * @param int $hidedesc Do not show desc
203
     * @param int $hideref Do not show ref
204
     * @return     int                             1=OK, 0=KO
205
     */
206
    public function write_file($object, $outputlangs, $srctemplatepath = '', $hidedetails = 0, $hidedesc = 0, $hideref = 0)
207
    {
208
        // phpcs:enable
209
        global $user, $langs, $conf, $mysoc, $hookmanager, $nblines;
210
211
        dol_syslog("write_file outputlangs->defaultlang=" . (is_object($outputlangs) ? $outputlangs->defaultlang : 'null'));
212
213
        if (!is_object($outputlangs)) {
214
            $outputlangs = $langs;
215
        }
216
        // For backward compatibility with FPDF, force output charset to ISO, because FPDF expect text to be encoded in ISO
217
        if (getDolGlobalString('MAIN_USE_FPDF')) {
218
            $outputlangs->charset_output = 'ISO-8859-1';
219
        }
220
221
        // Load translation files required by the page
222
        $outputlangs->loadLangs(array("main", "bills", "products", "dict", "companies"));
223
224
        // Show Draft Watermark
225
        if ($object->statut == $object::STATUS_DRAFT && (getDolGlobalString('FACTURE_DRAFT_WATERMARK'))) {
226
            $this->watermark = getDolGlobalString('FACTURE_DRAFT_WATERMARK');
227
        }
228
229
        global $outputlangsbis;
230
        $outputlangsbis = null;
231
        if (getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE') && $outputlangs->defaultlang != getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE')) {
232
            $outputlangsbis = new Translate('', $conf);
233
            $outputlangsbis->setDefaultLang(getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE'));
234
            $outputlangsbis->loadLangs(array("main", "bills", "products", "dict", "companies"));
235
        }
236
237
        $nblines = count($object->lines);
238
239
        // Loop on each lines to detect if there is at least one image to show
240
        $realpatharray = array();
241
        if (getDolGlobalString('MAIN_GENERATE_INVOICES_WITH_PICTURE')) {
242
            for ($i = 0; $i < $nblines; $i++) {
243
                if (empty($object->lines[$i]->fk_product)) {
244
                    continue;
245
                }
246
247
                $objphoto = new Product($this->db);
248
                $objphoto->fetch($object->lines[$i]->fk_product);
249
250
                $pdir = get_exdir($object->lines[$i]->fk_product, 2, 0, 0, $objphoto, 'product') . $object->lines[$i]->fk_product . "/photos/";
251
                $dir = $conf->product->dir_output . '/' . $pdir;
252
253
                $realpath = '';
254
                foreach ($objphoto->liste_photos($dir, 1) as $key => $obj) {
255
                    $filename = $obj['photo'];
256
                    //if ($obj['photo_vignette']) $filename='thumbs/'.$obj['photo_vignette'];
257
                    $realpath = $dir . $filename;
258
                    break;
259
                }
260
261
                if ($realpath) {
262
                    $realpatharray[$i] = $realpath;
263
                }
264
            }
265
        }
266
        if (count($realpatharray) == 0) {
267
            $this->posxpicture = $this->posxtva;
268
        }
269
270
        if ($conf->facture->dir_output) {
271
            $object->fetch_thirdparty();
272
273
            $deja_regle = $object->getSommePaiement((isModEnabled("multicurrency") && $object->multicurrency_tx != 1) ? 1 : 0);
274
            $amount_credit_notes_included = $object->getSumCreditNotesUsed((isModEnabled("multicurrency") && $object->multicurrency_tx != 1) ? 1 : 0);
275
            $amount_deposits_included = $object->getSumDepositsUsed((isModEnabled("multicurrency") && $object->multicurrency_tx != 1) ? 1 : 0);
276
277
            // Definition of $dir and $file
278
            if ($object->specimen) {
279
                $dir = empty($conf->facture->multidir_output[$object->entity]) ? $conf->facture->dir_output : $conf->facture->multidir_output[$object->entity];
280
                $file = $dir . "/SPECIMEN.pdf";
281
            } else {
282
                $objectref = dol_sanitizeFileName($object->ref);
283
                $dir = (empty($conf->facture->multidir_output[$object->entity]) ? $conf->facture->dir_output : $conf->facture->multidir_output[$object->entity]) . "/" . $objectref;
284
                $file = $dir . "/" . $objectref . ".pdf";
285
            }
286
            if (!file_exists($dir)) {
287
                if (dol_mkdir($dir) < 0) {
288
                    $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
289
                    return 0;
290
                }
291
            }
292
293
            if (file_exists($dir)) {
294
                // Add pdfgeneration hook
295
                if (!is_object($hookmanager)) {
296
                    $hookmanager = new HookManager($this->db);
297
                }
298
                $hookmanager->initHooks(array('pdfgeneration'));
299
                $parameters = array('file' => $file, 'object' => $object, 'outputlangs' => $outputlangs);
300
                global $action;
301
                $reshook = $hookmanager->executeHooks('beforePDFCreation', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
302
303
                // Set nblines with the new facture lines content after hook
304
                $nblines = count($object->lines);
305
                $nbpayments = count($object->getListOfPayments());
306
307
                // Create pdf instance
308
                $pdf = pdf_getInstance($this->format);
309
                $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance
310
                $pdf->SetAutoPageBreak(1, 0);
311
312
                $heightforinfotot = 50 + (4 * $nbpayments); // Height reserved to output the info and total part and payment part
313
                if ($heightforinfotot > 220) {
314
                    $heightforinfotot = 220;
315
                }
316
                $heightforfreetext = (isset($conf->global->MAIN_PDF_FREETEXT_HEIGHT) ? $conf->global->MAIN_PDF_FREETEXT_HEIGHT : 5); // Height reserved to output the free text on last page
317
                $heightforfooter = $this->marge_basse + 8; // Height reserved to output the footer (value include bottom margin)
318
                if (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS')) {
319
                    $heightforfooter += 6;
320
                }
321
322
                $heightforqrinvoice_firstpage = 0;
323
                if (getDolGlobalString('INVOICE_ADD_SWISS_QR_CODE') == 'bottom') {
324
                    $heightforqrinvoice_firstpage = $this->getHeightForQRInvoice(1, $object, $langs);
325
                    if ($heightforqrinvoice_firstpage > 0) {
326
                        // Shrink infotot to a base 30
327
                        $heightforinfotot = 30 + (4 * $nbpayments); // Height reserved to output the info and total part and payment part
328
                    }
329
                }
330
331
                if (class_exists('TCPDF')) {
332
                    $pdf->setPrintHeader(false);
333
                    $pdf->setPrintFooter(false);
334
                }
335
                $pdf->SetFont(pdf_getPDFFont($outputlangs));
336
337
                // Set path to the background PDF File
338
                if (getDolGlobalString('MAIN_ADD_PDF_BACKGROUND')) {
339
                    $logodir = $conf->mycompany->dir_output;
340
                    if (!empty($conf->mycompany->multidir_output[$object->entity])) {
341
                        $logodir = $conf->mycompany->multidir_output[$object->entity];
342
                    }
343
                    $pagecount = $pdf->setSourceFile($logodir . '/' . getDolGlobalString('MAIN_ADD_PDF_BACKGROUND'));
344
                    $tplidx = $pdf->importPage(1);
345
                }
346
347
                $pdf->Open();
348
                $pagenb = 0;
349
                $pdf->SetDrawColor(128, 128, 128);
350
351
                $pdf->SetTitle($outputlangs->convToOutputCharset($object->ref));
352
                $pdf->SetSubject($outputlangs->transnoentities("PdfInvoiceTitle"));
353
                $pdf->SetCreator("Dolibarr " . DOL_VERSION);
354
                $pdf->SetAuthor($mysoc->name . ($user->id > 0 ? ' - ' . $outputlangs->convToOutputCharset($user->getFullName($outputlangs)) : ''));
355
                $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref) . " " . $outputlangs->transnoentities("PdfInvoiceTitle") . " " . $outputlangs->convToOutputCharset($object->thirdparty->name));
356
                if (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) {
357
                    $pdf->SetCompression(false);
358
                }
359
360
                // Set certificate
361
                $cert = empty($user->conf->CERTIFICATE_CRT) ? '' : $user->conf->CERTIFICATE_CRT;
362
                $certprivate = empty($user->conf->CERTIFICATE_CRT_PRIVATE) ? '' : $user->conf->CERTIFICATE_CRT_PRIVATE;
363
                // If user has no certificate, we try to take the company one
364
                if (!$cert) {
365
                    $cert = !getDolGlobalString('CERTIFICATE_CRT') ? '' : $conf->global->CERTIFICATE_CRT;
366
                }
367
                if (!$certprivate) {
368
                    $certprivate = !getDolGlobalString('CERTIFICATE_CRT_PRIVATE') ? '' : $conf->global->CERTIFICATE_CRT_PRIVATE;
369
                }
370
                // If a certificate is found
371
                if ($cert) {
372
                    $info = array(
373
                        'Name' => $this->emetteur->name,
374
                        'Location' => getCountry($this->emetteur->country_code, 0),
375
                        'Reason' => 'INVOICE',
376
                        'ContactInfo' => $this->emetteur->email
377
                    );
378
                    $pdf->setSignature($cert, $certprivate, $this->emetteur->name, '', 2, $info);
379
                }
380
381
                // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
382
                $pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite); // Left, Top, Right
383
384
                // Set $this->atleastonediscount if you have at least one discount
385
                // and determine category of operation
386
                $categoryOfOperation = 0;
387
                $nbProduct = 0;
388
                $nbService = 0;
389
                for ($i = 0; $i < $nblines; $i++) {
390
                    if ($object->lines[$i]->remise_percent) {
391
                        $this->atleastonediscount++;
392
                    }
393
394
                    // determine category of operation
395
                    if ($categoryOfOperation < 2) {
396
                        $lineProductType = $object->lines[$i]->product_type;
397
                        if ($lineProductType == Product::TYPE_PRODUCT) {
398
                            $nbProduct++;
399
                        } elseif ($lineProductType == Product::TYPE_SERVICE) {
400
                            $nbService++;
401
                        }
402
                        if ($nbProduct > 0 && $nbService > 0) {
403
                            // mixed products and services
404
                            $categoryOfOperation = 2;
405
                        }
406
                    }
407
                }
408
                // determine category of operation
409
                if ($categoryOfOperation <= 0) {
410
                    // only services
411
                    if ($nbProduct == 0 && $nbService > 0) {
412
                        $categoryOfOperation = 1;
413
                    }
414
                }
415
                $this->categoryOfOperation = $categoryOfOperation;
416
                if (empty($this->atleastonediscount)) {    // retrieve space not used by discount
417
                    $delta = ($this->posxprogress - $this->posxdiscount);
418
                    $this->posxpicture += $delta;
419
                    $this->posxtva += $delta;
420
                    $this->posxup += $delta;
421
                    $this->posxqty += $delta;
422
                    $this->posxunit += $delta;
423
                    $this->posxdiscount += $delta;
424
                    // post of fields after are not modified, stay at same position
425
                }
426
427
                $progress_width = 0;
428
                // Situation invoice handling
429
                if ($object->situation_cycle_ref && !getDolGlobalString('MAIN_PDF_HIDE_SITUATION')) {
430
                    $this->situationinvoice = true;
431
                    $progress_width = 10;
432
                    $this->posxpicture -= $progress_width;
433
                    $this->posxtva -= $progress_width;
434
                    $this->posxup -= $progress_width;
435
                    $this->posxqty -= $progress_width;
436
                    $this->posxunit -= $progress_width;
437
                    $this->posxdiscount -= $progress_width;
438
                    $this->posxprogress -= $progress_width;
439
                }
440
441
                // New page
442
                $pdf->AddPage();
443
                if (!empty($tplidx)) {
444
                    $pdf->useTemplate($tplidx);
445
                }
446
                $pagenb++;
447
448
                // Output header (logo, ref and address blocks). This is first call for first page.
449
                $top_shift = $this->_pagehead($pdf, $object, 1, $outputlangs);
450
                $pdf->SetFont('', '', $default_font_size - 1);
451
                $pdf->MultiCell(0, 3, ''); // Set interline to 3
452
                $pdf->SetTextColor(0, 0, 0);
453
454
                // $pdf->GetY() here can't be used. It is bottom of the second address box but first one may be higher
455
456
                // $tab_top is y where we must continue content (90 = 42 + 48: 42 is height of logo and ref, 48 is address blocks)
457
                $tab_top = 90 + $top_shift;     // top_shift is an addition for linked objects or addons (0 in most cases)
458
                $tab_top_newpage = (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD') ? 42 + $top_shift : 10);
459
460
                // You can add more thing under header here, if you increase $extra_under_address_shift too.
461
                $extra_under_address_shift = 0;
462
                $qrcodestring = '';
463
                if (getDolGlobalString('INVOICE_ADD_ZATCA_QR_CODE')) {
464
                    $qrcodestring = $object->buildZATCAQRString();
465
                } elseif (getDolGlobalString('INVOICE_ADD_SWISS_QR_CODE') == '1' && (empty($object->mode_reglement_code) || $object->mode_reglement_code == 'VIR')) {
466
                    if ($object->fk_account > 0 || $object->fk_bank > 0 || getDolGlobalInt('FACTURE_RIB_NUMBER')) {
467
                        $qrcodestring = $object->buildSwitzerlandQRString();
468
                    }
469
                } elseif (getDolGlobalString('INVOICE_ADD_EPC_QR_CODE') == '1' && (empty($object->mode_reglement_code) || $object->mode_reglement_code == 'VIR')) {
470
                    if ($object->fk_account > 0 || $object->fk_bank > 0 || getDolGlobalInt('FACTURE_RIB_NUMBER')) {
471
                        $qrcodestring = $object->buildEPCQrCodeString();
472
                    }
473
                }
474
475
                if ($qrcodestring) {
476
                    $qrcodecolor = array('25', '25', '25');
477
                    // set style for QR-code
478
                    $styleQr = array(
479
                        'border' => false,
480
                        'padding' => 0,
481
                        'fgcolor' => $qrcodecolor,
482
                        'bgcolor' => false, //array(255,255,255)
483
                        'module_width' => 1, // width of a single module in points
484
                        'module_height' => 1 // height of a single module in points
485
                    );
486
                    $pdf->write2DBarcode($qrcodestring, 'QRCODE,M', $this->marge_gauche, $tab_top - 5, 25, 25, $styleQr, 'N');
487
488
                    if (getDolGlobalString('INVOICE_ADD_EPC_QR_CODE') == '1' && (empty($object->mode_reglement_code) || $object->mode_reglement_code == 'VIR')) {
489
                        if ($object->fk_account > 0 || $object->fk_bank > 0 || getDolGlobalInt('FACTURE_RIB_NUMBER')) {
490
                            $pdf->SetXY($this->marge_gauche + 30, $pdf->GetY() - 15);
491
                            $pdf->SetFont('', '', $default_font_size - 4);
492
                            $pdf->MultiCell(40, 3, $langs->transnoentitiesnoconv("INVOICE_ADD_EPC_QR_CODEPay"), 0, 'L', 0);
493
                        }
494
                    }
495
496
                    $extra_under_address_shift += 25;
497
                }
498
499
                // Call hook printUnderHeaderPDFline
500
                $parameters = array(
501
                    'object' => $object,
502
                    'i' => $i,
503
                    'pdf' => &$pdf,
504
                    'outputlangs' => $outputlangs,
505
                    'hidedetails' => $hidedetails
506
                );
507
                $reshook = $hookmanager->executeHooks('printUnderHeaderPDFline', $parameters, $this); // Note that $object may have been modified by hook
508
                if (!empty($hookmanager->resArray['extra_under_address_shift'])) {
509
                    $extra_under_address_shift += $hookmanager->resArray['extra_under_address_shift'];
510
                }
511
512
                $tab_top += $extra_under_address_shift;
513
                $tab_top_newpage += 0;
514
515
                // Incoterm
516
                $height_incoterms = 0;
517
                if (isModEnabled('incoterm')) {
518
                    $desc_incoterms = $object->getIncotermsForPDF();
519
                    if ($desc_incoterms) {
520
                        $tab_top -= 2;
521
522
                        $pdf->SetFont('', '', $default_font_size - 1);
523
                        $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top - 1, dol_htmlentitiesbr($desc_incoterms), 0, 1);
524
                        $nexY = $pdf->GetY();
525
                        $height_incoterms = $nexY - $tab_top;
526
527
                        // Rect takes a length in 3rd parameter
528
                        $pdf->SetDrawColor(192, 192, 192);
529
                        $pdf->Rect($this->marge_gauche, $tab_top - 1, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $height_incoterms + 1);
530
531
                        $tab_top = $nexY + 6;
532
                    }
533
                }
534
535
                // Display notes
536
                $notetoshow = empty($object->note_public) ? '' : $object->note_public;
537
                if (getDolGlobalString('MAIN_ADD_SALE_REP_SIGNATURE_IN_NOTE')) {
538
                    // Get first sale rep
539
                    if (is_object($object->thirdparty)) {
540
                        $salereparray = $object->thirdparty->getSalesRepresentatives($user);
541
                        $salerepobj = new User($this->db);
542
                        $salerepobj->fetch($salereparray[0]['id']);
543
                        if (!empty($salerepobj->signature)) {
544
                            $notetoshow = dol_concatdesc($notetoshow, $salerepobj->signature);
545
                        }
546
                    }
547
                }
548
                // Extrafields in note
549
                $extranote = $this->getExtrafieldsInHtml($object, $outputlangs);
550
                if (!empty($extranote)) {
551
                    $notetoshow = dol_concatdesc($notetoshow, $extranote);
552
                }
553
                if ($notetoshow) {
554
                    $tab_top -= 2;
555
556
                    $substitutionarray = pdf_getSubstitutionArray($outputlangs, null, $object);
557
                    complete_substitutions_array($substitutionarray, $outputlangs, $object);
558
559
                    $notetoshow = make_substitutions($notetoshow, $substitutionarray, $outputlangs);
560
                    $notetoshow = convertBackOfficeMediasLinksToPublicLinks($notetoshow);
561
562
                    $pdf->SetFont('', '', $default_font_size - 1);
563
                    $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top - 1, dol_htmlentitiesbr($notetoshow), 0, 1);
564
                    $nexY = $pdf->GetY();
565
                    $height_note = $nexY - $tab_top;
566
567
                    // Rect takes a length in 3rd parameter
568
                    $pdf->SetDrawColor(192, 192, 192);
569
                    $pdf->Rect($this->marge_gauche, $tab_top - 1, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $height_note + 1);
570
571
                    $tab_top = $nexY + 6;
572
                }
573
574
                $iniY = $tab_top + 7;
575
                $curY = $tab_top + 7;
576
                $nexY = $tab_top + 7;
577
578
                // Loop on each lines
579
                for ($i = 0; $i < $nblines; $i++) {
580
                    $curY = $nexY;
581
                    $pdf->SetFont('', '', $default_font_size - 1); // Into loop to work with multipage
582
                    $pdf->SetTextColor(0, 0, 0);
583
584
                    // Define size of image if we need it
585
                    $imglinesize = array();
586
                    if (!empty($realpatharray[$i])) {
587
                        $imglinesize = pdf_getSizeForImage($realpatharray[$i]);
588
                    }
589
590
                    $pdf->setTopMargin($tab_top_newpage);
591
                    $page_bottom_margin = $heightforfooter + $heightforfreetext + $heightforinfotot + $this->getHeightForQRInvoice($pdf->getPage(), $object, $langs);
592
                    $pdf->setPageOrientation('', 1, $page_bottom_margin);
593
                    $pageposbefore = $pdf->getPage();
594
595
                    $showpricebeforepagebreak = 1;
596
                    $posYAfterImage = 0;
597
                    $posYAfterDescription = 0;
598
599
                    // We start with Photo of product line
600
                    if (isset($imglinesize['width']) && isset($imglinesize['height']) && ($curY + $imglinesize['height']) > ($this->page_hauteur - $page_bottom_margin)) {  // If photo too high, we moved completely on new page
601
                        $pdf->AddPage('', '', true);
602
                        if (!empty($tplidx)) {
603
                            $pdf->useTemplate($tplidx);
604
                        }
605
                        if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
606
                            $top_shift = $this->_pagehead($pdf, $object, 0, $outputlangs);
607
                            $tab_top_newpage = (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD') ? 42 + $top_shift : 10);
608
                        }
609
                        $pdf->setPage($pageposbefore + 1);
610
611
                        $curY = $tab_top_newpage;
612
613
                        // Allows data in the first page if description is long enough to break in multiples pages
614
                        if (getDolGlobalString('MAIN_PDF_DATA_ON_FIRST_PAGE')) {
615
                            $showpricebeforepagebreak = 1;
616
                        } else {
617
                            $showpricebeforepagebreak = 0;
618
                        }
619
                    }
620
621
                    if (isset($imglinesize['width']) && isset($imglinesize['height'])) {
622
                        $curX = $this->posxpicture - 1;
623
                        $pdf->Image($realpatharray[$i], $curX + (($this->posxtva - $this->posxpicture - $imglinesize['width']) / 2), $curY, $imglinesize['width'], $imglinesize['height'], '', '', '', 2, 300); // Use 300 dpi
624
                        // $pdf->Image does not increase value return by getY, so we save it manually
625
                        $posYAfterImage = $curY + $imglinesize['height'];
626
                    }
627
628
                    // Description of product line
629
                    $curX = $this->posxdesc - 1;
630
631
                    $pdf->startTransaction();
632
                    pdf_writelinedesc($pdf, $object, $i, $outputlangs, $this->posxpicture - $curX - $progress_width, 3, $curX, $curY, $hideref, $hidedesc);
633
                    $pageposafter = $pdf->getPage();
634
                    if ($pageposafter > $pageposbefore) {   // There is a pagebreak
635
                        $pdf->rollbackTransaction(true);
636
                        $pageposafter = $pageposbefore;
637
                        //print $pageposafter.'-'.$pageposbefore;exit;
638
                        $pdf->setPageOrientation('', 1, $heightforfooter); // The only function to edit the bottom margin of current page to set it.
639
                        pdf_writelinedesc($pdf, $object, $i, $outputlangs, $this->posxpicture - $curX - $progress_width, 3, $curX, $curY, $hideref, $hidedesc);
640
                        $pageposafter = $pdf->getPage();
641
                        $posyafter = $pdf->GetY();
642
                        //var_dump($posyafter); var_dump(($this->page_hauteur - ($heightforfooter+$heightforfreetext+$heightforinfotot))); exit;
643
                        if ($posyafter > ($this->page_hauteur - $page_bottom_margin)) { // There is no space left for total+free text
644
                            if ($i == ($nblines - 1)) { // No more lines, and no space left to show total, so we create a new page
645
                                $pdf->AddPage('', '', true);
646
                                if (!empty($tplidx)) {
647
                                    $pdf->useTemplate($tplidx);
648
                                }
649
                                if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
650
                                    $top_shift = $this->_pagehead($pdf, $object, 0, $outputlangs);
651
                                    $tab_top_newpage = (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD') ? 42 + $top_shift : 10);
652
                                }
653
                                $pdf->setPage($pageposafter + 1);
654
                            }
655
                        } else {
656
                            // We found a page break
657
658
                            // Allows data in the first page if description is long enough to break in multiples pages
659
                            if (getDolGlobalString('MAIN_PDF_DATA_ON_FIRST_PAGE')) {
660
                                $showpricebeforepagebreak = 1;
661
                            } else {
662
                                $showpricebeforepagebreak = 0;
663
                            }
664
                        }
665
                    } else { // No pagebreak
666
                        $pdf->commitTransaction();
667
                    }
668
                    $posYAfterDescription = $pdf->GetY();
669
670
                    $nexY = $pdf->GetY();
671
                    $pageposafter = $pdf->getPage();
672
                    $pdf->setPage($pageposbefore);
673
                    $pdf->setTopMargin($this->marge_haute);
674
                    $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it.
675
676
                    // We suppose that a too long description or photo were moved completely on next page
677
                    if ($pageposafter > $pageposbefore && empty($showpricebeforepagebreak)) {
678
                        $pdf->setPage($pageposafter);
679
                        $curY = $tab_top_newpage;
680
                    }
681
682
                    $pdf->SetFont('', '', $default_font_size - 1); // We reposition the default font
683
684
                    // VAT Rate
685
                    if (!getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT') && !getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_COLUMN')) {
686
                        $vat_rate = pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails);
687
                        $pdf->SetXY($this->posxtva - 5, $curY);
688
                        $pdf->MultiCell($this->posxup - $this->posxtva + 4, 3, $vat_rate, 0, 'R');
689
                    }
690
691
                    // Unit price before discount
692
                    $up_excl_tax = pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails);
693
                    $pdf->SetXY($this->posxup, $curY);
694
                    $pdf->MultiCell($this->posxqty - $this->posxup - 0.8, 3, $up_excl_tax, 0, 'R', 0);
695
696
                    // Quantity
697
                    $qty = pdf_getlineqty($object, $i, $outputlangs, $hidedetails);
698
                    $pdf->SetXY($this->posxqty, $curY);
699
                    $pdf->MultiCell($this->posxunit - $this->posxqty - 0.8, 4, $qty, 0, 'R'); // Enough for 6 chars
700
701
                    // Unit
702
                    if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
703
                        $unit = pdf_getlineunit($object, $i, $outputlangs, $hidedetails);
704
                        $pdf->SetXY($this->posxunit, $curY);
705
                        $pdf->MultiCell($this->posxdiscount - $this->posxunit - 0.8, 4, $unit, 0, 'L');
706
                    }
707
708
                    // Discount on line
709
                    if ($object->lines[$i]->remise_percent) {
710
                        $pdf->SetXY($this->posxdiscount - 2, $curY);
711
                        $remise_percent = pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails);
712
                        $pdf->MultiCell($this->posxprogress - $this->posxdiscount + 2, 3, $remise_percent, 0, 'R');
713
                    }
714
715
                    // Situation progress
716
                    if ($this->situationinvoice) {
717
                        $progress = pdf_getlineprogress($object, $i, $outputlangs, $hidedetails);
718
                        $pdf->SetXY($this->posxprogress, $curY);
719
                        $pdf->MultiCell($this->postotalht - $this->posxprogress + 1, 3, $progress, 0, 'R');
720
                    }
721
722
                    // Total HT line
723
                    $total_excl_tax = pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails);
724
                    $pdf->SetXY($this->postotalht, $curY);
725
                    $pdf->MultiCell($this->page_largeur - $this->marge_droite - $this->postotalht, 3, $total_excl_tax, 0, 'R', 0);
726
727
728
                    $sign = 1;
729
                    if (isset($object->type) && $object->type == 2 && getDolGlobalString('INVOICE_POSITIVE_CREDIT_NOTE')) {
730
                        $sign = -1;
731
                    }
732
                    // Collection of totals by value of VAT in $this->tva["taux"]=total_tva
733
                    $prev_progress = $object->lines[$i]->get_prev_progress($object->id);
734
                    if ($prev_progress > 0 && !empty($object->lines[$i]->situation_percent)) { // Compute progress from previous situation
735
                        if (isModEnabled("multicurrency") && $object->multicurrency_tx != 1) {
736
                            $tvaligne = $sign * $object->lines[$i]->multicurrency_total_tva * ($object->lines[$i]->situation_percent - $prev_progress) / $object->lines[$i]->situation_percent;
737
                        } else {
738
                            $tvaligne = $sign * $object->lines[$i]->total_tva * ($object->lines[$i]->situation_percent - $prev_progress) / $object->lines[$i]->situation_percent;
739
                        }
740
                    } else {
741
                        if (isModEnabled("multicurrency") && $object->multicurrency_tx != 1) {
742
                            $tvaligne = $sign * $object->lines[$i]->multicurrency_total_tva;
743
                        } else {
744
                            $tvaligne = $sign * $object->lines[$i]->total_tva;
745
                        }
746
                    }
747
748
                    $localtax1ligne = $object->lines[$i]->total_localtax1;
749
                    $localtax2ligne = $object->lines[$i]->total_localtax2;
750
                    $localtax1_rate = $object->lines[$i]->localtax1_tx;
751
                    $localtax2_rate = $object->lines[$i]->localtax2_tx;
752
                    $localtax1_type = $object->lines[$i]->localtax1_type;
753
                    $localtax2_type = $object->lines[$i]->localtax2_type;
754
755
                    // TODO remise_percent is an obsolete field for object parent
756
                    /*if ($object->remise_percent) {
757
                        $tvaligne -= ($tvaligne * $object->remise_percent) / 100;
758
                    }
759
                    if ($object->remise_percent) {
760
                        $localtax1ligne -= ($localtax1ligne * $object->remise_percent) / 100;
761
                    }
762
                    if ($object->remise_percent) {
763
                        $localtax2ligne -= ($localtax2ligne * $object->remise_percent) / 100;
764
                    }*/
765
766
                    $vatrate = (string)$object->lines[$i]->tva_tx;
767
768
                    // Retrieve type from database for backward compatibility with old records
769
                    if (
770
                        (!isset($localtax1_type) || $localtax1_type == '' || !isset($localtax2_type) || $localtax2_type == '') // if tax type not defined
771
                        && (!empty($localtax1_rate) || !empty($localtax2_rate))
772
                    ) { // and there is local tax
773
                        $localtaxtmp_array = getLocalTaxesFromRate($vatrate, 0, $object->thirdparty, $mysoc);
774
                        $localtax1_type = isset($localtaxtmp_array[0]) ? $localtaxtmp_array[0] : '';
775
                        $localtax2_type = isset($localtaxtmp_array[2]) ? $localtaxtmp_array[2] : '';
776
                    }
777
778
                    // retrieve global local tax
779
                    if ($localtax1_type && $localtax1ligne != 0) {
780
                        if (empty($this->localtax1[$localtax1_type][$localtax1_rate])) {
781
                            $this->localtax1[$localtax1_type][$localtax1_rate] = $localtax1ligne;
782
                        } else {
783
                            $this->localtax1[$localtax1_type][$localtax1_rate] += $localtax1ligne;
784
                        }
785
                    }
786
                    if ($localtax2_type && $localtax2ligne != 0) {
787
                        if (empty($this->localtax2[$localtax2_type][$localtax2_rate])) {
788
                            $this->localtax2[$localtax2_type][$localtax2_rate] = $localtax2ligne;
789
                        } else {
790
                            $this->localtax2[$localtax2_type][$localtax2_rate] += $localtax2ligne;
791
                        }
792
                    }
793
794
                    if (($object->lines[$i]->info_bits & 0x01) == 0x01) {
795
                        $vatrate .= '*';
796
                    }
797
798
                    // Fill $this->tva and $this->tva_array
799
                    if (!isset($this->tva[$vatrate])) {
800
                        $this->tva[$vatrate] = 0;
801
                    }
802
                    $this->tva[$vatrate] += $tvaligne;  // ->tva is abandoned, we use now ->tva_array that is more complete
803
                    $vatcode = $object->lines[$i]->vat_src_code;
804
                    if (empty($this->tva_array[$vatrate . ($vatcode ? ' (' . $vatcode . ')' : '')]['amount'])) {
805
                        $this->tva_array[$vatrate . ($vatcode ? ' (' . $vatcode . ')' : '')]['amount'] = 0;
806
                    }
807
                    $this->tva_array[$vatrate . ($vatcode ? ' (' . $vatcode . ')' : '')] = array('vatrate' => $vatrate, 'vatcode' => $vatcode, 'amount' => $this->tva_array[$vatrate . ($vatcode ? ' (' . $vatcode . ')' : '')]['amount'] + $tvaligne);
808
809
                    if ($posYAfterImage > $posYAfterDescription) {
810
                        $nexY = $posYAfterImage;
811
                    }
812
813
                    // Add line
814
                    if (getDolGlobalString('MAIN_PDF_DASH_BETWEEN_LINES') && $i < ($nblines - 1)) {
815
                        $pdf->setPage($pageposafter);
816
                        $pdf->SetLineStyle(array('dash' => '1,1', 'color' => array(80, 80, 80)));
817
                        //$pdf->SetDrawColor(190,190,200);
818
                        $pdf->line($this->marge_gauche, $nexY + 1, $this->page_largeur - $this->marge_droite, $nexY + 1);
819
                        $pdf->SetLineStyle(array('dash' => 0));
820
                    }
821
822
                    $nexY += 2; // Add space between lines
823
824
                    // Detect if some page were added automatically and output _tableau for past pages
825
                    while ($pagenb < $pageposafter) {
826
                        $pdf->setPage($pagenb);
827
                        if ($pagenb == 1) {
828
                            $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter - $heightforqrinvoice_firstpage, 0, $outputlangs, 0, 1, $object->multicurrency_code);
829
                        } else {
830
                            $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code);
831
                        }
832
                        $this->_pagefoot($pdf, $object, $outputlangs, 1, $this->getHeightForQRInvoice($pagenb, $object, $langs));
833
                        $pagenb++;
834
                        $pdf->setPage($pagenb);
835
                        $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it.
836
                        if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
837
                            $top_shift = $this->_pagehead($pdf, $object, 0, $outputlangs);
838
                            $tab_top_newpage = (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD') ? 42 + $top_shift : 10);
839
                        }
840
                        if (!empty($tplidx)) {
841
                            $pdf->useTemplate($tplidx);
842
                        }
843
                    }
844
                    if (isset($object->lines[$i + 1]->pagebreak) && $object->lines[$i + 1]->pagebreak) {
845
                        if ($pagenb == 1) {
846
                            $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter - $heightforqrinvoice_firstpage, 0, $outputlangs, 0, 1, $object->multicurrency_code);
847
                        } else {
848
                            $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code);
849
                        }
850
                        $this->_pagefoot($pdf, $object, $outputlangs, 1, $this->getHeightForQRInvoice($pagenb, $object, $langs));
851
                        // New page
852
                        $pdf->AddPage();
853
                        if (!empty($tplidx)) {
854
                            $pdf->useTemplate($tplidx);
855
                        }
856
                        $pagenb++;
857
                        if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
858
                            $top_shift = $this->_pagehead($pdf, $object, 0, $outputlangs);
859
                            $tab_top_newpage = (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD') ? 42 + $top_shift : 10);
860
                        }
861
                    }
862
                }
863
864
                // Show square
865
                if ($pagenb == 1) {
866
                    $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforfooter - $heightforqrinvoice_firstpage, 0, $outputlangs, 0, 0, $object->multicurrency_code);
867
                    $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter - $heightforqrinvoice_firstpage + 1;
868
                } else {
869
                    $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 1, 0, $object->multicurrency_code);
870
                    $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
871
                }
872
                dol_syslog("bottomlasttab=" . $bottomlasttab . " this->page_hauteur=" . $this->page_hauteur . " heightforinfotot=" . $heightforinfotot . " heightforfreetext=" . $heightforfreetext . " heightforfooter=" . $heightforfooter);
873
874
                // Display info area
875
                $posy = $this->_tableau_info($pdf, $object, $bottomlasttab, $outputlangs, $outputlangsbis);
876
877
                // Display total area
878
                $posy = $this->_tableau_tot($pdf, $object, $deja_regle, $bottomlasttab, $outputlangs, $outputlangsbis);
879
880
                // Display Payments area
881
                if (($deja_regle || $amount_credit_notes_included || $amount_deposits_included) && !getDolGlobalString('INVOICE_NO_PAYMENT_DETAILS')) {
882
                    $posy = $this->_tableau_versements($pdf, $object, $posy, $outputlangs, $heightforfooter);
883
                }
884
885
                // Pagefoot
886
                $this->_pagefoot($pdf, $object, $outputlangs, 0, $this->getHeightForQRInvoice($pdf->getPage(), $object, $langs));
887
                if (method_exists($pdf, 'AliasNbPages')) {
888
                    $pdf->AliasNbPages();
889
                }
890
891
                if (getDolGlobalString('INVOICE_ADD_SWISS_QR_CODE') == 'bottom') {
892
                    $result = $this->addBottomQRInvoice($pdf, $object, $outputlangs);
893
                    if (!$result) {
894
                        $pdf->Close();
895
                        return 0;
896
                    }
897
                }
898
                $pdf->Close();
899
900
                $pdf->Output($file, 'F');
901
902
                // Add pdfgeneration hook
903
                $hookmanager->initHooks(array('pdfgeneration'));
904
                $parameters = array('file' => $file, 'object' => $object, 'outputlangs' => $outputlangs);
905
                global $action;
906
                $reshook = $hookmanager->executeHooks('afterPDFCreation', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
907
                if ($reshook < 0) {
908
                    $this->error = $hookmanager->error;
909
                    $this->errors = $hookmanager->errors;
910
                }
911
912
                dolChmod($file);
913
914
                $this->result = array('fullpath' => $file);
915
916
                return 1; // No error
917
            } else {
918
                $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
919
                return 0;
920
            }
921
        } else {
922
            $this->error = $langs->transnoentities("ErrorConstantNotDefined", "FAC_OUTPUTDIR");
923
            return 0;
924
        }
925
    }
926
927
928
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
929
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
930
    /**
931
     *  Show payments table
932
     *
933
     * @param TCPDF $pdf Object PDF
934
     * @param Facture $object Object invoice
935
     * @param int $posy Position y in PDF
936
     * @param Translate $outputlangs Object langs for output
937
     * @param int $heightforfooter Height for footer
938
     * @return int                             Return integer <0 if KO, >0 if OK
939
     */
940
    protected function _tableau_versements(&$pdf, $object, $posy, $outputlangs, $heightforfooter = 0)
941
    {
942
        // phpcs:enable
943
        global $conf;
944
945
        $sign = 1;
946
        if ($object->type == 2 && getDolGlobalString('INVOICE_POSITIVE_CREDIT_NOTE')) {
947
            $sign = -1;
948
        }
949
950
        $current_page = $pdf->getPage();
951
        $tab3_posx = 120;
952
        $tab3_top = $posy + 8;
953
        $tab3_width = 80;
954
        $tab3_height = 4;
955
        if ($this->page_largeur < 210) { // To work with US executive format
956
            $tab3_posx -= 15;
957
        }
958
959
        $default_font_size = pdf_getPDFFontSize($outputlangs);
960
961
        $this->_tableau_versements_header($pdf, $object, $outputlangs, $default_font_size, $tab3_posx, $tab3_top, $tab3_width, $tab3_height);
962
963
        $y = 0;
964
965
        $pdf->SetFont('', '', $default_font_size - 4);
966
967
968
        // Loop on each discount available (deposits and credit notes and excess of payment included)
969
        $sql = "SELECT re.rowid, re.amount_ht, re.multicurrency_amount_ht, re.amount_tva, re.multicurrency_amount_tva,  re.amount_ttc, re.multicurrency_amount_ttc,";
970
        $sql .= " re.description, re.fk_facture_source,";
971
        $sql .= " f.type, f.datef";
972
        $sql .= " FROM " . MAIN_DB_PREFIX . "societe_remise_except as re, " . MAIN_DB_PREFIX . "facture as f";
973
        $sql .= " WHERE re.fk_facture_source = f.rowid AND re.fk_facture = " . ((int)$object->id);
974
        $resql = $this->db->query($sql);
975
        if ($resql) {
976
            $num = $this->db->num_rows($resql);
977
            $i = 0;
978
            $invoice = new Facture($this->db);
979
            while ($i < $num) {
980
                $y += 3;
981
                if ($tab3_top + $y >= ($this->page_hauteur - $heightforfooter)) {
982
                    $y = 0;
983
                    $current_page++;
984
                    $pdf->AddPage('', '', true);
985
                    /*if (!empty($tplidx)) {
986
                        $pdf->useTemplate($tplidx);
987
                    }*/
988
                    if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
989
                        $top_shift = $this->_pagehead($pdf, $object, 0, $outputlangs);
990
                        $tab_top_newpage = (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD') ? 42 + $top_shift : 10);
991
                    }
992
                    $pdf->setPage($current_page);
993
                    $this->_tableau_versements_header($pdf, $object, $outputlangs, $default_font_size, $tab3_posx, $tab3_top + $y - 3, $tab3_width, $tab3_height);
994
                }
995
996
                $obj = $this->db->fetch_object($resql);
997
998
                if ($obj->type == 2) {
999
                    $text = $outputlangs->transnoentities("CreditNote");
1000
                } elseif ($obj->type == 3) {
1001
                    $text = $outputlangs->transnoentities("Deposit");
1002
                } elseif ($obj->type == 0) {
1003
                    $text = $outputlangs->transnoentities("ExcessReceived");
1004
                } else {
1005
                    $text = $outputlangs->transnoentities("UnknownType");
1006
                }
1007
1008
                $invoice->fetch($obj->fk_facture_source);
1009
1010
                $pdf->SetXY($tab3_posx, $tab3_top + $y);
1011
                $pdf->MultiCell(20, 3, dol_print_date($this->db->jdate($obj->datef), 'day', false, $outputlangs, true), 0, 'L', 0);
1012
                $pdf->SetXY($tab3_posx + 21, $tab3_top + $y);
1013
                $pdf->MultiCell(20, 3, price((isModEnabled("multicurrency") && $object->multicurrency_tx != 1) ? $obj->multicurrency_amount_ttc : $obj->amount_ttc, 0, $outputlangs), 0, 'L', 0);
1014
                $pdf->SetXY($tab3_posx + 40, $tab3_top + $y);
1015
                $pdf->MultiCell(20, 3, $text, 0, 'L', 0);
1016
                $pdf->SetXY($tab3_posx + 58, $tab3_top + $y);
1017
                $pdf->MultiCell(20, 3, $invoice->ref, 0, 'L', 0);
1018
1019
                $pdf->line($tab3_posx, $tab3_top + $y + 3, $tab3_posx + $tab3_width, $tab3_top + $y + 3);
1020
1021
                $i++;
1022
            }
1023
        } else {
1024
            $this->error = $this->db->lasterror();
1025
            return -1;
1026
        }
1027
1028
        // Loop on each payment
1029
        // TODO Call getListOfPaymentsgetListOfPayments instead of hard coded sql
1030
        $sql = "SELECT p.datep as date, p.fk_paiement, p.num_paiement as num, pf.amount as amount, pf.multicurrency_amount,";
1031
        $sql .= " cp.code";
1032
        $sql .= " FROM " . MAIN_DB_PREFIX . "paiement_facture as pf, " . MAIN_DB_PREFIX . "paiement as p";
1033
        $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_paiement as cp ON p.fk_paiement = cp.id";
1034
        $sql .= " WHERE pf.fk_paiement = p.rowid AND pf.fk_facture = " . ((int)$object->id);
1035
        //$sql.= " WHERE pf.fk_paiement = p.rowid AND pf.fk_facture = 1";
1036
        $sql .= " ORDER BY p.datep";
1037
1038
        $resql = $this->db->query($sql);
1039
        if ($resql) {
1040
            $num = $this->db->num_rows($resql);
1041
            $i = 0;
1042
            $y += 3;
1043
            $maxY = $y;
1044
            while ($i < $num) {
1045
                if ($tab3_top + $y >= ($this->page_hauteur - $heightforfooter)) {
1046
                    $y = 0;
1047
                    $current_page++;
1048
                    $pdf->AddPage('', '', true);
1049
                    /*if (!empty($tplidx)) {
1050
                        $pdf->useTemplate($tplidx);
1051
                    }*/
1052
                    if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
1053
                        $top_shift = $this->_pagehead($pdf, $object, 0, $outputlangs);
1054
                        $tab_top_newpage = (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD') ? 42 + $top_shift : 10);
1055
                    }
1056
                    $pdf->setPage($current_page);
1057
                    $this->_tableau_versements_header($pdf, $object, $outputlangs, $default_font_size, $tab3_posx, $tab3_top + $y - 3, $tab3_width, $tab3_height);
1058
                }
1059
1060
                $row = $this->db->fetch_object($resql);
1061
1062
                $pdf->SetXY($tab3_posx, $tab3_top + $y);
1063
                $pdf->MultiCell(20, 3, dol_print_date($this->db->jdate($row->date), 'day', false, $outputlangs, true), 0, 'L', 0);
1064
                $pdf->SetXY($tab3_posx + 21, $tab3_top + $y);
1065
                $pdf->MultiCell(20, 3, price($sign * ((isModEnabled("multicurrency") && $object->multicurrency_tx != 1) ? $row->multicurrency_amount : $row->amount), 0, $outputlangs), 0, 'L', 0);
1066
                $pdf->SetXY($tab3_posx + 40, $tab3_top + $y);
1067
                $oper = $outputlangs->transnoentitiesnoconv("PaymentTypeShort" . $row->code);
1068
1069
                $pdf->MultiCell(20, 3, $oper, 0, 'L', 0);
1070
                $maxY = max($pdf->GetY() - $tab3_top - 3, $maxY);
1071
                $pdf->SetXY($tab3_posx + 58, $tab3_top + $y);
1072
                $pdf->MultiCell(30, 3, $row->num, 0, 'L', 0);
1073
                $y = $maxY = max($pdf->GetY() - $tab3_top - 3, $maxY);
1074
                $pdf->line($tab3_posx, $tab3_top + $y + 3, $tab3_posx + $tab3_width, $tab3_top + $y + 3);
1075
                $y += 3;
1076
                $i++;
1077
            }
1078
1079
            return $tab3_top + $y + 3;
1080
        } else {
1081
            $this->error = $this->db->lasterror();
1082
            return -1;
1083
        }
1084
    }
1085
1086
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1087
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1088
    /**
1089
     * Function _tableau_versements_header
1090
     *
1091
     * @param TCPDF $pdf Object PDF
1092
     * @param Facture $object Object invoice
1093
     * @param Translate $outputlangs Object langs for output
1094
     * @param int $default_font_size Font size
1095
     * @param int $tab3_posx pos x
1096
     * @param int $tab3_top pos y
1097
     * @param int $tab3_width width
1098
     * @param int $tab3_height height
1099
     * @return void
1100
     */
1101
    protected function _tableau_versements_header($pdf, $object, $outputlangs, $default_font_size, $tab3_posx, $tab3_top, $tab3_width, $tab3_height)
1102
    {
1103
        // phpcs:enable
1104
        $title = $outputlangs->transnoentities("PaymentsAlreadyDone");
1105
        if ($object->type == 2) {
1106
            $title = $outputlangs->transnoentities("PaymentsBackAlreadyDone");
1107
        }
1108
1109
        $pdf->SetFont('', '', $default_font_size - 3);
1110
        $pdf->SetXY($tab3_posx, $tab3_top - 4);
1111
        $pdf->MultiCell(60, 3, $title, 0, 'L', 0);
1112
1113
        $pdf->line($tab3_posx, $tab3_top, $tab3_posx + $tab3_width, $tab3_top);
1114
1115
        $pdf->SetFont('', '', $default_font_size - 4);
1116
        $pdf->SetXY($tab3_posx, $tab3_top);
1117
        $pdf->MultiCell(20, 3, $outputlangs->transnoentities("Payment"), 0, 'L', 0);
1118
        $pdf->SetXY($tab3_posx + 21, $tab3_top);
1119
        $pdf->MultiCell(20, 3, $outputlangs->transnoentities("Amount"), 0, 'L', 0);
1120
        $pdf->SetXY($tab3_posx + 40, $tab3_top);
1121
        $pdf->MultiCell(20, 3, $outputlangs->transnoentities("Type"), 0, 'L', 0);
1122
        $pdf->SetXY($tab3_posx + 58, $tab3_top);
1123
        $pdf->MultiCell(20, 3, $outputlangs->transnoentities("Num"), 0, 'L', 0);
1124
1125
        $pdf->line($tab3_posx, $tab3_top - 1 + $tab3_height, $tab3_posx + $tab3_width, $tab3_top - 1 + $tab3_height);
1126
    }
1127
1128
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1129
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1130
    /**
1131
     *   Show miscellaneous information (payment mode, payment term, ...)
1132
     *
1133
     * @param TCPDF $pdf Object PDF
1134
     * @param Facture $object Object to show
1135
     * @param int $posy Y
1136
     * @param Translate $outputlangs Langs object
1137
     * @param Translate $outputlangsbis Object lang for output bis
1138
     * @return    int                         Pos y
1139
     */
1140
    protected function _tableau_info(&$pdf, $object, $posy, $outputlangs, $outputlangsbis)
1141
    {
1142
        // phpcs:enable
1143
        global $conf, $mysoc, $hookmanager;
1144
1145
        $default_font_size = pdf_getPDFFontSize($outputlangs);
1146
1147
        $pdf->SetFont('', '', $default_font_size - 1);
1148
1149
        // If France, show VAT mention if not applicable
1150
        if ($this->emetteur->country_code == 'FR' && empty($mysoc->tva_assuj)) {
1151
            $pdf->SetFont('', 'B', $default_font_size - 2);
1152
            $pdf->SetXY($this->marge_gauche, $posy);
1153
            if ($mysoc->forme_juridique_code == 92) {
1154
                $pdf->MultiCell(100, 3, $outputlangs->transnoentities("VATIsNotUsedForInvoiceAsso"), 0, 'L', 0);
1155
            } else {
1156
                $pdf->MultiCell(100, 3, $outputlangs->transnoentities("VATIsNotUsedForInvoice"), 0, 'L', 0);
1157
            }
1158
1159
            $posy = $pdf->GetY() + 4;
1160
        }
1161
1162
        $posxval = 52;
1163
        $posxend = 110; // End of x for text on left side
1164
        if ($this->page_largeur < 210) { // To work with US executive format
1165
            $posxend -= 10;
1166
        }
1167
1168
        // Show payments conditions
1169
        if ($object->type != 2 && ($object->cond_reglement_code || $object->cond_reglement)) {
1170
            $pdf->SetFont('', 'B', $default_font_size - 2);
1171
            $pdf->SetXY($this->marge_gauche, $posy);
1172
            $titre = $outputlangs->transnoentities("PaymentConditions") . ':';
1173
            $pdf->MultiCell(43, 4, $titre, 0, 'L');
1174
1175
            $pdf->SetFont('', '', $default_font_size - 2);
1176
            $pdf->SetXY($posxval, $posy);
1177
            $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);
1178
            $lib_condition_paiement = str_replace('\n', "\n", $lib_condition_paiement);
1179
            $pdf->MultiCell(67, 4, $lib_condition_paiement, 0, 'L');
1180
1181
            $posy = $pdf->GetY() + 3;   // We need spaces for 2 lines payment conditions
1182
        }
1183
1184
        // Show category of operations
1185
        if (getDolGlobalInt('INVOICE_CATEGORY_OF_OPERATION') == 2 && $this->categoryOfOperation >= 0) {
1186
            $pdf->SetFont('', 'B', $default_font_size - 2);
1187
            $pdf->SetXY($this->marge_gauche, $posy);
1188
            $categoryOfOperationTitle = $outputlangs->transnoentities("MentionCategoryOfOperations") . ' : ';
1189
            $pdf->MultiCell($posxval - $this->marge_gauche, 4, $categoryOfOperationTitle, 0, 'L');
1190
1191
            $pdf->SetFont('', '', $default_font_size - 2);
1192
            $pdf->SetXY($posxval, $posy);
1193
            $categoryOfOperationLabel = $outputlangs->transnoentities("MentionCategoryOfOperations" . $this->categoryOfOperation);
1194
            $pdf->MultiCell($posxend - $posxval, 4, $categoryOfOperationLabel, 0, 'L');
1195
1196
            $posy = $pdf->GetY() + 3; // for 2 lines
1197
        }
1198
1199
        if ($object->type != 2) {
1200
            // Check a payment mode is defined
1201
            if (
1202
                empty($object->mode_reglement_code)
1203
                && !getDolGlobalInt('FACTURE_CHQ_NUMBER')
1204
                && !getDolGlobalInt('FACTURE_RIB_NUMBER')
1205
            ) {
1206
                $this->error = $outputlangs->transnoentities("ErrorNoPaiementModeConfigured");
1207
            } elseif (
1208
                ($object->mode_reglement_code == 'CHQ' && !getDolGlobalInt('FACTURE_CHQ_NUMBER') && empty($object->fk_account) && empty($object->fk_bank))
1209
                || ($object->mode_reglement_code == 'VIR' && !getDolGlobalInt('FACTURE_RIB_NUMBER') && empty($object->fk_account) && empty($object->fk_bank))
1210
            ) {
1211
                // Avoid having any valid PDF with setup that is not complete
1212
                $outputlangs->load("errors");
1213
1214
                $pdf->SetXY($this->marge_gauche, $posy);
1215
                $pdf->SetTextColor(200, 0, 0);
1216
                $pdf->SetFont('', 'B', $default_font_size - 2);
1217
                $this->error = $outputlangs->transnoentities("ErrorPaymentModeDefinedToWithoutSetup", $object->mode_reglement_code);
1218
                $pdf->MultiCell(80, 3, $this->error, 0, 'L', 0);
1219
                $pdf->SetTextColor(0, 0, 0);
1220
1221
                $posy = $pdf->GetY() + 1;
1222
            }
1223
1224
            // Show payment mode
1225
            if (
1226
                !empty($object->mode_reglement_code)
1227
                && $object->mode_reglement_code != 'CHQ'
1228
                && $object->mode_reglement_code != 'VIR'
1229
            ) {
1230
                $pdf->SetFont('', 'B', $default_font_size - 2);
1231
                $pdf->SetXY($this->marge_gauche, $posy);
1232
                $titre = $outputlangs->transnoentities("PaymentMode") . ':';
1233
                $pdf->MultiCell(80, 5, $titre, 0, 'L');
1234
1235
                $pdf->SetFont('', '', $default_font_size - 2);
1236
                $pdf->SetXY($posxval, $posy);
1237
                $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);
1238
                //#21654: add account number used for the debit
1239
                if ($object->mode_reglement_code == "PRE") {
1240
                    $bac = new CompanyBankAccount($this->db);
1241
                    // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
1242
                    $bac->fetch(0, '', $object->thirdparty->id);
1243
                    $iban = $bac->iban . (($bac->iban && $bac->bic) ? ' / ' : '') . $bac->bic;
1244
                    $lib_mode_reg .= ' ' . $outputlangs->trans("PaymentTypePREdetails", dol_trunc($iban, 6, 'right', 'UTF-8', 1));
1245
                }
1246
                $pdf->MultiCell(80, 5, $lib_mode_reg, 0, 'L');
1247
1248
                $posy = $pdf->GetY();
1249
            }
1250
1251
            // Show if Option VAT debit option is on also if transmitter is french
1252
            // Decret n°2099-1299 2022-10-07
1253
            // French mention : "Option pour le paiement de la taxe d'après les débits"
1254
            if ($this->emetteur->country_code == 'FR') {
1255
                if (getDolGlobalInt('TAX_MODE') == 1) {
1256
                    $pdf->SetXY($this->marge_gauche, $posy);
1257
                    $pdf->writeHTMLCell(80, 5, '', '', $outputlangs->transnoentities("MentionVATDebitOptionIsOn"), 0, 1);
1258
1259
                    $posy = $pdf->GetY() + 1;
1260
                }
1261
            }
1262
1263
            // Show online payment link
1264
            if (empty($object->mode_reglement_code) || $object->mode_reglement_code == 'CB' || $object->mode_reglement_code == 'VAD') {
1265
                $useonlinepayment = 0;
1266
                if (getDolGlobalString('PDF_SHOW_LINK_TO_ONLINE_PAYMENT')) {
1267
                    // Show online payment link
1268
                    // The list can be complete by the hook 'doValidatePayment' executed inside getValidOnlinePaymentMethods()
1269
                    include_once DOL_DOCUMENT_ROOT . '/core/lib/payments.lib.php';
1270
                    $validpaymentmethod = getValidOnlinePaymentMethods('');
1271
                    $useonlinepayment = count($validpaymentmethod);
1272
                }
1273
1274
                if ($object->statut != Facture::STATUS_DRAFT && $useonlinepayment) {
1275
                    require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/payments.lib.php';
1276
                    global $langs;
1277
1278
                    $langs->loadLangs(array('payment', 'paybox', 'stripe'));
1279
                    $servicename = $langs->transnoentities('Online');
1280
                    $paiement_url = getOnlinePaymentUrl('', 'invoice', $object->ref, '', '', '');
1281
                    $linktopay = $langs->trans("ToOfferALinkForOnlinePayment", $servicename) . ' <a href="' . $paiement_url . '">' . $outputlangs->transnoentities("ClickHere") . '</a>';
1282
1283
                    $pdf->SetXY($this->marge_gauche, $posy);
1284
                    $pdf->writeHTMLCell(80, 5, '', '', dol_htmlentitiesbr($linktopay), 0, 1);
1285
1286
                    $posy = $pdf->GetY() + 1;
1287
                }
1288
            }
1289
1290
            // Show payment mode CHQ
1291
            if (empty($object->mode_reglement_code) || $object->mode_reglement_code == 'CHQ') {
1292
                // If payment mode unregulated or payment mode forced to CHQ
1293
                if (getDolGlobalInt('FACTURE_CHQ_NUMBER')) {
1294
                    $diffsizetitle = (!getDolGlobalString('PDF_DIFFSIZE_TITLE') ? 3 : $conf->global->PDF_DIFFSIZE_TITLE);
1295
1296
                    if (getDolGlobalInt('FACTURE_CHQ_NUMBER') > 0) {
1297
                        $account = new Account($this->db);
1298
                        $account->fetch(getDolGlobalInt('FACTURE_CHQ_NUMBER'));
1299
1300
                        $pdf->SetXY($this->marge_gauche, $posy);
1301
                        $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
1302
                        $pdf->MultiCell(100, 3, $outputlangs->transnoentities('PaymentByChequeOrderedTo', $account->owner_name), 0, 'L', 0);
1303
                        $posy = $pdf->GetY() + 1;
1304
1305
                        if (!getDolGlobalString('MAIN_PDF_HIDE_CHQ_ADDRESS')) {
1306
                            $pdf->SetXY($this->marge_gauche, $posy);
1307
                            $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
1308
                            $pdf->MultiCell(100, 3, $outputlangs->convToOutputCharset($account->owner_address), 0, 'L', 0);
1309
                            $posy = $pdf->GetY() + 2;
1310
                        }
1311
                    }
1312
                    if ($conf->global->FACTURE_CHQ_NUMBER == -1) {
1313
                        $pdf->SetXY($this->marge_gauche, $posy);
1314
                        $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
1315
                        $pdf->MultiCell(100, 3, $outputlangs->transnoentities('PaymentByChequeOrderedTo', $this->emetteur->name), 0, 'L', 0);
1316
                        $posy = $pdf->GetY() + 1;
1317
1318
                        if (!getDolGlobalString('MAIN_PDF_HIDE_CHQ_ADDRESS')) {
1319
                            $pdf->SetXY($this->marge_gauche, $posy);
1320
                            $pdf->SetFont('', '', $default_font_size - $diffsizetitle);
1321
                            $pdf->MultiCell(100, 3, $outputlangs->convToOutputCharset($this->emetteur->getFullAddress()), 0, 'L', 0);
1322
                            $posy = $pdf->GetY() + 2;
1323
                        }
1324
                    }
1325
                }
1326
            }
1327
1328
            // If payment mode not forced or forced to VIR, show payment with BAN
1329
            if (empty($object->mode_reglement_code) || $object->mode_reglement_code == 'VIR') {
1330
                if ($object->fk_account > 0 || $object->fk_bank > 0 || getDolGlobalInt('FACTURE_RIB_NUMBER')) {
1331
                    $bankid = ($object->fk_account <= 0 ? $conf->global->FACTURE_RIB_NUMBER : $object->fk_account);
1332
                    if ($object->fk_bank > 0) {
1333
                        $bankid = $object->fk_bank; // For backward compatibility when object->fk_account is forced with object->fk_bank
1334
                    }
1335
                    $account = new Account($this->db);
1336
                    $account->fetch($bankid);
1337
1338
                    $curx = $this->marge_gauche;
1339
                    $cury = $posy;
1340
1341
                    $posy = pdf_bank($pdf, $outputlangs, $curx, $cury, $account, 0, $default_font_size);
1342
1343
                    $posy += 2;
1344
                }
1345
            }
1346
        }
1347
1348
        return $posy;
1349
    }
1350
1351
1352
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1353
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1354
    /**
1355
     *  Show total to pay
1356
     *
1357
     * @param TCPDF $pdf Object PDF
1358
     * @param Facture $object Object invoice
1359
     * @param int $deja_regle Amount already paid (in the currency of invoice)
1360
     * @param int $posy Position depart
1361
     * @param Translate $outputlangs Object langs
1362
     * @param Translate $outputlangsbis Object lang for output bis
1363
     * @return int                         Position pour suite
1364
     */
1365
    protected function _tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs, $outputlangsbis)
1366
    {
1367
        // phpcs:enable
1368
        global $conf, $mysoc, $hookmanager;
1369
1370
        $sign = 1;
1371
        if ($object->type == 2 && getDolGlobalString('INVOICE_POSITIVE_CREDIT_NOTE')) {
1372
            $sign = -1;
1373
        }
1374
1375
        $default_font_size = pdf_getPDFFontSize($outputlangs);
1376
1377
        $outputlangsbis = null;
1378
        if (getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE') && $outputlangs->defaultlang != getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE')) {
1379
            $outputlangsbis = new Translate('', $conf);
1380
            $outputlangsbis->setDefaultLang(getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE'));
1381
            $outputlangsbis->loadLangs(array("main", "dict", "companies", "bills", "products", "propal"));
1382
            $default_font_size--;
1383
        }
1384
1385
        $tab2_top = $posy;
1386
        $tab2_hl = 4;
1387
        $pdf->SetFont('', '', $default_font_size - 1);
1388
1389
        // Total table
1390
        $col1x = 120;
1391
        $col2x = 170;
1392
        if ($this->page_largeur < 210) { // To work with US executive format
1393
            $col1x -= 15;
1394
            $col2x -= 10;
1395
        }
1396
        $largcol2 = ($this->page_largeur - $this->marge_droite - $col2x);
1397
1398
        $useborder = 0;
1399
        $index = 0;
1400
1401
        // Total HT
1402
        $pdf->SetFillColor(255, 255, 255);
1403
        $pdf->SetXY($col1x, $tab2_top);
1404
        $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities(!getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT') ? "TotalHT" : "Total") . (is_object($outputlangsbis) ? ' / ' . $outputlangsbis->transnoentities(!getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT') ? "TotalHT" : "Total") : ''), 0, 'L', 1);
1405
1406
        $total_ht = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? $object->multicurrency_total_ht : $object->total_ht);
1407
        $pdf->SetXY($col2x, $tab2_top);
1408
        $pdf->MultiCell($largcol2, $tab2_hl, price($sign * ($total_ht + (!empty($object->remise) ? $object->remise : 0)), 0, $outputlangs), 0, 'R', 1);
1409
1410
        // Show VAT by rates and total
1411
        $pdf->SetFillColor(248, 248, 248);
1412
1413
        $total_ttc = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1) ? $object->multicurrency_total_ttc : $object->total_ttc;
1414
1415
        $this->atleastoneratenotnull = 0;
1416
        if (!getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT')) {
1417
            $tvaisnull = ((!empty($this->tva) && count($this->tva) == 1 && isset($this->tva['0.000']) && is_float($this->tva['0.000'])) ? true : false);
1418
            if (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_IFNULL') && $tvaisnull) {
1419
                // Nothing to do
1420
            } else {
1421
                //Local tax 1 before VAT
1422
                //if (!empty($conf->global->FACTURE_LOCAL_TAX1_OPTION) && $conf->global->FACTURE_LOCAL_TAX1_OPTION=='localtax1on')
1423
                //{
1424
                foreach ($this->localtax1 as $localtax_type => $localtax_rate) {
1425
                    if (in_array((string)$localtax_type, array('1', '3', '5'))) {
1426
                        continue;
1427
                    }
1428
1429
                    foreach ($localtax_rate as $tvakey => $tvaval) {
1430
                        if ($tvakey != 0) {    // On affiche pas taux 0
1431
                            //$this->atleastoneratenotnull++;
1432
1433
                            $index++;
1434
                            $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1435
1436
                            $tvacompl = '';
1437
                            if (preg_match('/\*/', (string)$tvakey)) {
1438
                                $tvakey = str_replace('*', '', (string)$tvakey);
1439
                                $tvacompl = " (" . $outputlangs->transnoentities("NonPercuRecuperable") . ")";
1440
                            }
1441
1442
                            $totalvat = $outputlangs->transcountrynoentities("TotalLT1", $mysoc->country_code) . (is_object($outputlangsbis) ? ' / ' . $outputlangsbis->transcountrynoentities("TotalLT1", $mysoc->country_code) : '');
1443
                            $totalvat .= ' ';
1444
                            $totalvat .= vatrate(abs($tvakey), 1) . $tvacompl;
1445
                            $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1);
1446
1447
                            $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval);
1448
1449
                            $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1450
                            $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1);
1451
                        }
1452
                    }
1453
                }
1454
                //}
1455
                //Local tax 2 before VAT
1456
                //if (!empty($conf->global->FACTURE_LOCAL_TAX2_OPTION) && $conf->global->FACTURE_LOCAL_TAX2_OPTION=='localtax2on')
1457
                //{
1458
                foreach ($this->localtax2 as $localtax_type => $localtax_rate) {
1459
                    if (in_array((string)$localtax_type, array('1', '3', '5'))) {
1460
                        continue;
1461
                    }
1462
1463
                    foreach ($localtax_rate as $tvakey => $tvaval) {
1464
                        if ($tvakey != 0) {    // On affiche pas taux 0
1465
                            //$this->atleastoneratenotnull++;
1466
1467
                            $index++;
1468
                            $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1469
1470
                            $tvacompl = '';
1471
                            if (preg_match('/\*/', (string)$tvakey)) {
1472
                                $tvakey = str_replace('*', '', (string)$tvakey);
1473
                                $tvacompl = " (" . $outputlangs->transnoentities("NonPercuRecuperable") . ")";
1474
                            }
1475
                            $totalvat = $outputlangs->transcountrynoentities("TotalLT2", $mysoc->country_code) . (is_object($outputlangsbis) ? ' / ' . $outputlangsbis->transcountrynoentities("TotalLT2", $mysoc->country_code) : '');
1476
                            $totalvat .= ' ';
1477
                            $totalvat .= vatrate(abs($tvakey), 1) . $tvacompl;
1478
                            $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1);
1479
1480
                            $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval);
1481
1482
                            $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1483
                            $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1);
1484
                        }
1485
                    }
1486
                }
1487
1488
                //}
1489
1490
                // VAT
1491
                foreach ($this->tva_array as $tvakey => $tvaval) {
1492
                    if ($tvakey != 0) {    // On affiche pas taux 0
1493
                        $this->atleastoneratenotnull++;
1494
1495
                        $index++;
1496
                        $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1497
1498
                        $tvacompl = '';
1499
                        if (preg_match('/\*/', $tvakey)) {
1500
                            $tvakey = str_replace('*', '', $tvakey);
1501
                            $tvacompl = " (" . $outputlangs->transnoentities("NonPercuRecuperable") . ")";
1502
                        }
1503
                        $totalvat = $outputlangs->transcountrynoentities("TotalVAT", $mysoc->country_code) . (is_object($outputlangsbis) ? ' / ' . $outputlangsbis->transcountrynoentities("TotalVAT", $mysoc->country_code) : '');
1504
                        $totalvat .= ' ';
1505
                        if (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'rateonly') {
1506
                            $totalvat .= vatrate($tvaval['vatrate'], 1) . $tvacompl;
1507
                        } elseif (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'codeonly') {
1508
                            $totalvat .= $tvaval['vatcode'] . $tvacompl;
1509
                        } else {
1510
                            $totalvat .= vatrate($tvaval['vatrate'], 1) . ($tvaval['vatcode'] ? ' (' . $tvaval['vatcode'] . ')' : '') . $tvacompl;
1511
                        }
1512
                        $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1);
1513
1514
                        $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1515
                        $pdf->MultiCell($largcol2, $tab2_hl, price(price2num($tvaval['amount'], 'MT'), 0, $outputlangs), 0, 'R', 1);
1516
                    }
1517
                }
1518
1519
                //Local tax 1 after VAT
1520
                //if (!empty($conf->global->FACTURE_LOCAL_TAX1_OPTION) && $conf->global->FACTURE_LOCAL_TAX1_OPTION=='localtax1on')
1521
                //{
1522
                foreach ($this->localtax1 as $localtax_type => $localtax_rate) {
1523
                    if (in_array((string)$localtax_type, array('2', '4', '6'))) {
1524
                        continue;
1525
                    }
1526
1527
                    foreach ($localtax_rate as $tvakey => $tvaval) {
1528
                        if ($tvakey != 0) {    // On affiche pas taux 0
1529
                            //$this->atleastoneratenotnull++;
1530
1531
                            $index++;
1532
                            $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1533
1534
                            $tvacompl = '';
1535
                            if (preg_match('/\*/', (string)$tvakey)) {
1536
                                $tvakey = str_replace('*', '', (string)$tvakey);
1537
                                $tvacompl = " (" . $outputlangs->transnoentities("NonPercuRecuperable") . ")";
1538
                            }
1539
                            $totalvat = $outputlangs->transcountrynoentities("TotalLT1", $mysoc->country_code) . ' ';
1540
                            $totalvat .= vatrate(abs($tvakey), 1) . $tvacompl;
1541
1542
                            $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1);
1543
1544
                            $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval);
1545
1546
                            $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1547
                            $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1);
1548
                        }
1549
                    }
1550
                }
1551
                //}
1552
                //Local tax 2 after VAT
1553
                //if (!empty($conf->global->FACTURE_LOCAL_TAX2_OPTION) && $conf->global->FACTURE_LOCAL_TAX2_OPTION=='localtax2on')
1554
                //{
1555
                foreach ($this->localtax2 as $localtax_type => $localtax_rate) {
1556
                    if (in_array((string)$localtax_type, array('2', '4', '6'))) {
1557
                        continue;
1558
                    }
1559
1560
                    foreach ($localtax_rate as $tvakey => $tvaval) {
1561
                        //$this->atleastoneratenotnull++;
1562
1563
                        $index++;
1564
                        $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1565
1566
                        $tvacompl = '';
1567
                        if (preg_match('/\*/', (string)$tvakey)) {
1568
                            $tvakey = str_replace('*', '', (string)$tvakey);
1569
                            $tvacompl = " (" . $outputlangs->transnoentities("NonPercuRecuperable") . ")";
1570
                        }
1571
                        $totalvat = $outputlangs->transcountrynoentities("TotalLT2", $mysoc->country_code) . ' ';
1572
1573
                        $totalvat .= vatrate(abs($tvakey), 1) . $tvacompl;
1574
                        $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1);
1575
1576
                        $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval);
1577
1578
                        $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1579
                        $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1);
1580
                    }
1581
                }
1582
                //}
1583
1584
                // Revenue stamp
1585
                if (price2num($object->revenuestamp) != 0) {
1586
                    $index++;
1587
                    $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1588
                    $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("RevenueStamp"), $useborder, 'L', 1);
1589
1590
                    $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1591
                    $pdf->MultiCell($largcol2, $tab2_hl, price($sign * $object->revenuestamp), $useborder, 'R', 1);
1592
                }
1593
1594
                // Total TTC
1595
                $index++;
1596
                $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1597
                $pdf->SetTextColor(0, 0, 60);
1598
                $pdf->SetFillColor(224, 224, 224);
1599
                $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalTTC"), $useborder, 'L', 1);
1600
1601
                $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1602
                $pdf->MultiCell($largcol2, $tab2_hl, price($sign * $total_ttc, 0, $outputlangs), $useborder, 'R', 1);
1603
1604
                // Retained warranty
1605
                if ($object->displayRetainedWarranty()) {
1606
                    $pdf->SetTextColor(40, 40, 40);
1607
                    $pdf->SetFillColor(255, 255, 255);
1608
1609
                    $retainedWarranty = $object->getRetainedWarrantyAmount();
1610
                    $billedWithRetainedWarranty = $object->total_ttc - $retainedWarranty;
1611
1612
                    // Billed - retained warranty
1613
                    $index++;
1614
                    $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1615
                    $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("ToPayOn", dol_print_date($object->date_lim_reglement, 'day')), $useborder, 'L', 1);
1616
1617
                    $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1618
                    $pdf->MultiCell($largcol2, $tab2_hl, price($billedWithRetainedWarranty), $useborder, 'R', 1);
1619
1620
                    // retained warranty
1621
                    $index++;
1622
                    $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1623
1624
                    $retainedWarrantyToPayOn = $outputlangs->transnoentities("RetainedWarranty") . ' (' . $object->retained_warranty . '%)';
1625
                    $retainedWarrantyToPayOn .= !empty($object->retained_warranty_date_limit) ? ' ' . $outputlangs->transnoentities("toPayOn", dol_print_date($object->retained_warranty_date_limit, 'day')) : '';
1626
1627
                    $pdf->MultiCell($col2x - $col1x, $tab2_hl, $retainedWarrantyToPayOn, $useborder, 'L', 1);
1628
                    $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1629
                    $pdf->MultiCell($largcol2, $tab2_hl, price($retainedWarranty), $useborder, 'R', 1);
1630
                }
1631
            }
1632
        }
1633
1634
        $pdf->SetTextColor(0, 0, 0);
1635
        $creditnoteamount = $object->getSumCreditNotesUsed((isModEnabled("multicurrency") && $object->multicurrency_tx != 1) ? 1 : 0); // Warning, this also include excess received
1636
        $depositsamount = $object->getSumDepositsUsed((isModEnabled("multicurrency") && $object->multicurrency_tx != 1) ? 1 : 0);
1637
        //print "x".$creditnoteamount."-".$depositsamount;exit;
1638
        $resteapayer = price2num($total_ttc - $deja_regle - $creditnoteamount - $depositsamount, 'MT');
1639
        if (!empty($object->paye)) {
1640
            $resteapayer = 0;
1641
        }
1642
1643
        if (($deja_regle > 0 || $creditnoteamount > 0 || $depositsamount > 0) && !getDolGlobalString('INVOICE_NO_PAYMENT_DETAILS')) {
1644
            // Already paid + Deposits
1645
            $index++;
1646
            $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1647
            $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("Paid"), 0, 'L', 0);
1648
            $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1649
            $pdf->MultiCell($largcol2, $tab2_hl, price($deja_regle + $depositsamount, 0, $outputlangs), 0, 'R', 0);
1650
1651
            // Credit note
1652
            if ($creditnoteamount) {
1653
                $labeltouse = ($outputlangs->transnoentities("CreditNotesOrExcessReceived") != "CreditNotesOrExcessReceived") ? $outputlangs->transnoentities("CreditNotesOrExcessReceived") : $outputlangs->transnoentities("CreditNotes");
1654
                $index++;
1655
                $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1656
                $pdf->MultiCell($col2x - $col1x, $tab2_hl, $labeltouse, 0, 'L', 0);
1657
                $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1658
                $pdf->MultiCell($largcol2, $tab2_hl, price($creditnoteamount, 0, $outputlangs), 0, 'R', 0);
1659
            }
1660
1661
            // Escompte
1662
            if ($object->close_code == Facture::CLOSECODE_DISCOUNTVAT) {
1663
                $index++;
1664
                $pdf->SetFillColor(255, 255, 255);
1665
1666
                $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1667
                $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("EscompteOfferedShort"), $useborder, 'L', 1);
1668
                $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1669
                $pdf->MultiCell($largcol2, $tab2_hl, price($object->total_ttc - $deja_regle - $creditnoteamount - $depositsamount, 0, $outputlangs), $useborder, 'R', 1);
1670
1671
                $resteapayer = 0;
1672
            }
1673
1674
            $index++;
1675
            $pdf->SetTextColor(0, 0, 60);
1676
            $pdf->SetFillColor(224, 224, 224);
1677
            $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1678
            $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("RemainderToPay"), $useborder, 'L', 1);
1679
            $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1680
            $pdf->MultiCell($largcol2, $tab2_hl, price($resteapayer, 0, $outputlangs), $useborder, 'R', 1);
1681
1682
            $pdf->SetFont('', '', $default_font_size - 1);
1683
            $pdf->SetTextColor(0, 0, 0);
1684
        }
1685
1686
        $index++;
1687
1688
        if (getDolGlobalString("BILL_TEXT_TOTAL_FOOTER")) {
1689
            $index++;
1690
            $index++;
1691
            $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1692
            $pdf->MultiCell($col2x - $col1x, $tab2_hl, $conf->global->BILL_TEXT_TOTAL_FOOTER, 0, 'L', 0);
1693
        }
1694
1695
        return ($tab2_top + ($tab2_hl * $index));
1696
    }
1697
1698
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1699
1700
    /**
1701
     *   Show table for lines
1702
     *
1703
     * @param TCPDF $pdf Object PDF
1704
     * @param float|int $tab_top Top position of table
1705
     * @param float|int $tab_height Height of table (rectangle)
1706
     * @param int $nexY Y (not used)
1707
     * @param Translate $outputlangs Langs object
1708
     * @param int $hidetop 1=Hide top bar of array and title, 0=Hide nothing, -1=Hide only title
1709
     * @param int $hidebottom Hide bottom bar of array
1710
     * @param string $currency Currency code
1711
     * @return    void
1712
     */
1713
    protected function _tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop = 0, $hidebottom = 0, $currency = '')
1714
    {
1715
        global $conf;
1716
1717
        // Force to disable hidetop and hidebottom
1718
        $hidebottom = 0;
1719
        if ($hidetop) {
1720
            $hidetop = -1;
1721
        }
1722
1723
        $currency = !empty($currency) ? $currency : $conf->currency;
1724
        $default_font_size = pdf_getPDFFontSize($outputlangs);
1725
1726
        // Amount in (at tab_top - 1)
1727
        $pdf->SetTextColor(0, 0, 0);
1728
        $pdf->SetFont('', '', $default_font_size - 2);
1729
1730
        if (empty($hidetop)) {
1731
            // Show category of operations
1732
            if (getDolGlobalInt('INVOICE_CATEGORY_OF_OPERATION') == 1 && $this->categoryOfOperation >= 0) {
1733
                $categoryOfOperations = $outputlangs->transnoentities("MentionCategoryOfOperations") . ' : ' . $outputlangs->transnoentities("MentionCategoryOfOperations" . $this->categoryOfOperation);
1734
                $pdf->SetXY($this->marge_gauche, $tab_top - 4);
1735
                $pdf->MultiCell(($pdf->GetStringWidth($categoryOfOperations)) + 4, 2, $categoryOfOperations);
1736
            }
1737
1738
            $titre = $outputlangs->transnoentities("AmountInCurrency", $outputlangs->transnoentitiesnoconv("Currency" . $currency));
1739
            $pdf->SetXY($this->page_largeur - $this->marge_droite - ($pdf->GetStringWidth($titre) + 3), $tab_top - 4);
1740
            $pdf->MultiCell(($pdf->GetStringWidth($titre) + 3), 2, $titre);
1741
1742
            //$conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR='230,230,230';
1743
            if (getDolGlobalString('MAIN_PDF_TITLE_BACKGROUND_COLOR')) {
1744
                $pdf->Rect($this->marge_gauche, $tab_top, $this->page_largeur - $this->marge_droite - $this->marge_gauche, 5, 'F', null, explode(',', getDolGlobalString('MAIN_PDF_TITLE_BACKGROUND_COLOR')));
1745
            }
1746
        }
1747
1748
        $pdf->SetDrawColor(128, 128, 128);
1749
        $pdf->SetFont('', '', $default_font_size - 1);
1750
1751
        // Output Rect
1752
        $this->printRect($pdf, $this->marge_gauche, $tab_top, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $tab_height, $hidetop, $hidebottom); // Rect takes a length in 3rd parameter and 4th parameter
1753
1754
        if (empty($hidetop)) {
1755
            $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
1756
1757
            $pdf->SetXY($this->posxdesc - 1, $tab_top + 1);
1758
            $pdf->MultiCell(108, 2, $outputlangs->transnoentities("Designation"), '', 'L');
1759
        }
1760
1761
        if (getDolGlobalString('MAIN_GENERATE_INVOICES_WITH_PICTURE')) {
1762
            $pdf->line($this->posxpicture - 1, $tab_top, $this->posxpicture - 1, $tab_top + $tab_height);
1763
            if (empty($hidetop)) {
1764
                //$pdf->SetXY($this->posxpicture-1, $tab_top+1);
1765
                //$pdf->MultiCell($this->posxtva-$this->posxpicture-1,2, $outputlangs->transnoentities("Photo"),'','C');
1766
            }
1767
        }
1768
1769
        if (!getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT') && !getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_COLUMN')) {
1770
            $pdf->line($this->posxtva - 1, $tab_top, $this->posxtva - 1, $tab_top + $tab_height);
1771
            if (empty($hidetop)) {
1772
                $pdf->SetXY($this->posxtva - 3, $tab_top + 1);
1773
                $pdf->MultiCell($this->posxup - $this->posxtva + 3, 2, $outputlangs->transnoentities("VAT"), '', 'C');
1774
            }
1775
        }
1776
1777
        $pdf->line($this->posxup - 1, $tab_top, $this->posxup - 1, $tab_top + $tab_height);
1778
        if (empty($hidetop)) {
1779
            $pdf->SetXY($this->posxup - 1, $tab_top + 1);
1780
            $pdf->MultiCell($this->posxqty - $this->posxup - 1, 2, $outputlangs->transnoentities("PriceUHT"), '', 'C');
1781
        }
1782
1783
        $pdf->line($this->posxqty - 1, $tab_top, $this->posxqty - 1, $tab_top + $tab_height);
1784
        if (empty($hidetop)) {
1785
            $pdf->SetXY($this->posxqty - 1, $tab_top + 1);
1786
            $pdf->MultiCell($this->posxunit - $this->posxqty - 1, 2, $outputlangs->transnoentities("Qty"), '', 'C');
1787
        }
1788
1789
        if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
1790
            $pdf->line($this->posxunit - 1, $tab_top, $this->posxunit - 1, $tab_top + $tab_height);
1791
            if (empty($hidetop)) {
1792
                $pdf->SetXY($this->posxunit - 1, $tab_top + 1);
1793
                $pdf->MultiCell($this->posxdiscount - $this->posxunit - 1, 2, $outputlangs->transnoentities("Unit"), '', 'C');
1794
            }
1795
        }
1796
1797
        if ($this->atleastonediscount) {
1798
            $pdf->line($this->posxdiscount - 1, $tab_top, $this->posxdiscount - 1, $tab_top + $tab_height);
1799
            if (empty($hidetop)) {
1800
                $pdf->SetXY($this->posxdiscount - 1, $tab_top + 1);
1801
                $pdf->MultiCell($this->posxprogress - $this->posxdiscount + 1, 2, $outputlangs->transnoentities("ReductionShort"), '', 'C');
1802
            }
1803
        }
1804
1805
        if ($this->situationinvoice) {
1806
            $pdf->line($this->posxprogress - 1, $tab_top, $this->posxprogress - 1, $tab_top + $tab_height);
1807
            if (empty($hidetop)) {
1808
                $pdf->SetXY($this->posxprogress, $tab_top + 1);
1809
                $pdf->MultiCell($this->postotalht - $this->posxprogress, 2, $outputlangs->transnoentities("ProgressShort"), '', 'C');
1810
            }
1811
        }
1812
1813
        $pdf->line($this->postotalht, $tab_top, $this->postotalht, $tab_top + $tab_height);
1814
        if (empty($hidetop)) {
1815
            $pdf->SetXY($this->postotalht - 1, $tab_top + 1);
1816
            $pdf->MultiCell(30, 2, $outputlangs->transnoentities("TotalHTShort"), '', 'C');
1817
        }
1818
    }
1819
1820
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1821
1822
    /**
1823
     *  Show top header of page.
1824
     *
1825
     * @param TCPDF $pdf Object PDF
1826
     * @param Facture $object Object to show
1827
     * @param int $showaddress 0=no, 1=yes
1828
     * @param Translate $outputlangs Object lang for output
1829
     * @param Translate $outputlangsbis Object lang for output bis
1830
     * @return float|int                   Return topshift value
1831
     */
1832
    protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $outputlangsbis = null)
1833
    {
1834
        // phpcs:enable
1835
        global $conf, $langs;
1836
1837
        $ltrdirection = 'L';
1838
        if ($outputlangs->trans("DIRECTION") == 'rtl') {
1839
            $ltrdirection = 'R';
1840
        }
1841
1842
        // Load traductions files required by page
1843
        $outputlangs->loadLangs(array("main", "bills", "propal", "companies"));
1844
1845
        $default_font_size = pdf_getPDFFontSize($outputlangs);
1846
1847
        pdf_pagehead($pdf, $outputlangs, $this->page_hauteur);
1848
1849
        $pdf->SetTextColor(0, 0, 60);
1850
        $pdf->SetFont('', 'B', $default_font_size + 3);
1851
1852
        $w = 110;
1853
1854
        $posy = $this->marge_haute;
1855
        $posx = $this->page_largeur - $this->marge_droite - $w;
1856
1857
        $pdf->SetXY($this->marge_gauche, $posy);
1858
1859
        // Logo
1860
        if (!getDolGlobalInt('PDF_DISABLE_MYCOMPANY_LOGO')) {
1861
            if ($this->emetteur->logo) {
1862
                $logodir = $conf->mycompany->dir_output;
1863
                if (!empty($conf->mycompany->multidir_output[$object->entity])) {
1864
                    $logodir = $conf->mycompany->multidir_output[$object->entity];
1865
                }
1866
                if (!getDolGlobalInt('MAIN_PDF_USE_LARGE_LOGO')) {
1867
                    $logo = $logodir . '/logos/thumbs/' . $this->emetteur->logo_small;
1868
                } else {
1869
                    $logo = $logodir . '/logos/' . $this->emetteur->logo;
1870
                }
1871
                if (is_readable($logo)) {
1872
                    $height = pdf_getHeightForLogo($logo);
1873
                    $pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto)
1874
                } else {
1875
                    $pdf->SetTextColor(200, 0, 0);
1876
                    $pdf->SetFont('', 'B', $default_font_size - 2);
1877
                    $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound", $logo), 0, 'L');
1878
                    $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ErrorGoToGlobalSetup"), 0, 'L');
1879
                }
1880
            } else {
1881
                $text = $this->emetteur->name;
1882
                $pdf->MultiCell($w, 4, $outputlangs->convToOutputCharset($text), 0, $ltrdirection);
1883
            }
1884
        }
1885
1886
        $pdf->SetFont('', 'B', $default_font_size + 3);
1887
        $pdf->SetXY($posx, $posy);
1888
        $pdf->SetTextColor(0, 0, 60);
1889
        $title = $outputlangs->transnoentities("PdfInvoiceTitle");
1890
        if ($object->type == 1) {
1891
            $title = $outputlangs->transnoentities("InvoiceReplacement");
1892
        }
1893
        if ($object->type == 2) {
1894
            $title = $outputlangs->transnoentities("InvoiceAvoir");
1895
        }
1896
        if ($object->type == 3) {
1897
            $title = $outputlangs->transnoentities("InvoiceDeposit");
1898
        }
1899
        if ($object->type == 4) {
1900
            $title = $outputlangs->transnoentities("InvoiceProForma");
1901
        }
1902
        if ($this->situationinvoice) {
1903
            $langs->loadLangs(array("other"));
1904
            $title = $outputlangs->transnoentities("PDFInvoiceSituation") . " " . $outputlangs->transnoentities("NumberingShort") . $object->situation_counter . " -";
1905
        }
1906
        if (getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE') && is_object($outputlangsbis)) {
1907
            $title .= ' - ';
1908
            if ($object->type == 0) {
1909
                if ($this->situationinvoice) {
1910
                    $title .= $outputlangsbis->transnoentities("PDFInvoiceSituation");
1911
                }
1912
                $title .= $outputlangsbis->transnoentities("PdfInvoiceTitle");
1913
            } elseif ($object->type == 1) {
1914
                $title .= $outputlangsbis->transnoentities("InvoiceReplacement");
1915
            } elseif ($object->type == 2) {
1916
                $title .= $outputlangsbis->transnoentities("InvoiceAvoir");
1917
            } elseif ($object->type == 3) {
1918
                $title .= $outputlangsbis->transnoentities("InvoiceDeposit");
1919
            } elseif ($object->type == 4) {
1920
                $title .= $outputlangsbis->transnoentities("InvoiceProForma");
1921
            }
1922
        }
1923
        $title .= ' ' . $outputlangs->convToOutputCharset($object->ref);
1924
        if ($object->statut == $object::STATUS_DRAFT) {
1925
            $pdf->SetTextColor(128, 0, 0);
1926
            $title .= ' - ' . $outputlangs->transnoentities("NotValidated");
1927
        }
1928
1929
        $pdf->MultiCell($w, 3, $title, '', 'R');
1930
1931
        $pdf->SetFont('', 'B', $default_font_size);
1932
1933
        /*
1934
        $posy += 5;
1935
        $pdf->SetXY($posx, $posy);
1936
        $pdf->SetTextColor(0, 0, 60);
1937
        $textref = $outputlangs->transnoentities("Ref")." : ".$outputlangs->convToOutputCharset($object->ref);
1938
        if ($object->statut == $object::STATUS_DRAFT) {
1939
            $pdf->SetTextColor(128, 0, 0);
1940
            $textref .= ' - '.$outputlangs->transnoentities("NotValidated");
1941
        }
1942
        $pdf->MultiCell($w, 4, $textref, '', 'R');*/
1943
1944
        $posy += 3;
1945
        $pdf->SetFont('', '', $default_font_size - 2);
1946
1947
        if ($object->ref_customer) {
1948
            $posy += 4;
1949
            $pdf->SetXY($posx, $posy);
1950
            $pdf->SetTextColor(0, 0, 60);
1951
            $pdf->MultiCell($w, 3, $outputlangs->transnoentities("RefCustomer") . " : " . $outputlangs->convToOutputCharset($object->ref_customer), '', 'R');
1952
        }
1953
1954
        if (getDolGlobalString('PDF_SHOW_PROJECT_TITLE')) {
1955
            $object->fetch_projet();
1956
            if (!empty($object->project->ref)) {
1957
                $posy += 3;
1958
                $pdf->SetXY($posx, $posy);
1959
                $pdf->SetTextColor(0, 0, 60);
1960
                $pdf->MultiCell($w, 3, $outputlangs->transnoentities("Project") . " : " . (empty($object->project->title) ? '' : $object->project->title), '', 'R');
1961
            }
1962
        }
1963
1964
        if (getDolGlobalString('PDF_SHOW_PROJECT')) {
1965
            $object->fetch_projet();
1966
            if (!empty($object->project->ref)) {
1967
                $outputlangs->load("projects");
1968
                $posy += 3;
1969
                $pdf->SetXY($posx, $posy);
1970
                $pdf->SetTextColor(0, 0, 60);
1971
                $pdf->MultiCell($w, 3, $outputlangs->transnoentities("RefProject") . " : " . (empty($object->project->ref) ? '' : $object->project->ref), '', 'R');
1972
            }
1973
        }
1974
1975
        $objectidnext = $object->getIdReplacingInvoice('validated');
1976
        if ($object->type == 0 && $objectidnext) {
1977
            $objectreplacing = new Facture($this->db);
1978
            $objectreplacing->fetch($objectidnext);
1979
1980
            $posy += 3;
1981
            $pdf->SetXY($posx, $posy);
1982
            $pdf->SetTextColor(0, 0, 60);
1983
            $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ReplacementByInvoice") . ' : ' . $outputlangs->convToOutputCharset($objectreplacing->ref), '', 'R');
1984
        }
1985
        if ($object->type == 1) {
1986
            $objectreplaced = new Facture($this->db);
1987
            $objectreplaced->fetch($object->fk_facture_source);
1988
1989
            $posy += 4;
1990
            $pdf->SetXY($posx, $posy);
1991
            $pdf->SetTextColor(0, 0, 60);
1992
            $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ReplacementInvoice") . ' : ' . $outputlangs->convToOutputCharset($objectreplaced->ref), '', 'R');
1993
        }
1994
        if ($object->type == 2 && !empty($object->fk_facture_source)) {
1995
            $objectreplaced = new Facture($this->db);
1996
            $objectreplaced->fetch($object->fk_facture_source);
1997
1998
            $posy += 3;
1999
            $pdf->SetXY($posx, $posy);
2000
            $pdf->SetTextColor(0, 0, 60);
2001
            $pdf->MultiCell($w, 3, $outputlangs->transnoentities("CorrectionInvoice") . ' : ' . $outputlangs->convToOutputCharset($objectreplaced->ref), '', 'R');
2002
        }
2003
2004
        $posy += 4;
2005
        $pdf->SetXY($posx, $posy);
2006
        $pdf->SetTextColor(0, 0, 60);
2007
        $title = $outputlangs->transnoentities("DateInvoice");
2008
        if (getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE') && is_object($outputlangsbis)) {
2009
            $title .= ' - ' . $outputlangsbis->transnoentities("DateInvoice");
2010
        }
2011
        $pdf->MultiCell($w, 3, $title . " : " . dol_print_date($object->date, "day", false, $outputlangs, true), '', 'R');
2012
2013
        if (getDolGlobalString('INVOICE_POINTOFTAX_DATE')) {
2014
            $posy += 4;
2015
            $pdf->SetXY($posx, $posy);
2016
            $pdf->SetTextColor(0, 0, 60);
2017
            $pdf->MultiCell($w, 3, $outputlangs->transnoentities("DatePointOfTax") . " : " . dol_print_date($object->date_pointoftax, "day", false, $outputlangs), '', 'R');
2018
        }
2019
2020
        if ($object->type != 2) {
2021
            $posy += 3;
2022
            $pdf->SetXY($posx, $posy);
2023
            $pdf->SetTextColor(0, 0, 60);
2024
            $title = $outputlangs->transnoentities("DateDue");
2025
            if (getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE') && is_object($outputlangsbis)) {
2026
                $title .= ' - ' . $outputlangsbis->transnoentities("DateDue");
2027
            }
2028
            $pdf->MultiCell($w, 3, $title . " : " . dol_print_date($object->date_lim_reglement, "day", false, $outputlangs, true), '', 'R');
2029
        }
2030
2031
        if (!getDolGlobalString('MAIN_PDF_HIDE_CUSTOMER_CODE') && $object->thirdparty->code_client) {
2032
            $posy += 3;
2033
            $pdf->SetXY($posx, $posy);
2034
            $pdf->SetTextColor(0, 0, 60);
2035
            $pdf->MultiCell($w, 3, $outputlangs->transnoentities("CustomerCode") . " : " . $outputlangs->transnoentities($object->thirdparty->code_client), '', 'R');
2036
        }
2037
2038
        // Get contact
2039
        if (getDolGlobalString('DOC_SHOW_FIRST_SALES_REP')) {
2040
            $arrayidcontact = $object->getIdContact('internal', 'SALESREPFOLL');
2041
            if (count($arrayidcontact) > 0) {
2042
                $usertmp = new User($this->db);
2043
                $usertmp->fetch($arrayidcontact[0]);
2044
                $posy += 4;
2045
                $pdf->SetXY($posx, $posy);
2046
                $pdf->SetTextColor(0, 0, 60);
2047
                $pdf->MultiCell($w, 3, $langs->transnoentities("SalesRepresentative") . " : " . $usertmp->getFullName($langs), '', 'R');
2048
            }
2049
        }
2050
2051
        $posy += 1;
2052
2053
        $top_shift = 0;
2054
        // Show list of linked objects
2055
        $current_y = $pdf->getY();
2056
        $posy = pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, $w, 3, 'R', $default_font_size);
2057
        if ($current_y < $pdf->getY()) {
2058
            $top_shift = $pdf->getY() - $current_y;
2059
        }
2060
2061
        if ($showaddress) {
2062
            // Sender properties
2063
            $carac_emetteur = '';
2064
            // Add internal contact of object if defined
2065
            $arrayidcontact = $object->getIdContact('internal', 'BILLING');
2066
            if (count($arrayidcontact) > 0) {
2067
                $object->fetch_user($arrayidcontact[0]);
2068
                $labelbeforecontactname = ($outputlangs->transnoentities("FromContactName") != 'FromContactName' ? $outputlangs->transnoentities("FromContactName") : $outputlangs->transnoentities("Name"));
2069
                $carac_emetteur .= ($carac_emetteur ? "\n" : '') . $labelbeforecontactname . " " . $outputlangs->convToOutputCharset($object->user->getFullName($outputlangs));
2070
                $carac_emetteur .= "\n";
2071
            }
2072
2073
            $carac_emetteur .= pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, '', 0, 'source', $object);
2074
2075
            // Show sender
2076
            $posy = getDolGlobalString('MAIN_PDF_USE_ISO_LOCATION') ? 40 : 42;
2077
            $posy += $top_shift;
2078
            $posx = $this->marge_gauche;
2079
            if (getDolGlobalString('MAIN_INVERT_SENDER_RECIPIENT')) {
2080
                $posx = $this->page_largeur - $this->marge_droite - 80;
2081
            }
2082
2083
            $hautcadre = getDolGlobalString('MAIN_PDF_USE_ISO_LOCATION') ? 38 : 40;
2084
            $widthrecbox = getDolGlobalString('MAIN_PDF_USE_ISO_LOCATION') ? 92 : 82;
2085
2086
2087
            // Show sender frame
2088
            if (!getDolGlobalString('MAIN_PDF_NO_SENDER_FRAME')) {
2089
                $pdf->SetTextColor(0, 0, 0);
2090
                $pdf->SetFont('', '', $default_font_size - 2);
2091
                $pdf->SetXY($posx, $posy - 5);
2092
                $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillFrom"), 0, $ltrdirection);
2093
                $pdf->SetXY($posx, $posy);
2094
                $pdf->SetFillColor(230, 230, 230);
2095
                $pdf->MultiCell($widthrecbox, $hautcadre, "", 0, 'R', 1);
2096
                $pdf->SetTextColor(0, 0, 60);
2097
            }
2098
2099
            // Show sender name
2100
            if (!getDolGlobalString('MAIN_PDF_HIDE_SENDER_NAME')) {
2101
                $pdf->SetXY($posx + 2, $posy + 3);
2102
                $pdf->SetFont('', 'B', $default_font_size);
2103
                $pdf->MultiCell($widthrecbox - 2, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, $ltrdirection);
2104
                $posy = $pdf->getY();
2105
            }
2106
2107
            // Show sender information
2108
            $pdf->SetXY($posx + 2, $posy);
2109
            $pdf->SetFont('', '', $default_font_size - 1);
2110
            $pdf->MultiCell($widthrecbox - 2, 4, $carac_emetteur, 0, $ltrdirection);
2111
2112
2113
            // If BILLING contact defined on invoice, we use it
2114
            $usecontact = false;
2115
            $arrayidcontact = $object->getIdContact('external', 'BILLING');
2116
            if (count($arrayidcontact) > 0) {
2117
                $usecontact = true;
2118
                $result = $object->fetch_contact($arrayidcontact[0]);
2119
            }
2120
2121
            // Recipient name
2122
            if ($usecontact && ($object->contact->socid != $object->thirdparty->id && (!isset($conf->global->MAIN_USE_COMPANY_NAME_OF_CONTACT) || getDolGlobalString('MAIN_USE_COMPANY_NAME_OF_CONTACT')))) {
2123
                $thirdparty = $object->contact;
2124
            } else {
2125
                $thirdparty = $object->thirdparty;
2126
            }
2127
2128
            $carac_client_name = pdfBuildThirdpartyName($thirdparty, $outputlangs);
2129
2130
            $mode = 'target';
2131
            $carac_client = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, ($usecontact ? $object->contact : ''), $usecontact, $mode, $object);
2132
2133
            // Show recipient
2134
            $widthrecbox = getDolGlobalString('MAIN_PDF_USE_ISO_LOCATION') ? 92 : 100;
2135
            if ($this->page_largeur < 210) {
2136
                $widthrecbox = 84; // To work with US executive format
2137
            }
2138
            $posy = getDolGlobalString('MAIN_PDF_USE_ISO_LOCATION') ? 40 : 42;
2139
            $posy += $top_shift;
2140
            $posx = $this->page_largeur - $this->marge_droite - $widthrecbox;
2141
            if (getDolGlobalString('MAIN_INVERT_SENDER_RECIPIENT')) {
2142
                $posx = $this->marge_gauche;
2143
            }
2144
2145
            // Show recipient frame
2146
            if (!getDolGlobalString('MAIN_PDF_NO_RECIPENT_FRAME')) {
2147
                $pdf->SetTextColor(0, 0, 0);
2148
                $pdf->SetFont('', '', $default_font_size - 2);
2149
                $pdf->SetXY($posx + 2, $posy - 5);
2150
                $pdf->MultiCell($widthrecbox - 2, 5, $outputlangs->transnoentities("BillTo"), 0, $ltrdirection);
2151
                $pdf->Rect($posx, $posy, $widthrecbox, $hautcadre);
2152
            }
2153
2154
            // Show recipient name
2155
            $pdf->SetXY($posx + 2, $posy + 3);
2156
            $pdf->SetFont('', 'B', $default_font_size);
2157
            // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
2158
            $pdf->MultiCell($widthrecbox - 2, 2, $carac_client_name, 0, $ltrdirection);
2159
2160
            $posy = $pdf->getY();
2161
2162
            // Show recipient information
2163
            $pdf->SetFont('', '', $default_font_size - 1);
2164
            $pdf->SetXY($posx + 2, $posy);
2165
            // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
2166
            $pdf->MultiCell($widthrecbox - 2, 4, $carac_client, 0, $ltrdirection);
2167
2168
            // Show shipping address
2169
            if (getDolGlobalInt('INVOICE_SHOW_SHIPPING_ADDRESS')) {
2170
                $idaddressshipping = $object->getIdContact('external', 'SHIPPING');
2171
2172
                if (!empty($idaddressshipping)) {
2173
                    $contactshipping = $object->fetch_Contact($idaddressshipping[0]);
2174
                    $companystatic = new Societe($this->db);
2175
                    $companystatic->fetch($object->contact->fk_soc);
2176
                    $carac_client_name_shipping = pdfBuildThirdpartyName($object->contact, $outputlangs);
2177
                    $carac_client_shipping = pdf_build_address($outputlangs, $this->emetteur, $companystatic, $object->contact, $usecontact, 'target', $object);
2178
                } else {
2179
                    $carac_client_name_shipping = pdfBuildThirdpartyName($object->thirdparty, $outputlangs);
2180
                    $carac_client_shipping = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, '', 0, 'target', $object);
2181
                }
2182
                if (!empty($carac_client_shipping)) {
2183
                    $posy += $hautcadre;
2184
2185
                    // Show shipping frame
2186
                    $pdf->SetXY($posx + 2, $posy - 5);
2187
                    $pdf->SetFont('', '', $default_font_size - 2);
2188
                    $pdf->MultiCell($widthrecbox, '', $outputlangs->transnoentities('ShippingTo'), 0, 'L', 0);
2189
                    $pdf->Rect($posx, $posy, $widthrecbox, $hautcadre);
2190
2191
                    // Show shipping name
2192
                    $pdf->SetXY($posx + 2, $posy + 3);
2193
                    $pdf->SetFont('', 'B', $default_font_size);
2194
                    $pdf->MultiCell($widthrecbox - 2, 2, $carac_client_name_shipping, '', 'L');
2195
2196
                    $posy = $pdf->getY();
2197
2198
                    // Show shipping information
2199
                    $pdf->SetXY($posx + 2, $posy);
2200
                    $pdf->SetFont('', '', $default_font_size - 1);
2201
                    $pdf->MultiCell($widthrecbox - 2, 2, $carac_client_shipping, '', 'L');
2202
                    $top_shift += $hautcadre;
2203
                }
2204
            }
2205
        }
2206
2207
        $pdf->SetTextColor(0, 0, 0);
2208
2209
        return $top_shift;
2210
    }
2211
2212
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
2213
2214
    /**
2215
     *      Show footer of page. Need this->emetteur object
2216
     *
2217
     * @param TCPDF $pdf PDF
2218
     * @param Facture $object Object to show
2219
     * @param Translate $outputlangs Object lang for output
2220
     * @param int $hidefreetext 1=Hide free text
2221
     * @param int $heightforqrinvoice Height for QR invoices
2222
     * @return int                             Return height of bottom margin including footer text
2223
     */
2224
    protected function _pagefoot(&$pdf, $object, $outputlangs, $hidefreetext = 0, $heightforqrinvoice = 0)
2225
    {
2226
        $showdetails = getDolGlobalInt('MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS', 0);
2227
2228
        return pdf_pagefoot($pdf, $outputlangs, 'INVOICE_FREE_TEXT', $this->emetteur, $heightforqrinvoice + $this->marge_basse, $this->marge_gauche, $this->page_hauteur, $object, $showdetails, $hidefreetext, $this->page_largeur, $this->watermark);
2229
    }
2230
}
2231