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 *
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
29require_once DOL_DOCUMENT_ROOT.'/core/modules/stock/modules_stock.php';
30require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
31require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
32require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
33require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
34require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
35require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
36
37
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 = getDolGlobalInt('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 -= $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(); // @phan-suppress-current-line PhanUndeclaredMethod
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', array(), 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 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 '.
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_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:1022
pdf_pagehead(&$pdf, $outputlangs, $page_height)
Show header of page for PDF generation.
Definition pdf.lib.php:731
pdf_writeLinkedObjects(&$pdf, $object, $outputlangs, $posx, $posy, $w, $h, $align, $default_font_size)
Show linked objects for PDF generation.
Definition pdf.lib.php:1398
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:767
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:787
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