Passed
Branch develop (0d97d8)
by
unknown
25:42
created

pdf_sponge::_tableau()   B

Complexity

Conditions 8
Paths 40

Size

Total Lines 42
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 21
c 0
b 0
f 0
nc 40
nop 9
dl 0
loc 42
rs 8.4444

How to fix   Many Parameters   

Many Parameters

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

There are several approaches to avoid long parameter lists:

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