dolibarr 18.0.6
pdf_standard.modules.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2017 Laurent Destailleur <eldy@stocks.sourceforge.net>
3 * Copyright (C) 2022 Ferran Marcet <fmarcet@2byte.es>
4 * Copyright (C) 2022 Nicolas Silobre <nsilobre@ns-info90.fr>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 * or see https://www.gnu.org/
19 */
20
27require_once DOL_DOCUMENT_ROOT.'/core/modules/stock/modules_stock.php';
28require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
29require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
30require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
31require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
32require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
33require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
34
35
39class pdf_standard extends ModelePDFStock
40{
44 public $db;
45
49 public $name;
50
54 public $description;
55
59 public $type;
60
65 public $version = 'dolibarr';
66
71 public $emetteur;
72
73 public $wref;
74 public $posxdesc;
75 public $posxlabel;
76 public $posxtva;
77 public $posxqty;
78 public $posxup;
79 public $posxunit;
80 public $posxdiscount;
81 public $postotalht;
82
83 public $tabTitleHeight;
84
85
91 public function __construct($db)
92 {
93 global $conf, $langs, $mysoc;
94
95 // Load traductions files required by page
96 $langs->loadLangs(array("main", "companies"));
97
98 $this->db = $db;
99 $this->name = "standard";
100 $this->description = $langs->trans("DocumentModelStandardPDF");
101
102 // Page size for A4 format
103 $this->type = 'pdf';
104 $formatarray = pdf_getFormat();
105 $this->page_largeur = $formatarray['width'];
106 $this->page_hauteur = $formatarray['height'];
107 $this->format = array($this->page_largeur, $this->page_hauteur);
108 $this->marge_gauche = getDolGlobalInt('MAIN_PDF_MARGIN_LEFT', 10);
109 $this->marge_droite = getDolGlobalInt('MAIN_PDF_MARGIN_RIGHT', 10);
110 $this->marge_haute = getDolGlobalInt('MAIN_PDF_MARGIN_TOP', 10);
111 $this->marge_basse = getDolGlobalInt('MAIN_PDF_MARGIN_BOTTOM', 10);
112
113 $this->option_logo = 1; // Display logo
114 $this->option_codestockservice = 0; // Display product-service code
115 $this->option_multilang = 1; // Available in several languages
116 $this->option_freetext = 0; // Support add of a personalised text
117
118 // Get source company
119 $this->emetteur = $mysoc;
120 if (!$this->emetteur->country_code) {
121 $this->emetteur->country_code = substr($langs->defaultlang, -2); // By default if not defined
122 }
123
124 // Define position of columns
125 $this->wref = 35;
126 $this->posxdesc = $this->marge_gauche + 1;
127 $this->posxlabel = $this->posxdesc + $this->wref;
128 $this->posxtva = 80;
129 $this->posxqty = 95;
130 $this->posxup = 115;
131 $this->posxunit = 135;
132 $this->posxdiscount = 155;
133 $this->postotalht = 175;
134
135 if (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT) || !empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_COLUMN)) {
136 $this->posxtva = $this->posxup;
137 }
138 $this->posxpicture = $this->posxtva - (empty($conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH) ? 20 : $conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH); // width of images
139 if ($this->page_largeur < 210) { // To work with US executive format
140 $this->posxpicture -= 20;
141 $this->posxtva -= 20;
142 $this->posxup -= 20;
143 $this->posxqty -= 20;
144 $this->posxunit -= 20;
145 $this->posxdiscount -= 20;
146 $this->postotalht -= 20;
147 }
148
149 $this->tabTitleHeight = 11;
150 }
151
152
153 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
165 public function write_file($object, $outputlangs, $srctemplatepath = '', $hidedetails = 0, $hidedesc = 0, $hideref = 0)
166 {
167 // phpcs:enable
168 global $user, $langs, $conf, $mysoc, $db, $hookmanager;
169
170 if (!is_object($outputlangs)) {
171 $outputlangs = $langs;
172 }
173 // For backward compatibility with FPDF, force output charset to ISO, because FPDF expect text to be encoded in ISO
174 if (!empty($conf->global->MAIN_USE_FPDF)) {
175 $outputlangs->charset_output = 'ISO-8859-1';
176 }
177
178 // Load traductions files required by page
179 $outputlangs->loadLangs(array("main", "dict", "companies", "bills", "stocks", "orders", "deliveries"));
180
181 if ($conf->stock->dir_output) {
182 // Definition of $dir and $file
183 if ($object->specimen) {
184 $dir = $conf->stock->dir_output;
185 $file = $dir."/SPECIMEN.pdf";
186 } else {
187 $objectref = dol_sanitizeFileName($object->ref);
188 $dir = $conf->stock->dir_output."/".$objectref;
189 $file = $dir."/".$objectref.".pdf";
190 }
191
192 $stockFournisseur = new ProductFournisseur($this->db);
193 $supplierprices = $stockFournisseur->list_product_fournisseur_price($object->id);
194 $object->supplierprices = $supplierprices;
195
196 $productstatic = new Product($this->db);
197
198 if (!file_exists($dir)) {
199 if (dol_mkdir($dir) < 0) {
200 $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
201 return -1;
202 }
203 }
204
205 if (file_exists($dir)) {
206 // Add pdfgeneration hook
207 if (!is_object($hookmanager)) {
208 include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
209 $hookmanager = new HookManager($this->db);
210 }
211 $hookmanager->initHooks(array('pdfgeneration'));
212 $parameters = array('file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs);
213 global $action;
214 $reshook = $hookmanager->executeHooks('beforePDFCreation', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
215
216 // Create pdf instance
217 $pdf = pdf_getInstance($this->format);
218 $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance
219 $pdf->SetAutoPageBreak(1, 0);
220
221 $heightforinfotot = 40; // Height reserved to output the info and total part
222 $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
223 $heightforfooter = $this->marge_basse + 8; // Height reserved to output the footer (value include bottom margin)
224 if (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS)) {
225 $heightforfooter += 6;
226 }
227
228 if (class_exists('TCPDF')) {
229 $pdf->setPrintHeader(false);
230 $pdf->setPrintFooter(false);
231 }
232 $pdf->SetFont(pdf_getPDFFont($outputlangs));
233 // Set path to the background PDF File
234 if (empty($conf->global->MAIN_DISABLE_FPDI) && !empty($conf->global->MAIN_ADD_PDF_BACKGROUND)) {
235 $pagecount = $pdf->setSourceFile($conf->mycompany->dir_output.'/'.$conf->global->MAIN_ADD_PDF_BACKGROUND);
236 $tplidx = $pdf->importPage(1);
237 }
238
239 $pdf->Open();
240 $pagenb = 0;
241 $pdf->SetDrawColor(128, 128, 128);
242
243 $pdf->SetTitle($outputlangs->convToOutputCharset($object->ref));
244 $pdf->SetSubject($outputlangs->transnoentities("Stock"));
245 $pdf->SetCreator("Dolibarr ".DOL_VERSION);
246 $pdf->SetAuthor($outputlangs->convToOutputCharset($user->getFullName($outputlangs)));
247 $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("Stock")." ".$outputlangs->convToOutputCharset($object->label));
248 if (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) {
249 $pdf->SetCompression(false);
250 }
251
252 $pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite); // Left, Top, Right
253
254
255 // New page
256 $pdf->AddPage();
257 if (!empty($tplidx)) {
258 $pdf->useTemplate($tplidx);
259 }
260 $pagenb++;
261 $top_shift = $this->_pagehead($pdf, $object, 1, $outputlangs);
262 $pdf->SetFont('', '', $default_font_size - 1);
263 $pdf->MultiCell(0, 3, ''); // Set interline to 3
264 $pdf->SetTextColor(0, 0, 0);
265
266 $tab_top = 65 + $top_shift;
267 $tab_top_newpage = (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD') ? 42 + $top_shift : 10);
268
269 $tab_height = $this->page_hauteur - $tab_top - $heightforfooter - $heightforfreetext;
270
271
272 // Show list of product in warehouse */
273
274 $totalunit = 0;
275 $totalvalue = $totalvaluesell = 0;
276
277 $sortfield = 'p.ref';
278 $sortorder = 'ASC';
279
280 $sql = "SELECT p.rowid as rowid, p.ref, p.label as produit, p.tobatch, p.fk_product_type as type, p.pmp as ppmp, p.price, p.price_ttc, p.entity,";
281 $sql .= " ps.reel as value";
282 $sql .= " FROM ".MAIN_DB_PREFIX."product_stock as ps, ".MAIN_DB_PREFIX."product as p";
283 $sql .= " WHERE ps.fk_product = p.rowid";
284 $sql .= " AND ps.reel <> 0"; // We do not show if stock is 0 (no product in this warehouse)
285 $sql .= " AND ps.fk_entrepot = ".((int) $object->id);
286 $sql .= $this->db->order($sortfield, $sortorder);
287
288 //dol_syslog('List products', LOG_DEBUG);
289 $resql = $this->db->query($sql);
290 if ($resql) {
291 $num = $this->db->num_rows($resql);
292 $i = 0;
293 $nblines = $num;
294
295 $nexY = $tab_top + $this->tabTitleHeight;
296
297 for ($i = 0; $i < $nblines; $i++) {
298 $curY = $nexY;
299
300 $objp = $this->db->fetch_object($resql);
301
302 // Multilangs
303 if (getDolGlobalInt('MAIN_MULTILANGS')) { // si l'option est active
304 $sql = "SELECT label";
305 $sql .= " FROM ".MAIN_DB_PREFIX."product_lang";
306 $sql .= " WHERE fk_product = ".((int) $objp->rowid);
307 $sql .= " AND lang = '".$this->db->escape($langs->getDefaultLang())."'";
308 $sql .= " LIMIT 1";
309
310 $result = $this->db->query($sql);
311 if ($result) {
312 $objtp = $this->db->fetch_object($result);
313 if ($objtp->label != '') {
314 $objp->produit = $objtp->label;
315 }
316 }
317 }
318
319 $pdf->SetFont('', '', $default_font_size - 1); // Into loop to work with multipage
320 $pdf->SetTextColor(0, 0, 0);
321
322 $pdf->setTopMargin($tab_top_newpage);
323 $pdf->setPageOrientation('', 1, $heightforfooter + $heightforfreetext + $heightforinfotot); // The only function to edit the bottom margin of current page to set it.
324 $pageposbefore = $pdf->getPage();
325
326 // Description of product line
327 $curX = $this->posxdesc - 1;
328
329 $showpricebeforepagebreak = 1;
330
331 $pdf->startTransaction();
332 $pdf->writeHTMLCell($this->wref, 3, $curX, $curY, $outputlangs->convToOutputCharset($objp->ref), 0, 1, false, true, 'J', true);
333 //pdf_writelinedesc($pdf, $object, $i, $outputlangs, $this->posxtva - $curX, 3, $curX, $curY, $hideref, $hidedesc);
334 $pageposafter = $pdf->getPage();
335 if ($pageposafter > $pageposbefore) { // There is a pagebreak
336 $pdf->rollbackTransaction(true);
337 $pageposafter = $pageposbefore;
338 //print $pageposafter.'-'.$pageposbefore;exit;
339 $pdf->setPageOrientation('', 1, $heightforfooter); // The only function to edit the bottom margin of current page to set it.
340 $pdf->writeHTMLCell($this->wref, 4, $curX, $curY, $outputlangs->convToOutputCharset($objp->ref), 0, 1, false, true, 'J', true);
341 //pdf_writelinedesc($pdf, $object, $i, $outputlangs, $this->posxtva - $curX, 4, $curX, $curY, $hideref, $hidedesc);
342 $pageposafter = $pdf->getPage();
343 $posyafter = $pdf->GetY();
344 if ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforinfotot))) { // There is no space left for total+free text
345 if ($i == ($nblines - 1)) { // No more lines, and no space left to show total, so we create a new page
346 $pdf->AddPage('', '', true);
347 if (!empty($tplidx)) {
348 $pdf->useTemplate($tplidx);
349 }
350 if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
351 $this->_pagehead($pdf, $object, 0, $outputlangs);
352 }
353 $pdf->setPage($pageposafter + 1);
354 }
355 } else {
356 // We found a page break
357
358 // Allows data in the first page if description is long enough to break in multiples pages
359 if (!empty($conf->global->MAIN_PDF_DATA_ON_FIRST_PAGE)) {
360 $showpricebeforepagebreak = 1;
361 } else {
362 $showpricebeforepagebreak = 0;
363 }
364 }
365 } else // No pagebreak
366 {
367 $pdf->commitTransaction();
368 }
369 $posYAfterDescription = $pdf->GetY();
370
371 $nexY = $pdf->GetY();
372 $pageposafter = $pdf->getPage();
373
374 $pdf->setPage($pageposbefore);
375 $pdf->setTopMargin($this->marge_haute);
376 $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it.
377
378 // We suppose that a too long description is moved completely on next page
379 if ($pageposafter > $pageposbefore && empty($showpricebeforepagebreak)) {
380 $pdf->setPage($pageposafter);
381 $curY = $tab_top_newpage;
382 }
383
384 $pdf->SetFont('', '', $default_font_size - 1); // On repositionne la police par defaut
385
386 $productstatic->id = $objp->rowid;
387 $productstatic->ref = $objp->ref;
388 $productstatic->label = $objp->produit;
389 $productstatic->type = $objp->type;
390 $productstatic->entity = $objp->entity;
391 $productstatic->status_batch = $objp->tobatch;
392
393 // Ref.
394 //$pdf->SetXY($this->posxdesc, $curY);
395 //$pdf->MultiCell($this->wref, 3, $productstatic->ref, 0, 'L');
396
397 // Label
398 $pdf->SetXY($this->posxlabel + 0.8, $curY);
399 $pdf->MultiCell($this->posxqty - $this->posxlabel - 0.8, 3, dol_trunc($productstatic->label, 24), 0, 'L');
400
401 // Quantity
402 $valtoshow = price2num($objp->value, 'MS');
403 $towrite = (empty($valtoshow) ? '0' : $valtoshow);
404
405 $pdf->SetXY($this->posxqty, $curY);
406 $pdf->MultiCell($this->posxup - $this->posxqty - 0.8, 3, $towrite, 0, 'R');
407
408 // AWP
409 $totalunit += $objp->value;
410
411 $pdf->SetXY($this->posxup, $curY);
412 $pdf->MultiCell($this->posxunit - $this->posxup - 0.8, 3, price(price2num($objp->ppmp, 'MU'), 0, $outputlangs), 0, 'R');
413
414 // Total PMP
415 $pdf->SetXY($this->posxunit, $curY);
416 $pdf->MultiCell($this->posxdiscount - $this->posxunit - 0.8, 3, price(price2num($objp->ppmp * $objp->value, 'MT'), 0, $outputlangs), 0, 'R');
417 $totalvalue += price2num($objp->ppmp * $objp->value, 'MT');
418
419 // Price sell min
420 if (empty($conf->global->PRODUIT_MULTIPRICES)) {
421 $pricemin = $objp->price;
422 $pdf->SetXY($this->posxdiscount, $curY);
423 $pdf->MultiCell($this->postotalht - $this->posxdiscount, 3, price(price2num($pricemin, 'MU'), 0, $outputlangs), 0, 'R', 0);
424
425 // Total sell min
426 $pdf->SetXY($this->postotalht, $curY);
427 $pdf->MultiCell($this->page_largeur - $this->marge_droite - $this->postotalht, 3, price(price2num($pricemin * $objp->value, 'MT'), 0, $outputlangs), 0, 'R', 0);
428 }
429 $totalvaluesell += price2num($pricemin * $objp->value, 'MT');
430
431 // Add line
432 if (!empty($conf->global->MAIN_PDF_DASH_BETWEEN_LINES) && $i < ($nblines - 1)) {
433 $pdf->setPage($pageposafter);
434 $pdf->SetLineStyle(array('dash'=>'1,1', 'color'=>array(80, 80, 80)));
435 //$pdf->SetDrawColor(190,190,200);
436 $pdf->line($this->marge_gauche, $nexY + 1, $this->page_largeur - $this->marge_droite, $nexY + 1);
437 $pdf->SetLineStyle(array('dash'=>0));
438 }
439
440 $nexY += 2; // Add space between lines
441
442 // Detect if some page were added automatically and output _tableau for past pages
443 while ($pagenb < $pageposafter) {
444 $pdf->setPage($pagenb);
445 if ($pagenb == 1) {
446 $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1, $object->multicurrency_code);
447 } else {
448 $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code);
449 }
450 $this->_pagefoot($pdf, $object, $outputlangs, 1);
451 $pagenb++;
452 $pdf->setPage($pagenb);
453 $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it.
454 if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
455 $this->_pagehead($pdf, $object, 0, $outputlangs);
456 }
457 if (!empty($tplidx)) {
458 $pdf->useTemplate($tplidx);
459 }
460 }
461 if (isset($object->lines[$i + 1]->pagebreak) && $object->lines[$i + 1]->pagebreak) {
462 if ($pagenb == 1) {
463 $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1, $object->multicurrency_code);
464 } else {
465 $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code);
466 }
467 $this->_pagefoot($pdf, $object, $outputlangs, 1);
468 // New page
469 $pdf->AddPage();
470 if (!empty($tplidx)) {
471 $pdf->useTemplate($tplidx);
472 }
473 $pagenb++;
474 if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
475 $this->_pagehead($pdf, $object, 0, $outputlangs);
476 }
477 }
478 }
479
480 $this->db->free($resql);
481
485 //$nexY = $pdf->GetY();
486 $nexY += 2;
487 $curY = $nexY;
488
489 if ($nblines > 0) {
490 $pdf->SetLineStyle(array('dash'=>'0', 'color'=>array(200, 200, 200)));
491 $pdf->line($this->marge_gauche, $curY - 1, $this->page_largeur - $this->marge_droite, $curY - 1);
492 $pdf->SetLineStyle(array('dash'=>0));
493
494 $pdf->SetFont('', 'B', $default_font_size - 1);
495 $pdf->SetTextColor(0, 0, 0);
496
497 // Ref.
498 $pdf->SetXY($this->posxdesc, $curY);
499 $pdf->MultiCell($this->wref, 3, $langs->trans("Total"), 0, 'L');
500
501 // Quantity
502 $valtoshow = price2num($totalunit, 'MS');
503 $towrite = empty($valtoshow) ? '0' : $valtoshow;
504
505 $pdf->SetXY($this->posxqty, $curY);
506 $pdf->MultiCell($this->posxup - $this->posxqty - 0.8, 3, $towrite, 0, 'R');
507
508 // Total PMP
509 $pdf->SetXY($this->posxunit, $curY);
510 $pdf->MultiCell($this->posxdiscount - $this->posxunit - 0.8, 3, price(price2num($totalvalue, 'MT'), 0, $outputlangs), 0, 'R');
511
512 // Price sell min
513 if (empty($conf->global->PRODUIT_MULTIPRICES)) {
514 // Total sell min
515 $pdf->SetXY($this->postotalht, $curY);
516 $pdf->MultiCell($this->page_largeur - $this->marge_droite - $this->postotalht, 3, price(price2num($totalvaluesell, 'MT'), 0, $outputlangs), 0, 'R', 0);
517 }
518 }
519 } else {
520 dol_print_error($this->db);
521 }
522
523 // Displays notes
524 $notetoshow = empty($object->note_public) ? '' : $object->note_public;
525
526 if ($notetoshow) {
527 $substitutionarray = pdf_getSubstitutionArray($outputlangs, null, $object);
528 complete_substitutions_array($substitutionarray, $outputlangs, $object);
529 $notetoshow = make_substitutions($notetoshow, $substitutionarray, $outputlangs);
530 $notetoshow = convertBackOfficeMediasLinksToPublicLinks($notetoshow);
531
532 $tab_top = 88;
533
534 $pdf->SetFont('', '', $default_font_size - 1);
535 $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top, dol_htmlentitiesbr($notetoshow), 0, 1);
536 $nexY = $pdf->GetY();
537 $height_note = $nexY - $tab_top;
538
539 // Rect takes a length in 3rd parameter
540 $pdf->SetDrawColor(192, 192, 192);
541 $pdf->Rect($this->marge_gauche, $tab_top - 1, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $height_note + 1);
542
543 $tab_height = $tab_height - $height_note;
544 $tab_top = $nexY + 6;
545 } else {
546 $height_note = 0;
547 }
548
549 /*$iniY = $tab_top + 7;
550 $curY = $tab_top + 7;
551 $nexY = $tab_top + 7;
552
553 $tab_top = $tab_top_newpage + 25 + $top_shift;*/
554
555 // Show square
556 if ($pagenb == 1) {
557 $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 0, 0, $object->multicurrency_code);
558 $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
559 } else {
560 $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 1, 0, $object->multicurrency_code);
561 $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
562 }
563
564 $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
565
566 // Affiche zone infos
567 //$posy=$this->_tableau_info($pdf, $object, $bottomlasttab, $outputlangs);
568
569 // Affiche zone totaux
570 //$posy=$this->_tableau_tot($pdf, $object, $deja_regle, $bottomlasttab, $outputlangs);
571
572 // Pied de page
573 $this->_pagefoot($pdf, $object, $outputlangs);
574 if (method_exists($pdf, 'AliasNbPages')) {
575 $pdf->AliasNbPages();
576 }
577
578 $pdf->Close();
579
580 $pdf->Output($file, 'F');
581
582 // Add pdfgeneration hook
583 $hookmanager->initHooks(array('pdfgeneration'));
584 $parameters = array('file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs);
585 global $action;
586 $reshook = $hookmanager->executeHooks('afterPDFCreation', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
587 if ($reshook < 0) {
588 $this->error = $hookmanager->error;
589 $this->errors = $hookmanager->errors;
590 }
591
592 dolChmod($file);
593
594 $this->result = array('fullpath'=>$file);
595
596 return 1; // No error
597 } else {
598 $this->error = $langs->trans("ErrorCanNotCreateDir", $dir);
599 return 0;
600 }
601 } else {
602 $this->error = $langs->trans("ErrorConstantNotDefined", "PRODUCT_OUTPUTDIR");
603 return 0;
604 }
605 }
606
607 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
621 protected function _tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop = 0, $hidebottom = 0, $currency = '')
622 {
623 global $conf;
624
625 // Force to disable hidetop and hidebottom
626 $hidebottom = 0;
627 if ($hidetop) {
628 $hidetop = -1;
629 }
630
631 $currency = !empty($currency) ? $currency : $conf->currency;
632 $default_font_size = pdf_getPDFFontSize($outputlangs);
633
634 // Amount in (at tab_top - 1)
635 $pdf->SetTextColor(0, 0, 0);
636 $pdf->SetFont('', '', $default_font_size - 2);
637
638 if (empty($hidetop)) {
639 $titre = $outputlangs->transnoentities("AmountInCurrency", $outputlangs->transnoentitiesnoconv("Currency".$currency));
640 $pdf->SetXY($this->page_largeur - $this->marge_droite - ($pdf->GetStringWidth($titre) + 3), $tab_top - 4);
641 $pdf->MultiCell(($pdf->GetStringWidth($titre) + 3), 2, $titre);
642
643 //$conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR='230,230,230';
644 if (!empty($conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR)) {
645 $pdf->Rect($this->marge_gauche, $tab_top, $this->page_largeur - $this->marge_droite - $this->marge_gauche, 5, 'F', null, explode(',', $conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR));
646 }
647 }
648
649 $pdf->SetDrawColor(128, 128, 128);
650
651 $pdf->SetFont('', 'B', $default_font_size - 3);
652
653 // Output Rect
654 $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
655
656 $pdf->SetLineStyle(array('dash'=>'0', 'color'=>array(200, 200, 200)));
657 $pdf->SetDrawColor(200, 200, 200);
658 $pdf->line($this->marge_gauche, $tab_top, $this->page_largeur - $this->marge_droite, $tab_top);
659 $pdf->SetLineStyle(array('dash'=>0));
660 $pdf->SetDrawColor(128, 128, 128);
661 $pdf->SetTextColor(0, 0, 0);
662
663
664 if (empty($hidetop)) {
665 $pdf->line($this->marge_gauche, $tab_top+11, $this->page_largeur-$this->marge_droite, $tab_top+11); // line takes a position y in 2nd parameter and 4th parameter
666 $pdf->SetXY($this->posxdesc - 1, $tab_top + 1);
667 $pdf->MultiCell($this->wref, 3, $outputlangs->transnoentities("Ref"), '', 'L');
668 }
669
670 $pdf->line($this->posxlabel-1, $tab_top, $this->posxlabel-1, $tab_top + $tab_height);
671 if (empty($hidetop)) {
672 $pdf->SetXY($this->posxlabel - 1, $tab_top + 1);
673 $pdf->MultiCell($this->posxqty - $this->posxlabel - 1, 2, $outputlangs->transnoentities("Label"), '', 'C');
674 }
675
676 $pdf->line($this->posxqty-1, $tab_top, $this->posxqty-1, $tab_top + $tab_height);
677 if (empty($hidetop)) {
678 $pdf->SetXY($this->posxqty - 1, $tab_top + 1);
679 $pdf->MultiCell($this->posxup - $this->posxqty - 1, 2, $outputlangs->transnoentities("Units"), '', 'C');
680 }
681
682 $pdf->line($this->posxup-1, $tab_top, $this->posxup-1, $tab_top + $tab_height);
683 if (empty($hidetop)) {
684 $pdf->SetXY($this->posxup - 1, $tab_top + 1);
685 $pdf->MultiCell($this->posxunit - $this->posxup - 1, 2, $outputlangs->transnoentities("AverageUnitPricePMPShort"), '', 'C');
686 }
687
688 $pdf->line($this->posxunit - 1, $tab_top, $this->posxunit - 1, $tab_top + $tab_height);
689 if (empty($hidetop)) {
690 $pdf->SetXY($this->posxunit - 1, $tab_top + 1);
691 $pdf->MultiCell($this->posxdiscount - $this->posxunit - 1, 2, $outputlangs->transnoentities("EstimatedStockValueShort"), '', 'C');
692 }
693
694 $pdf->line($this->posxdiscount-1, $tab_top, $this->posxdiscount-1, $tab_top + $tab_height);
695 if (empty($hidetop)) {
696 $pdf->SetXY($this->posxdiscount - 1, $tab_top + 1);
697 $pdf->MultiCell($this->postotalht - $this->posxdiscount + 1, 2, $outputlangs->transnoentities("SellPriceMin"), '', 'C');
698 }
699
700 $pdf->line($this->postotalht, $tab_top, $this->postotalht, $tab_top + $tab_height);
701 if (empty($hidetop)) {
702 $pdf->SetXY($this->postotalht - 1, $tab_top + 1);
703 $pdf->MultiCell($this->page_largeur - $this->marge_droite - $this->postotalht, 2, $outputlangs->transnoentities("EstimatedStockValueSellShort"), '', 'C');
704 }
705
706 if (empty($hidetop)) {
707 $pdf->SetDrawColor(200, 200, 200);
708 $pdf->SetLineStyle(array('dash' => '0', 'color' => array(200, 200, 200)));
709 $pdf->line($this->marge_gauche, $tab_top + $this->tabTitleHeight, $this->page_largeur - $this->marge_droite, $tab_top + $this->tabTitleHeight);
710 $pdf->SetLineStyle(array('dash' => 0));
711 }
712 }
713
714 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
725 protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $titlekey = "")
726 {
727 global $conf, $langs, $db, $hookmanager;
728
729 // Load traductions files required by page
730 $outputlangs->loadLangs(array("main", "propal", "companies", "bills", "orders", "stocks"));
731
732 $default_font_size = pdf_getPDFFontSize($outputlangs);
733
734 if ($object->type == 1) {
735 $titlekey = 'ServiceSheet';
736 } else {
737 $titlekey = 'StockSheet';
738 }
739
740 pdf_pagehead($pdf, $outputlangs, $this->page_hauteur);
741
742 // Show Draft Watermark
743 if ($object->statut == 0 && (!empty($conf->global->STOCK_DRAFT_WATERMARK))) {
744 pdf_watermark($pdf, $outputlangs, $this->page_hauteur, $this->page_largeur, 'mm', $conf->global->STOCK_DRAFT_WATERMARK);
745 }
746
747 $pdf->SetTextColor(0, 0, 60);
748 $pdf->SetFont('', 'B', $default_font_size + 3);
749
750 $posy = $this->marge_haute;
751 $posx = $this->page_largeur - $this->marge_droite - 100;
752
753 $pdf->SetXY($this->marge_gauche, $posy);
754
755 // Logo
756 $height = 0;
757 $logo = $conf->mycompany->dir_output.'/logos/'.$this->emetteur->logo;
758 if ($this->emetteur->logo) {
759 if (is_readable($logo)) {
760 $height = pdf_getHeightForLogo($logo);
761 $pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto)
762 } else {
763 $pdf->SetTextColor(200, 0, 0);
764 $pdf->SetFont('', 'B', $default_font_size - 2);
765 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound", $logo), 0, 'L');
766 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorGoToGlobalSetup"), 0, 'L');
767 }
768 } else {
769 $text = $this->emetteur->name;
770 $pdf->MultiCell(100, 4, $outputlangs->convToOutputCharset($text), 0, 'L');
771 }
772
773 $yafterleft = $pdf->GetY() + $height;
774
775 $pdf->SetFont('', 'B', $default_font_size + 3);
776 $pdf->SetXY($posx, $posy);
777 $pdf->SetTextColor(0, 0, 60);
778
779 $pdf->MultiCell(100, 4, $outputlangs->transnoentities("Warehouse").' '.$outputlangs->convToOutputCharset($object->label), '', 'R');
780
781 $posy += 6;
782 $pdf->SetFont('', '', $default_font_size - 1);
783 $pdf->SetXY($posx, $posy);
784 $pdf->SetTextColor(0, 0, 60);
785 if (!empty($object->lieu)) {
786 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Label").' : '.$object->lieu, '', 'R');
787 }
788
789
790 $posy += 4;
791 $pdf->SetXY($posx, $posy);
792 $pdf->SetTextColor(0, 0, 60);
793
794 // Parent warehouse
795 $e = new Entrepot($this->db);
796 $hasparent = (!empty($object->fk_parent) && $e->fetch($object->fk_parent) > 0);
797
798 if ($hasparent) {
799 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ParentWarehouse").' :', '', 'R');
800
801 $posy += 4;
802 $pdf->SetXY($posx - 50, $posy);
803 $pdf->MultiCell(150, 3, $e->label, '', 'R');
804 }
805
806 $yafterright = $pdf->GetY();
807
808 // Description
809 $nbpage = $pdf->getPage();
810 if ($nbpage == 1) {
811 $nexY = max($yafterleft, $yafterright);
812 $nexY += 5;
813 $pdf->SetXY($posx, $posy);
814 $pdf->writeHTMLCell(190, 2, $this->marge_gauche, $nexY, '<b>'.$outputlangs->transnoentities("Description").' : </b>'.nl2br($object->description), 0, 1);
815 $nexY = $pdf->GetY();
816
817 $calcproductsunique = $object->nb_different_products();
818 $calcproducts = $object->nb_products();
819
820 // Total nb of different products
821 $pdf->writeHTMLCell(190, 2, $this->marge_gauche, $nexY, '<b>'.$outputlangs->transnoentities("NumberOfDifferentProducts").' : </b>'.(empty($calcproductsunique['nb']) ? '0' : $calcproductsunique['nb']), 0, 1);
822 $nexY = $pdf->GetY();
823
824 // Nb of products
825 $valtoshow = price2num($calcproducts['nb'], 'MS');
826 $pdf->writeHTMLCell(190, 2, $this->marge_gauche, $nexY, '<b>'.$outputlangs->transnoentities("NumberOfProducts").' : </b>'.(empty($valtoshow) ? '0' : $valtoshow), 0, 1);
827 $nexY = $pdf->GetY();
828
829 // Value
830 $pdf->writeHTMLCell(190, 2, $this->marge_gauche, $nexY, '<b>'.$outputlangs->transnoentities("EstimatedStockValueShort").' : </b>'.price((empty($calcproducts['value']) ? '0' : price2num($calcproducts['value'], 'MT')), 0, $langs, 0, -1, -1, $conf->currency), 0, 1);
831 $nexY = $pdf->GetY();
832
833 // Value
834 $pdf->writeHTMLCell(190, 2, $this->marge_gauche, $nexY, '<b>'.$outputlangs->transnoentities("Date").' : </b>'.dol_print_date(dol_now(), 'dayhour'), 0, 1);
835 $nexY = $pdf->GetY();
836
837 // Last movement
838 $sql = "SELECT max(m.datem) as datem";
839 $sql .= " FROM ".MAIN_DB_PREFIX."stock_mouvement as m";
840 $sql .= " WHERE m.fk_entrepot = ".((int) $object->id);
841 $resqlbis = $this->db->query($sql);
842 if ($resqlbis) {
843 $obj = $this->db->fetch_object($resqlbis);
844 $lastmovementdate = $this->db->jdate($obj->datem);
845 } else {
846 dol_print_error($this->db);
847 }
848
849 if ($lastmovementdate) {
850 $toWrite = dol_print_date($lastmovementdate, 'dayhour').' ';
851 } else {
852 $toWrite = $outputlangs->transnoentities("None");
853 }
854
855 $pdf->writeHTMLCell(190, 2, $this->marge_gauche, $nexY, '<b>'.$outputlangs->transnoentities("LastMovement").' : </b>'.$toWrite, 0, 1);
856 }
857 $nexY = $pdf->GetY();
858
859 $posy += 2;
860
861 $top_shift = 0;
862 // Show list of linked objects
863 $current_y = $pdf->getY();
864 $posy = pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, 100, 3, 'R', $default_font_size);
865 if ($current_y < $pdf->getY()) {
866 $top_shift = $pdf->getY() - $current_y;
867 }
868
869 $pdf->SetTextColor(0, 0, 0);
870
871 return $top_shift;
872 }
873
874 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
884 protected function _pagefoot(&$pdf, $object, $outputlangs, $hidefreetext = 0)
885 {
886 $showdetails = getDolGlobalInt('MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS', 0);
887 return pdf_pagefoot($pdf, $outputlangs, 'PRODUCT_FREE_TEXT', $this->emetteur, $this->marge_basse, $this->marge_gauche, $this->page_hauteur, $object, $showdetails, $hidefreetext);
888 }
889}
printRect($pdf, $x, $y, $l, $h, $hidetop=0, $hidebottom=0)
Rect pdf.
Class to manage warehouses.
Class to manage hooks.
Parent class for stock models of doc generators.
Class to manage predefined suppliers products.
Class to manage products or services.
Class to generate expense report based on standard model.
__construct($db)
Constructor.
_tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop=0, $hidebottom=0, $currency='')
Show table for lines.
_pagehead(&$pdf, $object, $showaddress, $outputlangs)
Show top header of page.
_pagehead(&$pdf, $object, $showaddress, $outputlangs, $titlekey="")
Show top header of page.
_pagefoot(&$pdf, $object, $outputlangs, $hidefreetext=0)
Show footer of page.
write_file($object, $outputlangs, $srctemplatepath='', $hidedetails=0, $hidedesc=0, $hideref=0)
Function to build a document on disk using the generic odt module.
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...
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
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.
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return dolibarr global constant int value.
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_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
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_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_pagehead(&$pdf, $outputlangs, $page_height)
Show header of page for PDF generation.
Definition pdf.lib.php:726
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_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
pdf_watermark(&$pdf, $outputlangs, $h, $w, $unit, $text)
Add a draft watermark on PDF files.
Definition pdf.lib.php:778
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