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