pdf_crabe::_tableau_tot()   F
last analyzed

Complexity

Conditions 78

Size

Total Lines 331
Code Lines 197

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 78
eloc 197
nop 6
dl 0
loc 331
rs 3.3333
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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