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