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