dolibarr 23.0.3
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('__SUM_OF_REEL__', $search_stock_physique, 1, 1);
296 $natural_search_physique = " " . substr(str_replace('__SUM_OF_REEL__', 'SUM(COALESCE(s.reel, 0))', $natural_search_physique), 1, -1); // remove first "(" and last ")" characters
297 if (!empty($sql_having)) {
298 $sql_having .= " AND";
299 } else {
300 $sql_having .= " HAVING";
301 }
302 $sql_having .= $natural_search_physique;
303 }
304}
305
306// Add HAVING from hooks
307$parameters = array();
308$reshook = $hookmanager->executeHooks('printFieldListHaving', $parameters, $object); // Note that $action and $object may have been modified by hook
309if (empty($reshook)) {
310 if (empty($sql_having)) {
311 $sql_having .= " HAVING 1=1";
312 }
313 $sql_having .= $hookmanager->resPrint;
314} else {
315 $sql_having = $hookmanager->resPrint;
316}
317
318if (!empty($sql_having)) {
319 $sql .= $sql_having;
320}
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) > (int) $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('auto', '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 $colspan = 0;
447 if (getDolGlobalString('STOCK_DETAIL_ON_WAREHOUSE')) {
448 $colspan_warehouse = $nb_warehouse > 1 ? $nb_warehouse + 1 : 1;
449 }
450
451 print '<div class="div-table-responsive">';
452 print '<table class="tagtable liste'.($moreforfilter ? " listwithfilterbefore" : "").'">';
453
454 // Fields title search
455 print '<tr class="liste_titre_filter">';
456 // Action column
457 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
458 print '<td class="liste_titre maxwidthsearch">';
459 $searchpicto = $form->showFilterAndCheckAddButtons(0);
460 print $searchpicto;
461 print '</td>';
462 $colspan++;
463 }
464 print '<td class="liste_titre">';
465 print '<input class="flat" type="text" name="sref" size="6" value="'.$sref.'">';
466 print '</td>';
467 $colspan++;
468 print '<td class="liste_titre">';
469 print '<input class="flat" type="text" name="snom" size="8" value="'.$snom.'">';
470 print '</td>';
471 $colspan++;
472 // Duration
473 if (isModEnabled("service") && $type == 1) {
474 print '<td class="liste_titre">';
475 print '&nbsp;';
476 print '</td>';
477 $colspan++;
478 }
479 // Stock limit
480 print '<td class="liste_titre">&nbsp;</td>';
481 $colspan++;
482 print '<td class="liste_titre right">&nbsp;</td>';
483 $colspan++;
484 // Physical stock
485 print '<td class="liste_titre right">';
486 print '<input class="flat" type="text" size="5" name="search_stock_physique" value="'.dol_escape_htmltag($search_stock_physique).'">';
487 print '</td>';
488 $colspan++;
489 if ($virtualdiffersfromphysical) {
490 print '<td class="liste_titre">&nbsp;</td>';
491 $colspan++;
492 }
493 if (getDolGlobalString('PRODUCT_USE_UNITS')) {
494 print '<td class="liste_titre"></td>';
495 $colspan++;
496 }
497 $parameters = array();
498 $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters); // Note that $action and $object may have been modified by hook
499 print $hookmanager->resPrint;
500 print '<td class="liste_titre">&nbsp;</td>';
501 $colspan++;
502 print '<td class="liste_titre" colspan="'.$colspan_warehouse.'">&nbsp;</td>';
503 $colspan++;
504 print '<td class="liste_titre"></td>';
505 $colspan++;
506 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
507 print '<td class="liste_titre maxwidthsearch">';
508 $searchpicto = $form->showFilterAndCheckAddButtons(0);
509 print $searchpicto;
510 print '</td>';
511 $colspan++;
512 }
513 print '</tr>';
514
515 // Line for column titles
516 print '<tr class="liste_titre">';
517 // Action column
518 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
520 }
521 print_liste_field_titre("Ref", $_SERVER["PHP_SELF"], "p.ref", '', $param, "", $sortfield, $sortorder);
522 print_liste_field_titre("Label", $_SERVER["PHP_SELF"], "p.label", '', $param, "", $sortfield, $sortorder);
523 if (isModEnabled("service") && $type == 1) {
524 print_liste_field_titre("Duration", $_SERVER["PHP_SELF"], "p.duration", '', $param, "", $sortfield, $sortorder, 'center ');
525 }
526 print_liste_field_titre("StockLimit", $_SERVER["PHP_SELF"], "p.seuil_stock_alerte", '', $param, "", $sortfield, $sortorder, 'right ');
527 print_liste_field_titre("DesiredStock", $_SERVER["PHP_SELF"], "p.desiredstock", '', $param, "", $sortfield, $sortorder, 'right ');
528 print_liste_field_titre("PhysicalStock", $_SERVER["PHP_SELF"], "stock_physique", '', $param, "", $sortfield, $sortorder, 'right ');
529 // Details per warehouse
530 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)
531 if ($nb_warehouse > 1) {
532 foreach ($warehouses_list as &$wh) {
533 print_liste_field_titre($wh['label'], '', '', '', '', '', '', '', 'right ');
534 }
535 }
536 }
537 if ($virtualdiffersfromphysical) {
538 print_liste_field_titre("VirtualStock", $_SERVER["PHP_SELF"], "", '', $param, "", $sortfield, $sortorder, 'right ', 'VirtualStockDesc');
539 }
540 // Units
541 if (getDolGlobalString('PRODUCT_USE_UNITS')) {
542 print_liste_field_titre("Unit", $_SERVER["PHP_SELF"], "unit_short", '', $param, 'align="right"', $sortfield, $sortorder);
543 }
544 // Hook fields
545 $parameters = array('param' => $param, 'sortfield' => $sortfield, 'sortorder' => $sortorder);
546 $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters); // Note that $action and $object may have been modified by hook
547 print $hookmanager->resPrint;
549 print_liste_field_titre("ProductStatusOnSell", $_SERVER["PHP_SELF"], "p.tosell", '', $param, "", $sortfield, $sortorder, 'right ');
550 print_liste_field_titre("ProductStatusOnBuy", $_SERVER["PHP_SELF"], "p.tobuy", '', $param, "", $sortfield, $sortorder, 'right ');
551 // Action column
552 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
554 }
555 print "</tr>\n";
556
557 while ($i < min($num, $limit)) {
558 $objp = $db->fetch_object($resql);
559
560 $product = new Product($db);
561 $product->fetch($objp->rowid);
562 $product->load_stock();
563
564 print '<tr>';
565 // Action column
566 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
567 print '<td></td>';
568 }
569 print '<td class="tdoverflowmax250">';
570 print $product->getNomUrl(1);
571 //if ($objp->stock_theorique < $objp->seuil_stock_alerte) print ' '.img_warning($langs->trans("StockTooLow"));
572 print '</td>';
573 print '<td class="tdoverflowmax150" title="'.dol_escape_htmltag($product->label).'">'.dol_escape_htmltag($product->label).'</td>';
574
575 if (isModEnabled("service") && $type == 1) {
576 print '<td class="center">';
577 $regs = array();
578 if (preg_match('/([0-9]+)y/i', $objp->duration, $regs)) {
579 print $regs[1].' '.$langs->trans("DurationYear");
580 } elseif (preg_match('/([0-9]+)m/i', $objp->duration, $regs)) {
581 print $regs[1].' '.$langs->trans("DurationMonth");
582 } elseif (preg_match('/([0-9]+)d/i', $objp->duration, $regs)) {
583 print $regs[1].' '.$langs->trans("DurationDay");
584 } else {
585 print $objp->duration;
586 }
587 print '</td>';
588 }
589 //print '<td class="right">'.$objp->stock_theorique.'</td>';
590 print '<td class="right">';
591 print $objp->seuil_stock_alerte;
592 print '</td>';
593 print '<td class="right">';
594 print $objp->desiredstock;
595 print '</td>';
596 // Real stock
597 print '<td class="right">';
598 if ($objp->seuil_stock_alerte != '' && ($objp->stock_physique < $objp->seuil_stock_alerte)) {
599 print img_warning($langs->trans("StockLowerThanLimit", $objp->seuil_stock_alerte)).' ';
600 }
601 if ($objp->stock_physique < 0) {
602 print '<span class="warning">';
603 }
604 print price(price2num($objp->stock_physique, 'MS'), 0, $langs, 1, 0);
605 if ($objp->stock_physique < 0) {
606 print '</span>';
607 }
608 print '</td>';
609
610 // Details per warehouse
611 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)
612 if ($nb_warehouse > 1) {
613 foreach ($warehouses_list as &$wh) {
614 print '<td class="right">';
615 print price(empty($product->stock_warehouse[$wh['id']]->real) ? 0 : price2num($product->stock_warehouse[$wh['id']]->real, 'MS'), 0, $langs, 1, 0);
616 print '</td>';
617 }
618 }
619 }
620
621 // Virtual stock
622 if ($virtualdiffersfromphysical) {
623 print '<td class="right">';
624 if ($objp->seuil_stock_alerte != '' && ($product->stock_theorique < (float) $objp->seuil_stock_alerte)) {
625 print img_warning($langs->trans("StockLowerThanLimit", $objp->seuil_stock_alerte)).' ';
626 }
627 if ($objp->stock_physique < 0) {
628 print '<span class="warning">';
629 }
630 print price(price2num($product->stock_theorique, 'MS'), 0, $langs, 1, 0);
631 if ($objp->stock_physique < 0) {
632 print '</span>';
633 }
634 print '</td>';
635 }
636 // Units
637 if (getDolGlobalString('PRODUCT_USE_UNITS')) {
638 print '<td class="left">'.dol_escape_htmltag($objp->unit_short).'</td>';
639 }
640 // Fields from hook
641 $parameters = array('obj' => $objp);
642 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $product); // Note that $action and $object may have been modified by hook
643 print $hookmanager->resPrint;
644 print '<td class="center nowraponall">';
645 print img_picto($langs->trans("StockMovement"), 'movement', 'class="pictofixedwidth"');
646 print '<a href="'.DOL_URL_ROOT.'/product/stock/movement_list.php?idproduct='.$product->id.'">'.$langs->trans("Movements").'</a>';
647 print '</td>';
648 print '<td class="right nowrap">'.$product->LibStatut($objp->statut, 5, 0).'</td>';
649 print '<td class="right nowrap">'.$product->LibStatut($objp->tobuy, 5, 1).'</td>';
650 // Action column
651 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
652 print '<td></td>';
653 }
654
655 print "</tr>\n";
656 $i++;
657 }
658 if ($num == 0) {
659 print '<tr><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
660 }
661
662 print "</table>";
663 print '</div>';
664
665 print '</form>';
666
667 $db->free($resql);
668} else {
669 dol_print_error($db);
670}
671
672// End of page
673llxFooter();
674$db->close();
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:91
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:73
$c
Definition line.php:331
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.
print_liste_field_titre($name, $file="", $field="", $begin="", $param="", $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, $selectlimitsuffix=0, $hidenavigation=0, $pagenavastextinput=0, $morehtmlrightbeforearrow='')
Print a title with navigation controls for pagination.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
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 '.
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.
natural_search($fields, $value, $mode=0, $nofirstand=0, $sqltoadd='')
Generate natural SQL search string for a criteria (this criteria can be tested on one or several fiel...
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
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.
isModEnabled($module)
Is Dolibarr module enabled.
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...
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.