dolibarr  x.y.z
reassortlot.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2001-2006 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3  * Copyright (C) 2004-2016 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) 2016 Ferran Marcet <fmarcet@2byte.es>
8  * Copyright (C) 2019 Juanjo Menent <jmenent@2byte.es>
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.'/product/stock/class/productlot.class.php';
34 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
35 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
36 require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
37 require_once DOL_DOCUMENT_ROOT.'/product/stock/class/productlot.class.php';
38 
39 // Load translation files required by the page
40 $langs->loadLangs(array('products', 'stocks', 'productbatch'));
41 
42 $action = GETPOST('action', 'aZ09') ?GETPOST('action', 'aZ09') : 'view'; // The action 'add', 'create', 'edit', 'update', 'view', ...
43 $massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choice into lists)
44 $contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'myobjectlist'; // To manage different context of search
45 $backtopage = GETPOST('backtopage', 'alpha'); // Go back to a dedicated page
46 $optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print')
47 $mode = GETPOST('mode', 'aZ');
48 
49 $sref = GETPOST("sref", 'alpha');
50 $snom = GETPOST("snom", 'alpha');
51 $sall = trim((GETPOST('search_all', 'alphanohtml') != '') ?GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml'));
52 $type = GETPOSTISSET('type') ? GETPOST('type', 'int') : Product::TYPE_PRODUCT;
53 $search_barcode = GETPOST("search_barcode", 'alpha');
54 $search_warehouse = GETPOST('search_warehouse', 'alpha');
55 $search_batch = GETPOST('search_batch', 'alpha');
56 $search_toolowstock = GETPOST('search_toolowstock');
57 $search_subjecttolotserial = GETPOST('search_subjecttolotserial');
58 $tosell = GETPOST("tosell");
59 $tobuy = GETPOST("tobuy");
60 $fourn_id = GETPOST("fourn_id", 'int');
61 $sbarcode = GETPOST("sbarcode", 'int');
62 $search_stock_physique = GETPOST('search_stock_physique', 'alpha');
63 
64 // Load variable for pagination
65 $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit;
66 $sortfield = GETPOST('sortfield', 'aZ09comma');
67 $sortorder = GETPOST('sortorder', 'aZ09comma');
68 $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int');
69 if (empty($page) || $page < 0 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha')) {
70  // If $page is not defined, or '' or -1 or if we click on clear filters
71  $page = 0;
72 }
73 $offset = $limit * $page;
74 $pageprev = $page - 1;
75 $pagenext = $page + 1;
76 
77 // Initialize array of search criterias
78 $object = new Product($db);
79 $search_sale = GETPOST("search_sale");
80 if (GETPOSTISSET('catid')) {
81  $search_categ = GETPOST('catid', 'int');
82 } else {
83  $search_categ = GETPOST('search_categ', 'int');
84 }
85 
86 // Fetch optionals attributes and labels
87 $extrafields->fetch_name_optionals_label($object->table_element);
88 //$extrafields->fetch_name_optionals_label($object->table_element_line);
89 
90 $search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_');
91 
92 // Default sort order (if not yet defined by previous GETPOST)
93 if (!$sortfield) {
94  reset($object->fields); // Reset is required to avoid key() to return null.
95  $sortfield = "p.".key($object->fields); // Set here default search field. By default 1st field in definition.
96 }
97 if (!$sortorder) {
98  $sortorder = "ASC";
99 }
100 
101 
102 // Initialize array of search criterias
103 $search = array();
104 foreach ($object->fields as $key => $val) {
105  if (GETPOST('search_'.$key, 'alpha') !== '') {
106  $search[$key] = GETPOST('search_'.$key, 'alpha');
107  }
108  if (preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
109  $search[$key.'_dtstart'] = dol_mktime(0, 0, 0, GETPOST('search_'.$key.'_dtstartmonth', 'int'), GETPOST('search_'.$key.'_dtstartday', 'int'), GETPOST('search_'.$key.'_dtstartyear', 'int'));
110  $search[$key.'_dtend'] = dol_mktime(23, 59, 59, GETPOST('search_'.$key.'_dtendmonth', 'int'), GETPOST('search_'.$key.'_dtendday', 'int'), GETPOST('search_'.$key.'_dtendyear', 'int'));
111  }
112 }
113 $key = 'sellby';
114 $search[$key.'_dtstart'] = dol_mktime(0, 0, 0, GETPOST('search_'.$key.'_dtstartmonth', 'int'), GETPOST('search_'.$key.'_dtstartday', 'int'), GETPOST('search_'.$key.'_dtstartyear', 'int'));
115 $search[$key.'_dtend'] = dol_mktime(23, 59, 59, GETPOST('search_'.$key.'_dtendmonth', 'int'), GETPOST('search_'.$key.'_dtendday', 'int'), GETPOST('search_'.$key.'_dtendyear', 'int'));
116 $key = 'eatby';
117 $search[$key.'_dtstart'] = dol_mktime(0, 0, 0, GETPOST('search_'.$key.'_dtstartmonth', 'int'), GETPOST('search_'.$key.'_dtstartday', 'int'), GETPOST('search_'.$key.'_dtstartyear', 'int'));
118 $search[$key.'_dtend'] = dol_mktime(23, 59, 59, GETPOST('search_'.$key.'_dtendmonth', 'int'), GETPOST('search_'.$key.'_dtendday', 'int'), GETPOST('search_'.$key.'_dtendyear', 'int'));
119 
120 // Get object canvas (By default, this is not defined, so standard usage of dolibarr)
121 $canvas = GETPOST("canvas");
122 $objcanvas = null;
123 if (!empty($canvas)) {
124  require_once DOL_DOCUMENT_ROOT.'/core/class/canvas.class.php';
125  $objcanvas = new Canvas($db, $action);
126  $objcanvas->getCanvas('product', 'list', $canvas);
127 }
128 
129 // Security check
130 if ($user->socid) {
131  $socid = $user->socid;
132 }
133 $result = restrictedArea($user, 'produit|service', 0, 'product&product');
134 
135 
136 /*
137  * Actions
138  */
139 
140 if (GETPOST('cancel', 'alpha')) {
141  $action = 'list';
142  $massaction = '';
143 }
144 if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') {
145  $massaction = '';
146 }
147 
148 $parameters = array();
149 $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
150 if ($reshook < 0) {
151  setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
152 }
153 
154 if (empty($reshook)) {
155  // Selection of new fields
156  include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
157 
158  // Purge search criteria
159  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
160  foreach ($object->fields as $key => $val) {
161  $search[$key] = '';
162  if (preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
163  $search[$key.'_dtstart'] = '';
164  $search[$key.'_dtend'] = '';
165  }
166  }
167  $search['sellby_dtstart'] = '';
168  $search['eatby_dtstart'] = '';
169  $search['sellby_dtend'] = '';
170  $search['eatby_dtend'] = '';
171  $sref = "";
172  $snom = "";
173  $sall = "";
174  $tosell = "";
175  $tobuy = "";
176  $search_sale = "";
177  $search_categ = "";
178  $search_toolowstock = '';
179  $search_subjecttolotserial = '';
180  $search_batch = '';
181  $search_warehouse = '';
182  $fourn_id = '';
183  $sbarcode = '';
184  $search_stock_physique = '';
185  $toselect = array();
186  $search_array_options = array();
187  }
188  if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')
189  || GETPOST('button_search_x', 'alpha') || GETPOST('button_search.x', 'alpha') || GETPOST('button_search', 'alpha')) {
190  $massaction = ''; // Protection to avoid mass action if we force a new search during a mass action confirmation
191  }
192 
193  // Mass actions
194  /*$objectclass = 'MyObject';
195  $objectlabel = 'MyObject';
196  $uploaddir = $conf->mymodule->dir_output;
197  include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php';
198  */
199 }
200 
201 
202 
203 /*
204  * View
205  */
206 
207 $form = new Form($db);
208 $htmlother = new FormOther($db);
209 
210 $now = dol_now();
211 
212 $helpurl = 'EN:Module_Stocks_En|FR:Module_Stock|ES:M&oacute;dulo_Stocks';
213 $title = $langs->trans("ProductsAndServices");
214 $morejs = array();
215 $morecss = array();
216 
217 $sql = 'SELECT p.rowid, p.ref, p.label, p.barcode, p.price, p.price_ttc, p.price_base_type, p.entity,';
218 $sql .= ' p.fk_product_type, p.tms as datem,';
219 $sql .= ' p.duration, p.tosell as statut, p.tobuy, p.seuil_stock_alerte, p.desiredstock, p.stock, p.tosell, p.tobuy, p.tobatch,';
220 $sql .= ' ps.fk_entrepot,';
221 $sql .= ' e.ref as warehouse_ref, e.lieu as warehouse_lieu, e.fk_parent as warehouse_parent,';
222 $sql .= ' pb.batch, pb.eatby as oldeatby, pb.sellby as oldsellby,';
223 $sql .= ' pl.rowid as lotid, pl.eatby, pl.sellby,';
224 $sql .= ' SUM(pb.qty) as stock_physique, COUNT(pb.rowid) as nbinbatchtable';
225 $sql .= ' FROM '.MAIN_DB_PREFIX.'product as p';
226 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_stock as ps on p.rowid = ps.fk_product'; // Detail for each warehouse
227 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'entrepot as e on ps.fk_entrepot = e.rowid'; // Link on unique key
228 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_batch as pb on pb.fk_product_stock = ps.rowid'; // Detail for each lot on each warehouse
229 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_lot as pl on pl.fk_product = p.rowid AND pl.batch = pb.batch'; // Link on unique key
230 $sql .= " WHERE p.entity IN (".getEntity('product').")";
231 if (!empty($search_categ) && $search_categ != '-1') {
232  $sql .= " AND ";
233  if ($search_categ == -2) {
234  $sql .= " NOT EXISTS ";
235  } else {
236  $sql .= " EXISTS ";
237  }
238  $sql .= "(";
239  $sql .= " SELECT cp.fk_categorie, cp.fk_product";
240  $sql .= " FROM " . MAIN_DB_PREFIX . "categorie_product as cp";
241  $sql .= " WHERE cp.fk_product = p.rowid"; // Join for the needed table to filter by categ
242  if ($search_categ > 0) {
243  $sql .= " AND cp.fk_categorie = " . ((int) $search_categ);
244  }
245  $sql .= ")";
246 }
247 if ($sall) {
248  $sql .= natural_search(array('p.ref', 'p.label', 'p.description', 'p.note'), $sall);
249 }
250 // if the type is not 1, we show all products (type = 0,2,3)
251 if (dol_strlen($type)) {
252  if ($type == 1) {
253  $sql .= " AND p.fk_product_type = '1'";
254  } else {
255  $sql .= " AND p.fk_product_type <> '1'";
256  }
257 }
258 if ($search_subjecttolotserial) {
259  $sql .= " AND p.tobatch > 0";
260 }
261 if ($sref) {
262  $sql .= natural_search("p.ref", $sref);
263 }
264 if ($search_barcode) {
265  $sql .= natural_search("p.barcode", $search_barcode);
266 }
267 if ($snom) {
268  $sql .= natural_search("p.label", $snom);
269 }
270 if (!empty($tosell)) {
271  $sql .= " AND p.tosell = ".((int) $tosell);
272 }
273 if (!empty($tobuy)) {
274  $sql .= " AND p.tobuy = ".((int) $tobuy);
275 }
276 if (!empty($canvas)) {
277  $sql .= " AND p.canvas = '".$db->escape($canvas)."'";
278 }
279 if ($fourn_id > 0) {
280  $sql .= " AND p.rowid = pf.fk_product AND pf.fk_soc = ".((int) $fourn_id);
281 }
282 if ($search_warehouse) {
283  $sql .= natural_search("e.ref", $search_warehouse);
284 }
285 if ($search_batch) {
286  $sql .= natural_search("pb.batch", $search_batch);
287 }
288 
289 foreach ($search as $key => $val) {
290  if (array_key_exists($key, $object->fields)) {
291  if ($key == 'status' && $search[$key] == -1) {
292  continue;
293  }
294  $mode_search = (($object->isInt($object->fields[$key]) || $object->isFloat($object->fields[$key])) ? 1 : 0);
295  if ((strpos($object->fields[$key]['type'], 'integer:') === 0) || (strpos($object->fields[$key]['type'], 'sellist:') === 0) || !empty($object->fields[$key]['arrayofkeyval'])) {
296  if ($search[$key] == '-1' || ($search[$key] === '0' && (empty($object->fields[$key]['arrayofkeyval']) || !array_key_exists('0', $object->fields[$key]['arrayofkeyval'])))) {
297  $search[$key] = '';
298  }
299  $mode_search = 2;
300  }
301  if ($search[$key] != '') {
302  $sql .= natural_search("t.".$db->escape($key), $search[$key], (($key == 'status') ? 2 : $mode_search));
303  }
304  } else {
305  if (preg_match('/(_dtstart|_dtend)$/', $key) && $search[$key] != '') {
306  $columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key);
307  if ($columnName == 'eatby' || $columnName == 'sellby') {
308  if (preg_match('/_dtstart$/', $key)) {
309  $sql .= " AND pl.".$db->escape($columnName)." >= '".$db->idate($search[$key])."'";
310  }
311  if (preg_match('/_dtend$/', $key)) {
312  $sql .= " AND pl.".$db->escape($columnName)." <= '".$db->idate($search[$key])."'";
313  }
314  }
315  }
316  }
317 }
318 
319 $sql .= " GROUP BY p.rowid, p.ref, p.label, p.barcode, p.price, p.price_ttc, p.price_base_type, p.entity,";
320 $sql .= " p.fk_product_type, p.tms,";
321 $sql .= " p.duration, p.tosell, p.tobuy, p.seuil_stock_alerte, p.desiredstock, p.stock, p.tosell, p.tobuy, p.tobatch,";
322 $sql .= " ps.fk_entrepot,";
323 $sql .= " e.ref, e.lieu, e.fk_parent,";
324 $sql .= " pb.batch, pb.eatby, pb.sellby,";
325 $sql .= " pl.rowid, pl.eatby, pl.sellby";
326 $sql_having = '';
327 if ($search_toolowstock) {
328  $sql_having .= " HAVING SUM(".$db->ifsql('ps.reel IS NULL', '0', 'ps.reel').") < p.seuil_stock_alerte"; // Not used yet
329 }
330 if ($search_stock_physique != '') {
331  $natural_search_physique = natural_search('SUM(' . $db->ifsql('pb.qty IS NULL', '0', 'pb.qty') . ')', $search_stock_physique, 1, 1);
332  $natural_search_physique = " " . substr($natural_search_physique, 1, -1); // remove first "(" and last ")" characters
333  if (!empty($sql_having)) {
334  $sql_having .= " AND";
335  } else {
336  $sql_having .= " HAVING";
337  }
338  $sql_having .= $natural_search_physique;
339 }
340 if (!empty($sql_having)) {
341  $sql .= $sql_having;
342 }
343 
344 //print $sql;
345 
346 // Count total nb of records
347 $nbtotalofrecords = '';
348 if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {
349  $resql = $db->query($sql);
350  $nbtotalofrecords = $db->num_rows($resql);
351 
352  if (($page * $limit) > $nbtotalofrecords) { // if total of record found is smaller than page * limit, goto and load page 0
353  $page = 0;
354  $offset = 0;
355  }
356  $db->free($resql);
357 }
358 
359 // Complete request and execute it with limit
360 $sql .= $db->order($sortfield, $sortorder);
361 if ($limit) {
362  $sql .= $db->plimit($limit + 1, $offset);
363 }
364 
365 $resql = $db->query($sql);
366 if (!$resql) {
367  dol_print_error($db);
368  exit;
369 }
370 
371 $num = $db->num_rows($resql);
372 
373 $i = 0;
374 
375 if ($num == 1 && GETPOST('autojumpifoneonly') && ($sall or $snom or $sref)) {
376  $objp = $db->fetch_object($resql);
377  header("Location: card.php?id=$objp->rowid");
378  exit;
379 }
380 
381 if (isset($type)) {
382  if ($type == 1) {
383  $texte = $langs->trans("Services");
384  } else {
385  $texte = $langs->trans("Products");
386  }
387 } else {
388  $texte = $langs->trans("ProductsAndServices");
389 }
390 $texte .= ' ('.$langs->trans("StocksByLotSerial").')';
391 
392 $param = '';
393 if (!empty($mode)) {
394  $param .= '&mode='.urlencode($mode);
395 }
396 if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
397  $param .= '&contextpage='.urlencode($contextpage);
398 }
399 if ($limit > 0 && $limit != $conf->liste_limit) {
400  $param .= '&limit='.urlencode($limit);
401 }
402 foreach ($search as $key => $val) {
403  if (is_array($search[$key]) && count($search[$key])) {
404  foreach ($search[$key] as $skey) {
405  if ($skey != '') {
406  $param .= '&search_'.$key.'[]='.urlencode($skey);
407  }
408  }
409  } elseif ($search[$key] != '') {
410  $param .= '&search_'.$key.'='.urlencode($search[$key]);
411  }
412 }
413 if ($optioncss != '') {
414  $param .= '&optioncss='.urlencode($optioncss);
415 }
416 if ($sall) {
417  $param .= "&sall=".urlencode($sall);
418 }
419 if ($tosell) {
420  $param .= "&tosell=".urlencode($tosell);
421 }
422 if ($tobuy) {
423  $param .= "&tobuy=".urlencode($tobuy);
424 }
425 if ($type != '') {
426  $param .= "&type=".urlencode($type);
427 }
428 if ($fourn_id) {
429  $param .= "&fourn_id=".urlencode($fourn_id);
430 }
431 if ($snom) {
432  $param .= "&snom=".urlencode($snom);
433 }
434 if ($sref) {
435  $param .= "&sref=".urlencode($sref);
436 }
437 if ($search_batch) {
438  $param .= "&search_batch=".urlencode($search_batch);
439 }
440 if ($sbarcode) {
441  $param .= "&sbarcode=".urlencode($sbarcode);
442 }
443 if ($search_warehouse) {
444  $param .= "&search_warehouse=".urlencode($search_warehouse);
445 }
446 if ($search_toolowstock) {
447  $param .= "&search_toolowstock=".urlencode($search_toolowstock);
448 }
449 if ($search_subjecttolotserial) {
450  $param .= "&search_subjecttolotserial=".urlencode($search_subjecttolotserial);
451 }
452 if ($search_sale) {
453  $param .= "&search_sale=".urlencode($search_sale);
454 }
455 if (!empty($search_categ) && $search_categ != '-1') {
456  $param .= "&search_categ=".urlencode($search_categ);
457 }
458 if ($search_stock_physique) {
459  $param .= '&search_stock_physique=' . urlencode($search_stock_physique);
460 }
461 /*if ($eatby) $param.="&eatby=".$eatby;
462 if ($sellby) $param.="&sellby=".$sellby;*/
463 
464 llxHeader("", $title, $helpurl, $texte);
465 
466 print '<form id="searchFormList" action="'.$_SERVER["PHP_SELF"].'" method="POST" name="formulaire">'."\n";
467 if ($optioncss != '') {
468  print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
469 }
470 print '<input type="hidden" name="token" value="'.newToken().'">';
471 print '<input type="hidden" name="action" value="list">';
472 print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
473 print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
474 print '<input type="hidden" name="type" value="'.$type.'">';
475 print '<input type="hidden" name="page" value="'.$page.'">';
476 print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
477 print '<input type="hidden" name="mode" value="'.$mode.'">';
478 
479 print_barre_liste($texte, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'product', 0, '', '', $limit, 0, 0, 1);
480 
481 
482 if ($search_categ > 0) {
483  print "<div id='ways'>";
484  $c = new Categorie($db);
485  $c->fetch($search_categ);
486  $ways = $c->print_all_ways(' &gt; ', 'product/reassortlot.php');
487  print " &gt; ".$ways[0]."<br>\n";
488  print "</div><br>";
489 }
490 
491 // Filter on categories
492 $moreforfilter = '';
493 if (isModEnabled('categorie')) {
494  $moreforfilter .= '<div class="divsearchfield">';
495  $moreforfilter .= img_picto($langs->trans('Categories'), 'category', 'class="pictofixedwidth"');
496  $moreforfilter .= $htmlother->select_categories(Categorie::TYPE_PRODUCT, $search_categ, 'search_categ', 1);
497  $moreforfilter .= '</div>';
498 }
499 $moreforfilter.='<label for="search_subjecttolotserial">'.$langs->trans("SubjectToLotSerialOnly").' </label><input type="checkbox" id="search_subjecttolotserial" name="search_subjecttolotserial" value="1"'.($search_subjecttolotserial?' checked':'').'>';
500 
501 if (!empty($moreforfilter)) {
502  print '<div class="liste_titre liste_titre_bydiv centpercent">';
503  print $moreforfilter;
504  $parameters = array();
505  $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters); // Note that $action and $object may have been modified by hook
506  print $hookmanager->resPrint;
507  print '</div>';
508 }
509 
510 
511 print '<div class="div-table-responsive">';
512 print '<table class="tagtable nobottomiftotal liste'.($moreforfilter ? " listwithfilterbefore" : "").'">';
513 
514 // Fields title search
515 // --------------------------------------------------------------------
516 print '<tr class="liste_titre_filter">';
517 print '<td class="liste_titre">';
518 print '<input class="flat" type="text" name="sref" size="6" value="'.$sref.'">';
519 print '</td>';
520 print '<td class="liste_titre">';
521 print '<input class="flat" type="text" name="snom" size="8" value="'.$snom.'">';
522 print '</td>';
523 if (isModEnabled("service") && $type == 1) {
524  print '<td class="liste_titre">';
525  print '&nbsp;';
526  print '</td>';
527 }
528 print '<td class="liste_titre"><input class="flat" type="text" name="search_warehouse" size="6" value="'.$search_warehouse.'"></td>';
529 print '<td class="liste_titre center"><input class="flat" type="text" name="search_batch" size="6" value="'.$search_batch.'"></td>';
530 if (empty($conf->global->PRODUCT_DISABLE_SELLBY)) {
531  print '<td class="liste_titre center">';
532  $key = 'sellby';
533  print '<div class="nowrap">';
534  print $form->selectDate($search[$key.'_dtstart'] ? $search[$key.'_dtstart'] : '', "search_".$key."_dtstart", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From'));
535  print '</div>';
536  print '<div class="nowrap">';
537  print $form->selectDate($search[$key.'_dtend'] ? $search[$key.'_dtend'] : '', "search_".$key."_dtend", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to'));
538  print '</div>';
539  print '</td>';
540 }
541 if (empty($conf->global->PRODUCT_DISABLE_EATBY)) {
542  print '<td class="liste_titre center">';
543  $key = 'eatby';
544  print '<div class="nowrap">';
545  print $form->selectDate($search[$key.'_dtstart'] ? $search[$key.'_dtstart'] : '', "search_".$key."_dtstart", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From'));
546  print '</div>';
547  print '<div class="nowrap">';
548  print $form->selectDate($search[$key.'_dtend'] ? $search[$key.'_dtend'] : '', "search_".$key."_dtend", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to'));
549  print '</div>';
550  print '</td>';
551 }
552 // Physical stock
553 print '<td class="liste_titre right">';
554 print '<input class="flat" type="text" size="5" name="search_stock_physique" value="'.dol_escape_htmltag($search_stock_physique).'">';
555 print '</td>';
556 print '<td class="liste_titre">&nbsp;</td>';
557 print '<td class="liste_titre">&nbsp;</td>';
558 print '<td class="liste_titre">&nbsp;</td>';
559 // Action column
560 if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) {
561  print '<td class="liste_titre maxwidthsearch">';
562  $searchpicto = $form->showFilterButtons();
563  print $searchpicto;
564  print '</td>';
565 }
566 print '</tr>'."\n";
567 
568 $totalarray = array();
569 $totalarray['nbfield'] = 0;
570 
571 // Fields title label
572 // --------------------------------------------------------------------
573 print '<tr class="liste_titre">';
574 print_liste_field_titre("Ref", $_SERVER["PHP_SELF"], "p.ref", '', $param, "", $sortfield, $sortorder);
575 print_liste_field_titre("Label", $_SERVER["PHP_SELF"], "p.label", '', $param, "", $sortfield, $sortorder);
576 if (isModEnabled("service") && $type == 1) {
577  print_liste_field_titre("Duration", $_SERVER["PHP_SELF"], "p.duration", '', $param, "", $sortfield, $sortorder, 'center ');
578 }
579 print_liste_field_titre("Warehouse", $_SERVER["PHP_SELF"], "e.ref", '', $param, "", $sortfield, $sortorder);
580 //print_liste_field_titre("DesiredStock", $_SERVER["PHP_SELF"], "p.desiredstock",$param,"",'',$sortfield,$sortorder, 'right );
581 print_liste_field_titre("Batch", $_SERVER["PHP_SELF"], "pb.batch", '', $param, "", $sortfield, $sortorder, 'center ');
582 if (empty($conf->global->PRODUCT_DISABLE_SELLBY)) {
583  print_liste_field_titre("SellByDate", $_SERVER["PHP_SELF"], "pl.sellby", '', $param, "", $sortfield, $sortorder, 'center ');
584 }
585 if (empty($conf->global->PRODUCT_DISABLE_EATBY)) {
586  print_liste_field_titre("EatByDate", $_SERVER["PHP_SELF"], "pl.eatby", '', $param, "", $sortfield, $sortorder, 'center ');
587 }
588 print_liste_field_titre("PhysicalStock", $_SERVER["PHP_SELF"], "stock_physique", '', $param, "", $sortfield, $sortorder, 'right ');
589 // TODO Add info of running suppliers/customers orders
590 //print_liste_field_titre("TheoreticalStock",$_SERVER["PHP_SELF"], "stock_theorique",$param,"",'',$sortfield,$sortorder, 'right ');
592 print_liste_field_titre("ProductStatusOnSell", $_SERVER["PHP_SELF"], "p.tosell", "", $param, '', $sortfield, $sortorder, 'right ');
593 print_liste_field_titre("ProductStatusOnBuy", $_SERVER["PHP_SELF"], "p.tobuy", "", $param, '', $sortfield, $sortorder, 'right ');
595 print "</tr>\n";
596 
597 $product_static = new Product($db);
598 $product_lot_static = new Productlot($db);
599 $warehousetmp = new Entrepot($db);
600 
601 // Loop on record
602 // --------------------------------------------------------------------
603 $i = 0;
604 $savnbfield = $totalarray['nbfield'];
605 $totalarray['nbfield'] = 0;
606 $imaxinloop = ($limit ? min($num, $limit) : $num);
607 while ($i < $imaxinloop) {
608  $objp = $db->fetch_object($resql);
609 
610  // Multilangs
611  if (getDolGlobalInt('MAIN_MULTILANGS')) { // si l'option est active
612  // TODO Use a cache
613  $sql = "SELECT label";
614  $sql .= " FROM ".MAIN_DB_PREFIX."product_lang";
615  $sql .= " WHERE fk_product = ".((int) $objp->rowid);
616  $sql .= " AND lang = '".$db->escape($langs->getDefaultLang())."'";
617  $sql .= " LIMIT 1";
618 
619  $result = $db->query($sql);
620  if ($result) {
621  $objtp = $db->fetch_object($result);
622  if (!empty($objtp->label)) {
623  $objp->label = $objtp->label;
624  }
625  }
626  }
627 
628  $product_static->ref = $objp->ref;
629  $product_static->id = $objp->rowid;
630  $product_static->label = $objp->label;
631  $product_static->type = $objp->fk_product_type;
632  $product_static->entity = $objp->entity;
633  $product_static->status = $objp->tosell;
634  $product_static->status_buy = $objp->tobuy;
635  $product_static->status_batch = $objp->tobatch;
636 
637  $product_lot_static->batch = $objp->batch;
638  $product_lot_static->fk_product = $objp->rowid;
639  $product_lot_static->id = $objp->lotid;
640  $product_lot_static->eatby = $objp->eatby;
641  $product_lot_static->sellby = $objp->sellby;
642 
643 
644  $warehousetmp->id = $objp->fk_entrepot;
645  $warehousetmp->ref = $objp->warehouse_ref;
646  $warehousetmp->label = $objp->warehouse_ref;
647  $warehousetmp->fk_parent = $objp->warehouse_parent;
648 
649  print '<tr>';
650 
651  // Ref
652  print '<td class="nowrap">';
653  print $product_static->getNomUrl(1, '', 16);
654  //if ($objp->stock_theorique < $objp->seuil_stock_alerte) print ' '.img_warning($langs->trans("StockTooLow"));
655  print '</td>';
656 
657  // Label
658  print '<td>'.$objp->label.'</td>';
659 
660  if (isModEnabled("service") && $type == 1) {
661  print '<td class="center">';
662  $regs = array();
663  if (preg_match('/([0-9]+)y/i', $objp->duration, $regs)) {
664  print $regs[1].' '.$langs->trans("DurationYear");
665  } elseif (preg_match('/([0-9]+)m/i', $objp->duration, $regs)) {
666  print $regs[1].' '.$langs->trans("DurationMonth");
667  } elseif (preg_match('/([0-9]+)d/i', $objp->duration, $regs)) {
668  print $regs[1].' '.$langs->trans("DurationDay");
669  } else {
670  print $objp->duration;
671  }
672  print '</td>';
673  }
674  //print '<td class="right">'.$objp->stock_theorique.'</td>';
675  //print '<td class="right">'.$objp->seuil_stock_alerte.'</td>';
676  //print '<td class="right">'.$objp->desiredstock.'</td>';
677 
678  // Warehouse
679  print '<td class="nowrap">';
680  if ($objp->fk_entrepot > 0) {
681  print $warehousetmp->getNomUrl(1);
682  }
683  print '</td>';
684 
685  // Lot
686  print '<td class="center nowrap">';
687  if ($product_lot_static->batch) {
688  print $product_lot_static->getNomUrl(1);
689  }
690  print '</td>';
691 
692  if (empty($conf->global->PRODUCT_DISABLE_SELLBY)) {
693  print '<td class="center">'.dol_print_date($db->jdate($objp->sellby), 'day').'</td>';
694  }
695 
696  if (empty($conf->global->PRODUCT_DISABLE_EATBY)) {
697  print '<td class="center">'.dol_print_date($db->jdate($objp->eatby), 'day').'</td>';
698  }
699 
700  print '<td class="right">';
701  //if ($objp->seuil_stock_alerte && ($objp->stock_physique < $objp->seuil_stock_alerte)) print img_warning($langs->trans("StockTooLow")).' ';
702  print $objp->stock_physique;
703  print '</td>';
704 
705  print '<td class="right">';
706  print img_picto($langs->trans("StockMovement"), 'movement', 'class="pictofixedwidth"');
707  print '<a href="'.DOL_URL_ROOT.'/product/stock/movement_list.php?idproduct='.$product_static->id.'&search_warehouse='.$objp->fk_entrepot.'&search_batch='.($objp->batch != 'Undefined' ? $objp->batch : 'Undefined').'">'.$langs->trans("Movements").'</a>';
708  print '</td>';
709 
710  print '<td class="right nowrap">'.$product_static->LibStatut($objp->statut, 5, 0).'</td>';
711 
712  print '<td class="right nowrap">'.$product_static->LibStatut($objp->tobuy, 5, 1).'</td>';
713 
714  print '<td></td>';
715 
716  print "</tr>\n";
717  $i++;
718 }
719 
720 $db->free($resql);
721 
722 print '</table>'."\n";
723 print '</div>'."\n";
724 
725 print '</form>'."\n";
726 
727 
728 // End of page
729 llxFooter();
730 $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 warehouses.
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 to manage products or services.
Class with list of lots and properties.
if(isModEnabled('facture') &&!empty($user->rights->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') &&!empty($user->rights->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)) $resql
Social contributions to pay.
Definition: index.php:745
if($cancel &&! $id) if($action=='add' &&! $cancel) if($action=='delete') if($id) $form
Actions.
Definition: card.php:143
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed informations (by default a local PHP server timestamp) Re...
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...
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='')
Set event messages in dol_events session object.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
dol_now($mode='auto')
Return date for now.
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.
$nbtotalofrecords
Count total nb of records.
Definition: list.php:329
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.