Advertisement
erptarragona

pdf_cyan.module.php

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