dolibarr 18.0.6
pdf_vinci.modules.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2004-2014 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2005-2011 Regis Houssin <regis.houssin@inodbox.com>
4 * Copyright (C) 2007 Franky Van Liedekerke <franky.van.liedekerke@telenet.be>
5 * Copyright (C) 2010-2014 Juanjo Menent <jmenent@2byte.es>
6 * Copyright (C) 2015 Marcos García <marcosgdf@gmail.com>
7 * Copyright (C) 2017 Ferran Marcet <fmarcet@2byte.es>
8 * Copyright (C) 2018-2021 Frédéric France <frederic.france@netlogic.fr>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 * or see https://www.gnu.org/
23 */
24
31require_once DOL_DOCUMENT_ROOT.'/core/modules/mrp/modules_mo.php';
32require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
33require_once DOL_DOCUMENT_ROOT.'/bom/class/bom.class.php';
34require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
35require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
36require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
37require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
38
39
44{
48 public $db;
49
53 public $name;
54
58 public $description;
59
63 public $update_main_doc_field;
64
68 public $type;
69
74 public $version = 'dolibarr';
75
79 public $page_largeur;
80
84 public $page_hauteur;
85
89 public $format;
90
94 public $marge_gauche;
95
99 public $marge_droite;
100
104 public $marge_haute;
105
109 public $marge_basse;
110
115 public $emetteur;
116
117
123 public function __construct($db)
124 {
125 global $conf, $langs, $mysoc;
126
127 // Load translation files required by the page
128 $langs->loadLangs(array("main", "bills", "mrp"));
129
130 $this->db = $db;
131 $this->name = "vinci";
132 $this->description = $langs->trans('DocumentModelStandardPDF');
133 $this->update_main_doc_field = 1; // Save the name of generated file as the main doc when generating a doc with this template
134
135 // Page size for A4 format
136 $this->type = 'pdf';
137 $formatarray = pdf_getFormat();
138 $this->page_largeur = $formatarray['width'];
139 $this->page_hauteur = $formatarray['height'];
140 $this->format = array($this->page_largeur, $this->page_hauteur);
141 $this->marge_gauche = getDolGlobalInt('MAIN_PDF_MARGIN_LEFT', 10);
142 $this->marge_droite = getDolGlobalInt('MAIN_PDF_MARGIN_RIGHT', 10);
143 $this->marge_haute = getDolGlobalInt('MAIN_PDF_MARGIN_TOP', 10);
144 $this->marge_basse = getDolGlobalInt('MAIN_PDF_MARGIN_BOTTOM', 10);
145
146 $this->option_logo = 1; // Display logo
147 $this->option_multilang = 1; //Available in several languages
148 $this->option_escompte = 0; // Displays if there has been a discount
149 $this->option_credit_note = 0; // Support credit notes
150 $this->option_freetext = 1; // Support add of a personalised text
151 $this->option_draft_watermark = 1; // Support add of a watermark on drafts
152
153 // Get source company
154 $this->emetteur = $mysoc;
155 if (empty($this->emetteur->country_code)) {
156 $this->emetteur->country_code = substr($langs->defaultlang, -2); // By default, if was not defined
157 }
158
159 // Define position of columns
160 $this->posxdesc = $this->marge_gauche + 1; // For module retrocompatibility support durring PDF transition: TODO remove this at the end
161 }
162
163
164 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
176 public function write_file($object, $outputlangs = '', $srctemplatepath = '', $hidedetails = 0, $hidedesc = 0, $hideref = 0)
177 {
178 // phpcs:enable
179 global $user, $langs, $conf, $hookmanager, $mysoc;
180
181 if (!is_object($outputlangs)) {
182 $outputlangs = $langs;
183 }
184 // For backward compatibility with FPDF, force output charset to ISO, because FPDF expect text to be encoded in ISO
185 if (!empty($conf->global->MAIN_USE_FPDF)) {
186 $outputlangs->charset_output = 'ISO-8859-1';
187 }
188
189 // Load translation files required by the page
190 $outputlangs->loadLangs(array("main", "orders", "companies", "bills", "dict", "products"));
191
192 global $outputlangsbis;
193 $outputlangsbis = null;
194 if (!empty($conf->global->PDF_USE_ALSO_LANGUAGE_CODE) && $outputlangs->defaultlang != $conf->global->PDF_USE_ALSO_LANGUAGE_CODE) {
195 $outputlangsbis = new Translate('', $conf);
196 $outputlangsbis->setDefaultLang($conf->global->PDF_USE_ALSO_LANGUAGE_CODE);
197 $outputlangsbis->loadLangs(array("main", "orders", "companies", "bills", "dict", "products"));
198 }
199
200 if (!isset($object->lines) || !is_array($object->lines)) {
201 $object->lines = array();
202 }
203
204 $nblines = count($object->lines);
205
206 $hidetop = 0;
207 if (!empty($conf->global->MAIN_PDF_DISABLE_COL_HEAD_TITLE)) {
208 $hidetop = $conf->global->MAIN_PDF_DISABLE_COL_HEAD_TITLE;
209 }
210
211 // Loop on each lines to detect if there is at least one image to show
212 $realpatharray = array();
213
214 if ($conf->mrp->dir_output) {
215 $object->fetch_thirdparty();
216
217 $deja_regle = 0;
218 $amount_credit_notes_included = 0;
219 $amount_deposits_included = 0;
220 //$amount_credit_notes_included = $object->getSumCreditNotesUsed();
221 //$amount_deposits_included = $object->getSumDepositsUsed();
222
223 // Definition of $dir and $file
224 if ($object->specimen) {
225 $dir = $conf->mrp->dir_output;
226 $file = $dir."/SPECIMEN.pdf";
227 } else {
228 $objectref = dol_sanitizeFileName($object->ref);
229 $dir = $conf->mrp->dir_output.'/'.$objectref;
230 $file = $dir."/".$objectref.".pdf";
231 }
232
233 if (!file_exists($dir)) {
234 if (dol_mkdir($dir) < 0) {
235 $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
236 return 0;
237 }
238 }
239
240 if (file_exists($dir)) {
241 // Add pdfgeneration hook
242 if (!is_object($hookmanager)) {
243 include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
244 $hookmanager = new HookManager($this->db);
245 }
246 $hookmanager->initHooks(array('pdfgeneration'));
247 $parameters = array('file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs);
248 global $action;
249 $reshook = $hookmanager->executeHooks('beforePDFCreation', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
250
251 $nblines = count($object->lines);
252
253 $pdf = pdf_getInstance($this->format);
254 $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance
255 $heightforinfotot = 50; // Height reserved to output the info and total part
256 $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
257 $heightforfooter = $this->marge_basse + 8; // Height reserved to output the footer (value include bottom margin)
258 if (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS)) {
259 $heightforfooter += 6;
260 }
261 $pdf->SetAutoPageBreak(1, 0);
262
263 if (class_exists('TCPDF')) {
264 $pdf->setPrintHeader(false);
265 $pdf->setPrintFooter(false);
266 }
267 $pdf->SetFont(pdf_getPDFFont($outputlangs));
268 // Set path to the background PDF File
269 if (!empty($conf->global->MAIN_ADD_PDF_BACKGROUND)) {
270 $pagecount = $pdf->setSourceFile($conf->mycompany->dir_output.'/'.$conf->global->MAIN_ADD_PDF_BACKGROUND);
271 $tplidx = $pdf->importPage(1);
272 }
273
274 $pdf->Open();
275 $pagenb = 0;
276 $pdf->SetDrawColor(128, 128, 128);
277
278 $pdf->SetTitle($outputlangs->convToOutputCharset($object->ref));
279 $pdf->SetSubject($outputlangs->transnoentities("Mo"));
280 $pdf->SetCreator("Dolibarr ".DOL_VERSION);
281 $pdf->SetAuthor($outputlangs->convToOutputCharset($user->getFullName($outputlangs)));
282 $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("Mo")." ".$outputlangs->convToOutputCharset($object->thirdparty->name));
283 if (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) {
284 $pdf->SetCompression(false);
285 }
286
287 $pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite); // Left, Top, Right
288
289 // Does we have at least one line with discount $this->atleastonediscount
290
291 // New page
292 $pdf->AddPage();
293 if (!empty($tplidx)) {
294 $pdf->useTemplate($tplidx);
295 }
296 $pagenb++;
297 $top_shift = $this->_pagehead($pdf, $object, 1, $outputlangs);
298 $pdf->SetFont('', '', $default_font_size - 1);
299 $pdf->MultiCell(0, 3, ''); // Set interline to 3
300 $pdf->SetTextColor(0, 0, 0);
301
302 $tab_top = 90 + $top_shift;
303 $tab_top_newpage = (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD') ? 42 + $top_shift : 10);
304
305 $tab_height = $this->page_hauteur - $tab_top - $heightforfooter - $heightforfreetext;
306
307
308 // Affiche notes
309 $notetoshow = empty($object->note_public) ? '' : $object->note_public;
310
311 // Extrafields in note
312 $extranote = $this->getExtrafieldsInHtml($object, $outputlangs);
313 if (!empty($extranote)) {
314 $notetoshow = dol_concatdesc($notetoshow, $extranote);
315 }
316
317 $pagenb = $pdf->getPage();
318 if ($notetoshow) {
319 $tab_width = $this->page_largeur - $this->marge_gauche - $this->marge_droite;
320 $pageposbeforenote = $pagenb;
321
322 $substitutionarray = pdf_getSubstitutionArray($outputlangs, null, $object);
323 complete_substitutions_array($substitutionarray, $outputlangs, $object);
324 $notetoshow = make_substitutions($notetoshow, $substitutionarray, $outputlangs);
325 $notetoshow = convertBackOfficeMediasLinksToPublicLinks($notetoshow);
326
327 $tab_top -= 2;
328
329 $pdf->startTransaction();
330
331 $pdf->SetFont('', '', $default_font_size - 1);
332 $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top, dol_htmlentitiesbr($notetoshow), 0, 1);
333 // Description
334 $pageposafternote = $pdf->getPage();
335 $posyafter = $pdf->GetY();
336
337 if ($pageposafternote > $pageposbeforenote) {
338 $pdf->rollbackTransaction(true);
339
340 // prepar pages to receive notes
341 while ($pagenb < $pageposafternote) {
342 $pdf->AddPage();
343 $pagenb++;
344 if (!empty($tplidx)) {
345 $pdf->useTemplate($tplidx);
346 }
347 if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
348 $this->_pagehead($pdf, $object, 0, $outputlangs);
349 }
350 // $this->_pagefoot($pdf,$object,$outputlangs,1);
351 $pdf->setTopMargin($tab_top_newpage);
352 // The only function to edit the bottom margin of current page to set it.
353 $pdf->setPageOrientation('', 1, $heightforfooter + $heightforfreetext);
354 }
355
356 // back to start
357 $pdf->setPage($pageposbeforenote);
358 $pdf->setPageOrientation('', 1, $heightforfooter + $heightforfreetext);
359 $pdf->SetFont('', '', $default_font_size - 1);
360 $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top, dol_htmlentitiesbr($notetoshow), 0, 1);
361 $pageposafternote = $pdf->getPage();
362
363 $posyafter = $pdf->GetY();
364
365 if ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + 20))) { // There is no space left for total+free text
366 $pdf->AddPage('', '', true);
367 $pagenb++;
368 $pageposafternote++;
369 $pdf->setPage($pageposafternote);
370 $pdf->setTopMargin($tab_top_newpage);
371 // The only function to edit the bottom margin of current page to set it.
372 $pdf->setPageOrientation('', 1, $heightforfooter + $heightforfreetext);
373 //$posyafter = $tab_top_newpage;
374 }
375
376
377 // apply note frame to previus pages
378 $i = $pageposbeforenote;
379 while ($i < $pageposafternote) {
380 $pdf->setPage($i);
381
382
383 $pdf->SetDrawColor(128, 128, 128);
384 // Draw note frame
385 if ($i > $pageposbeforenote) {
386 $height_note = $this->page_hauteur - ($tab_top_newpage + $heightforfooter);
387 $pdf->Rect($this->marge_gauche, $tab_top_newpage - 1, $tab_width, $height_note + 1);
388 } else {
389 $height_note = $this->page_hauteur - ($tab_top + $heightforfooter);
390 $pdf->Rect($this->marge_gauche, $tab_top - 1, $tab_width, $height_note + 1);
391 }
392
393 // Add footer
394 $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it.
395 $this->_pagefoot($pdf, $object, $outputlangs, 1);
396
397 $i++;
398 }
399
400 // apply note frame to last page
401 $pdf->setPage($pageposafternote);
402 if (!empty($tplidx)) {
403 $pdf->useTemplate($tplidx);
404 }
405 if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
406 $this->_pagehead($pdf, $object, 0, $outputlangs);
407 }
408 $height_note = $posyafter - $tab_top_newpage;
409 $pdf->Rect($this->marge_gauche, $tab_top_newpage - 1, $tab_width, $height_note + 1);
410 } else {
411 // No pagebreak
412 $pdf->commitTransaction();
413 $posyafter = $pdf->GetY();
414 $height_note = $posyafter - $tab_top;
415 $pdf->Rect($this->marge_gauche, $tab_top - 1, $tab_width, $height_note + 1);
416
417
418 if ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + 20))) {
419 // not enough space, need to add page
420 $pdf->AddPage('', '', true);
421 $pagenb++;
422 $pageposafternote++;
423 $pdf->setPage($pageposafternote);
424 if (!empty($tplidx)) {
425 $pdf->useTemplate($tplidx);
426 }
427 if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
428 $this->_pagehead($pdf, $object, 0, $outputlangs);
429 }
430
431 $posyafter = $tab_top_newpage;
432 }
433 }
434
435 $tab_height = $tab_height - $height_note;
436 $tab_top = $posyafter + 6;
437 } else {
438 $height_note = 0;
439 }
440
441 $nexY = $tab_top + 5;
442
443 // Use new auto collum system
444 $this->prepareArrayColumnField($object, $outputlangs, $hidedetails, $hidedesc, $hideref);
445
446 // Loop on each lines
447 $pageposbeforeprintlines = $pdf->getPage();
448 $pagenb = $pageposbeforeprintlines;
449
450 $bom = new BOM($this->db);
451 $bom -> fetch($object->fk_bom);
452
453 $nblines = count($bom->lines);
454
455 for ($i = 0; $i < $nblines; $i++) {
456 $curY = $nexY;
457 $pdf->SetFont('', '', $default_font_size - 1); // Into loop to work with multipage
458 $pdf->SetTextColor(0, 0, 0);
459
460 $prod = new Product($this->db);
461 $prod->fetch($bom->lines[$i]->fk_product);
462
463 // Define size of image if we need it
464 $imglinesize = array();
465 if (!empty($realpatharray[$i])) {
466 $imglinesize = pdf_getSizeForImage($realpatharray[$i]);
467 }
468
469 $pdf->setTopMargin($tab_top_newpage);
470 $pdf->setPageOrientation('', 1, $heightforfooter + $heightforfreetext + $heightforinfotot); // The only function to edit the bottom margin of current page to set it.
471 $pageposbefore = $pdf->getPage();
472
473 $showpricebeforepagebreak = 1;
474 $posYAfterImage = 0;
475 $posYAfterDescription = 0;
476
477 // We start with Photo of product line
478 if (!empty($imglinesize['width']) && !empty($imglinesize['height']) && ($curY + $imglinesize['height']) > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforinfotot))) { // If photo too high, we moved completely on new page
479 $pdf->AddPage('', '', true);
480 if (!empty($tplidx)) {
481 $pdf->useTemplate($tplidx);
482 }
483 if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
484 $this->_pagehead($pdf, $object, 0, $outputlangs);
485 }
486 $pdf->setPage($pageposbefore + 1);
487
488 $curY = $tab_top_newpage;
489
490 // Allows data in the first page if description is long enough to break in multiples pages
491 if (!empty($conf->global->MAIN_PDF_DATA_ON_FIRST_PAGE)) {
492 $showpricebeforepagebreak = 1;
493 } else {
494 $showpricebeforepagebreak = 0;
495 }
496 }
497
498 if (!empty($imglinesize['width']) && !empty($imglinesize['height'])) {
499 $curX = $this->posxpicture - 1;
500 $pdf->Image($realpatharray[$i], $curX + (($this->posxtva - $this->posxpicture - $imglinesize['width']) / 2), $curY, $imglinesize['width'], $imglinesize['height'], '', '', '', 2, 300); // Use 300 dpi
501 // $pdf->Image does not increase value return by getY, so we save it manually
502 $posYAfterImage = $curY + $imglinesize['height'];
503 }
504 // Description of product line
505 $curX = $this->posxdesc - 1;
506 $showpricebeforepagebreak = 1;
507
508 if ($this->getColumnStatus('code')) {
509 $pdf->startTransaction(); //description
510 //$this->printColDescContent($pdf, $curY, 'code', $object, $i, $outputlangs, $hideref, $hidedesc, $showsupplierSKU);
511 $this->printStdColumnContent($pdf, $curY, 'code', $prod->ref);
512
513 $pageposafter = $pdf->getPage();
514 $posyafter = $pdf->GetY();
515 if ($pageposafter > $pageposbefore) { // There is a pagebreak
516 $pdf->rollbackTransaction(true);
517
518 //$this->printColDescContent($pdf, $curY, 'code', $object, $i, $outputlangs, $hideref, $hidedesc, $showsupplierSKU);
519 $this->printStdColumnContent($pdf, $curY, 'code', $prod->ref);
520
521 $pageposafter = $pdf->getPage();
522 $posyafter = $pdf->GetY();
523 } elseif ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforinfotot))) { // There is no space left for total+free text
524 if ($i == ($nblines - 1)) { // No more lines, and no space left to show total, so we create a new page
525 $pdf->AddPage('', '', true);
526 if (!empty($tplidx)) {
527 $pdf->useTemplate($tplidx);
528 }
529 //if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) $this->_pagehead($pdf, $object, 0, $outputlangs);
530 $pdf->setPage($pageposafter + 1);
531 } else {
532 // We found a page break
533 // Allows data in the first page if description is long enough to break in multiples pages
534 if (!empty($conf->global->MAIN_PDF_DATA_ON_FIRST_PAGE)) {
535 $showpricebeforepagebreak = 1;
536 } else {
537 $showpricebeforepagebreak = 0;
538 }
539 }
540 } else // No pagebreak
541 {
542 $pdf->commitTransaction();
543 }
544 $posYAfterDescription = $pdf->GetY();
545 }
546
547 $nexY = $pdf->GetY();
548 $pageposafter = $pdf->getPage();
549 $pdf->setPage($pageposbefore);
550 $pdf->setTopMargin($this->marge_haute);
551 $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it.
552
553 // We suppose that a too long description is moved completely on next page
554 if ($pageposafter > $pageposbefore && empty($showpricebeforepagebreak)) {
555 $pdf->setPage($pageposafter);
556 $curY = $tab_top_newpage;
557 }
558
559 if ($this->getColumnStatus('desc')) {
560 $pdf->startTransaction(); //description
561 $des = $prod -> description;
562 $descr = $des;//implode("<br>", $des);
563
564 $this->printStdColumnContent($pdf, $curY, 'desc', $descr);
565
566 $pageposafter = $pdf->getPage();
567 $posyafter = $pdf->GetY();
568 if ($pageposafter > $pageposbefore) { // There is a pagebreak
569 $pdf->rollbackTransaction(true);
570
571 $this->printStdColumnContent($pdf, $curY, 'desc', $descr);
572
573 $pageposafter = $pdf->getPage();
574 $posyafter = $pdf->GetY();
575 } elseif ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforinfotot))) { // There is no space left for total+free text
576 if ($i == ($nblines - 1)) { // No more lines, and no space left to show total, so we create a new page
577 $pdf->AddPage('', '', true);
578 if (!empty($tplidx)) {
579 $pdf->useTemplate($tplidx);
580 }
581 //if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) $this->_pagehead($pdf, $object, 0, $outputlangs);
582 $pdf->setPage($pageposafter + 1);
583 } else {
584 // We found a page break
585 // Allows data in the first page if description is long enough to break in multiples pages
586 if (!empty($conf->global->MAIN_PDF_DATA_ON_FIRST_PAGE)) {
587 $showpricebeforepagebreak = 1;
588 } else {
589 $showpricebeforepagebreak = 0;
590 }
591 }
592 } else // No pagebreak
593 {
594 $pdf->commitTransaction();
595 }
596 $posYAfterDescription = max($posYAfterDescription, $pdf->GetY());
597 }
598
599 $nexY = max($nexY, $pdf->GetY());
600 $pageposafter = $pdf->getPage();
601 $pdf->setPage($pageposbefore);
602 $pdf->setTopMargin($this->marge_haute);
603 $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it.
604
605 // We suppose that a too long description is moved completely on next page
606 if ($pageposafter > $pageposbefore && empty($showpricebeforepagebreak)) {
607 $pdf->setPage($pageposafter);
608 $curY = $tab_top_newpage;
609 }
610
611 $pdf->SetFont('', '', $default_font_size - 1); // On repositionne la police par defaut
612
613 // Quantity
614 // Enough for 6 chars
615 if ($this->getColumnStatus('qty')) {
616 $qty = $bom->lines[$i]->qty;
617 $this->printStdColumnContent($pdf, $curY, 'qty', $qty);
618 $nexY = max($pdf->GetY(), $nexY);
619 }
620
621 // Quantity
622 // Enough for 6 chars
623 if ($this->getColumnStatus('qtytot')) {
624 $qtytot = $object->qty * $bom->lines[$i]->qty;
625 $this->printStdColumnContent($pdf, $curY, 'qtytot', $qtytot);
626 $nexY = max($pdf->GetY(), $nexY);
627 }
628
629 // Dimensions
630 if ($this->getColumnStatus('dim')) {
631 $array = array_filter(array($prod->length, $prod->width, $prod->height));
632 $dim = implode("x", $array);
633 $this->printStdColumnContent($pdf, $curY, 'dim', $dim);
634 $nexY = max($pdf->GetY(), $nexY);
635 }
636 }
637
638
639
640
641 // Show square
642 if ($pagenb == $pageposbeforeprintlines) {
643 $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, $hidetop, 0, $object->multicurrency_code);
644 $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
645 } else {
646 $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 1, 0, $object->multicurrency_code);
647 $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
648 }
649
650 // Affiche zone infos
651 $posy = $this->_tableau_info($pdf, $object, $bottomlasttab, $outputlangs);
652
653 // Affiche zone totaux
654 //$posy = $this->_tableau_tot($pdf, $object, $deja_regle, $bottomlasttab, $outputlangs);
655
656 // Affiche zone versements
657 if ($deja_regle || $amount_credit_notes_included || $amount_deposits_included) {
658 $posy = $this->_tableau_versements($pdf, $object, $posy, $outputlangs);
659 }
660
661 // Pied de page
662 $this->_pagefoot($pdf, $object, $outputlangs);
663 if (method_exists($pdf, 'AliasNbPages')) {
664 $pdf->AliasNbPages();
665 }
666
667 $pdf->Close();
668
669 $pdf->Output($file, 'F');
670
671 // Add pdfgeneration hook
672 $hookmanager->initHooks(array('pdfgeneration'));
673 $parameters = array('file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs);
674 global $action;
675 $reshook = $hookmanager->executeHooks('afterPDFCreation', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
676 if ($reshook < 0) {
677 $this->error = $hookmanager->error;
678 $this->errors = $hookmanager->errors;
679 }
680
681 dolChmod($file);
682
683 $this->result = array('fullpath'=>$file);
684
685 return 1; // No error
686 } else {
687 $this->error = $langs->trans("ErrorCanNotCreateDir", $dir);
688 return 0;
689 }
690 } else {
691 $this->error = $langs->trans("ErrorConstantNotDefined", "SUPPLIER_OUTPUTDIR");
692 return 0;
693 }
694 }
695
696 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
697 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
707 protected function _tableau_versements(&$pdf, $object, $posy, $outputlangs)
708 {
709 // phpcs:enable
710 return 1;
711 }
712
713 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
714 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
724 protected function _tableau_info(&$pdf, $object, $posy, $outputlangs)
725 {
726 // phpcs:enable
727 global $conf, $mysoc;
728 $default_font_size = pdf_getPDFFontSize($outputlangs);
729
730 // If France, show VAT mention if not applicable
731 if ($this->emetteur->country_code == 'FR' && empty($mysoc->tva_assuj)) {
732 $pdf->SetFont('', 'B', $default_font_size - 2);
733 $pdf->SetXY($this->marge_gauche, $posy);
734 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("VATIsNotUsedForInvoice"), 0, 'L', 0);
735
736 $posy = $pdf->GetY() + 4;
737 }
738
739 $posxval = 52;
740
741 // Show payments conditions
742 if (!empty($object->cond_reglement_code) || $object->cond_reglement) {
743 $pdf->SetFont('', 'B', $default_font_size - 2);
744 $pdf->SetXY($this->marge_gauche, $posy);
745 $titre = $outputlangs->transnoentities("PaymentConditions").':';
746 $pdf->MultiCell(80, 4, $titre, 0, 'L');
747
748 $pdf->SetFont('', '', $default_font_size - 2);
749 $pdf->SetXY($posxval, $posy);
750 $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);
751 $lib_condition_paiement = str_replace('\n', "\n", $lib_condition_paiement);
752 $pdf->MultiCell(80, 4, $lib_condition_paiement, 0, 'L');
753
754 $posy = $pdf->GetY() + 3;
755 }
756
757 // Show payment mode
758 if (!empty($object->mode_reglement_code)) {
759 $pdf->SetFont('', 'B', $default_font_size - 2);
760 $pdf->SetXY($this->marge_gauche, $posy);
761 $titre = $outputlangs->transnoentities("PaymentMode").':';
762 $pdf->MultiCell(80, 5, $titre, 0, 'L');
763
764 $pdf->SetFont('', '', $default_font_size - 2);
765 $pdf->SetXY($posxval, $posy);
766 $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);
767 $pdf->MultiCell(80, 5, $lib_mode_reg, 0, 'L');
768
769 $posy = $pdf->GetY() + 2;
770 }
771
772
773 return $posy;
774 }
775
776 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
777 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
788 protected function _tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs)
789 {
790 // phpcs:enable
791 global $conf, $mysoc;
792
793 $default_font_size = pdf_getPDFFontSize($outputlangs);
794
795 $tab2_top = $posy;
796 $tab2_hl = 4;
797 $pdf->SetFont('', '', $default_font_size - 1);
798
799 // Tableau total
800 $col1x = 120;
801 $col2x = 170;
802 if ($this->page_largeur < 210) { // To work with US executive format
803 $col2x -= 20;
804 }
805 $largcol2 = ($this->page_largeur - $this->marge_droite - $col2x);
806
807 $useborder = 0;
808 $index = 0;
809
810 // Total HT
811 $pdf->SetFillColor(255, 255, 255);
812 $pdf->SetXY($col1x, $tab2_top);
813 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalHT"), 0, 'L', 1);
814
815 $total_ht = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? $object->multicurrency_total_ht : $object->total_ht);
816 $pdf->SetXY($col2x, $tab2_top);
817 $pdf->MultiCell($largcol2, $tab2_hl, price($total_ht + (!empty($object->remise) ? $object->remise : 0)), 0, 'R', 1);
818
819 // Show VAT by rates and total
820 $pdf->SetFillColor(248, 248, 248);
821
822 $this->atleastoneratenotnull = 0;
823 foreach ($this->tva as $tvakey => $tvaval) {
824 if ($tvakey > 0) { // On affiche pas taux 0
825 $this->atleastoneratenotnull++;
826
827 $index++;
828 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
829
830 $tvacompl = '';
831
832 if (preg_match('/\*/', $tvakey)) {
833 $tvakey = str_replace('*', '', $tvakey);
834 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
835 }
836
837 $totalvat = $outputlangs->transcountrynoentities("TotalVAT", $mysoc->country_code).' ';
838 $totalvat .= vatrate($tvakey, 1).$tvacompl;
839 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1);
840
841 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
842 $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval), 0, 'R', 1);
843 }
844 }
845 if (!$this->atleastoneratenotnull) { // If no vat at all
846 $index++;
847 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
848 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transcountrynoentities("TotalVAT", $mysoc->country_code), 0, 'L', 1);
849
850 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
851 $pdf->MultiCell($largcol2, $tab2_hl, price($object->total_tva), 0, 'R', 1);
852
853 // Total LocalTax1
854 if (!empty($conf->global->FACTURE_LOCAL_TAX1_OPTION) && $conf->global->FACTURE_LOCAL_TAX1_OPTION == 'localtax1on' && $object->total_localtax1 > 0) {
855 $index++;
856 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
857 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transcountrynoentities("TotalLT1", $mysoc->country_code), 0, 'L', 1);
858 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
859 $pdf->MultiCell($largcol2, $tab2_hl, price($object->total_localtax1), $useborder, 'R', 1);
860 }
861
862 // Total LocalTax2
863 if (!empty($conf->global->FACTURE_LOCAL_TAX2_OPTION) && $conf->global->FACTURE_LOCAL_TAX2_OPTION == 'localtax2on' && $object->total_localtax2 > 0) {
864 $index++;
865 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
866 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transcountrynoentities("TotalLT2", $mysoc->country_code), 0, 'L', 1);
867 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
868 $pdf->MultiCell($largcol2, $tab2_hl, price($object->total_localtax2), $useborder, 'R', 1);
869 }
870 } else {
871 //if (!empty($conf->global->FACTURE_LOCAL_TAX1_OPTION) && $conf->global->FACTURE_LOCAL_TAX1_OPTION=='localtax1on')
872 //{
873 //Local tax 1
874 foreach ($this->localtax1 as $localtax_type => $localtax_rate) {
875 if (in_array((string) $localtax_type, array('2', '4', '6'))) {
876 continue;
877 }
878
879 foreach ($localtax_rate as $tvakey => $tvaval) {
880 if ($tvakey != 0) { // On affiche pas taux 0
881 //$this->atleastoneratenotnull++;
882
883 $index++;
884 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
885
886 $tvacompl = '';
887 if (preg_match('/\*/', $tvakey)) {
888 $tvakey = str_replace('*', '', $tvakey);
889 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
890 }
891 $totalvat = $outputlangs->transcountrynoentities("TotalLT1", $mysoc->country_code).' ';
892 $totalvat .= vatrate(abs($tvakey), 1).$tvacompl;
893 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1);
894
895 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
896 $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1);
897 }
898 }
899 }
900
901 //if (!empty($conf->global->FACTURE_LOCAL_TAX2_OPTION) && $conf->global->FACTURE_LOCAL_TAX2_OPTION=='localtax2on')
902 //{
903 //Local tax 2
904 foreach ($this->localtax2 as $localtax_type => $localtax_rate) {
905 if (in_array((string) $localtax_type, array('2', '4', '6'))) {
906 continue;
907 }
908
909 foreach ($localtax_rate as $tvakey => $tvaval) {
910 if ($tvakey != 0) { // On affiche pas taux 0
911 //$this->atleastoneratenotnull++;
912
913 $index++;
914 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
915
916 $tvacompl = '';
917 if (preg_match('/\*/', $tvakey)) {
918 $tvakey = str_replace('*', '', $tvakey);
919 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
920 }
921 $totalvat = $outputlangs->transcountrynoentities("TotalLT2", $mysoc->country_code).' ';
922 $totalvat .= vatrate(abs($tvakey), 1).$tvacompl;
923 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1);
924
925 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
926 $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval), 0, 'R', 1);
927 }
928 }
929 }
930 }
931
932 // Total TTC
933 $index++;
934 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
935 $pdf->SetTextColor(0, 0, 60);
936 $pdf->SetFillColor(224, 224, 224);
937 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalTTC"), $useborder, 'L', 1);
938
939 $total_ttc = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1) ? $object->multicurrency_total_ttc : $object->total_ttc;
940 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
941 $pdf->MultiCell($largcol2, $tab2_hl, price($total_ttc), $useborder, 'R', 1);
942 $pdf->SetFont('', '', $default_font_size - 1);
943 $pdf->SetTextColor(0, 0, 0);
944
945 $creditnoteamount = 0;
946 $depositsamount = 0;
947 //$creditnoteamount=$object->getSumCreditNotesUsed();
948 //$depositsamount=$object->getSumDepositsUsed();
949 //print "x".$creditnoteamount."-".$depositsamount;exit;
950 $resteapayer = price2num($total_ttc - $deja_regle - $creditnoteamount - $depositsamount, 'MT');
951 if (!empty($object->paye)) {
952 $resteapayer = 0;
953 }
954
955 if ($deja_regle > 0) {
956 // Already paid + Deposits
957 $index++;
958
959 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
960 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("AlreadyPaid"), 0, 'L', 0);
961 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
962 $pdf->MultiCell($largcol2, $tab2_hl, price($deja_regle), 0, 'R', 0);
963
964 $index++;
965 $pdf->SetTextColor(0, 0, 60);
966 $pdf->SetFillColor(224, 224, 224);
967 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
968 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("RemainderToPay"), $useborder, 'L', 1);
969
970 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
971 $pdf->MultiCell($largcol2, $tab2_hl, price($resteapayer), $useborder, 'R', 1);
972
973 $pdf->SetFont('', '', $default_font_size - 1);
974 $pdf->SetTextColor(0, 0, 0);
975 }
976
977 $index++;
978 return ($tab2_top + ($tab2_hl * $index));
979 }
980
981 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
995 protected function _tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop = 0, $hidebottom = 0, $currency = '')
996 {
997 global $conf;
998
999 // Force to disable hidetop and hidebottom
1000 $hidebottom = 0;
1001 if ($hidetop) {
1002 $hidetop = -1;
1003 }
1004
1005 $currency = !empty($currency) ? $currency : $conf->currency;
1006 $default_font_size = pdf_getPDFFontSize($outputlangs);
1007
1008 // Amount in (at tab_top - 1)
1009 $pdf->SetTextColor(0, 0, 0);
1010 $pdf->SetFont('', '', $default_font_size - 2);
1011
1012 if (empty($hidetop)) {
1013 //$titre = $outputlangs->transnoentities("AmountInCurrency", $outputlangs->transnoentitiesnoconv("Currency".$currency));
1014 $pdf->SetXY($this->page_largeur - $this->marge_droite - ($pdf->GetStringWidth($titre) + 3), $tab_top - 4);
1015 $pdf->MultiCell(($pdf->GetStringWidth($titre) + 3), 2, $titre);
1016
1017 //$conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR='230,230,230';
1018 if (!empty($conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR)) {
1019 $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));
1020 }
1021 }
1022
1023 $pdf->SetDrawColor(128, 128, 128);
1024 $pdf->SetFont('', '', $default_font_size - 1);
1025
1026 // Output Rect
1027 $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
1028
1029 foreach ($this->cols as $colKey => $colDef) {
1030 if (!$this->getColumnStatus($colKey)) {
1031 continue;
1032 }
1033
1034 // get title label
1035 $colDef['title']['label'] = !empty($colDef['title']['label']) ? $colDef['title']['label'] : $outputlangs->transnoentities($colDef['title']['textkey']);
1036
1037 // Add column separator
1038 if (!empty($colDef['border-left'])) {
1039 $pdf->line($colDef['xStartPos'], $tab_top, $colDef['xStartPos'], $tab_top + $tab_height);
1040 }
1041
1042 if (empty($hidetop)) {
1043 $pdf->SetXY($colDef['xStartPos'] + $colDef['title']['padding'][3], $tab_top + $colDef['title']['padding'][0]);
1044
1045 $textWidth = $colDef['width'] - $colDef['title']['padding'][3] - $colDef['title']['padding'][1];
1046 $pdf->MultiCell($textWidth, 2, $colDef['title']['label'], '', $colDef['title']['align']);
1047 }
1048 }
1049
1050 if (empty($hidetop)) {
1051 $pdf->line($this->marge_gauche, $tab_top + 5, $this->page_largeur - $this->marge_droite, $tab_top + 5); // line takes a position y in 2nd parameter and 4th parameter
1052 }
1053 }
1054
1055 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1065 protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs)
1066 {
1067 global $langs, $conf, $mysoc;
1068
1069 $ltrdirection = 'L';
1070 if ($outputlangs->trans("DIRECTION") == 'rtl') $ltrdirection = 'R';
1071
1072 // Load translation files required by the page
1073 $outputlangs->loadLangs(array("main", "orders", "companies", "bills", "sendings"));
1074
1075 $default_font_size = pdf_getPDFFontSize($outputlangs);
1076
1077 // Do not add the BACKGROUND as this is for suppliers
1078 //pdf_pagehead($pdf,$outputlangs,$this->page_hauteur);
1079
1080 //Affiche le filigrane brouillon - Print Draft Watermark
1081 /*if($object->statut==0 && getDolGlobalString('COMMANDE_DRAFT_WATERMARK'))
1082 {
1083 pdf_watermark($pdf,$outputlangs,$this->page_hauteur,$this->page_largeur,'mm',getDolGlobalString('COMMANDE_DRAFT_WATERMARK'));
1084 }*/
1085 //Print content
1086
1087 $pdf->SetTextColor(0, 0, 60);
1088 $pdf->SetFont('', 'B', $default_font_size + 3);
1089
1090 $posx = $this->page_largeur - $this->marge_droite - 100;
1091 $posy = $this->marge_haute;
1092 $w = 100;
1093
1094 $pdf->SetXY($this->marge_gauche, $posy);
1095
1096 // Logo
1097 $logo = $conf->mycompany->dir_output.'/logos/'.$this->emetteur->logo;
1098 if ($this->emetteur->logo) {
1099 if (is_readable($logo)) {
1100 $height = pdf_getHeightForLogo($logo);
1101 $pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto)
1102 } else {
1103 $pdf->SetTextColor(200, 0, 0);
1104 $pdf->SetFont('', 'B', $default_font_size - 2);
1105 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound", $logo), 0, 'L');
1106 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorGoToModuleSetup"), 0, 'L');
1107 }
1108 } else {
1109 $text = $this->emetteur->name;
1110 $pdf->MultiCell(100, 4, $outputlangs->convToOutputCharset($text), 0, $ltrdirection);
1111 }
1112
1113 $pdf->SetFont('', 'B', $default_font_size + 3);
1114 $pdf->SetXY($posx, $posy);
1115 $pdf->SetTextColor(0, 0, 60);
1116 $title = $outputlangs->transnoentities("Mo")." ".$outputlangs->convToOutputCharset($object->ref);
1117 $pdf->MultiCell(100, 3, $title, '', 'R');
1118 $posy += 1;
1119
1120 if ($object->ref_supplier) {
1121 $posy += 4;
1122 $pdf->SetFont('', 'B', $default_font_size);
1123 $pdf->SetXY($posx, $posy);
1124 $pdf->SetTextColor(0, 0, 60);
1125 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("RefSupplier")." : ".$outputlangs->convToOutputCharset($object->ref_supplier), '', 'R');
1126 $posy += 1;
1127 }
1128
1129 $pdf->SetFont('', '', $default_font_size - 1);
1130 if (!empty($conf->global->PDF_SHOW_PROJECT_TITLE)) {
1131 $object->fetch_projet();
1132 if (!empty($object->project->ref)) {
1133 $posy += 3;
1134 $pdf->SetXY($posx, $posy);
1135 $pdf->SetTextColor(0, 0, 60);
1136 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("Project")." : ".(empty($object->project->title) ? '' : $object->project->title), '', 'R');
1137 }
1138 }
1139
1140 if (!empty($conf->global->PDF_SHOW_PROJECT)) {
1141 $object->fetch_projet();
1142 if (!empty($object->project->ref)) {
1143 $outputlangs->load("projects");
1144 $posy += 4;
1145 $pdf->SetXY($posx, $posy);
1146 $langs->load("projects");
1147 $pdf->SetTextColor(0, 0, 60);
1148 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Project")." : ".(empty($object->project->ref) ? '' : $object->project->ref), '', 'R');
1149 }
1150 }
1151
1152 if (!empty($object->date_approve)) {
1153 $posy += 5;
1154 $pdf->SetXY($posx, $posy);
1155 $pdf->SetTextColor(0, 0, 60);
1156 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("MoDate")." : ".dol_print_date($object->date_approve, "day", false, $outputlangs, true), '', 'R');
1157 } else {
1158 $posy += 5;
1159 $pdf->SetXY($posx, $posy);
1160 $pdf->SetTextColor(255, 0, 0);
1161 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ToApprove"), '', 'R');
1162 }
1163
1164 // product info
1165 $prodToMake = new Product($this->db);
1166 $resProdToMake = $prodToMake->fetch($object->fk_product);
1167
1168 if ($resProdToMake > 0) {
1169 // ref
1170 $posy += 7;
1171 $pdf->SetFont('', 'B', $default_font_size + 1);
1172 $pdf->SetXY($posx, $posy);
1173 $pdf->SetTextColor(0, 0, 60);
1174 $pdf->MultiCell($w, 3, $prodToMake->ref, '', 'R');
1175
1176 // description
1177 $posy += 5;
1178 $pdf->SetFont('', 'B', $default_font_size + 3);
1179 $pdf->SetXY($posx, $posy);
1180 $pdf->SetTextColor(0, 0, 60);
1181 $pdf->MultiCell($w, 3, html_entity_decode($prodToMake->description), '', 'R', false, 1, '', '', true, 0, false, true, 51, 'T', true);
1182 $posy = $pdf->GetY() - 5;
1183
1184 // dimensions
1185 $array = array_filter(array($prodToMake->length, $prodToMake->width, $prodToMake->height));
1186 $dim = implode("x", $array);
1187 if (!empty($dim)) {
1188 $posy += 5;
1189 $pdf->SetFont('', 'B', $default_font_size + 3);
1190 $pdf->SetXY($posx, $posy);
1191 $pdf->SetTextColor(0, 0, 60);
1192 $pdf->MultiCell($w, 3, $dim, '', 'R');
1193 }
1194 }
1195
1196 $posy += 5;
1197 $pdf->SetFont('', 'B', $default_font_size + 3);
1198 $pdf->SetXY($posx, $posy);
1199 $pdf->SetTextColor(0, 0, 60);
1200 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("QtyToProduce").": " .$object->qty, '', 'R');
1201
1202
1203 $pdf->SetTextColor(0, 0, 60);
1204 $usehourmin = 'day';
1205 if (!empty($conf->global->SUPPLIER_ORDER_USE_HOUR_FOR_DELIVERY_DATE)) {
1206 $usehourmin = 'dayhour';
1207 }
1208 if (!empty($object->delivery_date)) {
1209 $posy += 4;
1210 $pdf->SetXY($posx - 90, $posy);
1211 $pdf->MultiCell(190, 3, $outputlangs->transnoentities("DateDeliveryPlanned")." : ".dol_print_date($object->delivery_date, $usehourmin, false, $outputlangs, true), '', 'R');
1212 }
1213
1214 if ($object->thirdparty->code_fournisseur) {
1215 $posy += 4;
1216 $pdf->SetXY($posx, $posy);
1217 $pdf->SetTextColor(0, 0, 60);
1218 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("SupplierCode")." : ".$outputlangs->transnoentities($object->thirdparty->code_fournisseur), '', 'R');
1219 }
1220
1221 // Get contact
1222 if (!empty($conf->global->DOC_SHOW_FIRST_SALES_REP)) {
1223 $arrayidcontact = $object->getIdContact('internal', 'SALESREPFOLL');
1224 if (count($arrayidcontact) > 0) {
1225 $usertmp = new User($this->db);
1226 $usertmp->fetch($arrayidcontact[0]);
1227 $posy += 4;
1228 $pdf->SetXY($posx, $posy);
1229 $pdf->SetTextColor(0, 0, 60);
1230 $pdf->MultiCell(100, 3, $langs->trans("BuyerName")." : ".$usertmp->getFullName($langs), '', 'R');
1231 }
1232 }
1233
1234 $posy += 1;
1235 $pdf->SetTextColor(0, 0, 60);
1236
1237 $top_shift = 0;
1238 // Show list of linked objects
1239 $current_y = $pdf->getY();
1240 $posy = pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, 100, 3, 'R', $default_font_size);
1241 if ($current_y < $pdf->getY()) {
1242 $top_shift = $pdf->getY() - $current_y;
1243 }
1244
1245 if ($showaddress) {
1246 // Sender properties
1247 $carac_emetteur = '';
1248 // Add internal contact of object if defined
1249 $arrayidcontact = $object->getIdContact('internal', 'SALESREPFOLL');
1250 if (count($arrayidcontact) > 0) {
1251 $object->fetch_user($arrayidcontact[0]);
1252 $labelbeforecontactname = ($outputlangs->transnoentities("FromContactName") != 'FromContactName' ? $outputlangs->transnoentities("FromContactName") : $outputlangs->transnoentities("Name"));
1253 $carac_emetteur .= ($carac_emetteur ? "\n" : '').$labelbeforecontactname.": ".$outputlangs->convToOutputCharset($object->user->getFullName($outputlangs));
1254 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') || getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ' (' : '';
1255 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') && !empty($object->user->office_phone)) ? $object->user->office_phone : '';
1256 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') && getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ', ' : '';
1257 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT') && !empty($object->user->email)) ? $object->user->email : '';
1258 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') || getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ')' : '';
1259 $carac_emetteur .= "\n";
1260 }
1261
1262 $carac_emetteur .= pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, '', 0, 'source', $object);
1263
1264 // Show sender
1265 $posy = 42 + $top_shift;
1266 $posx = $this->marge_gauche;
1267 if (!empty($conf->global->MAIN_INVERT_SENDER_RECIPIENT)) {
1268 $posx = $this->page_largeur - $this->marge_droite - 80;
1269 }
1270 $hautcadre = 40;
1271
1272 // Show sender frame
1273 $pdf->SetTextColor(0, 0, 0);
1274 $pdf->SetFont('', '', $default_font_size - 2);
1275 $pdf->SetXY($posx, $posy - 5);
1276 $pdf->MultiCell(80, 5, $outputlangs->transnoentities("BillFrom"), 0, $ltrdirection);
1277 $pdf->SetXY($posx, $posy);
1278 $pdf->SetFillColor(230, 230, 230);
1279 $pdf->MultiCell(82, $hautcadre, "", 0, 'R', 1);
1280 $pdf->SetTextColor(0, 0, 60);
1281
1282 // Show sender name
1283 $pdf->SetXY($posx + 2, $posy + 3);
1284 $pdf->SetFont('', 'B', $default_font_size);
1285 $pdf->MultiCell(80, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, $ltrdirection);
1286 $posy = $pdf->getY();
1287
1288 // Show sender information
1289 $pdf->SetXY($posx + 2, $posy);
1290 $pdf->SetFont('', '', $default_font_size - 1);
1291 $pdf->MultiCell(80, 4, $carac_emetteur, 0, $ltrdirection);
1292
1293
1294
1295 // If CUSTOMER contact defined on order, we use it. Note: Even if this is a supplier object, the code for external contat that follow order is 'CUSTOMER'
1296 $usecontact = false;
1297 $arrayidcontact = $object->getIdContact('external', 'CUSTOMER');
1298 if (count($arrayidcontact) > 0) {
1299 $usecontact = true;
1300 $result = $object->fetch_contact($arrayidcontact[0]);
1301 }
1302
1303 // Recipient name
1304 if ($usecontact && ($object->contact->fk_soc != $object->thirdparty->id && (!isset($conf->global->MAIN_USE_COMPANY_NAME_OF_CONTACT) || !empty($conf->global->MAIN_USE_COMPANY_NAME_OF_CONTACT)))) {
1305 $thirdparty = $object->contact;
1306 } else {
1307 $thirdparty = $object->thirdparty;
1308 }
1309
1310 //$carac_client_name = pdfBuildThirdpartyName($thirdparty, $outputlangs);
1311
1312 //$carac_client = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, ($usecontact ? $object->contact : ''), $usecontact, 'target', $object);
1313
1314 // Show recipient
1315 //$widthrecbox = 100;
1316 //if ($this->page_largeur < 210) {
1317 // $widthrecbox = 84; // To work with US executive format
1318 //}
1319 //$posy = 42 + $top_shift;
1320 //$posx = $this->page_largeur - $this->marge_droite - $widthrecbox;
1321 //if (!empty($conf->global->MAIN_INVERT_SENDER_RECIPIENT)) {
1322 // $posx = $this->marge_gauche;
1323 //}
1324 //
1326 //$pdf->SetTextColor(0, 0, 0);
1327 //$pdf->SetFont('', '', $default_font_size - 2);
1328 //$pdf->SetXY($posx + 2, $posy - 5);
1329 //$pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillTo"), 0, $ltrdirection);
1330 //$pdf->Rect($posx, $posy, $widthrecbox, $hautcadre);
1331 //
1333 //$pdf->SetXY($posx + 2, $posy + 3);
1334 //$pdf->SetFont('', 'B', $default_font_size);
1335 //$pdf->MultiCell($widthrecbox, 4, $carac_client_name, 0, $ltrdirection);
1336 //
1337 //$posy = $pdf->getY();
1338 //
1340 //$pdf->SetFont('', '', $default_font_size - 1);
1341 //$pdf->SetXY($posx + 2, $posy);
1342 //$pdf->MultiCell($widthrecbox, 4, $carac_client, 0, $ltrdirection);
1343 }
1344
1345 return $top_shift;
1346 }
1347
1348 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1358 protected function _pagefoot(&$pdf, $object, $outputlangs, $hidefreetext = 0)
1359 {
1360 $showdetails = getDolGlobalInt('MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS', 0);
1361 return pdf_pagefoot($pdf, $outputlangs, 'SUPPLIER_ORDER_FREE_TEXT', $this->emetteur, $this->marge_basse, $this->marge_gauche, $this->page_hauteur, $object, $showdetails, $hidefreetext);
1362 }
1363
1364
1365
1376 public function defineColumnField($object, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0)
1377 {
1378 global $conf, $hookmanager;
1379
1380 // Default field style for content
1381 $this->defaultContentsFieldsStyle = array(
1382 'align' => 'R', // R,C,L
1383 'padding' => array(1, 0.5, 1, 0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1384 );
1385
1386 // Default field style for content
1387 $this->defaultTitlesFieldsStyle = array(
1388 'align' => 'C', // R,C,L
1389 'padding' => array(0.5, 0, 0.5, 0), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1390 );
1391
1392 /*
1393 * For exemple
1394 $this->cols['theColKey'] = array(
1395 'rank' => $rank, // int : use for ordering columns
1396 'width' => 20, // the column width in mm
1397 'title' => array(
1398 'textkey' => 'yourLangKey', // if there is no label, yourLangKey will be translated to replace label
1399 'label' => ' ', // the final label : used fore final generated text
1400 'align' => 'L', // text alignement : R,C,L
1401 'padding' => array(0.5,0.5,0.5,0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1402 ),
1403 'content' => array(
1404 'align' => 'L', // text alignement : R,C,L
1405 'padding' => array(0.5,0.5,0.5,0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1406 ),
1407 );
1408 */
1409 $rank = 0;
1410 $this->cols['code'] = array(
1411 'rank' => $rank,
1412 'status' => true,
1413 'width' => 35, // in mm
1414 'title' => array(
1415 'textkey' => 'Ref'
1416 ),
1417 'border-left' => true, // add left line separator
1418 );
1419
1420 $rank = 1; // do not use negative rank
1421 $this->cols['desc'] = array(
1422 'rank' => $rank,
1423 'width' => false, // only for desc
1424 'status' => true,
1425 'title' => array(
1426 'textkey' => 'Designation', // use lang key is usefull in somme case with module
1427 'align' => 'L',
1428 // 'textkey' => 'yourLangKey', // if there is no label, yourLangKey will be translated to replace label
1429 // 'label' => ' ', // the final label
1430 'padding' => array(0.5, 1, 0.5, 1.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1431 ),
1432 'border-left' => true,
1433 'content' => array(
1434 'align' => 'L',
1435 'padding' => array(1, 0.5, 1, 1.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1436 ),
1437 );
1438
1439 $rank = $rank + 10;
1440 $this->cols['photo'] = array(
1441 'rank' => $rank,
1442 'width' => (empty($conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH) ? 20 : $conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH), // in mm
1443 'status' => false,
1444 'title' => array(
1445 'textkey' => 'Photo',
1446 'label' => ' '
1447 ),
1448 'content' => array(
1449 'padding' => array(0, 0, 0, 0), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1450 ),
1451 'border-left' => false, // remove left line separator
1452 );
1453
1454 if (!empty($conf->global->MAIN_GENERATE_ORDERS_WITH_PICTURE)) {
1455 $this->cols['photo']['status'] = true;
1456 }
1457
1458 $rank = $rank + 10;
1459 $this->cols['dim'] = array(
1460 'rank' => $rank,
1461 'status' => true,
1462 'width' => 25, // in mm
1463 'title' => array(
1464 'textkey' => 'Size'
1465 ),
1466 'border-left' => true, // add left line separator
1467 );
1468
1469 $rank = $rank + 10;
1470 $this->cols['qty'] = array(
1471 'rank' => $rank,
1472 'width' => 16, // in mm
1473 'status' => true,
1474 'title' => array(
1475 'textkey' => 'Qty'
1476 ),
1477 'border-left' => true, // add left line separator
1478 );
1479
1480 $rank = $rank + 10;
1481 $this->cols['qtytot'] = array(
1482 'rank' => $rank,
1483 'width' => 25, // in mm
1484 'status' => true,
1485 'title' => array(
1486 'textkey' => 'QtyTot'
1487 ),
1488 'border-left' => true, // add left line separator
1489 );
1490
1491 // Add extrafields cols
1492 if (!empty($object->lines)) {
1493 $line = reset($object->lines);
1494 $this->defineColumnExtrafield($line, $outputlangs, $hidedetails);
1495 }
1496
1497 $parameters = array(
1498 'object' => $object,
1499 'outputlangs' => $outputlangs,
1500 'hidedetails' => $hidedetails,
1501 'hidedesc' => $hidedesc,
1502 'hideref' => $hideref
1503 );
1504
1505 $reshook = $hookmanager->executeHooks('defineColumnField', $parameters, $this); // Note that $object may have been modified by hook
1506 if ($reshook < 0) {
1507 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1508 } elseif (empty($reshook)) {
1509 $this->cols = array_replace($this->cols, $hookmanager->resArray); // array_replace is used to preserve keys
1510 } else {
1511 $this->cols = $hookmanager->resArray;
1512 }
1513 }
1514}
Class for BOM.
Definition bom.class.php:39
prepareArrayColumnField($object, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0)
Prepare Array Column Field.
getColumnStatus($colKey)
get column status from column key
printStdColumnContent($pdf, &$curY, $colKey, $columnText='')
print standard column content
printRect($pdf, $x, $y, $l, $h, $hidetop=0, $hidebottom=0)
Rect pdf.
defineColumnExtrafield($object, $outputlangs, $hidedetails=0)
Define Array Column Field for extrafields.
Class to manage hooks.
Parent class for mos models.
Class to manage products or services.
Class to manage translations.
Class to manage Dolibarr users.
Class to generate the manufacturing orders with the vinci model.
_tableau_info(&$pdf, $object, $posy, $outputlangs)
Show miscellaneous information (payment mode, payment term, ...)
_pagehead(&$pdf, $object, $showaddress, $outputlangs)
Show top header of page.
_tableau_versements(&$pdf, $object, $posy, $outputlangs)
Show payments table.
_pagefoot(&$pdf, $object, $outputlangs, $hidefreetext=0)
Show footer of page.
__construct($db)
Constructor.
_tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop=0, $hidebottom=0, $currency='')
Show table for lines.
_tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs)
Show total to pay.
defineColumnField($object, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0)
Define Array Column Field.
write_file($object, $outputlangs='', $srctemplatepath='', $hidedetails=0, $hidedesc=0, $hideref=0)
Function to build pdf onto disk.
print $script_file $mode $langs defaultlang(is_numeric($duration_value) ? " delay=". $duration_value :"").(is_numeric($duration_value2) ? " after cd cd cd description as description
Only used if Module[ID]Desc translation string is not found.
if(!function_exists( 'dolEscapeXML')) convertBackOfficeMediasLinksToPublicLinks($notetoshow)
Convert links to local wrapper to medias files into a string into a public external URL readable on i...
vatrate($rate, $addpercent=false, $info_bits=0, $usestarfornpr=0, $html=0)
Return a string with VAT rate label formated for view output Used into pdf and HTML pages.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dolChmod($filepath, $newmask='')
Change mod of a file.
getDolGlobalInt($key, $default=0)
Return dolibarr global constant int value.
dol_concatdesc($text1, $text2, $forxml=false, $invert=false)
Concat 2 descriptions with a new line between them (second operand after first one with appropriate n...
complete_substitutions_array(&$substitutionarray, $outputlangs, $object=null, $parameters=null, $callfunc="completesubstitutionarray")
Complete the $substitutionarray with more entries coming from external module that had set the "subst...
make_substitutions($text, $substitutionarray, $outputlangs=null, $converttextinhtmlifnecessary=0)
Make substitution into a text string, replacing keys with vals from $substitutionarray (oldval=>newva...
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
dol_htmlentitiesbr($stringtoencode, $nl2brmode=0, $pagecodefrom='UTF-8', $removelasteolbr=1)
This function is called to encode a string into a HTML string but differs from htmlentities because a...
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
pdf_getSizeForImage($realpath)
Return dimensions to use for images onto PDF checking that width and height are not higher than maxim...
Definition pdf.lib.php:2529
pdf_getPDFFontSize($outputlangs)
Return font size to use for PDF generation.
Definition pdf.lib.php:289
pdf_getFormat(Translate $outputlangs=null, $mode='setup')
Return array with format properties of default PDF format.
Definition pdf.lib.php:85
pdf_getHeightForLogo($logo, $url=false)
Return height to use for Logo onto PDF.
Definition pdf.lib.php:314
pdf_pagefoot(&$pdf, $outputlangs, $paramfreetext, $fromcompany, $marge_basse, $marge_gauche, $page_hauteur, $object, $showdetails=0, $hidefreetext=0, $page_largeur=0, $watermark='')
Show footer of page for PDF generation.
Definition pdf.lib.php:1010
pdf_writeLinkedObjects(&$pdf, $object, $outputlangs, $posx, $posy, $w, $h, $align, $default_font_size)
Show linked objects for PDF generation.
Definition pdf.lib.php:1338
pdf_getPDFFont($outputlangs)
Return font name to use for PDF generation.
Definition pdf.lib.php:266
pdf_build_address($outputlangs, $sourcecompany, $targetcompany='', $targetcontact='', $usecontact=0, $mode='source', $object=null)
Return a string with full address formated for output on documents.
Definition pdf.lib.php:435
pdf_getSubstitutionArray($outputlangs, $exclude=null, $object=null, $onlykey=0, $include=null)
Return array of possible substitutions for PDF content (without external module substitutions).
Definition pdf.lib.php:758
pdf_getInstance($format='', $metric='mm', $pagetype='P')
Return a PDF instance object.
Definition pdf.lib.php:127
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition repair.php:120
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:123