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

pdf_sponge::drawInfoTable()   F

Complexity

Conditions 45
Paths > 20000

Size

Total Lines 158
Code Lines 92

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 45
eloc 92
c 0
b 0
f 0
nc 36726
nop 4
dl 0
loc 158
rs 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
/* 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