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