dolibarr  19.0.0-dev
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 $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 }
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:8366
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:4059
dol_sanitizeFileName
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
Definition: functions.lib.php:1323
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:85
ProductFournisseur
Class to manage predefined suppliers products.
Definition: fournisseur.product.class.php:40
pdf_getInstance
pdf_getInstance($format='', $metric='mm', $pagetype='P')
Return a PDF instance object.
Definition: pdf.lib.php:127
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:5107
pdf_getPDFFont
pdf_getPDFFont($outputlangs)
Return font name to use for PDF generation.
Definition: pdf.lib.php:266
pdf_standard\_pagefoot
_pagefoot(&$pdf, $object, $outputlangs, $hidefreetext=0)
Show footer of page.
Definition: pdf_standard.modules.php:1125
pdf_standard\_pagehead
_pagehead(&$pdf, $object, $showaddress, $outputlangs)
Show top header of page.
Definition: pdf_standard.modules.php:648
ModelePDFStock
Parent class for stock models of doc generators.
Definition: modules_stock.php:24
name
$conf db name
Definition: repair.php:123
price2num
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
Definition: functions.lib.php:5955
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:2675
dolChmod
dolChmod($filepath, $newmask='')
Change mod of a file.
Definition: functions.lib.php:7007
pdf_pagehead
pdf_pagehead(&$pdf, $outputlangs, $page_height)
Show header of page for PDF generation.
Definition: pdf.lib.php:721
pdf_standard\_pagehead
_pagehead(&$pdf, $object, $showaddress, $outputlangs, $titlekey="")
Show top header of page.
Definition: pdf_standard.modules.php:725
pdf_watermark
pdf_watermark(&$pdf, $outputlangs, $h, $w, $unit, $text)
Add a draft watermark on PDF files.
Definition: pdf.lib.php:773
pdf_getHeightForLogo
pdf_getHeightForLogo($logo, $url=false)
Return height to use for Logo onto PDF.
Definition: pdf.lib.php:314
CommonDocGenerator\printRect
printRect($pdf, $x, $y, $l, $h, $hidetop=0, $hidebottom=0)
Rect pdf.
Definition: commondocgenerator.class.php:1038
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:1333
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:2726
$sql
if(isModEnabled('facture') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') && $user->hasRight('don', 'lire')) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->hasRight("commande", "lire") &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $sql
Social contributions to pay.
Definition: index.php:746
getDolGlobalString
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
Definition: functions.lib.php:142
pdf_standard\__construct
__construct($db)
Constructor.
Definition: pdf_standard.modules.php:91
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:7469
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:165
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:895
Entrepot
Class to manage warehouses.
Definition: entrepot.class.php:35
dol_now
dol_now($mode='auto')
Return date for now.
Definition: functions.lib.php:3056
pdf_getSubstitutionArray
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:753
pdf_getPDFFontSize
pdf_getPDFFontSize($outputlangs)
Return font size to use for PDF generation.
Definition: pdf.lib.php:289
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:5829
dol_mkdir
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
Definition: functions.lib.php:6936
getDolGlobalInt
getDolGlobalInt($key, $default=0)
Return dolibarr global constant int value.
Definition: functions.lib.php:156
type
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition: repair.php:120
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:8489
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:1005