30 require
'../main.inc.php';
31 require_once DOL_DOCUMENT_ROOT.
'/product/class/product.class.php';
32 require_once DOL_DOCUMENT_ROOT.
'/core/class/html.formother.class.php';
33 require_once DOL_DOCUMENT_ROOT.
'/categories/class/categorie.class.php';
34 require_once DOL_DOCUMENT_ROOT.
'/product/class/html.formproduct.class.php';
37 $langs->loadLangs(array(
'products',
'stocks'));
39 $action =
GETPOST(
'action',
'aZ09');
40 $sref =
GETPOST(
"sref",
'alpha');
41 $snom =
GETPOST(
"snom",
'alpha');
42 $sall = trim((
GETPOST(
'search_all',
'alphanohtml') !=
'') ?
GETPOST(
'search_all',
'alphanohtml') :
GETPOST(
'sall',
'alphanohtml'));
44 $search_barcode =
GETPOST(
"search_barcode",
'alpha');
45 $search_toolowstock =
GETPOST(
'search_toolowstock');
48 $fourn_id =
GETPOST(
"fourn_id",
'int');
49 $sbarcode =
GETPOST(
"sbarcode",
'int');
50 $search_stock_physique =
GETPOST(
'search_stock_physique',
'alpha');
52 $sortfield =
GETPOST(
'sortfield',
'aZ09comma');
53 $sortorder =
GETPOST(
'sortorder',
'aZ09comma');
55 if (empty($page) || $page < 0) {
64 $limit =
GETPOST(
'limit',
'int') ?
GETPOST(
'limit',
'int') : $conf->liste_limit;
65 if (empty($page) || $page == -1) {
68 $offset = $limit * $page;
71 $search_sale =
GETPOST(
"search_sale");
73 $search_categ =
GETPOST(
'catid',
'int');
75 $search_categ =
GETPOST(
'search_categ',
'int');
81 if (!empty($canvas)) {
82 require_once DOL_DOCUMENT_ROOT.
'/core/class/canvas.class.php';
83 $objcanvas =
new Canvas($db, $action);
84 $objcanvas->getCanvas(
'product',
'list', $canvas);
88 $virtualdiffersfromphysical = 0;
89 if (!empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT)
90 || !empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER)
91 || !empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE)
92 || !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION)
93 || !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE)
95 $virtualdiffersfromphysical = 1;
99 $hookmanager->initHooks(array(
'productreassortlist'));
102 $socid = $user->socid;
104 $result =
restrictedArea($user,
'produit|service', 0,
'product&product');
112 if (
GETPOST(
'button_removefilter_x',
'alpha') ||
GETPOST(
'button_removefilter.x',
'alpha') ||
GETPOST(
'button_removefilter',
'alpha')) {
120 $search_toolowstock =
'';
123 $search_stock_physique =
'';
132 $helpurl =
'EN:Module_Stocks_En|FR:Module_Stock|ES:Módulo_Stocks';
137 $sql =
'SELECT p.rowid, p.ref, p.label, p.barcode, p.price, p.price_ttc, p.price_base_type, p.entity,';
138 $sql .=
' p.fk_product_type, p.tms as datem,';
139 $sql .=
' p.duration, p.tosell as statut, p.tobuy, p.seuil_stock_alerte, p.desiredstock,';
140 $sql .=
' SUM(s.reel) as stock_physique';
141 if (!empty($conf->global->PRODUCT_USE_UNITS)) {
142 $sql .=
', u.short_label as unit_short';
145 $parameters = array();
146 $reshook = $hookmanager->executeHooks(
'printFieldListSelect', $parameters, $object);
147 $sql .= $hookmanager->resPrint;
148 $sql .=
' FROM '.MAIN_DB_PREFIX.
'product as p';
149 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'product_stock as s ON p.rowid = s.fk_product';
150 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'entrepot as e ON s.fk_entrepot = e.rowid AND e.entity IN ('.
getEntity(
'stock').
')';
151 if (!empty($conf->global->PRODUCT_USE_UNITS)) {
152 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_units as u on p.fk_unit = u.rowid';
154 $sql .=
" WHERE p.entity IN (".getEntity(
'product').
")";
155 if (!empty($search_categ) && $search_categ !=
'-1') {
157 if ($search_categ == -2) {
158 $sql .=
" NOT EXISTS ";
163 $sql .=
" SELECT cp.fk_categorie, cp.fk_product";
164 $sql .=
" FROM " . MAIN_DB_PREFIX .
"categorie_product as cp";
165 $sql .=
" WHERE cp.fk_product = p.rowid";
166 if ($search_categ > 0) {
167 $sql .=
" AND cp.fk_categorie = " . ((int) $search_categ);
172 $sql .=
natural_search(array(
'p.ref',
'p.label',
'p.description',
'p.note'), $sall);
177 $sql .=
" AND p.fk_product_type = '1'";
179 $sql .=
" AND p.fk_product_type <> '1'";
185 if ($search_barcode) {
191 if (!empty($tosell)) {
192 $sql .=
" AND p.tosell = ".((int) $tosell);
194 if (!empty($tobuy)) {
195 $sql .=
" AND p.tobuy = ".((int) $tobuy);
197 if (!empty($canvas)) {
198 $sql .=
" AND p.canvas = '".$db->escape($canvas).
"'";
201 $sql .=
" AND p.rowid = pf.fk_product AND pf.fk_soc = ".((int) $fourn_id);
204 $parameters = array();
205 $reshook = $hookmanager->executeHooks(
'printFieldListWhere', $parameters, $object);
206 $sql .= $hookmanager->resPrint;
207 $sql .=
" GROUP BY p.rowid, p.ref, p.label, p.barcode, p.price, p.price_ttc, p.price_base_type, p.entity,";
208 $sql .=
" p.fk_product_type, p.tms, p.duration, p.tosell, p.tobuy, p.seuil_stock_alerte, p.desiredstock";
210 $parameters = array();
211 $reshook = $hookmanager->executeHooks(
'printFieldSelect', $parameters, $object);
212 $sql .= $hookmanager->resPrint;
214 if ($search_toolowstock) {
215 $sql_having .=
" HAVING SUM(".$db->ifsql(
's.reel IS NULL',
'0',
's.reel').
") < p.seuil_stock_alerte";
217 if ($search_stock_physique !=
'') {
219 $natural_search_physique =
natural_search(
'SUM(' . $db->ifsql(
's.reel IS NULL',
'0',
's.reel') .
')', $search_stock_physique, 1, 1);
220 $natural_search_physique =
" " . substr($natural_search_physique, 1, -1);
221 if (!empty($sql_having)) {
222 $sql_having .=
" AND";
224 $sql_having .=
" HAVING";
226 $sql_having .= $natural_search_physique;
228 if (!empty($sql_having)) {
231 $sql .= $db->order($sortfield, $sortorder);
235 if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {
236 $result = $db->query($sql);
244 $sql .= $db->plimit($limit + 1, $offset);
246 $resql = $db->query($sql);
248 $num = $db->num_rows(
$resql);
252 if ($num == 1 &&
GETPOST(
'autojumpifoneonly') && ($sall || $snom || $sref)) {
253 $objp = $db->fetch_object(
$resql);
254 header(
"Location: card.php?id=$objp->rowid");
260 $texte = $langs->trans(
"Services");
262 $texte = $langs->trans(
"Products");
265 $texte = $langs->trans(
"ProductsAndServices");
267 $texte .=
' ('.$langs->trans(
"MenuStocks").
')';
270 if ($limit > 0 && $limit != $conf->liste_limit) {
271 $param .=
'&limit='.urlencode($limit);
274 $param .=
"&sall=".urlencode($sall);
277 $param .=
"&tosell=".urlencode($tosell);
280 $param .=
"&tobuy=".urlencode($tobuy);
283 $param .=
"&type=".urlencode($type);
286 $param .=
"&fourn_id=".urlencode($fourn_id);
289 $param .=
"&snom=".urlencode($snom);
292 $param .=
"&sref=".urlencode($sref);
295 $param .=
"&search_sale=".urlencode($search_sale);
297 if ($search_categ > 0) {
298 $param .=
"&search_categ=".urlencode($search_categ);
300 if ($search_toolowstock) {
301 $param .=
"&search_toolowstock=".urlencode($search_toolowstock);
304 $param .=
"&sbarcode=".urlencode($sbarcode);
306 if ($search_stock_physique) {
307 $param .=
'&search_stock_physique=' . urlencode($search_stock_physique);
312 print
'<form action="'.$_SERVER[
"PHP_SELF"].
'" method="post" name="formulaire">';
313 print
'<input type="hidden" name="token" value="'.newToken().
'">';
314 print
'<input type="hidden" name="sortfield" value="'.$sortfield.
'">';
315 print
'<input type="hidden" name="sortorder" value="'.$sortorder.
'">';
316 print
'<input type="hidden" name="page" value="'.$page.
'">';
317 print
'<input type="hidden" name="type" value="'.$type.
'">';
319 print_barre_liste($texte, $page, $_SERVER[
"PHP_SELF"], $param, $sortfield, $sortorder,
'', $num,
$nbtotalofrecords,
'product', 0,
'',
'', $limit);
321 if ($search_categ > 0) {
322 print
"<div id='ways'>";
324 $c->fetch($search_categ);
325 $ways = $c->print_all_ways(
' > ',
'product/reassort.php');
326 print
" > ".$ways[0].
"<br>\n";
333 $moreforfilter .=
'<div class="divsearchfield">';
334 $moreforfilter .=
img_picto($langs->trans(
'Categories'),
'category',
'class="pictofixedwidth"');
335 $moreforfilter .= $htmlother->select_categories(Categorie::TYPE_PRODUCT, $search_categ,
'search_categ', 1);
336 $moreforfilter .=
'</div>';
339 $moreforfilter .=
'<div class="divsearchfield">';
340 $moreforfilter .=
'<label for="search_toolowstock">'.$langs->trans(
"StockTooLow").
' </label><input type="checkbox" id="search_toolowstock" name="search_toolowstock" value="1"'.($search_toolowstock ?
' checked' :
'').
'>';
341 $moreforfilter .=
'</div>';
343 if (!empty($moreforfilter)) {
344 print
'<div class="liste_titre liste_titre_bydiv centpercent">';
345 print $moreforfilter;
346 $parameters = array();
347 $reshook = $hookmanager->executeHooks(
'printFieldPreListTitle', $parameters);
348 print $hookmanager->resPrint;
353 $formProduct->loadWarehouses();
354 $warehouses_list = $formProduct->cache_warehouses;
355 $nb_warehouse = count($warehouses_list);
356 $colspan_warehouse = 1;
357 if (!empty($conf->global->STOCK_DETAIL_ON_WAREHOUSE)) {
358 $colspan_warehouse = $nb_warehouse > 1 ? $nb_warehouse + 1 : 1;
361 print
'<div class="div-table-responsive">';
362 print
'<table class="tagtable liste'.($moreforfilter ?
" listwithfilterbefore" :
"").
'">';
365 print
'<tr class="liste_titre_filter">';
366 print
'<td class="liste_titre">';
367 print
'<input class="flat" type="text" name="sref" size="6" value="'.$sref.
'">';
369 print
'<td class="liste_titre">';
370 print
'<input class="flat" type="text" name="snom" size="8" value="'.$snom.
'">';
374 print
'<td class="liste_titre">';
379 print
'<td class="liste_titre"> </td>';
380 print
'<td class="liste_titre right"> </td>';
382 print
'<td class="liste_titre right">';
383 print
'<input class="flat" type="text" size="5" name="search_stock_physique" value="'.dol_escape_htmltag($search_stock_physique).
'">';
385 if ($virtualdiffersfromphysical) {
386 print
'<td class="liste_titre"> </td>';
388 print
'<td class="liste_titre"> </td>';
389 print
'<td class="liste_titre" colspan="'.$colspan_warehouse.
'"> </td>';
390 print
'<td class="liste_titre"></td>';
391 $parameters = array();
392 $reshook = $hookmanager->executeHooks(
'printFieldListOption', $parameters);
393 print $hookmanager->resPrint;
394 print
'<td class="liste_titre maxwidthsearch">';
395 $searchpicto =
$form->showFilterAndCheckAddButtons(0);
401 print
"<tr class=\"liste_titre\">";
405 print_liste_field_titre(
"Duration", $_SERVER[
"PHP_SELF"],
"p.duration",
'', $param,
"", $sortfield, $sortorder,
'center ');
407 print_liste_field_titre(
"StockLimit", $_SERVER[
"PHP_SELF"],
"p.seuil_stock_alerte",
'', $param,
"", $sortfield, $sortorder,
'right ');
408 print_liste_field_titre(
"DesiredStock", $_SERVER[
"PHP_SELF"],
"p.desiredstock",
'', $param,
"", $sortfield, $sortorder,
'right ');
409 print_liste_field_titre(
"PhysicalStock", $_SERVER[
"PHP_SELF"],
"stock_physique",
'', $param,
"", $sortfield, $sortorder,
'right ');
411 if (!empty($conf->global->STOCK_DETAIL_ON_WAREHOUSE)) {
412 if ($nb_warehouse > 1) {
413 foreach ($warehouses_list as &$wh) {
418 if ($virtualdiffersfromphysical) {
419 print_liste_field_titre(
"VirtualStock", $_SERVER[
"PHP_SELF"],
"",
'', $param,
"", $sortfield, $sortorder,
'right ',
'VirtualStockDesc');
422 if (!empty($conf->global->PRODUCT_USE_UNITS)) {
423 print_liste_field_titre(
"Unit", $_SERVER[
"PHP_SELF"],
"unit_short",
'', $param,
'align="right"', $sortfield, $sortorder);
426 print_liste_field_titre(
"ProductStatusOnSell", $_SERVER[
"PHP_SELF"],
"p.tosell",
'', $param,
"", $sortfield, $sortorder,
'right ');
427 print_liste_field_titre(
"ProductStatusOnBuy", $_SERVER[
"PHP_SELF"],
"p.tobuy",
'', $param,
"", $sortfield, $sortorder,
'right ');
429 $parameters = array(
'param'=>$param,
'sortfield'=>$sortfield,
'sortorder'=>$sortorder);
430 $reshook = $hookmanager->executeHooks(
'printFieldListTitle', $parameters);
431 print $hookmanager->resPrint;
435 while ($i < min($num, $limit)) {
436 $objp = $db->fetch_object(
$resql);
439 $product->fetch($objp->rowid);
440 $product->load_stock();
443 print
'<td class="nowrap">';
444 print $product->getNomUrl(1,
'', 16);
447 print
'<td>'.$product->label.
'</td>';
450 print
'<td class="center">';
451 if (preg_match(
'/([0-9]+)y/i', $objp->duration, $regs)) {
452 print $regs[1].
' '.$langs->trans(
"DurationYear");
453 } elseif (preg_match(
'/([0-9]+)m/i', $objp->duration, $regs)) {
454 print $regs[1].
' '.$langs->trans(
"DurationMonth");
455 } elseif (preg_match(
'/([0-9]+)d/i', $objp->duration, $regs)) {
456 print $regs[1].
' '.$langs->trans(
"DurationDay");
458 print $objp->duration;
463 print
'<td class="right">'.$objp->seuil_stock_alerte.
'</td>';
464 print
'<td class="right">'.$objp->desiredstock.
'</td>';
466 print
'<td class="right">';
467 if ($objp->seuil_stock_alerte !=
'' && ($objp->stock_physique < $objp->seuil_stock_alerte)) {
468 print
img_warning($langs->trans(
"StockTooLow")).
' ';
470 print
price2num($objp->stock_physique,
'MS');
474 if (!empty($conf->global->STOCK_DETAIL_ON_WAREHOUSE)) {
475 if ($nb_warehouse > 1) {
476 foreach ($warehouses_list as &$wh) {
477 print
'<td class="right">';
478 print empty($product->stock_warehouse[$wh[
'id']]->real) ?
'0' : $product->stock_warehouse[$wh[
'id']]->real;
485 if ($virtualdiffersfromphysical) {
486 print
'<td class="right">';
487 if ($objp->seuil_stock_alerte !=
'' && ($product->stock_theorique < $objp->seuil_stock_alerte)) {
488 print
img_warning($langs->trans(
"StockTooLow")).
' ';
490 print
price2num($product->stock_theorique,
'MS');
494 if (!empty($conf->global->PRODUCT_USE_UNITS)) {
495 print
'<td class="left">'.$objp->unit_short.
'</td>';
497 print
'<td class="center">';
498 print
img_picto($langs->trans(
"StockMovement"),
'movement',
'class="pictofixedwidth"');
499 print
'<a href="'.DOL_URL_ROOT.
'/product/stock/movement_list.php?idproduct='.$product->id.
'">'.$langs->trans(
"Movements").
'</a>';
501 print
'<td class="right nowrap">'.$product->LibStatut($objp->statut, 5, 0).
'</td>';
502 print
'<td class="right nowrap">'.$product->LibStatut($objp->tobuy, 5, 1).
'</td>';
504 $parameters = array(
'obj'=>$objp);
505 $reshook = $hookmanager->executeHooks(
'printFieldListValue', $parameters, $product);
506 print $hookmanager->resPrint;
if(!defined('NOREQUIRESOC')) if(!defined('NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined('NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined('NOREQUIREAJAX')) llxHeader()
Empty header.
Class to manage categories.
Class to manage products or services.
if(isModEnabled('facture') &&!empty($user->rights->facture->lire)) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') &&!empty($user->rights->don->lire)) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->hasRight("commande", "lire") &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $resql
Social contributions to pay.
if($cancel &&! $id) if($action=='add' &&! $cancel) if($action=='delete') if($id) $form
Actions.
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
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.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
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.
print_barre_liste($titre, $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.
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname from a POST of a form.
isModEnabled($module)
Is Dolibarr module enabled.
getEntity($element, $shared=1, $currentobject=null)
Get list of entity id to use.
$nbtotalofrecords
Count total nb of records.
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.