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