NEW Can select several warehouses into the view stock at date in past

This commit is contained in:
Laurent Destailleur 2023-02-24 12:57:15 +01:00
parent 393b0e7c4c
commit 093099ea44
2 changed files with 67 additions and 35 deletions

View File

@ -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;

View File

@ -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&oacute;dulo_Stocks';
@ -361,10 +374,15 @@ print img_picto('', 'product', 'class="pictofiwedwidth"').' ';
print '</span> ';
print $form->select_produits($productid, 'productid', '', 0, 0, -1, 2, '', 0, array(), 0, $langs->trans('Product'), 0, 'maxwidth300', 0, '', null, 1);
print ' <span class="clearbothonsmartphone marginleftonly paddingleftonly marginrightonly paddingrightonly">&nbsp;</span> ';
print img_picto('', 'stock', 'class="pictofiwedwidth"');
print '</span> ';
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 ' <span class="clearbothonsmartphone marginleftonly paddingleftonly marginrightonly paddingrightonly">&nbsp;</span> ';
print img_picto('', 'stock', 'class="pictofixedwidth"').$langs->trans("Warehouse").' :';
print '</span> ';
$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 '</div>';
$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 '<form action="'.$_SERVER["PHP_SELF"].'" method="POST" name="formulaire">';
print '<input type="hidden" name="token" value="'.newToken().'">';
print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
@ -446,7 +465,7 @@ print '</td>';
print '</tr>';
$fieldtosortcurrentstock = 'stock';
if ($fk_warehouse > 0) {
if (!empty($search_fk_warehouse)) {
$fieldtosortcurrentstock = 'stock_reel';
}
@ -506,9 +525,14 @@ while ($i < ($limit ? min($num, $limit) : $num)) {
}*/
$currentstock = '';
if ($fk_warehouse > 0) {
if (!empty($search_fk_warehouse)) {
//if ($productid > 0) {
$currentstock = $stock_prod_warehouse[$objp->rowid][$fk_warehouse];
foreach ($search_fk_warehouse as $val) {
if (!is_numeric($currentstock)) {
$currentstock = 0;
}
$currentstock += $stock_prod_warehouse[$objp->rowid][$val];
}
//} else {
// $currentstock = $objp->stock_reel;
//}
@ -521,17 +545,21 @@ while ($i < ($limit ? min($num, $limit) : $num)) {
}
if ($mode == 'future') {
$prod->load_stock('warehouseopen, warehouseinternal', 0, $dateendofday);
$stock = $prod->stock_theorique;
$prod->load_stock('warehouseopen, warehouseinternal', 0);
$virtualstock = $prod->stock_theorique;
$prod->load_stock('warehouseopen,warehouseinternal,nobatch', 0, $dateendofday);
$stock = $prod->stock_theorique; // virtual stock at a date
$prod->load_stock('warehouseopen,warehouseinternal,nobatch', 0);
$virtualstock = $prod->stock_theorique; // virtual stock in infinite future
} else {
if ($fk_warehouse > 0) {
$stock = $currentstock - $movements_prod_warehouse[$objp->rowid][$fk_warehouse];
$nbofmovement = $movements_prod_warehouse_nb[$objp->rowid][$fk_warehouse];
$stock = $currentstock;
$nbofmovement = 0;
if (!empty($search_fk_warehouse)) {
foreach ($search_fk_warehouse as $val) {
$stock -= $movements_prod_warehouse[$objp->rowid][$val];
$nbofmovement += $movements_prod_warehouse_nb[$objp->rowid][$val];
}
} else {
$stock = $currentstock - $movements_prod[$objp->rowid];
$nbofmovement = $movements_prod_nb[$objp->rowid];
$stock -= $movements_prod[$objp->rowid];
$nbofmovement += $movements_prod_nb[$objp->rowid];
}
}
@ -585,7 +613,11 @@ while ($i < ($limit ? min($num, $limit) : $num)) {
print '<td class="right">';
if ($nbofmovement > 0) {
print '<a href="'.DOL_URL_ROOT.'/product/stock/movement_list.php?idproduct='.$objp->rowid.($fk_warehouse > 0 ? '&search_warehouse='.$fk_warehouse : '').'">'.$langs->trans("Movements").'</a>';
print '<a href="'.DOL_URL_ROOT.'/product/stock/movement_list.php?idproduct='.$objp->rowid;
foreach ($search_fk_warehouse as $val) {
print ($val > 0 ? '&search_warehouse='.$val : '');
}
print '">'.$langs->trans("Movements").'</a>';
print ' <span class="tabs"><span class="badge">'.$nbofmovement.'</span></span>';
}
print '</td>';