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

pdf_sponge::drawTotalTable()   F

Complexity

Conditions 92

Size

Total Lines 528
Code Lines 285

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 92
eloc 285
c 0
b 0
f 0
nop 5
dl 0
loc 528
rs 3.3333

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
/* Copyright (C) 2004-2014  Laurent Destailleur     <[email protected]>
3
 * Copyright (C) 2005-2012  Regis Houssin           <[email protected]>
4
 * Copyright (C) 2008       Raphael Bertrand        <[email protected]>
5
 * Copyright (C) 2010-2014  Juanjo Menent           <[email protected]>
6
 * Copyright (C) 2012       Christophe Battarel     <[email protected]>
7
 * Copyright (C) 2012       Cédric Salvador         <[email protected]>
8
 * Copyright (C) 2012-2014  Raphaël Doursenaud      <[email protected]>
9
 * Copyright (C) 2015       Marcos García           <[email protected]>
10
 * Copyright (C) 2017       Ferran Marcet           <[email protected]>
11
 * Copyright (C) 2018       Frédéric France         <[email protected]>
12
 *
13
 * This program is free software; you can redistribute it and/or modify
14
 * it under the terms of the GNU General Public License as published by
15
 * the Free Software Foundation; either version 3 of the License, or
16
 * (at your option) any later version.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 * GNU General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU General Public License
24
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
25
 * or see https://www.gnu.org/
26
 */
27
28
/**
29
 *  \file       htdocs/core/modules/facture/doc/pdf_sponge.modules.php
30
 *  \ingroup    facture
31
 *  \brief      File of class to generate customers invoices from sponge model
32
 */
33
34
require_once DOL_DOCUMENT_ROOT.'/core/modules/facture/modules_facture.php';
35
require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
36
require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
37
require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
38
require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
39
40
41
/**
42
 *	Class to manage PDF invoice template sponge
43
 */
44
class pdf_sponge extends ModelePDFFactures
45
{
46
    /**
47
     * @var DoliDb Database handler
48
     */
49
    public $db;
50
51
	/**
52
     * @var string model name
53
     */
54
    public $name;
55
56
	/**
57
     * @var string model description (short text)
58
     */
59
    public $description;
60
61
    /**
62
     * @var int     Save the name of generated file as the main doc when generating a doc with this template
63
     */
64
    public $update_main_doc_field;
65
66
	/**
67
     * @var string document type
68
     */
69
    public $type;
70
71
	/**
72
     * @var array Minimum version of PHP required by module.
73
     * e.g.: PHP ≥ 5.5 = array(5, 5)
74
     */
75
	public $phpmin = array(5, 5);
76
77
	/**
78
     * Dolibarr version of the loaded document
79
     * @var string
80
     */
81
	public $version = 'dolibarr';
82
83
     /**
84
     * @var int page_largeur
85
     */
86
    public $page_largeur;
87
88
	/**
89
     * @var int page_hauteur
90
     */
91
    public $page_hauteur;
92
93
	/**
94
     * @var array format
95
     */
96
    public $format;
97
98
	/**
99
     * @var int marge_gauche
100
     */
101
	public $marge_gauche;
102
103
	/**
104
     * @var int marge_droite
105
     */
106
	public $marge_droite;
107
108
	/**
109
     * @var int marge_haute
110
     */
111
	public $marge_haute;
112
113
	/**
114
     * @var int marge_basse
115
     */
116
	public $marge_basse;
117
118
    /**
119
	* Issuer
120
	* @var Societe Object that emits
121
	*/
122
	public $emetteur;
123
124
	/**
125
	 * @var bool Situation invoice type
126
	 */
127
	public $situationinvoice;
128
129
	/**
130
	 * @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