1<?php 2/* Copyright (C) 2004-2014 Laurent Destailleur <eldy@users.sourceforge.net> 3 * Copyright (C) 2005-2011 Regis Houssin <regis.houssin@inodbox.com> 4 * Copyright (C) 2007 Franky Van Liedekerke <franky.van.liedekerke@telenet.be> 5 * Copyright (C) 2010-2014 Juanjo Menent <jmenent@2byte.es> 6 * Copyright (C) 2015 Marcos García <marcosgdf@gmail.com> 7 * Copyright (C) 2017 Ferran Marcet <fmarcet@2byte.es> 8 * Copyright (C) 2018 Frédéric France <frederic.france@netlogic.fr> 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 3 of the License, or 13 * (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program. If not, see <https://www.gnu.org/licenses/>. 22 * or see https://www.gnu.org/ 23 */ 24 25/** 26 * \file htdocs/core/modules/supplier_order/doc/pdf_muscadet.modules.php 27 * \ingroup fournisseur 28 * \brief File of class to generate suppliers orders from muscadet model 29 */ 30 31require_once DOL_DOCUMENT_ROOT.'/core/modules/supplier_order/modules_commandefournisseur.php'; 32require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php'; 33require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; 34require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; 35require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; 36require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php'; 37 38 39/** 40 * Class to generate the supplier orders with the muscadet model 41 */ 42class pdf_muscadet extends ModelePDFSuppliersOrders 43{ 44 /** 45 * @var DoliDb Database handler 46 */ 47 public $db; 48 49 /** 50 * @var string model name 51 */ 52 public $name; 53 54 /** 55 * @var string model description (short text) 56 */ 57 public $description; 58 59 /** 60 * @var int Save the name of generated file as the main doc when generating a doc with this template 61 */ 62 public $update_main_doc_field; 63 64 /** 65 * @var string document type 66 */ 67 public $type; 68 69 /** 70 * @var array Minimum version of PHP required by module. 71 * e.g.: PHP ≥ 5.6 = array(5, 6) 72 */ 73 public $phpmin = array(5, 6); 74 75 /** 76 * Dolibarr version of the loaded document 77 * @var string 78 */ 79 public $version = 'dolibarr'; 80 81 /** 82 * @var int page_largeur 83 */ 84 public $page_largeur; 85 86 /** 87 * @var int page_hauteur 88 */ 89 public $page_hauteur; 90 91 /** 92 * @var array format 93 */ 94 public $format; 95 96 /** 97 * @var int marge_gauche 98 */ 99 public $marge_gauche; 100 101 /** 102 * @var int marge_droite 103 */ 104 public $marge_droite; 105 106 /** 107 * @var int marge_haute 108 */ 109 public $marge_haute; 110 111 /** 112 * @var int marge_basse 113 */ 114 public $marge_basse; 115 116 /** 117 * Issuer 118 * @var Societe object that emits 119 */ 120 public $emetteur; 121 122 123 /** 124 * Constructor 125 * 126 * @param DoliDB $db Database handler 127 */ 128 public function __construct($db) 129 { 130 global $conf, $langs, $mysoc; 131 132 // Load translation files required by the page 133 $langs->loadLangs(array("main", "bills")); 134 135 $this->db = $db; 136 $this->name = "muscadet"; 137 $this->description = $langs->trans('SuppliersCommandModelMuscadet'); 138 $this->update_main_doc_field = 1; // Save the name of generated file as the main doc when generating a doc with this template 139 140 // Page size for A4 format 141 $this->type = 'pdf'; 142 $formatarray = pdf_getFormat(); 143 $this->page_largeur = $formatarray['width']; 144 $this->page_hauteur = $formatarray['height']; 145 $this->format = array($this->page_largeur, $this->page_hauteur); 146 $this->marge_gauche = isset($conf->global->MAIN_PDF_MARGIN_LEFT) ? $conf->global->MAIN_PDF_MARGIN_LEFT : 10; 147 $this->marge_droite = isset($conf->global->MAIN_PDF_MARGIN_RIGHT) ? $conf->global->MAIN_PDF_MARGIN_RIGHT : 10; 148 $this->marge_haute = isset($conf->global->MAIN_PDF_MARGIN_TOP) ? $conf->global->MAIN_PDF_MARGIN_TOP : 10; 149 $this->marge_basse = isset($conf->global->MAIN_PDF_MARGIN_BOTTOM) ? $conf->global->MAIN_PDF_MARGIN_BOTTOM : 10; 150 151 $this->option_logo = 1; // Display logo 152 $this->option_tva = 1; // Manage the vat option FACTURE_TVAOPTION 153 $this->option_modereg = 1; // Display payment mode 154 $this->option_condreg = 1; // Display payment terms 155 $this->option_codeproduitservice = 1; // Display product-service code 156 $this->option_multilang = 1; // Available in several languages 157 $this->option_escompte = 0; // Displays if there has been a discount 158 $this->option_credit_note = 0; // Support credit notes 159 $this->option_freetext = 1; // Support add of a personalised text 160 $this->option_draft_watermark = 1; // Support add of a watermark on drafts 161 162 // Get source company 163 $this->emetteur = $mysoc; 164 if (empty($this->emetteur->country_code)) { 165 $this->emetteur->country_code = substr($langs->defaultlang, -2); // By default, if was not defined 166 } 167 168 // Define position of columns 169 $this->posxdesc = $this->marge_gauche + 1; 170 $this->posxdiscount = 162; 171 $this->postotalht = 174; 172 173 if (!empty($conf->global->PRODUCT_USE_UNITS)) { 174 $this->posxtva = 95; 175 $this->posxup = 114; 176 $this->posxqty = 132; 177 $this->posxunit = 147; 178 } else { 179 $this->posxtva = 110; 180 $this->posxup = 126; 181 $this->posxqty = 145; 182 $this->posxunit = 162; 183 } 184 185 if (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT)) { 186 $this->posxup = $this->posxtva; // posxtva is picture position reference 187 } 188 $this->posxpicture = $this->posxtva - (empty($conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH) ? 20 : $conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH); // width of images 189 if ($this->page_largeur < 210) { // To work with US executive format 190 $this->posxpicture -= 20; 191 $this->posxtva -= 20; 192 $this->posxup -= 20; 193 $this->posxqty -= 20; 194 $this->posxunit -= 20; 195 $this->posxdiscount -= 20; 196 $this->postotalht -= 20; 197 } 198 199 $this->tva = array(); 200 $this->localtax1 = array(); 201 $this->localtax2 = array(); 202 $this->atleastoneratenotnull = 0; 203 $this->atleastonediscount = 0; 204 } 205 206 207 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps 208 /** 209 * Function to build pdf onto disk 210 * 211 * @param CommandeFournisseur $object Id of object to generate 212 * @param Translate $outputlangs Lang output object 213 * @param string $srctemplatepath Full path of source filename for generator using a template file 214 * @param int $hidedetails Do not show line details 215 * @param int $hidedesc Do not show desc 216 * @param int $hideref Do not show ref 217 * @return int 1=OK, 0=KO 218 */ 219 public function write_file($object, $outputlangs = '', $srctemplatepath = '', $hidedetails = 0, $hidedesc = 0, $hideref = 0) 220 { 221 // phpcs:enable 222 global $user, $langs, $conf, $hookmanager, $mysoc, $nblines; 223 224 if (!is_object($outputlangs)) { 225 $outputlangs = $langs; 226 } 227 // For backward compatibility with FPDF, force output charset to ISO, because FPDF expect text to be encoded in ISO 228 if (!empty($conf->global->MAIN_USE_FPDF)) { 229 $outputlangs->charset_output = 'ISO-8859-1'; 230 } 231 232 // Load translation files required by the page 233 $outputlangs->loadLangs(array("main", "orders", "companies", "bills", "dict", "products")); 234 235 $nblines = count($object->lines); 236 237 // Loop on each lines to detect if there is at least one image to show 238 $realpatharray = array(); 239 if (!empty($conf->global->MAIN_GENERATE_SUPPLIER_ORDER_WITH_PICTURE)) { 240 for ($i = 0; $i < $nblines; $i++) { 241 if (empty($object->lines[$i]->fk_product)) { 242 continue; 243 } 244 245 $objphoto = new Product($this->db); 246 $objphoto->fetch($object->lines[$i]->fk_product); 247 248 if (!empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO)) { 249 $pdir = get_exdir($objphoto->id, 2, 0, 0, $objphoto, 'product').$object->lines[$i]->fk_product."/photos/"; 250 $dir = $conf->product->dir_output.'/'.$pdir; 251 } else { 252 $pdir = get_exdir($objphoto->id, 0, 0, 0, $objphoto, 'product'); 253 $dir = $conf->product->dir_output.'/'.$pdir; 254 } 255 $realpath = ''; 256 foreach ($objphoto->liste_photos($dir, 1) as $key => $obj) { 257 if (empty($conf->global->CAT_HIGH_QUALITY_IMAGES)) { // If CAT_HIGH_QUALITY_IMAGES not defined, we use thumb if defined and then original photo 258 if ($obj['photo_vignette']) { 259 $filename = $obj['photo_vignette']; 260 } else { 261 $filename = $obj['photo']; 262 } 263 } else { 264 $filename = $obj['photo']; 265 } 266 $realpath = $dir.$filename; 267 break; 268 } 269 270 if ($realpath) { 271 $realpatharray[$i] = $realpath; 272 } 273 } 274 } 275 if (count($realpatharray) == 0) { 276 $this->posxpicture = $this->posxtva; 277 } 278 279 if ($conf->fournisseur->commande->dir_output) { 280 $object->fetch_thirdparty(); 281 282 $deja_regle = 0; 283 $amount_credit_notes_included = 0; 284 $amount_deposits_included = 0; 285 //$amount_credit_notes_included = $object->getSumCreditNotesUsed(); 286 //$amount_deposits_included = $object->getSumDepositsUsed(); 287 288 // Definition of $dir and $file 289 if ($object->specimen) { 290 $dir = $conf->fournisseur->commande->dir_output; 291 $file = $dir."/SPECIMEN.pdf"; 292 } else { 293 $objectref = dol_sanitizeFileName($object->ref); 294 $objectrefsupplier = dol_sanitizeFileName($object->ref_supplier); 295 $dir = $conf->fournisseur->commande->dir_output.'/'.$objectref; 296 $file = $dir."/".$objectref.".pdf"; 297 if (!empty($conf->global->SUPPLIER_REF_IN_NAME)) { 298 $file = $dir."/".$objectref.($objectrefsupplier ? "_".$objectrefsupplier : "").".pdf"; 299 } 300 } 301 302 if (!file_exists($dir)) { 303 if (dol_mkdir($dir) < 0) { 304 $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir); 305 return 0; 306 } 307 } 308 309 if (file_exists($dir)) { 310 // Add pdfgeneration hook 311 if (!is_object($hookmanager)) { 312 include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php'; 313 $hookmanager = new HookManager($this->db); 314 } 315 $hookmanager->initHooks(array('pdfgeneration')); 316 $parameters = array('file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs); 317 global $action; 318 $reshook = $hookmanager->executeHooks('beforePDFCreation', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks 319 320 $nblines = count($object->lines); 321 322 $pdf = pdf_getInstance($this->format); 323 $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance 324 $heightforinfotot = 50; // Height reserved to output the info and total part 325 $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 326 $heightforfooter = $this->marge_basse + 8; // Height reserved to output the footer (value include bottom margin) 327 if (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS)) { 328 $heightforfooter += 6; 329 } 330 $pdf->SetAutoPageBreak(1, 0); 331 332 if (class_exists('TCPDF')) { 333 $pdf->setPrintHeader(false); 334 $pdf->setPrintFooter(false); 335 } 336 $pdf->SetFont(pdf_getPDFFont($outputlangs)); 337 // Set path to the background PDF File 338 if (!empty($conf->global->MAIN_ADD_PDF_BACKGROUND)) { 339 $pagecount = $pdf->setSourceFile($conf->mycompany->dir_output.'/'.$conf->global->MAIN_ADD_PDF_BACKGROUND); 340 $tplidx = $pdf->importPage(1); 341 } 342 343 $pdf->Open(); 344 $pagenb = 0; 345 $pdf->SetDrawColor(128, 128, 128); 346 347 $pdf->SetTitle($outputlangs->convToOutputCharset($object->ref)); 348 $pdf->SetSubject($outputlangs->transnoentities("PurchaseOrder")); 349 $pdf->SetCreator("Dolibarr ".DOL_VERSION); 350 $pdf->SetAuthor($outputlangs->convToOutputCharset($user->getFullName($outputlangs))); 351 352 $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("PurchaseOrder")." ".$outputlangs->convToOutputCharset($object->thirdparty->name)); 353 if (!empty($conf->global->MAIN_DISABLE_PDF_COMPRESSION)) { 354 $pdf->SetCompression(false); 355 } 356 357 $pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite); // Left, Top, Right 358 359 // Positionne $this->atleastonediscount si on a au moins une remise 360 for ($i = 0; $i < $nblines; $i++) { 361 if ($object->lines[$i]->remise_percent) { 362 $this->atleastonediscount++; 363 } 364 } 365 if (empty($this->atleastonediscount)) { 366 $delta = ($this->postotalht - $this->posxdiscount); 367 $this->posxpicture += $delta; 368 $this->posxtva += $delta; 369 $this->posxup += $delta; 370 $this->posxqty += $delta; 371 $this->posxunit += $delta; 372 $this->posxdiscount += $delta; 373 // post of fields after are not modified, stay at same position 374 } 375 376 // New page 377 $pdf->AddPage(); 378 if (!empty($tplidx)) { 379 $pdf->useTemplate($tplidx); 380 } 381 $pagenb++; 382 $top_shift = $this->_pagehead($pdf, $object, 1, $outputlangs); 383 $pdf->SetFont('', '', $default_font_size - 1); 384 $pdf->MultiCell(0, 3, ''); // Set interline to 3 385 $pdf->SetTextColor(0, 0, 0); 386 387 $tab_top = 90 + $top_shift; 388 $tab_top_newpage = (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD) ? 42 + $top_shift : 10); 389 390 // Incoterm 391 if (!empty($conf->incoterm->enabled)) { 392 $desc_incoterms = $object->getIncotermsForPDF(); 393 if ($desc_incoterms) { 394 $tab_top -= 2; 395 396 $pdf->SetFont('', '', $default_font_size - 1); 397 $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top - 1, dol_htmlentitiesbr($desc_incoterms), 0, 1); 398 $nexY = $pdf->GetY(); 399 $height_incoterms = $nexY - $tab_top; 400 401 // Rect takes a length in 3rd parameter 402 $pdf->SetDrawColor(192, 192, 192); 403 $pdf->Rect($this->marge_gauche, $tab_top - 1, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $height_incoterms + 1); 404 405 $tab_top = $nexY + 6; 406 } 407 } 408 409 // Affiche notes 410 if (!empty($object->note_public)) { 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($object->note_public), 0, 1); 415 $nexY = $pdf->GetY(); 416 $height_note = $nexY - $tab_top; 417 418 // Rect takes a length in 3rd parameter 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_note + 1); 421 422 $tab_top = $nexY + 6; 423 } 424 425 $iniY = $tab_top + 7; 426 $curY = $tab_top + 7; 427 $nexY = $tab_top + 7; 428 429 // Loop on each lines 430 for ($i = 0; $i < $nblines; $i++) { 431 $curY = $nexY; 432 $pdf->SetFont('', '', $default_font_size - 1); // Into loop to work with multipage 433 $pdf->SetTextColor(0, 0, 0); 434 435 // Define size of image if we need it 436 $imglinesize = array(); 437 if (!empty($realpatharray[$i])) { 438 $imglinesize = pdf_getSizeForImage($realpatharray[$i]); 439 } 440 441 $pdf->setTopMargin($tab_top_newpage); 442 $pdf->setPageOrientation('', 1, $heightforfooter + $heightforfreetext + $heightforinfotot); // The only function to edit the bottom margin of current page to set it. 443 $pageposbefore = $pdf->getPage(); 444 445 $showpricebeforepagebreak = 1; 446 $posYAfterImage = 0; 447 $posYAfterDescription = 0; 448 449 // We start with Photo of product line 450 if (!empty($imglinesize['width']) && !empty($imglinesize['height']) && ($curY + $imglinesize['height']) > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforinfotot))) { // If photo too high, we moved completely on new page 451 $pdf->AddPage('', '', true); 452 if (!empty($tplidx)) { 453 $pdf->useTemplate($tplidx); 454 } 455 if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) { 456 $this->_pagehead($pdf, $object, 0, $outputlangs); 457 } 458 $pdf->setPage($pageposbefore + 1); 459 460 $curY = $tab_top_newpage; 461 462 // Allows data in the first page if description is long enough to break in multiples pages 463 if (!empty($conf->global->MAIN_PDF_DATA_ON_FIRST_PAGE)) { 464 $showpricebeforepagebreak = 1; 465 } else { 466 $showpricebeforepagebreak = 0; 467 } 468 } 469 470 if (!empty($imglinesize['width']) && !empty($imglinesize['height'])) { 471 $curX = $this->posxpicture - 1; 472 $pdf->Image($realpatharray[$i], $curX + (($this->posxtva - $this->posxpicture - $imglinesize['width']) / 2), $curY, $imglinesize['width'], $imglinesize['height'], '', '', '', 2, 300); // Use 300 dpi 473 // $pdf->Image does not increase value return by getY, so we save it manually 474 $posYAfterImage = $curY + $imglinesize['height']; 475 } 476 // Description of product line 477 $curX = $this->posxdesc - 1; 478 $showpricebeforepagebreak = 1; 479 480 $pdf->startTransaction(); 481 if ($posYAfterImage > 0) { 482 $descWidth = $this->posxpicture - $curX; 483 } else { 484 $descWidth = $this->posxtva - $curX; 485 } 486 pdf_writelinedesc($pdf, $object, $i, $outputlangs, $descWidth, 3, $curX, $curY, $hideref, $hidedesc, 1); 487 488 $pageposafter = $pdf->getPage(); 489 if ($pageposafter > $pageposbefore) { // There is a pagebreak 490 $pdf->rollbackTransaction(true); 491 $pageposafter = $pageposbefore; 492 //print $pageposafter.'-'.$pageposbefore;exit; 493 $pdf->setPageOrientation('', 1, $heightforfooter); // The only function to edit the bottom margin of current page to set it. 494 pdf_writelinedesc($pdf, $object, $i, $outputlangs, $descWidth, 3, $curX, $curY, $hideref, $hidedesc, 1); 495 $posyafter = $pdf->GetY(); 496 if ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforinfotot))) { // There is no space left for total+free text 497 if ($i == ($nblines - 1)) { // No more lines, and no space left to show total, so we create a new page 498 $pdf->AddPage('', '', true); 499 if (!empty($tplidx)) { 500 $pdf->useTemplate($tplidx); 501 } 502 if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) { 503 $this->_pagehead($pdf, $object, 0, $outputlangs); 504 } 505 $pdf->setPage($pageposafter + 1); 506 } 507 } else { 508 // We found a page break 509 // Allows data in the first page if description is long enough to break in multiples pages 510 if (!empty($conf->global->MAIN_PDF_DATA_ON_FIRST_PAGE)) { 511 $showpricebeforepagebreak = 1; 512 } else { 513 $showpricebeforepagebreak = 0; 514 } 515 } 516 } else // No pagebreak 517 { 518 $pdf->commitTransaction(); 519 } 520 521 $nexY = $pdf->GetY(); 522 $pageposafter = $pdf->getPage(); 523 $pdf->setPage($pageposbefore); 524 $pdf->setTopMargin($this->marge_haute); 525 $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it. 526 527 // We suppose that a too long description is moved completely on next page 528 if ($pageposafter > $pageposbefore && empty($showpricebeforepagebreak)) { 529 $pdf->setPage($pageposafter); 530 $curY = $tab_top_newpage; 531 } 532 533 $pdf->SetFont('', '', $default_font_size - 1); // On repositionne la police par defaut 534 535 // VAT Rate 536 if (empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT) && empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_COLUMN)) { 537 $vat_rate = pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails); 538 $pdf->SetXY($this->posxtva, $curY); 539 $pdf->MultiCell($this->posxup - $this->posxtva - 1, 3, $vat_rate, 0, 'R'); 540 } 541 542 // Unit price before discount 543 if (empty($conf->global->MAIN_GENERATE_DOCUMENTS_PURCHASE_ORDER_WITHOUT_UNIT_PRICE)) { 544 $up_excl_tax = pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails); 545 $pdf->SetXY($this->posxup, $curY); 546 $pdf->MultiCell($this->posxqty - $this->posxup - 0.8, 3, $up_excl_tax, 0, 'R', 0); 547 } 548 549 // Quantity 550 $qty = pdf_getlineqty($object, $i, $outputlangs, $hidedetails); 551 $pdf->SetXY($this->posxqty, $curY); 552 $pdf->MultiCell($this->posxunit - $this->posxqty - 0.8, 4, $qty, 0, 'R'); // Enough for 6 chars 553 554 // Unit 555 if (!empty($conf->global->PRODUCT_USE_UNITS)) { 556 $unit = pdf_getlineunit($object, $i, $outputlangs, $hidedetails, $hookmanager); 557 $pdf->SetXY($this->posxunit, $curY); 558 $pdf->MultiCell($this->posxdiscount - $this->posxunit - 0.8, 4, $unit, 0, 'L'); 559 } 560 561 // Discount on line 562 $pdf->SetXY($this->posxdiscount, $curY); 563 if ($object->lines[$i]->remise_percent) { 564 $remise_percent = pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails); 565 $pdf->MultiCell($this->postotalht - $this->posxdiscount - 1, 3, $remise_percent, 0, 'R'); 566 } 567 568 // Total HT line 569 if (empty($conf->global->MAIN_GENERATE_DOCUMENTS_PURCHASE_ORDER_WITHOUT_TOTAL_COLUMN)) { 570 $total_excl_tax = pdf_getlinetotalexcltax($object, $i, $outputlangs); 571 $pdf->SetXY($this->postotalht, $curY); 572 $pdf->MultiCell($this->page_largeur - $this->marge_droite - $this->postotalht, 3, $total_excl_tax, 0, 'R', 0); 573 } 574 575 // Collecte des totaux par valeur de tva dans $this->tva["taux"]=total_tva 576 if (!empty($conf->multicurrency->enabled) && $object->multicurrency_tx != 1) { 577 $tvaligne = $object->lines[$i]->multicurrency_total_tva; 578 } else { 579 $tvaligne = $object->lines[$i]->total_tva; 580 } 581 582 $localtax1ligne = $object->lines[$i]->total_localtax1; 583 $localtax2ligne = $object->lines[$i]->total_localtax2; 584 $localtax1_rate = $object->lines[$i]->localtax1_tx; 585 $localtax2_rate = $object->lines[$i]->localtax2_tx; 586 $localtax1_type = $object->lines[$i]->localtax1_type; 587 $localtax2_type = $object->lines[$i]->localtax2_type; 588 589 if (!empty($object->remise_percent)) { 590 $tvaligne -= ($tvaligne * $object->remise_percent) / 100; 591 } 592 if (!empty($object->remise_percent)) { 593 $localtax1ligne -= ($localtax1ligne * $object->remise_percent) / 100; 594 } 595 if (!empty($object->remise_percent)) { 596 $localtax2ligne -= ($localtax2ligne * $object->remise_percent) / 100; 597 } 598 599 $vatrate = (string) $object->lines[$i]->tva_tx; 600 601 // Retrieve type from database for backward compatibility with old records 602 if ((!isset($localtax1_type) || $localtax1_type == '' || !isset($localtax2_type) || $localtax2_type == '') // if tax type not defined 603 && (!empty($localtax1_rate) || !empty($localtax2_rate))) { // and there is local tax 604 $localtaxtmp_array = getLocalTaxesFromRate($vatrate, 0, $mysoc, $object->thirdparty); 605 $localtax1_type = isset($localtaxtmp_array[0]) ? $localtaxtmp_array[0] : ''; 606 $localtax2_type = isset($localtaxtmp_array[2]) ? $localtaxtmp_array[2] : ''; 607 } 608 609 // retrieve global local tax 610 if ($localtax1_type && $localtax1ligne != 0) { 611 $this->localtax1[$localtax1_type][$localtax1_rate] += $localtax1ligne; 612 } 613 if ($localtax2_type && $localtax2ligne != 0) { 614 $this->localtax2[$localtax2_type][$localtax2_rate] += $localtax2ligne; 615 } 616 617 if (($object->lines[$i]->info_bits & 0x01) == 0x01) { 618 $vatrate .= '*'; 619 } 620 if (!isset($this->tva[$vatrate])) { 621 $this->tva[$vatrate] = 0; 622 } 623 $this->tva[$vatrate] += $tvaligne; 624 625 if ($posYAfterImage > $posYAfterDescription) { 626 $nexY = $posYAfterImage; 627 } 628 629 // Add line 630 if (!empty($conf->global->MAIN_PDF_DASH_BETWEEN_LINES) && $i < ($nblines - 1)) { 631 $pdf->setPage($pageposafter); 632 $pdf->SetLineStyle(array('dash'=>'1,1', 'color'=>array(80, 80, 80))); 633 //$pdf->SetDrawColor(190,190,200); 634 $pdf->line($this->marge_gauche, $nexY + 1, $this->page_largeur - $this->marge_droite, $nexY + 1); 635 $pdf->SetLineStyle(array('dash'=>0)); 636 } 637 638 $nexY += 2; // Add space between lines 639 640 // Detect if some page were added automatically and output _tableau for past pages 641 while ($pagenb < $pageposafter) { 642 $pdf->setPage($pagenb); 643 if ($pagenb == 1) { 644 $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1, $object->multicurrency_code); 645 } else { 646 $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code); 647 } 648 $this->_pagefoot($pdf, $object, $outputlangs, 1); 649 $pagenb++; 650 $pdf->setPage($pagenb); 651 $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it. 652 if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) { 653 $this->_pagehead($pdf, $object, 0, $outputlangs); 654 } 655 } 656 if (isset($object->lines[$i + 1]->pagebreak) && $object->lines[$i + 1]->pagebreak) { 657 if ($pagenb == 1) { 658 $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1, $object->multicurrency_code); 659 } else { 660 $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code); 661 } 662 $this->_pagefoot($pdf, $object, $outputlangs, 1); 663 // New page 664 $pdf->AddPage(); 665 if (!empty($tplidx)) { 666 $pdf->useTemplate($tplidx); 667 } 668 $pagenb++; 669 if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) { 670 $this->_pagehead($pdf, $object, 0, $outputlangs); 671 } 672 } 673 } 674 675 // Show square 676 if ($pagenb == 1) { 677 $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 0, 0, $object->multicurrency_code); 678 $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1; 679 } else { 680 $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 1, 0, $object->multicurrency_code); 681 $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1; 682 } 683 684 // Affiche zone infos 685 $posy = $this->_tableau_info($pdf, $object, $bottomlasttab, $outputlangs); 686 687 // Affiche zone totaux 688 $posy = $this->_tableau_tot($pdf, $object, $deja_regle, $bottomlasttab, $outputlangs); 689 690 // Affiche zone versements 691 if ($deja_regle || $amount_credit_notes_included || $amount_deposits_included) { 692 $posy = $this->_tableau_versements($pdf, $object, $posy, $outputlangs); 693 } 694 695 // Pied de page 696 $this->_pagefoot($pdf, $object, $outputlangs); 697 if (method_exists($pdf, 'AliasNbPages')) { 698 $pdf->AliasNbPages(); 699 } 700 701 $pdf->Close(); 702 703 $pdf->Output($file, 'F'); 704 705 // Add pdfgeneration hook 706 $hookmanager->initHooks(array('pdfgeneration')); 707 $parameters = array('file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs); 708 global $action; 709 $reshook = $hookmanager->executeHooks('afterPDFCreation', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks 710 if ($reshook < 0) { 711 $this->error = $hookmanager->error; 712 $this->errors = $hookmanager->errors; 713 } 714 715 if (!empty($conf->global->MAIN_UMASK)) { 716 @chmod($file, octdec($conf->global->MAIN_UMASK)); 717 } 718 719 $this->result = array('fullpath'=>$file); 720 721 return 1; // No error 722 } else { 723 $this->error = $langs->trans("ErrorCanNotCreateDir", $dir); 724 return 0; 725 } 726 } else { 727 $this->error = $langs->trans("ErrorConstantNotDefined", "SUPPLIER_OUTPUTDIR"); 728 return 0; 729 } 730 } 731 732 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore 733 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps 734 /** 735 * Show payments table 736 * 737 * @param TCPDF $pdf Object PDF 738 * @param CommandeFournisseur $object Object order 739 * @param int $posy Position y in PDF 740 * @param Translate $outputlangs Object langs for output 741 * @return int <0 if KO, >0 if OK 742 */ 743 protected function _tableau_versements(&$pdf, $object, $posy, $outputlangs) 744 { 745 // phpcs:enable 746 } 747 748 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore 749 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps 750 /** 751 * Show miscellaneous information (payment mode, payment term, ...) 752 * 753 * @param TCPDF $pdf Object PDF 754 * @param CommandeFournisseur $object Object to show 755 * @param int $posy Y 756 * @param Translate $outputlangs Langs object 757 * @return integer 758 */ 759 protected function _tableau_info(&$pdf, $object, $posy, $outputlangs) 760 { 761 // phpcs:enable 762 global $conf, $mysoc; 763 $default_font_size = pdf_getPDFFontSize($outputlangs); 764 765 // If France, show VAT mention if not applicable 766 if ($this->emetteur->country_code == 'FR' && empty($mysoc->tva_assuj)) { 767 $pdf->SetFont('', 'B', $default_font_size - 2); 768 $pdf->SetXY($this->marge_gauche, $posy); 769 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("VATIsNotUsedForInvoice"), 0, 'L', 0); 770 771 $posy = $pdf->GetY() + 4; 772 } 773 774 $posxval = 52; 775 776 // Show payments conditions 777 if (!empty($object->cond_reglement_code) || $object->cond_reglement_id) { 778 $pdf->SetFont('', 'B', $default_font_size - 2); 779 $pdf->SetXY($this->marge_gauche, $posy); 780 $titre = $outputlangs->transnoentities("PaymentConditions").':'; 781 $pdf->MultiCell(80, 4, $titre, 0, 'L'); 782 783 $pdf->SetFont('', '', $default_font_size - 2); 784 $pdf->SetXY($posxval, $posy); 785 $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 ? $object->cond_reglement_doc : $object->cond_reglement_label); 786 $lib_condition_paiement = str_replace('\n', "\n", $lib_condition_paiement); 787 $pdf->MultiCell(80, 4, $lib_condition_paiement, 0, 'L'); 788 789 $posy = $pdf->GetY() + 3; 790 } 791 792 // Show payment mode 793 if (!empty($object->mode_reglement_code)) { 794 $pdf->SetFont('', 'B', $default_font_size - 2); 795 $pdf->SetXY($this->marge_gauche, $posy); 796 $titre = $outputlangs->transnoentities("PaymentMode").':'; 797 $pdf->MultiCell(80, 5, $titre, 0, 'L'); 798 799 $pdf->SetFont('', '', $default_font_size - 2); 800 $pdf->SetXY($posxval, $posy); 801 $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); 802 $pdf->MultiCell(80, 5, $lib_mode_reg, 0, 'L'); 803 804 $posy = $pdf->GetY() + 2; 805 } 806 807 return $posy; 808 } 809 810 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore 811 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps 812 /** 813 * Show total to pay 814 * 815 * @param TCPDF $pdf Object PDF 816 * @param Facture $object Object invoice 817 * @param int $deja_regle Montant deja regle 818 * @param int $posy Position depart 819 * @param Translate $outputlangs Objet langs 820 * @return int Position pour suite 821 */ 822 protected function _tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs) 823 { 824 // phpcs:enable 825 global $conf, $mysoc; 826 827 $default_font_size = pdf_getPDFFontSize($outputlangs); 828 829 $tab2_top = $posy; 830 $tab2_hl = 4; 831 $pdf->SetFont('', '', $default_font_size - 1); 832 833 // Tableau total 834 $col1x = 120; 835 $col2x = 170; 836 if ($this->page_largeur < 210) { // To work with US executive format 837 $col2x -= 20; 838 } 839 $largcol2 = ($this->page_largeur - $this->marge_droite - $col2x); 840 841 $useborder = 0; 842 $index = 0; 843 844 // Total HT 845 $pdf->SetFillColor(255, 255, 255); 846 $pdf->SetXY($col1x, $tab2_top + 0); 847 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalHT"), 0, 'L', 1); 848 849 $total_ht = ((!empty($conf->multicurrency->enabled) && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? $object->multicurrency_total_ht : $object->total_ht); 850 $pdf->SetXY($col2x, $tab2_top + 0); 851 $pdf->MultiCell($largcol2, $tab2_hl, price($total_ht + (!empty($object->remise) ? $object->remise : 0)), 0, 'R', 1); 852 853 // Show VAT by rates and total 854 $pdf->SetFillColor(248, 248, 248); 855 856 $this->atleastoneratenotnull = 0; 857 foreach ($this->tva as $tvakey => $tvaval) { 858 if ($tvakey > 0) { // On affiche pas taux 0 859 $this->atleastoneratenotnull++; 860 861 $index++; 862 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); 863 864 $tvacompl = ''; 865 866 if (preg_match('/\*/', $tvakey)) { 867 $tvakey = str_replace('*', '', $tvakey); 868 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")"; 869 } 870 871 $totalvat = $outputlangs->transcountrynoentities("TotalVAT", $mysoc->country_code).' '; 872 $totalvat .= vatrate($tvakey, 1).$tvacompl; 873 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); 874 875 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); 876 $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval), 0, 'R', 1); 877 } 878 } 879 if (!$this->atleastoneratenotnull) { // If no vat at all 880 $index++; 881 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); 882 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transcountrynoentities("TotalVAT", $mysoc->country_code), 0, 'L', 1); 883 884 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); 885 $pdf->MultiCell($largcol2, $tab2_hl, price($object->total_tva), 0, 'R', 1); 886 887 // Total LocalTax1 888 if (!empty($conf->global->FACTURE_LOCAL_TAX1_OPTION) && $conf->global->FACTURE_LOCAL_TAX1_OPTION == 'localtax1on' && $object->total_localtax1 > 0) { 889 $index++; 890 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); 891 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transcountrynoentities("TotalLT1", $mysoc->country_code), 0, 'L', 1); 892 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); 893 $pdf->MultiCell($largcol2, $tab2_hl, price($object->total_localtax1), $useborder, 'R', 1); 894 } 895 896 // Total LocalTax2 897 if (!empty($conf->global->FACTURE_LOCAL_TAX2_OPTION) && $conf->global->FACTURE_LOCAL_TAX2_OPTION == 'localtax2on' && $object->total_localtax2 > 0) { 898 $index++; 899 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); 900 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transcountrynoentities("TotalLT2", $mysoc->country_code), 0, 'L', 1); 901 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); 902 $pdf->MultiCell($largcol2, $tab2_hl, price($object->total_localtax2), $useborder, 'R', 1); 903 } 904 } else { 905 //if (! empty($conf->global->FACTURE_LOCAL_TAX1_OPTION) && $conf->global->FACTURE_LOCAL_TAX1_OPTION=='localtax1on') 906 //{ 907 //Local tax 1 908 foreach ($this->localtax1 as $localtax_type => $localtax_rate) { 909 if (in_array((string) $localtax_type, array('2', '4', '6'))) { 910 continue; 911 } 912 913 foreach ($localtax_rate as $tvakey => $tvaval) { 914 if ($tvakey != 0) { // On affiche pas taux 0 915 //$this->atleastoneratenotnull++; 916 917 $index++; 918 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); 919 920 $tvacompl = ''; 921 if (preg_match('/\*/', $tvakey)) { 922 $tvakey = str_replace('*', '', $tvakey); 923 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")"; 924 } 925 $totalvat = $outputlangs->transcountrynoentities("TotalLT1", $mysoc->country_code).' '; 926 $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; 927 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); 928 929 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); 930 $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); 931 } 932 } 933 } 934 935 //if (! empty($conf->global->FACTURE_LOCAL_TAX2_OPTION) && $conf->global->FACTURE_LOCAL_TAX2_OPTION=='localtax2on') 936 //{ 937 //Local tax 2 938 foreach ($this->localtax2 as $localtax_type => $localtax_rate) { 939 if (in_array((string) $localtax_type, array('2', '4', '6'))) { 940 continue; 941 } 942 943 foreach ($localtax_rate as $tvakey => $tvaval) { 944 if ($tvakey != 0) { // On affiche pas taux 0 945 //$this->atleastoneratenotnull++; 946 947 $index++; 948 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); 949 950 $tvacompl = ''; 951 if (preg_match('/\*/', $tvakey)) { 952 $tvakey = str_replace('*', '', $tvakey); 953 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")"; 954 } 955 $totalvat = $outputlangs->transcountrynoentities("TotalLT2", $mysoc->country_code).' '; 956 $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; 957 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); 958 959 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); 960 $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval), 0, 'R', 1); 961 } 962 } 963 } 964 } 965 966 // Total TTC 967 $index++; 968 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); 969 $pdf->SetTextColor(0, 0, 60); 970 $pdf->SetFillColor(224, 224, 224); 971 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalTTC"), $useborder, 'L', 1); 972 973 $total_ttc = (!empty($conf->multicurrency->enabled) && $object->multicurrency_tx != 1) ? $object->multicurrency_total_ttc : $object->total_ttc; 974 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); 975 $pdf->MultiCell($largcol2, $tab2_hl, price($total_ttc), $useborder, 'R', 1); 976 $pdf->SetFont('', '', $default_font_size - 1); 977 $pdf->SetTextColor(0, 0, 0); 978 979 $creditnoteamount = 0; 980 $depositsamount = 0; 981 //$creditnoteamount=$object->getSumCreditNotesUsed(); 982 //$depositsamount=$object->getSumDepositsUsed(); 983 //print "x".$creditnoteamount."-".$depositsamount;exit; 984 $resteapayer = price2num($total_ttc - $deja_regle - $creditnoteamount - $depositsamount, 'MT'); 985 if (!empty($object->paye)) { 986 $resteapayer = 0; 987 } 988 989 if ($deja_regle > 0) { 990 // Already paid + Deposits 991 $index++; 992 993 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); 994 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("AlreadyPaid"), 0, 'L', 0); 995 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); 996 $pdf->MultiCell($largcol2, $tab2_hl, price($deja_regle), 0, 'R', 0); 997 998 $index++; 999 $pdf->SetTextColor(0, 0, 60); 1000 $pdf->SetFillColor(224, 224, 224); 1001 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); 1002 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("RemainderToPay"), $useborder, 'L', 1); 1003 1004 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); 1005 $pdf->MultiCell($largcol2, $tab2_hl, price($resteapayer), $useborder, 'R', 1); 1006 1007 $pdf->SetFont('', '', $default_font_size - 1); 1008 $pdf->SetTextColor(0, 0, 0); 1009 } 1010 1011 $index++; 1012 return ($tab2_top + ($tab2_hl * $index)); 1013 } 1014 1015 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore 1016 /** 1017 * Show table for lines 1018 * 1019 * @param TCPDF $pdf Object PDF 1020 * @param string $tab_top Top position of table 1021 * @param string $tab_height Height of table (rectangle) 1022 * @param int $nexY Y (not used) 1023 * @param Translate $outputlangs Langs object 1024 * @param int $hidetop Hide top bar of array 1025 * @param int $hidebottom Hide bottom bar of array 1026 * @param string $currency Currency code 1027 * @return void 1028 */ 1029 protected function _tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop = 0, $hidebottom = 0, $currency = '') 1030 { 1031 global $conf; 1032 1033 // Force to disable hidetop and hidebottom 1034 $hidebottom = 0; 1035 if ($hidetop) { 1036 $hidetop = -1; 1037 } 1038 1039 $currency = !empty($currency) ? $currency : $conf->currency; 1040 $default_font_size = pdf_getPDFFontSize($outputlangs); 1041 1042 // Amount in (at tab_top - 1) 1043 $pdf->SetTextColor(0, 0, 0); 1044 $pdf->SetFont('', '', $default_font_size - 2); 1045 1046 if (empty($hidetop)) { 1047 $titre = $outputlangs->transnoentities("AmountInCurrency", $outputlangs->transnoentitiesnoconv("Currency".$currency)); 1048 $pdf->SetXY($this->page_largeur - $this->marge_droite - ($pdf->GetStringWidth($titre) + 3), $tab_top - 4); 1049 $pdf->MultiCell(($pdf->GetStringWidth($titre) + 3), 2, $titre); 1050 1051 //$conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR='230,230,230'; 1052 if (!empty($conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR)) { 1053 $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)); 1054 } 1055 } 1056 1057 $pdf->SetDrawColor(128, 128, 128); 1058 $pdf->SetFont('', '', $default_font_size - 1); 1059 1060 // Output Rect 1061 $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 1062 1063 if (empty($hidetop)) { 1064 $pdf->line($this->marge_gauche, $tab_top + 5, $this->page_largeur - $this->marge_droite, $tab_top + 5); // line takes a position y in 2nd parameter and 4th parameter 1065 1066 $pdf->SetXY($this->posxdesc - 1, $tab_top + 1); 1067 $pdf->MultiCell(108, 2, $outputlangs->transnoentities("Designation"), '', 'L'); 1068 } 1069 1070 if (empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT)) { 1071 $pdf->line($this->posxtva, $tab_top, $this->posxtva, $tab_top + $tab_height); 1072 if (empty($hidetop)) { 1073 $pdf->SetXY($this->posxtva - 3, $tab_top + 1); 1074 $pdf->MultiCell($this->posxup - $this->posxtva + 3, 2, $outputlangs->transnoentities("VAT"), '', 'C'); 1075 } 1076 } 1077 1078 $pdf->line($this->posxup, $tab_top, $this->posxup, $tab_top + $tab_height); 1079 if (empty($hidetop)) { 1080 $pdf->SetXY($this->posxup - 1, $tab_top + 1); 1081 $pdf->MultiCell($this->posxqty - $this->posxup - 1, 2, $outputlangs->transnoentities("PriceUHT"), '', 'C'); 1082 } 1083 1084 $pdf->line($this->posxqty - 1, $tab_top, $this->posxqty - 1, $tab_top + $tab_height); 1085 if (empty($hidetop)) { 1086 $pdf->SetXY($this->posxqty - 1, $tab_top + 1); 1087 $pdf->MultiCell($this->posxunit - $this->posxqty - 1, 2, $outputlangs->transnoentities("Qty"), '', 'C'); 1088 } 1089 1090 if (!empty($conf->global->PRODUCT_USE_UNITS)) { 1091 $pdf->line($this->posxunit - 1, $tab_top, $this->posxunit - 1, $tab_top + $tab_height); 1092 if (empty($hidetop)) { 1093 $pdf->SetXY($this->posxunit - 1, $tab_top + 1); 1094 $pdf->MultiCell($this->posxdiscount - $this->posxunit - 1, 2, $outputlangs->transnoentities("Unit"), '', 'C'); 1095 } 1096 } 1097 1098 $pdf->line($this->posxdiscount - 1, $tab_top, $this->posxdiscount - 1, $tab_top + $tab_height); 1099 if (empty($hidetop)) { 1100 if ($this->atleastonediscount) { 1101 $pdf->SetXY($this->posxdiscount - 1, $tab_top + 1); 1102 $pdf->MultiCell($this->postotalht - $this->posxdiscount + 1, 2, $outputlangs->transnoentities("ReductionShort"), '', 'C'); 1103 } 1104 } 1105 1106 if ($this->atleastonediscount) { 1107 $pdf->line($this->postotalht, $tab_top, $this->postotalht, $tab_top + $tab_height); 1108 } 1109 if (empty($hidetop)) { 1110 $pdf->SetXY($this->postotalht - 1, $tab_top + 1); 1111 $pdf->MultiCell(30, 2, $outputlangs->transnoentities("TotalHTShort"), '', 'C'); 1112 } 1113 } 1114 1115 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore 1116 /** 1117 * Show top header of page. 1118 * 1119 * @param TCPDF $pdf Object PDF 1120 * @param CommandeFournisseur $object Object to show 1121 * @param int $showaddress 0=no, 1=yes 1122 * @param Translate $outputlangs Object lang for output 1123 * @return void 1124 */ 1125 protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs) 1126 { 1127 global $langs, $conf, $mysoc; 1128 1129 $ltrdirection = 'L'; 1130 if ($outputlangs->trans("DIRECTION") == 'rtl') $ltrdirection = 'R'; 1131 1132 // Load translation files required by the page 1133 $outputlangs->loadLangs(array("main", "orders", "companies", "bills", "sendings")); 1134 1135 $default_font_size = pdf_getPDFFontSize($outputlangs); 1136 1137 // Do not add the BACKGROUND as this is for suppliers 1138 //pdf_pagehead($pdf,$outputlangs,$this->page_hauteur); 1139 1140 //Affiche le filigrane brouillon - Print Draft Watermark 1141 /*if($object->statut==0 && (! empty($conf->global->COMMANDE_DRAFT_WATERMARK)) ) 1142 { 1143 pdf_watermark($pdf,$outputlangs,$this->page_hauteur,$this->page_largeur,'mm',$conf->global->COMMANDE_DRAFT_WATERMARK); 1144 }*/ 1145 //Print content 1146 1147 $pdf->SetTextColor(0, 0, 60); 1148 $pdf->SetFont('', 'B', $default_font_size + 3); 1149 1150 $posx = $this->page_largeur - $this->marge_droite - 100; 1151 $posy = $this->marge_haute; 1152 1153 $pdf->SetXY($this->marge_gauche, $posy); 1154 1155 // Logo 1156 $logo = $conf->mycompany->dir_output.'/logos/'.$this->emetteur->logo; 1157 if ($this->emetteur->logo) { 1158 if (is_readable($logo)) { 1159 $height = pdf_getHeightForLogo($logo); 1160 $pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto) 1161 } else { 1162 $pdf->SetTextColor(200, 0, 0); 1163 $pdf->SetFont('', 'B', $default_font_size - 2); 1164 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound", $logo), 0, 'L'); 1165 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorGoToModuleSetup"), 0, 'L'); 1166 } 1167 } else { 1168 $text = $this->emetteur->name; 1169 $pdf->MultiCell(100, 4, $outputlangs->convToOutputCharset($text), 0, $ltrdirection); 1170 } 1171 1172 $pdf->SetFont('', 'B', $default_font_size + 3); 1173 $pdf->SetXY($posx, $posy); 1174 $pdf->SetTextColor(0, 0, 60); 1175 $title = $outputlangs->transnoentities("SupplierOrder")." ".$outputlangs->convToOutputCharset($object->ref); 1176 $pdf->MultiCell(100, 3, $title, '', 'R'); 1177 $posy += 1; 1178 1179 if ($object->ref_supplier) { 1180 $posy += 4; 1181 $pdf->SetFont('', 'B', $default_font_size); 1182 $pdf->SetXY($posx, $posy); 1183 $pdf->SetTextColor(0, 0, 60); 1184 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("RefSupplier")." : ".$outputlangs->convToOutputCharset($object->ref_supplier), '', 'R'); 1185 $posy += 1; 1186 } 1187 1188 $pdf->SetFont('', '', $default_font_size - 1); 1189 1190 if (!empty($conf->global->PDF_SHOW_PROJECT_TITLE)) { 1191 $object->fetch_projet(); 1192 if (!empty($object->project->ref)) { 1193 $posy += 3; 1194 $pdf->SetXY($posx, $posy); 1195 $pdf->SetTextColor(0, 0, 60); 1196 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("Project")." : ".(empty($object->project->title) ? '' : $object->project->title), '', 'R'); 1197 } 1198 } 1199 1200 if (!empty($conf->global->PDF_SHOW_PROJECT)) { 1201 $object->fetch_projet(); 1202 if (!empty($object->project->ref)) { 1203 $outputlangs->load("projects"); 1204 $posy += 4; 1205 $pdf->SetXY($posx, $posy); 1206 $langs->load("projects"); 1207 $pdf->SetTextColor(0, 0, 60); 1208 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Project")." : ".(empty($object->project->ref) ? '' : $object->project->ref), '', 'R'); 1209 } 1210 } 1211 1212 if (!empty($object->date_commande)) { 1213 $posy += 5; 1214 $pdf->SetXY($posx, $posy); 1215 $pdf->SetTextColor(0, 0, 60); 1216 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("OrderDate")." : ".dol_print_date($object->date_commande, "day", false, $outputlangs, true), '', 'R'); 1217 } else { 1218 $posy += 5; 1219 $pdf->SetXY($posx, $posy); 1220 $pdf->SetTextColor(255, 0, 0); 1221 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("OrderToProcess"), '', 'R'); 1222 } 1223 1224 $pdf->SetTextColor(0, 0, 60); 1225 $usehourmin = 'day'; 1226 if (!empty($conf->global->SUPPLIER_ORDER_USE_HOUR_FOR_DELIVERY_DATE)) { 1227 $usehourmin = 'dayhour'; 1228 } 1229 if (!empty($object->delivery_date)) { 1230 $posy += 4; 1231 $pdf->SetXY($posx - 90, $posy); 1232 $pdf->MultiCell(190, 3, $outputlangs->transnoentities("DateDeliveryPlanned")." : ".dol_print_date($object->delivery_date, $usehourmin, false, $outputlangs, true), '', 'R'); 1233 } 1234 1235 if ($object->thirdparty->code_fournisseur) { 1236 $posy += 4; 1237 $pdf->SetXY($posx, $posy); 1238 $pdf->SetTextColor(0, 0, 60); 1239 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("SupplierCode")." : ".$outputlangs->transnoentities($object->thirdparty->code_fournisseur), '', 'R'); 1240 } 1241 1242 // Get contact 1243 if (!empty($conf->global->DOC_SHOW_FIRST_SALES_REP)) { 1244 $arrayidcontact = $object->getIdContact('internal', 'SALESREPFOLL'); 1245 if (count($arrayidcontact) > 0) { 1246 $usertmp = new User($this->db); 1247 $usertmp->fetch($arrayidcontact[0]); 1248 $posy += 4; 1249 $pdf->SetXY($posx, $posy); 1250 $pdf->SetTextColor(0, 0, 60); 1251 $pdf->MultiCell(100, 3, $langs->trans("BuyerName")." : ".$usertmp->getFullName($langs), '', 'R'); 1252 } 1253 } 1254 1255 $posy += 1; 1256 $pdf->SetTextColor(0, 0, 60); 1257 1258 $top_shift = 0; 1259 // Show list of linked objects 1260 $current_y = $pdf->getY(); 1261 $posy = pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, 100, 3, 'R', $default_font_size); 1262 if ($current_y < $pdf->getY()) { 1263 $top_shift = $pdf->getY() - $current_y; 1264 } 1265 1266 if ($showaddress) { 1267 // Sender properties 1268 $carac_emetteur = ''; 1269 // Add internal contact of proposal if defined 1270 $arrayidcontact = $object->getIdContact('internal', 'SALESREPFOLL'); 1271 if (count($arrayidcontact) > 0) { 1272 $object->fetch_user($arrayidcontact[0]); 1273 $carac_emetteur .= ($carac_emetteur ? "\n" : '').$outputlangs->convToOutputCharset($object->user->getFullName($outputlangs))."\n"; 1274 } 1275 1276 $carac_emetteur .= pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, '', 0, 'source', $object); 1277 1278 // Show sender 1279 $posy = 42 + $top_shift; 1280 $posx = $this->marge_gauche; 1281 if (!empty($conf->global->MAIN_INVERT_SENDER_RECIPIENT)) { 1282 $posx = $this->page_largeur - $this->marge_droite - 80; 1283 } 1284 $hautcadre = 40; 1285 1286 // Show sender frame 1287 $pdf->SetTextColor(0, 0, 0); 1288 $pdf->SetFont('', '', $default_font_size - 2); 1289 $pdf->SetXY($posx, $posy - 5); 1290 $pdf->MultiCell(80, 5, $outputlangs->transnoentities("BillFrom"), 0, $ltrdirection); 1291 $pdf->SetXY($posx, $posy); 1292 $pdf->SetFillColor(230, 230, 230); 1293 $pdf->MultiCell(82, $hautcadre, "", 0, 'R', 1); 1294 $pdf->SetTextColor(0, 0, 60); 1295 1296 // Show sender name 1297 $pdf->SetXY($posx + 2, $posy + 3); 1298 $pdf->SetFont('', 'B', $default_font_size); 1299 $pdf->MultiCell(80, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, $ltrdirection); 1300 $posy = $pdf->getY(); 1301 1302 // Show sender information 1303 $pdf->SetXY($posx + 2, $posy); 1304 $pdf->SetFont('', '', $default_font_size - 1); 1305 $pdf->MultiCell(80, 4, $carac_emetteur, 0, $ltrdirection); 1306 1307 1308 // If CUSTOMER contact defined on order, we use it. Note: Even if this is a supplier object, the code for external contat that follow order is 'CUSTOMER' 1309 $usecontact = false; 1310 $arrayidcontact = $object->getIdContact('external', 'CUSTOMER'); 1311 if (count($arrayidcontact) > 0) { 1312 $usecontact = true; 1313 $result = $object->fetch_contact($arrayidcontact[0]); 1314 } 1315 1316 // Recipient name 1317 if ($usecontact && ($object->contact->socid != $object->thirdparty->id && (!isset($conf->global->MAIN_USE_COMPANY_NAME_OF_CONTACT) || !empty($conf->global->MAIN_USE_COMPANY_NAME_OF_CONTACT)))) { 1318 $thirdparty = $object->contact; 1319 } else { 1320 $thirdparty = $object->thirdparty; 1321 } 1322 1323 $carac_client_name = pdfBuildThirdpartyName($thirdparty, $outputlangs); 1324 1325 $carac_client = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, ($usecontact ? $object->contact : ''), $usecontact, 'target', $object); 1326 1327 // Show recipient 1328 $widthrecbox = 100; 1329 if ($this->page_largeur < 210) { 1330 $widthrecbox = 84; // To work with US executive format 1331 } 1332 $posy = 42 + $top_shift; 1333 $posx = $this->page_largeur - $this->marge_droite - $widthrecbox; 1334 if (!empty($conf->global->MAIN_INVERT_SENDER_RECIPIENT)) { 1335 $posx = $this->marge_gauche; 1336 } 1337 1338 // Show recipient frame 1339 $pdf->SetTextColor(0, 0, 0); 1340 $pdf->SetFont('', '', $default_font_size - 2); 1341 $pdf->SetXY($posx + 2, $posy - 5); 1342 $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillTo"), 0, $ltrdirection); 1343 $pdf->Rect($posx, $posy, $widthrecbox, $hautcadre); 1344 1345 // Show recipient name 1346 $pdf->SetXY($posx + 2, $posy + 3); 1347 $pdf->SetFont('', 'B', $default_font_size); 1348 $pdf->MultiCell($widthrecbox, 4, $carac_client_name, 0, $ltrdirection); 1349 1350 $posy = $pdf->getY(); 1351 1352 // Show recipient information 1353 $pdf->SetFont('', '', $default_font_size - 1); 1354 $pdf->SetXY($posx + 2, $posy); 1355 $pdf->MultiCell($widthrecbox, 4, $carac_client, 0, $ltrdirection); 1356 } 1357 1358 return $top_shift; 1359 } 1360 1361 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore 1362 /** 1363 * Show footer of page. Need this->emetteur object 1364 * 1365 * @param TCPDF $pdf PDF 1366 * @param CommandeFournisseur $object Object to show 1367 * @param Translate $outputlangs Object lang for output 1368 * @param int $hidefreetext 1=Hide free text 1369 * @return int Return height of bottom margin including footer text 1370 */ 1371 protected function _pagefoot(&$pdf, $object, $outputlangs, $hidefreetext = 0) 1372 { 1373 global $conf; 1374 $showdetails = empty($conf->global->MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS) ? 0 : $conf->global->MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS; 1375 return pdf_pagefoot($pdf, $outputlangs, 'SUPPLIER_ORDER_FREE_TEXT', $this->emetteur, $this->marge_basse, $this->marge_gauche, $this->page_hauteur, $object, $showdetails, $hidefreetext); 1376 } 1377} 1378