dolibarr 23.0.3
stock.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2006 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2008-2010 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2005-2009 Regis Houssin <regis.houssin@inodbox.com>
5 * Copyright (C) 2012-2013 Juanjo Menent <jmenent@2byte.es>
6 * Copyright (C) 2013-2018 Philippe Grand <philippe.grand@atoo-net.com>
7 * Copyright (C) 2013 Florian Henry <florian.henry@open-concept.pro>
8 * Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
9 * Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see <https://www.gnu.org/licenses/>.
23 */
24
30require '../main.inc.php';
31require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
32require_once DOL_DOCUMENT_ROOT.'/core/lib/stock.lib.php';
33require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
34
43// Load translation files required by the page
44$langs->loadLangs(array("admin", "stocks"));
45
46// Security check
47if (!$user->admin) {
49}
50
51$action = GETPOST('action', 'aZ09');
52$value = GETPOST('value', 'alpha');
53$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php
54$label = GETPOST('label', 'alpha');
55$scandir = GETPOST('scan_dir', 'alpha');
56$type = 'stock';
57$page_y = GETPOST('page_y');
58
59
60/*
61 * Action
62 */
63$error = 0;
64
65include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php';
66
67$reg = array();
68
69if ($action == 'update' || preg_match('/set_([a-z0-9_\-]+)/i', $action, $reg)) {
70 if ($action == 'update') {
71 $arrayofcode = array(
72 'STOCK_CALCULATE_ON_BILL', 'STOCK_CALCULATE_ON_VALIDATE_ORDER', 'STOCK_CALCULATE_ON_SHIPMENT', 'STOCK_CALCULATE_ON_SHIPMENT_CLOSE',
73 'STOCK_CALCULATE_ON_SUPPLIER_BILL', 'STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER', 'STOCK_CALCULATE_ON_RECEPTION', 'STOCK_CALCULATE_ON_RECEPTION_CLOSE', 'STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER',
74 'STOCK_DISALLOW_NEGATIVE_TRANSFER', 'STOCK_MUST_BE_ENOUGH_FOR_INVOICE', 'STOCK_MUST_BE_ENOUGH_FOR_ORDER', 'STOCK_MUST_BE_ENOUGH_FOR_SHIPMENT',
75 'STOCK_USE_REAL_STOCK_BY_DEFAULT_FOR_REPLENISHMENT'
76 );
77 } else {
78 $arrayofcode = array($reg[1]);
79 }
80
81 $result = 1;
82 foreach ($arrayofcode as $code) {
83 $value = 1;
84 if (GETPOSTISSET($code)) { // For the case of nojs=1
85 $value = GETPOST($code);
86 }
87
88 if ($value == 1) {
89 if (in_array($code, array('STOCK_CALCULATE_ON_BILL', 'STOCK_CALCULATE_ON_VALIDATE_ORDER', 'STOCK_CALCULATE_ON_SHIPMENT', 'STOCK_CALCULATE_ON_SHIPMENT_CLOSE'))) {
90 dolibarr_del_const($db, 'STOCK_CALCULATE_ON_BILL', $conf->entity);
91 dolibarr_del_const($db, 'STOCK_CALCULATE_ON_VALIDATE_ORDER', $conf->entity);
92 dolibarr_del_const($db, 'STOCK_CALCULATE_ON_SHIPMENT', $conf->entity);
93 dolibarr_del_const($db, 'STOCK_CALCULATE_ON_SHIPMENT_CLOSE', $conf->entity);
94 }
95 if (in_array($code, array('STOCK_CALCULATE_ON_SUPPLIER_BILL', 'STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER', 'STOCK_CALCULATE_ON_RECEPTION', 'STOCK_CALCULATE_ON_RECEPTION_CLOSE', 'STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER'))) {
96 dolibarr_del_const($db, 'STOCK_CALCULATE_ON_SUPPLIER_BILL', $conf->entity);
97 dolibarr_del_const($db, 'STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER', $conf->entity);
98 dolibarr_del_const($db, 'STOCK_CALCULATE_ON_RECEPTION', $conf->entity);
99 dolibarr_del_const($db, 'STOCK_CALCULATE_ON_RECEPTION_CLOSE', $conf->entity);
100 dolibarr_del_const($db, 'STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER', $conf->entity);
101 }
102 }
103
104 // If constant is for a unique choice, delete other choices
105 $result = dolibarr_set_const($db, $code, $value, 'chaine', 0, '', $conf->entity);
106 }
107
108 if ($result) {
109 header("Location: ".$_SERVER["PHP_SELF"].($page_y ? '?page_y='.$page_y : ''));
110 exit;
111 } else {
112 dol_print_error($db);
113 }
114}
115
116if ($action == 'update' || preg_match('/del_([a-z0-9_\-]+)/i', $action, $reg)) {
117 if ($action == 'update') {
118 $arrayofcode = array(
119 'STOCK_CALCULATE_ON_BILL', 'STOCK_CALCULATE_ON_VALIDATE_ORDER', 'STOCK_CALCULATE_ON_SHIPMENT', 'STOCK_CALCULATE_ON_SHIPMENT_CLOSE',
120 'STOCK_CALCULATE_ON_SUPPLIER_BILL', 'STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER', 'STOCK_CALCULATE_ON_RECEPTION', 'STOCK_CALCULATE_ON_RECEPTION_CLOSE', 'STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER',
121 );
122 } else {
123 $arrayofcode = array($reg[1]);
124 }
125
126 $result = 1;
127 foreach ($arrayofcode as $code) {
128 $result = dolibarr_del_const($db, $code, $conf->entity);
129 }
130 if ($result > 0) {
131 header("Location: ".$_SERVER["PHP_SELF"].($page_y ? '?page_y='.$page_y : ''));
132 exit;
133 } else {
134 dol_print_error($db);
135 }
136}
137
138if ($action == 'warehouse') {
139 $value = GETPOST('default_warehouse', 'alpha');
140 $res = dolibarr_set_const($db, "MAIN_DEFAULT_WAREHOUSE", $value, 'chaine', 0, '', $conf->entity);
141 if ($value == -1 || empty($value) && getDolGlobalString('MAIN_DEFAULT_WAREHOUSE')) {
142 $res = dolibarr_del_const($db, "MAIN_DEFAULT_WAREHOUSE", $conf->entity);
143 }
144 if (!($res > 0)) {
145 $error++;
146 }
147}
148
149if ($action == 'specimen') {
150 $modele = GETPOST('module', 'alpha');
151
152 $object = new Entrepot($db);
153 $object->initAsSpecimen();
154
155 // Search template files
156 $file = '';
157 $classname = '';
158 $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
159 foreach ($dirmodels as $reldir) {
160 $file = dol_buildpath($reldir."core/modules/stock/doc/pdf_".$modele.".modules.php", 0);
161 if (file_exists($file)) {
162 $classname = "pdf_".$modele;
163 break;
164 }
165 }
166
167 if ($classname !== '') {
168 require_once $file;
169
170 $module = new $classname($db);
171 '@phan-var-force ModelePDFStock $module';
172
173 if ($module->write_file($object, $langs) > 0) {
174 header("Location: ".DOL_URL_ROOT."/document.php?modulepart=stock&file=SPECIMEN.pdf");
175 return;
176 } else {
177 setEventMessages($module->error, null, 'errors');
178 dol_syslog($module->error, LOG_ERR);
179 }
180 } else {
181 setEventMessages($langs->trans("ErrorModuleNotFound"), null, 'errors');
182 dol_syslog($langs->trans("ErrorModuleNotFound"), LOG_ERR);
183 }
184} elseif ($action == 'set') {
185 // Activate a model
186 $ret = addDocumentModel($value, $type, $label, $scandir);
187} elseif ($action == 'del') {
188 $ret = delDocumentModel($value, $type);
189 if ($ret > 0) {
190 if (getDolGlobalString('STOCK_ADDON_PDF') == "$value") {
191 dolibarr_del_const($db, 'STOCK_ADDON_PDF', $conf->entity);
192 }
193 }
194} elseif ($action == 'setdoc') {
195 // Set default model
196 if (dolibarr_set_const($db, "STOCK_ADDON_PDF", $value, 'chaine', 0, '', $conf->entity)) {
197 // The constant that was read before the new set
198 // We therefore requires a variable to have a coherent view
199 $conf->global->STOCK_ADDON_PDF = $value;
200 }
201
202 // On active le modele
203 $ret = delDocumentModel($value, $type);
204 if ($ret > 0) {
205 $ret = addDocumentModel($value, $type, $label, $scandir);
206 }
207}
208
209
210/*
211 * View
212 */
213
214$form = new Form($db);
215$dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
216
217llxHeader('', $langs->trans("StockSetup"), '', '', 0, 0, '', '', '', 'mod-admin page-stock');
218
219$linkback = '<a href="'.dolBuildUrl(DOL_URL_ROOT.'/admin/modules.php', ['restore_lastsearch_values' => 1]).'">'.img_picto($langs->trans("BackToModuleList"), 'back', 'class="pictofixedwidth"').'<span class="hideonsmartphone">'.$langs->trans("BackToModuleList").'</span></a>';
220
221print load_fiche_titre($langs->trans("StockSetup"), $linkback, 'title_setup');
222
224
225print dol_get_fiche_head($head, 'general', $langs->trans("StockSetup"), -1, 'stock');
226
227$form = new Form($db);
228$formproduct = new FormProduct($db);
229
230
231$disableStockCalculateOn = array();
232if (getDolGlobalInt('PRODUIT_SOUSPRODUITS')) {
233 // If option virtual stock is enabled, we disable some mode for inc/dec stock change
234 // Why this ? As i don't see why, i comment this code by a hidden option
235 if (getDolGlobalString('PRODUIT_RESTRICT_STOCK_INCDEC_IF_SUBPRODUCTS_ENABLED')) {
236 $disableStockCalculateOn[] = 'BILL';
237 $disableStockCalculateOn[] = 'VALIDATE_ORDER';
238 // STOCK_CALCULATE_ON_SHIPMENT is ok so not disable
239 // STOCK_CALCULATE_ON_SHIPMENT_CLOSE is ok so not disabled
240
241 $disableStockCalculateOn[] = 'SUPPLIER_BILL';
242 $disableStockCalculateOn[] = 'SUPPLIER_VALIDATE_ORDER';
243
244 print info_admin($langs->trans('WhenProductVirtualOnOptionAreForced'));
245 }
246}
247if (isModEnabled('productbatch')) {
248 // If module lot/serial enabled, we disable some mode for inc/dec stock change
249 $langs->load("productbatch");
250 $disableStockCalculateOn[] = 'BILL';
251 $disableStockCalculateOn[] = 'VALIDATE_ORDER';
252 // STOCK_CALCULATE_ON_SHIPMENT is ok so not disable
253 // STOCK_CALCULATE_ON_SHIPMENT_CLOSE is ok so not disabled
254
255 $disableStockCalculateOn[] = 'SUPPLIER_BILL';
256 $disableStockCalculateOn[] = 'SUPPLIER_VALIDATE_ORDER';
257
258 $descmode = ""; $incmode = "";
259 /* $descmode = $langs->trans('DeStockOnShipmentOnClosing');
260 if (!isModEnabled('reception')) {
261 // STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER
262 $incmode = $langs->trans('ReStockOnDispatchOrder');
263 } else {
264 // STOCK_CALCULATE_ON_RECEPTION_CLOSE
265 $incmode = $langs->trans('StockOnReceptionOnClosing');
266 } */
267 print info_admin($langs->transnoentitiesnoconv("WhenProductBatchModuleOnOptionAreForced", $descmode, $incmode));
268}
269
270
271print info_admin($langs->trans("IfYouUsePointOfSaleCheckModule"));
272print '<br>';
273
274
275print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
276print '<input type="hidden" name="token" value="'.newToken().'">';
277print '<input type="hidden" name="action" value="update">';
278print '<input type="hidden" name="page_y" value="">';
279
280// Title rule for stock decrease
281print '<div class="div-table-responsive-no-min">'; // You can use div-table-responsive-no-min if you don't need reserved height for your table
282print '<table class="noborder centpercent">';
283print '<tr class="liste_titre">';
284print "<td>".$langs->trans("RuleForStockManagementDecrease")."</td>\n";
285print '<td class="right">'.$langs->trans("Status").'</td>'."\n";
286print '</tr>'."\n";
287
288$found = 0;
289
290print '<!-- STOCK_CALCULATE_ON_BILL -->';
291print '<tr class="oddeven">';
292print '<td>'.$langs->trans("DeStockOnBill").'</td>';
293print '<td class="right">';
294if (isModEnabled('invoice')) {
295 if ($conf->use_javascript_ajax) {
296 if (in_array('BILL', $disableStockCalculateOn)) {
297 print img_picto($langs->trans("Disabled"), 'off', 'class="opacitymedium"');
298 } else {
299 print ajax_constantonoff('STOCK_CALCULATE_ON_BILL', array(), null, 0, 0, 0, 2, 1, 0, '', '', 'reposition');
300 }
301 } else {
302 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
303 print $form->selectarray("STOCK_CALCULATE_ON_BILL", $arrval, getDolGlobalString('STOCK_CALCULATE_ON_BILL'));
304 }
305} else {
306 print '<span class="opacitymedium">'.$langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module30Name")).'</span>';
307}
308print "</td>\n</tr>\n";
309$found++;
310
311
312print '<!-- STOCK_CALCULATE_ON_VALIDATE_ORDER -->';
313print '<tr class="oddeven">';
314print '<td>'.$langs->trans("DeStockOnValidateOrder").'</td>';
315print '<td class="right">';
316if (isModEnabled('order')) {
317 if ($conf->use_javascript_ajax) {
318 if (in_array('VALIDATE_ORDER', $disableStockCalculateOn)) {
319 print img_picto($langs->trans("Disabled"), 'off', 'class="opacitymedium"');
320 } else {
321 print ajax_constantonoff('STOCK_CALCULATE_ON_VALIDATE_ORDER', array(), null, 0, 0, 0, 2, 1, 0, '', '', 'reposition');
322 }
323 } else {
324 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
325 print $form->selectarray("STOCK_CALCULATE_ON_VALIDATE_ORDER", $arrval, getDolGlobalString('STOCK_CALCULATE_ON_VALIDATE_ORDER'));
326 }
327} else {
328 print '<span class="opacitymedium">'.$langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module25Name")).'</span>';
329}
330print "</td>\n</tr>\n";
331$found++;
332
333//if (isModEnabled('shipping'))
334//{
335
336print '<!-- STOCK_CALCULATE_ON_SHIPMENT -->';
337print '<tr class="oddeven">';
338print '<td>'.$langs->trans("DeStockOnShipment").'</td>';
339print '<td class="right">';
340if (isModEnabled("shipping")) {
341 if ($conf->use_javascript_ajax) {
342 if (in_array('SHIPMENT', $disableStockCalculateOn)) {
343 print img_picto($langs->trans("Disabled"), 'off', 'class="opacitymedium"');
344 } else {
345 print ajax_constantonoff('STOCK_CALCULATE_ON_SHIPMENT', array(), null, 0, 0, 0, 2, 1, 0, '', '', 'reposition');
346 }
347 } else {
348 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
349 print $form->selectarray("STOCK_CALCULATE_ON_SHIPMENT", $arrval, getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT'));
350 }
351} else {
352 print '<span class="opacitymedium">'.$langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module80Name")).'</span>';
353}
354print "</td>\n</tr>\n";
355$found++;
356
357print '<!-- STOCK_CALCULATE_ON_SHIPMENT_CLOSE -->';
358print '<tr class="oddeven">';
359print '<td>'.$langs->trans("DeStockOnShipmentOnClosing").'</td>';
360print '<td class="right">';
361if (isModEnabled("shipping")) {
362 if ($conf->use_javascript_ajax) {
363 if (in_array('SHIPMENT_CLOSE', $disableStockCalculateOn)) {
364 print img_picto($langs->trans("Disabled"), 'off', 'class="opacitymedium"');
365 } else {
366 print ajax_constantonoff('STOCK_CALCULATE_ON_SHIPMENT_CLOSE', array(), null, 0, 0, 0, 2, 1, 0, '', '', 'reposition');
367 }
368 } else {
369 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
370 print $form->selectarray("STOCK_CALCULATE_ON_SHIPMENT_CLOSE", $arrval, getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT_CLOSE'));
371 }
372} else {
373 print '<span class="opacitymedium">'.$langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module80Name")).'</span>';
374}
375print "</td>\n</tr>\n";
376$found++;
377
378print '</table>';
379print '</div>';
380
381
382print '<br>';
383
384
385// Title rule for stock increase
386print '<div class="div-table-responsive-no-min">'; // You can use div-table-responsive-no-min if you don't need reserved height for your table
387print '<table class="noborder centpercent">';
388print '<tr class="liste_titre">';
389print "<td>".$langs->trans("RuleForStockManagementIncrease")."</td>\n";
390print '<td class="right">'.$langs->trans("Status").'</td>'."\n";
391print '</tr>'."\n";
392
393$found = 0;
394
395print '<!-- STOCK_CALCULATE_ON_SUPPLIER_BILL -->';
396print '<tr class="oddeven">';
397print '<td>'.$langs->trans("ReStockOnBill").'</td>';
398print '<td class="right">';
399if (isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) {
400 if ($conf->use_javascript_ajax) {
401 if (in_array('SUPPLIER_BILL', $disableStockCalculateOn)) {
402 print img_picto($langs->trans("Disabled"), 'off', 'class="opacitymedium"');
403 } else {
404 print ajax_constantonoff('STOCK_CALCULATE_ON_SUPPLIER_BILL', array(), null, 0, 0, 0, 2, 1, 0, '', '', 'reposition');
405 }
406 } else {
407 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
408 print $form->selectarray("STOCK_CALCULATE_ON_SUPPLIER_BILL", $arrval, getDolGlobalString('STOCK_CALCULATE_ON_SUPPLIER_BILL'));
409 }
410} else {
411 print '<span class="opacitymedium">'.$langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module40Name")).'</span>';
412}
413print "</td>\n</tr>\n";
414$found++;
415
416
417print '<!-- STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER -->';
418print '<tr class="oddeven">';
419print '<td>'.$langs->trans("ReStockOnValidateOrder").'</td>';
420print '<td class="right">';
421if (isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) {
422 if ($conf->use_javascript_ajax) {
423 if (in_array('SUPPLIER_VALIDATE_ORDER', $disableStockCalculateOn)) {
424 print img_picto($langs->trans("Disabled"), 'off', 'class="opacitymedium"');
425 } else {
426 print ajax_constantonoff('STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER', array(), null, 0, 0, 0, 2, 1, 0, '', '', 'reposition');
427 }
428 } else {
429 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
430 print $form->selectarray("STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER", $arrval, getDolGlobalString('STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER'));
431 }
432} else {
433 print '<span class="opacitymedium">'.$langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module40Name")).'</span>';
434}
435print "</td>\n</tr>\n";
436$found++;
437
438if (isModEnabled("reception")) {
439 print '<!-- STOCK_CALCULATE_ON_RECEPTION -->';
440 print '<tr class="oddeven">';
441 print '<td>'.$langs->trans("StockOnReception").'</td>';
442 print '<td class="right">';
443
444 if ($conf->use_javascript_ajax) {
445 if (in_array('RECEPTION', $disableStockCalculateOn)) {
446 print img_picto($langs->trans("Disabled"), 'off', 'class="opacitymedium"');
447 } else {
448 print ajax_constantonoff('STOCK_CALCULATE_ON_RECEPTION', array(), null, 0, 0, 0, 2, 1, 0, '', '', 'reposition');
449 }
450 } else {
451 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
452 print $form->selectarray("STOCK_CALCULATE_ON_RECEPTION", $arrval, getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION'));
453 }
454
455 print "</td>\n</tr>\n";
456 $found++;
457
458 print '<!-- STOCK_CALCULATE_ON_RECEPTION_CLOSE -->';
459 print '<tr class="oddeven">';
460 print '<td>'.$langs->trans("StockOnReceptionOnClosing").'</td>';
461 print '<td class="right">';
462
463 if ($conf->use_javascript_ajax) {
464 if (in_array('RECEPTION_CLOSE', $disableStockCalculateOn)) {
465 print img_picto($langs->trans("Disabled"), 'off', 'class="opacitymedium"');
466 } else {
467 print ajax_constantonoff('STOCK_CALCULATE_ON_RECEPTION_CLOSE', array(), null, 0, 0, 0, 2, 1, 0, '', '', 'reposition');
468 }
469 } else {
470 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
471 print $form->selectarray("STOCK_CALCULATE_ON_RECEPTION_CLOSE", $arrval, getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION_CLOSE'));
472 }
473 print "</td>\n</tr>\n";
474 $found++;
475} else {
476 // When module Reception is not enabled, option to increase real stocks on manual dispatching into warehouse, after purchase order receipt of goods
477 print '<!-- STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER -->';
478 print '<tr class="oddeven">';
479 print '<td>'.$langs->trans("ReStockOnDispatchOrder").'</td>';
480 print '<td class="right">';
481 if (isModEnabled("supplier_order")) {
482 if ($conf->use_javascript_ajax) {
483 if (in_array('SUPPLIER_DISPATCH_ORDER', $disableStockCalculateOn)) {
484 print img_picto($langs->trans("Disabled"), 'off', 'class="opacitymedium"');
485 } else {
486 print ajax_constantonoff('STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER', array(), null, 0, 0, 0, 2, 1, 0, '', '', 'reposition');
487 }
488 } else {
489 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
490 print $form->selectarray("STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER", $arrval, getDolGlobalString('STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER'));
491 }
492 } else {
493 print '<span class="opacitymedium">'.$langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module40Name")).'</span>';
494 }
495 print "</td>\n</tr>\n";
496 $found++;
497}
498
499print '</table>';
500print '</div>';
501
502print '<br>';
503
504print '<div class="div-table-responsive-no-min">'; // You can use div-table-responsive-no-min if you don't need reserved height for your table
505print '<table class="noborder centpercent">';
506print '<tr class="liste_titre">';
507print "<td>".$langs->trans("RuleForStockAvailability")."</td>\n";
508print '<td class="right">'.$langs->trans("Status").'</td>'."\n";
509print '</tr>'."\n";
510
511
512print '<tr class="oddeven">';
513print '<td>'.$langs->trans("WarehouseAllowNegativeTransfer").'</td>';
514print '<td class="right">';
515if ($conf->use_javascript_ajax) {
516 print ajax_constantonoff('STOCK_DISALLOW_NEGATIVE_TRANSFER', array(), null, 1);
517} else {
518 $arrval = array('1' => $langs->trans("No"), '0' => $langs->trans("Yes"));
519 print $form->selectarray("STOCK_DISALLOW_NEGATIVE_TRANSFER", $arrval, getDolGlobalInt('STOCK_DISALLOW_NEGATIVE_TRANSFER'));
520}
521print "</td>\n";
522print "</tr>\n";
523
524// Option to force stock to be enough before adding a line into document
525if (isModEnabled('invoice')) {
526 print '<tr class="oddeven">';
527 print '<td>'.$langs->trans("StockMustBeEnoughForInvoice").'</td>';
528 print '<td class="right">';
529 if ($conf->use_javascript_ajax) {
530 print ajax_constantonoff('STOCK_MUST_BE_ENOUGH_FOR_INVOICE');
531 } else {
532 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
533 print $form->selectarray("STOCK_MUST_BE_ENOUGH_FOR_INVOICE", $arrval, getDolGlobalString('STOCK_MUST_BE_ENOUGH_FOR_INVOICE'));
534 }
535 print "</td>\n";
536 print "</tr>\n";
537}
538
539if (isModEnabled('order')) {
540 print '<tr class="oddeven">';
541 print '<td>'.$langs->trans("StockMustBeEnoughForOrder").'</td>';
542 print '<td class="right">';
543 if ($conf->use_javascript_ajax) {
544 print ajax_constantonoff('STOCK_MUST_BE_ENOUGH_FOR_ORDER');
545 } else {
546 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
547 print $form->selectarray("STOCK_MUST_BE_ENOUGH_FOR_ORDER", $arrval, getDolGlobalString('STOCK_MUST_BE_ENOUGH_FOR_ORDER'));
548 }
549 print "</td>\n";
550 print "</tr>\n";
551}
552
553if (isModEnabled("shipping")) {
554 print '<tr class="oddeven">';
555 print '<td>'.$langs->trans("StockMustBeEnoughForShipment").'</td>';
556 print '<td class="right">';
557 if ($conf->use_javascript_ajax) {
558 print ajax_constantonoff('STOCK_MUST_BE_ENOUGH_FOR_SHIPMENT');
559 } else {
560 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
561 print $form->selectarray("STOCK_MUST_BE_ENOUGH_FOR_SHIPMENT", $arrval, getDolGlobalString('STOCK_MUST_BE_ENOUGH_FOR_SHIPMENT'));
562 }
563 print "</td>\n";
564 print "</tr>\n";
565}
566print '</table>';
567print '</div>';
568
569print '<br>';
570
571$virtualdiffersfromphysical = 0;
572if (getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT')
573 || getDolGlobalString('STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER')
574 || getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT_CLOSE')
575 || getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION')
576 || getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION_CLOSE')
577 || isModEnabled('mrp')) {
578 $virtualdiffersfromphysical = 1; // According to increase/decrease stock options, virtual and physical stock may differs.
579}
580
581if ($virtualdiffersfromphysical) {
582 print '<div class="div-table-responsive-no-min">'; // You can use div-table-responsive-no-min if you don't need reserved height for your table
583 print '<table class="noborder centpercent">';
584 print '<tr class="liste_titre">';
585 print "<td>".$langs->trans("RuleForStockReplenishment")." ".img_help(1, $langs->trans("VirtualDiffersFromPhysical"))."</td>\n";
586 print '<td class="right">'.$langs->trans("Status").'</td>'."\n";
587 print '</tr>'."\n";
588
589 print '<tr class="oddeven">';
590 print '<td>';
591 print $form->textwithpicto($langs->trans("UseRealStockByDefault"), $langs->trans("ReplenishmentCalculation"));
592 print '</td>';
593 print '<td class="right">';
594 if ($conf->use_javascript_ajax) {
595 print ajax_constantonoff('STOCK_USE_REAL_STOCK_BY_DEFAULT_FOR_REPLENISHMENT');
596 } else {
597 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
598 print $form->selectarray("STOCK_USE_REAL_STOCK_BY_DEFAULT_FOR_REPLENISHMENT", $arrval, getDolGlobalString('STOCK_USE_REAL_STOCK_BY_DEFAULT_FOR_REPLENISHMENT'));
599 }
600 print "</td>\n";
601 print "</tr>\n";
602 print '</table>';
603 print '</div>';
604
605 print '<br>';
606}
607
608if (empty($conf->use_javascript_ajax)) {
609 print '<center>';
610 print '<input type="submit" class="button button-edit" value="'.$langs->trans("Save").'">';
611 print '<center>';
612 print '<br>';
613}
614
615print '</form>';
616
617
618/*
619 * Document templates generators
620 */
621
622print load_fiche_titre($langs->trans("WarehouseModelModules"), '', '');
623
624// Load array def with activated templates
625$def = array();
626$sql = "SELECT nom";
627$sql .= " FROM ".MAIN_DB_PREFIX."document_model";
628$sql .= " WHERE type = '".$db->escape($type)."'";
629$sql .= " AND entity = ".((int) $conf->entity);
630$resql = $db->query($sql);
631if ($resql) {
632 $i = 0;
633 $num_rows = $db->num_rows($resql);
634 while ($i < $num_rows) {
635 $array = $db->fetch_array($resql);
636 if (is_array($array)) {
637 array_push($def, $array[0]);
638 }
639 $i++;
640 }
641} else {
642 dol_print_error($db);
643}
644
645
646print '<div class="div-table-responsive-no-min">'; // You can use div-table-responsive-no-min if you don't need reserved height for your table
647print '<table class="noborder centpercent">'."\n";
648print '<tr class="liste_titre">'."\n";
649print '<td>'.$langs->trans("Name").'</td>';
650print '<td>'.$langs->trans("Description").'</td>';
651print '<td class="center" width="60">'.$langs->trans("Status")."</td>\n";
652print '<td class="center" width="60">'.$langs->trans("Default")."</td>\n";
653print '<td class="center" width="38">'.$langs->trans("ShortInfo").'</td>';
654print '<td class="center" width="38">'.$langs->trans("Preview").'</td>';
655print "</tr>\n";
656
657clearstatcache();
658
659foreach ($dirmodels as $reldir) {
660 foreach (array('', '/doc') as $valdir) {
661 $realpath = $reldir."core/modules/stock".$valdir;
662 $dir = dol_buildpath($realpath);
663
664 if (is_dir($dir)) {
665 $handle = opendir($dir);
666 if (is_resource($handle)) {
667 $filelist = array();
668 while (($file = readdir($handle)) !== false) {
669 $filelist[] = $file;
670 }
671 closedir($handle);
672 arsort($filelist);
673
674 foreach ($filelist as $file) {
675 if (preg_match('/\.modules\.php$/i', $file) && preg_match('/^(pdf_|doc_)/', $file)) {
676 if (file_exists($dir.'/'.$file)) {
677 $name = substr($file, 4, dol_strlen($file) - 16);
678 $classname = substr($file, 0, dol_strlen($file) - 12);
679
680 require_once $dir.'/'.$file;
681 $module = new $classname($db);
682 '@phan-var-force ModelePDFStock $module';
683
684 $modulequalified = 1;
685 if ($module->version == 'development' && getDolGlobalInt('MAIN_FEATURES_LEVEL') < 2) {
686 $modulequalified = 0;
687 }
688 if ($module->version == 'experimental' && getDolGlobalInt('MAIN_FEATURES_LEVEL') < 1) {
689 $modulequalified = 0;
690 }
691
692 if ($modulequalified) {
693 print '<tr class="oddeven"><td width="100">';
694 print(empty($module->name) ? $name : $module->name);
695 print "</td><td>\n";
696 if (method_exists($module, 'info')) {
697 print $module->info($langs); // @phan-suppress-current-line PhanUndeclaredMethod
698 } else {
699 print $module->description;
700 }
701 print '</td>';
702
703 // Active
704 if (in_array($name, $def)) {
705 print '<td class="center">'."\n";
706 print '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?action=del&token='.newToken().'&value='.urlencode($name).'">';
707 print img_picto($langs->trans("Enabled"), 'switch_on');
708 print '</a>';
709 print '</td>';
710 } else {
711 print '<td class="center">'."\n";
712 print '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?action=set&token='.newToken().'&value='.urlencode($name).'&scan_dir='.urlencode($module->scandir).'&label='.urlencode($module->name).'">'.img_picto($langs->trans("Disabled"), 'switch_off').'</a>';
713 print "</td>";
714 }
715
716 // Default
717 print '<td class="center">';
718 if (getDolGlobalString('STOCK_ADDON_PDF') == $name) {
719 print img_picto($langs->trans("Default"), 'on');
720 } else {
721 print '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?action=setdoc&token='.newToken().'&value='.urlencode($name).'&scan_dir='.urlencode($module->scandir).'&label='.urlencode($module->name).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"), 'off').'</a>';
722 }
723 print '</td>';
724
725 // Info
726 $htmltooltip = ''.$langs->trans("Name").': '.$module->name;
727 $htmltooltip .= '<br>'.$langs->trans("Type").': '.($module->type ? $module->type : $langs->trans("Unknown"));
728 if ($module->type == 'pdf') {
729 $htmltooltip .= '<br>'.$langs->trans("Width").'/'.$langs->trans("Height").': '.$module->page_largeur.'/'.$module->page_hauteur;
730 }
731 $htmltooltip .= '<br>'.$langs->trans("Path").': '.preg_replace('/^\//', '', $realpath).'/'.$file;
732
733 $htmltooltip .= '<br><br><u>'.$langs->trans("FeaturesSupported").':</u>';
734 $htmltooltip .= '<br>'.$langs->trans("Logo").': '.yn($module->option_logo, 1, 1);
735 $htmltooltip .= '<br>'.$langs->trans("MultiLanguage").': '.yn($module->option_multilang, 1, 1);
736
737
738 print '<td class="center">';
739 print $form->textwithpicto('', $htmltooltip, 1, 'info');
740 print '</td>';
741
742 // Preview
743 print '<td class="center">';
744 if ($module->type == 'pdf') {
745 print '<a href="'.$_SERVER["PHP_SELF"].'?action=specimen&module='.$name.'">'.img_object($langs->trans("Preview"), 'pdf').'</a>';
746 } else {
747 print img_object($langs->transnoentitiesnoconv("PreviewNotAvailable"), 'generic');
748 }
749 print '</td>';
750
751 print "</tr>\n";
752 }
753 }
754 }
755 }
756 }
757 }
758 }
759}
760
761print '</table>';
762print '</div>';
763
764
765// Other
766
767print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
768print '<input type="hidden" name="token" value="'.newToken().'">';
769print '<input type="hidden" name="action" value="warehouse">';
770print '<input type="hidden" name="page_y" value="">';
771
772print load_fiche_titre($langs->trans("Other"), '', '');
773
774print '<div class="div-table-responsive-no-min">'; // You can use div-table-responsive-no-min if you don't need reserved height for your table
775print '<table class="noborder centpercent">';
776
777print '<tr class="liste_titre">';
778print "<td>".$langs->trans("Parameter")."</td>\n";
779print '<td class="right"></td>'."\n";
780print '</tr>'."\n";
781
782print '<tr class="oddeven">';
783print '<td>'.$langs->trans("MainDefaultWarehouse").'</td>';
784print '<td class="right">';
785print $formproduct->selectWarehouses(getDolGlobalInt('MAIN_DEFAULT_WAREHOUSE', -1), 'default_warehouse', '', 1, 0, 0, '', 0, 0, array(), 'left reposition');
786print '<input type="submit" class="button button-edit smallpaddingimp" value="'.$langs->trans("Modify").'">';
787print "</td>";
788print "</tr>\n";
789
790print '<tr class="oddeven">';
791print '<td>'.$langs->trans("UserDefaultWarehouse").'</td>';
792print '<td class="right">';
793if ($conf->use_javascript_ajax) {
794 print ajax_constantonoff('MAIN_DEFAULT_WAREHOUSE_USER', array(), null, 0, 0, 1);
795} else {
796 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
797 print $form->selectarray("MAIN_DEFAULT_WAREHOUSE_USER", $arrval, getDolGlobalString('MAIN_DEFAULT_WAREHOUSE_USER'));
798}
799print "</td>\n";
800print "</tr>\n";
801
802if (getDolGlobalString('MAIN_DEFAULT_WAREHOUSE_USER')) {
803 print '<tr class="oddeven">';
804 print '<td>'.$langs->trans("UserWarehouseAutoCreate").'</td>';
805 print '<td class="right">';
806 if ($conf->use_javascript_ajax) {
807 print ajax_constantonoff('STOCK_USERSTOCK_AUTOCREATE');
808 } else {
809 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
810 print $form->selectarray("STOCK_USERSTOCK_AUTOCREATE", $arrval, getDolGlobalString('STOCK_USERSTOCK_AUTOCREATE'));
811 }
812 print "</td>\n";
813 print "</tr>\n";
814}
815
816print '<tr class="oddeven">';
817print '<td>'.$langs->trans("WarehouseAskWarehouseOnThirparty").'</td>';
818print '<td class="right">';
819if ($conf->use_javascript_ajax) {
820 print ajax_constantonoff('SOCIETE_ASK_FOR_WAREHOUSE');
821} else {
822 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
823 print $form->selectarray("SOCIETE_ASK_FOR_WAREHOUSE", $arrval, getDolGlobalString('SOCIETE_ASK_FOR_WAREHOUSE'));
824}
825print "</td>";
826print "</tr>\n";
827
828print '<tr class="oddeven">';
829print '<td>'.$langs->trans("WarehouseAskWarehouseDuringPropal").'</td>';
830print '<td class="right">';
831if ($conf->use_javascript_ajax) {
832 print ajax_constantonoff('WAREHOUSE_ASK_WAREHOUSE_DURING_PROPAL');
833} else {
834 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
835 print $form->selectarray("WAREHOUSE_ASK_WAREHOUSE_DURING_PROPAL", $arrval, getDolGlobalString('WAREHOUSE_ASK_WAREHOUSE_DURING_PROPAL'));
836}
837print "</td>";
838print "</tr>\n";
839
840print '<tr class="oddeven">';
841print '<td>'.$langs->trans("WarehouseAskWarehouseDuringOrder").'</td>';
842print '<td class="right">';
843if ($conf->use_javascript_ajax) {
844 print ajax_constantonoff('WAREHOUSE_ASK_WAREHOUSE_DURING_ORDER');
845} else {
846 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
847 print $form->selectarray("WAREHOUSE_ASK_WAREHOUSE_DURING_ORDER", $arrval, getDolGlobalString('WAREHOUSE_ASK_WAREHOUSE_DURING_ORDER'));
848}
849print '</td>';
850print "</tr>\n";
851
852/*
853print '<tr class="oddeven">';
854print '<td>'.$langs->trans("WarehouseAskWarehouseDuringProject").'</td>';
855print '<td class="right">';
856if ($conf->use_javascript_ajax) {
857 print ajax_constantonoff('WAREHOUSE_ASK_WAREHOUSE_DURING_PROJECT');
858} else {
859 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
860 print $form->selectarray("WAREHOUSE_ASK_WAREHOUSE_DURING_PROJECT", $arrval, getDolGlobalString('WAREHOUSE_ASK_WAREHOUSE_DURING_PROJECT'));
861}
862print '</td>';
863print "</tr>\n";
864*/
865
866print '<tr class="oddeven">';
867print '<td>';
868print $form->textwithpicto($langs->trans("StockSupportServices"), $langs->trans("StockSupportServicesDesc"));
869print '</td>';
870print '<td class="right">';
871if ($conf->use_javascript_ajax) {
872 print ajax_constantonoff('STOCK_SUPPORTS_SERVICES');
873} else {
874 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
875 print $form->selectarray("STOCK_SUPPORTS_SERVICES", $arrval, getDolGlobalString('STOCK_SUPPORTS_SERVICES'));
876}
877print "</td>\n";
878print "</tr>\n";
879
880// Add option to allow a "Limit for warning" and a "Desired stock" per warehouse.
881print '<tr class="oddeven">';
882print '<td>'.$langs->trans("AllowAddLimitStockByWarehouse").'</td>';
883print '<td class="right">';
884if ($conf->use_javascript_ajax) {
885 print ajax_constantonoff('STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE');
886} else {
887 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
888 print $form->selectarray("STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE", $arrval, getDolGlobalString('STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE'));
889}
890print "</td>\n";
891print "</tr>\n";
892
893print '<tr class="oddeven">';
894print '<td>'.$langs->trans("AlwaysShowFullArbo").'</td>';
895print '<td class="right">';
896if ($conf->use_javascript_ajax) {
897 print ajax_constantonoff('STOCK_ALWAYS_SHOW_FULL_ARBO');
898} else {
899 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
900 print $form->selectarray("STOCK_ALWAYS_SHOW_FULL_ARBO", $arrval, getDolGlobalString('STOCK_ALWAYS_SHOW_FULL_ARBO'));
901}
902print "</td>\n";
903print "</tr>\n";
904
905print '</table>';
906print '</div>';
907
908print '</form>';
909
910// End of page
911llxFooter();
912$db->close();
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
addDocumentModel($name, $type, $label='', $description='')
Add document model used by doc generator.
dolibarr_set_const($db, $name, $value, $type='chaine', $visible=0, $note='', $entity=1)
Insert a parameter (key,value) into database (delete old key then insert it again).
dolibarr_del_const($db, $name, $entity=1)
Delete a constant.
delDocumentModel($name, $type)
Delete document model used by doc generator.
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:91
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
Definition wrapper.php:73
Class to manage warehouses.
Class to manage generation of HTML components Only common components must be here.
Class with static methods for building HTML components related to products Only components common to ...
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
img_help($usehelpcursor=1, $usealttitle=1)
Show help logo with cursor "?".
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0, $morecssdiv='')
Show tabs of a record.
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $allowothertags=array())
Show a picto called object_picto (generic function)
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
newToken()
Return the value of token currently saved into session with name 'newtoken'.
yn($yesno, $format=1, $color=0)
Return yes or no in current language.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='', $morecssonpicto='widthpictotitle')
Load a title with picto.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='', $picto='')
Show information in HTML for admin users or standard users.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:128
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.
stock_admin_prepare_head()
Return array head with list of tabs to view object information.
Definition stock.lib.php:91