Passed
Branch develop (65fef4)
by
unknown
31:06
created

pdf_sponge::_tableau()   A

Complexity

Conditions 6

Size

Total Lines 36
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 18
c 0
b 0
f 0
nop 8
dl 0
loc 36
rs 9.0444

How to fix   Many Parameters   

Many Parameters

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

There are several approaches to avoid long parameter lists:

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