dolibarr 22.0.5
pdf_standard_stock.modules.php
1<?php
2
3/* Copyright (C) 2017 Laurent Destailleur <eldy@stocks.sourceforge.net>
4 * Copyright (C) 2022 Ferran Marcet <fmarcet@2byte.es>
5 * Copyright (C) 2022 Nicolas Silobre <nsilobre@ns-info90.fr>
6 * Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
7 * Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
8 * Copyright (C) 2024 Nick Fragoulis
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 * or see https://www.gnu.org/
23 */
24
31require_once DOL_DOCUMENT_ROOT.'/core/modules/stock/modules_stock.php';
32require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
33require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
34require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
35require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
36require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
37require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
38
39
44{
48 public $wref;
52 public $posxdesc;
56 public $posxlabel;
60 public $posxtva;
64 public $posxqty;
68 public $posxup;
72 public $posxunit;
76 public $posxdiscount;
80 public $postotalht;
81
85 public $tabTitleHeight;
86
87
93 public function __construct($db)
94 {
95 global $conf, $langs, $mysoc;
96
97 // Load traductions files required by page
98 $langs->loadLangs(array("main", "companies"));
99
100 $this->db = $db;
101 $this->name = "standard";
102 $this->description = $langs->trans("DocumentModelStandardPDF");
103
104 // Page size for A4 format
105 $this->type = 'pdf';
106 $formatarray = pdf_getFormat();
107 $this->page_largeur = $formatarray['width'];
108 $this->page_hauteur = $formatarray['height'];
109 $this->format = array($this->page_largeur, $this->page_hauteur);
110 $this->marge_gauche = getDolGlobalInt('MAIN_PDF_MARGIN_LEFT', 10);
111 $this->marge_droite = getDolGlobalInt('MAIN_PDF_MARGIN_RIGHT', 10);
112 $this->marge_haute = getDolGlobalInt('MAIN_PDF_MARGIN_TOP', 10);
113 $this->marge_basse = getDolGlobalInt('MAIN_PDF_MARGIN_BOTTOM', 10);
114 $this->corner_radius = getDolGlobalInt('MAIN_PDF_FRAME_CORNER_RADIUS', 0);
115 $this->option_logo = 1; // Display logo
116 $this->option_multilang = 1; // Available in several languages
117 $this->option_freetext = 0; // Support add of a personalised text
118
119 // Define position of columns
120 $this->wref = 35;
121 $this->posxdesc = $this->marge_gauche + 1;
122 $this->posxlabel = $this->posxdesc + $this->wref;
123 $this->posxtva = 80;
124 $this->posxqty = 95;
125 $this->posxup = 115;
126 $this->posxunit = 135;
127 $this->posxdiscount = 155;
128 $this->postotalht = 175;
129
130 if (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT') || getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_COLUMN')) {
131 $this->posxtva = $this->posxup;
132 }
133 $this->posxpicture = $this->posxtva - getDolGlobalInt('MAIN_DOCUMENTS_WITH_PICTURE_WIDTH', 20); // width of images
134 if ($this->page_largeur < 210) { // To work with US executive format
135 $this->posxpicture -= 20;
136 $this->posxtva -= 20;
137 $this->posxup -= 20;
138 $this->posxqty -= 20;
139 $this->posxunit -= 20;
140 $this->posxdiscount -= 20;
141 $this->postotalht -= 20;
142 }
143
144 $this->tabTitleHeight = 11;
145
146 if ($mysoc === null) {
147 dol_syslog(get_class($this).'::__construct() Global $mysoc should not be null.'. getCallerInfoString(), LOG_ERR);
148 return;
149 }
150
151 // Get source company
152 $this->emetteur = $mysoc;
153 if (!$this->emetteur->country_code) {
154 $this->emetteur->country_code = substr($langs->defaultlang, -2); // By default if not defined
155 }
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 (getDolGlobalString('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(true, 0);
226
227 $heightforinfotot = 40; // Height reserved to output the info and total part
228 $heightforfreetext = getDolGlobalInt('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 (getDolGlobalString('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 (!getDolGlobalString('MAIN_DISABLE_FPDI') && getDolGlobalString('MAIN_ADD_PDF_BACKGROUND')) {
241 $pagecount = $pdf->setSourceFile($conf->mycompany->dir_output.'/' . getDolGlobalString('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 (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) {
255 $pdf->SetCompression(false);
256 }
257
258 // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
259 $pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite); // Left, Top, Right
260
261
262 // New page
263 $pdf->AddPage();
264 if (!empty($tplidx)) {
265 $pdf->useTemplate($tplidx);
266 }
267 $pagenb++;
268 $top_shift = $this->_pagehead($pdf, $object, 1, $outputlangs);
269 $pdf->SetFont('', '', $default_font_size - 1);
270 $pdf->MultiCell(0, 3, ''); // Set interline to 3
271 $pdf->SetTextColor(0, 0, 0);
272
273 $tab_top = 65 + $top_shift;
274 $tab_top_newpage = (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD') ? 42 + $top_shift : 10);
275
276 $tab_height = $this->page_hauteur - $tab_top - $heightforfooter - $heightforfreetext;
277
278
279 // Show list of product in warehouse */
280
281 $totalunit = 0;
282 $totalvalue = $totalvaluesell = 0;
283
284 $sortfield = 'p.ref';
285 $sortorder = 'ASC';
286
287 $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,";
288 $sql .= " ps.reel as value";
289 $sql .= " FROM ".MAIN_DB_PREFIX."product_stock as ps, ".MAIN_DB_PREFIX."product as p";
290 $sql .= " WHERE ps.fk_product = p.rowid";
291 $sql .= " AND ps.reel <> 0"; // We do not show if stock is 0 (no product in this warehouse)
292 $sql .= " AND ps.fk_entrepot = ".((int) $object->id);
293 $sql .= $this->db->order($sortfield, $sortorder);
294
295 //dol_syslog('List products', LOG_DEBUG);
296 $resql = $this->db->query($sql);
297 if ($resql) {
298 $num = $this->db->num_rows($resql);
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 (getDolGlobalInt('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('', true, $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('', true, $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 (!getDolGlobalInt('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 (getDolGlobalString('MAIN_PDF_DATA_ON_FIRST_PAGE')) {
366 $showpricebeforepagebreak = 1;
367 } else {
368 $showpricebeforepagebreak = 0;
369 }
370 }
371 } else { // No pagebreak
372 $pdf->commitTransaction();
373 }
374 $posYAfterDescription = $pdf->GetY();
375
376 $nexY = $pdf->GetY();
377 $pageposafter = $pdf->getPage();
378
379 $pdf->setPage($pageposbefore);
380 $pdf->setTopMargin($this->marge_haute);
381 $pdf->setPageOrientation('', true, 0); // The only function to edit the bottom margin of current page to set it.
382
383 // We suppose that a too long description is moved completely on next page
384 if ($pageposafter > $pageposbefore && empty($showpricebeforepagebreak)) {
385 $pdf->setPage($pageposafter);
386 $curY = $tab_top_newpage;
387 }
388
389 $pdf->SetFont('', '', $default_font_size - 1); // On repositionne la police par default
390
391 $productstatic->id = $objp->rowid;
392 $productstatic->ref = $objp->ref;
393 $productstatic->label = $objp->produit;
394 $productstatic->type = $objp->type;
395 $productstatic->entity = $objp->entity;
396 $productstatic->status_batch = $objp->tobatch;
397
398 // Ref.
399 //$pdf->SetXY($this->posxdesc, $curY);
400 //$pdf->MultiCell($this->wref, 3, $productstatic->ref, 0, 'L');
401
402 // Label
403 $pdf->SetXY($this->posxlabel + 0.8, $curY);
404 $pdf->MultiCell($this->posxqty - $this->posxlabel - 0.8, 3, dol_trunc($productstatic->label, 24), 0, 'L');
405
406 // Quantity
407 $valtoshow = price2num($objp->value, 'MS');
408 $towrite = (empty($valtoshow) ? '0' : $valtoshow);
409
410 $pdf->SetXY($this->posxqty, $curY);
411 $pdf->MultiCell($this->posxup - $this->posxqty - 0.8, 3, $towrite, 0, 'R');
412
413 // AWP
414 $totalunit += $objp->value;
415
416 $pdf->SetXY($this->posxup, $curY);
417 $pdf->MultiCell($this->posxunit - $this->posxup - 0.8, 3, price(price2num($objp->ppmp, 'MU'), 0, $outputlangs), 0, 'R');
418
419 // Total PMP
420 $pdf->SetXY($this->posxunit, $curY);
421 $pdf->MultiCell($this->posxdiscount - $this->posxunit - 0.8, 3, price(price2num($objp->ppmp * $objp->value, 'MT'), 0, $outputlangs), 0, 'R');
422 $totalvalue += price2num($objp->ppmp * $objp->value, 'MT');
423
424 $pricemin = 0;
425 // Price sell min
426 if (!getDolGlobalString('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', false);
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', false);
434 }
435 $totalvaluesell += price2num($pricemin * $objp->value, 'MT');
436
437 // Add line
438 if (getDolGlobalString('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('', true, 0); // The only function to edit the bottom margin of current page to set it.
460 if (!getDolGlobalInt('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 (!getDolGlobalInt('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 (!getDolGlobalString('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', false);
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->RoundedRect($this->marge_gauche, $tab_top - 1, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $height_note + 2, $this->corner_radius, '1234', 'D');
548
549 $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(); // @phan-suppress-current-line PhanUndeclaredMethod
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 dolChmod($file);
599
600 $this->result = array('fullpath' => $file);
601
602 return 1; // No error
603 } else {
604 $this->error = $langs->trans("ErrorCanNotCreateDir", $dir);
605 return 0;
606 }
607 } else {
608 $this->error = $langs->trans("ErrorConstantNotDefined", "PRODUCT_OUTPUTDIR");
609 return 0;
610 }
611 }
612
613 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
627 protected function _tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop = 0, $hidebottom = 0, $currency = '')
628 {
629 global $conf;
630
631 // Force to disable hidetop and hidebottom
632 $hidebottom = 0;
633 if ($hidetop) {
634 $hidetop = -1;
635 }
636
637 $currency = !empty($currency) ? $currency : $conf->currency;
638 $default_font_size = pdf_getPDFFontSize($outputlangs);
639
640 // Amount in (at tab_top - 1)
641 $pdf->SetTextColor(0, 0, 0);
642 $pdf->SetFont('', '', $default_font_size - 2);
643
644 if (empty($hidetop)) {
645 $titre = $outputlangs->transnoentities("AmountInCurrency", $outputlangs->transnoentitiesnoconv("Currency".$currency));
646 $pdf->SetXY($this->page_largeur - $this->marge_droite - ($pdf->GetStringWidth($titre) + 3), $tab_top - 4);
647 $pdf->MultiCell(($pdf->GetStringWidth($titre) + 3), 2, $titre);
648
649 //$conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR='230,230,230';
650 if (getDolGlobalString('MAIN_PDF_TITLE_BACKGROUND_COLOR')) {
651 $pdf->RoundedRect($this->marge_gauche, $tab_top, $this->page_largeur - $this->marge_droite - $this->marge_gauche, 5, $this->corner_radius, '1001', 'F', array(), explode(',', getDolGlobalString('MAIN_PDF_TITLE_BACKGROUND_COLOR')));
652 }
653 }
654
655 $pdf->SetDrawColor(128, 128, 128);
656
657 $pdf->SetFont('', 'B', $default_font_size - 3);
658
659 // Output Rect
660 $this->printRoundedRect($pdf, $this->marge_gauche, $tab_top, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $tab_height, $this->corner_radius, $hidetop, $hidebottom, 'D'); // Rect takes a length in 3rd parameter and 4th parameter
661
662 $pdf->SetLineStyle(array('dash' => '0', 'color' => array(200, 200, 200)));
663 $pdf->SetDrawColor(200, 200, 200);
664 $pdf->line($this->marge_gauche, $tab_top, $this->page_largeur - $this->marge_droite, $tab_top);
665 $pdf->SetLineStyle(array('dash' => 0));
666 $pdf->SetDrawColor(128, 128, 128);
667 $pdf->SetTextColor(0, 0, 0);
668
669
670 if (empty($hidetop)) {
671 $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
672 $pdf->SetXY($this->posxdesc - 1, $tab_top + 1);
673 $pdf->MultiCell($this->wref, 3, $outputlangs->transnoentities("Ref"), '', 'L');
674 }
675
676 $pdf->line($this->posxlabel - 1, $tab_top, $this->posxlabel - 1, $tab_top + $tab_height);
677 if (empty($hidetop)) {
678 $pdf->SetXY($this->posxlabel - 1, $tab_top + 1);
679 $pdf->MultiCell($this->posxqty - $this->posxlabel - 1, 2, $outputlangs->transnoentities("Label"), '', 'C');
680 }
681
682 $pdf->line($this->posxqty - 1, $tab_top, $this->posxqty - 1, $tab_top + $tab_height);
683 if (empty($hidetop)) {
684 $pdf->SetXY($this->posxqty - 1, $tab_top + 1);
685 $pdf->MultiCell($this->posxup - $this->posxqty - 1, 2, $outputlangs->transnoentities("Units"), '', 'C');
686 }
687
688 $pdf->line($this->posxup - 1, $tab_top, $this->posxup - 1, $tab_top + $tab_height);
689 if (empty($hidetop)) {
690 $pdf->SetXY($this->posxup - 1, $tab_top + 1);
691 $pdf->MultiCell($this->posxunit - $this->posxup - 1, 2, $outputlangs->transnoentities("AverageUnitPricePMPShort"), '', 'C');
692 }
693
694 $pdf->line($this->posxunit - 1, $tab_top, $this->posxunit - 1, $tab_top + $tab_height);
695 if (empty($hidetop)) {
696 $pdf->SetXY($this->posxunit - 1, $tab_top + 1);
697 $pdf->MultiCell($this->posxdiscount - $this->posxunit - 1, 2, $outputlangs->transnoentities("EstimatedStockValueShort"), '', 'C');
698 }
699
700 $pdf->line($this->posxdiscount - 1, $tab_top, $this->posxdiscount - 1, $tab_top + $tab_height);
701 if (empty($hidetop)) {
702 $pdf->SetXY($this->posxdiscount - 1, $tab_top + 1);
703 $pdf->MultiCell($this->postotalht - $this->posxdiscount + 1, 2, $outputlangs->transnoentities("SellPriceMin"), '', 'C');
704 }
705
706 $pdf->line($this->postotalht, $tab_top, $this->postotalht, $tab_top + $tab_height);
707 if (empty($hidetop)) {
708 $pdf->SetXY($this->postotalht - 1, $tab_top + 1);
709 $pdf->MultiCell($this->page_largeur - $this->marge_droite - $this->postotalht, 2, $outputlangs->transnoentities("EstimatedStockValueSellShort"), '', 'C');
710 }
711
712 if (empty($hidetop)) {
713 $pdf->SetDrawColor(200, 200, 200);
714 $pdf->SetLineStyle(array('dash' => '0', 'color' => array(200, 200, 200)));
715 $pdf->line($this->marge_gauche, $tab_top + $this->tabTitleHeight, $this->page_largeur - $this->marge_droite, $tab_top + $this->tabTitleHeight);
716 $pdf->SetLineStyle(array('dash' => 0));
717 }
718 }
719
720 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
731 protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $titlekey = "")
732 {
733 global $conf, $langs;
734
735 // Load traductions files required by page
736 $outputlangs->loadLangs(array("main", "propal", "companies", "bills", "orders", "stocks"));
737
738 $default_font_size = pdf_getPDFFontSize($outputlangs);
739
740 pdf_pagehead($pdf, $outputlangs, $this->page_hauteur);
741
742 // Show Draft Watermark
743 if ($object->statut == 0 && (getDolGlobalString('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 $lastmovementdate = 0;
842 $resqlbis = $this->db->query($sql);
843 if ($resqlbis) {
844 $obj = $this->db->fetch_object($resqlbis);
845 $lastmovementdate = $this->db->jdate($obj->datem);
846 } else {
847 dol_print_error($this->db);
848 }
849
850 if ($lastmovementdate) {
851 $toWrite = dol_print_date($lastmovementdate, 'dayhour').' ';
852 } else {
853 $toWrite = $outputlangs->transnoentities("None");
854 }
855
856 $pdf->writeHTMLCell(190, 2, $this->marge_gauche, $nexY, '<b>'.$outputlangs->transnoentities("LastMovement").' : </b>'.$toWrite, 0, 1);
857 }
858 $nexY = $pdf->GetY();
859
860 $posy += 2;
861
862 $top_shift = 0;
863 // Show list of linked objects
864 $current_y = $pdf->getY();
865 $posy = pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, 100, 3, 'R', $default_font_size);
866 if ($current_y < $pdf->getY()) {
867 $top_shift = $pdf->getY() - $current_y;
868 }
869
870 $pdf->SetTextColor(0, 0, 0);
871
872 return $top_shift;
873 }
874
875 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
885 protected function _pagefoot(&$pdf, $object, $outputlangs, $hidefreetext = 0)
886 {
887 $showdetails = getDolGlobalInt('MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS', 0);
888 return pdf_pagefoot($pdf, $outputlangs, 'PRODUCT_FREE_TEXT', $this->emetteur, $this->marge_basse, $this->marge_gauche, $this->page_hauteur, $object, $showdetails, $hidefreetext);
889 }
890}
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:67
printRoundedRect($pdf, $x, $y, $w, $h, $r, $hidetop=0, $hidebottom=0, $style='D')
Print a rounded rectangle on the 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 build documents using ODF templates generator.
_tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop=0, $hidebottom=0, $currency='')
Show table for lines.
write_file($object, $outputlangs, $srctemplatepath='', $hidedetails=0, $hidedesc=0, $hideref=0)
Function to build a document on disk.
_pagefoot(&$pdf, $object, $outputlangs, $hidefreetext=0)
Show footer of page.
_pagehead(&$pdf, $object, $showaddress, $outputlangs, $titlekey="")
Show top header of page.
print $script_file $mode $langs defaultlang(is_numeric($duration_value) ? " delay=". $duration_value :"").(is_numeric($duration_value2) ? " after cd cd cd description as description
Only used if Module[ID]Desc translation string is not found.
if(!function_exists( 'dolEscapeXML')) convertBackOfficeMediasLinksToPublicLinks($notetoshow)
Convert links to local wrapper to medias files into a string into a public external URL readable on i...
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
getCallerInfoString()
Get caller info as a string that can be appended to a log message.
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_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...
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0)
Clean a string to use it as a file name.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
Definition member.php:79
pdf_getFormat($outputlangs=null, $mode='setup')
Return array with format properties of default PDF format.
Definition pdf.lib.php:87
pdf_getPDFFontSize($outputlangs)
Return font size to use for PDF generation.
Definition pdf.lib.php:289
pdf_getHeightForLogo($logo, $url=false)
Return height to use for Logo onto PDF.
Definition pdf.lib.php:314
pdf_pagefoot(&$pdf, $outputlangs, $paramfreetext, $fromcompany, $marge_basse, $marge_gauche, $page_hauteur, $object, $showdetails=0, $hidefreetext=0, $page_largeur=0, $watermark='')
Show footer of page for PDF generation.
Definition pdf.lib.php:1047
pdf_pagehead(&$pdf, $outputlangs, $page_height)
Show header of page for PDF generation.
Definition pdf.lib.php:742
pdf_writeLinkedObjects(&$pdf, $object, $outputlangs, $posx, $posy, $w, $h, $align, $default_font_size)
Show linked objects for PDF generation.
Definition pdf.lib.php:1425
pdf_getPDFFont($outputlangs)
Return font name to use for PDF generation.
Definition pdf.lib.php:266
pdf_getSubstitutionArray($outputlangs, $exclude=null, $object=null, $onlykey=0, $include=null)
Return array of possible substitutions for PDF content (without external module substitutions).
Definition pdf.lib.php:778
pdf_getInstance($format='', $metric='mm', $pagetype='P')
Return a PDF instance object.
Definition pdf.lib.php:129
pdf_watermark(&$pdf, $outputlangs, $h, $w, $unit, $text)
Add a draft watermark on PDF files.
Definition pdf.lib.php:798
if(preg_match('/(crypted|dolcrypt):/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition repair.php:158
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:161