dolibarr  9.0.0
pdf_crabe.modules.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2004-2014 Laurent Destailleur <eldy@users.sourceforge.net>
3  * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
4  * Copyright (C) 2008 Raphael Bertrand <raphael.bertrand@resultic.fr>
5  * Copyright (C) 2010-2014 Juanjo Menent <jmenent@2byte.es>
6  * Copyright (C) 2012 Christophe Battarel <christophe.battarel@altairis.fr>
7  * Copyright (C) 2012 Cédric Salvador <csalvador@gpcsolutions.fr>
8  * Copyright (C) 2012-2014 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
9  * Copyright (C) 2015 Marcos García <marcosgdf@gmail.com>
10  * Copyright (C) 2017-2018 Ferran Marcet <fmarcet@2byte.es>
11  * Copyright (C) 2018 Frédéric France <frederic.france@netlogic.fr>
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 <http://www.gnu.org/licenses/>.
25  * or see http://www.gnu.org/
26  */
27 
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 
45 {
49  public $db;
50 
54  public $name;
55 
59  public $description;
60 
64  public $update_main_doc_field;
65 
69  public $type;
70 
75  public $phpmin = array(5, 4);
76 
81  public $version = 'dolibarr';
82 
86  public $page_largeur;
87 
91  public $page_hauteur;
92 
96  public $format;
97 
101  public $marge_gauche;
102 
106  public $marge_droite;
107 
111  public $marge_haute;
112 
116  public $marge_basse;
117 
122  public $emetteur;
123 
127  public $situationinvoice;
128 
132  public $posxprogress;
133 
134 
140  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 = "crabe";
149  $this->description = $langs->trans('PDFCrabeDescription');
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  // Dimensiont 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; // Affiche logo
164  $this->option_tva = 1; // Gere option tva FACTURE_TVAOPTION
165  $this->option_modereg = 1; // Affiche mode reglement
166  $this->option_condreg = 1; // Affiche conditions reglement
167  $this->option_codeproduitservice = 1; // Affiche code produit-service
168  $this->option_multilang = 1; // Dispo en plusieurs langues
169  $this->option_escompte = 1; // Affiche si il y a eu escompte
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;
182  if($conf->global->PRODUCT_USE_UNITS)
183  {
184  $this->posxtva=101;
185  $this->posxup=118;
186  $this->posxqty=135;
187  $this->posxunit=151;
188  }
189  else
190  {
191  $this->posxtva=110;
192  $this->posxup=126;
193  $this->posxqty=145;
194  }
195  $this->posxdiscount=162;
196  $this->posxprogress=126; // Only displayed for situation invoices
197  $this->postotalht=174;
198  if (! empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT) || ! empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_COLUMN)) $this->posxtva=$this->posxup;
199  $this->posxpicture=$this->posxtva - (empty($conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH)?20:$conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH); // width of images
200  if ($this->page_largeur < 210) // To work with US executive format
201  {
202  $this->posxpicture-=20;
203  $this->posxtva-=20;
204  $this->posxup-=20;
205  $this->posxqty-=20;
206  $this->posxunit-=20;
207  $this->posxdiscount-=20;
208  $this->posxprogress-=20;
209  $this->postotalht-=20;
210  }
211 
212  $this->tva=array();
213  $this->localtax1=array();
214  $this->localtax2=array();
215  $this->atleastoneratenotnull=0;
216  $this->atleastonediscount=0;
217  $this->situationinvoice=false;
218  }
219 
220 
221  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
233  function write_file($object,$outputlangs,$srctemplatepath='',$hidedetails=0,$hidedesc=0,$hideref=0)
234  {
235  // phpcs:enable
236  global $user,$langs,$conf,$mysoc,$db,$hookmanager,$nblignes;
237 
238  if (! is_object($outputlangs)) $outputlangs=$langs;
239  // For backward compatibility with FPDF, force output charset to ISO, because FPDF expect text to be encoded in ISO
240  if (! empty($conf->global->MAIN_USE_FPDF)) $outputlangs->charset_output='ISO-8859-1';
241 
242  // Load traductions files requiredby by page
243  $outputlangs->loadLangs(array("main", "bills", "products", "dict", "companies"));
244 
245  $nblignes = count($object->lines);
246 
247  // Loop on each lines to detect if there is at least one image to show
248  $realpatharray=array();
249  if (! empty($conf->global->MAIN_GENERATE_INVOICES_WITH_PICTURE))
250  {
251  for ($i = 0 ; $i < $nblignes ; $i++)
252  {
253  if (empty($object->lines[$i]->fk_product)) continue;
254 
255  $objphoto = new Product($this->db);
256  $objphoto->fetch($object->lines[$i]->fk_product);
257 
258  $pdir = get_exdir($object->lines[$i]->fk_product,2,0,0,$objphoto,'product') . $object->lines[$i]->fk_product ."/photos/";
259  $dir = $conf->product->dir_output.'/'.$pdir;
260 
261  $realpath='';
262  foreach ($objphoto->liste_photos($dir,1) as $key => $obj)
263  {
264  $filename=$obj['photo'];
265  //if ($obj['photo_vignette']) $filename='thumbs/'.$obj['photo_vignette'];
266  $realpath = $dir.$filename;
267  break;
268  }
269 
270  if ($realpath) $realpatharray[$i]=$realpath;
271  }
272  }
273  if (count($realpatharray) == 0) $this->posxpicture=$this->posxtva;
274 
275  if ($conf->facture->dir_output)
276  {
277  $object->fetch_thirdparty();
278 
279  $deja_regle = $object->getSommePaiement(($conf->multicurrency->enabled && $object->multicurrency_tx != 1) ? 1 : 0);
280  $amount_credit_notes_included = $object->getSumCreditNotesUsed(($conf->multicurrency->enabled && $object->multicurrency_tx != 1) ? 1 : 0);
281  $amount_deposits_included = $object->getSumDepositsUsed(($conf->multicurrency->enabled && $object->multicurrency_tx != 1) ? 1 : 0);
282 
283  // Definition of $dir and $file
284  if ($object->specimen)
285  {
286  $dir = $conf->facture->dir_output;
287  $file = $dir . "/SPECIMEN.pdf";
288  }
289  else
290  {
291  $objectref = dol_sanitizeFileName($object->ref);
292  $dir = $conf->facture->dir_output . "/" . $objectref;
293  $file = $dir . "/" . $objectref . ".pdf";
294  }
295  if (! file_exists($dir))
296  {
297  if (dol_mkdir($dir) < 0)
298  {
299  $this->error=$langs->transnoentities("ErrorCanNotCreateDir",$dir);
300  return 0;
301  }
302  }
303 
304  if (file_exists($dir))
305  {
306  // Add pdfgeneration hook
307  if (! is_object($hookmanager))
308  {
309  include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
310  $hookmanager=new HookManager($this->db);
311  }
312  $hookmanager->initHooks(array('pdfgeneration'));
313  $parameters=array('file'=>$file,'object'=>$object,'outputlangs'=>$outputlangs);
314  global $action;
315  $reshook=$hookmanager->executeHooks('beforePDFCreation',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks
316 
317  // Set nblignes with the new facture lines content after hook
318  $nblignes = count($object->lines);
319  $nbpayments = count($object->getListOfPayments());
320 
321  // Create pdf instance
322  $pdf=pdf_getInstance($this->format);
323  $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance
324  $pdf->SetAutoPageBreak(1,0);
325 
326  $heightforinfotot = 50+(4*$nbpayments); // Height reserved to output the info and total part and payment part
327  $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
328  $heightforfooter = $this->marge_basse + 8; // Height reserved to output the footer (value include bottom margin)
329  if ($conf->global->MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS >0) $heightforfooter+= 6;
330 
331  if (class_exists('TCPDF'))
332  {
333  $pdf->setPrintHeader(false);
334  $pdf->setPrintFooter(false);
335  }
336  $pdf->SetFont(pdf_getPDFFont($outputlangs));
337 
338  // Set path to the background PDF File
339  if (! empty($conf->global->MAIN_ADD_PDF_BACKGROUND))
340  {
341  $pagecount = $pdf->setSourceFile($conf->mycompany->dir_output.'/'.$conf->global->MAIN_ADD_PDF_BACKGROUND);
342  $tplidx = $pdf->importPage(1);
343  }
344 
345  $pdf->Open();
346  $pagenb=0;
347  $pdf->SetDrawColor(128,128,128);
348 
349  $pdf->SetTitle($outputlangs->convToOutputCharset($object->ref));
350  $pdf->SetSubject($outputlangs->transnoentities("PdfInvoiceTitle"));
351  $pdf->SetCreator("Dolibarr ".DOL_VERSION);
352  $pdf->SetAuthor($outputlangs->convToOutputCharset($user->getFullName($outputlangs)));
353  $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("PdfInvoiceTitle")." ".$outputlangs->convToOutputCharset($object->thirdparty->name));
354  if (! empty($conf->global->MAIN_DISABLE_PDF_COMPRESSION)) $pdf->SetCompression(false);
355 
356  $pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite); // Left, Top, Right
357 
358  // Positionne $this->atleastonediscount si on a au moins une remise
359  for ($i = 0 ; $i < $nblignes ; $i++)
360  {
361  if ($object->lines[$i]->remise_percent)
362  {
363  $this->atleastonediscount++;
364  }
365  }
366  if (empty($this->atleastonediscount) && empty($conf->global->PRODUCT_USE_UNITS)) // retreive space not used by discount
367  {
368  $this->posxpicture+=($this->postotalht - $this->posxdiscount);
369  $this->posxtva+=($this->postotalht - $this->posxdiscount);
370  $this->posxup+=($this->postotalht - $this->posxdiscount);
371  $this->posxqty+=($this->postotalht - $this->posxdiscount);
372  $this->posxdiscount+=($this->postotalht - $this->posxdiscount);
373  //$this->postotalht;
374  }
375 
376  $progress_width = 0;
377  // Situation invoice handling
378  if ($object->situation_cycle_ref)
379  {
380  $this->situationinvoice = true;
381  $progress_width = 18;
382  $this->posxtva -= $progress_width;
383  $this->posxup -= $progress_width;
384  $this->posxqty -= $progress_width;
385  if(empty($conf->global->PRODUCT_USE_UNITS)) {
386  $this->posxprogress += $progress_width;
387  }
388  /*$this->posxdiscount -= $progress_width;
389  $this->posxprogress -= $progress_width;*/
390  }
391 
392  // New page
393  $pdf->AddPage();
394  if (! empty($tplidx)) $pdf->useTemplate($tplidx);
395  $pagenb++;
396 
397  $top_shift = $this->_pagehead($pdf, $object, 1, $outputlangs);
398  $pdf->SetFont('','', $default_font_size - 1);
399  $pdf->MultiCell(0, 3, ''); // Set interline to 3
400  $pdf->SetTextColor(0,0,0);
401 
402  $tab_top = 90+$top_shift;
403  $tab_top_newpage = (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)?42+$top_shift:10);
404 
405  // Incoterm
406  if ($conf->incoterm->enabled)
407  {
408  $desc_incoterms = $object->getIncotermsForPDF();
409  if ($desc_incoterms)
410  {
411  $tab_top -= 2;
412 
413  $pdf->SetFont('','', $default_font_size - 1);
414  $pdf->writeHTMLCell(190, 3, $this->posxdesc-1, $tab_top-1, dol_htmlentitiesbr($desc_incoterms), 0, 1);
415  $nexY = $pdf->GetY();
416  $height_incoterms=$nexY-$tab_top;
417 
418  // Rect prend une longueur en 3eme param
419  $pdf->SetDrawColor(192,192,192);
420  $pdf->Rect($this->marge_gauche, $tab_top-1, $this->page_largeur-$this->marge_gauche-$this->marge_droite, $height_incoterms+1);
421 
422  $tab_top = $nexY+6;
423  }
424  }
425 
426  // Affiche notes
427  $notetoshow=empty($object->note_public)?'':$object->note_public;
428  if (! empty($conf->global->MAIN_ADD_SALE_REP_SIGNATURE_IN_NOTE))
429  {
430  // Get first sale rep
431  if (is_object($object->thirdparty))
432  {
433  $salereparray=$object->thirdparty->getSalesRepresentatives($user);
434  $salerepobj=new User($this->db);
435  $salerepobj->fetch($salereparray[0]['id']);
436  if (! empty($salerepobj->signature)) $notetoshow=dol_concatdesc($notetoshow, $salerepobj->signature);
437  }
438  }
439  if ($notetoshow)
440  {
441  $tab_top -= 2;
442 
443  $substitutionarray=pdf_getSubstitutionArray($outputlangs, null, $object);
444  complete_substitutions_array($substitutionarray, $outputlangs, $object);
445  $notetoshow = make_substitutions($notetoshow, $substitutionarray, $outputlangs);
446 
447  $pdf->SetFont('','', $default_font_size - 1);
448  $pdf->writeHTMLCell(190, 3, $this->posxdesc-1, $tab_top-1, dol_htmlentitiesbr($notetoshow), 0, 1);
449  $nexY = $pdf->GetY();
450  $height_note=$nexY-$tab_top;
451 
452  // Rect prend une longueur en 3eme param
453  $pdf->SetDrawColor(192,192,192);
454  $pdf->Rect($this->marge_gauche, $tab_top-1, $this->page_largeur-$this->marge_gauche-$this->marge_droite, $height_note+1);
455 
456  $tab_top = $nexY+6;
457  }
458 
459  $iniY = $tab_top + 7;
460  $curY = $tab_top + 7;
461  $nexY = $tab_top + 7;
462 
463  // Loop on each lines
464  for ($i = 0; $i < $nblignes; $i++)
465  {
466  $curY = $nexY;
467  $pdf->SetFont('','', $default_font_size - 1); // Into loop to work with multipage
468  $pdf->SetTextColor(0,0,0);
469 
470  // Define size of image if we need it
471  $imglinesize=array();
472  if (! empty($realpatharray[$i])) $imglinesize=pdf_getSizeForImage($realpatharray[$i]);
473 
474  $pdf->setTopMargin($tab_top_newpage);
475  $pdf->setPageOrientation('', 1, $heightforfooter+$heightforfreetext+$heightforinfotot); // The only function to edit the bottom margin of current page to set it.
476  $pageposbefore=$pdf->getPage();
477 
478  $showpricebeforepagebreak=1;
479  $posYAfterImage=0;
480  $posYAfterDescription=0;
481 
482  // We start with Photo of product line
483  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
484  {
485  $pdf->AddPage('','',true);
486  if (! empty($tplidx)) $pdf->useTemplate($tplidx);
487  if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) $this->_pagehead($pdf, $object, 0, $outputlangs);
488  $pdf->setPage($pageposbefore+1);
489 
490  $curY = $tab_top_newpage;
491  $showpricebeforepagebreak=0;
492  }
493 
494  if (isset($imglinesize['width']) && isset($imglinesize['height']))
495  {
496  $curX = $this->posxpicture-1;
497  $pdf->Image($realpatharray[$i], $curX + (($this->posxtva-$this->posxpicture-$imglinesize['width'])/2), $curY, $imglinesize['width'], $imglinesize['height'], '', '', '', 2, 300); // Use 300 dpi
498  // $pdf->Image does not increase value return by getY, so we save it manually
499  $posYAfterImage=$curY+$imglinesize['height'];
500  }
501 
502  // Description of product line
503  $curX = $this->posxdesc-1;
504 
505  $pdf->startTransaction();
506  pdf_writelinedesc($pdf,$object,$i,$outputlangs,$this->posxpicture-$curX-$progress_width,3,$curX,$curY,$hideref,$hidedesc);
507  $pageposafter=$pdf->getPage();
508  if ($pageposafter > $pageposbefore) // There is a pagebreak
509  {
510  $pdf->rollbackTransaction(true);
511  $pageposafter=$pageposbefore;
512  //print $pageposafter.'-'.$pageposbefore;exit;
513  $pdf->setPageOrientation('', 1, $heightforfooter); // The only function to edit the bottom margin of current page to set it.
514  pdf_writelinedesc($pdf,$object,$i,$outputlangs,$this->posxpicture-$curX-$progress_width,3,$curX,$curY,$hideref,$hidedesc);
515  $pageposafter=$pdf->getPage();
516  $posyafter=$pdf->GetY();
517  //var_dump($posyafter); var_dump(($this->page_hauteur - ($heightforfooter+$heightforfreetext+$heightforinfotot))); exit;
518  if ($posyafter > ($this->page_hauteur - ($heightforfooter+$heightforfreetext+$heightforinfotot))) // There is no space left for total+free text
519  {
520  if ($i == ($nblignes-1)) // No more lines, and no space left to show total, so we create a new page
521  {
522  $pdf->AddPage('','',true);
523  if (! empty($tplidx)) $pdf->useTemplate($tplidx);
524  if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) $this->_pagehead($pdf, $object, 0, $outputlangs);
525  $pdf->setPage($pageposafter+1);
526  }
527  }
528  else
529  {
530  // We found a page break
531  $showpricebeforepagebreak=0;
532  }
533  }
534  else // No pagebreak
535  {
536  $pdf->commitTransaction();
537  }
538  $posYAfterDescription=$pdf->GetY();
539 
540  $nexY = $pdf->GetY();
541  $pageposafter=$pdf->getPage();
542  $pdf->setPage($pageposbefore);
543  $pdf->setTopMargin($this->marge_haute);
544  $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it.
545 
546  // We suppose that a too long description or photo were moved completely on next page
547  if ($pageposafter > $pageposbefore && empty($showpricebeforepagebreak)) {
548  $pdf->setPage($pageposafter); $curY = $tab_top_newpage;
549  }
550 
551  $pdf->SetFont('','', $default_font_size - 1); // On repositionne la police par defaut
552 
553  // VAT Rate
554  if (empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT) && empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_COLUMN))
555  {
556  $vat_rate = pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails);
557  $pdf->SetXY($this->posxtva-5, $curY);
558  $pdf->MultiCell($this->posxup-$this->posxtva+4, 3, $vat_rate, 0, 'R');
559  }
560 
561  // Unit price before discount
562  $up_excl_tax = pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails);
563  $pdf->SetXY($this->posxup, $curY);
564  $pdf->MultiCell($this->posxqty-$this->posxup-0.8, 3, $up_excl_tax, 0, 'R', 0);
565 
566  // Quantity
567  $qty = pdf_getlineqty($object, $i, $outputlangs, $hidedetails);
568  $pdf->SetXY($this->posxqty, $curY);
569  // Enough for 6 chars
570 
571  if ($this->situationinvoice)
572  {
573  $pdf->MultiCell($this->posxprogress-$this->posxqty-0.8, 4, $qty, 0, 'R');
574  }
575  else if($conf->global->PRODUCT_USE_UNITS)
576  {
577  $pdf->MultiCell($this->posxunit-$this->posxqty-0.8, 4, $qty, 0, 'R');
578  }
579  else
580  {
581  $pdf->MultiCell($this->posxdiscount-$this->posxqty-0.8, 4, $qty, 0, 'R');
582  }
583 
584  // Situation progress
585  if ($this->situationinvoice)
586  {
587  $progress = pdf_getlineprogress($object, $i, $outputlangs, $hidedetails);
588  $pdf->SetXY($this->posxprogress, $curY);
589  if($conf->global->PRODUCT_USE_UNITS)
590  {
591  $pdf->MultiCell($this->posxunit-$this->posxprogress-1, 3, $progress, 0, 'R');
592  }
593  else if ($this->atleastonediscount)
594  {
595  $pdf->MultiCell($this->posxdiscount-$this->posxprogress-1, 3, $progress, 0, 'R');
596  }
597  else
598  {
599  $pdf->MultiCell($this->postotalht-$this->posxprogress-1, 3, $progress, 0, 'R');
600  }
601  }
602 
603  // Unit
604  if($conf->global->PRODUCT_USE_UNITS)
605  {
606  $unit = pdf_getlineunit($object, $i, $outputlangs, $hidedetails, $hookmanager);
607  $pdf->SetXY($this->posxunit, $curY);
608  $pdf->MultiCell($this->posxdiscount-$this->posxunit-0.8, 4, $unit, 0, 'L');
609  }
610 
611  // Discount on line
612  if ($object->lines[$i]->remise_percent)
613  {
614  $pdf->SetXY($this->posxdiscount-2, $curY);
615  $remise_percent = pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails);
616  $pdf->MultiCell($this->postotalht-$this->posxdiscount+2, 3, $remise_percent, 0, 'R');
617  }
618 
619  // Total HT line
620  $total_excl_tax = pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails);
621  $pdf->SetXY($this->postotalht, $curY);
622  $pdf->MultiCell($this->page_largeur-$this->marge_droite-$this->postotalht, 3, $total_excl_tax, 0, 'R', 0);
623 
624 
625  $sign=1;
626  if (isset($object->type) && $object->type == 2 && ! empty($conf->global->INVOICE_POSITIVE_CREDIT_NOTE)) $sign=-1;
627  // Collecte des totaux par valeur de tva dans $this->tva["taux"]=total_tva
628  $prev_progress = $object->lines[$i]->get_prev_progress($object->id);
629  if ($prev_progress > 0 && !empty($object->lines[$i]->situation_percent)) // Compute progress from previous situation
630  {
631  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;
632  else $tvaligne = $sign * $object->lines[$i]->total_tva * ($object->lines[$i]->situation_percent - $prev_progress) / $object->lines[$i]->situation_percent;
633  } else {
634  if ($conf->multicurrency->enabled && $object->multicurrency_tx != 1) $tvaligne= $sign * $object->lines[$i]->multicurrency_total_tva;
635  else $tvaligne= $sign * $object->lines[$i]->total_tva;
636  }
637 
638  $localtax1ligne=$object->lines[$i]->total_localtax1;
639  $localtax2ligne=$object->lines[$i]->total_localtax2;
640  $localtax1_rate=$object->lines[$i]->localtax1_tx;
641  $localtax2_rate=$object->lines[$i]->localtax2_tx;
642  $localtax1_type=$object->lines[$i]->localtax1_type;
643  $localtax2_type=$object->lines[$i]->localtax2_type;
644 
645  if ($object->remise_percent) $tvaligne-=($tvaligne*$object->remise_percent)/100;
646  if ($object->remise_percent) $localtax1ligne-=($localtax1ligne*$object->remise_percent)/100;
647  if ($object->remise_percent) $localtax2ligne-=($localtax2ligne*$object->remise_percent)/100;
648 
649  $vatrate=(string) $object->lines[$i]->tva_tx;
650 
651  // Retrieve type from database for backward compatibility with old records
652  if ((! isset($localtax1_type) || $localtax1_type=='' || ! isset($localtax2_type) || $localtax2_type=='') // if tax type not defined
653  && (! empty($localtax1_rate) || ! empty($localtax2_rate))) // and there is local tax
654  {
655  $localtaxtmp_array=getLocalTaxesFromRate($vatrate,0, $object->thirdparty, $mysoc);
656  $localtax1_type = $localtaxtmp_array[0];
657  $localtax2_type = $localtaxtmp_array[2];
658  }
659 
660  // retrieve global local tax
661  if ($localtax1_type && $localtax1ligne != 0)
662  $this->localtax1[$localtax1_type][$localtax1_rate]+=$localtax1ligne;
663  if ($localtax2_type && $localtax2ligne != 0)
664  $this->localtax2[$localtax2_type][$localtax2_rate]+=$localtax2ligne;
665 
666  if (($object->lines[$i]->info_bits & 0x01) == 0x01) $vatrate.='*';
667  if (! isset($this->tva[$vatrate])) $this->tva[$vatrate]=0;
668  $this->tva[$vatrate] += $tvaligne;
669 
670  if ($posYAfterImage > $posYAfterDescription) $nexY=$posYAfterImage;
671 
672  // Add line
673  if (! empty($conf->global->MAIN_PDF_DASH_BETWEEN_LINES) && $i < ($nblignes - 1))
674  {
675  $pdf->setPage($pageposafter);
676  $pdf->SetLineStyle(array('dash'=>'1,1','color'=>array(80,80,80)));
677  //$pdf->SetDrawColor(190,190,200);
678  $pdf->line($this->marge_gauche, $nexY+1, $this->page_largeur - $this->marge_droite, $nexY+1);
679  $pdf->SetLineStyle(array('dash'=>0));
680  }
681 
682  $nexY+=2; // Passe espace entre les lignes
683 
684  // Detect if some page were added automatically and output _tableau for past pages
685  while ($pagenb < $pageposafter)
686  {
687  $pdf->setPage($pagenb);
688  if ($pagenb == 1)
689  {
690  $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1, $object->multicurrency_code);
691  }
692  else
693  {
694  $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code);
695  }
696  $this->_pagefoot($pdf,$object,$outputlangs,1);
697  $pagenb++;
698  $pdf->setPage($pagenb);
699  $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it.
700  if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) $this->_pagehead($pdf, $object, 0, $outputlangs);
701  }
702  if (isset($object->lines[$i+1]->pagebreak) && $object->lines[$i+1]->pagebreak)
703  {
704  if ($pagenb == 1)
705  {
706  $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1, $object->multicurrency_code);
707  }
708  else
709  {
710  $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code);
711  }
712  $this->_pagefoot($pdf,$object,$outputlangs,1);
713  // New page
714  $pdf->AddPage();
715  if (! empty($tplidx)) $pdf->useTemplate($tplidx);
716  $pagenb++;
717  if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) $this->_pagehead($pdf, $object, 0, $outputlangs);
718  }
719  }
720 
721  // Show square
722  if ($pagenb == 1)
723  {
724  $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 0, 0, $object->multicurrency_code);
725  $bottomlasttab=$this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
726  }
727  else
728  {
729  $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 1, 0, $object->multicurrency_code);
730  $bottomlasttab=$this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
731  }
732 
733  // Affiche zone infos
734  $posy=$this->_tableau_info($pdf, $object, $bottomlasttab, $outputlangs);
735 
736  // Affiche zone totaux
737  $posy=$this->_tableau_tot($pdf, $object, $deja_regle, $bottomlasttab, $outputlangs);
738 
739  // Affiche zone versements
740  if (($deja_regle || $amount_credit_notes_included || $amount_deposits_included) && empty($conf->global->INVOICE_NO_PAYMENT_DETAILS))
741  {
742  $posy=$this->_tableau_versements($pdf, $object, $posy, $outputlangs);
743  }
744 
745  // Pied de page
746  $this->_pagefoot($pdf,$object,$outputlangs);
747  if (method_exists($pdf,'AliasNbPages')) $pdf->AliasNbPages();
748 
749  $pdf->Close();
750 
751  $pdf->Output($file,'F');
752 
753  // Add pdfgeneration hook
754  $hookmanager->initHooks(array('pdfgeneration'));
755  $parameters=array('file'=>$file,'object'=>$object,'outputlangs'=>$outputlangs);
756  global $action;
757  $reshook=$hookmanager->executeHooks('afterPDFCreation',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks
758 
759  if (! empty($conf->global->MAIN_UMASK))
760  @chmod($file, octdec($conf->global->MAIN_UMASK));
761 
762  $this->result = array('fullpath'=>$file);
763 
764  return 1; // No error
765  }
766  else
767  {
768  $this->error=$langs->transnoentities("ErrorCanNotCreateDir",$dir);
769  return 0;
770  }
771  }
772  else
773  {
774  $this->error=$langs->transnoentities("ErrorConstantNotDefined","FAC_OUTPUTDIR");
775  return 0;
776  }
777  }
778 
779 
780  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
790  function _tableau_versements(&$pdf, $object, $posy, $outputlangs)
791  {
792  // phpcs:enable
793  global $conf;
794 
795  $sign=1;
796  if ($object->type == 2 && ! empty($conf->global->INVOICE_POSITIVE_CREDIT_NOTE)) $sign=-1;
797 
798  $tab3_posx = 120;
799  $tab3_top = $posy + 8;
800  $tab3_width = 80;
801  $tab3_height = 4;
802  if ($this->page_largeur < 210) // To work with US executive format
803  {
804  $tab3_posx -= 20;
805  }
806 
807  $default_font_size = pdf_getPDFFontSize($outputlangs);
808 
809  $title=$outputlangs->transnoentities("PaymentsAlreadyDone");
810  if ($object->type == 2) $title=$outputlangs->transnoentities("PaymentsBackAlreadyDone");
811 
812  $pdf->SetFont('','', $default_font_size - 3);
813  $pdf->SetXY($tab3_posx, $tab3_top - 4);
814  $pdf->MultiCell(60, 3, $title, 0, 'L', 0);
815 
816  $pdf->line($tab3_posx, $tab3_top, $tab3_posx+$tab3_width, $tab3_top);
817 
818  $pdf->SetFont('','', $default_font_size - 4);
819  $pdf->SetXY($tab3_posx, $tab3_top);
820  $pdf->MultiCell(20, 3, $outputlangs->transnoentities("Payment"), 0, 'L', 0);
821  $pdf->SetXY($tab3_posx+21, $tab3_top);
822  $pdf->MultiCell(20, 3, $outputlangs->transnoentities("Amount"), 0, 'L', 0);
823  $pdf->SetXY($tab3_posx+40, $tab3_top);
824  $pdf->MultiCell(20, 3, $outputlangs->transnoentities("Type"), 0, 'L', 0);
825  $pdf->SetXY($tab3_posx+58, $tab3_top);
826  $pdf->MultiCell(20, 3, $outputlangs->transnoentities("Num"), 0, 'L', 0);
827 
828  $pdf->line($tab3_posx, $tab3_top-1+$tab3_height, $tab3_posx+$tab3_width, $tab3_top-1+$tab3_height);
829 
830  $y=0;
831 
832  $pdf->SetFont('','', $default_font_size - 4);
833 
834 
835  // Loop on each discount available (deposits and credit notes and excess of payment included)
836  $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,";
837  $sql.= " re.description, re.fk_facture_source,";
838  $sql.= " f.type, f.datef";
839  $sql.= " FROM ".MAIN_DB_PREFIX ."societe_remise_except as re, ".MAIN_DB_PREFIX ."facture as f";
840  $sql.= " WHERE re.fk_facture_source = f.rowid AND re.fk_facture = ".$object->id;
841  $resql=$this->db->query($sql);
842  if ($resql)
843  {
844  $num = $this->db->num_rows($resql);
845  $i=0;
846  $invoice=new Facture($this->db);
847  while ($i < $num)
848  {
849  $y+=3;
850  $obj = $this->db->fetch_object($resql);
851 
852  if ($obj->type == 2) $text=$outputlangs->transnoentities("CreditNote");
853  elseif ($obj->type == 3) $text=$outputlangs->transnoentities("Deposit");
854  elseif ($obj->type == 0) $text=$outputlangs->transnoentities("ExcessReceived");
855  else $text=$outputlangs->transnoentities("UnknownType");
856 
857  $invoice->fetch($obj->fk_facture_source);
858 
859  $pdf->SetXY($tab3_posx, $tab3_top+$y);
860  $pdf->MultiCell(20, 3, dol_print_date($obj->datef,'day',false,$outputlangs,true), 0, 'L', 0);
861  $pdf->SetXY($tab3_posx+21, $tab3_top+$y);
862  $pdf->MultiCell(20, 3, price(($conf->multicurrency->enabled && $object->multicurrency_tx != 1) ? $obj->multicurrency_amount_ttc : $obj->amount_ttc, 0, $outputlangs), 0, 'L', 0);
863  $pdf->SetXY($tab3_posx+40, $tab3_top+$y);
864  $pdf->MultiCell(20, 3, $text, 0, 'L', 0);
865  $pdf->SetXY($tab3_posx+58, $tab3_top+$y);
866  $pdf->MultiCell(20, 3, $invoice->ref, 0, 'L', 0);
867 
868  $pdf->line($tab3_posx, $tab3_top+$y+3, $tab3_posx+$tab3_width, $tab3_top+$y+3);
869 
870  $i++;
871  }
872  }
873  else
874  {
875  $this->error=$this->db->lasterror();
876  return -1;
877  }
878 
879  // Loop on each payment
880  // TODO Call getListOfPaymentsgetListOfPayments instead of hard coded sql
881  $sql = "SELECT p.datep as date, p.fk_paiement, p.num_paiement as num, pf.amount as amount, pf.multicurrency_amount,";
882  $sql.= " cp.code";
883  $sql.= " FROM ".MAIN_DB_PREFIX."paiement_facture as pf, ".MAIN_DB_PREFIX."paiement as p";
884  $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."c_paiement as cp ON p.fk_paiement = cp.id";
885  $sql.= " WHERE pf.fk_paiement = p.rowid AND pf.fk_facture = ".$object->id;
886  //$sql.= " WHERE pf.fk_paiement = p.rowid AND pf.fk_facture = 1";
887  $sql.= " ORDER BY p.datep";
888 
889  $resql=$this->db->query($sql);
890  if ($resql)
891  {
892  $num = $this->db->num_rows($resql);
893  $i=0;
894  while ($i < $num) {
895  $y+=3;
896  $row = $this->db->fetch_object($resql);
897 
898  $pdf->SetXY($tab3_posx, $tab3_top+$y);
899  $pdf->MultiCell(20, 3, dol_print_date($this->db->jdate($row->date),'day',false,$outputlangs,true), 0, 'L', 0);
900  $pdf->SetXY($tab3_posx+21, $tab3_top+$y);
901  $pdf->MultiCell(20, 3, price($sign * (($conf->multicurrency->enabled && $object->multicurrency_tx != 1) ? $row->multicurrency_amount : $row->amount), 0, $outputlangs), 0, 'L', 0);
902  $pdf->SetXY($tab3_posx+40, $tab3_top+$y);
903  $oper = $outputlangs->transnoentitiesnoconv("PaymentTypeShort" . $row->code);
904 
905  $pdf->MultiCell(20, 3, $oper, 0, 'L', 0);
906  $pdf->SetXY($tab3_posx+58, $tab3_top+$y);
907  $pdf->MultiCell(30, 3, $row->num, 0, 'L', 0);
908 
909  $pdf->line($tab3_posx, $tab3_top+$y+3, $tab3_posx+$tab3_width, $tab3_top+$y+3);
910 
911  $i++;
912  }
913  }
914  else
915  {
916  $this->error=$this->db->lasterror();
917  return -1;
918  }
919  }
920 
921 
922  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
932  function _tableau_info(&$pdf, $object, $posy, $outputlangs)
933  {
934  // phpcs:enable
935  global $conf;
936 
937  $default_font_size = pdf_getPDFFontSize($outputlangs);
938 
939  $pdf->SetFont('','', $default_font_size - 1);
940 
941  // If France, show VAT mention if not applicable
942  if ($this->emetteur->country_code == 'FR' && $this->franchise == 1)
943  {
944  $pdf->SetFont('','B', $default_font_size - 2);
945  $pdf->SetXY($this->marge_gauche, $posy);
946  $pdf->MultiCell(100, 3, $outputlangs->transnoentities("VATIsNotUsedForInvoice"), 0, 'L', 0);
947 
948  $posy=$pdf->GetY()+4;
949  }
950 
951  $posxval=52;
952 
953  // Show payments conditions
954  if ($object->type != 2 && ($object->cond_reglement_code || $object->cond_reglement))
955  {
956  $pdf->SetFont('','B', $default_font_size - 2);
957  $pdf->SetXY($this->marge_gauche, $posy);
958  $titre = $outputlangs->transnoentities("PaymentConditions").':';
959  $pdf->MultiCell(43, 4, $titre, 0, 'L');
960 
961  $pdf->SetFont('','', $default_font_size - 2);
962  $pdf->SetXY($posxval, $posy);
963  $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);
964  $lib_condition_paiement=str_replace('\n',"\n",$lib_condition_paiement);
965  $pdf->MultiCell(67, 4, $lib_condition_paiement,0,'L');
966 
967  $posy=$pdf->GetY()+3;
968  }
969 
970  if ($object->type != 2)
971  {
972  // Check a payment mode is defined
973  if (empty($object->mode_reglement_code)
974  && empty($conf->global->FACTURE_CHQ_NUMBER)
975  && empty($conf->global->FACTURE_RIB_NUMBER))
976  {
977  $this->error = $outputlangs->transnoentities("ErrorNoPaiementModeConfigured");
978  }
979  // Avoid having any valid PDF with setup that is not complete
980  elseif (($object->mode_reglement_code == 'CHQ' && empty($conf->global->FACTURE_CHQ_NUMBER) && empty($object->fk_account) && empty($object->fk_bank))
981  || ($object->mode_reglement_code == 'VIR' && empty($conf->global->FACTURE_RIB_NUMBER) && empty($object->fk_account) && empty($object->fk_bank)))
982  {
983  $outputlangs->load("errors");
984 
985  $pdf->SetXY($this->marge_gauche, $posy);
986  $pdf->SetTextColor(200,0,0);
987  $pdf->SetFont('','B', $default_font_size - 2);
988  $this->error = $outputlangs->transnoentities("ErrorPaymentModeDefinedToWithoutSetup",$object->mode_reglement_code);
989  $pdf->MultiCell(80, 3, $this->error,0,'L',0);
990  $pdf->SetTextColor(0,0,0);
991 
992  $posy=$pdf->GetY()+1;
993  }
994 
995  // Show payment mode
996  if ($object->mode_reglement_code
997  && $object->mode_reglement_code != 'CHQ'
998  && $object->mode_reglement_code != 'VIR')
999  {
1000  $pdf->SetFont('','B', $default_font_size - 2);
1001  $pdf->SetXY($this->marge_gauche, $posy);
1002  $titre = $outputlangs->transnoentities("PaymentMode").':';
1003  $pdf->MultiCell(80, 5, $titre, 0, 'L');
1004 
1005  $pdf->SetFont('','', $default_font_size - 2);
1006  $pdf->SetXY($posxval, $posy);
1007  $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);
1008  $pdf->MultiCell(80, 5, $lib_mode_reg,0,'L');
1009 
1010  $posy=$pdf->GetY()+2;
1011  }
1012 
1013  // Show payment mode CHQ
1014  if (empty($object->mode_reglement_code) || $object->mode_reglement_code == 'CHQ')
1015  {
1016  // Si mode reglement non force ou si force a CHQ
1017  if (! empty($conf->global->FACTURE_CHQ_NUMBER))
1018  {
1019  $diffsizetitle=(empty($conf->global->PDF_DIFFSIZE_TITLE)?3:$conf->global->PDF_DIFFSIZE_TITLE);
1020 
1021  if ($conf->global->FACTURE_CHQ_NUMBER > 0)
1022  {
1023  $account = new Account($this->db);
1024  $account->fetch($conf->global->FACTURE_CHQ_NUMBER);
1025 
1026  $pdf->SetXY($this->marge_gauche, $posy);
1027  $pdf->SetFont('','B', $default_font_size - $diffsizetitle);
1028  $pdf->MultiCell(100, 3, $outputlangs->transnoentities('PaymentByChequeOrderedTo',$account->proprio),0,'L',0);
1029  $posy=$pdf->GetY()+1;
1030 
1031  if (empty($conf->global->MAIN_PDF_HIDE_CHQ_ADDRESS))
1032  {
1033  $pdf->SetXY($this->marge_gauche, $posy);
1034  $pdf->SetFont('','', $default_font_size - $diffsizetitle);
1035  $pdf->MultiCell(100, 3, $outputlangs->convToOutputCharset($account->owner_address), 0, 'L', 0);
1036  $posy=$pdf->GetY()+2;
1037  }
1038  }
1039  if ($conf->global->FACTURE_CHQ_NUMBER == -1)
1040  {
1041  $pdf->SetXY($this->marge_gauche, $posy);
1042  $pdf->SetFont('','B', $default_font_size - $diffsizetitle);
1043  $pdf->MultiCell(100, 3, $outputlangs->transnoentities('PaymentByChequeOrderedTo',$this->emetteur->name),0,'L',0);
1044  $posy=$pdf->GetY()+1;
1045 
1046  if (empty($conf->global->MAIN_PDF_HIDE_CHQ_ADDRESS))
1047  {
1048  $pdf->SetXY($this->marge_gauche, $posy);
1049  $pdf->SetFont('','', $default_font_size - $diffsizetitle);
1050  $pdf->MultiCell(100, 3, $outputlangs->convToOutputCharset($this->emetteur->getFullAddress()), 0, 'L', 0);
1051  $posy=$pdf->GetY()+2;
1052  }
1053  }
1054  }
1055  }
1056 
1057  // If payment mode not forced or forced to VIR, show payment with BAN
1058  if (empty($object->mode_reglement_code) || $object->mode_reglement_code == 'VIR')
1059  {
1060  if (! empty($object->fk_account) || ! empty($object->fk_bank) || ! empty($conf->global->FACTURE_RIB_NUMBER))
1061  {
1062  $bankid=(empty($object->fk_account)?$conf->global->FACTURE_RIB_NUMBER:$object->fk_account);
1063  if (! empty($object->fk_bank)) $bankid=$object->fk_bank; // For backward compatibility when object->fk_account is forced with object->fk_bank
1064  $account = new Account($this->db);
1065  $account->fetch($bankid);
1066 
1067  $curx=$this->marge_gauche;
1068  $cury=$posy;
1069 
1070  $posy=pdf_bank($pdf,$outputlangs,$curx,$cury,$account,0,$default_font_size);
1071 
1072  $posy+=2;
1073  }
1074  }
1075  }
1076 
1077  return $posy;
1078  }
1079 
1080 
1081  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1092  function _tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs)
1093  {
1094  // phpcs:enable
1095  global $conf,$mysoc;
1096 
1097  $sign=1;
1098  if ($object->type == 2 && ! empty($conf->global->INVOICE_POSITIVE_CREDIT_NOTE)) $sign=-1;
1099 
1100  $default_font_size = pdf_getPDFFontSize($outputlangs);
1101 
1102  $tab2_top = $posy;
1103  $tab2_hl = 4;
1104  $pdf->SetFont('','', $default_font_size - 1);
1105 
1106  // Tableau total
1107  $col1x = 120; $col2x = 170;
1108  if ($this->page_largeur < 210) // To work with US executive format
1109  {
1110  $col2x-=20;
1111  }
1112  $largcol2 = ($this->page_largeur - $this->marge_droite - $col2x);
1113 
1114  $useborder=0;
1115  $index = 0;
1116 
1117  // Total HT
1118  $pdf->SetFillColor(255,255,255);
1119  $pdf->SetXY($col1x, $tab2_top + 0);
1120  $pdf->MultiCell($col2x-$col1x, $tab2_hl, $outputlangs->transnoentities("TotalHT"), 0, 'L', 1);
1121 
1122  $total_ht = (($conf->multicurrency->enabled && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? $object->multicurrency_total_ht : $object->total_ht);
1123  $pdf->SetXY($col2x, $tab2_top + 0);
1124  $pdf->MultiCell($largcol2, $tab2_hl, price($sign * ($total_ht + (! empty($object->remise)?$object->remise:0)), 0, $outputlangs), 0, 'R', 1);
1125 
1126  // Show VAT by rates and total
1127  $pdf->SetFillColor(248,248,248);
1128 
1129  $total_ttc = ($conf->multicurrency->enabled && $object->multicurrency_tx != 1) ? $object->multicurrency_total_ttc : $object->total_ttc;
1130 
1131  $this->atleastoneratenotnull=0;
1132  if (empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT))
1133  {
1134  $tvaisnull=((! empty($this->tva) && count($this->tva) == 1 && isset($this->tva['0.000']) && is_float($this->tva['0.000'])) ? true : false);
1135  if (! empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_IFNULL) && $tvaisnull)
1136  {
1137  // Nothing to do
1138  }
1139  else
1140  {
1141  // FIXME amount of vat not supported with multicurrency
1142 
1143  //Local tax 1 before VAT
1144  //if (! empty($conf->global->FACTURE_LOCAL_TAX1_OPTION) && $conf->global->FACTURE_LOCAL_TAX1_OPTION=='localtax1on')
1145  //{
1146  foreach( $this->localtax1 as $localtax_type => $localtax_rate )
1147  {
1148  if (in_array((string) $localtax_type, array('1','3','5'))) continue;
1149 
1150  foreach( $localtax_rate as $tvakey => $tvaval )
1151  {
1152  if ($tvakey!=0) // On affiche pas taux 0
1153  {
1154  //$this->atleastoneratenotnull++;
1155 
1156  $index++;
1157  $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1158 
1159  $tvacompl='';
1160  if (preg_match('/\*/',$tvakey))
1161  {
1162  $tvakey=str_replace('*','',$tvakey);
1163  $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1164  }
1165 
1166  $totalvat = $outputlangs->transcountrynoentities("TotalLT1",$mysoc->country_code).' ';
1167  $totalvat.=vatrate(abs($tvakey),1).$tvacompl;
1168  $pdf->MultiCell($col2x-$col1x, $tab2_hl, $totalvat, 0, 'L', 1);
1169 
1170  $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1171  $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1);
1172  }
1173  }
1174  }
1175  //}
1176  //Local tax 2 before VAT
1177  //if (! empty($conf->global->FACTURE_LOCAL_TAX2_OPTION) && $conf->global->FACTURE_LOCAL_TAX2_OPTION=='localtax2on')
1178  //{
1179  foreach( $this->localtax2 as $localtax_type => $localtax_rate )
1180  {
1181  if (in_array((string) $localtax_type, array('1','3','5'))) continue;
1182 
1183  foreach( $localtax_rate as $tvakey => $tvaval )
1184  {
1185  if ($tvakey!=0) // On affiche pas taux 0
1186  {
1187  //$this->atleastoneratenotnull++;
1188 
1189 
1190 
1191  $index++;
1192  $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1193 
1194  $tvacompl='';
1195  if (preg_match('/\*/',$tvakey))
1196  {
1197  $tvakey=str_replace('*','',$tvakey);
1198  $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1199  }
1200  $totalvat = $outputlangs->transcountrynoentities("TotalLT2",$mysoc->country_code).' ';
1201  $totalvat.=vatrate(abs($tvakey),1).$tvacompl;
1202  $pdf->MultiCell($col2x-$col1x, $tab2_hl, $totalvat, 0, 'L', 1);
1203 
1204  $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1205  $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1);
1206  }
1207  }
1208  }
1209 
1210  //}
1211 
1212  // VAT
1213  // Situations totals migth be wrong on huge amounts
1214  if ($object->situation_cycle_ref && $object->situation_counter > 1) {
1215 
1216  $sum_pdf_tva = 0;
1217  foreach($this->tva as $tvakey => $tvaval){
1218  $sum_pdf_tva+=$tvaval; // sum VAT amounts to compare to object
1219  }
1220 
1221  if($sum_pdf_tva!=$object->total_tva) { // apply coef to recover the VAT object amount (the good one)
1222  $coef_fix_tva = $object->total_tva / $sum_pdf_tva;
1223 
1224  foreach($this->tva as $tvakey => $tvaval) {
1225  $this->tva[$tvakey]=$tvaval * $coef_fix_tva;
1226  }
1227  }
1228  }
1229 
1230  foreach($this->tva as $tvakey => $tvaval)
1231  {
1232  if ($tvakey != 0) // On affiche pas taux 0
1233  {
1234  $this->atleastoneratenotnull++;
1235 
1236  $index++;
1237  $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1238 
1239  $tvacompl='';
1240  if (preg_match('/\*/',$tvakey))
1241  {
1242  $tvakey=str_replace('*','',$tvakey);
1243  $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1244  }
1245  $totalvat =$outputlangs->transcountrynoentities("TotalVAT",$mysoc->country_code).' ';
1246  $totalvat.=vatrate($tvakey,1).$tvacompl;
1247  $pdf->MultiCell($col2x-$col1x, $tab2_hl, $totalvat, 0, 'L', 1);
1248 
1249  $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1250  $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1);
1251  }
1252  }
1253 
1254  //Local tax 1 after VAT
1255  //if (! empty($conf->global->FACTURE_LOCAL_TAX1_OPTION) && $conf->global->FACTURE_LOCAL_TAX1_OPTION=='localtax1on')
1256  //{
1257  foreach( $this->localtax1 as $localtax_type => $localtax_rate )
1258  {
1259  if (in_array((string) $localtax_type, array('2','4','6'))) continue;
1260 
1261  foreach( $localtax_rate as $tvakey => $tvaval )
1262  {
1263  if ($tvakey != 0) // On affiche pas taux 0
1264  {
1265  //$this->atleastoneratenotnull++;
1266 
1267  $index++;
1268  $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1269 
1270  $tvacompl='';
1271  if (preg_match('/\*/',$tvakey))
1272  {
1273  $tvakey=str_replace('*','',$tvakey);
1274  $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1275  }
1276  $totalvat = $outputlangs->transcountrynoentities("TotalLT1",$mysoc->country_code).' ';
1277  $totalvat.=vatrate(abs($tvakey),1).$tvacompl;
1278 
1279  $pdf->MultiCell($col2x-$col1x, $tab2_hl, $totalvat, 0, 'L', 1);
1280  $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1281  $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1);
1282  }
1283  }
1284  }
1285  //}
1286  //Local tax 2 after VAT
1287  //if (! empty($conf->global->FACTURE_LOCAL_TAX2_OPTION) && $conf->global->FACTURE_LOCAL_TAX2_OPTION=='localtax2on')
1288  //{
1289  foreach( $this->localtax2 as $localtax_type => $localtax_rate )
1290  {
1291  if (in_array((string) $localtax_type, array('2','4','6'))) continue;
1292 
1293  foreach( $localtax_rate as $tvakey => $tvaval )
1294  {
1295  // retrieve global local tax
1296  if ($tvakey != 0) // On affiche pas taux 0
1297  {
1298  //$this->atleastoneratenotnull++;
1299 
1300  $index++;
1301  $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1302 
1303  $tvacompl='';
1304  if (preg_match('/\*/',$tvakey))
1305  {
1306  $tvakey=str_replace('*','',$tvakey);
1307  $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1308  }
1309  $totalvat = $outputlangs->transcountrynoentities("TotalLT2",$mysoc->country_code).' ';
1310 
1311  $totalvat.=vatrate(abs($tvakey),1).$tvacompl;
1312  $pdf->MultiCell($col2x-$col1x, $tab2_hl, $totalvat, 0, 'L', 1);
1313 
1314  $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1315  $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1);
1316  }
1317  }
1318  //}
1319  }
1320 
1321  // Revenue stamp
1322  if (price2num($object->revenuestamp) != 0)
1323  {
1324  $index++;
1325  $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1326  $pdf->MultiCell($col2x-$col1x, $tab2_hl, $outputlangs->transnoentities("RevenueStamp"), $useborder, 'L', 1);
1327 
1328  $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1329  $pdf->MultiCell($largcol2, $tab2_hl, price($sign * $object->revenuestamp), $useborder, 'R', 1);
1330  }
1331 
1332  // Total TTC
1333  $index++;
1334  $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1335  $pdf->SetTextColor(0,0,60);
1336  $pdf->SetFillColor(224,224,224);
1337  $pdf->MultiCell($col2x-$col1x, $tab2_hl, $outputlangs->transnoentities("TotalTTC"), $useborder, 'L', 1);
1338 
1339  $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1340  $pdf->MultiCell($largcol2, $tab2_hl, price($sign * $total_ttc, 0, $outputlangs), $useborder, 'R', 1);
1341  }
1342  }
1343 
1344  $pdf->SetTextColor(0,0,0);
1345  $creditnoteamount=$object->getSumCreditNotesUsed(($conf->multicurrency->enabled && $object->multicurrency_tx != 1) ? 1 : 0); // Warning, this also include excess received
1346  $depositsamount=$object->getSumDepositsUsed(($conf->multicurrency->enabled && $object->multicurrency_tx != 1) ? 1 : 0);
1347  //print "x".$creditnoteamount."-".$depositsamount;exit;
1348  $resteapayer = price2num($total_ttc - $deja_regle - $creditnoteamount - $depositsamount, 'MT');
1349  if ($object->paye) $resteapayer=0;
1350 
1351  if (($deja_regle > 0 || $creditnoteamount > 0 || $depositsamount > 0) && empty($conf->global->INVOICE_NO_PAYMENT_DETAILS))
1352  {
1353  // Already paid + Deposits
1354  $index++;
1355  $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1356  $pdf->MultiCell($col2x-$col1x, $tab2_hl, $outputlangs->transnoentities("Paid"), 0, 'L', 0);
1357  $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1358  $pdf->MultiCell($largcol2, $tab2_hl, price($deja_regle + $depositsamount, 0, $outputlangs), 0, 'R', 0);
1359 
1360  // Credit note
1361  if ($creditnoteamount)
1362  {
1363  $labeltouse = ($outputlangs->transnoentities("CreditNotesOrExcessReceived") != "CreditNotesOrExcessReceived") ? $outputlangs->transnoentities("CreditNotesOrExcessReceived") : $outputlangs->transnoentities("CreditNotes");
1364  $index++;
1365  $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1366  $pdf->MultiCell($col2x-$col1x, $tab2_hl, $labeltouse, 0, 'L', 0);
1367  $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1368  $pdf->MultiCell($largcol2, $tab2_hl, price($creditnoteamount, 0, $outputlangs), 0, 'R', 0);
1369  }
1370 
1371  // Escompte
1372  if ($object->close_code == Facture::CLOSECODE_DISCOUNTVAT)
1373  {
1374  $index++;
1375  $pdf->SetFillColor(255,255,255);
1376 
1377  $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1378  $pdf->MultiCell($col2x-$col1x, $tab2_hl, $outputlangs->transnoentities("EscompteOfferedShort"), $useborder, 'L', 1);
1379  $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1380  $pdf->MultiCell($largcol2, $tab2_hl, price($object->total_ttc - $deja_regle - $creditnoteamount - $depositsamount, 0, $outputlangs), $useborder, 'R', 1);
1381 
1382  $resteapayer=0;
1383  }
1384 
1385  $index++;
1386  $pdf->SetTextColor(0,0,60);
1387  $pdf->SetFillColor(224,224,224);
1388  $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1389  $pdf->MultiCell($col2x-$col1x, $tab2_hl, $outputlangs->transnoentities("RemainderToPay"), $useborder, 'L', 1);
1390  $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1391  $pdf->MultiCell($largcol2, $tab2_hl, price($resteapayer, 0, $outputlangs), $useborder, 'R', 1);
1392 
1393  $pdf->SetFont('','', $default_font_size - 1);
1394  $pdf->SetTextColor(0,0,0);
1395  }
1396 
1397  $index++;
1398  return ($tab2_top + ($tab2_hl * $index));
1399  }
1400 
1414  function _tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop=0, $hidebottom=0, $currency='')
1415  {
1416  global $conf;
1417 
1418  // Force to disable hidetop and hidebottom
1419  $hidebottom=0;
1420  if ($hidetop) $hidetop=-1;
1421 
1422  $currency = !empty($currency) ? $currency : $conf->currency;
1423  $default_font_size = pdf_getPDFFontSize($outputlangs);
1424 
1425  // Amount in (at tab_top - 1)
1426  $pdf->SetTextColor(0,0,0);
1427  $pdf->SetFont('','', $default_font_size - 2);
1428 
1429  if (empty($hidetop))
1430  {
1431  $titre = $outputlangs->transnoentities("AmountInCurrency",$outputlangs->transnoentitiesnoconv("Currency".$currency));
1432  $pdf->SetXY($this->page_largeur - $this->marge_droite - ($pdf->GetStringWidth($titre) + 3), $tab_top-4);
1433  $pdf->MultiCell(($pdf->GetStringWidth($titre) + 3), 2, $titre);
1434 
1435  //$conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR='230,230,230';
1436  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));
1437  }
1438 
1439  $pdf->SetDrawColor(128,128,128);
1440  $pdf->SetFont('','', $default_font_size - 1);
1441 
1442  // Output Rect
1443  $this->printRect($pdf,$this->marge_gauche, $tab_top, $this->page_largeur-$this->marge_gauche-$this->marge_droite, $tab_height, $hidetop, $hidebottom); // Rect prend une longueur en 3eme param et 4eme param
1444 
1445  if (empty($hidetop))
1446  {
1447  $pdf->line($this->marge_gauche, $tab_top+5, $this->page_largeur-$this->marge_droite, $tab_top+5); // line prend une position y en 2eme param et 4eme param
1448 
1449  $pdf->SetXY($this->posxdesc-1, $tab_top+1);
1450  $pdf->MultiCell(108,2, $outputlangs->transnoentities("Designation"),'','L');
1451  }
1452 
1453  if (! empty($conf->global->MAIN_GENERATE_INVOICES_WITH_PICTURE))
1454  {
1455  $pdf->line($this->posxpicture-1, $tab_top, $this->posxpicture-1, $tab_top + $tab_height);
1456  if (empty($hidetop))
1457  {
1458  //$pdf->SetXY($this->posxpicture-1, $tab_top+1);
1459  //$pdf->MultiCell($this->posxtva-$this->posxpicture-1,2, $outputlangs->transnoentities("Photo"),'','C');
1460  }
1461  }
1462 
1463  if (empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT) && empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_COLUMN))
1464  {
1465  $pdf->line($this->posxtva-1, $tab_top, $this->posxtva-1, $tab_top + $tab_height);
1466  if (empty($hidetop))
1467  {
1468  $pdf->SetXY($this->posxtva-3, $tab_top+1);
1469  $pdf->MultiCell($this->posxup-$this->posxtva+3,2, $outputlangs->transnoentities("VAT"),'','C');
1470  }
1471  }
1472 
1473  $pdf->line($this->posxup-1, $tab_top, $this->posxup-1, $tab_top + $tab_height);
1474  if (empty($hidetop))
1475  {
1476  $pdf->SetXY($this->posxup-1, $tab_top+1);
1477  $pdf->MultiCell($this->posxqty-$this->posxup-1,2, $outputlangs->transnoentities("PriceUHT"),'','C');
1478  }
1479 
1480  $pdf->line($this->posxqty-1, $tab_top, $this->posxqty-1, $tab_top + $tab_height);
1481  if (empty($hidetop))
1482  {
1483  $pdf->SetXY($this->posxqty-1, $tab_top+1);
1484 
1485  if($this->situationinvoice)
1486  {
1487  $pdf->MultiCell($this->posxprogress-$this->posxqty-1,2, $outputlangs->transnoentities("Qty"),'','C');
1488  }
1489  else if($conf->global->PRODUCT_USE_UNITS)
1490  {
1491  $pdf->MultiCell($this->posxunit-$this->posxqty-1,2, $outputlangs->transnoentities("Qty"),'','C');
1492  }
1493  else
1494  {
1495  $pdf->MultiCell($this->posxdiscount-$this->posxqty-1,2, $outputlangs->transnoentities("Qty"),'','C');
1496  }
1497  }
1498 
1499  if ($this->situationinvoice) {
1500  $pdf->line($this->posxprogress - 1, $tab_top, $this->posxprogress - 1, $tab_top + $tab_height);
1501 
1502  if (empty($hidetop)) {
1503 
1504  $pdf->SetXY($this->posxprogress, $tab_top+1);
1505 
1506  if($conf->global->PRODUCT_USE_UNITS)
1507  {
1508  $pdf->MultiCell($this->posxunit-$this->posxprogress,2, $outputlangs->transnoentities("Progress"),'','C');
1509  }
1510  else if ($this->atleastonediscount)
1511  {
1512  $pdf->MultiCell($this->posxdiscount-$this->posxprogress,2, $outputlangs->transnoentities("Progress"),'','C');
1513  }
1514  else
1515  {
1516  $pdf->MultiCell($this->postotalht-$this->posxprogress,2, $outputlangs->transnoentities("Progress"),'','C');
1517  }
1518  }
1519  }
1520 
1521  if($conf->global->PRODUCT_USE_UNITS) {
1522  $pdf->line($this->posxunit - 1, $tab_top, $this->posxunit - 1, $tab_top + $tab_height);
1523  if (empty($hidetop)) {
1524  $pdf->SetXY($this->posxunit - 1, $tab_top + 1);
1525  $pdf->MultiCell($this->posxdiscount - $this->posxunit - 1, 2, $outputlangs->transnoentities("Unit"), '',
1526  'C');
1527  }
1528  }
1529 
1530  $pdf->line($this->posxdiscount-1, $tab_top, $this->posxdiscount-1, $tab_top + $tab_height);
1531  if (empty($hidetop))
1532  {
1533  if ($this->atleastonediscount)
1534  {
1535  $pdf->SetXY($this->posxdiscount-1, $tab_top+1);
1536  $pdf->MultiCell($this->postotalht-$this->posxdiscount+1,2, $outputlangs->transnoentities("ReductionShort"),'','C');
1537  }
1538  }
1539 
1540  if ($this->situationinvoice)
1541  {
1542  $pdf->line($this->postotalht+4, $tab_top, $this->postotalht+4, $tab_top + $tab_height);
1543  if (empty($hidetop))
1544  {
1545  $pdf->SetXY($this->postotalht-19, $tab_top+1);
1546  $pdf->MultiCell(30,2, $outputlangs->transnoentities("Situation"),'','C');
1547  }
1548  }
1549 
1550  if ($this->atleastonediscount)
1551  {
1552  $pdf->line($this->postotalht, $tab_top, $this->postotalht, $tab_top + $tab_height);
1553  }
1554  if (empty($hidetop))
1555  {
1556  $pdf->SetXY($this->postotalht-1, $tab_top+1);
1557  $pdf->MultiCell(30,2, $outputlangs->transnoentities("TotalHT"),'','C');
1558  }
1559  }
1560 
1570  function _pagehead(&$pdf, $object, $showaddress, $outputlangs)
1571  {
1572  global $conf, $langs;
1573 
1574  // Load traductions files requiredby by page
1575  $outputlangs->loadLangs(array("main", "bills", "propal", "companies"));
1576 
1577  $default_font_size = pdf_getPDFFontSize($outputlangs);
1578 
1579  pdf_pagehead($pdf,$outputlangs,$this->page_hauteur);
1580 
1581  // Show Draft Watermark
1582  if($object->statut==Facture::STATUS_DRAFT && (! empty($conf->global->FACTURE_DRAFT_WATERMARK)) )
1583  {
1584  pdf_watermark($pdf,$outputlangs,$this->page_hauteur,$this->page_largeur,'mm',$conf->global->FACTURE_DRAFT_WATERMARK);
1585  }
1586 
1587  $pdf->SetTextColor(0,0,60);
1588  $pdf->SetFont('','B', $default_font_size + 3);
1589 
1590  $w = 110;
1591 
1592  $posy=$this->marge_haute;
1593  $posx=$this->page_largeur-$this->marge_droite-$w;
1594 
1595  $pdf->SetXY($this->marge_gauche,$posy);
1596 
1597  // Logo
1598  if (empty($conf->global->PDF_DISABLE_MYCOMPANY_LOGO))
1599  {
1600  $logo=$conf->mycompany->dir_output.'/logos/'.$this->emetteur->logo;
1601  if ($this->emetteur->logo)
1602  {
1603  if (is_readable($logo))
1604  {
1605  $height=pdf_getHeightForLogo($logo);
1606  $pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto)
1607  }
1608  else
1609  {
1610  $pdf->SetTextColor(200,0,0);
1611  $pdf->SetFont('','B',$default_font_size - 2);
1612  $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound",$logo), 0, 'L');
1613  $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ErrorGoToGlobalSetup"), 0, 'L');
1614  }
1615  }
1616  else
1617  {
1618  $text=$this->emetteur->name;
1619  $pdf->MultiCell($w, 4, $outputlangs->convToOutputCharset($text), 0, 'L');
1620  }
1621  }
1622 
1623  $pdf->SetFont('','B', $default_font_size + 3);
1624  $pdf->SetXY($posx,$posy);
1625  $pdf->SetTextColor(0,0,60);
1626  $title=$outputlangs->transnoentities("PdfInvoiceTitle");
1627  if ($object->type == 1) $title=$outputlangs->transnoentities("InvoiceReplacement");
1628  if ($object->type == 2) $title=$outputlangs->transnoentities("InvoiceAvoir");
1629  if ($object->type == 3) $title=$outputlangs->transnoentities("InvoiceDeposit");
1630  if ($object->type == 4) $title=$outputlangs->transnoentities("InvoiceProForma");
1631  if ($this->situationinvoice) $title=$outputlangs->transnoentities("InvoiceSituation");
1632  $pdf->MultiCell($w, 3, $title, '', 'R');
1633 
1634  $pdf->SetFont('','B',$default_font_size);
1635 
1636  $posy+=5;
1637  $pdf->SetXY($posx,$posy);
1638  $pdf->SetTextColor(0,0,60);
1639  $textref=$outputlangs->transnoentities("Ref")." : " . $outputlangs->convToOutputCharset($object->ref);
1640  if ($object->statut == Facture::STATUS_DRAFT)
1641  {
1642  $pdf->SetTextColor(128,0,0);
1643  $textref.=' - '.$outputlangs->transnoentities("NotValidated");
1644  }
1645  $pdf->MultiCell($w, 4, $textref, '', 'R');
1646 
1647  $posy+=1;
1648  $pdf->SetFont('','', $default_font_size - 2);
1649 
1650  if ($object->ref_client)
1651  {
1652  $posy+=4;
1653  $pdf->SetXY($posx,$posy);
1654  $pdf->SetTextColor(0,0,60);
1655  $pdf->MultiCell($w, 3, $outputlangs->transnoentities("RefCustomer")." : " . $outputlangs->convToOutputCharset($object->ref_client), '', 'R');
1656  }
1657 
1658  $objectidnext=$object->getIdReplacingInvoice('validated');
1659  if ($object->type == 0 && $objectidnext)
1660  {
1661  $objectreplacing=new Facture($this->db);
1662  $objectreplacing->fetch($objectidnext);
1663 
1664  $posy+=3;
1665  $pdf->SetXY($posx,$posy);
1666  $pdf->SetTextColor(0,0,60);
1667  $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ReplacementByInvoice").' : '.$outputlangs->convToOutputCharset($objectreplacing->ref), '', 'R');
1668  }
1669  if ($object->type == 1)
1670  {
1671  $objectreplaced=new Facture($this->db);
1672  $objectreplaced->fetch($object->fk_facture_source);
1673 
1674  $posy+=4;
1675  $pdf->SetXY($posx,$posy);
1676  $pdf->SetTextColor(0,0,60);
1677  $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ReplacementInvoice").' : '.$outputlangs->convToOutputCharset($objectreplaced->ref), '', 'R');
1678  }
1679  if ($object->type == 2 && !empty($object->fk_facture_source))
1680  {
1681  $objectreplaced=new Facture($this->db);
1682  $objectreplaced->fetch($object->fk_facture_source);
1683 
1684  $posy+=3;
1685  $pdf->SetXY($posx,$posy);
1686  $pdf->SetTextColor(0,0,60);
1687  $pdf->MultiCell($w, 3, $outputlangs->transnoentities("CorrectionInvoice").' : '.$outputlangs->convToOutputCharset($objectreplaced->ref), '', 'R');
1688  }
1689 
1690  $posy+=4;
1691  $pdf->SetXY($posx,$posy);
1692  $pdf->SetTextColor(0,0,60);
1693  $pdf->MultiCell($w, 3, $outputlangs->transnoentities("DateInvoice")." : " . dol_print_date($object->date,"day",false,$outputlangs), '', 'R');
1694 
1695  if (! empty($conf->global->INVOICE_POINTOFTAX_DATE))
1696  {
1697  $posy+=4;
1698  $pdf->SetXY($posx,$posy);
1699  $pdf->SetTextColor(0,0,60);
1700  $pdf->MultiCell($w, 3, $outputlangs->transnoentities("DatePointOfTax")." : " . dol_print_date($object->date_pointoftax,"day",false,$outputlangs), '', 'R');
1701  }
1702 
1703  if ($object->type != 2)
1704  {
1705  $posy+=3;
1706  $pdf->SetXY($posx,$posy);
1707  $pdf->SetTextColor(0,0,60);
1708  $pdf->MultiCell($w, 3, $outputlangs->transnoentities("DateDue")." : " . dol_print_date($object->date_lim_reglement,"day",false,$outputlangs,true), '', 'R');
1709  }
1710 
1711  if ($object->thirdparty->code_client)
1712  {
1713  $posy+=3;
1714  $pdf->SetXY($posx,$posy);
1715  $pdf->SetTextColor(0,0,60);
1716  $pdf->MultiCell($w, 3, $outputlangs->transnoentities("CustomerCode")." : " . $outputlangs->transnoentities($object->thirdparty->code_client), '', 'R');
1717  }
1718 
1719  // Get contact
1720  if (!empty($conf->global->DOC_SHOW_FIRST_SALES_REP))
1721  {
1722  $arrayidcontact=$object->getIdContact('internal','SALESREPFOLL');
1723  if (count($arrayidcontact) > 0)
1724  {
1725  $usertmp=new User($this->db);
1726  $usertmp->fetch($arrayidcontact[0]);
1727  $posy+=4;
1728  $pdf->SetXY($posx,$posy);
1729  $pdf->SetTextColor(0,0,60);
1730  $pdf->MultiCell($w, 3, $langs->transnoentities("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R');
1731  }
1732  }
1733 
1734  $posy+=1;
1735 
1736  $top_shift = 0;
1737  // Show list of linked objects
1738  $current_y = $pdf->getY();
1739  $posy = pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, $w, 3, 'R', $default_font_size);
1740  if ($current_y < $pdf->getY())
1741  {
1742  $top_shift = $pdf->getY() - $current_y;
1743  }
1744 
1745  if ($showaddress)
1746  {
1747  // Sender properties
1748  $carac_emetteur = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, '', 0, 'source', $object);
1749 
1750  // Show sender
1751  $posy=!empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 40 : 42;
1752  $posy+=$top_shift;
1753  $posx=$this->marge_gauche;
1754  if (! empty($conf->global->MAIN_INVERT_SENDER_RECIPIENT)) $posx=$this->page_largeur-$this->marge_droite-80;
1755 
1756  $hautcadre=!empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 38 : 40;
1757  $widthrecbox=!empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 92 : 82;
1758 
1759 
1760  // Show sender frame
1761  $pdf->SetTextColor(0,0,0);
1762  $pdf->SetFont('','', $default_font_size - 2);
1763  $pdf->SetXY($posx,$posy-5);
1764  $pdf->MultiCell(66,5, $outputlangs->transnoentities("BillFrom").":", 0, 'L');
1765  $pdf->SetXY($posx,$posy);
1766  $pdf->SetFillColor(230,230,230);
1767  $pdf->MultiCell($widthrecbox, $hautcadre, "", 0, 'R', 1);
1768  $pdf->SetTextColor(0,0,60);
1769 
1770  // Show sender name
1771  $pdf->SetXY($posx+2,$posy+3);
1772  $pdf->SetFont('','B', $default_font_size);
1773  $pdf->MultiCell($widthrecbox-2, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, 'L');
1774  $posy=$pdf->getY();
1775 
1776  // Show sender information
1777  $pdf->SetXY($posx+2,$posy);
1778  $pdf->SetFont('','', $default_font_size - 1);
1779  $pdf->MultiCell($widthrecbox-2, 4, $carac_emetteur, 0, 'L');
1780 
1781 
1782 
1783  // If BILLING contact defined on invoice, we use it
1784  $usecontact=false;
1785  $arrayidcontact=$object->getIdContact('external','BILLING');
1786  if (count($arrayidcontact) > 0)
1787  {
1788  $usecontact=true;
1789  $result=$object->fetch_contact($arrayidcontact[0]);
1790  }
1791 
1792  //Recipient name
1793  // On peut utiliser le nom de la societe du contact
1794  if ($usecontact && !empty($conf->global->MAIN_USE_COMPANY_NAME_OF_CONTACT)) {
1795  $thirdparty = $object->contact;
1796  } else {
1797  $thirdparty = $object->thirdparty;
1798  }
1799 
1800  $carac_client_name= pdfBuildThirdpartyName($thirdparty, $outputlangs);
1801 
1802  $carac_client=pdf_build_address($outputlangs,$this->emetteur,$object->thirdparty,($usecontact?$object->contact:''),$usecontact,'target',$object);
1803 
1804  // Show recipient
1805  $widthrecbox=!empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 92 : 100;
1806  if ($this->page_largeur < 210) $widthrecbox=84; // To work with US executive format
1807  $posy=!empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 40 : 42;
1808  $posy+=$top_shift;
1809  $posx=$this->page_largeur-$this->marge_droite-$widthrecbox;
1810  if (! empty($conf->global->MAIN_INVERT_SENDER_RECIPIENT)) $posx=$this->marge_gauche;
1811 
1812  // Show recipient frame
1813  $pdf->SetTextColor(0,0,0);
1814  $pdf->SetFont('','', $default_font_size - 2);
1815  $pdf->SetXY($posx+2,$posy-5);
1816  $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillTo").":",0,'L');
1817  $pdf->Rect($posx, $posy, $widthrecbox, $hautcadre);
1818 
1819  // Show recipient name
1820  $pdf->SetXY($posx+2,$posy+3);
1821  $pdf->SetFont('','B', $default_font_size);
1822  $pdf->MultiCell($widthrecbox, 2, $carac_client_name, 0, 'L');
1823 
1824  $posy = $pdf->getY();
1825 
1826  // Show recipient information
1827  $pdf->SetFont('','', $default_font_size - 1);
1828  $pdf->SetXY($posx+2,$posy);
1829  $pdf->MultiCell($widthrecbox, 4, $carac_client, 0, 'L');
1830  }
1831 
1832  $pdf->SetTextColor(0,0,0);
1833  return $top_shift;
1834  }
1835 
1845  function _pagefoot(&$pdf,$object,$outputlangs,$hidefreetext=0)
1846  {
1847  global $conf;
1848  $showdetails=$conf->global->MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS;
1849  return pdf_pagefoot($pdf,$outputlangs,'INVOICE_FREE_TEXT',$this->emetteur,$this->marge_basse,$this->marge_gauche,$this->page_hauteur,$object,$showdetails,$hidefreetext);
1850  }
1851 }
pdf_bank(&$pdf, $outputlangs, $curx, $cury, $account, $onlynumber=0, $default_font_size=10)
Show bank informations for PDF generation.
Definition: pdf.lib.php:692
pdf_getInstance($format='', $metric='mm', $pagetype='P')
Return a PDF instance object.
Definition: pdf.lib.php:82
pdfBuildThirdpartyName($thirdparty, Translate $outputlangs, $includealias=0)
Returns the name of the thirdparty.
Definition: pdf.lib.php:319
pdf_pagehead(&$pdf, $outputlangs, $page_height)
Show header of page for PDF generation.
Definition: pdf.lib.php:600
if(! empty($conf->facture->enabled) && $user->rights->facture->lire) if(! empty($conf->fournisseur->enabled) && $user->rights->fournisseur->facture->lire) if(! empty($conf->don->enabled) && $user->rights->societe->lire) if(! empty($conf->tax->enabled) && $user->rights->tax->charges->lire) if(! empty($conf->facture->enabled) &&! empty($conf->commande->enabled) && $user->rights->commande->lire &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) if(! empty($conf->facture->enabled) && $user->rights->facture->lire) if(! empty($conf->fournisseur->enabled) && $user->rights->fournisseur->facture->lire) $resql
Social contributions to pay.
Definition: index.php:1053
Class to manage PDF invoice template Crabe.
_tableau_info(&$pdf, $object, $posy, $outputlangs)
Show miscellaneous information (payment mode, payment term, ...)
pdf_watermark(&$pdf, $outputlangs, $h, $w, $unit, $text)
Add a draft watermark on PDF files.
Definition: pdf.lib.php:643
pdf_build_address($outputlangs, $sourcecompany, $targetcompany='', $targetcontact='', $usecontact=0, $mode='source', $object=null)
Return a string with full address formated for output on documents.
Definition: pdf.lib.php:353
</td >< td class="liste_titre" align="right"></td ></tr >< tr class="liste_titre">< input type="checkbox" onClick="toggle(this)"/> Ref p ref Label p label Duration p duration warehouseinternal SELECT description FROM product_lang WHERE qty< br > qty qty qty StockTooLow img yes disabled img no img no< tr class="oddeven">< td >< input type="checkbox" class="check" name="' . $i . '"' . $disabled . '></td >< td >< input type="checkbox" class="check" name="choose'.$i.'"></td >< td class="nowrap"></td >< td >< input type="hidden" name="desc' . $i . '" value="' . dol_escape_htmltag($objp-> description
Only used if Module[ID]Desc translation string is not found.
Definition: replenish.php:573
pdf_getFormat(Translate $outputlangs=null)
Return array with format properties of default PDF format.
Definition: pdf.lib.php:42
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
get_exdir($num, $level, $alpha, $withoutslash, $object, $modulepart)
Return a path to have a the directory according to object where files are stored. ...
pdf_getPDFFontSize($outputlangs)
Return font size to use for PDF generation.
Definition: pdf.lib.php:224
Class to manage products or services.
Class to manage Dolibarr users.
Definition: user.class.php:41
_tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs)
Show total to pay.
pdf_getPDFFont($outputlangs)
Return font name to use for PDF generation.
Definition: pdf.lib.php:201
dol_concatdesc($text1, $text2, $forxml=false)
Concat 2 descriptions with a new line between them (second operand after first one with appropriate n...
_pagefoot(&$pdf, $object, $outputlangs, $hidefreetext=0)
Show footer of page.
pdf_getlineunit($object, $i, $outputlangs, $hidedetails=0, $hookmanager=false)
Return line unit.
Definition: pdf.lib.php:1798
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition: repair.php:103
Class to manage bank accounts.
pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line total excluding tax.
Definition: pdf.lib.php:1925
Class to manage hooks.
pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails=0)
Return line vat rate.
Definition: pdf.lib.php:1526
type
Definition: viewcat.php:284
_pagehead(&$pdf, $object, $showaddress, $outputlangs)
Show top header of page.
pdf_getlineqty($object, $i, $outputlangs, $hidedetails=0)
Return line quantity.
Definition: pdf.lib.php:1661
pdf_pagefoot(&$pdf, $outputlangs, $paramfreetext, $fromcompany, $marge_basse, $marge_gauche, $page_hauteur, $object, $showdetails=0, $hidefreetext=0)
Show footer of page for PDF generation.
Definition: pdf.lib.php:872
pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line unit price excluding tax.
Definition: pdf.lib.php:1585
Parent class of invoice document generators.
_tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop=0, $hidebottom=0, $currency='')
Show table for lines.
const STATUS_DRAFT
Draft status.
pdf_getSizeForImage($realpath)
Return dimensions to use for images onto PDF checking that width and height are not higher than maxim...
Definition: pdf.lib.php:2170
if(GETPOST('cancel', 'alpha')) if(! GETPOST( 'confirmmassaction', 'alpha') &&$massaction !='presend' &&$massaction !='confirm_presend')
Draft customers invoices.
Definition: list.php:156
pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails=0)
Return line remise percent.
Definition: pdf.lib.php:1840
printRect($pdf, $x, $y, $l, $h, $hidetop=0, $hidebottom=0)
Rect pdf.
pdf_getlineprogress($object, $i, $outputlangs, $hidedetails=0, $hookmanager=null)
Return line percent.
Definition: pdf.lib.php:1877
pdf_getHeightForLogo($logo, $url=false)
Return height to use for Logo onto PDF.
Definition: pdf.lib.php:245
vatrate($rate, $addpercent=false, $info_bits=0, $usestarfornpr=0)
Return a string with VAT rate label formated for view output Used into pdf and HTML pages...
write_file($object, $outputlangs, $srctemplatepath='', $hidedetails=0, $hidedesc=0, $hideref=0)
Function to build pdf onto disk.
pdf_writeLinkedObjects(&$pdf, $object, $outputlangs, $posx, $posy, $w, $h, $align, $default_font_size)
Show linked objects for PDF generation.
Definition: pdf.lib.php:1119
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages...
dol_print_date($time, $format='', $tzoutput='tzserver', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
pdf_getSubstitutionArray($outputlangs, $exclude=null, $object=null, $onlykey=0)
Return array of possible substitutions for PDF content (without external module substitutions).
Definition: pdf.lib.php:623
_tableau_versements(&$pdf, $object, $posy, $outputlangs)
Show payments table.
pdf_writelinedesc(&$pdf, $object, $i, $outputlangs, $w, $h, $posx, $posy, $hideref=0, $hidedesc=0, $issupplierline=0)
Output line description into PDF.
Definition: pdf.lib.php:1158
dol_mkdir($dir, $dataroot='', $newmask=null)
Creation of a directory (this can create recursive subdir)
dol_htmlentitiesbr($stringtoencode, $nl2brmode=0, $pagecodefrom='UTF-8', $removelasteolbr=1)
This function is called to encode a string into a HTML string but differs from htmlentities because a...
make_substitutions($text, $substitutionarray, $outputlangs=null)
Make substitution into a text string, replacing keys with vals from $substitutionarray (oldval=>newva...
Class to manage invoices.
getLocalTaxesFromRate($vatrate, $local, $buyer, $seller, $firstparamisid=0)
Get type and rate of localtaxes for a particular vat rate/country of a thirdparty.
__construct($db)
Constructor.
price2num($amount, $rounding='', $alreadysqlnb=0)
Function that return a number with universal decimal format (decimal separator is &#39;...
complete_substitutions_array(&$substitutionarray, $outputlangs, $object=null, $parameters=null, $callfunc="completesubstitutionarray")
Complete the $substitutionarray with more entries coming from external module that had set the "subst...
$version
Dolibarr version of the loaded document string.