dolibarr 21.0.0-beta
reassort.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2001-2006 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2004-2015 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) 2019 Juanjo Menent <jmenent@2byte.es>
8 * Copyright (C) 2023 Vincent de Grandpré <vincent@de-grandpre.quebec>
9 * Copyright (C) 2024 Frédéric France <frederic.france@free.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.'/core/class/html.formother.class.php';
35require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
36require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
37
46// Load translation files required by the page
47$langs->loadLangs(array('products', 'stocks'));
48
49$action = GETPOST('action', 'aZ09');
50$sref = GETPOST("sref", 'alpha');
51$snom = GETPOST("snom", 'alpha');
52$sall = trim(GETPOST('search_all', 'alphanohtml'));
53$type = GETPOSTISSET('type') ? GETPOSTINT('type') : Product::TYPE_PRODUCT;
54$search_barcode = GETPOST("search_barcode", 'alpha');
55$search_toolowstock = GETPOST('search_toolowstock');
56$tosell = GETPOST("tosell");
57$tobuy = GETPOST("tobuy");
58$fourn_id = GETPOSTINT("fourn_id");
59$sbarcode = GETPOSTINT("sbarcode");
60$search_stock_physique = GETPOST('search_stock_physique', 'alpha');
61
62$sortfield = GETPOST('sortfield', 'aZ09comma');
63$sortorder = GETPOST('sortorder', 'aZ09comma');
64$page = GETPOSTISSET('pageplusone') ? (GETPOSTINT('pageplusone') - 1) : GETPOSTINT("page");
65if (empty($page) || $page < 0) {
66 $page = 0;
67}
68if (!$sortfield) {
69 $sortfield = "p.ref";
70}
71if (!$sortorder) {
72 $sortorder = "ASC";
73}
74$limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit;
75if (empty($page) || $page == -1) {
76 $page = 0;
77} // If $page is not defined, or '' or -1
78$offset = $limit * $page;
79
80// Load sale and categ filters
81$search_sale = GETPOST("search_sale");
82if (GETPOSTISSET('catid')) {
83 $search_categ = GETPOSTINT('catid');
84} else {
85 $search_categ = GETPOSTINT('search_categ');
86}
87
88// Get object canvas (By default, this is not defined, so standard usage of dolibarr)
89$canvas = GETPOST("canvas");
90$objcanvas = null;
91if (!empty($canvas)) {
92 require_once DOL_DOCUMENT_ROOT.'/core/class/canvas.class.php';
93 $objcanvas = new Canvas($db, $action);
94 $objcanvas->getCanvas('product', 'list', $canvas);
95}
96
97// Define virtualdiffersfromphysical
98$virtualdiffersfromphysical = 0;
99if (getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT')
100 || getDolGlobalString('STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER')
101 || getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT_CLOSE')
102 || getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION')
103 || getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION_CLOSE')
104 || isModEnabled('mrp')) {
105 $virtualdiffersfromphysical = 1; // According to increase/decrease stock options, virtual and physical stock may differs.
106}
107
108// Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
109$hookmanager->initHooks(array('productreassortlist'));
110
111if ($user->socid) {
112 $socid = $user->socid;
113}
114$result = restrictedArea($user, 'produit|service', 0, 'product&product');
115$result = restrictedArea($user, 'stock');
116
117$object = new Product($db);
118
119
120/*
121 * Actions
122 */
123
124if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers
125 $sref = "";
126 $snom = "";
127 $sall = "";
128 $tosell = "";
129 $tobuy = "";
130 $search_sale = "";
131 $search_categ = "";
132 $search_toolowstock = '';
133 $fourn_id = '';
134 $sbarcode = '';
135 $search_stock_physique = '';
136}
137
138
139
140/*
141 * View
142 */
143
144$helpurl = 'EN:Module_Stocks_En|FR:Module_Stock|ES:M&oacute;dulo_Stocks';
145
146$form = new Form($db);
147$htmlother = new FormOther($db);
148if (!empty($objp->stock_physique) && $objp->stock_physique < 0) {
149 print '<span class="warning">';
150}
151
152$sql = 'SELECT p.rowid, p.ref, p.label, p.barcode, p.price, p.price_ttc, p.price_base_type, p.entity,';
153$sql .= ' p.fk_product_type, p.tms as datem,';
154$sql .= ' p.duration, p.tosell as statut, p.tobuy, p.seuil_stock_alerte, p.desiredstock,';
155if (getDolGlobalString('PRODUCT_STOCK_LIST_SHOW_WITH_PRECALCULATED_DENORMALIZED_PHYSICAL_STOCK')) {
156 $sql .= ' p.stock as stock_physique';
157} else {
158 $sql .= ' SUM(s.reel) as stock_physique';
159}
160if (getDolGlobalString('PRODUCT_USE_UNITS')) {
161 $sql .= ', u.short_label as unit_short';
162}
163// Add fields from hooks
164$parameters = array();
165$reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object); // Note that $action and $object may have been modified by hook
166$sql .= $hookmanager->resPrint;
167$sql .= ' FROM '.MAIN_DB_PREFIX.'product as p';
168if (!getDolGlobalString('PRODUCT_STOCK_LIST_SHOW_WITH_PRECALCULATED_DENORMALIZED_PHYSICAL_STOCK')) {
169 $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'product_stock as s ON p.rowid = s.fk_product';
170}
171if (getDolGlobalString('PRODUCT_USE_UNITS')) {
172 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_units as u on p.fk_unit = u.rowid';
173}
174// Add table from hooks
175$parameters = array();
176$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object); // Note that $action and $object may have been modified by hook
177$sql .= $hookmanager->resPrint;
178$sql .= " WHERE p.entity IN (".getEntity('product').")";
179if (!empty($search_categ) && $search_categ != '-1') {
180 $sql .= " AND ";
181 if ($search_categ == -2) {
182 $sql .= " NOT EXISTS ";
183 } else {
184 $sql .= " EXISTS ";
185 }
186 $sql .= "(";
187 $sql .= " SELECT cp.fk_categorie, cp.fk_product";
188 $sql .= " FROM " . MAIN_DB_PREFIX . "categorie_product as cp";
189 $sql .= " WHERE cp.fk_product = p.rowid"; // Join for the needed table to filter by categ
190 if ($search_categ > 0) {
191 $sql .= " AND cp.fk_categorie = " . ((int) $search_categ);
192 }
193 $sql .= ")";
194}
195if (!getDolGlobalString('PRODUCT_STOCK_LIST_SHOW_WITH_PRECALCULATED_DENORMALIZED_PHYSICAL_STOCK')) {
196 if (!getDolGlobalString('PRODUCT_STOCK_LIST_SHOW_VIRTUAL_WITH_NO_PHYSICAL')) {
197 $sql .= " AND EXISTS (SELECT e.rowid FROM " . MAIN_DB_PREFIX . "entrepot as e WHERE e.rowid = s.fk_entrepot AND e.entity IN (" . getEntity('stock') . "))";
198 } else {
199 $sql .= " AND
200 (
201 EXISTS
202 (SELECT e.rowid
203 FROM " . MAIN_DB_PREFIX . "entrepot as e
204 WHERE e.rowid = s.fk_entrepot AND e.entity IN (" . getEntity('stock') . "))
205 OR (
206 SELECT SUM(cd1.qty) as qty
207 FROM " . MAIN_DB_PREFIX . "commande_fournisseurdet as cd1
208 LEFT JOIN " . MAIN_DB_PREFIX . "commande_fournisseur as c1
209 ON c1.rowid = cd1.fk_commande
210 WHERE c1.entity IN (1) AND cd1.fk_product = p.rowid AND c1.fk_statut in (3,4) AND cd1.qty <> 0
211 ) IS NOT NULL
212 OR (
213 SELECT SUM(cd2.qty) as qty
214 FROM " . MAIN_DB_PREFIX . "commandedet as cd2
215 LEFT JOIN " . MAIN_DB_PREFIX . "commande as c2 ON c2.rowid = cd2.fk_commande
216 WHERE c2.entity IN (1) AND cd2.fk_product = p.rowid AND c2.fk_statut in (1,2) AND cd2.qty <> 0
217 ) IS NOT NULL
218 OR (
219 SELECT SUM(ed3.qty) as qty
220 FROM " . MAIN_DB_PREFIX . "expeditiondet as ed3
221 LEFT JOIN " . MAIN_DB_PREFIX . "expedition as e3 ON e3.rowid = ed3.fk_expedition
222 LEFT JOIN " . MAIN_DB_PREFIX . "commandedet as cd3 ON ed3.fk_elementdet = cd3.rowid
223 LEFT JOIN " . MAIN_DB_PREFIX . "commande as c3 ON c3.rowid = cd3.fk_commande
224 WHERE e3.entity IN (1) AND cd3.fk_product = p.rowid AND c3.fk_statut IN (1,2) AND e3.fk_statut IN (1,2) AND ed3.qty <> 0
225 ) IS NOT NULL
226 OR (
227 SELECT SUM(mp4.qty) as qty
228 FROM " . MAIN_DB_PREFIX . "mrp_production as mp4
229 LEFT JOIN " . MAIN_DB_PREFIX . "mrp_mo as m4 ON m4.rowid = mp4.fk_mo AND m4.entity IN (1) AND m4.status IN (1,2)
230 WHERE mp4.fk_product = p.rowid AND mp4.qty <> 0
231 ) IS NOT NULL
232 ) ";
233 }
234}
235if ($sall) {
236 $sql .= natural_search(array('p.ref', 'p.label', 'p.description', 'p.note'), $sall);
237}
238// if the type is not 1, we show all products (type = 0,2,3)
239if (dol_strlen((string) $type)) {
240 if ($type == 1) {
241 $sql .= " AND p.fk_product_type = '1'";
242 } else {
243 $sql .= " AND p.fk_product_type <> '1'";
244 }
245}
246if ($sref) {
247 $sql .= natural_search('p.ref', $sref);
248}
249if ($search_barcode) {
250 $sql .= natural_search('p.barcode', $search_barcode);
251}
252if ($snom) {
253 $sql .= natural_search('p.label', $snom);
254}
255if (!empty($tosell)) {
256 $sql .= " AND p.tosell = ".((int) $tosell);
257}
258if (!empty($tobuy)) {
259 $sql .= " AND p.tobuy = ".((int) $tobuy);
260}
261if (!empty($canvas)) {
262 $sql .= " AND p.canvas = '".$db->escape($canvas)."'";
263}
264if ($fourn_id > 0) {
265 $sql .= " AND p.rowid = pf.fk_product AND pf.fk_soc = ".((int) $fourn_id);
266}
267if (getDolGlobalString('PRODUCT_STOCK_LIST_SHOW_WITH_PRECALCULATED_DENORMALIZED_PHYSICAL_STOCK')) {
268 if ($search_toolowstock) {
269 $sql .= " AND p.stock < p.seuil_stock_alerte";
270 }
271 if ($search_stock_physique != '') {
272 $sql .= natural_search('p.stock', $search_stock_physique, 1, 1);
273 }
274}
275// Add where from hooks
276$parameters = array();
277$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object); // Note that $action and $object may have been modified by hook
278$sql .= $hookmanager->resPrint;
279if (!getDolGlobalString('PRODUCT_STOCK_LIST_SHOW_WITH_PRECALCULATED_DENORMALIZED_PHYSICAL_STOCK')) {
280 $sql .= " GROUP BY p.rowid, p.ref, p.label, p.barcode, p.price, p.price_ttc, p.price_base_type, p.entity,";
281 $sql .= " p.fk_product_type, p.tms, p.duration, p.tosell, p.tobuy, p.seuil_stock_alerte, p.desiredstock";
282}
283
284// Add GROUP BY from hooks
285$parameters = array();
286$reshook = $hookmanager->executeHooks('printFieldListGroupBy', $parameters, $object); // Note that $action and $object may have been modified by hook
287$sql .= $hookmanager->resPrint;
288
289$sql_having = '';
290if (!getDolGlobalString('PRODUCT_STOCK_LIST_SHOW_WITH_PRECALCULATED_DENORMALIZED_PHYSICAL_STOCK')) {
291 if ($search_toolowstock) {
292 $sql_having .= " HAVING SUM(" . $db->ifsql('s.reel IS NULL', '0', 's.reel') . ") < p.seuil_stock_alerte";
293 }
294 if ($search_stock_physique != '') {
295 //$natural_search_physique = natural_search('HAVING SUM(' . $db->ifsql('s.reel IS NULL', '0', 's.reel') . ')', $search_stock_physique, 1, 1);
296 $natural_search_physique = natural_search('SUM(' . $db->ifsql('s.reel IS NULL', '0', 's.reel') . ')', $search_stock_physique, 1, 1);
297 $natural_search_physique = " " . substr($natural_search_physique, 1, -1); // remove first "(" and last ")" characters
298 if (!empty($sql_having)) {
299 $sql_having .= " AND";
300 } else {
301 $sql_having .= " HAVING";
302 }
303 $sql_having .= $natural_search_physique;
304 }
305}
306
307// Add HAVING from hooks
308$parameters = array();
309$reshook = $hookmanager->executeHooks('printFieldListHaving', $parameters, $object); // Note that $action and $object may have been modified by hook
310if (!empty($hookmanager->resPrint)) {
311 if (!empty($sql_having)) {
312 $sql_having .= " AND";
313 } else {
314 $sql_having .= " HAVING";
315 }
316 $sql_having .= $hookmanager->resPrint;
317}
318
319if (!empty($sql_having)) {
320 $sql .= $sql_having;
321}
322$sql .= $db->order($sortfield, $sortorder);
323
324// Count total nb of records
325$nbtotalofrecords = '';
326if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
327 $result = $db->query($sql);
328 $nbtotalofrecords = $db->num_rows($result);
329 if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller then paging size (filtering), goto and load page 0
330 $page = 0;
331 $offset = 0;
332 }
333}
334
335$sql .= $db->plimit($limit + 1, $offset);
336
337$resql = $db->query($sql);
338if ($resql) {
339 $num = $db->num_rows($resql);
340
341 $i = 0;
342
343 if ($num == 1 && GETPOST('autojumpifoneonly') && ($sall || $snom || $sref)) {
344 $objp = $db->fetch_object($resql);
345 header("Location: card.php?id=$objp->rowid");
346 exit;
347 }
348
349 if (isset($type)) {
350 if ($type == 1) {
351 $texte = $langs->trans("Services");
352 } else {
353 $texte = $langs->trans("Products");
354 }
355 } else {
356 $texte = $langs->trans("ProductsAndServices");
357 }
358 $texte .= ' ('.$langs->trans("MenuStocks").')';
359
360 $param = '';
361 if ($limit > 0 && $limit != $conf->liste_limit) {
362 $param .= '&limit='.((int) $limit);
363 }
364 if ($sall) {
365 $param .= "&sall=".urlencode($sall);
366 }
367 if ($tosell) {
368 $param .= "&tosell=".urlencode($tosell);
369 }
370 if ($tobuy) {
371 $param .= "&tobuy=".urlencode($tobuy);
372 }
373 if ($type != '') {
374 $param .= "&type=".urlencode((string) ($type));
375 }
376 if ($fourn_id) {
377 $param .= "&fourn_id=".urlencode((string) ($fourn_id));
378 }
379 if ($snom) {
380 $param .= "&snom=".urlencode($snom);
381 }
382 if ($sref) {
383 $param .= "&sref=".urlencode($sref);
384 }
385 if ($search_sale) {
386 $param .= "&search_sale=".urlencode($search_sale);
387 }
388 if ($search_categ > 0) {
389 $param .= "&search_categ=".urlencode((string) ($search_categ));
390 }
391 if ($search_toolowstock) {
392 $param .= "&search_toolowstock=".urlencode($search_toolowstock);
393 }
394 if ($sbarcode) {
395 $param .= "&sbarcode=".urlencode((string) ($sbarcode));
396 }
397 if ($search_stock_physique) {
398 $param .= '&search_stock_physique=' . urlencode($search_stock_physique);
399 }
400
401 llxHeader("", $texte, $helpurl, '', 0, 0, '', '', '', 'mod-product page-reassort');
402
403 print '<form action="'.$_SERVER["PHP_SELF"].'" method="post" name="formulaire">';
404 print '<input type="hidden" name="token" value="'.newToken().'">';
405 print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
406 print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
407 print '<input type="hidden" name="page" value="'.$page.'">';
408 print '<input type="hidden" name="type" value="'.$type.'">';
409
410 print_barre_liste($texte, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'product', 0, '', '', $limit);
411
412 if ($search_categ > 0) {
413 print "<div id='ways'>";
414 $c = new Categorie($db);
415 $c->fetch($search_categ);
416 $ways = $c->print_all_ways(' &gt; ', 'product/reassort.php');
417 print " &gt; ".$ways[0]."<br>\n";
418 print "</div><br>";
419 }
420
421 // Filter on categories
422 $moreforfilter = '';
423 if (isModEnabled('category')) {
424 $moreforfilter .= '<div class="divsearchfield">';
425 $moreforfilter .= img_picto($langs->trans('Categories'), 'category', 'class="pictofixedwidth"');
426 $moreforfilter .= $htmlother->select_categories(Categorie::TYPE_PRODUCT, $search_categ, 'search_categ', 1);
427 $moreforfilter .= '</div>';
428 }
429
430 $moreforfilter .= '<div class="divsearchfield">';
431 $moreforfilter .= '<label for="search_toolowstock">'.$langs->trans("StockTooLow").' </label><input type="checkbox" id="search_toolowstock" name="search_toolowstock" value="1"'.($search_toolowstock ? ' checked' : '').'>';
432 $moreforfilter .= '</div>';
433
434 print '<div class="liste_titre liste_titre_bydiv centpercent">';
435 print $moreforfilter;
436 $parameters = array();
437 $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
438 print $hookmanager->resPrint;
439 print '</div>';
440
441 $formProduct = new FormProduct($db);
442 $formProduct->loadWarehouses();
443 $warehouses_list = $formProduct->cache_warehouses;
444 $nb_warehouse = count($warehouses_list);
445 $colspan_warehouse = 1;
446 if (getDolGlobalString('STOCK_DETAIL_ON_WAREHOUSE')) {
447 $colspan_warehouse = $nb_warehouse > 1 ? $nb_warehouse + 1 : 1;
448 }
449
450 print '<div class="div-table-responsive">';
451 print '<table class="tagtable liste'.($moreforfilter ? " listwithfilterbefore" : "").'">';
452
453 // Fields title search
454 print '<tr class="liste_titre_filter">';
455 // Action column
456 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
457 print '<td class="liste_titre maxwidthsearch">';
458 $searchpicto = $form->showFilterAndCheckAddButtons(0);
459 print $searchpicto;
460 print '</td>';
461 }
462 print '<td class="liste_titre">';
463 print '<input class="flat" type="text" name="sref" size="6" value="'.$sref.'">';
464 print '</td>';
465 print '<td class="liste_titre">';
466 print '<input class="flat" type="text" name="snom" size="8" value="'.$snom.'">';
467 print '</td>';
468 // Duration
469 if (isModEnabled("service") && $type == 1) {
470 print '<td class="liste_titre">';
471 print '&nbsp;';
472 print '</td>';
473 }
474 // Stock limit
475 print '<td class="liste_titre">&nbsp;</td>';
476 print '<td class="liste_titre right">&nbsp;</td>';
477 // Physical stock
478 print '<td class="liste_titre right">';
479 print '<input class="flat" type="text" size="5" name="search_stock_physique" value="'.dol_escape_htmltag($search_stock_physique).'">';
480 print '</td>';
481 if ($virtualdiffersfromphysical) {
482 print '<td class="liste_titre">&nbsp;</td>';
483 }
484 print '<td class="liste_titre">&nbsp;</td>';
485 print '<td class="liste_titre" colspan="'.$colspan_warehouse.'">&nbsp;</td>';
486 print '<td class="liste_titre"></td>';
487 $parameters = array();
488 $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters); // Note that $action and $object may have been modified by hook
489 print $hookmanager->resPrint;
490 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
491 print '<td class="liste_titre maxwidthsearch">';
492 $searchpicto = $form->showFilterAndCheckAddButtons(0);
493 print $searchpicto;
494 print '</td>';
495 }
496 print '</tr>';
497
498 // Line for column titles
499 print '<tr class="liste_titre">';
500 // Action column
501 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
503 }
504 print_liste_field_titre("Ref", $_SERVER["PHP_SELF"], "p.ref", '', $param, "", $sortfield, $sortorder);
505 print_liste_field_titre("Label", $_SERVER["PHP_SELF"], "p.label", '', $param, "", $sortfield, $sortorder);
506 if (isModEnabled("service") && $type == 1) {
507 print_liste_field_titre("Duration", $_SERVER["PHP_SELF"], "p.duration", '', $param, "", $sortfield, $sortorder, 'center ');
508 }
509 print_liste_field_titre("StockLimit", $_SERVER["PHP_SELF"], "p.seuil_stock_alerte", '', $param, "", $sortfield, $sortorder, 'right ');
510 print_liste_field_titre("DesiredStock", $_SERVER["PHP_SELF"], "p.desiredstock", '', $param, "", $sortfield, $sortorder, 'right ');
511 print_liste_field_titre("PhysicalStock", $_SERVER["PHP_SELF"], "stock_physique", '', $param, "", $sortfield, $sortorder, 'right ');
512 // Details per warehouse
513 if (getDolGlobalString('STOCK_DETAIL_ON_WAREHOUSE')) { // TODO This should be moved into the selection of fields on page product/list (page product/stock will be removed and replaced with product/list with its own context)
514 if ($nb_warehouse > 1) {
515 foreach ($warehouses_list as &$wh) {
516 print_liste_field_titre($wh['label'], '', '', '', '', '', '', '', 'right ');
517 }
518 }
519 }
520 if ($virtualdiffersfromphysical) {
521 print_liste_field_titre("VirtualStock", $_SERVER["PHP_SELF"], "", '', $param, "", $sortfield, $sortorder, 'right ', 'VirtualStockDesc');
522 }
523 // Units
524 if (getDolGlobalString('PRODUCT_USE_UNITS')) {
525 print_liste_field_titre("Unit", $_SERVER["PHP_SELF"], "unit_short", '', $param, 'align="right"', $sortfield, $sortorder);
526 }
528 print_liste_field_titre("ProductStatusOnSell", $_SERVER["PHP_SELF"], "p.tosell", '', $param, "", $sortfield, $sortorder, 'right ');
529 print_liste_field_titre("ProductStatusOnBuy", $_SERVER["PHP_SELF"], "p.tobuy", '', $param, "", $sortfield, $sortorder, 'right ');
530 // Hook fields
531 $parameters = array('param' => $param, 'sortfield' => $sortfield, 'sortorder' => $sortorder);
532 $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters); // Note that $action and $object may have been modified by hook
533 print $hookmanager->resPrint;
534 // Action column
535 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
537 }
538 print "</tr>\n";
539
540 while ($i < min($num, $limit)) {
541 $objp = $db->fetch_object($resql);
542
543 $product = new Product($db);
544 $product->fetch($objp->rowid);
545 $product->load_stock();
546
547 print '<tr>';
548 // Action column
549 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
550 print '<td></td>';
551 }
552 print '<td class="nowrap">';
553 print $product->getNomUrl(1, '', 16);
554 //if ($objp->stock_theorique < $objp->seuil_stock_alerte) print ' '.img_warning($langs->trans("StockTooLow"));
555 print '</td>';
556 print '<td class="tdoverflowmax150" title="'.dol_escape_htmltag($product->label).'">'.dol_escape_htmltag($product->label).'</td>';
557
558 if (isModEnabled("service") && $type == 1) {
559 print '<td class="center">';
560 if (preg_match('/([0-9]+)y/i', $objp->duration, $regs)) {
561 print $regs[1].' '.$langs->trans("DurationYear");
562 } elseif (preg_match('/([0-9]+)m/i', $objp->duration, $regs)) {
563 print $regs[1].' '.$langs->trans("DurationMonth");
564 } elseif (preg_match('/([0-9]+)d/i', $objp->duration, $regs)) {
565 print $regs[1].' '.$langs->trans("DurationDay");
566 } else {
567 print $objp->duration;
568 }
569 print '</td>';
570 }
571 //print '<td class="right">'.$objp->stock_theorique.'</td>';
572 print '<td class="right">';
573 print $objp->seuil_stock_alerte;
574 print '</td>';
575 print '<td class="right">';
576 print $objp->desiredstock;
577 print '</td>';
578 // Real stock
579 print '<td class="right">';
580 if ($objp->seuil_stock_alerte != '' && ($objp->stock_physique < $objp->seuil_stock_alerte)) {
581 print img_warning($langs->trans("StockLowerThanLimit", $objp->seuil_stock_alerte)).' ';
582 }
583 if ($objp->stock_physique < 0) {
584 print '<span class="warning">';
585 }
586 print price(price2num($objp->stock_physique, 'MS'), 0, $langs, 1, 0);
587 if ($objp->stock_physique < 0) {
588 print '</span>';
589 }
590 print '</td>';
591
592 // Details per warehouse
593 if (getDolGlobalString('STOCK_DETAIL_ON_WAREHOUSE')) { // TODO This should be moved into the selection of fields on page product/list (page product/stock will be removed and replaced with product/list with its own context)
594 if ($nb_warehouse > 1) {
595 foreach ($warehouses_list as &$wh) {
596 print '<td class="right">';
597 print price(empty($product->stock_warehouse[$wh['id']]->real) ? 0 : price2num($product->stock_warehouse[$wh['id']]->real, 'MS'), 0, $langs, 1, 0);
598 print '</td>';
599 }
600 }
601 }
602
603 // Virtual stock
604 if ($virtualdiffersfromphysical) {
605 print '<td class="right">';
606 if ($objp->seuil_stock_alerte != '' && ($product->stock_theorique < (float) $objp->seuil_stock_alerte)) {
607 print img_warning($langs->trans("StockLowerThanLimit", $objp->seuil_stock_alerte)).' ';
608 }
609 if ($objp->stock_physique < 0) {
610 print '<span class="warning">';
611 }
612 print price(price2num($product->stock_theorique, 'MS'), 0, $langs, 1, 0);
613 if ($objp->stock_physique < 0) {
614 print '</span>';
615 }
616 print '</td>';
617 }
618 // Units
619 if (getDolGlobalString('PRODUCT_USE_UNITS')) {
620 print '<td class="left">'.dol_escape_htmltag($objp->unit_short).'</td>';
621 }
622 print '<td class="center nowraponall">';
623 print img_picto($langs->trans("StockMovement"), 'movement', 'class="pictofixedwidth"');
624 print '<a href="'.DOL_URL_ROOT.'/product/stock/movement_list.php?idproduct='.$product->id.'">'.$langs->trans("Movements").'</a>';
625 print '</td>';
626 print '<td class="right nowrap">'.$product->LibStatut($objp->statut, 5, 0).'</td>';
627 print '<td class="right nowrap">'.$product->LibStatut($objp->tobuy, 5, 1).'</td>';
628 // Fields from hook
629 $parameters = array('obj' => $objp);
630 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $product); // Note that $action and $object may have been modified by hook
631 print $hookmanager->resPrint;
632 // Action column
633 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
634 print '<td></td>';
635 }
636
637 print "</tr>\n";
638 $i++;
639 }
640
641 print "</table>";
642 print '</div>';
643
644 print '</form>';
645
646 $db->free($resql);
647} else {
648 dol_print_error($db);
649}
650
651// End of page
652llxFooter();
653$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 categories.
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 with static methods for building HTML components related to products Only components common to ...
Class to manage products or services.
llxFooter()
Footer empty.
Definition document.php:107
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.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
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.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
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.