dolibarr 22.0.5
reassort.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2001-2006 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2004-2015 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2005-2018 Regis Houssin <regis.houssin@inodbox.com>
5 * Copyright (C) 2013 Cédric Salvador <csalvador@gpcsolutions.fr>
6 * Copyright (C) 2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
7 * Copyright (C) 2019 Juanjo Menent <jmenent@2byte.es>
8 * Copyright (C) 2023 Vincent de Grandpré <vincent@de-grandpre.quebec>
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
31// Load Dolibarr environment
32require '../main.inc.php';
33require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
34require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
35require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
36require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
37
46// Load translation files required by the page
47$langs->loadLangs(array('products', 'stocks'));
48
49$action = GETPOST('action', 'aZ09');
50$sref = GETPOST("sref", 'alpha');
51$snom = GETPOST("snom", 'alpha');
52$sall = trim(GETPOST('search_all', 'alphanohtml'));
53$type = GETPOSTISSET('type') ? GETPOSTINT('type') : Product::TYPE_PRODUCT;
54$search_barcode = GETPOST("search_barcode", 'alpha');
55$search_toolowstock = GETPOST('search_toolowstock');
56$tosell = GETPOST("tosell");
57$tobuy = GETPOST("tobuy");
58$fourn_id = GETPOSTINT("fourn_id");
59$sbarcode = GETPOSTINT("sbarcode");
60$search_stock_physique = GETPOST('search_stock_physique', 'alpha');
61
62$sortfield = GETPOST('sortfield', 'aZ09comma');
63$sortorder = GETPOST('sortorder', 'aZ09comma');
64$page = GETPOSTISSET('pageplusone') ? (GETPOSTINT('pageplusone') - 1) : GETPOSTINT("page");
65if (empty($page) || $page < 0) {
66 $page = 0;
67}
68if (!$sortfield) {
69 $sortfield = "p.ref";
70}
71if (!$sortorder) {
72 $sortorder = "ASC";
73}
74$limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit;
75if (empty($page) || $page == -1) {
76 $page = 0;
77} // If $page is not defined, or '' or -1
78$offset = $limit * $page;
79
80// Load sale and categ filters
81$search_sale = GETPOST("search_sale");
82if (GETPOSTISSET('catid')) {
83 $search_categ = GETPOSTINT('catid');
84} else {
85 $search_categ = GETPOSTINT('search_categ');
86}
87
88// Get object canvas (By default, this is not defined, so standard usage of dolibarr)
89$canvas = GETPOST("canvas");
90$objcanvas = null;
91if (!empty($canvas)) {
92 require_once DOL_DOCUMENT_ROOT.'/core/class/canvas.class.php';
93 $objcanvas = new Canvas($db, $action);
94 $objcanvas->getCanvas('product', 'list', $canvas);
95}
96
97// Define virtualdiffersfromphysical
98$virtualdiffersfromphysical = 0;
99if (getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT')
100 || getDolGlobalString('STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER')
101 || getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT_CLOSE')
102 || getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION')
103 || getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION_CLOSE')
104 || isModEnabled('mrp')) {
105 $virtualdiffersfromphysical = 1; // According to increase/decrease stock options, virtual and physical stock may differs.
106}
107
108// Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
109$hookmanager->initHooks(array('productreassortlist'));
110
111if ($user->socid) {
112 $socid = $user->socid;
113}
114$result = restrictedArea($user, 'produit|service', 0, 'product&product');
115$result = restrictedArea($user, 'stock');
116
117$object = new Product($db);
118
119
120/*
121 * Actions
122 */
123
124if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers
125 $sref = "";
126 $snom = "";
127 $sall = "";
128 $tosell = "";
129 $tobuy = "";
130 $search_sale = "";
131 $search_categ = "";
132 $search_toolowstock = '';
133 $fourn_id = '';
134 $sbarcode = '';
135 $search_stock_physique = '';
136}
137
138
139
140/*
141 * View
142 */
143
144$helpurl = 'EN:Module_Stocks_En|FR:Module_Stock|ES:M&oacute;dulo_Stocks';
145
146$form = new Form($db);
147$htmlother = new FormOther($db);
148if (!empty($objp->stock_physique) && $objp->stock_physique < 0) {
149 print '<span class="warning">';
150}
151
152$sql = 'SELECT p.rowid, p.ref, p.label, p.barcode, p.price, p.price_ttc, p.price_base_type, p.entity,';
153$sql .= ' p.fk_product_type, p.tms as datem,';
154$sql .= ' p.duration, p.tosell as statut, p.tobuy, p.seuil_stock_alerte, p.desiredstock,';
155if (getDolGlobalString('PRODUCT_STOCK_LIST_SHOW_WITH_PRECALCULATED_DENORMALIZED_PHYSICAL_STOCK')) {
156 $sql .= ' p.stock as stock_physique';
157} else {
158 $sql .= ' SUM(s.reel) as stock_physique';
159}
160if (getDolGlobalString('PRODUCT_USE_UNITS')) {
161 $sql .= ', u.short_label as unit_short';
162}
163// Add fields from hooks
164$parameters = array();
165$reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object); // Note that $action and $object may have been modified by hook
166$sql .= $hookmanager->resPrint;
167$sql .= ' FROM '.MAIN_DB_PREFIX.'product as p';
168if (!getDolGlobalString('PRODUCT_STOCK_LIST_SHOW_WITH_PRECALCULATED_DENORMALIZED_PHYSICAL_STOCK')) {
169 $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'product_stock as s ON p.rowid = s.fk_product';
170}
171if (getDolGlobalString('PRODUCT_USE_UNITS')) {
172 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_units as u on p.fk_unit = u.rowid';
173}
174// Add table from hooks
175$parameters = array();
176$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object); // Note that $action and $object may have been modified by hook
177$sql .= $hookmanager->resPrint;
178$sql .= " WHERE p.entity IN (".getEntity('product').")";
179if (!empty($search_categ) && $search_categ != '-1') {
180 $sql .= " AND ";
181 if ($search_categ == -2) {
182 $sql .= " NOT EXISTS ";
183 } else {
184 $sql .= " EXISTS ";
185 }
186 $sql .= "(";
187 $sql .= " SELECT cp.fk_categorie, cp.fk_product";
188 $sql .= " FROM " . MAIN_DB_PREFIX . "categorie_product as cp";
189 $sql .= " WHERE cp.fk_product = p.rowid"; // Join for the needed table to filter by categ
190 if ($search_categ > 0) {
191 $sql .= " AND cp.fk_categorie = " . ((int) $search_categ);
192 }
193 $sql .= ")";
194}
195if (!getDolGlobalString('PRODUCT_STOCK_LIST_SHOW_WITH_PRECALCULATED_DENORMALIZED_PHYSICAL_STOCK')) {
196 if (!getDolGlobalString('PRODUCT_STOCK_LIST_SHOW_VIRTUAL_WITH_NO_PHYSICAL')) {
197 $sql .= " AND EXISTS (SELECT e.rowid FROM " . MAIN_DB_PREFIX . "entrepot as e WHERE e.rowid = s.fk_entrepot AND e.entity IN (" . getEntity('stock') . "))";
198 } else {
199 $sql .= " AND
200 (
201 EXISTS
202 (SELECT e.rowid
203 FROM " . MAIN_DB_PREFIX . "entrepot as e
204 WHERE e.rowid = s.fk_entrepot AND e.entity IN (" . getEntity('stock') . "))
205 OR (
206 SELECT SUM(cd1.qty) as qty
207 FROM " . MAIN_DB_PREFIX . "commande_fournisseurdet as cd1
208 LEFT JOIN " . MAIN_DB_PREFIX . "commande_fournisseur as c1
209 ON c1.rowid = cd1.fk_commande
210 WHERE c1.entity IN (1) AND cd1.fk_product = p.rowid AND c1.fk_statut in (3,4) AND cd1.qty <> 0
211 ) IS NOT NULL
212 OR (
213 SELECT SUM(cd2.qty) as qty
214 FROM " . MAIN_DB_PREFIX . "commandedet as cd2
215 LEFT JOIN " . MAIN_DB_PREFIX . "commande as c2 ON c2.rowid = cd2.fk_commande
216 WHERE c2.entity IN (1) AND cd2.fk_product = p.rowid AND c2.fk_statut in (1,2) AND cd2.qty <> 0
217 ) IS NOT NULL
218 OR (
219 SELECT SUM(ed3.qty) as qty
220 FROM " . MAIN_DB_PREFIX . "expeditiondet as ed3
221 LEFT JOIN " . MAIN_DB_PREFIX . "expedition as e3 ON e3.rowid = ed3.fk_expedition
222 LEFT JOIN " . MAIN_DB_PREFIX . "commandedet as cd3 ON ed3.fk_elementdet = cd3.rowid
223 LEFT JOIN " . MAIN_DB_PREFIX . "commande as c3 ON c3.rowid = cd3.fk_commande
224 WHERE e3.entity IN (1) AND cd3.fk_product = p.rowid AND c3.fk_statut IN (1,2) AND e3.fk_statut IN (1,2) AND ed3.qty <> 0
225 ) IS NOT NULL
226 OR (
227 SELECT SUM(mp4.qty) as qty
228 FROM " . MAIN_DB_PREFIX . "mrp_production as mp4
229 LEFT JOIN " . MAIN_DB_PREFIX . "mrp_mo as m4 ON m4.rowid = mp4.fk_mo AND m4.entity IN (1) AND m4.status IN (1,2)
230 WHERE mp4.fk_product = p.rowid AND mp4.qty <> 0
231 ) IS NOT NULL
232 ) ";
233 }
234}
235if ($sall) {
236 $sql .= natural_search(array('p.ref', 'p.label', 'p.description', 'p.note'), $sall);
237}
238// if the type is not 1, we show all products (type = 0,2,3)
239if (dol_strlen((string) $type)) {
240 if ($type == 1) {
241 $sql .= " AND p.fk_product_type = '1'";
242 } else {
243 $sql .= " AND p.fk_product_type <> '1'";
244 }
245}
246if ($sref) {
247 $sql .= natural_search('p.ref', $sref);
248}
249if ($search_barcode) {
250 $sql .= natural_search('p.barcode', $search_barcode);
251}
252if ($snom) {
253 $sql .= natural_search('p.label', $snom);
254}
255if (!empty($tosell)) {
256 $sql .= " AND p.tosell = ".((int) $tosell);
257}
258if (!empty($tobuy)) {
259 $sql .= " AND p.tobuy = ".((int) $tobuy);
260}
261if (!empty($canvas)) {
262 $sql .= " AND p.canvas = '".$db->escape($canvas)."'";
263}
264if ($fourn_id > 0) {
265 $sql .= " AND p.rowid = pf.fk_product AND pf.fk_soc = ".((int) $fourn_id);
266}
267if (getDolGlobalString('PRODUCT_STOCK_LIST_SHOW_WITH_PRECALCULATED_DENORMALIZED_PHYSICAL_STOCK')) {
268 if ($search_toolowstock) {
269 $sql .= " AND p.stock < p.seuil_stock_alerte";
270 }
271 if ($search_stock_physique != '') {
272 $sql .= natural_search('p.stock', $search_stock_physique, 1, 1);
273 }
274}
275// Add where from hooks
276$parameters = array();
277$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object); // Note that $action and $object may have been modified by hook
278$sql .= $hookmanager->resPrint;
279if (!getDolGlobalString('PRODUCT_STOCK_LIST_SHOW_WITH_PRECALCULATED_DENORMALIZED_PHYSICAL_STOCK')) {
280 $sql .= " GROUP BY p.rowid, p.ref, p.label, p.barcode, p.price, p.price_ttc, p.price_base_type, p.entity,";
281 $sql .= " p.fk_product_type, p.tms, p.duration, p.tosell, p.tobuy, p.seuil_stock_alerte, p.desiredstock";
282}
283
284// Add GROUP BY from hooks
285$parameters = array();
286$reshook = $hookmanager->executeHooks('printFieldListGroupBy', $parameters, $object); // Note that $action and $object may have been modified by hook
287$sql .= $hookmanager->resPrint;
288
289$sql_having = '';
290if (!getDolGlobalString('PRODUCT_STOCK_LIST_SHOW_WITH_PRECALCULATED_DENORMALIZED_PHYSICAL_STOCK')) {
291 if ($search_toolowstock) {
292 $sql_having .= " HAVING SUM(" . $db->ifsql('s.reel IS NULL', '0', 's.reel') . ") < p.seuil_stock_alerte";
293 }
294 if ($search_stock_physique != '') {
295 $natural_search_physique = natural_search('__SUM_OF_REEL__', $search_stock_physique, 1, 1);
296 $natural_search_physique = " " . substr(str_replace('__SUM_OF_REEL__', 'SUM(COALESCE(s.reel, 0))', $natural_search_physique), 1, -1); // remove first "(" and last ")" characters
297 if (!empty($sql_having)) {
298 $sql_having .= " AND";
299 } else {
300 $sql_having .= " HAVING";
301 }
302 $sql_having .= $natural_search_physique;
303 }
304}
305
306// Add HAVING from hooks
307$parameters = array();
308$reshook = $hookmanager->executeHooks('printFieldListHaving', $parameters, $object); // Note that $action and $object may have been modified by hook
309if (!empty($hookmanager->resPrint)) {
310 if (!empty($sql_having)) {
311 $sql_having .= " AND";
312 } else {
313 $sql_having .= " HAVING";
314 }
315 $sql_having .= $hookmanager->resPrint;
316}
317
318if (!empty($sql_having)) {
319 $sql .= $sql_having;
320}
321$sql .= $db->order($sortfield, $sortorder);
322
323// Count total nb of records
324$nbtotalofrecords = '';
325if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
326 $result = $db->query($sql);
327 $nbtotalofrecords = $db->num_rows($result);
328 if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller then paging size (filtering), goto and load page 0
329 $page = 0;
330 $offset = 0;
331 }
332}
333
334$sql .= $db->plimit($limit + 1, $offset);
335
336$resql = $db->query($sql);
337if ($resql) {
338 $num = $db->num_rows($resql);
339
340 $i = 0;
341
342 if ($num == 1 && GETPOST('autojumpifoneonly') && ($sall || $snom || $sref)) {
343 $objp = $db->fetch_object($resql);
344 header("Location: card.php?id=$objp->rowid");
345 exit;
346 }
347
348 if (isset($type)) {
349 if ($type == 1) {
350 $texte = $langs->trans("Services");
351 } else {
352 $texte = $langs->trans("Products");
353 }
354 } else {
355 $texte = $langs->trans("ProductsAndServices");
356 }
357 $texte .= ' ('.$langs->trans("MenuStocks").')';
358
359 $param = '';
360 if ($limit > 0 && $limit != $conf->liste_limit) {
361 $param .= '&limit='.((int) $limit);
362 }
363 if ($sall) {
364 $param .= "&sall=".urlencode($sall);
365 }
366 if ($tosell) {
367 $param .= "&tosell=".urlencode($tosell);
368 }
369 if ($tobuy) {
370 $param .= "&tobuy=".urlencode($tobuy);
371 }
372 if ($type != '') {
373 $param .= "&type=".urlencode((string) ($type));
374 }
375 if ($fourn_id) {
376 $param .= "&fourn_id=".urlencode((string) ($fourn_id));
377 }
378 if ($snom) {
379 $param .= "&snom=".urlencode($snom);
380 }
381 if ($sref) {
382 $param .= "&sref=".urlencode($sref);
383 }
384 if ($search_sale) {
385 $param .= "&search_sale=".urlencode($search_sale);
386 }
387 if ($search_categ > 0) {
388 $param .= "&search_categ=".urlencode((string) ($search_categ));
389 }
390 if ($search_toolowstock) {
391 $param .= "&search_toolowstock=".urlencode($search_toolowstock);
392 }
393 if ($sbarcode) {
394 $param .= "&sbarcode=".urlencode((string) ($sbarcode));
395 }
396 if ($search_stock_physique) {
397 $param .= '&search_stock_physique=' . urlencode($search_stock_physique);
398 }
399
400 llxHeader("", $texte, $helpurl, '', 0, 0, '', '', '', 'mod-product page-reassort');
401
402 print '<form action="'.$_SERVER["PHP_SELF"].'" method="post" name="formulaire">';
403 print '<input type="hidden" name="token" value="'.newToken().'">';
404 print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
405 print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
406 print '<input type="hidden" name="page" value="'.$page.'">';
407 print '<input type="hidden" name="type" value="'.$type.'">';
408
409 print_barre_liste($texte, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'product', 0, '', '', $limit);
410
411 if ($search_categ > 0) {
412 print "<div id='ways'>";
413 $c = new Categorie($db);
414 $c->fetch($search_categ);
415 $ways = $c->print_all_ways(' &gt; ', 'product/reassort.php');
416 print " &gt; ".$ways[0]."<br>\n";
417 print "</div><br>";
418 }
419
420 // Filter on categories
421 $moreforfilter = '';
422 if (isModEnabled('category')) {
423 $moreforfilter .= '<div class="divsearchfield">';
424 $moreforfilter .= img_picto($langs->trans('Categories'), 'category', 'class="pictofixedwidth"');
425 $moreforfilter .= $htmlother->select_categories(Categorie::TYPE_PRODUCT, $search_categ, 'search_categ', 1);
426 $moreforfilter .= '</div>';
427 }
428
429 $moreforfilter .= '<div class="divsearchfield">';
430 $moreforfilter .= '<label for="search_toolowstock">'.$langs->trans("StockTooLow").' </label><input type="checkbox" id="search_toolowstock" name="search_toolowstock" value="1"'.($search_toolowstock ? ' checked' : '').'>';
431 $moreforfilter .= '</div>';
432
433 print '<div class="liste_titre liste_titre_bydiv centpercent">';
434 print $moreforfilter;
435 $parameters = array();
436 $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
437 print $hookmanager->resPrint;
438 print '</div>';
439
440 $formProduct = new FormProduct($db);
441 $formProduct->loadWarehouses();
442 $warehouses_list = $formProduct->cache_warehouses;
443 $nb_warehouse = count($warehouses_list);
444 $colspan_warehouse = 1;
445 $colspan = 0;
446 if (getDolGlobalString('STOCK_DETAIL_ON_WAREHOUSE')) {
447 $colspan_warehouse = $nb_warehouse > 1 ? $nb_warehouse + 1 : 1;
448 }
449
450 print '<div class="div-table-responsive">';
451 print '<table class="tagtable liste'.($moreforfilter ? " listwithfilterbefore" : "").'">';
452
453 // Fields title search
454 print '<tr class="liste_titre_filter">';
455 // Action column
456 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
457 print '<td class="liste_titre maxwidthsearch">';
458 $searchpicto = $form->showFilterAndCheckAddButtons(0);
459 print $searchpicto;
460 print '</td>';
461 $colspan++;
462 }
463 print '<td class="liste_titre">';
464 print '<input class="flat" type="text" name="sref" size="6" value="'.$sref.'">';
465 print '</td>';
466 $colspan++;
467 print '<td class="liste_titre">';
468 print '<input class="flat" type="text" name="snom" size="8" value="'.$snom.'">';
469 print '</td>';
470 $colspan++;
471 // Duration
472 if (isModEnabled("service") && $type == 1) {
473 print '<td class="liste_titre">';
474 print '&nbsp;';
475 print '</td>';
476 $colspan++;
477 }
478 // Stock limit
479 print '<td class="liste_titre">&nbsp;</td>';
480 $colspan++;
481 print '<td class="liste_titre right">&nbsp;</td>';
482 $colspan++;
483 // Physical stock
484 print '<td class="liste_titre right">';
485 print '<input class="flat" type="text" size="5" name="search_stock_physique" value="'.dol_escape_htmltag($search_stock_physique).'">';
486 print '</td>';
487 $colspan++;
488 if ($virtualdiffersfromphysical) {
489 print '<td class="liste_titre">&nbsp;</td>';
490 $colspan++;
491 }
492 if (getDolGlobalString('PRODUCT_USE_UNITS')) {
493 print '<td class="liste_titre"></td>';
494 $colspan++;
495 }
496 $parameters = array();
497 $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters); // Note that $action and $object may have been modified by hook
498 print $hookmanager->resPrint;
499 print '<td class="liste_titre">&nbsp;</td>';
500 $colspan++;
501 print '<td class="liste_titre" colspan="'.$colspan_warehouse.'">&nbsp;</td>';
502 $colspan++;
503 print '<td class="liste_titre"></td>';
504 $colspan++;
505 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
506 print '<td class="liste_titre maxwidthsearch">';
507 $searchpicto = $form->showFilterAndCheckAddButtons(0);
508 print $searchpicto;
509 print '</td>';
510 $colspan++;
511 }
512 print '</tr>';
513
514 // Line for column titles
515 print '<tr class="liste_titre">';
516 // Action column
517 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
519 }
520 print_liste_field_titre("Ref", $_SERVER["PHP_SELF"], "p.ref", '', $param, "", $sortfield, $sortorder);
521 print_liste_field_titre("Label", $_SERVER["PHP_SELF"], "p.label", '', $param, "", $sortfield, $sortorder);
522 if (isModEnabled("service") && $type == 1) {
523 print_liste_field_titre("Duration", $_SERVER["PHP_SELF"], "p.duration", '', $param, "", $sortfield, $sortorder, 'center ');
524 }
525 print_liste_field_titre("StockLimit", $_SERVER["PHP_SELF"], "p.seuil_stock_alerte", '', $param, "", $sortfield, $sortorder, 'right ');
526 print_liste_field_titre("DesiredStock", $_SERVER["PHP_SELF"], "p.desiredstock", '', $param, "", $sortfield, $sortorder, 'right ');
527 print_liste_field_titre("PhysicalStock", $_SERVER["PHP_SELF"], "stock_physique", '', $param, "", $sortfield, $sortorder, 'right ');
528 // Details per warehouse
529 if (getDolGlobalString('STOCK_DETAIL_ON_WAREHOUSE')) { // TODO This should be moved into the selection of fields on page product/list (page product/stock will be removed and replaced with product/list with its own context)
530 if ($nb_warehouse > 1) {
531 foreach ($warehouses_list as &$wh) {
532 print_liste_field_titre($wh['label'], '', '', '', '', '', '', '', 'right ');
533 }
534 }
535 }
536 if ($virtualdiffersfromphysical) {
537 print_liste_field_titre("VirtualStock", $_SERVER["PHP_SELF"], "", '', $param, "", $sortfield, $sortorder, 'right ', 'VirtualStockDesc');
538 }
539 // Units
540 if (getDolGlobalString('PRODUCT_USE_UNITS')) {
541 print_liste_field_titre("Unit", $_SERVER["PHP_SELF"], "unit_short", '', $param, 'align="right"', $sortfield, $sortorder);
542 }
543 // Hook fields
544 $parameters = array('param' => $param, 'sortfield' => $sortfield, 'sortorder' => $sortorder);
545 $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters); // Note that $action and $object may have been modified by hook
546 print $hookmanager->resPrint;
548 print_liste_field_titre("ProductStatusOnSell", $_SERVER["PHP_SELF"], "p.tosell", '', $param, "", $sortfield, $sortorder, 'right ');
549 print_liste_field_titre("ProductStatusOnBuy", $_SERVER["PHP_SELF"], "p.tobuy", '', $param, "", $sortfield, $sortorder, 'right ');
550 // Action column
551 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
553 }
554 print "</tr>\n";
555
556 while ($i < min($num, $limit)) {
557 $objp = $db->fetch_object($resql);
558
559 $product = new Product($db);
560 $product->fetch($objp->rowid);
561 $product->load_stock();
562
563 print '<tr>';
564 // Action column
565 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
566 print '<td></td>';
567 }
568 print '<td class="tdoverflowmax250">';
569 print $product->getNomUrl(1);
570 //if ($objp->stock_theorique < $objp->seuil_stock_alerte) print ' '.img_warning($langs->trans("StockTooLow"));
571 print '</td>';
572 print '<td class="tdoverflowmax150" title="'.dol_escape_htmltag($product->label).'">'.dol_escape_htmltag($product->label).'</td>';
573
574 if (isModEnabled("service") && $type == 1) {
575 print '<td class="center">';
576 $regs = array();
577 if (preg_match('/([0-9]+)y/i', $objp->duration, $regs)) {
578 print $regs[1].' '.$langs->trans("DurationYear");
579 } elseif (preg_match('/([0-9]+)m/i', $objp->duration, $regs)) {
580 print $regs[1].' '.$langs->trans("DurationMonth");
581 } elseif (preg_match('/([0-9]+)d/i', $objp->duration, $regs)) {
582 print $regs[1].' '.$langs->trans("DurationDay");
583 } else {
584 print $objp->duration;
585 }
586 print '</td>';
587 }
588 //print '<td class="right">'.$objp->stock_theorique.'</td>';
589 print '<td class="right">';
590 print $objp->seuil_stock_alerte;
591 print '</td>';
592 print '<td class="right">';
593 print $objp->desiredstock;
594 print '</td>';
595 // Real stock
596 print '<td class="right">';
597 if ($objp->seuil_stock_alerte != '' && ($objp->stock_physique < $objp->seuil_stock_alerte)) {
598 print img_warning($langs->trans("StockLowerThanLimit", $objp->seuil_stock_alerte)).' ';
599 }
600 if ($objp->stock_physique < 0) {
601 print '<span class="warning">';
602 }
603 print price(price2num($objp->stock_physique, 'MS'), 0, $langs, 1, 0);
604 if ($objp->stock_physique < 0) {
605 print '</span>';
606 }
607 print '</td>';
608
609 // Details per warehouse
610 if (getDolGlobalString('STOCK_DETAIL_ON_WAREHOUSE')) { // TODO This should be moved into the selection of fields on page product/list (page product/stock will be removed and replaced with product/list with its own context)
611 if ($nb_warehouse > 1) {
612 foreach ($warehouses_list as &$wh) {
613 print '<td class="right">';
614 print price(empty($product->stock_warehouse[$wh['id']]->real) ? 0 : price2num($product->stock_warehouse[$wh['id']]->real, 'MS'), 0, $langs, 1, 0);
615 print '</td>';
616 }
617 }
618 }
619
620 // Virtual stock
621 if ($virtualdiffersfromphysical) {
622 print '<td class="right">';
623 if ($objp->seuil_stock_alerte != '' && ($product->stock_theorique < (float) $objp->seuil_stock_alerte)) {
624 print img_warning($langs->trans("StockLowerThanLimit", $objp->seuil_stock_alerte)).' ';
625 }
626 if ($objp->stock_physique < 0) {
627 print '<span class="warning">';
628 }
629 print price(price2num($product->stock_theorique, 'MS'), 0, $langs, 1, 0);
630 if ($objp->stock_physique < 0) {
631 print '</span>';
632 }
633 print '</td>';
634 }
635 // Units
636 if (getDolGlobalString('PRODUCT_USE_UNITS')) {
637 print '<td class="left">'.dol_escape_htmltag($objp->unit_short).'</td>';
638 }
639 // Fields from hook
640 $parameters = array('obj' => $objp);
641 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $product); // Note that $action and $object may have been modified by hook
642 print $hookmanager->resPrint;
643 print '<td class="center nowraponall">';
644 print img_picto($langs->trans("StockMovement"), 'movement', 'class="pictofixedwidth"');
645 print '<a href="'.DOL_URL_ROOT.'/product/stock/movement_list.php?idproduct='.$product->id.'">'.$langs->trans("Movements").'</a>';
646 print '</td>';
647 print '<td class="right nowrap">'.$product->LibStatut($objp->statut, 5, 0).'</td>';
648 print '<td class="right nowrap">'.$product->LibStatut($objp->tobuy, 5, 1).'</td>';
649 // Action column
650 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
651 print '<td></td>';
652 }
653
654 print "</tr>\n";
655 $i++;
656 }
657 if ($num == 0) {
658 print '<tr><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
659 }
660
661 print "</table>";
662 print '</div>';
663
664 print '</form>';
665
666 $db->free($resql);
667} else {
668 dol_print_error($db);
669}
670
671// End of page
672llxFooter();
673$db->close();
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:67
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
$c
Definition line.php:331
Class to manage canvas.
Class to manage categories.
Class to manage generation of HTML components Only common components must be here.
Class permettant la generation de composants html autre Only common components are here.
Class with static methods for building HTML components related to products Only components common to ...
Class to manage products or services.
print_liste_field_titre($name, $file="", $field="", $begin="", $param="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $tooltip="", $forcenowrapcolumntitle=0)
Show title line of an array.
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.
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
natural_search($fields, $value, $mode=0, $nofirstand=0)
Generate natural SQL search string for a criteria (this criteria can be tested on one or several fiel...
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
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.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
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.
getEntity($element, $shared=1, $currentobject=null)
Get list of entity id to use.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
Definition member.php:79
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.