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