dolibarr 19.0.3
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 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 */
23
30// Load Dolibarr environment
31require '../main.inc.php';
32require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
33require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
34require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
35require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
36
37// Load translation files required by the page
38$langs->loadLangs(array('products', 'stocks'));
39
40$action = GETPOST('action', 'aZ09');
41$sref = GETPOST("sref", 'alpha');
42$snom = GETPOST("snom", 'alpha');
43$sall = trim((GETPOST('search_all', 'alphanohtml') != '') ? GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml'));
44$type = GETPOSTISSET('type') ? GETPOST('type', 'int') : Product::TYPE_PRODUCT;
45$search_barcode = GETPOST("search_barcode", 'alpha');
46$search_toolowstock = GETPOST('search_toolowstock');
47$tosell = GETPOST("tosell");
48$tobuy = GETPOST("tobuy");
49$fourn_id = GETPOST("fourn_id", 'int');
50$sbarcode = GETPOST("sbarcode", 'int');
51$search_stock_physique = GETPOST('search_stock_physique', 'alpha');
52
53$sortfield = GETPOST('sortfield', 'aZ09comma');
54$sortorder = GETPOST('sortorder', 'aZ09comma');
55$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int');
56if (empty($page) || $page < 0) {
57 $page = 0;
58}
59if (!$sortfield) {
60 $sortfield = "p.ref";
61}
62if (!$sortorder) {
63 $sortorder = "ASC";
64}
65$limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit;
66if (empty($page) || $page == -1) {
67 $page = 0;
68} // If $page is not defined, or '' or -1
69$offset = $limit * $page;
70
71// Load sale and categ filters
72$search_sale = GETPOST("search_sale");
73if (GETPOSTISSET('catid')) {
74 $search_categ = GETPOST('catid', 'int');
75} else {
76 $search_categ = GETPOST('search_categ', 'int');
77}
78
79// Get object canvas (By default, this is not defined, so standard usage of dolibarr)
80$canvas = GETPOST("canvas");
81$objcanvas = null;
82if (!empty($canvas)) {
83 require_once DOL_DOCUMENT_ROOT.'/core/class/canvas.class.php';
84 $objcanvas = new Canvas($db, $action);
85 $objcanvas->getCanvas('product', 'list', $canvas);
86}
87
88// Define virtualdiffersfromphysical
89$virtualdiffersfromphysical = 0;
90if (getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT')
91 || getDolGlobalString('STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER')
92 || getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT_CLOSE')
93 || getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION')
94 || getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION_CLOSE')
95 || isModEnabled('mrp')) {
96 $virtualdiffersfromphysical = 1; // According to increase/decrease stock options, virtual and physical stock may differs.
97}
98
99// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
100$hookmanager->initHooks(array('productreassortlist'));
101
102if ($user->socid) {
103 $socid = $user->socid;
104}
105$result = restrictedArea($user, 'produit|service', 0, 'product&product');
106
107$object = new Product($db);
108
109/*
110 * Actions
111 */
112
113if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers
114 $sref = "";
115 $snom = "";
116 $sall = "";
117 $tosell = "";
118 $tobuy = "";
119 $search_sale = "";
120 $search_categ = "";
121 $search_toolowstock = '';
122 $fourn_id = '';
123 $sbarcode = '';
124 $search_stock_physique = '';
125}
126
127
128
129/*
130 * View
131 */
132
133$helpurl = 'EN:Module_Stocks_En|FR:Module_Stock|ES:M&oacute;dulo_Stocks';
134
135$form = new Form($db);
136$htmlother = new FormOther($db);
137if (!empty($objp->stock_physique) && $objp->stock_physique < 0) {
138 print '<span class="warning">';
139}
140
141$sql = 'SELECT p.rowid, p.ref, p.label, p.barcode, p.price, p.price_ttc, p.price_base_type, p.entity,';
142$sql .= ' p.fk_product_type, p.tms as datem,';
143$sql .= ' p.duration, p.tosell as statut, p.tobuy, p.seuil_stock_alerte, p.desiredstock,';
144$sql .= ' SUM(s.reel) as stock_physique';
145if (getDolGlobalString('PRODUCT_USE_UNITS')) {
146 $sql .= ', u.short_label as unit_short';
147}
148// Add fields from hooks
149$parameters = array();
150$reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object); // Note that $action and $object may have been modified by hook
151$sql .= $hookmanager->resPrint;
152$sql .= ' FROM '.MAIN_DB_PREFIX.'product as p';
153$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_stock as s ON p.rowid = s.fk_product';
154if (getDolGlobalString('PRODUCT_USE_UNITS')) {
155 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_units as u on p.fk_unit = u.rowid';
156}
157// Add table from hooks
158$parameters = array();
159$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object); // Note that $action and $object may have been modified by hook
160$sql .= $hookmanager->resPrint;
161$sql .= " WHERE p.entity IN (".getEntity('product').")";
162if (!empty($search_categ) && $search_categ != '-1') {
163 $sql .= " AND ";
164 if ($search_categ == -2) {
165 $sql .= " NOT EXISTS ";
166 } else {
167 $sql .= " EXISTS ";
168 }
169 $sql .= "(";
170 $sql .= " SELECT cp.fk_categorie, cp.fk_product";
171 $sql .= " FROM " . MAIN_DB_PREFIX . "categorie_product as cp";
172 $sql .= " WHERE cp.fk_product = p.rowid"; // Join for the needed table to filter by categ
173 if ($search_categ > 0) {
174 $sql .= " AND cp.fk_categorie = " . ((int) $search_categ);
175 }
176 $sql .= ")";
177}
178if (!getDolGlobalString('PRODUCT_STOCK_LIST_SHOW_VIRTUAL_WITH_NO_PHYSICAL')) {
179 $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')."))";
180} else {
181 $sql .= " AND
182 (
183 EXISTS
184 (SELECT e.rowid
185 FROM ".MAIN_DB_PREFIX."entrepot as e
186 WHERE e.rowid = s.fk_entrepot AND e.entity IN (".getEntity('stock')."))
187 OR (
188 SELECT SUM(cd1.qty) as qty
189 FROM ".MAIN_DB_PREFIX."commande_fournisseurdet as cd1
190 LEFT JOIN ".MAIN_DB_PREFIX."commande_fournisseur as c1
191 ON c1.rowid = cd1.fk_commande
192 WHERE c1.entity IN (1) AND cd1.fk_product = p.rowid AND c1.fk_statut in (3,4) AND cd1.qty <> 0
193 ) IS NOT NULL
194 OR (
195 SELECT SUM(cd2.qty) as qty
196 FROM ".MAIN_DB_PREFIX."commandedet as cd2
197 LEFT JOIN ".MAIN_DB_PREFIX."commande as c2 ON c2.rowid = cd2.fk_commande
198 WHERE c2.entity IN (1) AND cd2.fk_product = p.rowid AND c2.fk_statut in (1,2) AND cd2.qty <> 0
199 ) IS NOT NULL
200 OR (
201 SELECT SUM(ed3.qty) as qty
202 FROM ".MAIN_DB_PREFIX."expeditiondet as ed3
203 LEFT JOIN ".MAIN_DB_PREFIX."expedition as e3 ON e3.rowid = ed3.fk_expedition
204 LEFT JOIN ".MAIN_DB_PREFIX."commandedet as cd3 ON ed3.fk_origin_line = cd3.rowid
205 LEFT JOIN ".MAIN_DB_PREFIX."commande as c3 ON c3.rowid = cd3.fk_commande
206 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
207 ) IS NOT NULL
208 OR (
209 SELECT SUM(mp4.qty) as qty
210 FROM ".MAIN_DB_PREFIX."mrp_production as mp4
211 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)
212 WHERE mp4.fk_product = p.rowid AND mp4.qty <> 0
213 ) IS NOT NULL
214 ) ";
215}
216if ($sall) {
217 $sql .= natural_search(array('p.ref', 'p.label', 'p.description', 'p.note'), $sall);
218}
219// if the type is not 1, we show all products (type = 0,2,3)
220if (dol_strlen($type)) {
221 if ($type == 1) {
222 $sql .= " AND p.fk_product_type = '1'";
223 } else {
224 $sql .= " AND p.fk_product_type <> '1'";
225 }
226}
227if ($sref) {
228 $sql .= natural_search('p.ref', $sref);
229}
230if ($search_barcode) {
231 $sql .= natural_search('p.barcode', $search_barcode);
232}
233if ($snom) {
234 $sql .= natural_search('p.label', $snom);
235}
236if (!empty($tosell)) {
237 $sql .= " AND p.tosell = ".((int) $tosell);
238}
239if (!empty($tobuy)) {
240 $sql .= " AND p.tobuy = ".((int) $tobuy);
241}
242if (!empty($canvas)) {
243 $sql .= " AND p.canvas = '".$db->escape($canvas)."'";
244}
245if ($fourn_id > 0) {
246 $sql .= " AND p.rowid = pf.fk_product AND pf.fk_soc = ".((int) $fourn_id);
247}
248// Add where from hooks
249$parameters = array();
250$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object); // Note that $action and $object may have been modified by hook
251$sql .= $hookmanager->resPrint;
252$sql .= " GROUP BY p.rowid, p.ref, p.label, p.barcode, p.price, p.price_ttc, p.price_base_type, p.entity,";
253$sql .= " p.fk_product_type, p.tms, p.duration, p.tosell, p.tobuy, p.seuil_stock_alerte, p.desiredstock";
254
255// Add GROUP BY from hooks
256$parameters = array();
257$reshook = $hookmanager->executeHooks('printFieldListGroupBy', $parameters, $object); // Note that $action and $object may have been modified by hook
258$sql .= $hookmanager->resPrint;
259
260$sql_having = '';
261if ($search_toolowstock) {
262 $sql_having .= " HAVING SUM(".$db->ifsql('s.reel IS NULL', '0', 's.reel').") < p.seuil_stock_alerte";
263}
264if ($search_stock_physique != '') {
265 //$natural_search_physique = natural_search('HAVING SUM(' . $db->ifsql('s.reel IS NULL', '0', 's.reel') . ')', $search_stock_physique, 1, 1);
266 $natural_search_physique = natural_search('SUM(' . $db->ifsql('s.reel IS NULL', '0', 's.reel') . ')', $search_stock_physique, 1, 1);
267 $natural_search_physique = " " . substr($natural_search_physique, 1, -1); // remove first "(" and last ")" characters
268 if (!empty($sql_having)) {
269 $sql_having .= " AND";
270 } else {
271 $sql_having .= " HAVING";
272 }
273 $sql_having .= $natural_search_physique;
274}
275
276// Add HAVING from hooks
277$parameters = array();
278$reshook = $hookmanager->executeHooks('printFieldListHaving', $parameters, $object); // Note that $action and $object may have been modified by hook
279if (!empty($hookmanager->resPrint)) {
280 if (!empty($sql_having)) {
281 $sql_having .= " AND";
282 } else {
283 $sql_having .= " HAVING";
284 }
285 $sql_having .= $hookmanager->resPrint;
286}
287
288if (!empty($sql_having)) {
289 $sql .= $sql_having;
290}
291$sql .= $db->order($sortfield, $sortorder);
292
293// Count total nb of records
294$nbtotalofrecords = '';
295if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
296 $result = $db->query($sql);
297 $nbtotalofrecords = $db->num_rows($result);
298 if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller then paging size (filtering), goto and load page 0
299 $page = 0;
300 $offset = 0;
301 }
302}
303
304$sql .= $db->plimit($limit + 1, $offset);
305
306$resql = $db->query($sql);
307if ($resql) {
308 $num = $db->num_rows($resql);
309
310 $i = 0;
311
312 if ($num == 1 && GETPOST('autojumpifoneonly') && ($sall || $snom || $sref)) {
313 $objp = $db->fetch_object($resql);
314 header("Location: card.php?id=$objp->rowid");
315 exit;
316 }
317
318 if (isset($type)) {
319 if ($type == 1) {
320 $texte = $langs->trans("Services");
321 } else {
322 $texte = $langs->trans("Products");
323 }
324 } else {
325 $texte = $langs->trans("ProductsAndServices");
326 }
327 $texte .= ' ('.$langs->trans("MenuStocks").')';
328
329 $param = '';
330 if ($limit > 0 && $limit != $conf->liste_limit) {
331 $param .= '&limit='.((int) $limit);
332 }
333 if ($sall) {
334 $param .= "&sall=".urlencode($sall);
335 }
336 if ($tosell) {
337 $param .= "&tosell=".urlencode($tosell);
338 }
339 if ($tobuy) {
340 $param .= "&tobuy=".urlencode($tobuy);
341 }
342 if ($type != '') {
343 $param .= "&type=".urlencode($type);
344 }
345 if ($fourn_id) {
346 $param .= "&fourn_id=".urlencode($fourn_id);
347 }
348 if ($snom) {
349 $param .= "&snom=".urlencode($snom);
350 }
351 if ($sref) {
352 $param .= "&sref=".urlencode($sref);
353 }
354 if ($search_sale) {
355 $param .= "&search_sale=".urlencode($search_sale);
356 }
357 if ($search_categ > 0) {
358 $param .= "&search_categ=".urlencode($search_categ);
359 }
360 if ($search_toolowstock) {
361 $param .= "&search_toolowstock=".urlencode($search_toolowstock);
362 }
363 if ($sbarcode) {
364 $param .= "&sbarcode=".urlencode($sbarcode);
365 }
366 if ($search_stock_physique) {
367 $param .= '&search_stock_physique=' . urlencode($search_stock_physique);
368 }
369
370 llxHeader("", $texte, $helpurl);
371
372 print '<form action="'.$_SERVER["PHP_SELF"].'" method="post" name="formulaire">';
373 print '<input type="hidden" name="token" value="'.newToken().'">';
374 print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
375 print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
376 print '<input type="hidden" name="page" value="'.$page.'">';
377 print '<input type="hidden" name="type" value="'.$type.'">';
378
379 print_barre_liste($texte, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'product', 0, '', '', $limit);
380
381 if ($search_categ > 0) {
382 print "<div id='ways'>";
383 $c = new Categorie($db);
384 $c->fetch($search_categ);
385 $ways = $c->print_all_ways(' &gt; ', 'product/reassort.php');
386 print " &gt; ".$ways[0]."<br>\n";
387 print "</div><br>";
388 }
389
390 // Filter on categories
391 $moreforfilter = '';
392 if (isModEnabled('categorie')) {
393 $moreforfilter .= '<div class="divsearchfield">';
394 $moreforfilter .= img_picto($langs->trans('Categories'), 'category', 'class="pictofixedwidth"');
395 $moreforfilter .= $htmlother->select_categories(Categorie::TYPE_PRODUCT, $search_categ, 'search_categ', 1);
396 $moreforfilter .= '</div>';
397 }
398
399 $moreforfilter .= '<div class="divsearchfield">';
400 $moreforfilter .= '<label for="search_toolowstock">'.$langs->trans("StockTooLow").' </label><input type="checkbox" id="search_toolowstock" name="search_toolowstock" value="1"'.($search_toolowstock ? ' checked' : '').'>';
401 $moreforfilter .= '</div>';
402
403 if (!empty($moreforfilter)) {
404 print '<div class="liste_titre liste_titre_bydiv centpercent">';
405 print $moreforfilter;
406 $parameters = array();
407 $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters); // Note that $action and $object may have been modified by hook
408 print $hookmanager->resPrint;
409 print '</div>';
410 }
411
412 $formProduct = new FormProduct($db);
413 $formProduct->loadWarehouses();
414 $warehouses_list = $formProduct->cache_warehouses;
415 $nb_warehouse = count($warehouses_list);
416 $colspan_warehouse = 1;
417 if (getDolGlobalString('STOCK_DETAIL_ON_WAREHOUSE')) {
418 $colspan_warehouse = $nb_warehouse > 1 ? $nb_warehouse + 1 : 1;
419 }
420
421 print '<div class="div-table-responsive">';
422 print '<table class="tagtable liste'.($moreforfilter ? " listwithfilterbefore" : "").'">';
423
424 // Fields title search
425 print '<tr class="liste_titre_filter">';
426 // Action column
427 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
428 print '<td class="liste_titre maxwidthsearch">';
429 $searchpicto = $form->showFilterAndCheckAddButtons(0);
430 print $searchpicto;
431 print '</td>';
432 }
433 print '<td class="liste_titre">';
434 print '<input class="flat" type="text" name="sref" size="6" value="'.$sref.'">';
435 print '</td>';
436 print '<td class="liste_titre">';
437 print '<input class="flat" type="text" name="snom" size="8" value="'.$snom.'">';
438 print '</td>';
439 // Duration
440 if (isModEnabled("service") && $type == 1) {
441 print '<td class="liste_titre">';
442 print '&nbsp;';
443 print '</td>';
444 }
445 // Stock limit
446 print '<td class="liste_titre">&nbsp;</td>';
447 print '<td class="liste_titre right">&nbsp;</td>';
448 // Physical stock
449 print '<td class="liste_titre right">';
450 print '<input class="flat" type="text" size="5" name="search_stock_physique" value="'.dol_escape_htmltag($search_stock_physique).'">';
451 print '</td>';
452 if ($virtualdiffersfromphysical) {
453 print '<td class="liste_titre">&nbsp;</td>';
454 }
455 print '<td class="liste_titre">&nbsp;</td>';
456 print '<td class="liste_titre" colspan="'.$colspan_warehouse.'">&nbsp;</td>';
457 print '<td class="liste_titre"></td>';
458 $parameters = array();
459 $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters); // Note that $action and $object may have been modified by hook
460 print $hookmanager->resPrint;
461 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
462 print '<td class="liste_titre maxwidthsearch">';
463 $searchpicto = $form->showFilterAndCheckAddButtons(0);
464 print $searchpicto;
465 print '</td>';
466 }
467 print '</tr>';
468
469 // Line for column titles
470 print '<tr class="liste_titre">';
471 // Action column
472 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
474 }
475 print_liste_field_titre("Ref", $_SERVER["PHP_SELF"], "p.ref", '', $param, "", $sortfield, $sortorder);
476 print_liste_field_titre("Label", $_SERVER["PHP_SELF"], "p.label", '', $param, "", $sortfield, $sortorder);
477 if (isModEnabled("service") && $type == 1) {
478 print_liste_field_titre("Duration", $_SERVER["PHP_SELF"], "p.duration", '', $param, "", $sortfield, $sortorder, 'center ');
479 }
480 print_liste_field_titre("StockLimit", $_SERVER["PHP_SELF"], "p.seuil_stock_alerte", '', $param, "", $sortfield, $sortorder, 'right ');
481 print_liste_field_titre("DesiredStock", $_SERVER["PHP_SELF"], "p.desiredstock", '', $param, "", $sortfield, $sortorder, 'right ');
482 print_liste_field_titre("PhysicalStock", $_SERVER["PHP_SELF"], "stock_physique", '', $param, "", $sortfield, $sortorder, 'right ');
483 // Details per warehouse
484 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)
485 if ($nb_warehouse > 1) {
486 foreach ($warehouses_list as &$wh) {
487 print_liste_field_titre($wh['label'], '', '', '', '', '', '', '', 'right ');
488 }
489 }
490 }
491 if ($virtualdiffersfromphysical) {
492 print_liste_field_titre("VirtualStock", $_SERVER["PHP_SELF"], "", '', $param, "", $sortfield, $sortorder, 'right ', 'VirtualStockDesc');
493 }
494 // Units
495 if (getDolGlobalString('PRODUCT_USE_UNITS')) {
496 print_liste_field_titre("Unit", $_SERVER["PHP_SELF"], "unit_short", '', $param, 'align="right"', $sortfield, $sortorder);
497 }
499 print_liste_field_titre("ProductStatusOnSell", $_SERVER["PHP_SELF"], "p.tosell", '', $param, "", $sortfield, $sortorder, 'right ');
500 print_liste_field_titre("ProductStatusOnBuy", $_SERVER["PHP_SELF"], "p.tobuy", '', $param, "", $sortfield, $sortorder, 'right ');
501 // Hook fields
502 $parameters = array('param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder);
503 $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters); // Note that $action and $object may have been modified by hook
504 print $hookmanager->resPrint;
505 // Action column
506 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
508 }
509 print "</tr>\n";
510
511 while ($i < min($num, $limit)) {
512 $objp = $db->fetch_object($resql);
513
514 $product = new Product($db);
515 $product->fetch($objp->rowid);
516 $product->load_stock();
517
518 print '<tr>';
519 // Action column
520 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
521 print '<td></td>';
522 }
523 print '<td class="nowrap">';
524 print $product->getNomUrl(1, '', 16);
525 //if ($objp->stock_theorique < $objp->seuil_stock_alerte) print ' '.img_warning($langs->trans("StockTooLow"));
526 print '</td>';
527 print '<td class="tdoverflowmax150" title="'.dol_escape_htmltag($product->label).'">'.dol_escape_htmltag($product->label).'</td>';
528
529 if (isModEnabled("service") && $type == 1) {
530 print '<td class="center">';
531 if (preg_match('/([0-9]+)y/i', $objp->duration, $regs)) {
532 print $regs[1].' '.$langs->trans("DurationYear");
533 } elseif (preg_match('/([0-9]+)m/i', $objp->duration, $regs)) {
534 print $regs[1].' '.$langs->trans("DurationMonth");
535 } elseif (preg_match('/([0-9]+)d/i', $objp->duration, $regs)) {
536 print $regs[1].' '.$langs->trans("DurationDay");
537 } else {
538 print $objp->duration;
539 }
540 print '</td>';
541 }
542 //print '<td class="right">'.$objp->stock_theorique.'</td>';
543 print '<td class="right">';
544 print $objp->seuil_stock_alerte;
545 print '</td>';
546 print '<td class="right">';
547 print $objp->desiredstock;
548 print '</td>';
549 // Real stock
550 print '<td class="right">';
551 if ($objp->seuil_stock_alerte != '' && ($objp->stock_physique < $objp->seuil_stock_alerte)) {
552 print img_warning($langs->trans("StockLowerThanLimit", $objp->seuil_stock_alerte)).' ';
553 }
554 if ($objp->stock_physique < 0) {
555 print '<span class="warning">';
556 }
557 print price(price2num($objp->stock_physique, 'MS'), 0, $langs, 1, 0);
558 if ($objp->stock_physique < 0) {
559 print '</span>';
560 }
561 print '</td>';
562
563 // Details per warehouse
564 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)
565 if ($nb_warehouse > 1) {
566 foreach ($warehouses_list as &$wh) {
567 print '<td class="right">';
568 print price(empty($product->stock_warehouse[$wh['id']]->real) ? 0 : price2num($product->stock_warehouse[$wh['id']]->real, 'MS'), 0, $langs, 1, 0);
569 print '</td>';
570 }
571 }
572 }
573
574 // Virtual stock
575 if ($virtualdiffersfromphysical) {
576 print '<td class="right">';
577 if ($objp->seuil_stock_alerte != '' && ($product->stock_theorique < (float) $objp->seuil_stock_alerte)) {
578 print img_warning($langs->trans("StockLowerThanLimit", $objp->seuil_stock_alerte)).' ';
579 }
580 if ($objp->stock_physique < 0) {
581 print '<span class="warning">';
582 }
583 print price(price2num($product->stock_theorique, 'MS'), 0, $langs, 1, 0);
584 if ($objp->stock_physique < 0) {
585 print '</span>';
586 }
587 print '</td>';
588 }
589 // Units
590 if (getDolGlobalString('PRODUCT_USE_UNITS')) {
591 print '<td class="left">'.dol_escape_htmltag($objp->unit_short).'</td>';
592 }
593 print '<td class="center nowraponall">';
594 print img_picto($langs->trans("StockMovement"), 'movement', 'class="pictofixedwidth"');
595 print '<a href="'.DOL_URL_ROOT.'/product/stock/movement_list.php?idproduct='.$product->id.'">'.$langs->trans("Movements").'</a>';
596 print '</td>';
597 print '<td class="right nowrap">'.$product->LibStatut($objp->statut, 5, 0).'</td>';
598 print '<td class="right nowrap">'.$product->LibStatut($objp->tobuy, 5, 1).'</td>';
599 // Fields from hook
600 $parameters = array('obj'=>$objp);
601 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $product); // Note that $action and $object may have been modified by hook
602 print $hookmanager->resPrint;
603 // Action column
604 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
605 print '<td></td>';
606 }
607
608 print "</tr>\n";
609 $i++;
610 }
611
612 print "</table>";
613 print '</div>';
614
615 print '</form>';
616
617 $db->free($resql);
618} else {
619 dol_print_error($db);
620}
621
622// End of page
623llxFooter();
624$db->close();
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader()
Empty header.
Definition wrapper.php:55
llxFooter()
Empty footer.
Definition wrapper.php:69
Class to manage canvas.
Class to manage categories.
Class to manage generation of HTML components Only common components must be here.
Classe 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.
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
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.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
print_liste_field_titre($name, $file="", $field="", $begin="", $moreparam="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $tooltip="", $forcenowrapcolumntitle=0)
Show title line of an array.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
print_barre_liste($titre, $page, $file, $options='', $sortfield='', $sortorder='', $morehtmlcenter='', $num=-1, $totalnboflines='', $picto='generic', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limit=-1, $hideselectlimit=0, $hidenavigation=0, $pagenavastextinput=0, $morehtmlrightbeforearrow='')
Print a title with navigation controls for pagination.
getDolGlobalString($key, $default='')
Return 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...
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.