diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 8a6cfd5419c..8939132cff9 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -5503,7 +5503,7 @@ class Product extends CommonObject * This function need a lot of load. If you use it on list, use a cache to execute it once for each product id. * If ENTREPOT_EXTRA_STATUS is set, filtering on warehouse status is possible. * - * @param string $option '' = Load all stock info, also from closed and internal warehouses, 'nobatch', 'novirtual' + * @param string $option '' = Load all stock info, also from closed and internal warehouses, 'nobatch' = do not load batch detail, 'novirtual' = do no load virtual detail * You can also filter on 'warehouseclosed', 'warehouseopen', 'warehouseinternal' * @param int $includedraftpoforvirtual Include draft status of PO for virtual stock calculation * @param int $dateofvirtualstock Date of virtual stock @@ -5568,7 +5568,7 @@ class Product extends CommonObject $this->db->free($result); if (!preg_match('/novirtual/', $option)) { - $this->load_virtual_stock($includedraftpoforvirtual, $dateofvirtualstock); // This also load all arrays stats_xxx... + $this->load_virtual_stock($includedraftpoforvirtual, $dateofvirtualstock); // This load stock_theorique and also load all arrays stats_xxx... } return 1; diff --git a/htdocs/product/stock/stockatdate.php b/htdocs/product/stock/stockatdate.php index da6627942c5..075a8df857d 100644 --- a/htdocs/product/stock/stockatdate.php +++ b/htdocs/product/stock/stockatdate.php @@ -67,7 +67,21 @@ $search_nom = GETPOST('search_nom', 'alphanohtml'); $now = dol_now(); $productid = GETPOST('productid', 'int'); -$fk_warehouse = GETPOST('fk_warehouse', 'int'); +if (GETPOSTISARRAY('search_fk_warehouse')) { + $search_fk_warehouse = GETPOST('search_fk_warehouse', 'array:int'); +} else { + $search_fk_warehouse = array(GETPOST('search_fk_warehouse', 'int')); +} +// For backward compatibility +if (GETPOST('fk_warehouse', 'int')) { + $search_fk_warehouse = array(GETPOST('fk_warehouse', 'int')); +} +// Clean value -1 +foreach ($search_fk_warehouse as $key => $val) { + if ($val == -1 || empty($val)) { + unset($search_fk_warehouse[$key]); + } +} $sortfield = GETPOST('sortfield', 'aZ09comma'); $sortorder = GETPOST('sortorder', 'aZ09comma'); @@ -111,7 +125,7 @@ if ($mode == 'future') { if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // Both test are required to be compatible with all browsers $date = ''; $productid = 0; - $fk_warehouse = 0; + $search_fk_warehouse = array(); $search_ref = ''; $search_nom = ''; } @@ -139,8 +153,8 @@ if ($date && $dateIsValid) { // Avoid heavy sql if mandatory date is not defined if ($productid > 0) { $sql .= " AND ps.fk_product = ".((int) $productid); } - if ($fk_warehouse > 0) { - $sql .= " AND ps.fk_entrepot = ".((int) $fk_warehouse); + if (! empty($search_fk_warehouse)) { + $sql .= " AND ps.fk_entrepot IN (".$db->sanitize(join(",", $search_fk_warehouse)).")"; } $sql .= " GROUP BY fk_product, fk_entrepot"; //print $sql; @@ -194,8 +208,8 @@ if ($date && $dateIsValid) { if ($productid > 0) { $sql .= " AND sm.fk_product = ".((int) $productid); } - if ($fk_warehouse > 0) { - $sql .= " AND sm.fk_entrepot = ".((int) $fk_warehouse); + if (!empty($search_fk_warehouse)) { + $sql .= " AND sm.fk_entrepot IN (".$db->sanitize(join(",", $search_fk_warehouse)).")"; } $sql .= " GROUP BY sm.fk_product, sm.fk_entrepot"; $resql = $db->query($sql); @@ -246,7 +260,7 @@ $title = $langs->trans('StockAtDate'); $sql = 'SELECT p.rowid, p.ref, p.label, p.description, p.price, p.pmp,'; $sql .= ' p.price_ttc, p.price_base_type, p.fk_product_type, p.desiredstock, p.seuil_stock_alerte,'; $sql .= ' p.tms as datem, p.duration, p.tobuy, p.stock, '; -if ($fk_warehouse > 0) { +if (!empty($search_fk_warehouse)) { $sql .= " SUM(p.pmp * ps.reel) as estimatedvalue, SUM(p.price * ps.reel) as sellvalue"; $sql .= ', SUM(ps.reel) as stock_reel'; } else { @@ -258,8 +272,8 @@ $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters); // N $sql .= $hookmanager->resPrint; $sql .= ' FROM '.MAIN_DB_PREFIX.'product as p'; -if ($fk_warehouse > 0) { - $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_stock as ps ON p.rowid = ps.fk_product AND ps.fk_entrepot = '.((int) $fk_warehouse); +if (!empty($search_fk_warehouse)) { + $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_stock as ps ON p.rowid = ps.fk_product AND ps.fk_entrepot IN ('.$db->sanitize(join(",", $search_fk_warehouse)).")"; } // Add fields from hooks $parameters = array(); @@ -275,7 +289,7 @@ if (empty($conf->global->STOCK_SUPPORTS_SERVICES)) { if (!empty($canvas)) { $sql .= " AND p.canvas = '".$db->escape($canvas)."'"; } -if ($fk_warehouse > 0) { +if (!empty($search_fk_warehouse)) { $sql .= ' GROUP BY p.rowid, p.ref, p.label, p.description, p.price, p.pmp, p.price_ttc, p.price_base_type, p.fk_product_type, p.desiredstock, p.seuil_stock_alerte,'; $sql .= ' p.tms, p.duration, p.tobuy, p.stock'; } else { @@ -287,10 +301,10 @@ $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters); // Note that $action and $object may have been modified by hook $sql .= $hookmanager->resPrint; -if ($sortfield == 'stock_reel' && $fk_warehouse <= 0) { +if ($sortfield == 'stock_reel' && empty($search_fk_warehouse)) { $sortfield = 'stock'; } -if ($sortfield == 'stock' && $fk_warehouse > 0) { +if ($sortfield == 'stock' && !empty($search_fk_warehouse)) { $sortfield = 'stock_reel'; } $sql .= $db->order($sortfield, $sortorder); @@ -319,7 +333,6 @@ if ($date && $dateIsValid) { // We avoid a heavy sql if mandatory parameter date } $i = 0; -//print $sql; $helpurl = 'EN:Module_Stocks_En|FR:Module_Stock|'; $helpurl .= 'ES:Módulo_Stocks'; @@ -361,10 +374,15 @@ print img_picto('', 'product', 'class="pictofiwedwidth"').' '; print ' '; print $form->select_produits($productid, 'productid', '', 0, 0, -1, 2, '', 0, array(), 0, $langs->trans('Product'), 0, 'maxwidth300', 0, '', null, 1); -print ' '; -print img_picto('', 'stock', 'class="pictofiwedwidth"'); -print ' '; -print $formproduct->selectWarehouses((GETPOSTISSET('fk_warehouse') ? $fk_warehouse : 'ifonenodefault'), 'fk_warehouse', '', 1, 0, 0, $langs->trans('Warehouse'), 0, 0, null, '', null, 1, false, 'e.ref'); +if ($mode != 'future') { + // A virtual stock in future has no sense on a per warehouse view, so no filter on warehouse is available for stock at date in future + print ' '; + print img_picto('', 'stock', 'class="pictofixedwidth"').$langs->trans("Warehouse").' :'; + print ' '; + $selected = ((GETPOSTISSET('search_fk_warehouse') || GETPOSTISSET('fk_warehouse')) ? $search_fk_warehouse : 'ifonenodefault'); + print $formproduct->selectWarehouses($selected, 'search_fk_warehouse', '', 1, 0, 0, $langs->trans('Warehouse'), 0, 0, null, '', null, 1, false, 'e.ref', 1); +} + print ''; $parameters = array(); @@ -387,8 +405,10 @@ if ($limit > 0 && $limit != $conf->liste_limit) { $param .= '&limit='.urlencode($limit); } $param .= '&mode='.$mode; -if ($fk_warehouse > 0) { - $param .= '&fk_warehouse='.$fk_warehouse; +if (!empty($search_fk_warehouse)) { + foreach ($search_fk_warehouse as $val) { + $param .= '&search_fk_warehouse[]='.$val; + } } if ($productid > 0) { $param .= '&productid='.$productid; @@ -414,7 +434,6 @@ if ($mode == 'future') { $stocklabel = $langs->trans("VirtualStockAtDate"); } -//print '