diff --git a/htdocs/langs/en_US/errors.lang b/htdocs/langs/en_US/errors.lang index 75a12d517d0..f46307a21ae 100644 --- a/htdocs/langs/en_US/errors.lang +++ b/htdocs/langs/en_US/errors.lang @@ -136,7 +136,8 @@ ErrorNewValueCantMatchOldValue=New value can't be equal to old one ErrorFailedToValidatePasswordReset=Failed to reinit password. May be the reinit was already done (this link can be used only one time). If not, try to restart the reinit process. ErrorToConnectToMysqlCheckInstance=Connect to database fails. Check database server is running (for example, with mysql/mariadb, you can launch it from command line with 'sudo service mysql start'). ErrorFailedToAddContact=Failed to add contact -ErrorDateMustBeBeforeToday=The date cannot be greater than today +ErrorDateMustBeBeforeToday=The date must be lower than today +ErrorDateMustBeInFuture=The date must be greater than today ErrorPaymentModeDefinedToWithoutSetup=A payment mode was set to type %s but setup of module Invoice was not completed to define information to show for this payment mode. ErrorPHPNeedModule=Error, your PHP must have module %s installed to use this feature. ErrorOpenIDSetupNotComplete=You setup Dolibarr config file to allow OpenID authentication, but URL of OpenID service is not defined into constant %s diff --git a/htdocs/langs/en_US/stocks.lang b/htdocs/langs/en_US/stocks.lang index 41c88747498..9ce03f64942 100644 --- a/htdocs/langs/en_US/stocks.lang +++ b/htdocs/langs/en_US/stocks.lang @@ -95,6 +95,8 @@ RealStock=Real Stock RealStockDesc=Physical/real stock is the stock currently in the warehouses. RealStockWillAutomaticallyWhen=The real stock will be modified according to this rule (as defined in the Stock module): VirtualStock=Virtual stock +VirtualStockAtDate=Virtual stock at date +VirtualStockAtDateDesc=Virtual stock atonce all pending orders that are planned to be done before the date will be finished VirtualStockDesc=Virtual stock is the calculated stock available once all open/pending actions (that affect stocks) are closed (purchase orders received, sales orders shipped, manufacturing orders produced, etc) IdWarehouse=Id warehouse DescWareHouse=Description warehouse diff --git a/htdocs/product/stock/stockatdate.php b/htdocs/product/stock/stockatdate.php index 288db71fb15..9b03d5ecfc4 100644 --- a/htdocs/product/stock/stockatdate.php +++ b/htdocs/product/stock/stockatdate.php @@ -1,6 +1,6 @@ - * Copyright (C) 2013-2018 Laurent Destaileur + * Copyright (C) 2013-2020 Laurent Destaileur * Copyright (C) 2014 Regis Houssin * Copyright (C) 2016 Juanjo Menent * Copyright (C) 2016 ATM Consulting @@ -59,9 +59,10 @@ if (GETPOSTISSET('dateday') && GETPOSTISSET('datemonth') && GETPOSTISSET('dateye $dateendofday = dol_mktime(23, 59, 59, GETPOST('datemonth', 'int'), GETPOST('dateday', 'int'), GETPOST('dateyear', 'int')); } +$now = dol_now(); + $productid = GETPOST('productid', 'int'); $fk_warehouse = GETPOST('fk_warehouse', 'int'); -$texte = ''; $sortfield = GETPOST('sortfield', 'alpha'); $sortorder = GETPOST('sortorder', 'alpha'); @@ -80,6 +81,19 @@ $parameters = array(); $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +$dateIsValid= true; +if ($mode == 'future') { + if ($date && $date < $now) { + setEventMessages($langs->trans("ErrorDateMustBeInFuture"), null, 'errors'); + $dateIsValid= false; + } +} else { + if ($date && $date > $now) { + setEventMessages($langs->trans("ErrorDateMustBeBeforeToday"), null, 'errors'); + $dateIsValid= false; + } +} + /* * Actions @@ -99,11 +113,10 @@ if ($conf->global->ENTREPOT_EXTRA_STATUS) { $warehouseStatus[] = Entrepot::STATUS_OPEN_INTERNAL; } - // Get array with current stock per product, warehouse $stock_prod_warehouse = array(); $stock_prod = array(); -if ($date) { // Avoid heavy sql if mandatory date is not defined +if ($date && $dateIsValid) { // Avoid heavy sql if mandatory date is not defined $sql = "SELECT ps.fk_product, ps.fk_entrepot as fk_warehouse,"; $sql .= " SUM(ps.reel) AS stock"; $sql .= " FROM ".MAIN_DB_PREFIX."product_stock as ps"; @@ -146,13 +159,17 @@ if ($date) { // Avoid heavy sql if mandatory date is not defined dol_print_error($db); } //var_dump($stock_prod_warehouse); +} elseif ($action == 'filter') { + setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Date")), null, 'errors'); } // Get array with list of stock movements between date and now (for product/warehouse= $movements_prod_warehouse = array(); $movements_prod = array(); -if ($date) { - $sql = "SELECT sm.fk_product, sm.fk_entrepot, SUM(sm.value) AS stock"; +$movements_prod_warehouse_nb = array(); +$movements_prod_nb = array(); +if ($date && $dateIsValid) { + $sql = "SELECT sm.fk_product, sm.fk_entrepot, SUM(sm.value) AS stock, COUNT(sm.rowid) AS nbofmovement"; $sql .= " FROM ".MAIN_DB_PREFIX."stock_mouvement as sm"; $sql .= ", ".MAIN_DB_PREFIX."entrepot as w"; $sql .= " WHERE w.entity IN (".getEntity('stock').")"; @@ -184,12 +201,15 @@ if ($date) { $fk_product = $obj->fk_product; $fk_entrepot = $obj->fk_entrepot; $stock = $obj->stock; + $nbofmovement = $obj->nbofmovement; // Pour llx_product_stock.reel $movements_prod_warehouse[$fk_product][$fk_entrepot] = $stock; + $movements_prod_warehouse_nb[$fk_product][$fk_entrepot] = $nbofmovement; // Pour llx_product.stock $movements_prod[$fk_product] += $stock; + $movements_prod_nb[$fk_product] += $nbofmovement; $i++; } @@ -259,7 +279,7 @@ if ($sortfield == 'stock' && $fk_warehouse > 0) { } $sql .= $db->order($sortfield, $sortorder); -if ($date) { // We avoid a heavy sql if mandatory parameter date not yet defined +if ($date && $dateIsValid) { // We avoid a heavy sql if mandatory parameter date not yet defined $nbtotalofrecords = ''; if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) { @@ -355,7 +375,7 @@ print '
'; // You can use div-table-responsive- print ''; $stocklabel = $langs->trans('StockAtDate'); -if ($mode == 'future') $stocklabel = $langs->trans("VirtualStock"); +if ($mode == 'future') $stocklabel = $langs->trans("VirtualStockAtDate"); //print ''; print ''; @@ -371,6 +391,9 @@ print ''; print ''; print ''; +if ($mode == 'future') { + print ''; +} // Fields from hook $parameters = array('param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder); $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters); // Note that $action and $object may have been modified by hook @@ -394,7 +417,8 @@ print_liste_field_titre('Label', $_SERVER["PHP_SELF"], 'p.label', $param, '', '' if ($mode == 'future') { print_liste_field_titre('CurrentStock', $_SERVER["PHP_SELF"], $fieldtosortcurrentstock, $param, '', '', $sortfield, $sortorder, 'right '); print_liste_field_titre('', $_SERVER["PHP_SELF"]); - print_liste_field_titre($stocklabel, $_SERVER["PHP_SELF"], '', $param, '', '', $sortfield, $sortorder, 'right ', 'VirtualStockDesc'); + print_liste_field_titre($stocklabel, $_SERVER["PHP_SELF"], '', $param, '', '', $sortfield, $sortorder, 'right ', 'VirtualStockAtDateDesc'); + print_liste_field_titre('VirtualStock', $_SERVER["PHP_SELF"], '', $param, '', '', $sortfield, $sortorder, 'right ', 'VirtualStockDesc'); } else { print_liste_field_titre($stocklabel, $_SERVER["PHP_SELF"], '', $param, '', '', $sortfield, $sortorder, 'right '); print_liste_field_titre('', $_SERVER["PHP_SELF"]); @@ -453,18 +477,21 @@ while ($i < ($limit ? min($num, $limit) : $num)) } if ($mode == 'future') { - $prod->load_stock('warehouseopen, warehouseinternal', 0); + $prod->load_stock('warehouseopen, warehouseinternal', 0); // This call also ->load_virtual_stock() //$result = $prod->load_stats_reception(0, '4'); //print $prod->stats_commande_fournisseur['qty'].'
'."\n"; //print $prod->stats_reception['qty']; - $stock = 123; + $stock = ''.$langs->trans("FeatureNotYetAvailable").''; + $virtualstock = $prod->stock_theorique; } else { if ($fk_warehouse > 0) { $stock = $currentstock - $movements_prod_warehouse[$objp->rowid][$fk_warehouse]; + $nbofmovement = $movements_prod_warehouse_nb[$objp->rowid][$fk_warehouse]; } else { $stock = $currentstock - $movements_prod[$objp->rowid]; + $nbofmovement = $movements_prod_nb[$objp->rowid]; } } @@ -485,16 +512,24 @@ while ($i < ($limit ? min($num, $limit) : $num)) print ''; - // Stock at date + // Virtual stock at date print ''; + + // Final virtual stock + print ''; } else { // Stock at date - print ''; + print ''; - print ''; + print ''; // Current stock - print ''; + print ''; } // Action
'.$stock.''.$virtualstock.''.$stock.''.($stock ? $stock : ''.$stock.'').''.$langs->trans("Movements").''; + if ($nbofmovement > 0) { + print ''.$langs->trans("Movements").''; + print ' '.$nbofmovement.''; + } + print ''.$currentstock.''.($currentstock ? $currentstock : '0').'