dolibarr 19.0.3
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 * Copyright (C) 2021 Noé Cendrier <noe.cendrier@altairis.fr>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see <https://www.gnu.org/licenses/>.
23 */
24
31// Load Dolibarr environment
32require '../main.inc.php';
33require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
34require_once DOL_DOCUMENT_ROOT.'/product/stock/class/productlot.class.php';
35require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
36require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
37require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
38require_once DOL_DOCUMENT_ROOT.'/product/stock/class/productlot.class.php';
39
40// Load translation files required by the page
41$langs->loadLangs(array('products', 'stocks', 'productbatch', 'categories'));
42
43$action = GETPOST('action', 'aZ09') ? GETPOST('action', 'aZ09') : 'view'; // The action 'add', 'create', 'edit', 'update', 'view', ...
44$massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choice into lists)
45$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'myobjectlist'; // To manage different context of search
46$backtopage = GETPOST('backtopage', 'alpha'); // Go back to a dedicated page
47$optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print')
48$mode = GETPOST('mode', 'aZ');
49
50$sref = GETPOST("sref", 'alpha');
51$snom = GETPOST("snom", 'alpha');
52$search_all = trim((GETPOST('search_all', 'alphanohtml') != '') ? GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml'));
53$type = GETPOSTISSET('type') ? GETPOST('type', 'int') : Product::TYPE_PRODUCT;
54$search_barcode = GETPOST("search_barcode", 'alpha');
55$search_warehouse = GETPOST('search_warehouse', 'alpha');
56$search_batch = GETPOST('search_batch', 'alpha');
57$search_toolowstock = GETPOST('search_toolowstock');
58$search_subjecttolotserial = GETPOST('search_subjecttolotserial');
59$tosell = GETPOST("tosell");
60$tobuy = GETPOST("tobuy");
61$fourn_id = GETPOST("fourn_id", 'int');
62$sbarcode = GETPOST("sbarcode", 'int');
63$search_stock_physique = GETPOST('search_stock_physique', 'alpha');
64
65// Load variable for pagination
66$limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit;
67$sortfield = GETPOST('sortfield', 'aZ09comma');
68$sortorder = GETPOST('sortorder', 'aZ09comma');
69$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int');
70if (empty($page) || $page < 0 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha')) {
71 // If $page is not defined, or '' or -1 or if we click on clear filters
72 $page = 0;
73}
74$offset = $limit * $page;
75$pageprev = $page - 1;
76$pagenext = $page + 1;
77
78// Initialize array of search criterias
79$object = new Product($db);
80$search_sale = GETPOST("search_sale");
81if (GETPOSTISSET('catid')) {
82 $search_categ = GETPOST('catid', 'int');
83} else {
84 $search_categ = GETPOST('search_categ', 'int');
85}
86$search_warehouse_categ = GETPOST('search_warehouse_categ', 'int');
87
88// Fetch optionals attributes and labels
89$extrafields->fetch_name_optionals_label($object->table_element);
90//$extrafields->fetch_name_optionals_label($object->table_element_line);
91
92$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_');
93
94// Default sort order (if not yet defined by previous GETPOST)
95if (!$sortfield) {
96 reset($object->fields); // Reset is required to avoid key() to return null.
97 $sortfield = "p.".key($object->fields); // Set here default search field. By default 1st field in definition.
98}
99if (!$sortorder) {
100 $sortorder = "ASC";
101}
102
103
104// Initialize array of search criterias
105$search = array();
106foreach ($object->fields as $key => $val) {
107 if (GETPOST('search_'.$key, 'alpha') !== '') {
108 $search[$key] = GETPOST('search_'.$key, 'alpha');
109 }
110 if (preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
111 $search[$key.'_dtstart'] = dol_mktime(0, 0, 0, GETPOST('search_'.$key.'_dtstartmonth', 'int'), GETPOST('search_'.$key.'_dtstartday', 'int'), GETPOST('search_'.$key.'_dtstartyear', 'int'));
112 $search[$key.'_dtend'] = dol_mktime(23, 59, 59, GETPOST('search_'.$key.'_dtendmonth', 'int'), GETPOST('search_'.$key.'_dtendday', 'int'), GETPOST('search_'.$key.'_dtendyear', 'int'));
113 }
114}
115$key = 'sellby';
116$search[$key.'_dtstart'] = dol_mktime(0, 0, 0, GETPOST('search_'.$key.'_dtstartmonth', 'int'), GETPOST('search_'.$key.'_dtstartday', 'int'), GETPOST('search_'.$key.'_dtstartyear', 'int'));
117$search[$key.'_dtend'] = dol_mktime(23, 59, 59, GETPOST('search_'.$key.'_dtendmonth', 'int'), GETPOST('search_'.$key.'_dtendday', 'int'), GETPOST('search_'.$key.'_dtendyear', 'int'));
118$key = 'eatby';
119$search[$key.'_dtstart'] = dol_mktime(0, 0, 0, GETPOST('search_'.$key.'_dtstartmonth', 'int'), GETPOST('search_'.$key.'_dtstartday', 'int'), GETPOST('search_'.$key.'_dtstartyear', 'int'));
120$search[$key.'_dtend'] = dol_mktime(23, 59, 59, GETPOST('search_'.$key.'_dtendmonth', 'int'), GETPOST('search_'.$key.'_dtendday', 'int'), GETPOST('search_'.$key.'_dtendyear', 'int'));
121
122// Get object canvas (By default, this is not defined, so standard usage of dolibarr)
123$canvas = GETPOST("canvas");
124$objcanvas = null;
125if (!empty($canvas)) {
126 require_once DOL_DOCUMENT_ROOT.'/core/class/canvas.class.php';
127 $objcanvas = new Canvas($db, $action);
128 $objcanvas->getCanvas('product', 'list', $canvas);
129}
130
131// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
132$hookmanager->initHooks(array('reassortlotlist'));
133
134// Security check
135if ($user->socid) {
136 $socid = $user->socid;
137}
138$result = restrictedArea($user, 'produit|service', 0, 'product&product');
139
140// Definition of array of fields for columns
141$arrayfields = array(
142 array('type'=>'varchar', 'label'=>'Ref', 'checked'=>1, 'enabled'=>1, 'position'=>1),
143 array('type'=>'varchar', 'label'=>'Label', 'checked'=>1, 'enabled'=>1, 'position'=>1),
144 array('type'=>'int', 'label'=>'Warehouse', 'checked'=>1, 'enabled'=>1, 'position'=>1),
145 array('type'=>'varchar', 'label'=>'Lot', 'checked'=>1, 'enabled'=>1, 'position'=>1),
146 array('type'=>'varchar', 'label'=>'DLC', 'checked'=>1, 'enabled'=>1, 'position'=>1),
147 array('type'=>'varchar', 'label'=>'DLUO', 'checked'=>1, 'enabled'=>1, 'position'=>1),
148 array('type'=>'int', 'label'=>'Stock', 'checked'=>1, 'enabled'=>1, 'position'=>1),
149 array('type'=>'int', 'label'=>'StatusSell', 'checked'=>1, 'enabled'=>1, 'position'=>1),
150 array('type'=>'int', 'label'=>'StatusBuy', 'checked'=>1, 'enabled'=>1, 'position'=>1),
151);
152
153//$arrayfields['anotherfield'] = array('type'=>'integer', 'label'=>'AnotherField', 'checked'=>1, 'enabled'=>1, 'position'=>90, 'csslist'=>'right');
154$arrayfields = dol_sort_array($arrayfields, 'position');
155
156
157
158/*
159 * Actions
160 */
161
162if (GETPOST('cancel', 'alpha')) {
163 $action = 'list';
164 $massaction = '';
165}
166if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') {
167 $massaction = '';
168}
169
170$parameters = array();
171$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
172if ($reshook < 0) {
173 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
174}
175
176if (empty($reshook)) {
177 // Selection of new fields
178 include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
179
180 // Purge search criteria
181 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
182 foreach ($object->fields as $key => $val) {
183 $search[$key] = '';
184 if (preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
185 $search[$key.'_dtstart'] = '';
186 $search[$key.'_dtend'] = '';
187 }
188 }
189 $search['sellby_dtstart'] = '';
190 $search['eatby_dtstart'] = '';
191 $search['sellby_dtend'] = '';
192 $search['eatby_dtend'] = '';
193 $sref = "";
194 $snom = "";
195 $search_all = "";
196 $tosell = "";
197 $tobuy = "";
198 $search_sale = "";
199 $search_categ = "";
200 $search_warehouse_categ = "";
201 $search_toolowstock = '';
202 $search_subjecttolotserial = '';
203 $search_batch = '';
204 $search_warehouse = '';
205 $fourn_id = '';
206 $sbarcode = '';
207 $search_stock_physique = '';
208 $toselect = array();
209 $search_array_options = array();
210 }
211 if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')
212 || GETPOST('button_search_x', 'alpha') || GETPOST('button_search.x', 'alpha') || GETPOST('button_search', 'alpha')) {
213 $massaction = ''; // Protection to avoid mass action if we force a new search during a mass action confirmation
214 }
215
216 // Mass actions
217 /*$objectclass = 'MyObject';
218 $objectlabel = 'MyObject';
219 $uploaddir = $conf->mymodule->dir_output;
220 include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php';
221 */
222}
223
224
225
226/*
227 * View
228 */
229
230$form = new Form($db);
231$htmlother = new FormOther($db);
232
233$now = dol_now();
234
235$helpurl = 'EN:Module_Stocks_En|FR:Module_Stock|ES:M&oacute;dulo_Stocks';
236$title = $langs->trans("ProductsAndServices");
237$morejs = array();
238$morecss = array();
239
240$sql = 'SELECT p.rowid, p.ref, p.label, p.barcode, p.price, p.price_ttc, p.price_base_type, p.entity,';
241$sql .= ' p.fk_product_type, p.tms as datem,';
242$sql .= ' p.duration, p.tosell as statut, p.tobuy, p.seuil_stock_alerte, p.desiredstock, p.stock, p.tosell, p.tobuy, p.tobatch,';
243$sql .= ' ps.fk_entrepot, ps.reel,';
244$sql .= ' e.ref as warehouse_ref, e.lieu as warehouse_lieu, e.fk_parent as warehouse_parent,';
245$sql .= ' pb.batch, pb.eatby as oldeatby, pb.sellby as oldsellby,';
246$sql .= ' pl.rowid as lotid, pl.eatby, pl.sellby,';
247$sql .= ' SUM(pb.qty) as stock_physique, COUNT(pb.rowid) as nbinbatchtable';
248// Add fields from hooks
249$parameters = array();
250$reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object); // Note that $action and $object may have been modified by hook
251$sql .= $hookmanager->resPrint;
252$sql .= ' FROM '.MAIN_DB_PREFIX.'product as p';
253$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_stock as ps on p.rowid = ps.fk_product'; // Detail for each warehouse
254$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'entrepot as e on ps.fk_entrepot = e.rowid'; // Link on unique key
255$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_batch as pb on pb.fk_product_stock = ps.rowid'; // Detail for each lot on each warehouse
256$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
257// Add table from hooks
258$parameters = array();
259$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object); // Note that $action and $object may have been modified by hook
260$sql .= $hookmanager->resPrint;
261$sql .= " WHERE p.entity IN (".getEntity('product').") AND e.entity IN (".getEntity('stock').")";
262if (!empty($search_categ) && $search_categ != '-1') {
263 $sql .= " AND ";
264 if ($search_categ == -2) {
265 $sql .= " NOT EXISTS ";
266 } else {
267 $sql .= " EXISTS ";
268 }
269 $sql .= "(";
270 $sql .= " SELECT cp.fk_categorie, cp.fk_product";
271 $sql .= " FROM " . MAIN_DB_PREFIX . "categorie_product as cp";
272 $sql .= " WHERE cp.fk_product = p.rowid"; // Join for the needed table to filter by categ
273 if ($search_categ > 0) {
274 $sql .= " AND cp.fk_categorie = " . ((int) $search_categ);
275 }
276 $sql .= ")";
277}
278if (!empty($search_warehouse_categ) && $search_warehouse_categ != '-1') {
279 $sql .= " AND ";
280 if ($search_warehouse_categ == -2) {
281 $sql .= " NOT EXISTS ";
282 } else {
283 $sql .= " EXISTS ";
284 }
285 $sql .= "(";
286 $sql .= " SELECT cp.fk_categorie, cp.fk_warehouse";
287 $sql .= " FROM " . MAIN_DB_PREFIX . "categorie_warehouse as cp";
288 $sql .= " WHERE cp.fk_warehouse = e.rowid"; // Join for the needed table to filter by categ
289 if ($search_warehouse_categ > 0) {
290 $sql .= " AND cp.fk_categorie = " . ((int) $search_warehouse_categ);
291 }
292 $sql .= ")";
293}
294if ($search_all) {
295 $sql .= natural_search(array('p.ref', 'p.label', 'p.description', 'p.note'), $search_all);
296}
297// if the type is not 1, we show all products (type = 0,2,3)
298if (dol_strlen($type)) {
299 if ($type == 1) {
300 $sql .= " AND p.fk_product_type = '1'";
301 } else {
302 $sql .= " AND p.fk_product_type <> '1'";
303 }
304}
305if ($search_subjecttolotserial) {
306 $sql .= " AND p.tobatch > 0";
307}
308if ($sref) {
309 $sql .= natural_search("p.ref", $sref);
310}
311if ($search_barcode) {
312 $sql .= natural_search("p.barcode", $search_barcode);
313}
314if ($snom) {
315 $sql .= natural_search("p.label", $snom);
316}
317if (!empty($tosell)) {
318 $sql .= " AND p.tosell = ".((int) $tosell);
319}
320if (!empty($tobuy)) {
321 $sql .= " AND p.tobuy = ".((int) $tobuy);
322}
323if (!empty($canvas)) {
324 $sql .= " AND p.canvas = '".$db->escape($canvas)."'";
325}
326if ($fourn_id > 0) {
327 $sql .= " AND p.rowid = pf.fk_product AND pf.fk_soc = ".((int) $fourn_id);
328}
329if ($search_warehouse) {
330 $sql .= natural_search("e.ref", $search_warehouse);
331}
332if ($search_batch) {
333 $sql .= natural_search("pb.batch", $search_batch);
334}
335
336foreach ($search as $key => $val) {
337 if (array_key_exists($key, $object->fields)) {
338 if ($key == 'status' && $search[$key] == -1) {
339 continue;
340 }
341 $mode_search = (($object->isInt($object->fields[$key]) || $object->isFloat($object->fields[$key])) ? 1 : 0);
342 if ((strpos($object->fields[$key]['type'], 'integer:') === 0) || (strpos($object->fields[$key]['type'], 'sellist:') === 0) || !empty($object->fields[$key]['arrayofkeyval'])) {
343 if ($search[$key] == '-1' || ($search[$key] === '0' && (empty($object->fields[$key]['arrayofkeyval']) || !array_key_exists('0', $object->fields[$key]['arrayofkeyval'])))) {
344 $search[$key] = '';
345 }
346 $mode_search = 2;
347 }
348 if ($search[$key] != '') {
349 $sql .= natural_search("t.".$db->escape($key), $search[$key], (($key == 'status') ? 2 : $mode_search));
350 }
351 } else {
352 if (preg_match('/(_dtstart|_dtend)$/', $key) && $search[$key] != '') {
353 $columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key);
354 if ($columnName == 'eatby' || $columnName == 'sellby') {
355 if (preg_match('/_dtstart$/', $key)) {
356 $sql .= " AND pl.".$db->escape($columnName)." >= '".$db->idate($search[$key])."'";
357 }
358 if (preg_match('/_dtend$/', $key)) {
359 $sql .= " AND pl.".$db->escape($columnName)." <= '".$db->idate($search[$key])."'";
360 }
361 }
362 }
363 }
364}
365// Add where from hooks
366$parameters = array();
367$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object); // Note that $action and $object may have been modified by hook
368$sql .= $hookmanager->resPrint;
369
370$sql .= " GROUP BY p.rowid, p.ref, p.label, p.barcode, p.price, p.price_ttc, p.price_base_type, p.entity,";
371$sql .= " p.fk_product_type, p.tms,";
372$sql .= " p.duration, p.tosell, p.tobuy, p.seuil_stock_alerte, p.desiredstock, p.stock, p.tosell, p.tobuy, p.tobatch,";
373$sql .= " ps.fk_entrepot, ps.reel,";
374$sql .= " e.ref, e.lieu, e.fk_parent,";
375$sql .= " pb.batch, pb.eatby, pb.sellby,";
376$sql .= " pl.rowid, pl.eatby, pl.sellby";
377// Add GROUP BY from hooks
378$parameters = array();
379$reshook = $hookmanager->executeHooks('printFieldListGroupBy', $parameters, $object); // Note that $action and $object may have been modified by hook
380$sql .= $hookmanager->resPrint;
381$sql_having = '';
382if ($search_toolowstock) {
383 $sql_having .= " HAVING SUM(".$db->ifsql('ps.reel IS NULL', '0', 'ps.reel').") < p.seuil_stock_alerte"; // Not used yet
384}
385if ($search_stock_physique != '') {
386 $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);
387 $natural_search_physique = " " . substr($natural_search_physique, 1, -1); // remove first "(" and last ")" characters
388 if (!empty($sql_having)) {
389 $sql_having .= " AND";
390 } else {
391 $sql_having .= " HAVING";
392 }
393 $sql_having .= $natural_search_physique;
394}
395// Add HAVING from hooks
396$parameters = array();
397$reshook = $hookmanager->executeHooks('printFieldListHaving', $parameters, $object); // Note that $action and $object may have been modified by hook
398if (!empty($hookmanager->resPrint)) {
399 if (!empty($sql_having)) {
400 $sql_having .= " AND";
401 } else {
402 $sql_having .= " HAVING";
403 }
404 $sql_having .= $hookmanager->resPrint;
405}
406if (!empty($sql_having)) {
407 $sql .= $sql_having;
408}
409
410//print $sql;
411
412// Count total nb of records
413$nbtotalofrecords = '';
414if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
415 $resql = $db->query($sql);
416 $nbtotalofrecords = $db->num_rows($resql);
417
418 if (($page * $limit) > $nbtotalofrecords) { // if total of record found is smaller than page * limit, goto and load page 0
419 $page = 0;
420 $offset = 0;
421 }
422 $db->free($resql);
423}
424
425// Complete request and execute it with limit
426$sql .= $db->order($sortfield, $sortorder);
427if ($limit) {
428 $sql .= $db->plimit($limit + 1, $offset);
429}
430
431$resql = $db->query($sql);
432if (!$resql) {
433 dol_print_error($db);
434 exit;
435}
436
437$num = $db->num_rows($resql);
438
439$i = 0;
440
441if ($num == 1 && GETPOST('autojumpifoneonly') && ($search_all || $snom || $sref)) {
442 $objp = $db->fetch_object($resql);
443 header("Location: card.php?id=$objp->rowid");
444 exit;
445}
446
447if (isset($type)) {
448 if ($type == 1) {
449 $texte = $langs->trans("Services");
450 } else {
451 $texte = $langs->trans("Products");
452 }
453} else {
454 $texte = $langs->trans("ProductsAndServices");
455}
456$texte .= ' ('.$langs->trans("StocksByLotSerial").')';
457
458$param = '';
459if (!empty($mode)) {
460 $param .= '&mode='.urlencode($mode);
461}
462if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
463 $param .= '&contextpage='.urlencode($contextpage);
464}
465if ($limit > 0 && $limit != $conf->liste_limit) {
466 $param .= '&limit='.((int) $limit);
467}
468foreach ($search as $key => $val) {
469 if (is_array($search[$key]) && count($search[$key])) {
470 foreach ($search[$key] as $skey) {
471 if ($skey != '') {
472 $param .= '&search_'.$key.'[]='.urlencode($skey);
473 }
474 }
475 } elseif ($search[$key] != '') {
476 $param .= '&search_'.$key.'='.urlencode($search[$key]);
477 }
478}
479if ($optioncss != '') {
480 $param .= '&optioncss='.urlencode($optioncss);
481}
482if ($search_all) {
483 $param .= "&search_all=".urlencode($search_all);
484}
485if ($tosell) {
486 $param .= "&tosell=".urlencode($tosell);
487}
488if ($tobuy) {
489 $param .= "&tobuy=".urlencode($tobuy);
490}
491if ($type != '') {
492 $param .= "&type=".urlencode($type);
493}
494if ($fourn_id) {
495 $param .= "&fourn_id=".urlencode($fourn_id);
496}
497if ($snom) {
498 $param .= "&snom=".urlencode($snom);
499}
500if ($sref) {
501 $param .= "&sref=".urlencode($sref);
502}
503if ($search_batch) {
504 $param .= "&search_batch=".urlencode($search_batch);
505}
506if ($sbarcode) {
507 $param .= "&sbarcode=".urlencode($sbarcode);
508}
509if ($search_warehouse) {
510 $param .= "&search_warehouse=".urlencode($search_warehouse);
511}
512if ($search_toolowstock) {
513 $param .= "&search_toolowstock=".urlencode($search_toolowstock);
514}
515if ($search_subjecttolotserial) {
516 $param .= "&search_subjecttolotserial=".urlencode($search_subjecttolotserial);
517}
518if ($search_sale) {
519 $param .= "&search_sale=".urlencode($search_sale);
520}
521if (!empty($search_categ) && $search_categ != '-1') {
522 $param .= "&search_categ=".urlencode($search_categ);
523}
524if (!empty($search_warehouse_categ) && $search_warehouse_categ != '-1') {
525 $param .= "&search_warehouse_categ=".urlencode($search_warehouse_categ);
526}
527if ($search_stock_physique) {
528 $param .= '&search_stock_physique=' . urlencode($search_stock_physique);
529}
530/*if ($eatby) $param.="&eatby=".$eatby;
531if ($sellby) $param.="&sellby=".$sellby;*/
532
533llxHeader("", $title, $helpurl, $texte);
534
535print '<form id="searchFormList" action="'.$_SERVER["PHP_SELF"].'" method="POST" name="formulaire">'."\n";
536if ($optioncss != '') {
537 print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
538}
539print '<input type="hidden" name="token" value="'.newToken().'">';
540print '<input type="hidden" name="action" value="list">';
541print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
542print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
543print '<input type="hidden" name="type" value="'.$type.'">';
544print '<input type="hidden" name="page" value="'.$page.'">';
545print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
546print '<input type="hidden" name="mode" value="'.$mode.'">';
547
548print_barre_liste($texte, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'product', 0, '', '', $limit, 0, 0, 1);
549
550/*
551if ($search_categ > 0) {
552 print "<div id='ways'>";
553 $c = new Categorie($db);
554 $c->fetch($search_categ);
555 $ways = $c->print_all_ways(' &gt; ', 'product/reassortlot.php');
556 print " &gt; ".$ways[0]."<br>\n";
557 print "</div><br>";
558}
559*/
560
561// Filter on categories
562$moreforfilter = '';
563if (isModEnabled('categorie')) {
564 $moreforfilter .= '<div class="divsearchfield">';
565 $moreforfilter .= img_picto($langs->trans('ProductsCategoriesShort'), 'category', 'class="pictofixedwidth"');
566 $moreforfilter .= $htmlother->select_categories(Categorie::TYPE_PRODUCT, $search_categ, 'search_categ', 1, $langs->trans("ProductsCategoryShort"), 'maxwidth400');
567 $moreforfilter .= '</div>';
568}
569// Filter on warehouse categories
570if (isModEnabled('categorie')) {
571 $moreforfilter .= '<div class="divsearchfield">';
572 $moreforfilter .= img_picto($langs->trans('StockCategoriesShort'), 'category', 'class="pictofixedwidth"');
573 $moreforfilter .= $htmlother->select_categories(Categorie::TYPE_WAREHOUSE, $search_warehouse_categ, 'search_warehouse_categ', 1, $langs->trans("StockCategoriesShort"), 'maxwidth400');
574 $moreforfilter .= '</div>';
575}
576
577$moreforfilter.='<label for="search_subjecttolotserial">'.$langs->trans("SubjectToLotSerialOnly").' </label><input type="checkbox" id="search_subjecttolotserial" name="search_subjecttolotserial" value="1"'.($search_subjecttolotserial ? ' checked' : '').'>';
578
579
580if (!empty($moreforfilter)) {
581 print '<div class="liste_titre liste_titre_bydiv centpercent">';
582 print $moreforfilter;
583 $parameters = array();
584 $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters); // Note that $action and $object may have been modified by hook
585 print $hookmanager->resPrint;
586 print '</div>';
587}
588
589
590print '<div class="div-table-responsive">';
591print '<table class="tagtable nobottomiftotal liste'.($moreforfilter ? " listwithfilterbefore" : "").'">';
592
593// Fields title search
594// --------------------------------------------------------------------
595print '<tr class="liste_titre_filter">';
596// Action column
597if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
598 print '<td class="liste_titre maxwidthsearch">';
599 $searchpicto = $form->showFilterButtons();
600 print $searchpicto;
601 print '</td>';
602}
603print '<td class="liste_titre">';
604print '<input class="flat" type="text" name="sref" size="6" value="'.dol_escape_htmltag($sref).'">';
605print '</td>';
606print '<td class="liste_titre">';
607print '<input class="flat" type="text" name="snom" size="8" value="'.dol_escape_htmltag($snom).'">';
608print '</td>';
609if (isModEnabled("service") && $type == 1) {
610 print '<td class="liste_titre">';
611 print '&nbsp;';
612 print '</td>';
613}
614
615print '<td class="liste_titre"><input class="flat" type="text" name="search_warehouse" size="6" value="'.dol_escape_htmltag($search_warehouse).'"></td>';
616print '<td class="liste_titre center"><input class="flat" type="text" name="search_batch" size="6" value="'.dol_escape_htmltag($search_batch).'"></td>';
617if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
618 print '<td class="liste_titre center">';
619 $key = 'sellby';
620 print '<div class="nowrap">';
621 print $form->selectDate($search[$key.'_dtstart'] ? $search[$key.'_dtstart'] : '', "search_".$key."_dtstart", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From'));
622 print '</div>';
623 print '<div class="nowrap">';
624 print $form->selectDate($search[$key.'_dtend'] ? $search[$key.'_dtend'] : '', "search_".$key."_dtend", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to'));
625 print '</div>';
626 print '</td>';
627}
628if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
629 print '<td class="liste_titre center">';
630 $key = 'eatby';
631 print '<div class="nowrap">';
632 print $form->selectDate($search[$key.'_dtstart'] ? $search[$key.'_dtstart'] : '', "search_".$key."_dtstart", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From'));
633 print '</div>';
634 print '<div class="nowrap">';
635 print $form->selectDate($search[$key.'_dtend'] ? $search[$key.'_dtend'] : '', "search_".$key."_dtend", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to'));
636 print '</div>';
637 print '</td>';
638}
639// Physical stock
640print '<td class="liste_titre right">';
641print '<input class="flat" type="text" size="5" name="search_stock_physique" value="'.dol_escape_htmltag($search_stock_physique).'">';
642print '</td>';
643print '<td class="liste_titre">&nbsp;</td>';
644print '<td class="liste_titre">&nbsp;</td>';
645print '<td class="liste_titre">&nbsp;</td>';
646$parameters = array();
647$reshook = $hookmanager->executeHooks('printFieldListOption', $parameters); // Note that $action and $object may have been modified by hook
648print $hookmanager->resPrint;
649// Action column
650if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
651 print '<td class="liste_titre maxwidthsearch">';
652 $searchpicto = $form->showFilterButtons();
653 print $searchpicto;
654 print '</td>';
655}
656print '</tr>'."\n";
657
658$totalarray = array();
659$totalarray['nbfield'] = 0;
660
661// Fields title label
662// --------------------------------------------------------------------
663print '<tr class="liste_titre">';
664// Action column
665if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
667}
668print_liste_field_titre("Ref", $_SERVER["PHP_SELF"], "p.ref", '', $param, "", $sortfield, $sortorder);
669print_liste_field_titre("Label", $_SERVER["PHP_SELF"], "p.label", '', $param, "", $sortfield, $sortorder);
670if (isModEnabled("service") && $type == 1) {
671 print_liste_field_titre("Duration", $_SERVER["PHP_SELF"], "p.duration", '', $param, "", $sortfield, $sortorder, 'center ');
672}
673print_liste_field_titre("Warehouse", $_SERVER["PHP_SELF"], "e.ref", '', $param, "", $sortfield, $sortorder);
674//print_liste_field_titre("DesiredStock", $_SERVER["PHP_SELF"], "p.desiredstock",$param,"",'',$sortfield,$sortorder, 'right );
675print_liste_field_titre("Batch", $_SERVER["PHP_SELF"], "pb.batch", '', $param, "", $sortfield, $sortorder, 'center ');
676if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
677 print_liste_field_titre("SellByDate", $_SERVER["PHP_SELF"], "pl.sellby", '', $param, "", $sortfield, $sortorder, 'center ');
678}
679if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
680 print_liste_field_titre("EatByDate", $_SERVER["PHP_SELF"], "pl.eatby", '', $param, "", $sortfield, $sortorder, 'center ');
681}
682print_liste_field_titre("PhysicalStock", $_SERVER["PHP_SELF"], "stock_physique", '', $param, "", $sortfield, $sortorder, 'right ');
683// TODO Add info of running suppliers/customers orders
684//print_liste_field_titre("TheoreticalStock",$_SERVER["PHP_SELF"], "stock_theorique",$param,"",'',$sortfield,$sortorder, 'right ');
686print_liste_field_titre("ProductStatusOnSell", $_SERVER["PHP_SELF"], "p.tosell", "", $param, '', $sortfield, $sortorder, 'right ');
687print_liste_field_titre("ProductStatusOnBuy", $_SERVER["PHP_SELF"], "p.tobuy", "", $param, '', $sortfield, $sortorder, 'right ');
688// Hook fields
689$parameters = array('param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder);
690$reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters); // Note that $action and $object may have been modified by hook
691print $hookmanager->resPrint;
692if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
694}
695print "</tr>\n";
696
697$product_static = new Product($db);
698$product_lot_static = new Productlot($db);
699$warehousetmp = new Entrepot($db);
700
701// Loop on record
702// --------------------------------------------------------------------
703$i = 0;
704$savnbfield = $totalarray['nbfield'];
705$totalarray['nbfield'] = 0;
706$imaxinloop = ($limit ? min($num, $limit) : $num);
707while ($i < $imaxinloop) {
708 $objp = $db->fetch_object($resql);
709
710 // Multilangs
711 if (getDolGlobalInt('MAIN_MULTILANGS')) { // si l'option est active
712 // TODO Use a cache
713 $sql = "SELECT label";
714 $sql .= " FROM ".MAIN_DB_PREFIX."product_lang";
715 $sql .= " WHERE fk_product = ".((int) $objp->rowid);
716 $sql .= " AND lang = '".$db->escape($langs->getDefaultLang())."'";
717 $sql .= " LIMIT 1";
718
719 $result = $db->query($sql);
720 if ($result) {
721 $objtp = $db->fetch_object($result);
722 if (!empty($objtp->label)) {
723 $objp->label = $objtp->label;
724 }
725 }
726 }
727
728 $product_static->ref = $objp->ref;
729 $product_static->id = $objp->rowid;
730 $product_static->label = $objp->label;
731 $product_static->type = $objp->fk_product_type;
732 $product_static->entity = $objp->entity;
733 $product_static->status = $objp->tosell;
734 $product_static->status_buy = $objp->tobuy;
735 $product_static->status_batch = $objp->tobatch;
736
737 $product_lot_static->batch = $objp->batch;
738 $product_lot_static->fk_product = $objp->rowid;
739 $product_lot_static->id = $objp->lotid;
740 $product_lot_static->eatby = $objp->eatby;
741 $product_lot_static->sellby = $objp->sellby;
742
743
744 $warehousetmp->id = $objp->fk_entrepot;
745 $warehousetmp->ref = $objp->warehouse_ref;
746 $warehousetmp->label = $objp->warehouse_ref;
747 $warehousetmp->fk_parent = $objp->warehouse_parent;
748
749 print '<tr>';
750
751 // Action column
752 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
753 print '<td></td>';
754 if (!$i) {
755 $totalarray['nbfield']++;
756 }
757 }
758
759 // Ref
760 print '<td class="nowrap">';
761 print $product_static->getNomUrl(1, '', 16);
762 //if ($objp->stock_theorique < $objp->seuil_stock_alerte) print ' '.img_warning($langs->trans("StockTooLow"));
763 print '</td>';
764 if (!$i) {
765 $totalarray['nbfield']++;
766 }
767
768 // Label
769 print '<td>'.$objp->label.'</td>';
770 if (!$i) {
771 $totalarray['nbfield']++;
772 }
773
774 if (isModEnabled("service") && $type == 1) {
775 print '<td class="center">';
776 $regs = array();
777 if (preg_match('/([0-9]+)y/i', $objp->duration, $regs)) {
778 print $regs[1].' '.$langs->trans("DurationYear");
779 } elseif (preg_match('/([0-9]+)m/i', $objp->duration, $regs)) {
780 print $regs[1].' '.$langs->trans("DurationMonth");
781 } elseif (preg_match('/([0-9]+)d/i', $objp->duration, $regs)) {
782 print $regs[1].' '.$langs->trans("DurationDay");
783 } else {
784 print $objp->duration;
785 }
786 if (!$i) {
787 $totalarray['nbfield']++;
788 }
789 print '</td>';
790 }
791 //print '<td class="right">'.$objp->stock_theorique.'</td>';
792 //print '<td class="right">'.$objp->seuil_stock_alerte.'</td>';
793 //print '<td class="right">'.$objp->desiredstock.'</td>';
794
795 // Warehouse
796 print '<td class="nowrap">';
797 if ($objp->fk_entrepot > 0) {
798 print $warehousetmp->getNomUrl(1);
799 }
800 if (!$i) {
801 $totalarray['nbfield']++;
802 }
803 print '</td>';
804
805 // Lot
806 print '<td class="center nowrap">';
807 if ($product_lot_static->batch) {
808 print $product_lot_static->getNomUrl(1);
809 }
810 if (!$i) {
811 $totalarray['nbfield']++;
812 }
813 print '</td>';
814
815 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
816 print '<td class="center">'.dol_print_date($db->jdate($objp->sellby), 'day').'</td>';
817 if (!$i) {
818 $totalarray['nbfield']++;
819 }
820 }
821
822 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
823 print '<td class="center">'.dol_print_date($db->jdate($objp->eatby), 'day').'</td>';
824 if (!$i) {
825 $totalarray['nbfield']++;
826 }
827 }
828
829 print '<td class="right">';
830 //if ($objp->seuil_stock_alerte && ($objp->stock_physique < $objp->seuil_stock_alerte)) print img_warning($langs->trans("StockTooLow")).' ';
831 if (is_null($objp->stock_physique)) {
832 if (!empty($objp->reel)) {
833 if ($objp->reel < 0) {
834 print '<span class="warning">';
835 }
836 print price2num($objp->reel, 'MS');
837 if ($objp->reel < 0) {
838 print '</span>';
839 }
840 print($objp->stock_physique < 0 ? ' '.img_warning() : '');
841 }
842 } else {
843 if (!empty($objp->stock_physique)) {
844 if ($objp->stock_physique < 0) {
845 print '<span class="warning">';
846 }
847 print price2num($objp->stock_physique, 'MS');
848 if ($objp->stock_physique < 0) {
849 print '</span>';
850 }
851 print($objp->stock_physique < 0 ? ' '.img_warning() : (($objp->stock_physique > 1 && $objp->tobatch == 2) ? ' '.img_warning($langs->trans('IlligalQtyForSerialNumbers')) : ''));
852 }
853 }
854 print '</td>';
855 if (!$i) {
856 $totalarray['nbfield']++;
857 }
858
859 print '<td class="right">';
860 print img_picto($langs->trans("StockMovement"), 'movement', 'class="pictofixedwidth"');
861 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>';
862 print '</td>';
863 if (!$i) {
864 $totalarray['nbfield']++;
865 }
866
867 print '<td class="right nowrap">'.$product_static->LibStatut($objp->statut, 5, 0).'</td>';
868 if (!$i) {
869 $totalarray['nbfield']++;
870 }
871
872 print '<td class="right nowrap">'.$product_static->LibStatut($objp->tobuy, 5, 1).'</td>';
873 if (!$i) {
874 $totalarray['nbfield']++;
875 }
876
877 // Fields values from hook
878 $parameters = array('obj'=>$objp);
879 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $product); // Note that $action and $object may have been modified by hook
880 print $hookmanager->resPrint;
881
882 // Action column
883 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
884 print '<td></td>';
885 if (!$i) {
886 $totalarray['nbfield']++;
887 }
888 }
889
890 print "</tr>\n";
891 $i++;
892}
893
894// If no record found
895if ($num == 0) {
896 $colspan = 2;
897 foreach ($arrayfields as $key => $val) {
898 if (!empty($val['checked'])) {
899 $colspan++;
900 }
901 }
902 print '<tr><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
903}
904
905
906$db->free($resql);
907
908print '</table>'."\n";
909print '</div>'."\n";
910
911print '</form>'."\n";
912
913
914// End of page
915llxFooter();
916$db->close();
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader()
Empty header.
Definition wrapper.php:55
llxFooter()
Empty footer.
Definition wrapper.php:69
Class to manage canvas.
Class to manage 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.
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...
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.
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
dol_sort_array(&$array, $index, $order='asc', $natsort=0, $case_sensitive=0, $keepindex=0)
Advanced sort array by second index function, which produces ascending (default) or descending output...
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.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
print_barre_liste($titre, $page, $file, $options='', $sortfield='', $sortorder='', $morehtmlcenter='', $num=-1, $totalnboflines='', $picto='generic', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limit=-1, $hideselectlimit=0, $hidenavigation=0, $pagenavastextinput=0, $morehtmlrightbeforearrow='')
Print a title with navigation controls for pagination.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
getEntity($element, $shared=1, $currentobject=null)
Get list of entity id to use.
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.