dolibarr 22.0.5
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="'.DOL_URL_ROOT.'/admin/modules.php?restore_lastsearch_values=1">'.$langs->trans("BackToModuleList").'</a>';
220print load_fiche_titre($langs->trans("StockSetup"), $linkback, 'title_setup');
221
223
224print dol_get_fiche_head($head, 'general', $langs->trans("StockSetup"), -1, 'stock');
225
226$form = new Form($db);
227$formproduct = new FormProduct($db);
228
229
230$disableStockCalculateOn = array();
231if (getDolGlobalInt('PRODUIT_SOUSPRODUITS')) {
232 // If option virtual stock is enabled, we disable some mode for inc/dec stock change
233 // Why this ? As i don't see why, i comment this code by a hidden option
234 if (getDolGlobalString('PRODUIT_RESTRICT_STOCK_INCDEC_IF_SUBPRODUCTS_ENABLED')) {
235 $disableStockCalculateOn[] = 'BILL';
236 $disableStockCalculateOn[] = 'VALIDATE_ORDER';
237 // STOCK_CALCULATE_ON_SHIPMENT is ok so not disable
238 // STOCK_CALCULATE_ON_SHIPMENT_CLOSE is ok so not disabled
239
240 $disableStockCalculateOn[] = 'SUPPLIER_BILL';
241 $disableStockCalculateOn[] = 'SUPPLIER_VALIDATE_ORDER';
242
243 print info_admin($langs->trans('WhenProductVirtualOnOptionAreForced'));
244 }
245}
246if (isModEnabled('productbatch')) {
247 // If module lot/serial enabled, we disable some mode for inc/dec stock change
248 $langs->load("productbatch");
249 $disableStockCalculateOn[] = 'BILL';
250 $disableStockCalculateOn[] = 'VALIDATE_ORDER';
251 // STOCK_CALCULATE_ON_SHIPMENT is ok so not disable
252 // STOCK_CALCULATE_ON_SHIPMENT_CLOSE is ok so not disabled
253
254 $disableStockCalculateOn[] = 'SUPPLIER_BILL';
255 $disableStockCalculateOn[] = 'SUPPLIER_VALIDATE_ORDER';
256
257 $descmode = ""; $incmode = "";
258 /* $descmode = $langs->trans('DeStockOnShipmentOnClosing');
259 if (!isModEnabled('reception')) {
260 // STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER
261 $incmode = $langs->trans('ReStockOnDispatchOrder');
262 } else {
263 // STOCK_CALCULATE_ON_RECEPTION_CLOSE
264 $incmode = $langs->trans('StockOnReceptionOnClosing');
265 } */
266 print info_admin($langs->transnoentitiesnoconv("WhenProductBatchModuleOnOptionAreForced", $descmode, $incmode));
267}
268
269
270print info_admin($langs->trans("IfYouUsePointOfSaleCheckModule"));
271print '<br>';
272
273
274print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
275print '<input type="hidden" name="token" value="'.newToken().'">';
276print '<input type="hidden" name="action" value="update">';
277print '<input type="hidden" name="page_y" value="">';
278
279// Title rule for stock decrease
280print '<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
281print '<table class="noborder centpercent">';
282print '<tr class="liste_titre">';
283print "<td>".$langs->trans("RuleForStockManagementDecrease")."</td>\n";
284print '<td class="right">'.$langs->trans("Status").'</td>'."\n";
285print '</tr>'."\n";
286
287$found = 0;
288
289print '<!-- STOCK_CALCULATE_ON_BILL -->';
290print '<tr class="oddeven">';
291print '<td>'.$langs->trans("DeStockOnBill").'</td>';
292print '<td class="right">';
293if (isModEnabled('invoice')) {
294 if ($conf->use_javascript_ajax) {
295 if (in_array('BILL', $disableStockCalculateOn)) {
296 print img_picto($langs->trans("Disabled"), 'off', 'class="opacitymedium"');
297 } else {
298 print ajax_constantonoff('STOCK_CALCULATE_ON_BILL', array(), null, 0, 0, 0, 2, 1, 0, '', '', 'reposition');
299 }
300 } else {
301 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
302 print $form->selectarray("STOCK_CALCULATE_ON_BILL", $arrval, getDolGlobalString('STOCK_CALCULATE_ON_BILL'));
303 }
304} else {
305 print '<span class="opacitymedium">'.$langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module30Name")).'</span>';
306}
307print "</td>\n</tr>\n";
308$found++;
309
310
311print '<!-- STOCK_CALCULATE_ON_VALIDATE_ORDER -->';
312print '<tr class="oddeven">';
313print '<td>'.$langs->trans("DeStockOnValidateOrder").'</td>';
314print '<td class="right">';
315if (isModEnabled('order')) {
316 if ($conf->use_javascript_ajax) {
317 if (in_array('VALIDATE_ORDER', $disableStockCalculateOn)) {
318 print img_picto($langs->trans("Disabled"), 'off', 'class="opacitymedium"');
319 } else {
320 print ajax_constantonoff('STOCK_CALCULATE_ON_VALIDATE_ORDER', array(), null, 0, 0, 0, 2, 1, 0, '', '', 'reposition');
321 }
322 } else {
323 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
324 print $form->selectarray("STOCK_CALCULATE_ON_VALIDATE_ORDER", $arrval, getDolGlobalString('STOCK_CALCULATE_ON_VALIDATE_ORDER'));
325 }
326} else {
327 print '<span class="opacitymedium">'.$langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module25Name")).'</span>';
328}
329print "</td>\n</tr>\n";
330$found++;
331
332//if (isModEnabled('shipping'))
333//{
334
335print '<!-- STOCK_CALCULATE_ON_SHIPMENT -->';
336print '<tr class="oddeven">';
337print '<td>'.$langs->trans("DeStockOnShipment").'</td>';
338print '<td class="right">';
339if (isModEnabled("shipping")) {
340 if ($conf->use_javascript_ajax) {
341 if (in_array('SHIPMENT', $disableStockCalculateOn)) {
342 print img_picto($langs->trans("Disabled"), 'off', 'class="opacitymedium"');
343 } else {
344 print ajax_constantonoff('STOCK_CALCULATE_ON_SHIPMENT', array(), null, 0, 0, 0, 2, 1, 0, '', '', 'reposition');
345 }
346 } else {
347 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
348 print $form->selectarray("STOCK_CALCULATE_ON_SHIPMENT", $arrval, getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT'));
349 }
350} else {
351 print '<span class="opacitymedium">'.$langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module80Name")).'</span>';
352}
353print "</td>\n</tr>\n";
354$found++;
355
356print '<!-- STOCK_CALCULATE_ON_SHIPMENT_CLOSE -->';
357print '<tr class="oddeven">';
358print '<td>'.$langs->trans("DeStockOnShipmentOnClosing").'</td>';
359print '<td class="right">';
360if (isModEnabled("shipping")) {
361 if ($conf->use_javascript_ajax) {
362 if (in_array('SHIPMENT_CLOSE', $disableStockCalculateOn)) {
363 print img_picto($langs->trans("Disabled"), 'off', 'class="opacitymedium"');
364 } else {
365 print ajax_constantonoff('STOCK_CALCULATE_ON_SHIPMENT_CLOSE', array(), null, 0, 0, 0, 2, 1, 0, '', '', 'reposition');
366 }
367 } else {
368 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
369 print $form->selectarray("STOCK_CALCULATE_ON_SHIPMENT_CLOSE", $arrval, getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT_CLOSE'));
370 }
371} else {
372 print '<span class="opacitymedium">'.$langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module80Name")).'</span>';
373}
374print "</td>\n</tr>\n";
375$found++;
376
377print '</table>';
378print '</div>';
379
380
381print '<br>';
382
383
384// Title rule for stock increase
385print '<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
386print '<table class="noborder centpercent">';
387print '<tr class="liste_titre">';
388print "<td>".$langs->trans("RuleForStockManagementIncrease")."</td>\n";
389print '<td class="right">'.$langs->trans("Status").'</td>'."\n";
390print '</tr>'."\n";
391
392$found = 0;
393
394print '<!-- STOCK_CALCULATE_ON_SUPPLIER_BILL -->';
395print '<tr class="oddeven">';
396print '<td>'.$langs->trans("ReStockOnBill").'</td>';
397print '<td class="right">';
398if (isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) {
399 if ($conf->use_javascript_ajax) {
400 if (in_array('SUPPLIER_BILL', $disableStockCalculateOn)) {
401 print img_picto($langs->trans("Disabled"), 'off', 'class="opacitymedium"');
402 } else {
403 print ajax_constantonoff('STOCK_CALCULATE_ON_SUPPLIER_BILL', array(), null, 0, 0, 0, 2, 1, 0, '', '', 'reposition');
404 }
405 } else {
406 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
407 print $form->selectarray("STOCK_CALCULATE_ON_SUPPLIER_BILL", $arrval, getDolGlobalString('STOCK_CALCULATE_ON_SUPPLIER_BILL'));
408 }
409} else {
410 print '<span class="opacitymedium">'.$langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module40Name")).'</span>';
411}
412print "</td>\n</tr>\n";
413$found++;
414
415
416print '<!-- STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER -->';
417print '<tr class="oddeven">';
418print '<td>'.$langs->trans("ReStockOnValidateOrder").'</td>';
419print '<td class="right">';
420if (isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) {
421 if ($conf->use_javascript_ajax) {
422 if (in_array('SUPPLIER_VALIDATE_ORDER', $disableStockCalculateOn)) {
423 print img_picto($langs->trans("Disabled"), 'off', 'class="opacitymedium"');
424 } else {
425 print ajax_constantonoff('STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER', array(), null, 0, 0, 0, 2, 1, 0, '', '', 'reposition');
426 }
427 } else {
428 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
429 print $form->selectarray("STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER", $arrval, getDolGlobalString('STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER'));
430 }
431} else {
432 print '<span class="opacitymedium">'.$langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module40Name")).'</span>';
433}
434print "</td>\n</tr>\n";
435$found++;
436
437if (isModEnabled("reception")) {
438 print '<!-- STOCK_CALCULATE_ON_RECEPTION -->';
439 print '<tr class="oddeven">';
440 print '<td>'.$langs->trans("StockOnReception").'</td>';
441 print '<td class="right">';
442
443 if ($conf->use_javascript_ajax) {
444 if (in_array('RECEPTION', $disableStockCalculateOn)) {
445 print img_picto($langs->trans("Disabled"), 'off', 'class="opacitymedium"');
446 } else {
447 print ajax_constantonoff('STOCK_CALCULATE_ON_RECEPTION', array(), null, 0, 0, 0, 2, 1, 0, '', '', 'reposition');
448 }
449 } else {
450 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
451 print $form->selectarray("STOCK_CALCULATE_ON_RECEPTION", $arrval, getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION'));
452 }
453
454 print "</td>\n</tr>\n";
455 $found++;
456
457 print '<!-- STOCK_CALCULATE_ON_RECEPTION_CLOSE -->';
458 print '<tr class="oddeven">';
459 print '<td>'.$langs->trans("StockOnReceptionOnClosing").'</td>';
460 print '<td class="right">';
461
462 if ($conf->use_javascript_ajax) {
463 if (in_array('RECEPTION_CLOSE', $disableStockCalculateOn)) {
464 print img_picto($langs->trans("Disabled"), 'off', 'class="opacitymedium"');
465 } else {
466 print ajax_constantonoff('STOCK_CALCULATE_ON_RECEPTION_CLOSE', array(), null, 0, 0, 0, 2, 1, 0, '', '', 'reposition');
467 }
468 } else {
469 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
470 print $form->selectarray("STOCK_CALCULATE_ON_RECEPTION_CLOSE", $arrval, getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION_CLOSE'));
471 }
472 print "</td>\n</tr>\n";
473 $found++;
474} else {
475 // When module Reception is not enabled, option to increase real stocks on manual dispatching into warehouse, after purchase order receipt of goods
476 print '<!-- STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER -->';
477 print '<tr class="oddeven">';
478 print '<td>'.$langs->trans("ReStockOnDispatchOrder").'</td>';
479 print '<td class="right">';
480 if (isModEnabled("supplier_order")) {
481 if ($conf->use_javascript_ajax) {
482 if (in_array('SUPPLIER_DISPATCH_ORDER', $disableStockCalculateOn)) {
483 print img_picto($langs->trans("Disabled"), 'off', 'class="opacitymedium"');
484 } else {
485 print ajax_constantonoff('STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER', array(), null, 0, 0, 0, 2, 1, 0, '', '', 'reposition');
486 }
487 } else {
488 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
489 print $form->selectarray("STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER", $arrval, getDolGlobalString('STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER'));
490 }
491 } else {
492 print '<span class="opacitymedium">'.$langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module40Name")).'</span>';
493 }
494 print "</td>\n</tr>\n";
495 $found++;
496}
497
498print '</table>';
499print '</div>';
500
501print '<br>';
502
503print '<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
504print '<table class="noborder centpercent">';
505print '<tr class="liste_titre">';
506print "<td>".$langs->trans("RuleForStockAvailability")."</td>\n";
507print '<td class="right">'.$langs->trans("Status").'</td>'."\n";
508print '</tr>'."\n";
509
510
511print '<tr class="oddeven">';
512print '<td>'.$langs->trans("WarehouseAllowNegativeTransfer").'</td>';
513print '<td class="right">';
514if ($conf->use_javascript_ajax) {
515 print ajax_constantonoff('STOCK_DISALLOW_NEGATIVE_TRANSFER', array(), null, 1);
516} else {
517 $arrval = array('1' => $langs->trans("No"), '0' => $langs->trans("Yes"));
518 print $form->selectarray("STOCK_DISALLOW_NEGATIVE_TRANSFER", $arrval, getDolGlobalInt('STOCK_DISALLOW_NEGATIVE_TRANSFER'));
519}
520print "</td>\n";
521print "</tr>\n";
522
523// Option to force stock to be enough before adding a line into document
524if (isModEnabled('invoice')) {
525 print '<tr class="oddeven">';
526 print '<td>'.$langs->trans("StockMustBeEnoughForInvoice").'</td>';
527 print '<td class="right">';
528 if ($conf->use_javascript_ajax) {
529 print ajax_constantonoff('STOCK_MUST_BE_ENOUGH_FOR_INVOICE');
530 } else {
531 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
532 print $form->selectarray("STOCK_MUST_BE_ENOUGH_FOR_INVOICE", $arrval, getDolGlobalString('STOCK_MUST_BE_ENOUGH_FOR_INVOICE'));
533 }
534 print "</td>\n";
535 print "</tr>\n";
536}
537
538if (isModEnabled('order')) {
539 print '<tr class="oddeven">';
540 print '<td>'.$langs->trans("StockMustBeEnoughForOrder").'</td>';
541 print '<td class="right">';
542 if ($conf->use_javascript_ajax) {
543 print ajax_constantonoff('STOCK_MUST_BE_ENOUGH_FOR_ORDER');
544 } else {
545 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
546 print $form->selectarray("STOCK_MUST_BE_ENOUGH_FOR_ORDER", $arrval, getDolGlobalString('STOCK_MUST_BE_ENOUGH_FOR_ORDER'));
547 }
548 print "</td>\n";
549 print "</tr>\n";
550}
551
552if (isModEnabled("shipping")) {
553 print '<tr class="oddeven">';
554 print '<td>'.$langs->trans("StockMustBeEnoughForShipment").'</td>';
555 print '<td class="right">';
556 if ($conf->use_javascript_ajax) {
557 print ajax_constantonoff('STOCK_MUST_BE_ENOUGH_FOR_SHIPMENT');
558 } else {
559 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
560 print $form->selectarray("STOCK_MUST_BE_ENOUGH_FOR_SHIPMENT", $arrval, getDolGlobalString('STOCK_MUST_BE_ENOUGH_FOR_SHIPMENT'));
561 }
562 print "</td>\n";
563 print "</tr>\n";
564}
565print '</table>';
566print '</div>';
567
568print '<br>';
569
570$virtualdiffersfromphysical = 0;
571if (getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT')
572 || getDolGlobalString('STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER')
573 || getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT_CLOSE')
574 || getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION')
575 || getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION_CLOSE')
576 || isModEnabled('mrp')) {
577 $virtualdiffersfromphysical = 1; // According to increase/decrease stock options, virtual and physical stock may differs.
578}
579
580if ($virtualdiffersfromphysical) {
581 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
582 print '<table class="noborder centpercent">';
583 print '<tr class="liste_titre">';
584 print "<td>".$langs->trans("RuleForStockReplenishment")." ".img_help(1, $langs->trans("VirtualDiffersFromPhysical"))."</td>\n";
585 print '<td class="right">'.$langs->trans("Status").'</td>'."\n";
586 print '</tr>'."\n";
587
588 print '<tr class="oddeven">';
589 print '<td>';
590 print $form->textwithpicto($langs->trans("UseRealStockByDefault"), $langs->trans("ReplenishmentCalculation"));
591 print '</td>';
592 print '<td class="right">';
593 if ($conf->use_javascript_ajax) {
594 print ajax_constantonoff('STOCK_USE_REAL_STOCK_BY_DEFAULT_FOR_REPLENISHMENT');
595 } else {
596 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
597 print $form->selectarray("STOCK_USE_REAL_STOCK_BY_DEFAULT_FOR_REPLENISHMENT", $arrval, getDolGlobalString('STOCK_USE_REAL_STOCK_BY_DEFAULT_FOR_REPLENISHMENT'));
598 }
599 print "</td>\n";
600 print "</tr>\n";
601 print '</table>';
602 print '</div>';
603
604 print '<br>';
605}
606
607if (empty($conf->use_javascript_ajax)) {
608 print '<center>';
609 print '<input type="submit" class="button button-edit" value="'.$langs->trans("Save").'">';
610 print '<center>';
611 print '<br>';
612}
613
614print '</form>';
615
616
617/*
618 * Document templates generators
619 */
620
621print load_fiche_titre($langs->trans("WarehouseModelModules"), '', '');
622
623// Load array def with activated templates
624$def = array();
625$sql = "SELECT nom";
626$sql .= " FROM ".MAIN_DB_PREFIX."document_model";
627$sql .= " WHERE type = '".$db->escape($type)."'";
628$sql .= " AND entity = ".$conf->entity;
629$resql = $db->query($sql);
630if ($resql) {
631 $i = 0;
632 $num_rows = $db->num_rows($resql);
633 while ($i < $num_rows) {
634 $array = $db->fetch_array($resql);
635 if (is_array($array)) {
636 array_push($def, $array[0]);
637 }
638 $i++;
639 }
640} else {
641 dol_print_error($db);
642}
643
644
645print '<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
646print '<table class="noborder centpercent">'."\n";
647print '<tr class="liste_titre">'."\n";
648print '<td>'.$langs->trans("Name").'</td>';
649print '<td>'.$langs->trans("Description").'</td>';
650print '<td class="center" width="60">'.$langs->trans("Status")."</td>\n";
651print '<td class="center" width="60">'.$langs->trans("Default")."</td>\n";
652print '<td class="center" width="38">'.$langs->trans("ShortInfo").'</td>';
653print '<td class="center" width="38">'.$langs->trans("Preview").'</td>';
654print "</tr>\n";
655
656clearstatcache();
657
658foreach ($dirmodels as $reldir) {
659 foreach (array('', '/doc') as $valdir) {
660 $realpath = $reldir."core/modules/stock".$valdir;
661 $dir = dol_buildpath($realpath);
662
663 if (is_dir($dir)) {
664 $handle = opendir($dir);
665 if (is_resource($handle)) {
666 $filelist = array();
667 while (($file = readdir($handle)) !== false) {
668 $filelist[] = $file;
669 }
670 closedir($handle);
671 arsort($filelist);
672
673 foreach ($filelist as $file) {
674 if (preg_match('/\.modules\.php$/i', $file) && preg_match('/^(pdf_|doc_)/', $file)) {
675 if (file_exists($dir.'/'.$file)) {
676 $name = substr($file, 4, dol_strlen($file) - 16);
677 $classname = substr($file, 0, dol_strlen($file) - 12);
678
679 require_once $dir.'/'.$file;
680 $module = new $classname($db);
681 '@phan-var-force ModelePDFStock $module';
682
683 $modulequalified = 1;
684 if ($module->version == 'development' && getDolGlobalInt('MAIN_FEATURES_LEVEL') < 2) {
685 $modulequalified = 0;
686 }
687 if ($module->version == 'experimental' && getDolGlobalInt('MAIN_FEATURES_LEVEL') < 1) {
688 $modulequalified = 0;
689 }
690
691 if ($modulequalified) {
692 print '<tr class="oddeven"><td width="100">';
693 print(empty($module->name) ? $name : $module->name);
694 print "</td><td>\n";
695 if (method_exists($module, 'info')) {
696 print $module->info($langs); // @phan-suppress-current-line PhanUndeclaredMethod
697 } else {
698 print $module->description;
699 }
700 print '</td>';
701
702 // Active
703 if (in_array($name, $def)) {
704 print '<td class="center">'."\n";
705 print '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?action=del&token='.newToken().'&value='.urlencode($name).'">';
706 print img_picto($langs->trans("Enabled"), 'switch_on');
707 print '</a>';
708 print '</td>';
709 } else {
710 print '<td class="center">'."\n";
711 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>';
712 print "</td>";
713 }
714
715 // Default
716 print '<td class="center">';
717 if (getDolGlobalString('STOCK_ADDON_PDF') == $name) {
718 print img_picto($langs->trans("Default"), 'on');
719 } else {
720 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>';
721 }
722 print '</td>';
723
724 // Info
725 $htmltooltip = ''.$langs->trans("Name").': '.$module->name;
726 $htmltooltip .= '<br>'.$langs->trans("Type").': '.($module->type ? $module->type : $langs->trans("Unknown"));
727 if ($module->type == 'pdf') {
728 $htmltooltip .= '<br>'.$langs->trans("Width").'/'.$langs->trans("Height").': '.$module->page_largeur.'/'.$module->page_hauteur;
729 }
730 $htmltooltip .= '<br>'.$langs->trans("Path").': '.preg_replace('/^\//', '', $realpath).'/'.$file;
731
732 $htmltooltip .= '<br><br><u>'.$langs->trans("FeaturesSupported").':</u>';
733 $htmltooltip .= '<br>'.$langs->trans("Logo").': '.yn($module->option_logo, 1, 1);
734 $htmltooltip .= '<br>'.$langs->trans("MultiLanguage").': '.yn($module->option_multilang, 1, 1);
735
736
737 print '<td class="center">';
738 print $form->textwithpicto('', $htmltooltip, 1, 'info');
739 print '</td>';
740
741 // Preview
742 print '<td class="center">';
743 if ($module->type == 'pdf') {
744 print '<a href="'.$_SERVER["PHP_SELF"].'?action=specimen&module='.$name.'">'.img_object($langs->trans("Preview"), 'pdf').'</a>';
745 } else {
746 print img_object($langs->transnoentitiesnoconv("PreviewNotAvailable"), 'generic');
747 }
748 print '</td>';
749
750 print "</tr>\n";
751 }
752 }
753 }
754 }
755 }
756 }
757 }
758}
759
760print '</table>';
761print '</div>';
762
763
764// Other
765
766print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
767print '<input type="hidden" name="token" value="'.newToken().'">';
768print '<input type="hidden" name="action" value="warehouse">';
769print '<input type="hidden" name="page_y" value="">';
770
771print load_fiche_titre($langs->trans("Other"), '', '');
772
773print '<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
774print '<table class="noborder centpercent">';
775
776print '<tr class="liste_titre">';
777print "<td>".$langs->trans("Parameter")."</td>\n";
778print '<td class="right"></td>'."\n";
779print '</tr>'."\n";
780
781print '<tr class="oddeven">';
782print '<td>'.$langs->trans("MainDefaultWarehouse").'</td>';
783print '<td class="right">';
784print $formproduct->selectWarehouses(getDolGlobalInt('MAIN_DEFAULT_WAREHOUSE', -1), 'default_warehouse', '', 1, 0, 0, '', 0, 0, array(), 'left reposition');
785print '<input type="submit" class="button button-edit smallpaddingimp" value="'.$langs->trans("Modify").'">';
786print "</td>";
787print "</tr>\n";
788
789print '<tr class="oddeven">';
790print '<td>'.$langs->trans("UserDefaultWarehouse").'</td>';
791print '<td class="right">';
792if ($conf->use_javascript_ajax) {
793 print ajax_constantonoff('MAIN_DEFAULT_WAREHOUSE_USER', array(), null, 0, 0, 1);
794} else {
795 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
796 print $form->selectarray("MAIN_DEFAULT_WAREHOUSE_USER", $arrval, getDolGlobalString('MAIN_DEFAULT_WAREHOUSE_USER'));
797}
798print "</td>\n";
799print "</tr>\n";
800
801if (getDolGlobalString('MAIN_DEFAULT_WAREHOUSE_USER')) {
802 print '<tr class="oddeven">';
803 print '<td>'.$langs->trans("UserWarehouseAutoCreate").'</td>';
804 print '<td class="right">';
805 if ($conf->use_javascript_ajax) {
806 print ajax_constantonoff('STOCK_USERSTOCK_AUTOCREATE');
807 } else {
808 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
809 print $form->selectarray("STOCK_USERSTOCK_AUTOCREATE", $arrval, getDolGlobalString('STOCK_USERSTOCK_AUTOCREATE'));
810 }
811 print "</td>\n";
812 print "</tr>\n";
813}
814
815print '<tr class="oddeven">';
816print '<td>'.$langs->trans("WarehouseAskWarehouseOnThirparty").'</td>';
817print '<td class="right">';
818if ($conf->use_javascript_ajax) {
819 print ajax_constantonoff('SOCIETE_ASK_FOR_WAREHOUSE');
820} else {
821 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
822 print $form->selectarray("SOCIETE_ASK_FOR_WAREHOUSE", $arrval, getDolGlobalString('SOCIETE_ASK_FOR_WAREHOUSE'));
823}
824print "</td>";
825print "</tr>\n";
826
827print '<tr class="oddeven">';
828print '<td>'.$langs->trans("WarehouseAskWarehouseDuringPropal").'</td>';
829print '<td class="right">';
830if ($conf->use_javascript_ajax) {
831 print ajax_constantonoff('WAREHOUSE_ASK_WAREHOUSE_DURING_PROPAL');
832} else {
833 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
834 print $form->selectarray("WAREHOUSE_ASK_WAREHOUSE_DURING_PROPAL", $arrval, getDolGlobalString('WAREHOUSE_ASK_WAREHOUSE_DURING_PROPAL'));
835}
836print "</td>";
837print "</tr>\n";
838
839print '<tr class="oddeven">';
840print '<td>'.$langs->trans("WarehouseAskWarehouseDuringOrder").'</td>';
841print '<td class="right">';
842if ($conf->use_javascript_ajax) {
843 print ajax_constantonoff('WAREHOUSE_ASK_WAREHOUSE_DURING_ORDER');
844} else {
845 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
846 print $form->selectarray("WAREHOUSE_ASK_WAREHOUSE_DURING_ORDER", $arrval, getDolGlobalString('WAREHOUSE_ASK_WAREHOUSE_DURING_ORDER'));
847}
848print '</td>';
849print "</tr>\n";
850
851/*
852print '<tr class="oddeven">';
853print '<td>'.$langs->trans("WarehouseAskWarehouseDuringProject").'</td>';
854print '<td class="right">';
855if ($conf->use_javascript_ajax) {
856 print ajax_constantonoff('WAREHOUSE_ASK_WAREHOUSE_DURING_PROJECT');
857} else {
858 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
859 print $form->selectarray("WAREHOUSE_ASK_WAREHOUSE_DURING_PROJECT", $arrval, getDolGlobalString('WAREHOUSE_ASK_WAREHOUSE_DURING_PROJECT'));
860}
861print '</td>';
862print "</tr>\n";
863*/
864
865print '<tr class="oddeven">';
866print '<td>';
867print $form->textwithpicto($langs->trans("StockSupportServices"), $langs->trans("StockSupportServicesDesc"));
868print '</td>';
869print '<td class="right">';
870if ($conf->use_javascript_ajax) {
871 print ajax_constantonoff('STOCK_SUPPORTS_SERVICES');
872} else {
873 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
874 print $form->selectarray("STOCK_SUPPORTS_SERVICES", $arrval, getDolGlobalString('STOCK_SUPPORTS_SERVICES'));
875}
876print "</td>\n";
877print "</tr>\n";
878
879// Add option to allow a "Limit for warning" and a "Desired stock" per warehouse.
880print '<tr class="oddeven">';
881print '<td>'.$langs->trans("AllowAddLimitStockByWarehouse").'</td>';
882print '<td class="right">';
883if ($conf->use_javascript_ajax) {
884 print ajax_constantonoff('STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE');
885} else {
886 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
887 print $form->selectarray("STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE", $arrval, getDolGlobalString('STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE'));
888}
889print "</td>\n";
890print "</tr>\n";
891
892print '<tr class="oddeven">';
893print '<td>'.$langs->trans("AlwaysShowFullArbo").'</td>';
894print '<td class="right">';
895if ($conf->use_javascript_ajax) {
896 print ajax_constantonoff('STOCK_ALWAYS_SHOW_FULL_ARBO');
897} else {
898 $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
899 print $form->selectarray("STOCK_ALWAYS_SHOW_FULL_ARBO", $arrval, getDolGlobalString('STOCK_ALWAYS_SHOW_FULL_ARBO'));
900}
901print "</td>\n";
902print "</tr>\n";
903
904print '</table>';
905print '</div>';
906
907print '</form>';
908
909// End of page
910llxFooter();
911$db->close();
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:67
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 ...
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
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...
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
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.
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
Definition member.php:79
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:161
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