dolibarr 23.0.3
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-2025 Frédéric France <frederic.france@free.fr>
9 * Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
10 * Copyright (C) 2024 Josep Lluís Amador <joseplluis@lliuretic.cat>
11 * Copyright (C) 2024 Nick Fragoulis
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program. If not, see <https://www.gnu.org/licenses/>.
25 * or see https://www.gnu.org/
26 */
27
34require_once DOL_DOCUMENT_ROOT.'/core/modules/mrp/modules_mo.php';
35require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
36require_once DOL_DOCUMENT_ROOT.'/bom/class/bom.class.php';
37require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
38require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
39require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
40require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
41
42
47{
51 public $db;
52
56 public $name;
57
61 public $description;
62
66 public $update_main_doc_field;
67
71 public $type;
72
77 public $version = 'dolibarr';
78
79
85 public function __construct($db)
86 {
87 global $langs, $mysoc;
88
89 // Load translation files required by the page
90 $langs->loadLangs(array("main", "bills", "mrp"));
91
92 $this->db = $db;
93 $this->name = "vinci";
94 $this->description = $langs->trans('DocumentModelStandardPDF');
95 $this->update_main_doc_field = 1; // Save the name of generated file as the main doc when generating a doc with this template
96
97 // Page size for A4 format
98 $this->type = 'pdf';
99 $formatarray = pdf_getFormat();
100 $this->page_largeur = $formatarray['width'];
101 $this->page_hauteur = $formatarray['height'];
102 $this->format = array($this->page_largeur, $this->page_hauteur);
103 $this->marge_gauche = getDolGlobalInt('MAIN_PDF_MARGIN_LEFT', 10);
104 $this->marge_droite = getDolGlobalInt('MAIN_PDF_MARGIN_RIGHT', 10);
105 $this->marge_haute = getDolGlobalInt('MAIN_PDF_MARGIN_TOP', 10);
106 $this->marge_basse = getDolGlobalInt('MAIN_PDF_MARGIN_BOTTOM', 10);
107 $this->corner_radius = getDolGlobalInt('MAIN_PDF_FRAME_CORNER_RADIUS', 0);
108 $this->option_logo = 1; // Display logo
109 $this->option_multilang = 1; //Available in several languages
110 $this->option_escompte = 0; // Displays if there has been a discount
111 $this->option_credit_note = 0; // Support credit notes
112 $this->option_freetext = 1; // Support add of a personalised text
113 $this->option_draft_watermark = 1; // Support add of a watermark on drafts
114
115 // Define position of columns
116 $this->posxdesc = $this->marge_gauche + 1; // For module retrocompatibility support during PDF transition: TODO remove this at the end
117
118 if ($mysoc === null) {
119 dol_syslog(get_class($this).'::__construct() Global $mysoc should not be null.'. getCallerInfoString(), LOG_ERR);
120 return;
121 }
122
123 // Get source company
124 $this->emetteur = $mysoc;
125 if (empty($this->emetteur->country_code)) {
126 $this->emetteur->country_code = substr($langs->defaultlang, -2); // By default, if was not defined
127 }
128 }
129
130
131 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
143 public function write_file($object, $outputlangs, $srctemplatepath = '', $hidedetails = 0, $hidedesc = 0, $hideref = 0)
144 {
145 // phpcs:enable
146 global $user, $langs, $conf, $hookmanager, $mysoc;
147
148 if (!is_object($outputlangs)) {
149 $outputlangs = $langs;
150 }
151 // For backward compatibility with FPDF, force output charset to ISO, because FPDF expect text to be encoded in ISO
152 if (getDolGlobalString('MAIN_USE_FPDF')) {
153 $outputlangs->charset_output = 'ISO-8859-1';
154 }
155
156 // Load translation files required by the page
157 $outputlangs->loadLangs(array("main", "orders", "companies", "bills", "dict", "products"));
158
159 global $outputlangsbis;
160 $outputlangsbis = null;
161 if (getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE') && $outputlangs->defaultlang != getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE')) {
162 $outputlangsbis = new Translate('', $conf);
163 $outputlangsbis->setDefaultLang(getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE'));
164 $outputlangsbis->loadLangs(array("main", "orders", "companies", "bills", "dict", "products"));
165 }
166
167 if (!isset($object->lines) || !is_array($object->lines)) {
168 $object->lines = array();
169 }
170
171 $nblines = count($object->lines);
172
173 $hidetop = 0;
174 if (getDolGlobalString('MAIN_PDF_DISABLE_COL_HEAD_TITLE')) {
175 $hidetop = getDolGlobalString('MAIN_PDF_DISABLE_COL_HEAD_TITLE');
176 }
177
178 if ($conf->mrp->dir_output) {
179 $object->fetch_thirdparty();
180
181 $deja_regle = 0;
182 $amount_credit_notes_included = 0;
183 $amount_deposits_included = 0;
184 //$amount_credit_notes_included = $object->getSumCreditNotesUsed();
185 //$amount_deposits_included = $object->getSumDepositsUsed();
186
187 // Definition of $dir and $file
188 if ($object->specimen) {
189 $dir = $conf->mrp->dir_output;
190 $file = $dir."/SPECIMEN.pdf";
191 } else {
192 $objectref = dol_sanitizeFileName($object->ref);
193 $dir = $conf->mrp->dir_output.'/'.$objectref;
194 $file = $dir."/".$objectref.".pdf";
195 }
196
197 if (!file_exists($dir)) {
198 if (dol_mkdir($dir) < 0) {
199 $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
200 return 0;
201 }
202 }
203
204 if (file_exists($dir)) {
205 // Add pdfgeneration hook
206 if (!is_object($hookmanager)) {
207 include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
208 $hookmanager = new HookManager($this->db);
209 }
210 $hookmanager->initHooks(array('pdfgeneration'));
211 $parameters = array('file' => $file, 'object' => $object, 'outputlangs' => $outputlangs);
212 global $action;
213 $reshook = $hookmanager->executeHooks('beforePDFCreation', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
214
215 $nblines = count($object->lines);
216
217 $pdf = pdf_getInstance($this->format);
218 $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance
219 $heightforinfotot = 50; // Height reserved to output the info and total part
220 $heightforfreetext = getDolGlobalInt('MAIN_PDF_FREETEXT_HEIGHT', 5); // Height reserved to output the free text on last page
221 $heightforfooter = $this->marge_basse + 8; // Height reserved to output the footer (value include bottom margin)
222 if (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS')) {
223 $heightforfooter += 6;
224 }
225 $pdf->setAutoPageBreak(true, 0);
226
227 if (class_exists('TCPDF')) {
228 $pdf->setPrintHeader(false);
229 $pdf->setPrintFooter(false);
230 }
231 $pdf->SetFont(pdf_getPDFFont($outputlangs));
232 // Set path to the background PDF File
233 if (getDolGlobalString('MAIN_ADD_PDF_BACKGROUND')) {
234 $pagecount = $pdf->setSourceFile($conf->mycompany->dir_output.'/' . getDolGlobalString('MAIN_ADD_PDF_BACKGROUND'));
235 $tplidx = $pdf->importPage(1);
236 }
237
238 $pdf->Open();
239 $pagenb = 0;
240 $pdf->SetDrawColor(128, 128, 128);
241
242 $pdf->SetTitle($outputlangs->convToOutputCharset($object->ref));
243 $pdf->SetSubject($outputlangs->transnoentities("ManufacturingOrder"));
244 $pdf->SetCreator("Dolibarr ".DOL_VERSION);
245 $pdf->SetAuthor($outputlangs->convToOutputCharset($user->getFullName($outputlangs)));
246 $key_word=$outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("ManufacturingOrder");
247 if (isset($object->thirdparty->name) && $object->thirdparty->name !== "") {
248 $key_word.=" ".$outputlangs->convToOutputCharset($object->thirdparty->name);
249 }
250 $pdf->SetKeyWords($key_word);
251 if (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) {
252 $pdf->SetCompression(false);
253 }
254
255 // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
256 $pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite); // Left, Top, Right
257
258 // Does we have at least one line with discount $this->atleastonediscount
259
260 // New page
261 $pdf->AddPage();
262 if (!empty($tplidx)) {
263 $pdf->useTemplate($tplidx);
264 }
265 $pagenb++;
266 $top_shift = $this->_pagehead($pdf, $object, 1, $outputlangs);
267 $pdf->SetFont('', '', $default_font_size - 1);
268 $pdf->MultiCell(0, 3, ''); // Set interline to 3
269 $pdf->SetTextColor(0, 0, 0);
270
271 $tab_top = 90 + $top_shift;
272 $tab_top_newpage = (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD') ? 42 + $top_shift : 10);
273
274 $tab_height = $this->page_hauteur - $tab_top - $heightforfooter - $heightforfreetext;
275
276
277 // Affiche notes
278 $notetoshow = empty($object->note_public) ? '' : $object->note_public;
279
280 // Extrafields in note
281 $extranote = $this->getExtrafieldsInHtml($object, $outputlangs);
282 if (!empty($extranote)) {
283 $notetoshow = dol_concatdesc($notetoshow, $extranote);
284 }
285
286 $pagenb = $pdf->getPage();
287 if ($notetoshow) {
288 $tab_width = $this->page_largeur - $this->marge_gauche - $this->marge_droite;
289 $pageposbeforenote = $pagenb;
290
291 $substitutionarray = pdf_getSubstitutionArray($outputlangs, null, $object);
292 complete_substitutions_array($substitutionarray, $outputlangs, $object);
293 $notetoshow = make_substitutions($notetoshow, $substitutionarray, $outputlangs);
294 $notetoshow = convertBackOfficeMediasLinksToPublicLinks($notetoshow);
295
296 $tab_top -= 2;
297
298 $pdf->startTransaction();
299
300 $pdf->SetFont('', '', $default_font_size - 1);
301 $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top, dol_htmlentitiesbr($notetoshow), 0, 1);
302 // Description
303 $pageposafternote = $pdf->getPage();
304 $posyafter = $pdf->GetY();
305
306 if ($pageposafternote > $pageposbeforenote) {
307 $pdf->rollbackTransaction(true);
308
309 // prepar pages to receive notes
310 while ($pagenb < $pageposafternote) {
311 $pdf->AddPage();
312 $pagenb++;
313 if (!empty($tplidx)) {
314 $pdf->useTemplate($tplidx);
315 }
316 if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
317 $this->_pagehead($pdf, $object, 0, $outputlangs);
318 }
319 // $this->_pagefoot($pdf,$object,$outputlangs,1);
320 $pdf->setTopMargin($tab_top_newpage);
321 // The only function to edit the bottom margin of current page to set it.
322 $pdf->setPageOrientation('', true, $heightforfooter + $heightforfreetext);
323 }
324
325 // back to start
326 $pdf->setPage($pageposbeforenote);
327 $pdf->setPageOrientation('', true, $heightforfooter + $heightforfreetext);
328 $pdf->SetFont('', '', $default_font_size - 1);
329 $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top, dol_htmlentitiesbr($notetoshow), 0, 1);
330 $pageposafternote = $pdf->getPage();
331
332 $posyafter = $pdf->GetY();
333
334 if ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + 20))) { // There is no space left for total+free text
335 $pdf->AddPage('', '', true);
336 $pagenb++;
337 $pageposafternote++;
338 $pdf->setPage($pageposafternote);
339 $pdf->setTopMargin($tab_top_newpage);
340 // The only function to edit the bottom margin of current page to set it.
341 $pdf->setPageOrientation('', true, $heightforfooter + $heightforfreetext);
342 //$posyafter = $tab_top_newpage;
343 }
344
345
346 // apply note frame to previous pages
347 $i = $pageposbeforenote;
348 while ($i < $pageposafternote) {
349 $pdf->setPage($i);
350
351 $pdf->SetDrawColor(128, 128, 128);
352 // Draw note frame
353 if ($i > $pageposbeforenote) {
354 $height_note = $this->page_hauteur - ($tab_top_newpage + $heightforfooter);
355 $pdf->RoundedRect($this->marge_gauche, $tab_top_newpage - 1, $tab_width, $height_note + 2, $this->corner_radius, '1234', 'D');
356 } else {
357 $height_note = $this->page_hauteur - ($tab_top + $heightforfooter);
358 $pdf->RoundedRect($this->marge_gauche, $tab_top - 1, $tab_width, $height_note + 2, $this->corner_radius, '1234', 'D');
359 }
360
361 // Add footer
362 $pdf->setPageOrientation('', true, 0); // The only function to edit the bottom margin of current page to set it.
363 $this->_pagefoot($pdf, $object, $outputlangs, 1);
364
365 $i++;
366 }
367
368 // apply note frame to last page
369 $pdf->setPage($pageposafternote);
370 if (!empty($tplidx)) {
371 $pdf->useTemplate($tplidx);
372 }
373 if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
374 $this->_pagehead($pdf, $object, 0, $outputlangs);
375 }
376 $height_note = $posyafter - $tab_top_newpage;
377 $pdf->RoundedRect($this->marge_gauche, $tab_top_newpage - 1, $tab_width, $height_note + 2, $this->corner_radius, '1234', 'D');
378 } else {
379 // No pagebreak
380 $pdf->commitTransaction();
381 $posyafter = $pdf->GetY();
382 $height_note = $posyafter - $tab_top;
383 $pdf->RoundedRect($this->marge_gauche, $tab_top - 1, $tab_width, $height_note + 2, $this->corner_radius, '1234', 'D');
384
385
386 if ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + 20))) {
387 // not enough space, need to add page
388 $pdf->AddPage('', '', true);
389 $pagenb++;
390 $pageposafternote++;
391 $pdf->setPage($pageposafternote);
392 if (!empty($tplidx)) {
393 $pdf->useTemplate($tplidx);
394 }
395 if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
396 $this->_pagehead($pdf, $object, 0, $outputlangs);
397 }
398
399 $posyafter = $tab_top_newpage;
400 }
401 }
402
403 $tab_height -= $height_note;
404 $tab_top = $posyafter + 6;
405 } else {
406 $height_note = 0;
407 }
408
409 $nexY = $tab_top + 5;
410
411 // Use new auto column system
412 $this->prepareArrayColumnField($object, $outputlangs, $hidedetails, $hidedesc, $hideref);
413
414 // Loop on each lines
415 $pageposbeforeprintlines = $pdf->getPage();
416 $pagenb = $pageposbeforeprintlines;
417
418 $bom = new BOM($this->db);
419 $bom -> fetch($object->fk_bom);
420
421 $nblines = count($bom->lines);
422
423 for ($i = 0; $i < $nblines; $i++) {
424 $curY = $nexY;
425 $pdf->SetFont('', '', $default_font_size - 1); // Into loop to work with multipage
426 $pdf->SetTextColor(0, 0, 0);
427
428 $prod = new Product($this->db);
429 $prod->fetch($bom->lines[$i]->fk_product);
430
431 $pdf->setTopMargin($tab_top_newpage);
432 $pdf->setPageOrientation('', true, $heightforfooter + $heightforfreetext + $heightforinfotot); // The only function to edit the bottom margin of current page to set it.
433 $pageposbefore = $pdf->getPage();
434
435 $showpricebeforepagebreak = 1;
436 $posYAfterImage = 0;
437 $posYAfterDescription = 0;
438
439 // Description of product line
440 $curX = $this->posxdesc - 1;
441 $showpricebeforepagebreak = 1;
442
443 if ($this->getColumnStatus('code')) {
444 $pdf->startTransaction(); //description
445 //$this->printColDescContent($pdf, $curY, 'code', $object, $i, $outputlangs, $hideref, $hidedesc, $showsupplierSKU);
446 $this->printStdColumnContent($pdf, $curY, 'code', $prod->ref);
447
448 $pageposafter = $pdf->getPage();
449 $posyafter = $pdf->GetY();
450 if ($pageposafter > $pageposbefore) { // There is a pagebreak
451 $pdf->rollbackTransaction(true);
452
453 //$this->printColDescContent($pdf, $curY, 'code', $object, $i, $outputlangs, $hideref, $hidedesc, $showsupplierSKU);
454 $this->printStdColumnContent($pdf, $curY, 'code', $prod->ref);
455
456 $pageposafter = $pdf->getPage();
457 $posyafter = $pdf->GetY();
458 } elseif ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforinfotot))) { // There is no space left for total+free text
459 if ($i == ($nblines - 1)) { // No more lines, and no space left to show total, so we create a new page
460 $pdf->AddPage('', '', true);
461 if (!empty($tplidx)) {
462 $pdf->useTemplate($tplidx);
463 }
464 //if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) $this->_pagehead($pdf, $object, 0, $outputlangs);
465 $pdf->setPage($pageposafter + 1);
466 } else {
467 // We found a page break
468 // Allows data in the first page if description is long enough to break in multiples pages
469 if (getDolGlobalString('MAIN_PDF_DATA_ON_FIRST_PAGE')) {
470 $showpricebeforepagebreak = 1;
471 } else {
472 $showpricebeforepagebreak = 0;
473 }
474 }
475 } else { // No pagebreak
476 $pdf->commitTransaction();
477 }
478 $posYAfterDescription = $pdf->GetY();
479 }
480
481 $nexY = $pdf->GetY();
482 $pageposafter = $pdf->getPage();
483 $pdf->setPage($pageposbefore);
484 $pdf->setTopMargin($this->marge_haute);
485 $pdf->setPageOrientation('', true, 0); // The only function to edit the bottom margin of current page to set it.
486
487 // We suppose that a too long description is moved completely on next page
488 if ($pageposafter > $pageposbefore && empty($showpricebeforepagebreak)) {
489 $pdf->setPage($pageposafter);
490 $curY = $tab_top_newpage;
491 }
492
493 if ($this->getColumnStatus('desc')) {
494 $pdf->startTransaction(); //description
495 $des = $prod -> description;
496 $descr = $des;//implode("<br>", $des);
497
498 $this->printStdColumnContent($pdf, $curY, 'desc', $descr);
499
500 $pageposafter = $pdf->getPage();
501 $posyafter = $pdf->GetY();
502 if ($pageposafter > $pageposbefore) { // There is a pagebreak
503 $pdf->rollbackTransaction(true);
504
505 $this->printStdColumnContent($pdf, $curY, 'desc', $descr);
506
507 $pageposafter = $pdf->getPage();
508 $posyafter = $pdf->GetY();
509 } elseif ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforinfotot))) { // There is no space left for total+free text
510 if ($i == ($nblines - 1)) { // No more lines, and no space left to show total, so we create a new page
511 $pdf->AddPage('', '', true);
512 if (!empty($tplidx)) {
513 $pdf->useTemplate($tplidx);
514 }
515 //if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) $this->_pagehead($pdf, $object, 0, $outputlangs);
516 $pdf->setPage($pageposafter + 1);
517 } else {
518 // We found a page break
519 // Allows data in the first page if description is long enough to break in multiples pages
520 if (getDolGlobalString('MAIN_PDF_DATA_ON_FIRST_PAGE')) {
521 $showpricebeforepagebreak = 1;
522 } else {
523 $showpricebeforepagebreak = 0;
524 }
525 }
526 } else { // No pagebreak
527 $pdf->commitTransaction();
528 }
529 $posYAfterDescription = max($posYAfterDescription, $pdf->GetY());
530 }
531
532 $nexY = max($nexY, $pdf->GetY());
533 $pageposafter = $pdf->getPage();
534 $pdf->setPage($pageposbefore);
535 $pdf->setTopMargin($this->marge_haute);
536 $pdf->setPageOrientation('', true, 0); // The only function to edit the bottom margin of current page to set it.
537
538 // We suppose that a too long description is moved completely on next page
539 if ($pageposafter > $pageposbefore && empty($showpricebeforepagebreak)) {
540 $pdf->setPage($pageposafter);
541 $curY = $tab_top_newpage;
542 }
543
544 $pdf->SetFont('', '', $default_font_size - 1); // On repositionne la police par default
545
546 // Quantity
547 // Enough for 6 chars
548 if ($this->getColumnStatus('qty')) {
549 $qty = $bom->lines[$i]->qty;
550 $this->printStdColumnContent($pdf, $curY, 'qty', (string) $qty);
551 $nexY = max($pdf->GetY(), $nexY);
552 }
553
554 // Quantity
555 // Enough for 6 chars
556 if ($this->getColumnStatus('qtytot')) {
557 $qtytot = $object->qty * $bom->lines[$i]->qty;
558 $this->printStdColumnContent($pdf, $curY, 'qtytot', (string) $qtytot);
559 $nexY = max($pdf->GetY(), $nexY);
560 }
561
562 // Dimensions
563 if ($this->getColumnStatus('dim')) {
564 $array = array_filter(array($prod->length, $prod->width, $prod->height));
565 $dim = implode("x", $array);
566 $this->printStdColumnContent($pdf, $curY, 'dim', $dim);
567 $nexY = max($pdf->GetY(), $nexY);
568 }
569 }
570
571
572 // Show square
573 if ($pagenb == $pageposbeforeprintlines) {
574 $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, $hidetop, 0, $object->multicurrency_code);
575 $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
576 } else {
577 $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 1, 0, $object->multicurrency_code);
578 $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
579 }
580
581 // Affiche zone infos
582 $posy = $this->_tableau_info($pdf, $object, $bottomlasttab, $outputlangs);
583
584 // Affiche zone totaux
585 //$posy = $this->_tableau_tot($pdf, $object, $deja_regle, $bottomlasttab, $outputlangs);
586
587 // Affiche zone versements
588 if ($deja_regle || $amount_credit_notes_included || $amount_deposits_included) {
589 $posy = $this->_tableau_versements($pdf, $object, $posy, $outputlangs);
590 }
591
592 // Pied de page
593 $this->_pagefoot($pdf, $object, $outputlangs);
594 if (method_exists($pdf, 'AliasNbPages')) {
595 $pdf->AliasNbPages(); // @phan-suppress-current-line PhanUndeclaredMethod
596 }
597
598 $pdf->Close();
599
600 $pdf->Output($file, 'F');
601
602 // Add pdfgeneration hook
603 $hookmanager->initHooks(array('pdfgeneration'));
604 $parameters = array('file' => $file, 'object' => $object, 'outputlangs' => $outputlangs);
605 global $action;
606 $reshook = $hookmanager->executeHooks('afterPDFCreation', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
607 $this->warnings = $hookmanager->warnings;
608 if ($reshook < 0) {
609 $this->error = $hookmanager->error;
610 $this->errors = $hookmanager->errors;
611 dolChmod($file);
612 return -1;
613 }
614
615 dolChmod($file);
616
617 $this->result = array('fullpath' => $file);
618
619 return 1; // No error
620 } else {
621 $this->error = $langs->trans("ErrorCanNotCreateDir", $dir);
622 return 0;
623 }
624 } else {
625 $this->error = $langs->trans("ErrorConstantNotDefined", "SUPPLIER_OUTPUTDIR");
626 return 0;
627 }
628 }
629
630 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
631 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
641 protected function _tableau_versements(&$pdf, $object, $posy, $outputlangs)
642 {
643 // phpcs:enable
644 return 1;
645 }
646
647 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
648 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
658 protected function _tableau_info(&$pdf, $object, $posy, $outputlangs)
659 {
660 // phpcs:enable
661 global $conf, $mysoc;
662 $default_font_size = pdf_getPDFFontSize($outputlangs);
663
664 // If France, show VAT mention if not applicable
665 if ($this->emetteur->country_code == 'FR' && empty($mysoc->tva_assuj)) {
666 $pdf->SetFont('', 'B', $default_font_size - 2);
667 $pdf->SetXY($this->marge_gauche, $posy);
668 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("VATIsNotUsedForInvoice"), 0, 'L', false);
669
670 $posy = $pdf->GetY() + 4;
671 }
672
673 $posxval = 52;
674
675 // Show payments conditions
676 if (!empty($object->cond_reglement_code) || $object->cond_reglement) {
677 $pdf->SetFont('', 'B', $default_font_size - 2);
678 $pdf->SetXY($this->marge_gauche, $posy);
679 $titre = $outputlangs->transnoentities("PaymentConditions").':';
680 $pdf->MultiCell(80, 4, $titre, 0, 'L');
681
682 $pdf->SetFont('', '', $default_font_size - 2);
683 $pdf->SetXY($posxval, $posy);
684 $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);
685 $lib_condition_paiement = str_replace('\n', "\n", $lib_condition_paiement);
686 $pdf->MultiCell(80, 4, $lib_condition_paiement, 0, 'L');
687
688 $posy = $pdf->GetY() + 3;
689 }
690
691 // Show payment mode
692 if (!empty($object->mode_reglement_code)) {
693 $pdf->SetFont('', 'B', $default_font_size - 2);
694 $pdf->SetXY($this->marge_gauche, $posy);
695 $titre = $outputlangs->transnoentities("PaymentMode").':';
696 $pdf->MultiCell(80, 5, $titre, 0, 'L');
697
698 $pdf->SetFont('', '', $default_font_size - 2);
699 $pdf->SetXY($posxval, $posy);
700 $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);
701 $pdf->MultiCell(80, 5, $lib_mode_reg, 0, 'L');
702
703 $posy = $pdf->GetY() + 2;
704 }
705
706
707 return $posy;
708 }
709
710 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
711 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
722 protected function _tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs)
723 {
724 // phpcs:enable
725 global $conf, $mysoc;
726
727 $default_font_size = pdf_getPDFFontSize($outputlangs);
728
729 $tab2_top = $posy;
730 $tab2_hl = 4;
731 $pdf->SetFont('', '', $default_font_size - 1);
732
733 // Tableau total
734 $col1x = 120;
735 $col2x = 170;
736 if ($this->page_largeur < 210) { // To work with US executive format
737 $col2x -= 20;
738 }
739 $largcol2 = ($this->page_largeur - $this->marge_droite - $col2x);
740
741 $useborder = 0;
742 $index = 0;
743
744 // Total HT
745 $pdf->SetFillColor(255, 255, 255);
746 $pdf->SetXY($col1x, $tab2_top);
747 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalHT"), 0, 'L', true);
748
749 $total_ht = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? $object->multicurrency_total_ht : $object->total_ht);
750 $pdf->SetXY($col2x, $tab2_top);
751 $pdf->MultiCell($largcol2, $tab2_hl, price($total_ht + (!empty($object->remise) ? $object->remise : 0)), 0, 'R', true);
752
753 // Show VAT by rates and total
754 $pdf->SetFillColor(248, 248, 248);
755
756 $this->atleastoneratenotnull = 0;
757 foreach ($this->tva as $tvakey => $tvaval) {
758 if ($tvakey > 0) { // On affiche pas taux 0
759 $this->atleastoneratenotnull++;
760
761 $index++;
762 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
763
764 $tvacompl = '';
765
766 if (preg_match('/\*/', $tvakey)) {
767 $tvakey = str_replace('*', '', $tvakey);
768 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
769 }
770
771 $totalvat = $outputlangs->transcountrynoentities("TotalVAT", $mysoc->country_code).' ';
772 $totalvat .= vatrate($tvakey, true).$tvacompl;
773 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
774
775 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
776 $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval), 0, 'R', true);
777 }
778 }
779 if (!$this->atleastoneratenotnull) { // If no vat at all
780 $index++;
781 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
782 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transcountrynoentities("TotalVAT", $mysoc->country_code), 0, 'L', true);
783
784 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
785 $pdf->MultiCell($largcol2, $tab2_hl, price($object->total_tva), 0, 'R', true);
786
787 // Total LocalTax1
788 if (getDolGlobalString('FACTURE_LOCAL_TAX1_OPTION') == 'localtax1on' && $object->total_localtax1 > 0) {
789 $index++;
790 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
791 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transcountrynoentities("TotalLT1", $mysoc->country_code), 0, 'L', true);
792 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
793 $pdf->MultiCell($largcol2, $tab2_hl, price($object->total_localtax1), $useborder, 'R', true);
794 }
795
796 // Total LocalTax2
797 if (getDolGlobalString('FACTURE_LOCAL_TAX2_OPTION') == 'localtax2on' && $object->total_localtax2 > 0) {
798 $index++;
799 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
800 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transcountrynoentities("TotalLT2", $mysoc->country_code), 0, 'L', true);
801 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
802 $pdf->MultiCell($largcol2, $tab2_hl, price($object->total_localtax2), $useborder, 'R', true);
803 }
804 } else {
805 //if (getDolGlobalString('FACTURE_LOCAL_TAX1_OPTION') && getDolGlobalString('FACTURE_LOCAL_TAX1_OPTION') == 'localtax1on')
806 //{
807 //Local tax 1
808 foreach ($this->localtax1 as $localtax_type => $localtax_rate) {
809 if (in_array((string) $localtax_type, array('2', '4', '6'))) {
810 continue;
811 }
812
813 foreach ($localtax_rate as $tvakey => $tvaval) {
814 if ($tvakey != 0) { // On affiche pas taux 0
815 //$this->atleastoneratenotnull++;
816
817 $index++;
818 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
819
820 $tvacompl = '';
821 if (preg_match('/\*/', $tvakey)) {
822 $tvakey = str_replace('*', '', $tvakey);
823 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
824 }
825 $totalvat = $outputlangs->transcountrynoentities("TotalLT1", $mysoc->country_code).' ';
826 $totalvat .= vatrate((string) abs((float) $tvakey), true).$tvacompl;
827 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
828
829 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
830 $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', true);
831 }
832 }
833 }
834
835 //if (getDolGlobalString('FACTURE_LOCAL_TAX2_OPTION') && getDolGlobalString('FACTURE_LOCAL_TAX2_OPTION') == 'localtax2on')
836 //{
837 //Local tax 2
838 foreach ($this->localtax2 as $localtax_type => $localtax_rate) {
839 if (in_array((string) $localtax_type, array('2', '4', '6'))) {
840 continue;
841 }
842
843 foreach ($localtax_rate as $tvakey => $tvaval) {
844 if ($tvakey != 0) { // On affiche pas taux 0
845 //$this->atleastoneratenotnull++;
846
847 $index++;
848 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
849
850 $tvacompl = '';
851 if (preg_match('/\*/', $tvakey)) {
852 $tvakey = str_replace('*', '', $tvakey);
853 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
854 }
855 $totalvat = $outputlangs->transcountrynoentities("TotalLT2", $mysoc->country_code).' ';
856 $totalvat .= vatrate((string) abs((float) $tvakey), true).$tvacompl;
857 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
858
859 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
860 $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval), 0, 'R', true);
861 }
862 }
863 }
864 }
865
866 // Total TTC
867 $index++;
868 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
869 $pdf->SetTextColor(0, 0, 60);
870 $pdf->SetFillColor(224, 224, 224);
871 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("TotalTTC"), $useborder, 'L', true);
872
873 $total_ttc = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1) ? $object->multicurrency_total_ttc : $object->total_ttc;
874 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
875 $pdf->MultiCell($largcol2, $tab2_hl, price($total_ttc), $useborder, 'R', true);
876 $pdf->SetFont('', '', $default_font_size - 1);
877 $pdf->SetTextColor(0, 0, 0);
878
879 $creditnoteamount = 0;
880 $depositsamount = 0;
881 //$creditnoteamount=$object->getSumCreditNotesUsed();
882 //$depositsamount=$object->getSumDepositsUsed();
883 //print "x".$creditnoteamount."-".$depositsamount;exit;
884 $resteapayer = price2num($total_ttc - $deja_regle - $creditnoteamount - $depositsamount, 'MT');
885 if (!empty($object->paye)) {
886 $resteapayer = 0;
887 }
888
889 if ($deja_regle > 0) {
890 // Already paid + Deposits
891 $index++;
892
893 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
894 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("AlreadyPaid"), 0, 'L', false);
895 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
896 $pdf->MultiCell($largcol2, $tab2_hl, price($deja_regle), 0, 'R', false);
897
898 $index++;
899 $pdf->SetTextColor(0, 0, 60);
900 $pdf->SetFillColor(224, 224, 224);
901 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
902 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("RemainderToPay"), $useborder, 'L', true);
903
904 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
905 $pdf->MultiCell($largcol2, $tab2_hl, price($resteapayer), $useborder, 'R', true);
906
907 $pdf->SetFont('', '', $default_font_size - 1);
908 $pdf->SetTextColor(0, 0, 0);
909 }
910
911 $index++;
912 return ($tab2_top + ($tab2_hl * $index));
913 }
914
915 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
929 protected function _tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop = 0, $hidebottom = 0, $currency = '')
930 {
931 global $conf;
932
933 // Force to disable hidetop and hidebottom
934 $hidebottom = 0;
935 if ($hidetop) {
936 $hidetop = -1;
937 }
938
939 $currency = !empty($currency) ? $currency : $conf->currency;
940 $default_font_size = pdf_getPDFFontSize($outputlangs);
941
942 // Amount in (at tab_top - 1)
943 $pdf->SetTextColor(0, 0, 0);
944 $pdf->SetFont('', '', $default_font_size - 2);
945
946 if (empty($hidetop)) {
947 // $title = $outputlangs->transnoentities("AmountInCurrency", $outputlangs->transnoentitiesnoconv("Currency".$currency));
948 $title = '';
949 $pdf->SetXY($this->page_largeur - $this->marge_droite - ($pdf->GetStringWidth($title) + 3), $tab_top - 4);
950 $pdf->MultiCell(($pdf->GetStringWidth($title) + 3), 2, $title);
951
952 //$conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR='230,230,230';
953 if (getDolGlobalString('MAIN_PDF_TITLE_BACKGROUND_COLOR')) {
954 $pdf->RoundedRect($this->marge_gauche, $tab_top, $this->page_largeur - $this->marge_droite - $this->marge_gauche, $this->tabTitleHeight, $this->corner_radius, '1001', 'F', array(), explode(',', getDolGlobalString('MAIN_PDF_TITLE_BACKGROUND_COLOR')));
955 }
956 }
957
958 $pdf->SetDrawColor(128, 128, 128);
959 $pdf->SetFont('', '', $default_font_size - 1);
960
961 // Output Rect
962 $this->printRoundedRect($pdf, $this->marge_gauche, $tab_top, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $tab_height, $this->corner_radius, $hidetop, $hidebottom, 'D'); // Rect takes a length in 3rd parameter and 4th parameter
963
964 foreach ($this->cols as $colKey => $colDef) {
965 if (!$this->getColumnStatus($colKey)) {
966 continue;
967 }
968
969 // get title label
970 $colDef['title']['label'] = !empty($colDef['title']['label']) ? $colDef['title']['label'] : $outputlangs->transnoentities($colDef['title']['textkey']);
971
972 // Add column separator
973 if (!empty($colDef['border-left'])) {
974 $pdf->line($colDef['xStartPos'], $tab_top, $colDef['xStartPos'], $tab_top + $tab_height);
975 }
976
977 if (empty($hidetop) && array_key_exists('title', $colDef) && array_key_exists('width', $colDef)) {
978 $pdf->SetXY($colDef['xStartPos'] + $colDef['title']['padding'][3], $tab_top + $colDef['title']['padding'][0]);
979
980 $textWidth = $colDef['width'] - $colDef['title']['padding'][3] - $colDef['title']['padding'][1];
981 $pdf->MultiCell($textWidth, 2, $colDef['title']['label'], '', $colDef['title']['align']);
982 }
983 }
984
985 if (empty($hidetop)) {
986 $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
987 }
988 }
989
990 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1000 protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs)
1001 {
1002 global $langs, $conf, $mysoc;
1003
1004 $ltrdirection = 'L';
1005 if ($outputlangs->trans("DIRECTION") == 'rtl') {
1006 $ltrdirection = 'R';
1007 }
1008
1009 // Load translation files required by the page
1010 $outputlangs->loadLangs(array("main", "orders", "companies", "bills", "sendings", "mrp"));
1011
1012 $default_font_size = pdf_getPDFFontSize($outputlangs);
1013
1014 // Do not add the BACKGROUND as this is for suppliers
1015 //pdf_pagehead($pdf,$outputlangs,$this->page_hauteur);
1016
1017 //Affiche le filigrane brouillon - Print Draft Watermark
1018 /*if($object->statut==0 && getDolGlobalString('COMMANDE_DRAFT_WATERMARK'))
1019 {
1020 pdf_watermark($pdf,$outputlangs,$this->page_hauteur,$this->page_largeur,'mm',getDolGlobalString('COMMANDE_DRAFT_WATERMARK'));
1021 }*/
1022 //Print content
1023
1024 $pdf->SetTextColor(0, 0, 60);
1025 $pdf->SetFont('', 'B', $default_font_size + 3);
1026
1027 $posx = $this->page_largeur - $this->marge_droite - 100;
1028 $posy = $this->marge_haute;
1029 $w = 100;
1030
1031 $pdf->SetXY($this->marge_gauche, $posy);
1032
1033 // Logo
1034 $logo = $conf->mycompany->dir_output.'/logos/'.$this->emetteur->logo;
1035 if ($this->emetteur->logo) {
1036 if (is_readable($logo)) {
1037 $height = pdf_getHeightForLogo($logo);
1038 $pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto)
1039 } else {
1040 $pdf->SetTextColor(200, 0, 0);
1041 $pdf->SetFont('', 'B', $default_font_size - 2);
1042 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound", $logo), 0, 'L');
1043 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorGoToModuleSetup"), 0, 'L');
1044 }
1045 } else {
1046 $text = $this->emetteur->name;
1047 $pdf->MultiCell(100, 4, $outputlangs->convToOutputCharset($text), 0, $ltrdirection);
1048 }
1049
1050 $pdf->SetFont('', 'B', $default_font_size + 3);
1051 $pdf->SetXY($posx, $posy);
1052 $pdf->SetTextColor(0, 0, 60);
1053 $title = $outputlangs->transnoentities("ManufacturingOrder")." ".$outputlangs->convToOutputCharset($object->ref);
1054 $pdf->MultiCell(100, 3, $title, '', 'R');
1055 $posy += 1;
1056
1057 if ($object->ref_supplier) {
1058 $posy += 4;
1059 $pdf->SetFont('', 'B', $default_font_size);
1060 $pdf->SetXY($posx, $posy);
1061 $pdf->SetTextColor(0, 0, 60);
1062 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("RefSupplier")." : ".$outputlangs->convToOutputCharset($object->ref_supplier), '', 'R');
1063 $posy += 1;
1064 }
1065
1066 $pdf->SetFont('', '', $default_font_size - 1);
1067 if (getDolGlobalString('PDF_SHOW_PROJECT_TITLE')) {
1068 $object->fetchProject();
1069 if (!empty($object->project->ref)) {
1070 $posy += 3;
1071 $pdf->SetXY($posx, $posy);
1072 $pdf->SetTextColor(0, 0, 60);
1073 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("Project")." : ".(empty($object->project->title) ? '' : $object->project->title), '', 'R');
1074 }
1075 }
1076
1077 if (getDolGlobalString('PDF_SHOW_PROJECT')) {
1078 $object->fetchProject();
1079 if (!empty($object->project->ref)) {
1080 $outputlangs->load("projects");
1081 $posy += 4;
1082 $pdf->SetXY($posx, $posy);
1083 $langs->load("projects");
1084 $pdf->SetTextColor(0, 0, 60);
1085 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Project")." : ".(empty($object->project->ref) ? '' : $object->project->ref), '', 'R');
1086 }
1087 }
1088
1089 if (!empty($object->date_start_planned)) {
1090 $posy += 5;
1091 $pdf->SetXY($posx, $posy);
1092 $pdf->SetTextColor(0, 0, 60);
1093 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("MoDate")." : ".dol_print_date($object->date_start_planned, "day", false, $outputlangs, true), '', 'R');
1094 } else {
1095 $posy += 5;
1096 $pdf->SetXY($posx, $posy);
1097 $pdf->SetTextColor(255, 0, 0);
1098 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ToApprove"), '', 'R');
1099 }
1100
1101 // product info
1102 $prodToMake = new Product($this->db);
1103 $resProdToMake = $prodToMake->fetch((int) $object->fk_product);
1104
1105 if ($resProdToMake > 0) {
1106 // ref
1107 $posy += 7;
1108 $pdf->SetFont('', 'B', $default_font_size + 1);
1109 $pdf->SetXY($posx, $posy);
1110 $pdf->SetTextColor(0, 0, 60);
1111 $pdf->MultiCell($w, 3, $prodToMake->ref, '', 'R');
1112
1113 // description
1114 $posy += 5;
1115 $pdf->SetFont('', 'B', $default_font_size + 3);
1116 $pdf->SetXY($posx, $posy);
1117 $pdf->SetTextColor(0, 0, 60);
1118 $pdf->MultiCell($w, 3, html_entity_decode($prodToMake->description), '', 'R', false, 1, null, null, true, 0, false, true, 51, 'T', true);
1119 $posy = $pdf->GetY() - 5;
1120
1121 // dimensions
1122 $array = array_filter(array($prodToMake->length, $prodToMake->width, $prodToMake->height));
1123 $dim = implode("x", $array);
1124 if (!empty($dim)) {
1125 $posy += 5;
1126 $pdf->SetFont('', 'B', $default_font_size + 3);
1127 $pdf->SetXY($posx, $posy);
1128 $pdf->SetTextColor(0, 0, 60);
1129 $pdf->MultiCell($w, 3, $dim, '', 'R');
1130 }
1131 }
1132
1133 $posy += 5;
1134 $pdf->SetFont('', 'B', $default_font_size + 3);
1135 $pdf->SetXY($posx, $posy);
1136 $pdf->SetTextColor(0, 0, 60);
1137 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("QtyToProduce").": " .$object->qty, '', 'R');
1138
1139
1140 $pdf->SetTextColor(0, 0, 60);
1141 $usehourmin = 'day';
1142 if (getDolGlobalString('SUPPLIER_ORDER_USE_HOUR_FOR_DELIVERY_DATE')) {
1143 $usehourmin = 'dayhour';
1144 }
1145 if (!empty($object->delivery_date)) {
1146 $posy += 4;
1147 $pdf->SetXY($posx - 90, $posy);
1148 $pdf->MultiCell(190, 3, $outputlangs->transnoentities("DateDeliveryPlanned")." : ".dol_print_date($object->delivery_date, $usehourmin, false, $outputlangs, true), '', 'R');
1149 }
1150
1151 if (isset($object->thirdparty->code_fournisseur)) {
1152 $posy += 4;
1153 $pdf->SetXY($posx, $posy);
1154 $pdf->SetTextColor(0, 0, 60);
1155 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("SupplierCode")." : ".$outputlangs->transnoentities($object->thirdparty->code_fournisseur), '', 'R');
1156 }
1157
1158 // Get contact
1159 if (getDolGlobalString('DOC_SHOW_FIRST_SALES_REP')) {
1160 $arrayidcontact = $object->getIdContact('internal', 'SALESREPFOLL');
1161 if (count($arrayidcontact) > 0) {
1162 $usertmp = new User($this->db);
1163 $usertmp->fetch($arrayidcontact[0]);
1164 $posy += 4;
1165 $pdf->SetXY($posx, $posy);
1166 $pdf->SetTextColor(0, 0, 60);
1167 $pdf->MultiCell(100, 3, $langs->trans("BuyerName")." : ".$usertmp->getFullName($langs), '', 'R');
1168 }
1169 }
1170
1171 $posy += 1;
1172 $pdf->SetTextColor(0, 0, 60);
1173
1174 $top_shift = 0;
1175 // Show list of linked objects
1176 $current_y = $pdf->getY();
1177 $posy = pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, 100, 3, 'R', $default_font_size);
1178 if ($current_y < $pdf->getY()) {
1179 $top_shift = $pdf->getY() - $current_y;
1180 }
1181
1182 if ($showaddress) {
1183 // Sender properties
1184 $carac_emetteur = '';
1185 // Add internal contact of object if defined
1186 $arrayidcontact = $object->getIdContact('internal', 'SALESREPFOLL');
1187 if (count($arrayidcontact) > 0) {
1188 $object->fetch_user($arrayidcontact[0]);
1189 $labelbeforecontactname = ($outputlangs->transnoentities("FromContactName") != 'FromContactName' ? $outputlangs->transnoentities("FromContactName") : $outputlangs->transnoentities("Name"));
1190 $carac_emetteur .= ($carac_emetteur ? "\n" : '').$labelbeforecontactname.": ".$outputlangs->convToOutputCharset($object->user->getFullName($outputlangs));
1191 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') || getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ' (' : '';
1192 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') && !empty($object->user->office_phone)) ? $object->user->office_phone : '';
1193 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') && getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ', ' : '';
1194 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT') && !empty($object->user->email)) ? $object->user->email : '';
1195 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') || getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ')' : '';
1196 $carac_emetteur .= "\n";
1197 }
1198
1199 $carac_emetteur .= pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, '', 0, 'source', $object);
1200
1201 // Show sender
1202 $posy = 42 + $top_shift;
1203 $posx = $this->marge_gauche;
1204 if (getDolGlobalString('MAIN_INVERT_SENDER_RECIPIENT')) {
1205 $posx = $this->page_largeur - $this->marge_droite - 80;
1206 }
1207 $hautcadre = 40;
1208
1209 // Show sender frame
1210 $pdf->SetTextColor(0, 0, 0);
1211 $pdf->SetFont('', '', $default_font_size - 2);
1212 $pdf->SetXY($posx, $posy - 5);
1213 $pdf->MultiCell(80, 5, $outputlangs->transnoentities("BillFrom"), 0, $ltrdirection);
1214 $pdf->SetXY($posx, $posy);
1215 $pdf->SetFillColor(230, 230, 230);
1216 $pdf->RoundedRect($posx, $posy, 82, $hautcadre, $this->corner_radius, '1234', 'F');
1217 $pdf->SetTextColor(0, 0, 60);
1218
1219 // Show sender name
1220 $pdf->SetXY($posx + 2, $posy + 3);
1221 $pdf->SetFont('', 'B', $default_font_size);
1222 $pdf->MultiCell(80, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, $ltrdirection);
1223 $posy = $pdf->getY();
1224
1225 // Show sender information
1226 $pdf->SetXY($posx + 2, $posy);
1227 $pdf->SetFont('', '', $default_font_size - 1);
1228 $pdf->MultiCell(80, 4, $carac_emetteur, 0, $ltrdirection);
1229
1230
1231
1232 // 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'
1233 $usecontact = false;
1234 $arrayidcontact = $object->getIdContact('external', 'CUSTOMER');
1235 if (count($arrayidcontact) > 0) {
1236 $usecontact = true;
1237 $result = $object->fetch_contact($arrayidcontact[0]);
1238 }
1239
1240 // Recipient name
1241 if ($usecontact && ($object->contact->fk_soc != $object->thirdparty->id && (!isset($conf->global->MAIN_USE_COMPANY_NAME_OF_CONTACT) || getDolGlobalString('MAIN_USE_COMPANY_NAME_OF_CONTACT')))) {
1242 $thirdparty = $object->contact;
1243 } else {
1244 $thirdparty = $object->thirdparty;
1245 }
1246
1247 //$carac_client_name = pdfBuildThirdpartyName($thirdparty, $outputlangs);
1248
1249 //$carac_client = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, ($usecontact ? $object->contact : ''), $usecontact, 'target', $object);
1250
1251 // Show recipient
1252 //$widthrecbox = 100;
1253 //if ($this->page_largeur < 210) {
1254 // $widthrecbox = 84; // To work with US executive format
1255 //}
1256 //$posy = 42 + $top_shift;
1257 //$posx = $this->page_largeur - $this->marge_droite - $widthrecbox;
1258 //if (getDolGlobalString('MAIN_INVERT_SENDER_RECIPIENT')) {
1259 // $posx = $this->marge_gauche;
1260 //}
1261 //
1263 //$pdf->SetTextColor(0, 0, 0);
1264 //$pdf->SetFont('', '', $default_font_size - 2);
1265 //$pdf->SetXY($posx + 2, $posy - 5);
1266 //$pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillTo"), 0, $ltrdirection);
1267 //$pdf->Rect($posx, $posy, $widthrecbox, $hautcadre);
1268 //
1270 //$pdf->SetXY($posx + 2, $posy + 3);
1271 //$pdf->SetFont('', 'B', $default_font_size);
1272 //$pdf->MultiCell($widthrecbox, 4, $carac_client_name, 0, $ltrdirection);
1273 //
1274 //$posy = $pdf->getY();
1275 //
1277 //$pdf->SetFont('', '', $default_font_size - 1);
1278 //$pdf->SetXY($posx + 2, $posy);
1279 //$pdf->MultiCell($widthrecbox, 4, $carac_client, 0, $ltrdirection);
1280 }
1281
1282 return $top_shift;
1283 }
1284
1285 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1295 protected function _pagefoot(&$pdf, $object, $outputlangs, $hidefreetext = 0)
1296 {
1297 $showdetails = getDolGlobalInt('MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS', 0);
1298 return pdf_pagefoot($pdf, $outputlangs, 'SUPPLIER_ORDER_FREE_TEXT', $this->emetteur, $this->marge_basse, $this->marge_gauche, $this->page_hauteur, $object, $showdetails, $hidefreetext);
1299 }
1300
1301
1312 public function defineColumnField($object, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0)
1313 {
1314 global $conf, $hookmanager;
1315
1316 // Default field style for content
1317 $this->defaultContentsFieldsStyle = array(
1318 'align' => 'R', // R,C,L
1319 'padding' => array(1, 0.5, 1, 0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1320 );
1321
1322 // Default field style for content
1323 $this->defaultTitlesFieldsStyle = array(
1324 'align' => 'C', // R,C,L
1325 'padding' => array(0.5, 0, 0.5, 0), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1326 );
1327
1328 /*
1329 * For example
1330 $this->cols['theColKey'] = array(
1331 'rank' => $rank, // int : use for ordering columns
1332 'width' => 20, // the column width in mm
1333 'title' => array(
1334 'textkey' => 'yourLangKey', // if there is no label, yourLangKey will be translated to replace label
1335 'label' => ' ', // the final label : used fore final generated text
1336 'align' => 'L', // text alignment : R,C,L
1337 'padding' => array(0.5,0.5,0.5,0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1338 ),
1339 'content' => array(
1340 'align' => 'L', // text alignment : R,C,L
1341 'padding' => array(0.5,0.5,0.5,0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1342 ),
1343 );
1344 */
1345 $rank = 0;
1346 $this->cols['code'] = array(
1347 'rank' => $rank,
1348 'status' => true,
1349 'width' => 35, // in mm
1350 'title' => array(
1351 'textkey' => 'Ref',
1352 'align' => 'L',
1353 'padding' => array(0.5, 1, 0.5, 1.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1354 ),
1355 'border-left' => true, // add left line separator
1356 'content' => array(
1357 'align' => 'L',
1358 'padding' => array(1, 0.5, 1, 1.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1359 ),
1360 );
1361
1362 $rank = 1; // do not use negative rank
1363 $this->cols['desc'] = array(
1364 'rank' => $rank,
1365 'width' => false, // only for desc
1366 'status' => true,
1367 'title' => array(
1368 'textkey' => 'Designation', // use lang key is useful in some case with module
1369 'align' => 'L',
1370 // 'textkey' => 'yourLangKey', // if there is no label, yourLangKey will be translated to replace label
1371 // 'label' => ' ', // the final label
1372 'padding' => array(0.5, 1, 0.5, 1.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1373 ),
1374 'border-left' => true,
1375 'content' => array(
1376 'align' => 'L',
1377 'padding' => array(1, 0.5, 1, 1.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1378 ),
1379 );
1380
1381 $rank += 10;
1382 $this->cols['dim'] = array(
1383 'rank' => $rank,
1384 'status' => true,
1385 'width' => 25, // in mm
1386 'title' => array(
1387 'textkey' => 'Dimensions'
1388 ),
1389 'border-left' => true, // add left line separator
1390 );
1391
1392 $rank += 10;
1393 $this->cols['qty'] = array(
1394 'rank' => $rank,
1395 'width' => 16, // in mm
1396 'status' => true,
1397 'title' => array(
1398 'textkey' => 'Qty'
1399 ),
1400 'border-left' => true, // add left line separator
1401 );
1402
1403 $rank += 10;
1404 $this->cols['qtytot'] = array(
1405 'rank' => $rank,
1406 'width' => 25, // in mm
1407 'status' => true,
1408 'title' => array(
1409 'textkey' => 'QtyTot'
1410 ),
1411 'border-left' => true, // add left line separator
1412 );
1413
1414 // Add extrafields cols
1415 if (!empty($object->lines)) {
1416 $line = reset($object->lines);
1417 $this->defineColumnExtrafield($line, $outputlangs, $hidedetails);
1418 }
1419
1420 $parameters = array(
1421 'object' => $object,
1422 'outputlangs' => $outputlangs,
1423 'hidedetails' => $hidedetails,
1424 'hidedesc' => $hidedesc,
1425 'hideref' => $hideref
1426 );
1427
1428 $reshook = $hookmanager->executeHooks('defineColumnField', $parameters, $this); // Note that $object may have been modified by hook
1429 if ($reshook < 0) {
1430 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1431 } elseif (empty($reshook)) {
1432 // @phan-suppress-next-line PhanPluginSuspiciousParamOrderInternal
1433 $this->cols = array_replace($this->cols, $hookmanager->resArray); // array_replace is used to preserve keys
1434 } else {
1435 $this->cols = $hookmanager->resArray;
1436 }
1437 }
1438}
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
Class for BOM.
Definition bom.class.php:42
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
printRoundedRect($pdf, $x, $y, $w, $h, $r, $hidetop=0, $hidebottom=0, $style='D')
Print a rounded rectangle on the 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.
write_file($object, $outputlangs, $srctemplatepath='', $hidedetails=0, $hidedesc=0, $hideref=0)
Function to build pdf onto disk.
defineColumnField($object, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0)
Define Array Column Field.
global $mysoc
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...
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
vatrate($rate, $addpercent=false, $info_bits=0, $usestarfornpr=0, $html=0)
Return a string with VAT rate label formatted 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 '.
getCallerInfoString()
Get caller info as a string that can be appended to a log message.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
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.
dolChmod($filepath, $newmask='')
Change mod of a file.
getDolGlobalInt($key, $default=0)
Return a 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...
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
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 a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
pdf_getFormat($outputlangs=null, $mode='setup')
Return array with format properties of default PDF format.
Definition pdf.lib.php:87
pdf_getPDFFontSize($outputlangs)
Return font size to use for PDF generation.
Definition pdf.lib.php:289
pdf_getHeightForLogo($logo, $url=false)
Return height to use for Logo onto PDF.
Definition pdf.lib.php:312
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:1110
pdf_writeLinkedObjects(&$pdf, $object, $outputlangs, $posx, $posy, $w, $h, $align, $default_font_size)
Show linked objects for PDF generation.
Definition pdf.lib.php:1497
pdf_getPDFFont($outputlangs)
Return font name to use for PDF generation.
Definition pdf.lib.php:268
pdf_build_address($outputlangs, $sourcecompany, $targetcompany='', $targetcontact='', $usecontact=0, $mode='source', $object=null)
Return a string with full address formatted for output on PDF documents.
Definition pdf.lib.php:433
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:824
pdf_getInstance($format='', $metric='mm', $pagetype='P')
Return a PDF instance object.
Definition pdf.lib.php:129
if(preg_match('/(crypted|dolcrypt):/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
'integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]',...
Definition repair.php:125
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:128