dolibarr  19.0.0-dev
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
31 require '../main.inc.php';
32 require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
33 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
34 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
35 require_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');
56 if (empty($page) || $page < 0) {
57  $page = 0;
58 }
59 if (!$sortfield) {
60  $sortfield = "p.ref";
61 }
62 if (!$sortorder) {
63  $sortorder = "ASC";
64 }
65 $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit;
66 if (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");
73 if (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;
82 if (!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;
90 if (!empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT)
91  || !empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER)
92  || !empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE)
93  || !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION)
94  || !empty($conf->global->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 
102 if ($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 
113 if (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);
137 if (!empty($objp->stock_physique) && $objp->stock_physique < 0) { print '<span class="warning">'; }
138 
139 $sql = 'SELECT p.rowid, p.ref, p.label, p.barcode, p.price, p.price_ttc, p.price_base_type, p.entity,';
140 $sql .= ' p.fk_product_type, p.tms as datem,';
141 $sql .= ' p.duration, p.tosell as statut, p.tobuy, p.seuil_stock_alerte, p.desiredstock,';
142 $sql .= ' SUM(s.reel) as stock_physique';
143 if (!empty($conf->global->PRODUCT_USE_UNITS)) {
144  $sql .= ', u.short_label as unit_short';
145 }
146 // Add fields from hooks
147 $parameters = array();
148 $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object); // Note that $action and $object may have been modified by hook
149 $sql .= $hookmanager->resPrint;
150 $sql .= ' FROM '.MAIN_DB_PREFIX.'product as p';
151 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_stock as s ON p.rowid = s.fk_product';
152 if (!empty($conf->global->PRODUCT_USE_UNITS)) {
153  $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_units as u on p.fk_unit = u.rowid';
154 }
155 // Add table from hooks
156 $parameters = array();
157 $reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object); // Note that $action and $object may have been modified by hook
158 $sql .= $hookmanager->resPrint;
159 $sql .= " WHERE p.entity IN (".getEntity('product').")";
160 if (!empty($search_categ) && $search_categ != '-1') {
161  $sql .= " AND ";
162  if ($search_categ == -2) {
163  $sql .= " NOT EXISTS ";
164  } else {
165  $sql .= " EXISTS ";
166  }
167  $sql .= "(";
168  $sql .= " SELECT cp.fk_categorie, cp.fk_product";
169  $sql .= " FROM " . MAIN_DB_PREFIX . "categorie_product as cp";
170  $sql .= " WHERE cp.fk_product = p.rowid"; // Join for the needed table to filter by categ
171  if ($search_categ > 0) {
172  $sql .= " AND cp.fk_categorie = " . ((int) $search_categ);
173  }
174  $sql .= ")";
175 }
176 if (empty($conf->global->PRODUCT_STOCK_LIST_SHOW_VIRTUAL_WITH_NO_PHYSICAL)) {
177  $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')."))";
178 } else {
179  $sql .= " AND
180  (
181  EXISTS
182  (SELECT e.rowid
183  FROM ".MAIN_DB_PREFIX."entrepot as e
184  WHERE e.rowid = s.fk_entrepot AND e.entity IN (".getEntity('stock')."))
185  OR (
186  SELECT SUM(cd1.qty) as qty
187  FROM ".MAIN_DB_PREFIX."commande_fournisseurdet as cd1
188  LEFT JOIN ".MAIN_DB_PREFIX."commande_fournisseur as c1
189  ON c1.rowid = cd1.fk_commande
190  WHERE c1.entity IN (1) AND cd1.fk_product = p.rowid AND c1.fk_statut in (3,4) AND cd1.qty <> 0
191  ) IS NOT NULL
192  OR (
193  SELECT SUM(cd2.qty) as qty
194  FROM ".MAIN_DB_PREFIX."commandedet as cd2
195  LEFT JOIN ".MAIN_DB_PREFIX."commande as c2 ON c2.rowid = cd2.fk_commande
196  WHERE c2.entity IN (1) AND cd2.fk_product = p.rowid AND c2.fk_statut in (1,2) AND cd2.qty <> 0
197  ) IS NOT NULL
198  OR (
199  SELECT SUM(ed3.qty) as qty
200  FROM ".MAIN_DB_PREFIX."expeditiondet as ed3
201  LEFT JOIN ".MAIN_DB_PREFIX."expedition as e3 ON e3.rowid = ed3.fk_expedition
202  LEFT JOIN ".MAIN_DB_PREFIX."commandedet as cd3 ON ed3.fk_origin_line = cd3.rowid
203  LEFT JOIN ".MAIN_DB_PREFIX."commande as c3 ON c3.rowid = cd3.fk_commande
204  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
205  ) IS NOT NULL
206  OR (
207  SELECT SUM(mp4.qty) as qty
208  FROM ".MAIN_DB_PREFIX."mrp_production as mp4
209  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)
210  WHERE mp4.fk_product = p.rowid AND mp4.qty <> 0
211  ) IS NOT NULL
212  ) ";
213 }
214 if ($sall) {
215  $sql .= natural_search(array('p.ref', 'p.label', 'p.description', 'p.note'), $sall);
216 }
217 // if the type is not 1, we show all products (type = 0,2,3)
218 if (dol_strlen($type)) {
219  if ($type == 1) {
220  $sql .= " AND p.fk_product_type = '1'";
221  } else {
222  $sql .= " AND p.fk_product_type <> '1'";
223  }
224 }
225 if ($sref) {
226  $sql .= natural_search('p.ref', $sref);
227 }
228 if ($search_barcode) {
229  $sql .= natural_search('p.barcode', $search_barcode);
230 }
231 if ($snom) {
232  $sql .= natural_search('p.label', $snom);
233 }
234 if (!empty($tosell)) {
235  $sql .= " AND p.tosell = ".((int) $tosell);
236 }
237 if (!empty($tobuy)) {
238  $sql .= " AND p.tobuy = ".((int) $tobuy);
239 }
240 if (!empty($canvas)) {
241  $sql .= " AND p.canvas = '".$db->escape($canvas)."'";
242 }
243 if ($fourn_id > 0) {
244  $sql .= " AND p.rowid = pf.fk_product AND pf.fk_soc = ".((int) $fourn_id);
245 }
246 // Add where from hooks
247 $parameters = array();
248 $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object); // Note that $action and $object may have been modified by hook
249 $sql .= $hookmanager->resPrint;
250 $sql .= " GROUP BY p.rowid, p.ref, p.label, p.barcode, p.price, p.price_ttc, p.price_base_type, p.entity,";
251 $sql .= " p.fk_product_type, p.tms, p.duration, p.tosell, p.tobuy, p.seuil_stock_alerte, p.desiredstock";
252 
253 // Add GROUP BY from hooks
254 $parameters = array();
255 $reshook = $hookmanager->executeHooks('printFieldListGroupBy', $parameters, $object); // Note that $action and $object may have been modified by hook
256 $sql .= $hookmanager->resPrint;
257 
258 $sql_having = '';
259 if ($search_toolowstock) {
260  $sql_having .= " HAVING SUM(".$db->ifsql('s.reel IS NULL', '0', 's.reel').") < p.seuil_stock_alerte";
261 }
262 if ($search_stock_physique != '') {
263  //$natural_search_physique = natural_search('HAVING SUM(' . $db->ifsql('s.reel IS NULL', '0', 's.reel') . ')', $search_stock_physique, 1, 1);
264  $natural_search_physique = natural_search('SUM(' . $db->ifsql('s.reel IS NULL', '0', 's.reel') . ')', $search_stock_physique, 1, 1);
265  $natural_search_physique = " " . substr($natural_search_physique, 1, -1); // remove first "(" and last ")" characters
266  if (!empty($sql_having)) {
267  $sql_having .= " AND";
268  } else {
269  $sql_having .= " HAVING";
270  }
271  $sql_having .= $natural_search_physique;
272 }
273 
274 // Add HAVING from hooks
275 $parameters = array();
276 $reshook = $hookmanager->executeHooks('printFieldListHaving', $parameters, $object); // Note that $action and $object may have been modified by hook
277 if (!empty($hookmanager->resPrint)) {
278  if (!empty($sql_having)) {
279  $sql_having .= " AND";
280  } else {
281  $sql_having .= " HAVING";
282  }
283  $sql_having .= $hookmanager->resPrint;
284 }
285 
286 if (!empty($sql_having)) {
287  $sql .= $sql_having;
288 }
289 $sql .= $db->order($sortfield, $sortorder);
290 
291 // Count total nb of records
292 $nbtotalofrecords = '';
293 if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
294  $result = $db->query($sql);
295  $nbtotalofrecords = $db->num_rows($result);
296  if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller then paging size (filtering), goto and load page 0
297  $page = 0;
298  $offset = 0;
299  }
300 }
301 
302 $sql .= $db->plimit($limit + 1, $offset);
303 
304 $resql = $db->query($sql);
305 if ($resql) {
306  $num = $db->num_rows($resql);
307 
308  $i = 0;
309 
310  if ($num == 1 && GETPOST('autojumpifoneonly') && ($sall || $snom || $sref)) {
311  $objp = $db->fetch_object($resql);
312  header("Location: card.php?id=$objp->rowid");
313  exit;
314  }
315 
316  if (isset($type)) {
317  if ($type == 1) {
318  $texte = $langs->trans("Services");
319  } else {
320  $texte = $langs->trans("Products");
321  }
322  } else {
323  $texte = $langs->trans("ProductsAndServices");
324  }
325  $texte .= ' ('.$langs->trans("MenuStocks").')';
326 
327  $param = '';
328  if ($limit > 0 && $limit != $conf->liste_limit) {
329  $param .= '&limit='.((int) $limit);
330  }
331  if ($sall) {
332  $param .= "&sall=".urlencode($sall);
333  }
334  if ($tosell) {
335  $param .= "&tosell=".urlencode($tosell);
336  }
337  if ($tobuy) {
338  $param .= "&tobuy=".urlencode($tobuy);
339  }
340  if ($type != '') {
341  $param .= "&type=".urlencode($type);
342  }
343  if ($fourn_id) {
344  $param .= "&fourn_id=".urlencode($fourn_id);
345  }
346  if ($snom) {
347  $param .= "&snom=".urlencode($snom);
348  }
349  if ($sref) {
350  $param .= "&sref=".urlencode($sref);
351  }
352  if ($search_sale) {
353  $param .= "&search_sale=".urlencode($search_sale);
354  }
355  if ($search_categ > 0) {
356  $param .= "&search_categ=".urlencode($search_categ);
357  }
358  if ($search_toolowstock) {
359  $param .= "&search_toolowstock=".urlencode($search_toolowstock);
360  }
361  if ($sbarcode) {
362  $param .= "&sbarcode=".urlencode($sbarcode);
363  }
364  if ($search_stock_physique) {
365  $param .= '&search_stock_physique=' . urlencode($search_stock_physique);
366  }
367 
368  llxHeader("", $texte, $helpurl);
369 
370  print '<form action="'.$_SERVER["PHP_SELF"].'" method="post" name="formulaire">';
371  print '<input type="hidden" name="token" value="'.newToken().'">';
372  print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
373  print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
374  print '<input type="hidden" name="page" value="'.$page.'">';
375  print '<input type="hidden" name="type" value="'.$type.'">';
376 
377  print_barre_liste($texte, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'product', 0, '', '', $limit);
378 
379  if ($search_categ > 0) {
380  print "<div id='ways'>";
381  $c = new Categorie($db);
382  $c->fetch($search_categ);
383  $ways = $c->print_all_ways(' &gt; ', 'product/reassort.php');
384  print " &gt; ".$ways[0]."<br>\n";
385  print "</div><br>";
386  }
387 
388  // Filter on categories
389  $moreforfilter = '';
390  if (isModEnabled('categorie')) {
391  $moreforfilter .= '<div class="divsearchfield">';
392  $moreforfilter .= img_picto($langs->trans('Categories'), 'category', 'class="pictofixedwidth"');
393  $moreforfilter .= $htmlother->select_categories(Categorie::TYPE_PRODUCT, $search_categ, 'search_categ', 1);
394  $moreforfilter .= '</div>';
395  }
396 
397  $moreforfilter .= '<div class="divsearchfield">';
398  $moreforfilter .= '<label for="search_toolowstock">'.$langs->trans("StockTooLow").' </label><input type="checkbox" id="search_toolowstock" name="search_toolowstock" value="1"'.($search_toolowstock ? ' checked' : '').'>';
399  $moreforfilter .= '</div>';
400 
401  if (!empty($moreforfilter)) {
402  print '<div class="liste_titre liste_titre_bydiv centpercent">';
403  print $moreforfilter;
404  $parameters = array();
405  $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters); // Note that $action and $object may have been modified by hook
406  print $hookmanager->resPrint;
407  print '</div>';
408  }
409 
410  $formProduct = new FormProduct($db);
411  $formProduct->loadWarehouses();
412  $warehouses_list = $formProduct->cache_warehouses;
413  $nb_warehouse = count($warehouses_list);
414  $colspan_warehouse = 1;
415  if (!empty($conf->global->STOCK_DETAIL_ON_WAREHOUSE)) {
416  $colspan_warehouse = $nb_warehouse > 1 ? $nb_warehouse + 1 : 1;
417  }
418 
419  print '<div class="div-table-responsive">';
420  print '<table class="tagtable liste'.($moreforfilter ? " listwithfilterbefore" : "").'">';
421 
422  // Fields title search
423  print '<tr class="liste_titre_filter">';
424  // Action column
425  if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) {
426  print '<td class="liste_titre maxwidthsearch">';
427  $searchpicto = $form->showFilterAndCheckAddButtons(0);
428  print $searchpicto;
429  print '</td>';
430  }
431  print '<td class="liste_titre">';
432  print '<input class="flat" type="text" name="sref" size="6" value="'.$sref.'">';
433  print '</td>';
434  print '<td class="liste_titre">';
435  print '<input class="flat" type="text" name="snom" size="8" value="'.$snom.'">';
436  print '</td>';
437  // Duration
438  if (isModEnabled("service") && $type == 1) {
439  print '<td class="liste_titre">';
440  print '&nbsp;';
441  print '</td>';
442  }
443  // Stock limit
444  print '<td class="liste_titre">&nbsp;</td>';
445  print '<td class="liste_titre right">&nbsp;</td>';
446  // Physical stock
447  print '<td class="liste_titre right">';
448  print '<input class="flat" type="text" size="5" name="search_stock_physique" value="'.dol_escape_htmltag($search_stock_physique).'">';
449  print '</td>';
450  if ($virtualdiffersfromphysical) {
451  print '<td class="liste_titre">&nbsp;</td>';
452  }
453  print '<td class="liste_titre">&nbsp;</td>';
454  print '<td class="liste_titre" colspan="'.$colspan_warehouse.'">&nbsp;</td>';
455  print '<td class="liste_titre"></td>';
456  $parameters = array();
457  $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters); // Note that $action and $object may have been modified by hook
458  print $hookmanager->resPrint;
459  if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) {
460  print '<td class="liste_titre maxwidthsearch">';
461  $searchpicto = $form->showFilterAndCheckAddButtons(0);
462  print $searchpicto;
463  print '</td>';
464  }
465  print '</tr>';
466 
467  // Line for column titles
468  print '<tr class="liste_titre">';
469  // Action column
470  if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) {
472  }
473  print_liste_field_titre("Ref", $_SERVER["PHP_SELF"], "p.ref", '', $param, "", $sortfield, $sortorder);
474  print_liste_field_titre("Label", $_SERVER["PHP_SELF"], "p.label", '', $param, "", $sortfield, $sortorder);
475  if (isModEnabled("service") && $type == 1) {
476  print_liste_field_titre("Duration", $_SERVER["PHP_SELF"], "p.duration", '', $param, "", $sortfield, $sortorder, 'center ');
477  }
478  print_liste_field_titre("StockLimit", $_SERVER["PHP_SELF"], "p.seuil_stock_alerte", '', $param, "", $sortfield, $sortorder, 'right ');
479  print_liste_field_titre("DesiredStock", $_SERVER["PHP_SELF"], "p.desiredstock", '', $param, "", $sortfield, $sortorder, 'right ');
480  print_liste_field_titre("PhysicalStock", $_SERVER["PHP_SELF"], "stock_physique", '', $param, "", $sortfield, $sortorder, 'right ');
481  // Details per warehouse
482  if (!empty($conf->global->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)
483  if ($nb_warehouse > 1) {
484  foreach ($warehouses_list as &$wh) {
485  print_liste_field_titre($wh['label'], '', '', '', '', '', '', '', 'right ');
486  }
487  }
488  }
489  if ($virtualdiffersfromphysical) {
490  print_liste_field_titre("VirtualStock", $_SERVER["PHP_SELF"], "", '', $param, "", $sortfield, $sortorder, 'right ', 'VirtualStockDesc');
491  }
492  // Units
493  if (!empty($conf->global->PRODUCT_USE_UNITS)) {
494  print_liste_field_titre("Unit", $_SERVER["PHP_SELF"], "unit_short", '', $param, 'align="right"', $sortfield, $sortorder);
495  }
497  print_liste_field_titre("ProductStatusOnSell", $_SERVER["PHP_SELF"], "p.tosell", '', $param, "", $sortfield, $sortorder, 'right ');
498  print_liste_field_titre("ProductStatusOnBuy", $_SERVER["PHP_SELF"], "p.tobuy", '', $param, "", $sortfield, $sortorder, 'right ');
499  // Hook fields
500  $parameters = array('param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder);
501  $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters); // Note that $action and $object may have been modified by hook
502  print $hookmanager->resPrint;
503  // Action column
504  if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) {
506  }
507  print "</tr>\n";
508 
509  while ($i < min($num, $limit)) {
510  $objp = $db->fetch_object($resql);
511 
512  $product = new Product($db);
513  $product->fetch($objp->rowid);
514  $product->load_stock();
515 
516  print '<tr>';
517  // Action column
518  if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) {
519  print '<td></td>';
520  }
521  print '<td class="nowrap">';
522  print $product->getNomUrl(1, '', 16);
523  //if ($objp->stock_theorique < $objp->seuil_stock_alerte) print ' '.img_warning($langs->trans("StockTooLow"));
524  print '</td>';
525  print '<td class="tdoverflowmax150" title="'.dol_escape_htmltag($product->label).'">'.dol_escape_htmltag($product->label).'</td>';
526 
527  if (isModEnabled("service") && $type == 1) {
528  print '<td class="center">';
529  if (preg_match('/([0-9]+)y/i', $objp->duration, $regs)) {
530  print $regs[1].' '.$langs->trans("DurationYear");
531  } elseif (preg_match('/([0-9]+)m/i', $objp->duration, $regs)) {
532  print $regs[1].' '.$langs->trans("DurationMonth");
533  } elseif (preg_match('/([0-9]+)d/i', $objp->duration, $regs)) {
534  print $regs[1].' '.$langs->trans("DurationDay");
535  } else {
536  print $objp->duration;
537  }
538  print '</td>';
539  }
540  //print '<td class="right">'.$objp->stock_theorique.'</td>';
541  print '<td class="right">';
542  print $objp->seuil_stock_alerte;
543  print '</td>';
544  print '<td class="right">';
545  print $objp->desiredstock;
546  print '</td>';
547  // Real stock
548  print '<td class="right">';
549  if ($objp->seuil_stock_alerte != '' && ($objp->stock_physique < $objp->seuil_stock_alerte)) {
550  print img_warning($langs->trans("StockLowerThanLimit", $objp->seuil_stock_alerte)).' ';
551  }
552  if ($objp->stock_physique < 0) { print '<span class="warning">'; }
553  print price(price2num($objp->stock_physique, 'MS'), 0, $langs, 1, 0);
554  if ($objp->stock_physique < 0) { print '</span>'; }
555  print '</td>';
556 
557  // Details per warehouse
558  if (!empty($conf->global->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)
559  if ($nb_warehouse > 1) {
560  foreach ($warehouses_list as &$wh) {
561  print '<td class="right">';
562  print price(empty($product->stock_warehouse[$wh['id']]->real) ? 0 : price2num($product->stock_warehouse[$wh['id']]->real, 'MS'), 0, $langs, 1, 0);
563  print '</td>';
564  }
565  }
566  }
567 
568  // Virtual stock
569  if ($virtualdiffersfromphysical) {
570  print '<td class="right">';
571  if ($objp->seuil_stock_alerte != '' && ($product->stock_theorique < (float) $objp->seuil_stock_alerte)) {
572  print img_warning($langs->trans("StockLowerThanLimit", $objp->seuil_stock_alerte)).' ';
573  }
574  if ($objp->stock_physique < 0) { print '<span class="warning">'; }
575  print price(price2num($product->stock_theorique, 'MS'), 0, $langs, 1, 0);
576  if ($objp->stock_physique < 0) { print '</span>'; }
577  print '</td>';
578  }
579  // Units
580  if (!empty($conf->global->PRODUCT_USE_UNITS)) {
581  print '<td class="left">'.dol_escape_htmltag($objp->unit_short).'</td>';
582  }
583  print '<td class="center nowraponall">';
584  print img_picto($langs->trans("StockMovement"), 'movement', 'class="pictofixedwidth"');
585  print '<a href="'.DOL_URL_ROOT.'/product/stock/movement_list.php?idproduct='.$product->id.'">'.$langs->trans("Movements").'</a>';
586  print '</td>';
587  print '<td class="right nowrap">'.$product->LibStatut($objp->statut, 5, 0).'</td>';
588  print '<td class="right nowrap">'.$product->LibStatut($objp->tobuy, 5, 1).'</td>';
589  // Fields from hook
590  $parameters = array('obj'=>$objp);
591  $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $product); // Note that $action and $object may have been modified by hook
592  print $hookmanager->resPrint;
593  // Action column
594  if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) {
595  print '<td></td>';
596  }
597 
598  print "</tr>\n";
599  $i++;
600  }
601 
602  print "</table>";
603  print '</div>';
604 
605  print '</form>';
606 
607  $db->free($resql);
608 } else {
609  dol_print_error($db);
610 }
611 
612 // End of page
613 llxFooter();
614 $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:56
llxFooter()
Empty footer.
Definition: wrapper.php:70
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.
if(isModEnabled('facture') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') && $user->hasRight('don', 'lire')) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->hasRight("commande", "lire") &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $sql
Social contributions to pay.
Definition: index.php:746
if($cancel &&! $id) if($action=='add' &&! $cancel) if($action=='delete') if($id) $form
Actions.
Definition: card.php:143
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 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.
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname from a POST of a form.
isModEnabled($module)
Is Dolibarr module enabled.
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.