dolibarr 24.0.0-beta
product.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2001-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2004-2020 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2004 Eric Seigne <eric.seigne@ryxeo.com>
5 * Copyright (C) 2005 Simon TOSSER <simon@kornog-computing.com>
6 * Copyright (C) 2005-2009 Regis Houssin <regis.houssin@inodbox.com>
7 * Copyright (C) 2013 Cédric Salvador <csalvador.gpcsolutions.fr>
8 * Copyright (C) 2013-2018 Juanjo Menent <jmenent@2byte.es>
9 * Copyright (C) 2014-2015 Cédric Gross <c.gross@kreiz-it.fr>
10 * Copyright (C) 2015 Marcos García <marcosgdf@gmail.com>
11 * Copyright (C) 2018-2025 Frédéric France <frederic.france@free.fr>
12 * Copyright (C) 2021 Gauthier VERDOL <gauthier.verdol@atm-consulting.fr>
13 * Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 3 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program. If not, see <https://www.gnu.org/licenses/>.
27 */
28
35// Load Dolibarr environment
36require '../../main.inc.php';
37require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
38require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
39require_once DOL_DOCUMENT_ROOT.'/product/stock/class/productlot.class.php';
40require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
41require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php';
42require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
43require_once DOL_DOCUMENT_ROOT.'/product/stock/class/productstockentrepot.class.php';
44if (isModEnabled('productbatch')) {
45 require_once DOL_DOCUMENT_ROOT.'/product/class/productbatch.class.php';
46}
47if (isModEnabled('project')) {
48 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
49 require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
50}
51
52if (isModEnabled('variants')) {
53 require_once DOL_DOCUMENT_ROOT.'/variants/class/ProductAttribute.class.php';
54 require_once DOL_DOCUMENT_ROOT.'/variants/class/ProductAttributeValue.class.php';
55 require_once DOL_DOCUMENT_ROOT.'/variants/class/ProductCombination.class.php';
56 require_once DOL_DOCUMENT_ROOT.'/variants/class/ProductCombination2ValuePair.class.php';
57}
58
67// Load translation files required by the page
68$langs->loadlangs(array('products', 'suppliers', 'orders', 'bills', 'stocks', 'sendings', 'margins'));
69if (isModEnabled('productbatch')) {
70 $langs->load("productbatch");
71}
72
73$backtopage = GETPOST('backtopage', 'alpha');
74$action = GETPOST('action', 'aZ09');
75$cancel = GETPOST('cancel', 'alpha');
76
77$id = GETPOSTINT('id');
78$ref = GETPOST('ref', 'alpha');
79$stocklimit = GETPOSTFLOAT('seuil_stock_alerte');
80$desiredstock = GETPOSTFLOAT('desiredstock');
81$cancel = GETPOST('cancel', 'alpha');
82$fieldid = GETPOSTISSET("ref") ? 'ref' : 'rowid';
83$d_eatby = dol_mktime(0, 0, 0, GETPOSTINT('eatbymonth'), GETPOSTINT('eatbyday'), GETPOSTINT('eatbyyear'));
84$d_sellby = dol_mktime(0, 0, 0, GETPOSTINT('sellbymonth'), GETPOSTINT('sellbyday'), GETPOSTINT('sellbyyear'));
85$pdluoid = GETPOSTINT('pdluoid');
86$batchnumber = GETPOST('batch_number', 'alphanohtml'); // Lot/serial number may contain chars like '/' so we must not use aZ09 sanitizing here. Value is escaped before SQL use.
87if (!empty($batchnumber)) {
88 $batchnumber = trim($batchnumber);
89}
90$cost_price = GETPOST('cost_price', 'alpha');
91
92
93// Load variable for pagination
94$limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit;
95$sortfield = GETPOST('sortfield', 'aZ09comma');
96$sortorder = GETPOST('sortorder', 'aZ09comma');
97$page = GETPOSTISSET('pageplusone') ? (GETPOSTINT('pageplusone') - 1) : GETPOSTINT('page');
98if (empty($page) || $page < 0 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha')) {
99 // If $page is not defined, or '' or -1 or if we click on clear filters
100 $page = 0;
101}
102$offset = $limit * $page;
103$pageprev = $page - 1;
104$pagenext = $page + 1;
105
106
107// Security check
108if ($user->socid) {
109 $socid = $user->socid;
110}
111
112$object = new Product($db);
113$extrafields = new ExtraFields($db);
114
115// fetch optionals attributes and labels
116$extrafields->fetch_name_optionals_label($object->table_element);
117
118if ($id > 0 || !empty($ref)) {
119 $result = $object->fetch($id, $ref);
120}
121
122if (empty($id) && !empty($object->id)) {
123 $id = $object->id;
124}
125
126$modulepart = 'product';
127
128// Get object canvas (By default, this is not defined, so standard usage of dolibarr)
129$canvas = !empty($object->canvas) ? $object->canvas : GETPOST("canvas");
130$objcanvas = null;
131if (!empty($canvas)) {
132 require_once DOL_DOCUMENT_ROOT.'/core/class/canvas.class.php';
133 $objcanvas = new Canvas($db, $action);
134 $objcanvas->getCanvas('stockproduct', 'card', $canvas);
135}
136
137// Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
138$hookmanager->initHooks(array('stockproductcard', 'globalcard'));
139
140$error = 0;
141
142$usercanread = (($object->type == Product::TYPE_PRODUCT && $user->hasRight('produit', 'lire')) || ($object->type == Product::TYPE_SERVICE && $user->hasRight('service', 'lire')));
143$usercancreate = (($object->type == Product::TYPE_PRODUCT && $user->hasRight('produit', 'creer')) || ($object->type == Product::TYPE_SERVICE && $user->hasRight('service', 'creer')));
144$usercancreadprice = getDolGlobalString('MAIN_USE_ADVANCED_PERMS') ? $user->hasRight('product', 'product_advance', 'read_prices') : $user->hasRight('product', 'lire');
145$usercancreadsupplierprice = getDolGlobalString('MAIN_USE_ADVANCED_PERMS') ? $user->hasRight('product', 'product_advance', 'read_supplier_prices') : $user->hasRight('product', 'lire');
146$usercanupdatestock = $user->hasRight('stock', 'mouvement', 'creer');
147
148if ($object->isService()) {
149 $label = $langs->trans('Service');
150 $usercancreadprice = getDolGlobalString('MAIN_USE_ADVANCED_PERMS') ? $user->hasRight('service', 'service_advance', 'read_prices') : $user->hasRight('service', 'lire');
151 $usercancreadsupplierprice = getDolGlobalString('MAIN_USE_ADVANCED_PERMS') ? $user->hasRight('service', 'service_advance', 'read_supplier_prices') : $user->hasRight('service', 'lire');
152}
153
154if ($object->id > 0) {
155 if ($object->type == $object::TYPE_PRODUCT) {
156 restrictedArea($user, 'produit', $object->id, 'product&product', '', '');
157 }
158 if ($object->type == $object::TYPE_SERVICE) {
159 restrictedArea($user, 'service', $object->id, 'product&product', '', '');
160 }
161} else {
162 restrictedArea($user, 'produit|service', $id, 'product&product', '', '', $fieldid);
163}
164
165
166/*
167 * Actions
168 */
169
170if ($cancel) {
171 $action = '';
172}
173
174$parameters = array('id' => $id, 'ref' => $ref, 'objcanvas' => $objcanvas);
175$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
176if ($reshook < 0) {
177 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
178}
179
180if ($action == 'setcost_price' && $usercancreate) {
181 if ($id) {
182 $result = $object->fetch($id);
183 $object->cost_price = (float) price2num($cost_price);
184 $result = $object->update($object->id, $user);
185 if ($result > 0) {
186 setEventMessages($langs->trans("RecordSaved"), null, 'mesgs');
187 $action = '';
188 } else {
189 $error++;
190 setEventMessages($object->error, $object->errors, 'errors');
191 }
192 }
193}
194
195if ($action == 'addlimitstockwarehouse' && $usercancreate) {
196 $seuil_stock_alerte = GETPOSTFLOAT('seuil_stock_alerte');
197 $desiredstock = GETPOSTFLOAT('desiredstock');
198
199 $maj_ok = true;
200 if ($seuil_stock_alerte == '') {
201 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("StockLimit")), null, 'errors');
202 $maj_ok = false;
203 }
204 if ($desiredstock == '' || is_array($desiredstock)) {
205 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("DesiredStock")), null, 'errors');
206 $maj_ok = false;
207 }
208
209 $desiredstock = (float) $desiredstock;
210
211 if ($maj_ok) {
212 $pse = new ProductStockEntrepot($db);
213 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
214 if ($pse->fetch(0, $id, GETPOSTINT('fk_entrepot')) > 0) {
215 // Update
216 $pse->seuil_stock_alerte = $seuil_stock_alerte;
217 $pse->desiredstock = $desiredstock;
218 if ($pse->update($user) > 0) {
219 setEventMessages($langs->trans('ProductStockWarehouseUpdated'), null, 'mesgs');
220 }
221 } else {
222 // Create
223 $pse->fk_entrepot = GETPOSTINT('fk_entrepot');
224 $pse->fk_product = $id;
225 $pse->seuil_stock_alerte = GETPOSTFLOAT('seuil_stock_alerte');
226 $pse->desiredstock = GETPOSTFLOAT('desiredstock');
227 if ($pse->create($user) > 0) {
228 setEventMessages($langs->trans('ProductStockWarehouseCreated'), null, 'mesgs');
229 }
230 }
231 }
232
233 header("Location: ".$_SERVER["PHP_SELF"]."?id=".$id);
234 exit;
235}
236
237if ($action == 'delete_productstockwarehouse' && $usercancreate) {
238 $pse = new ProductStockEntrepot($db);
239
240 $pse->fetch(GETPOSTINT('fk_productstockwarehouse'));
241 if ($pse->delete($user) > 0) {
242 setEventMessages($langs->trans('ProductStockWarehouseDeleted'), null, 'mesgs');
243 }
244
245 $action = '';
246}
247
248// Set stock limit
249if ($action == 'setseuil_stock_alerte' && $usercancreate) {
250 $object = new Product($db);
251 $result = $object->fetch($id);
252 $object->seuil_stock_alerte = $stocklimit;
253 $result = $object->update($object->id, $user, 0, 'update');
254 if ($result < 0) {
255 setEventMessages($object->error, $object->errors, 'errors');
256 }
257 //else
258 // setEventMessages($lans->trans("SavedRecordSuccessfully"), null, 'mesgs');
259 $action = '';
260}
261
262// Set desired stock
263if ($action == 'setdesiredstock' && $usercancreate) {
264 $object = new Product($db);
265 $result = $object->fetch($id);
266 $object->desiredstock = $desiredstock;
267 $result = $object->update($object->id, $user, 0, 'update');
268 if ($result < 0) {
269 setEventMessages($object->error, $object->errors, 'errors');
270 }
271 $action = '';
272}
273
274
275// Correct stock
276if ($action == "correct_stock" && !$cancel && $usercanupdatestock) {
277 if (!(GETPOSTINT("id_entrepot") > 0)) {
278 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Warehouse")), null, 'errors');
279 $error++;
280 $action = 'correction';
281 }
282 if (!GETPOST("nbpiece")) {
283 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("NumberOfUnit")), null, 'errors');
284 $error++;
285 $action = 'correction';
286 }
287
288 if (isModEnabled('productbatch')) {
289 $object = new Product($db);
290 $result = $object->fetch($id);
291
292 if ($object->hasbatch() && !$batchnumber) {
293 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("batch_number")), null, 'errors');
294 $error++;
295 $action = 'correction';
296 }
297 }
298
299 if (!$error) {
300 $priceunit = price2num(GETPOST("unitprice"));
301 $nbpiece = price2num(GETPOST("nbpiece", 'alphanohtml'));
302 if (is_numeric($nbpiece) && $nbpiece != 0 && $id) {
303 $origin_element = '';
304 $origin_id = null;
305
306 if (GETPOSTINT('projectid')) {
307 $origin_element = 'project';
308 $origin_id = GETPOSTINT('projectid');
309 }
310
311 if (empty($object)) {
312 $object = new Product($db);
313 $result = $object->fetch($id);
314 }
315
316 $disablestockchangeforsubproduct = 0;
317 if (GETPOST('disablesubproductstockchange')) {
318 $disablestockchangeforsubproduct = 1;
319 }
320
321 if ($object->hasbatch()) {
322 $result = $object->correct_stock_batch(
323 $user,
324 GETPOSTINT("id_entrepot"),
325 (float) $nbpiece,
326 GETPOSTINT("mouvement"),
327 GETPOST("label", 'alphanohtml'), // label movement
328 (float) $priceunit,
329 $d_eatby,
330 $d_sellby,
331 $batchnumber,
332 GETPOST('inventorycode', 'alphanohtml'),
333 $origin_element,
334 $origin_id,
335 $disablestockchangeforsubproduct
336 ); // We do not change value of stock for a correction
337 } else {
338 $result = $object->correct_stock(
339 $user,
340 GETPOSTINT("id_entrepot"),
341 (float) $nbpiece,
342 GETPOSTINT("mouvement"),
343 GETPOST("label", 'alphanohtml'),
344 (float) $priceunit,
345 GETPOST('inventorycode', 'alphanohtml'),
346 $origin_element,
347 $origin_id,
348 $disablestockchangeforsubproduct
349 ); // We do not change value of stock for a correction
350 }
351
352 if ($result > 0) {
353 if ($backtopage) {
354 header("Location: ".$backtopage);
355 exit;
356 } else {
357 header("Location: ".$_SERVER["PHP_SELF"]."?id=".$object->id);
358 exit;
359 }
360 } else {
361 setEventMessages($object->error, $object->errors, 'errors');
362 $action = 'correction';
363 }
364 }
365 }
366}
367
368// Transfer stock from a warehouse to another warehouse
369if ($action == "transfert_stock" && !$cancel && $usercanupdatestock) {
370 if (!(GETPOSTINT("id_entrepot") > 0) || !(GETPOSTINT("id_entrepot_destination") > 0)) {
371 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Warehouse")), null, 'errors');
372 $error++;
373 $action = 'transfer';
374 }
375 if (!GETPOST("nbpiece")) {
376 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("NumberOfUnit")), null, 'errors');
377 $error++;
378 $action = 'transfer';
379 }
380 if (GETPOSTINT("id_entrepot") == GETPOSTINT("id_entrepot_destination")) {
381 setEventMessages($langs->trans("ErrorSrcAndTargetWarehouseMustDiffers"), null, 'errors');
382 $error++;
383 $action = 'transfer';
384 }
385 if (isModEnabled('productbatch')) {
386 $object = new Product($db);
387 $result = $object->fetch($id);
388
389 if ($object->hasbatch() && !$batchnumber) {
390 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("batch_number")), null, 'errors');
391 $error++;
392 $action = 'transfer';
393 }
394 }
395 $batch = '';
396 $sellby = 0;
397 $eatby = 0;
398
399 if (!$error) {
400 if ($id) {
401 $object = new Product($db);
402 $result = $object->fetch($id);
403 $result1 = -1;
404 $result2 = -1;
405
406 $db->begin();
407
408 $object->load_stock('novirtual'); // Load array product->stock_warehouse
409
410 // Define value of products moved
411 $pricesrc = 0;
412 if (isset($object->pmp)) {
413 $pricesrc = $object->pmp;
414 }
415 $pricedest = $pricesrc;
416
417 $nbpiece = price2num(GETPOST("nbpiece", 'alphanohtml'));
418
419 if ($object->hasbatch()) {
420 $pdluo = new Productbatch($db);
421
422 $srcwarehouseid = 0;
423
424 if ($pdluoid > 0) {
425 $result = $pdluo->fetch($pdluoid);
426 if ($result) {
427 $srcwarehouseid = $pdluo->warehouseid;
428 $batch = $pdluo->batch;
429 $eatby = $pdluo->eatby;
430 $sellby = $pdluo->sellby;
431 } else {
432 setEventMessages($pdluo->error, $pdluo->errors, 'errors');
433 $error++;
434 }
435 } else {
436 $srcwarehouseid = GETPOSTINT('id_entrepot');
437 $batch = $batchnumber;
438 $eatby = $d_eatby;
439 $sellby = $d_sellby;
440 }
441
442 $nbpiece = price2num(GETPOST("nbpiece", 'alphanohtml'));
443
444 if (!$error) {
445 // Remove stock
446 $result1 = $object->correct_stock_batch(
447 $user,
448 $srcwarehouseid,
449 (float) $nbpiece,
450 1,
451 GETPOST("label", 'alphanohtml'),
452 (float) $pricesrc,
453 $eatby,
454 $sellby,
455 $batch,
456 GETPOST('inventorycode', 'alphanohtml')
457 );
458 if ($result1 < 0) {
459 $error++;
460 }
461 }
462 if (!$error) {
463 // Add stock
464 $result2 = $object->correct_stock_batch(
465 $user,
466 GETPOSTINT("id_entrepot_destination"),
467 (float) $nbpiece,
468 0,
469 GETPOST("label", 'alphanohtml'),
470 (float) $pricedest,
471 $eatby,
472 $sellby,
473 (string) $batch,
474 GETPOST('inventorycode', 'alphanohtml')
475 );
476 if ($result2 < 0) {
477 $error++;
478 }
479 }
480 } else {
481 if (!$error) {
482 // Remove stock
483 $result1 = $object->correct_stock(
484 $user,
485 GETPOSTINT("id_entrepot"),
486 (float) $nbpiece,
487 1,
488 GETPOST("label", 'alphanohtml'),
489 (float) $pricesrc,
490 GETPOST('inventorycode', 'alphanohtml')
491 );
492 if ($result1 < 0) {
493 $error++;
494 }
495 }
496 if (!$error) {
497 // Add stock
498 $result2 = $object->correct_stock(
499 $user,
500 GETPOSTINT("id_entrepot_destination"),
501 (float) $nbpiece,
502 0,
503 GETPOST("label", 'alphanohtml'),
504 (float) $pricedest,
505 GETPOST('inventorycode', 'alphanohtml')
506 );
507 if ($result2 < 0) {
508 $error++;
509 }
510 }
511 }
512
513
514 if (!$error && $result1 >= 0 && $result2 >= 0) {
515 $db->commit();
516
517 if ($backtopage) {
518 header("Location: ".$backtopage);
519 exit;
520 } else {
521 header("Location: product.php?id=".$object->id);
522 exit;
523 }
524 } else {
525 setEventMessages($object->error, $object->errors, 'errors');
526 $db->rollback();
527 $action = 'transfer';
528 }
529 }
530 }
531}
532
533// Update batch information
534if ($action == 'updateline' && GETPOST('save') == $langs->trans("Save") && $usercancreate) {
535 $pdluo = new Productbatch($db);
536 $result = $pdluo->fetch(GETPOSTINT('pdluoid'));
537
538 if ($result > 0) {
539 if ($pdluo->id) {
540 if ((!GETPOST("sellby")) && (!GETPOST("eatby")) && (!$batchnumber)) {
541 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("atleast1batchfield")), null, 'errors');
542 } else {
543 $d_eatby = dol_mktime(0, 0, 0, GETPOSTINT('eatbymonth'), GETPOSTINT('eatbyday'), GETPOSTINT('eatbyyear'));
544 $d_sellby = dol_mktime(0, 0, 0, GETPOSTINT('sellbymonth'), GETPOSTINT('sellbyday'), GETPOSTINT('sellbyyear'));
545 $pdluo->batch = $batchnumber;
546 $pdluo->eatby = $d_eatby;
547 $pdluo->sellby = $d_sellby;
548 $result = $pdluo->update($user);
549 if ($result < 0) {
550 setEventMessages($pdluo->error, $pdluo->errors, 'errors');
551 }
552 }
553 } else {
554 setEventMessages($langs->trans('BatchInformationNotfound'), null, 'errors');
555 }
556 } else {
557 setEventMessages($pdluo->error, null, 'errors');
558 }
559 header("Location: product.php?id=".$id);
560 exit;
561}
562
563
564/*
565 * View
566 */
567
568$form = new Form($db);
569$formproduct = new FormProduct($db);
570$formproject = null;
571if (isModEnabled('project')) {
572 $formproject = new FormProjets($db);
573}
574
575$variants = 0;
576$iskit = 0;
577
578if ($id > 0 || $ref) {
579 $object = new Product($db);
580 $result = $object->fetch($id, $ref);
581
582 $iskit = $object->hasFatherOrChild(1);
583
584 $variants = $object->hasVariants();
585
586 $object->load_stock(); // This include the load_virtual_stock()
587
588 $title = $langs->trans('ProductServiceCard');
589 $helpurl = '';
590 $shortlabel = dol_trunc($object->label, 16);
591 if (GETPOST("type") == '0' || ($object->type == Product::TYPE_PRODUCT)) {
592 $title = $langs->trans('Product')." ".$shortlabel." - ".$langs->trans('Stock');
593 $helpurl = 'EN:Module_Products|FR:Module_Produits|ES:M&oacute;dulo_Productos';
594 }
595 if (GETPOST("type") == '1' || ($object->type == Product::TYPE_SERVICE)) {
596 $title = $langs->trans('Service')." ".$shortlabel." - ".$langs->trans('Stock');
597 $helpurl = 'EN:Module_Services_En|FR:Module_Services|ES:M&oacute;dulo_Servicios';
598 }
599
600 llxHeader('', $title, $helpurl, '', 0, 0, '', '', '', 'mod-product page-card_stock_product');
601
602 if (!empty($conf->use_javascript_ajax)) {
603 ?>
604 <script type="text/javascript">
605 $(document).ready(function() {
606 $(".collapse_batch").click(function() {
607 console.log("We click on collapse_batch");
608 var id_entrepot = $(this).attr('id').replace('ent', '');
609
610 if($(this).text().indexOf('+') > 0) {
611 $(".batch_warehouse" + id_entrepot).show();
612 $(this).html('(-)');
613 jQuery("#show_all").hide();
614 jQuery("#hide_all").show();
615 }
616 else {
617 $(".batch_warehouse" + id_entrepot).hide();
618 $(this).html('(+)');
619 }
620
621 return false;
622 });
623
624 $("#show_all").click(function() {
625 console.log("We click on show_all");
626 $("[class^=batch_warehouse]").show();
627 $("[class^=collapse_batch]").html('(-)');
628 jQuery("#show_all").hide();
629 jQuery("#hide_all").show();
630 return false;
631 });
632
633 $("#hide_all").click(function() {
634 console.log("We click on hide_all");
635 $("[class^=batch_warehouse]").hide();
636 $("[class^=collapse_batch]").html('(+)');
637 jQuery("#hide_all").hide();
638 jQuery("#show_all").show();
639 return false;
640 });
641
642 });
643 </script>
644 <?php
645 }
646
647 if ($result > 0) {
649 $titre = $langs->trans("CardProduct".$object->type);
650 $picto = ($object->type == Product::TYPE_SERVICE ? 'service' : 'product');
651
652 print dol_get_fiche_head($head, 'stock', $titre, -1, $picto);
653
655
656 $linkback = '<a href="'.DOL_URL_ROOT.'/product/list.php?restore_lastsearch_values=1&type='.$object->type.'">'.$langs->trans("BackToList").'</a>';
657 $object->next_prev_filter = "(te.fk_product_type:=:".((int) $object->type).")";
658
659 $shownav = 1;
660 if ($user->socid && !in_array('stock', explode(',', getDolGlobalString('MAIN_MODULES_FOR_EXTERNAL')))) {
661 $shownav = 0;
662 }
663
664 dol_banner_tab($object, 'ref', $linkback, $shownav, 'ref');
665
666 if (!$variants) {
667 print '<div class="fichecenter">';
668
669 print '<div class="fichehalfleft">';
670 print '<div class="underbanner clearboth"></div>';
671
672 print '<table class="border tableforfield centpercent">';
673
674 // Type
675 if (isModEnabled("product") && isModEnabled("service")) {
676 $typeformat = 'select;0:'.$langs->trans("Product").',1:'.$langs->trans("Service");
677 print '<tr><td class="titlefieldmiddle">';
678 print (!getDolGlobalString('PRODUCT_DENY_CHANGE_PRODUCT_TYPE')) ? $form->editfieldkey("Type", 'fk_product_type', (string) $object->type, $object, 0, $typeformat) : $langs->trans('Type');
679 print '</td><td>';
680 print $form->editfieldval("Type", 'fk_product_type', $object->type, $object, 0, $typeformat);
681 print '</td></tr>';
682 }
683
684 // Stockable product / default warehouse
685 if (($object->isProduct() || getDolGlobalInt('STOCK_SUPPORTS_SERVICES')) && isModEnabled('stock')) { // Do not use isStockManaged here.We must sow info even if stock not managed
686 print '<tr><td>' . $form->textwithpicto($langs->trans("StockableProduct"), $langs->trans('StockableProductDescription')) . '</td>';
687 print '<td>';
688 if ($iskit) {
689 print '<input type="checkbox" readonly disabled> <span class="opacitymedium">' . $langs->trans("NotSupportedOnKits").'</span>';
690 } else {
691 print '<input type="checkbox" readonly disabled '.($object->stockable_product == 1 ? 'checked' : '').'>';
692 }
693 print '</td></tr>';
694
695 if ($object->isStockManaged() && !$iskit) {
696 $warehouse = new Entrepot($db);
697 $warehouse->fetch($object->fk_default_warehouse);
698
699 print '<tr><td>'.$langs->trans("DefaultWarehouse").'</td><td>';
700 print(!empty($warehouse->id) ? $warehouse->getNomUrl(1) : '');
701 print '</td>';
702 }
703 }
704
705 if (isModEnabled('productbatch')) {
706 print '<tr><td class="titlefieldmiddle">'.$langs->trans("ManageLotSerial").'</td><td>';
707 print $object->getLibStatut(0, 2);
708 print '</td></tr>';
709 }
710
711 // Cost price. Can be used for margin module for option "calculate margin on explicit cost price
712 print '<tr><td>';
713 $textdesc = $langs->trans("CostPriceDescription");
714 $textdesc .= "<br>".$langs->trans("CostPriceUsage");
715 $text = $form->textwithpicto($langs->trans("CostPrice"), $textdesc, 1, 'help', '');
716 if (!$usercancreadsupplierprice) {
717 print $form->editfieldkey($text, 'cost_price', '', $object, 0, 'amount:6');
718 print '</td><td>';
719 print $form->editfieldval($text, 'cost_price', '', $object, 0, 'amount:6');
720 } else {
721 print $form->editfieldkey($text, 'cost_price', (string) $object->cost_price, $object, (int) $usercancreate, 'amount:6');
722 print '</td><td>';
723 print $form->editfieldval($text, 'cost_price', $object->cost_price, $object, $usercancreate, 'amount:6');
724 }
725 print '</td></tr>';
726
727
728
729 // AWP
730 print '<tr><td class="titlefieldmiddle">';
731 print $form->textwithpicto($langs->trans("AverageUnitPricePMPShort"), $langs->trans("AverageUnitPricePMPDesc"));
732 print '</td>';
733 print '<td>';
734 if ($object->pmp > 0 && $usercancreadsupplierprice) {
735 print price($object->pmp).' '.$langs->trans("HT");
736 }
737 print '</td>';
738 print '</tr>';
739
740 // Minimum Price
741 print '<tr><td>'.$langs->trans("BuyingPriceMin").'</td>';
742 print '<td>';
743 $product_fourn = new ProductFournisseur($db);
744 if ($product_fourn->find_min_price_product_fournisseur($object->id) > 0) {
745 if ($product_fourn->product_fourn_price_id > 0 && $usercancreadsupplierprice) {
746 print $product_fourn->display_price_product_fournisseur();
747 } else {
748 print $langs->trans("NotDefined");
749 }
750 }
751 print '</td></tr>';
752
753 if (!getDolGlobalString('PRODUIT_MULTIPRICES') && !getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) {
754 // Price
755 print '<tr><td>'.$langs->trans("SellingPrice").'</td><td>';
756 if ($usercancreadprice) {
757 if ($object->price_base_type == 'TTC') {
758 print price($object->price_ttc).' '.$langs->trans($object->price_base_type);
759 } else {
760 print price($object->price).' '.$langs->trans($object->price_base_type);
761 }
762 }
763 print '</td></tr>';
764
765 // Price minimum
766 print '<tr><td>'.$langs->trans("MinPrice").'</td><td>';
767 if ($usercancreadprice) {
768 if ($object->price_base_type == 'TTC') {
769 print price($object->price_min_ttc).' '.$langs->trans($object->price_base_type);
770 } else {
771 print price($object->price_min).' '.$langs->trans($object->price_base_type);
772 }
773 }
774 print '</td></tr>';
775 } else {
776 // Price
777 print '<tr><td>'.$langs->trans("SellingPrice").'</td><td>';
778 print '<span class="opacitymedium">'.$langs->trans("Variable").'</span>';
779 print '</td></tr>';
780
781 // Price minimum
782 print '<tr><td>'.$langs->trans("MinPrice").'</td><td>';
783 print '<span class="opacitymedium">'.$langs->trans("Variable").'</span>';
784 print '</td></tr>';
785 }
786
787 // Hook formObject
788 $parameters = array();
789 $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
790 print $hookmanager->resPrint;
791
792 print '</table>';
793
794 print '</div>';
795 print '<div class="fichehalfright"><div class="underbanner clearboth"></div>';
796
797 if (!$iskit || getDolGlobalInt('PRODUIT_SOUSPRODUITS_ALSO_ENABLE_PARENT_STOCK_MOVE')) {
798 print '<table class="border tableforfield centpercent">';
799
800 // Stock alert threshold
801 print '<tr><td>'.$form->editfieldkey($form->textwithpicto($langs->trans("StockLimit"), $langs->trans("StockLimitDesc"), 1), 'seuil_stock_alerte', (string) $object->seuil_stock_alerte, $object, $user->hasRight('produit', 'creer')).'</td><td>';
802 print $form->editfieldval("StockLimit", 'seuil_stock_alerte', $object->seuil_stock_alerte, $object, $user->hasRight('produit', 'creer'), 'string');
803 print '</td></tr>';
804
805 // Desired stock
806 print '<tr><td>'.$form->editfieldkey($form->textwithpicto($langs->trans("DesiredStock"), $langs->trans("DesiredStockDesc"), 1), 'desiredstock', (string) $object->desiredstock, $object, $user->hasRight('produit', 'creer'));
807 print '</td><td>';
808 print $form->editfieldval("DesiredStock", 'desiredstock', $object->desiredstock, $object, $user->hasRight('produit', 'creer'), 'string');
809 print '</td></tr>';
810
811 // Real stock
812 $text_stock_options = $langs->trans("RealStockDesc").'<br>';
813 $text_stock_options .= $langs->trans("RealStockWillAutomaticallyWhen").'<br>';
814 $text_stock_options .= (getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT') || getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT_CLOSE') ? '- '.$langs->trans("DeStockOnShipment").'<br>' : '');
815 $text_stock_options .= (getDolGlobalString('STOCK_CALCULATE_ON_VALIDATE_ORDER') ? '- '.$langs->trans("DeStockOnValidateOrder").'<br>' : '');
816 $text_stock_options .= (getDolGlobalString('STOCK_CALCULATE_ON_BILL') ? '- '.$langs->trans("DeStockOnBill").'<br>' : '');
817 $text_stock_options .= (getDolGlobalString('STOCK_CALCULATE_ON_SUPPLIER_BILL') ? '- '.$langs->trans("ReStockOnBill").'<br>' : '');
818 $text_stock_options .= (getDolGlobalString('STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER') ? '- '.$langs->trans("ReStockOnValidateOrder").'<br>' : '');
819 $text_stock_options .= (getDolGlobalString('STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER') ? '- '.$langs->trans("ReStockOnDispatchOrder").'<br>' : '');
820 $text_stock_options .= (getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION') || getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION_CLOSE') ? '- '.$langs->trans("StockOnReception").'<br>' : '');
821 $parameters = array();
822 $reshook = $hookmanager->executeHooks('physicalStockTextStockOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
823 if ($reshook > 0) {
824 $text_stock_options = $hookmanager->resPrint;
825 } elseif ($reshook == 0) {
826 $text_stock_options .= $hookmanager->resPrint;
827 } else {
828 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
829 }
830
831 print '<tr><td>';
832 print $form->textwithpicto($langs->trans("PhysicalStock"), $text_stock_options, 1);
833 print '</td>';
834 print '<td>'.price2num($object->stock_reel, 'MS');
835 if ($object->seuil_stock_alerte != '' && ($object->stock_reel < $object->seuil_stock_alerte)) {
836 print ' '.img_warning($langs->trans("StockLowerThanLimit", $object->seuil_stock_alerte));
837 }
838
839 print ' &nbsp; &nbsp;<a href="'.DOL_URL_ROOT.'/product/stock/stockatdate.php?productid='.$object->id.'">'.$langs->trans("StockAtDate").'</a>';
840 print '</td>';
841 print '</tr>';
842
843 $stocktheo = price2num($object->stock_theorique, 'MS');
844
845 $found = 0;
846 $helpondiff = '<strong>'.$langs->trans("StockDiffPhysicTeoric").':</strong><br>';
847 // Number of sales orders running
848 if (isModEnabled('order')) {
849 if ($found) {
850 $helpondiff .= '<br>';
851 } else {
852 $found = 1;
853 }
854 $helpondiff .= $langs->trans("ProductQtyInCustomersOrdersRunning").': '.$object->stats_commande['qty'];
855 $result = $object->load_stats_commande(0, '0', 1);
856 if ($result < 0) {
857 dol_print_error($db, $object->error);
858 }
859 $helpondiff .= ' <span class="opacitymedium">('.$langs->trans("ProductQtyInDraft").': '.$object->stats_commande['qty'].')</span>';
860 }
861
862 // Number of product from sales order already sent (partial shipping)
863 if (isModEnabled("shipping")) {
864 require_once DOL_DOCUMENT_ROOT.'/expedition/class/expedition.class.php';
865 $filterShipmentStatus = '';
866 if (getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT')) {
868 } elseif (getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT_CLOSE')) {
869 $filterShipmentStatus = Expedition::STATUS_CLOSED;
870 }
871 if ($found) {
872 $helpondiff .= '<br>';
873 } else {
874 $found = 1;
875 }
876 $result = $object->load_stats_sending(0, '2', 1, $filterShipmentStatus);
877 $helpondiff .= $langs->trans("ProductQtyInShipmentAlreadySent").': '.$object->stats_expedition['qty'];
878 }
879
880 // Number of supplier order running
881 if (isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) {
882 if ($found) {
883 $helpondiff .= '<br>';
884 } else {
885 $found = 1;
886 }
887 $result = $object->load_stats_commande_fournisseur(0, '3,4', 1);
888 $helpondiff .= $langs->trans("ProductQtyInSuppliersOrdersRunning").': '.$object->stats_commande_fournisseur['qty'];
889 $result = $object->load_stats_commande_fournisseur(0, '0,1,2', 1);
890 if ($result < 0) {
891 dol_print_error($db, $object->error);
892 }
893 $helpondiff .= ' <span class="opacitymedium">('.$langs->trans("ProductQtyInDraftOrWaitingApproved").': '.$object->stats_commande_fournisseur['qty'].')</span>';
894 }
895
896 // Number of product from supplier order already received (partial receipt)
897 if (isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) {
898 if ($found) {
899 $helpondiff .= '<br>';
900 } else {
901 $found = 1;
902 }
903 $helpondiff .= $langs->trans("ProductQtyInSuppliersShipmentAlreadyRecevied").': '.$object->stats_reception['qty'];
904 }
905
906 // Number of product in production
907 if (isModEnabled('mrp')) {
908 if ($found) {
909 $helpondiff .= '<br>';
910 } else {
911 $found = 1;
912 }
913 $helpondiff .= $langs->trans("ProductQtyToConsumeByMO").': '.$object->stats_mrptoconsume['qty'].'<br>';
914 $helpondiff .= $langs->trans("ProductQtyToProduceByMO").': '.$object->stats_mrptoproduce['qty'];
915 }
916 $parameters = array('found' => &$found, 'id' => $object->id, 'includedraftpoforvirtual' => null);
917 $reshook = $hookmanager->executeHooks('virtualStockHelpOnDiff', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
918 if ($reshook > 0) {
919 $helpondiff = $hookmanager->resPrint;
920 } elseif ($reshook == 0) {
921 $helpondiff .= $hookmanager->resPrint;
922 } else {
923 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
924 }
925
926
927 // Calculating a theoretical value
928 print '<tr><td>';
929 print $form->textwithpicto($langs->trans("VirtualStock"), $langs->trans("VirtualStockDesc"));
930 print '</td>';
931 print "<td>";
932 //print (empty($stocktheo)?0:$stocktheo);
933 print $form->textwithpicto((empty($stocktheo) ? 0 : $stocktheo), $helpondiff);
934 if ($object->seuil_stock_alerte != '' && ($object->stock_theorique < $object->seuil_stock_alerte)) {
935 print ' '.img_warning($langs->trans("StockLowerThanLimit", $object->seuil_stock_alerte));
936 }
937 print ' &nbsp; &nbsp;<a href="'.DOL_URL_ROOT.'/product/stock/stockatdate.php?mode=future&productid='.$object->id.'">'.$langs->trans("VirtualStockAtDate").'</a>';
938 print '</td>';
939 print '</tr>';
940
941 // Last movement
942 if ($user->hasRight('stock', 'mouvement', 'lire')) {
943 $sql = "SELECT max(m.datem) as datem";
944 $sql .= " FROM ".MAIN_DB_PREFIX."stock_mouvement as m";
945 $sql .= " WHERE m.fk_product = ".((int) $object->id);
946 $lastmovementdate = 0;
947 $resqlbis = $db->query($sql);
948 if ($resqlbis) {
949 $obj = $db->fetch_object($resqlbis);
950 $lastmovementdate = $db->jdate($obj->datem);
951 } else {
953 }
954 print '<tr><td class="tdtop">'.$langs->trans("LastMovement").'</td><td>';
955 if ($lastmovementdate) {
956 print dol_print_date($lastmovementdate, 'dayhour').' ';
957 print ' &nbsp; &nbsp; ';
958 print img_picto($langs->trans("StockMovement"), 'movement', 'class="pictofixedwidth"');
959 print '<a href="'.DOL_URL_ROOT.'/product/stock/movement_list.php?idproduct='.$object->id.'">'.$langs->trans("FullList").'</a>';
960 } else {
961 print img_picto($langs->trans("StockMovement"), 'movement', 'class="pictofixedwidth"');
962 print '<a href="'.DOL_URL_ROOT.'/product/stock/movement_list.php?idproduct='.$object->id.'">'.$langs->trans("None").'</a>';
963 }
964 print "</td></tr>";
965 }
966
967 print "</table>";
968 }
969
970 print '</div>';
971 print '</div>';
972
973 print '<div class="clearboth"></div>';
974 }
975
976 print dol_get_fiche_end();
977 }
978
979 // Correct stock
980 if ($action == "correction") {
981 include DOL_DOCUMENT_ROOT.'/product/stock/tpl/stockcorrection.tpl.php';
982 print '<br><br>';
983 }
984
985 // Transfer of units
986 if ($action == "transfer") {
987 include DOL_DOCUMENT_ROOT.'/product/stock/tpl/stocktransfer.tpl.php';
988 print '<br><br>';
989 }
990} else {
992}
993
994
995$showstockdetails = 1;
996if ($variants && !getDolGlobalString('VARIANT_ALLOW_STOCK_MOVEMENT_ON_VARIANT_PARENT')) {
997 $showstockdetails = 0;
998}
999if ($iskit && !getDolGlobalInt('PRODUIT_SOUSPRODUITS_ALSO_ENABLE_PARENT_STOCK_MOVE')) {
1000 $showstockdetails = 0;
1001}
1002
1003
1004
1005// Actions buttons
1006
1007$parameters = array();
1008
1009$reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1010if (empty($reshook)) {
1011 if (empty($action) && $object->id) {
1012 if ($showstockdetails) {
1013 print '<div class="tabsAction">'."\n";
1014
1015 if ($user->hasRight('stock', 'mouvement', 'creer')) {
1016 if (!$variants || getDolGlobalString('VARIANT_ALLOW_STOCK_MOVEMENT_ON_VARIANT_PARENT')) {
1017 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=transfer&token='.newToken().'">'.$langs->trans("TransferStock").'</a>';
1018 } else {
1019 print '<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("ActionAvailableOnVariantProductOnly").'">'.$langs->trans("TransferStock").'</a>';
1020 }
1021 } else {
1022 print '<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("NotEnoughPermissions").'">'.$langs->trans("TransferStock").'</a>';
1023 }
1024
1025 if ($user->hasRight('stock', 'mouvement', 'creer')) {
1026 if (!$variants || getDolGlobalString('VARIANT_ALLOW_STOCK_MOVEMENT_ON_VARIANT_PARENT')) {
1027 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=correction&token='.newToken().'">'.$langs->trans("CorrectStock").'</a>';
1028 } else {
1029 print '<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("ActionAvailableOnVariantProductOnly").'">'.$langs->trans("CorrectStock").'</a>';
1030 }
1031 } else {
1032 print '<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("NotEnoughPermissions").'">'.$langs->trans("CorrectStock").'</a>';
1033 }
1034
1035 print '</div>';
1036 }
1037 }
1038}
1039
1040
1041if ($showstockdetails) {
1042 /*
1043 * Stock detail (by warehouse). May go down into batch details.
1044 */
1045
1046 print '<div class="div-table-responsive">';
1047 print '<table class="noborder centpercent">';
1048
1049 print '<tr class="liste_titre">';
1050 print '<td colspan="4">'.$langs->trans("Warehouse").'</td>';
1051 print '<td class="right">'.$langs->trans("NumberOfUnit").'</td>';
1052 print '<td class="right">'.$form->textwithpicto($langs->trans("AverageUnitPricePMPShort"), $langs->trans("AverageUnitPricePMPDesc")).'</td>';
1053 print '<td class="right">'.$langs->trans("EstimatedStockValueShort").'</td>';
1054 print '<td class="right">'.$langs->trans("SellPriceMin").'</td>';
1055 print '<td class="right">'.$langs->trans("EstimatedStockValueSellShort").'</td>';
1056 print '<td></td>';
1057 print '<td></td>';
1058 print '</tr>';
1059
1060 if ((isModEnabled('productbatch')) && $object->hasbatch()) {
1061 $colspan = 3;
1062 print '<tr class="liste_titre"><td class="minwidth200">';
1063 if (!empty($conf->use_javascript_ajax)) {
1064 print '<a id="show_all" href="#" class="hideobject">'.img_picto('', 'folder-open', 'class="paddingright"').$langs->trans("ShowAllLots").'</a>';
1065 //print ' &nbsp; ';
1066 print '<a id="hide_all" href="#">'.img_picto('', 'folder', 'class="paddingright"').$langs->trans("HideLots").'</a>';
1067 //print '&nbsp;'.$form->textwithpicto('', $langs->trans('CollapseBatchDetailHelp'), 1, 'help', '');
1068 }
1069 print '</td>';
1070 print '<td class="right">'.$langs->trans("batch_number").'</td>';
1071 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
1072 $colspan--;
1073 print '<td class="center width100">'.$langs->trans("SellByDate").'</td>';
1074 }
1075 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
1076 $colspan--;
1077 print '<td class="center width100">'.$langs->trans("EatByDate").'</td>';
1078 }
1079 print '<td colspan="'.$colspan.'"></td>';
1080 print '<td></td>';
1081 print '<td></td>';
1082 print '<td></td>';
1083 print '<td></td>';
1084 print '<td></td>';
1085 print '<td></td>';
1086 print '</tr>';
1087 }
1088
1089 $sql = "SELECT e.rowid, e.ref, e.lieu, e.fk_parent, e.statut as status, ps.reel, ps.rowid as product_stock_id, p.pmp";
1090 $sql .= " FROM ".MAIN_DB_PREFIX."entrepot as e,";
1091 $sql .= " ".MAIN_DB_PREFIX."product_stock as ps";
1092 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = ps.fk_product";
1093 $sql .= " WHERE ps.reel != 0";
1094 $sql .= " AND ps.fk_entrepot = e.rowid";
1095 $sql .= " AND e.entity IN (".getEntity('stock').")";
1096 $sql .= " AND ps.fk_product = ".((int) $object->id);
1097 $sql .= " ORDER BY e.ref";
1098
1099 $entrepotstatic = new Entrepot($db);
1100 $product_lot_static = new Productlot($db);
1101
1102 $num = 0;
1103 $total = 0;
1104 $totalvalue = $totalvaluesell = 0;
1105 $totalwithpmp = 0;
1106
1107 $resql = $db->query($sql);
1108 if ($resql) {
1109 $num = $db->num_rows($resql);
1110 $total = $totalwithpmp;
1111 $i = 0;
1112 $var = false;
1113 while ($i < $num) {
1114 $obj = $db->fetch_object($resql);
1115
1116 $entrepotstatic->id = $obj->rowid;
1117 $entrepotstatic->ref = $obj->ref;
1118 $entrepotstatic->label = $obj->ref;
1119 $entrepotstatic->lieu = $obj->lieu;
1120 $entrepotstatic->fk_parent = $obj->fk_parent;
1121 $entrepotstatic->statut = $obj->status;
1122 $entrepotstatic->status = $obj->status;
1123
1124 $stock_real = price2num($obj->reel, 'MS');
1125 print '<tr class="oddeven">';
1126
1127 // Warehouse
1128 print '<td colspan="4">';
1129 print $entrepotstatic->getNomUrl(1);
1130 if (!empty($conf->use_javascript_ajax) && isModEnabled('productbatch') && $object->hasbatch()) {
1131 print '<a class="collapse_batch marginleftonly" id="ent' . $entrepotstatic->id . '" href="#">';
1132 print(!getDolGlobalString('STOCK_SHOW_ALL_BATCH_BY_DEFAULT') ? '(+)' : '(-)');
1133 print '</a>';
1134 }
1135 print '</td>';
1136
1137 print '<td class="right">'.$stock_real.($stock_real < 0 ? ' '.img_warning() : '').'</td>';
1138
1139 // PMP
1140 print '<td class="right nowraponall">'.($usercancreadsupplierprice ? (price2num($object->pmp) ? price2num($object->pmp, 'MU') : '') : '').'</td>';
1141
1142 // Value purchase
1143 if ($usercancreadsupplierprice) {
1144 print '<td class="right amount nowraponall">'.(price2num($object->pmp) ? price(price2num($object->pmp * $obj->reel, 'MT')) : '').'</td>';
1145 } else {
1146 print '<td class="right amount nowraponall"></td>';
1147 }
1148
1149 // Sell price
1150 $minsellprice = null;
1151 $maxsellprice = null;
1152 print '<td class="right nowraponall">';
1153 if (getDolGlobalString('PRODUIT_MULTIPRICES')) {
1154 foreach ($object->multiprices as $priceforlevel) {
1155 if (is_numeric($priceforlevel)) {
1156 if (is_null($maxsellprice) || $priceforlevel > $maxsellprice) {
1157 $maxsellprice = $priceforlevel;
1158 }
1159 if (is_null($minsellprice) || $priceforlevel < $minsellprice) {
1160 $minsellprice = $priceforlevel;
1161 }
1162 }
1163 }
1164 print '<span class="valignmiddle">';
1165 if ($usercancreadprice) {
1166 if ($minsellprice != $maxsellprice) {
1167 print price(price2num($minsellprice, 'MU'), 1).' - '.price(price2num($maxsellprice, 'MU'), 1);
1168 } else {
1169 print price(price2num($minsellprice, 'MU'), 1);
1170 }
1171 }
1172 print '</span>';
1173 print $form->textwithpicto('', $langs->trans("Variable"));
1174 } elseif ($usercancreadprice) {
1175 print price(price2num($object->price, 'MU'), 1);
1176 }
1177 print '</td>';
1178
1179 // Value sell
1180 print '<td class="right amount nowraponall">';
1181 if (getDolGlobalString('PRODUIT_MULTIPRICES')) {
1182 print '<span class="valignmiddle">';
1183 if ($usercancreadprice) {
1184 if ($minsellprice != $maxsellprice) {
1185 print price(price2num($minsellprice * $obj->reel, 'MT'), 1).' - '.price(price2num($maxsellprice * $obj->reel, 'MT'), 1);
1186 } else {
1187 print price(price2num($minsellprice * $obj->reel, 'MT'), 1);
1188 }
1189 }
1190 print '</span>';
1191 print $form->textwithpicto('', $langs->trans("Variable"));
1192 } else {
1193 if ($usercancreadprice) {
1194 print price(price2num($object->price * $obj->reel, 'MT'), 1);
1195 }
1196 }
1197 print '</td>';
1198 print '<td></td>';
1199 print '<td></td>';
1200 print '</tr>';
1201 $total += $obj->reel;
1202 if (price2num($object->pmp)) {
1203 $totalwithpmp += $obj->reel;
1204 }
1205 $totalvalue += ($object->pmp * $obj->reel);
1206 $totalvaluesell += ($object->price * $obj->reel);
1207 // Batch Detail
1208 if ((isModEnabled('productbatch')) && $object->hasbatch()) {
1209 $details = Productbatch::findAll($db, $obj->product_stock_id, 0, $object->id);
1210 if ($details < 0) {
1212 }
1213 foreach ($details as $pdluo) {
1214 $product_lot_static->id = $pdluo->lotid;
1215 $product_lot_static->batch = $pdluo->batch;
1216 $product_lot_static->eatby = $pdluo->eatby;
1217 $product_lot_static->sellby = $pdluo->sellby;
1218
1219 if ($action == 'editline' && GETPOSTINT('lineid') == $pdluo->id) { //Current line edit
1220 print "\n".'<tr>';
1221 print '<td colspan="9">';
1222 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
1223 print '<input type="hidden" name="token" value="'.newToken().'">';
1224 print '<input type="hidden" name="pdluoid" value="'.$pdluo->id.'"><input type="hidden" name="action" value="updateline"><input type="hidden" name="id" value="'.$id.'"><table class="noborder centpercent"><tr><td width="10%"></td>';
1225 print '<td class="right" width="10%"><input type="text" name="batch_number" value="'.$pdluo->batch.'"></td>';
1226 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
1227 print '<td class="center" width="10%">';
1228 print $form->selectDate($pdluo->sellby, 'sellby', 0, 0, 1, '', 1, 0);
1229 print '</td>';
1230 }
1231 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
1232 print '<td class="center" width="10%">';
1233 print $form->selectDate($pdluo->eatby, 'eatby', 0, 0, 1, '', 1, 0);
1234 print '</td>';
1235 }
1236 print '<td class="right" colspan="3">'.$pdluo->qty.($pdluo->qty < 0 ? ' '.img_warning() : '').'</td>';
1237 print '<td colspan="4"><input type="submit" class="button button-save" id="savelinebutton marginbottomonly" name="save" value="'.$langs->trans("Save").'">';
1238 print '<input type="submit" class="button button-cancel" id="cancellinebutton" name="Cancel" value="'.$langs->trans("Cancel").'"></td></tr>';
1239 print '</table>';
1240 print '</form>';
1241 print '</td>';
1242 print '<td></td>';
1243 print '<td></td>';
1244 print '</tr>';
1245 } else {
1246 print "\n".'<tr style="display:'.(!getDolGlobalString('STOCK_SHOW_ALL_BATCH_BY_DEFAULT') ? 'none' : 'visible').';" class="batch_warehouse'.$entrepotstatic->id.'"><td class="left">';
1247 print '</td>';
1248 print '<td class="right nowraponall">';
1249 if ($product_lot_static->id > 0) {
1250 print $product_lot_static->getNomUrl(1);
1251 } else {
1252 print $product_lot_static->getNomUrl(1, 'nolink');
1253 }
1254 print '</td>';
1255 $colspan = 3;
1256 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
1257 $colspan--;
1258 print '<td class="center">'.dol_print_date($pdluo->sellby, 'day').'</td>';
1259 }
1260 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
1261 $colspan--;
1262 print '<td class="center">'.dol_print_date($pdluo->eatby, 'day').'</td>';
1263 }
1264 print '<td class="right" colspan="'.$colspan.'">'.$pdluo->qty.($pdluo->qty < 0 ? ' '.img_warning() : (($pdluo->qty > 1 && $object->status_batch == 2) ? ' '.img_warning($langs->trans('IlligalQtyForSerialNumbers')) : '')).'</td>';
1265 print '<td colspan="4"></td>';
1266 print '<td class="center tdoverflowmax125" title="'.dol_escape_htmltag($langs->trans("TransferStock")).'">';
1267 if ($entrepotstatic->status != $entrepotstatic::STATUS_CLOSED) {
1268 print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&id_entrepot='.$entrepotstatic->id.'&action=transfer&pdluoid='.$pdluo->id.'&token='.newToken().'">';
1269 print img_picto($langs->trans("TransferStock"), 'add', 'class="hideonsmartphone paddingright" style="color: #a69944"');
1270 print $langs->trans("TransferStock");
1271 print '</a>';
1272 // Disabled, because edition of stock content must use the "Correct stock menu".
1273 // Do not use this, or data will be wrong (bad tracking of movement label, inventory code, ...
1274 //print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$id.'&action=editline&token='.newToken().'&lineid='.$pdluo->id.'#'.$pdluo->id.'">';
1275 //print img_edit().'</a>';
1276 }
1277 print '</td>';
1278 print '<td class="center tdoverflowmax125" title="'.dol_escape_htmltag($langs->trans("CorrectStock")).'">';
1279 if ($entrepotstatic->status != $entrepotstatic::STATUS_CLOSED) {
1280 print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&id_entrepot='.$entrepotstatic->id.'&action=correction&pdluoid='.$pdluo->id.'&token='.newToken().'">';
1281 print img_picto($langs->trans("CorrectStock"), 'add', 'class="hideonsmartphone paddingright" style="color: #a69944"');
1282 print $langs->trans("CorrectStock");
1283 print '</a>';
1284 // Disabled, because edition of stock content must use the "Correct stock menu".
1285 // Do not use this, or data will be wrong (bad tracking of movement label, inventory code, ...
1286 //print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$id.'&action=editline&token='.newToken().'&lineid='.$pdluo->id.'#'.$pdluo->id.'">';
1287 //print img_edit().'</a>';
1288 }
1289 print '</td>';
1290 print '</tr>';
1291 }
1292 }
1293 }
1294 $i++;
1295 }
1296 } else {
1298 }
1299
1300 // Total line
1301 print '<tr class="liste_total"><td class="right liste_total" colspan="4">'.$langs->trans("Total").':</td>';
1302 print '<td class="liste_total right">'.price2num($total, 'MS').'</td>';
1303 print '<td class="liste_total right">';
1304 if ($usercancreadsupplierprice) {
1305 print($totalwithpmp ? price(price2num($totalvalue / $totalwithpmp, 'MU')) : '&nbsp;'); // This value may have rounding errors
1306 }
1307 print '</td>';
1308 // Value purchase
1309 print '<td class="liste_total right">';
1310 if ($usercancreadsupplierprice) {
1311 print $totalvalue ? price(price2num($totalvalue, 'MT'), 1) : '&nbsp;';
1312 }
1313 print '</td>';
1314 print '<td class="liste_total right">';
1315 if ($num) {
1316 if ($total) {
1317 print '<span class="valignmiddle">';
1318 if (getDolGlobalString('PRODUIT_MULTIPRICES')) {
1319 print $form->textwithpicto('', $langs->trans("Variable"));
1320 } elseif ($usercancreadprice) {
1321 print price($totalvaluesell / $total, 1);
1322 }
1323 print '</span>';
1324 }
1325 }
1326 print '</td>';
1327 // Value to sell
1328 print '<td class="liste_total right amount">';
1329 if ($num) {
1330 print '<span class="valignmiddle">';
1331 if (!getDolGlobalString('PRODUIT_MULTIPRICES') && !getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES') && $usercancreadprice) {
1332 print price(price2num($totalvaluesell, 'MT'), 1);
1333 } else {
1334 print $form->textwithpicto('', $langs->trans("Variable"));
1335 }
1336 print '</span>';
1337 }
1338 print '</td>';
1339 print '<td></td>';
1340 print '<td></td>';
1341 print "</tr>";
1342
1343 print "</table>";
1344 print '</div>';
1345
1346
1347 if (getDolGlobalString('STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE')) {
1348 print '<br><br>';
1349 print load_fiche_titre($langs->trans('AddNewProductStockWarehouse'));
1350
1351 if ($user->hasRight('produit', 'creer')) {
1352 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
1353 print '<input type="hidden" name="token" value="'.newToken().'">';
1354 print '<input type="hidden" name="action" value="addlimitstockwarehouse">';
1355 print '<input type="hidden" name="id" value="'.$id.'">';
1356 }
1357 print '<table class="noborder centpercent">';
1358 if ($user->hasRight('produit', 'creer')) {
1359 print '<tr class="liste_titre"><td>'.$formproduct->selectWarehouses('', 'fk_entrepot').'</td>';
1360 print '<td class="right"><input name="seuil_stock_alerte" type="text" placeholder="'.$langs->trans("StockLimit").'" /></td>';
1361 print '<td class="right"><input name="desiredstock" type="text" placeholder="'.$langs->trans("DesiredStock").'" /></td>';
1362 print '<td class="right"><input type="submit" value="'.$langs->trans("Save").'" class="button button-save" /></td>';
1363 print '</tr>';
1364 } else {
1365 print '<tr class="liste_titre"><td>'.$langs->trans("Warehouse").'</td>';
1366 print '<td class="right">'.$langs->trans("StockLimit").'</td>';
1367 print '<td class="right">'.$langs->trans("DesiredStock").'</td>';
1368 print '</tr>';
1369 }
1370
1371 $pse = new ProductStockEntrepot($db);
1372 $lines = $pse->fetchAll($id);
1373
1374 $visibleWarehouseEntities = explode(',', getEntity('stock')); // For MultiCompany compatibility
1375
1376 if (!empty($lines)) {
1377 $var = false;
1378 foreach ($lines as $line) {
1379 $ent = new Entrepot($db);
1380 $ent->fetch($line['fk_entrepot']);
1381
1382 if (!isModEnabled("multicompany") || in_array($ent->entity, $visibleWarehouseEntities)) {
1383 // Display only warehouses from our entity and entities sharing stock with actual entity
1384 print '<tr class="oddeven"><td>'.$ent->getNomUrl(3).'</td>';
1385 print '<td class="right">'.$line['seuil_stock_alerte'].'</td>';
1386 print '<td class="right">'.$line['desiredstock'].'</td>';
1387 if ($user->hasRight('produit', 'creer')) {
1388 print '<td class="right"><a href="'.$_SERVER['PHP_SELF'].'?id='.$id.'&fk_productstockwarehouse='.$line['id'].'&action=delete_productstockwarehouse&token='.newToken().'">'.img_delete().'</a></td>';
1389 }
1390 print '</tr>';
1391 }
1392 }
1393 }
1394
1395 print "</table>";
1396
1397 if ($user->hasRight('produit', 'creer')) {
1398 print '</form>';
1399 }
1400 }
1401}
1402
1403if ($variants) {
1404 // List of variants
1405 include_once DOL_DOCUMENT_ROOT.'/variants/class/ProductCombination.class.php';
1406 include_once DOL_DOCUMENT_ROOT.'/variants/class/ProductCombination2ValuePair.class.php';
1407 $prodstatic = new Product($db);
1408 $prodcomb = new ProductCombination($db);
1409 $comb2val = new ProductCombination2ValuePair($db);
1410 $productCombinations = $prodcomb->fetchAllByFkProductParent($object->id);
1411
1412 print '<form method="POST" action="'.dolBuildUrl($_SERVER["PHP_SELF"]).'">';
1413 print '<input type="hidden" name="token" value="'.newToken().'">';
1414 print '<input type="hidden" name="action" value="massaction">';
1415 print '<input type="hidden" name="id" value="'.$id.'">';
1416 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
1417
1418 // load variants
1419 $title = $langs->trans("ProductCombinations");
1420
1421 print_barre_liste($title, 0, $_SERVER["PHP_SELF"], '', $sortfield, $sortorder, '', 0);
1422
1423 print '<div class="div-table-responsive">'; ?>
1424 <table class="liste">
1425 <tr class="liste_titre">
1426 <td class="liste_titre"><?php echo $langs->trans('Product') ?></td>
1427 <td class="liste_titre"><?php echo $langs->trans('Combination') ?></td>
1428 <td class="liste_titre center"><?php echo $langs->trans('OnSell') ?></td>
1429 <td class="liste_titre center"><?php echo $langs->trans('OnBuy') ?></td>
1430 <td class="liste_titre right"><?php echo $langs->trans('Stock') ?></td>
1431 <td class="liste_titre"></td>
1432 </tr>
1433 <?php
1434
1435 if (count($productCombinations)) {
1436 $stock_total = 0;
1437 foreach ($productCombinations as $currcomb) {
1438 $prodstatic->fetch($currcomb->fk_product_child);
1439 $prodstatic->load_stock();
1440 $stock_total += $prodstatic->stock_reel; ?>
1441 <tr class="oddeven">
1442 <td><?php echo $prodstatic->getNomUrl(1) ?></td>
1443 <td>
1444 <?php
1445
1446 $productCombination2ValuePairs = $comb2val->fetchByFkCombination($currcomb->id);
1447 $iMax = count($productCombination2ValuePairs);
1448
1449 for ($i = 0; $i < $iMax; $i++) {
1450 echo dol_htmlentities($productCombination2ValuePairs[$i]);
1451
1452 if ($i !== ($iMax - 1)) {
1453 echo ', ';
1454 }
1455 } ?>
1456 </td>
1457 <td style="text-align: center;"><?php echo $prodstatic->getLibStatut(2, 0) ?></td>
1458 <td style="text-align: center;"><?php echo $prodstatic->getLibStatut(2, 1) ?></td>
1459 <td class="right"><?php echo $prodstatic->stock_reel ?></td>
1460 <td class="right">
1461 <a class="paddingleft paddingright editfielda" href="<?php echo dol_buildpath('/product/stock/product.php?id='.$currcomb->fk_product_child, 2) ?>"><?php echo img_edit() ?></a>
1462 </td>
1463 <?php
1464 ?>
1465 </tr>
1466 <?php
1467 }
1468
1469 print '<tr class="liste_total">';
1470 print '<td colspan="4" class="left">'.$langs->trans("Total").'</td>';
1471 print '<td class="right">'.$stock_total.'</td>';
1472 print '<td></td>';
1473 print '</tr>';
1474 } else {
1475 print '<tr><td colspan="8"><span class="opacitymedium">'.$langs->trans("None").'</span></td></tr>';
1476 } ?>
1477 </table>
1478
1479 <?php
1480 print '</div>';
1481
1482 print '</form>';
1483}
1484
1485// End of page
1486llxFooter();
1487$db->close();
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:47
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
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 canvas.
Class to manage warehouses.
const STATUS_CLOSED
Closed status -> parcel was received by customer / end of process prev status : validated or shipment...
const STATUS_VALIDATED
Validated status -> parcel is ready to be sent prev status : draft next status : closed or shipment_i...
Class to manage standard extra fields.
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 ...
Class to manage building of HTML components.
Class ProductCombination2ValuePair Used to represent the relation between a variant and its attribute...
Class ProductCombination Used to represent the relation between a product and one of its variants.
Class to manage predefined suppliers products.
Class to manage products or services.
const TYPE_PRODUCT
Regular product.
const TYPE_SERVICE
Service.
Class ProductStockEntrepot.
Manage record for batch number management.
static findAll($dbs, $fk_product_stock, $with_qty=0, $fk_product=0)
Return all batch detail records for a given product and warehouse.
Class with list of lots and properties.
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed information (by default a local PHP server timestamp) Rep...
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
print_barre_liste($title, $page, $file, $options='', $sortfield='', $sortorder='', $morehtmlcenter='', $num=-1, $totalnboflines='', $picto='generic', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limit=-1, $selectlimitsuffix=0, $hidenavigation=0, $pagenavastextinput=0, $morehtmlrightbeforearrow='')
Print a title with navigation controls for pagination.
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)
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
img_delete($titlealt='default', $other='class="pictodelete"', $morecss='')
Show delete logo.
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
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.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
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.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
GETPOSTFLOAT($paramname, $rounding='', $option=2)
Return the value of a $_GET or $_POST supervariable, converted into float.
dol_htmlentities($string, $flags=ENT_QUOTES|ENT_SUBSTITUTE, $encoding='UTF-8', $double_encode=false)
Replace htmlentities functions.
dol_htmloutput_events($disabledoutputofmessages=0)
Print formatted messages to output (Used to show messages on html output).
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
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.
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.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
img_edit($titlealt='default', $float=0, $other='')
Show logo edit/modify fiche.
getEntity($element, $shared=1, $currentobject=null)
Get list of entity id to use.
treeview li table
No Email.
product_prepare_head($object)
Prepare array with list of tabs.
if(preg_match('/(crypted|dolcrypt):/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
'integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]',...
Definition repair.php:130
restrictedArea(User $user, $features, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $isdraft=0, $mode=0)
Check permissions of a user to show a page and an object.