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