diff --git a/htdocs/comm/index.php b/htdocs/comm/index.php
index 15f94043b1c..2c20eaea352 100644
--- a/htdocs/comm/index.php
+++ b/htdocs/comm/index.php
@@ -1091,7 +1091,7 @@ if (isModEnabled('commande') && $user->rights->commande->lire) {
print '';
print '';
- print '
'.$companystatic->getNomUrl(1, 'customer', 44).' | ';
+ print ''.$companystatic->getNomUrl(1, 'customer', 44).' | ';
$datem = $db->jdate($obj->dv);
print '';
print dol_print_date($datem, 'day', 'tzserver');
diff --git a/htdocs/core/menus/init_menu_auguria.sql b/htdocs/core/menus/init_menu_auguria.sql
index d6945d26fd5..e6fc16a62d6 100644
--- a/htdocs/core/menus/init_menu_auguria.sql
+++ b/htdocs/core/menus/init_menu_auguria.sql
@@ -138,7 +138,7 @@ insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, left
insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->stock->enabled', __HANDLER__, 'left', 3102__+MAX_llx_menu__, 'products', '', 3100__+MAX_llx_menu__, '/product/stock/list.php?mainmenu=products', 'List', 1, 'stocks', '$user->rights->stock->lire', '', 2, 1, __ENTITY__);
insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->stock->enabled', __HANDLER__, 'left', 3104__+MAX_llx_menu__, 'products', '', 3100__+MAX_llx_menu__, '/product/stock/movement_list.php?mainmenu=products', 'Movements', 1, 'stocks', '$user->rights->stock->mouvement->lire', '', 2, 3, __ENTITY__);
insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->stock->enabled && $conf->supplier_order->enabled', __HANDLER__, 'left', 3105__+MAX_llx_menu__, 'products', '', 3100__+MAX_llx_menu__, '/product/stock/replenish.php?mainmenu=products', 'Replenishments', 1, 'stocks', '$user->rights->stock->mouvement->creer && $user->rights->fournisseur->lire', '', 2, 4, __ENTITY__);
-insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->stock->enabled', __HANDLER__, 'left', 3106__+MAX_llx_menu__, 'products', '', 3100__+MAX_llx_menu__, '/product/stock/massstockmove.php?mainmenu=products', 'MassStockTransferShort', 1, 'stocks', '$user->rights->stock->mouvement->creer', '', 2, 5, __ENTITY__);
+insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->stock->enabled', __HANDLER__, 'left', 3106__+MAX_llx_menu__, 'products', '', 3100__+MAX_llx_menu__, '/product/stock/massstockmove.php?init=1&mainmenu=products', 'MassStockTransferShort', 1, 'stocks', '$user->rights->stock->mouvement->creer', '', 2, 5, __ENTITY__);
-- Product - Categories
insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->categorie->enabled', __HANDLER__, 'left', 3200__+MAX_llx_menu__, 'products', 'cat', 3__+MAX_llx_menu__, '/categories/index.php?mainmenu=products&leftmenu=cat&type=0', 'Categories', 0, 'categories', '$user->rights->categorie->lire', '', 2, 4, __ENTITY__);
diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php
index 8c14bd40027..a09f85e1f4e 100644
--- a/htdocs/core/menus/standard/eldy.lib.php
+++ b/htdocs/core/menus/standard/eldy.lib.php
@@ -2057,7 +2057,7 @@ function get_left_menu_products($mainmenu, &$newmenu, $usemenuhider = 1, $leftme
$newmenu->add("/product/stock/list.php", $langs->trans("List"), 1, $user->hasRight('stock', 'lire'));
$newmenu->add("/product/stock/movement_list.php", $langs->trans("Movements"), 1, $user->hasRight('stock', 'mouvement', 'lire'));
- $newmenu->add("/product/stock/massstockmove.php", $langs->trans("MassStockTransferShort"), 1, $user->hasRight('stock', 'mouvement', 'creer'));
+ $newmenu->add("/product/stock/massstockmove.php?init=1", $langs->trans("MassStockTransferShort"), 1, $user->hasRight('stock', 'mouvement', 'creer'));
if (isModEnabled('supplier_order')) {
$newmenu->add("/product/stock/replenish.php", $langs->trans("Replenishment"), 1, $user->hasRight('stock', 'mouvement', 'creer') && $user->hasRight('fournisseur', 'lire'));
}
diff --git a/htdocs/langs/en_US/stocks.lang b/htdocs/langs/en_US/stocks.lang
index b575e7fcd4b..f789ce283e5 100644
--- a/htdocs/langs/en_US/stocks.lang
+++ b/htdocs/langs/en_US/stocks.lang
@@ -49,7 +49,7 @@ StockCorrection=Stock correction
CorrectStock=Correct stock
StockTransfer=Stock transfer
TransferStock=Transfer stock
-MassStockTransferShort=Mass stock transfer
+MassStockTransferShort=Bulk stock change
StockMovement=Stock movement
StockMovements=Stock movements
NumberOfUnit=Number of units
@@ -147,8 +147,9 @@ Replenishments=Replenishments
NbOfProductBeforePeriod=Quantity of product %s in stock before selected period (< %s)
NbOfProductAfterPeriod=Quantity of product %s in stock after selected period (> %s)
MassMovement=Mass movement
-SelectProductInAndOutWareHouse=Select a source warehouse and a target warehouse, a product and a quantity then click "%s". Once this is done for all required movements, click on "%s".
+SelectProductInAndOutWareHouse=Select a source warehouse (optional), a target warehouse, a product and a quantity then click "%s". Once this is done for all required movements, click on "%s".
RecordMovement=Record transfer
+RecordMovements=Record stock movements
ReceivingForSameOrder=Receipts for this order
StockMovementRecorded=Stock movements recorded
RuleForStockAvailability=Rules on stock requirements
diff --git a/htdocs/product/stock/index.php b/htdocs/product/stock/index.php
index dcf53a760b1..896ba2e20ba 100644
--- a/htdocs/product/stock/index.php
+++ b/htdocs/product/stock/index.php
@@ -162,7 +162,7 @@ if ($resql) {
print '';
print ' ';
- print "";
+ print ' ';
print '| '.$langs->trans("LastMovements", min($num, $max)).' | ';
print ''.$langs->trans("Product").' | ';
if (isModEnabled('productbatch')) {
@@ -202,7 +202,7 @@ if ($resql) {
print ' ';
print '| '.img_picto($langs->trans("Ref").' '.$objp->mid, 'movement', 'class="pictofixedwidth"').dol_print_date($db->jdate($objp->datem), 'dayhour').' | ';
- print '';
+ print ' | ';
print $producttmp->getNomUrl(1);
print " | \n";
if (isModEnabled('productbatch')) {
@@ -216,7 +216,7 @@ if ($resql) {
print ''.dol_print_date($db->jdate($objp->eatby), 'day').' | ';
}*/
}
- print '';
+ print ' | ';
print $warehouse->getNomUrl(1);
print " | \n";
print '';
diff --git a/htdocs/product/stock/massstockmove.php b/htdocs/product/stock/massstockmove.php
index 0c41cbed44a..df0eb013397 100644
--- a/htdocs/product/stock/massstockmove.php
+++ b/htdocs/product/stock/massstockmove.php
@@ -1,5 +1,5 @@
+/* Copyright (C) 2013-2022 Laurent Destaileur
* Copyright (C) 2014 Regis Houssin
*
* This program is free software: you can redistribute it and/or modify
@@ -77,6 +77,9 @@ if (!$sortorder) {
$limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit;
$offset = $limit * $page;
+if (GETPOST('init')) {
+ unset($_SESSION['massstockmove']);
+}
$listofdata = array();
if (!empty($_SESSION['massstockmove'])) {
$listofdata = json_decode($_SESSION['massstockmove'], true);
@@ -88,13 +91,12 @@ if (!empty($_SESSION['massstockmove'])) {
*/
if ($action == 'addline' && !empty($user->rights->stock->mouvement->creer)) {
- if (!($id_product > 0)) {
- $error++;
- setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Product")), null, 'errors');
- }
if (!($id_sw > 0)) {
- $error++;
- setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("WarehouseSource")), null, 'errors');
+ //$error++;
+ //setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("WarehouseSource")), null, 'errors');
+ if ($id_sw < 0) {
+ $id_sw = 0;
+ }
}
if (!($id_tw > 0)) {
$error++;
@@ -105,6 +107,10 @@ if ($action == 'addline' && !empty($user->rights->stock->mouvement->creer)) {
$langs->load("errors");
setEventMessages($langs->trans("ErrorWarehouseMustDiffers"), null, 'errors');
}
+ if (!($id_product > 0)) {
+ $error++;
+ setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Product")), null, 'errors');
+ }
if (!$qty) {
$error++;
setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Qty")), null, 'errors');
@@ -132,6 +138,7 @@ if ($action == 'addline' && !empty($user->rights->stock->mouvement->creer)) {
}
}
+ //var_dump($_SESSION['massstockmove']);exit;
if (!$error) {
if (count(array_keys($listofdata)) > 0) {
$id = max(array_keys($listofdata)) + 1;
@@ -197,20 +204,22 @@ if ($action == 'createmovements' && !empty($user->rights->stock->mouvement->cree
//print 'price src='.$pricesrc.', price dest='.$pricedest;exit;
- if (empty($conf->productbatch->enabled) || !$product->hasbatch()) { // If product does not need lot/serial
- // Remove stock
- $result1 = $product->correct_stock(
- $user,
- $id_sw,
- $qty,
- 1,
- GETPOST("label"),
- $pricesrc,
- GETPOST("codemove")
- );
- if ($result1 < 0) {
- $error++;
- setEventMessages($product->error, $product->errors, 'errors');
+ if (empty($conf->productbatch->enabled) || !$product->hasbatch()) { // If product does not need lot/serial
+ // Remove stock if source warehouse defined
+ if ($id_sw > 0) {
+ $result1 = $product->correct_stock(
+ $user,
+ $id_sw,
+ $qty,
+ 1,
+ GETPOST("label"),
+ $pricesrc,
+ GETPOST("codemove")
+ );
+ if ($result1 < 0) {
+ $error++;
+ setEventMessages($product->error, $product->errors, 'errors');
+ }
}
// Add stock
@@ -244,21 +253,23 @@ if ($action == 'createmovements' && !empty($user->rights->stock->mouvement->cree
}
// Remove stock
- $result1 = $product->correct_stock_batch(
- $user,
- $id_sw,
- $qty,
- 1,
- GETPOST("label"),
- $pricesrc,
- $dlc,
- $dluo,
- $batch,
- GETPOST("codemove")
- );
- if ($result1 < 0) {
- $error++;
- setEventMessages($product->error, $product->errors, 'errors');
+ if ($id_sw > 0) {
+ $result1 = $product->correct_stock_batch(
+ $user,
+ $id_sw,
+ $qty,
+ 1,
+ GETPOST("label"),
+ $pricesrc,
+ $dlc,
+ $dluo,
+ $batch,
+ GETPOST("codemove")
+ );
+ if ($result1 < 0) {
+ $error++;
+ setEventMessages($product->error, $product->errors, 'errors');
+ }
}
// Add stock
@@ -285,6 +296,7 @@ if ($action == 'createmovements' && !empty($user->rights->stock->mouvement->cree
}
}
}
+ //var_dump($_SESSION['massstockmove']);exit;
if (!$error) {
unset($_SESSION['massstockmove']);
@@ -465,9 +477,9 @@ llxHeader('', $title, $help_url);
print load_fiche_titre($langs->trans("MassStockTransferShort"), '', 'stock');
$titletoadd = $langs->trans("Select");
-$buttonrecord = $langs->trans("RecordMovement");
+$buttonrecord = $langs->trans("RecordMovements");
$titletoaddnoent = $langs->transnoentitiesnoconv("Select");
-$buttonrecordnoent = $langs->transnoentitiesnoconv("RecordMovement");
+$buttonrecordnoent = $langs->transnoentitiesnoconv("RecordMovements");
print ''.$langs->trans("SelectProductInAndOutWareHouse", $titletoaddnoent, $buttonrecordnoent).' ';
print ' ';
@@ -569,25 +581,25 @@ $param = '';
print '';
print getTitleFieldOfList($langs->trans('WarehouseSource'), 0, $_SERVER["PHP_SELF"], '', $param, '', '', $sortfield, $sortorder, 'tagtd maxwidthonsmartphone ');
print getTitleFieldOfList($langs->trans('WarehouseTarget'), 0, $_SERVER["PHP_SELF"], '', $param, '', '', $sortfield, $sortorder, 'tagtd maxwidthonsmartphone ');
-print getTitleFieldOfList($langs->trans('ProductRef'), 0, $_SERVER["PHP_SELF"], '', $param, '', '', $sortfield, $sortorder, 'tagtd maxwidthonsmartphone ');
+print getTitleFieldOfList($langs->trans('Product'), 0, $_SERVER["PHP_SELF"], '', $param, '', '', $sortfield, $sortorder, 'tagtd maxwidthonsmartphone ');
if (isModEnabled('productbatch')) {
print getTitleFieldOfList($langs->trans('Batch'), 0, $_SERVER["PHP_SELF"], '', $param, '', '', $sortfield, $sortorder, 'tagtd maxwidthonsmartphone ');
}
-print getTitleFieldOfList($langs->trans('Qty'), 0, $_SERVER["PHP_SELF"], '', $param, '', '', $sortfield, $sortorder, 'center tagtd maxwidthonsmartphone ');
+print getTitleFieldOfList($langs->trans('Qty'), 0, $_SERVER["PHP_SELF"], '', $param, '', '', $sortfield, $sortorder, 'right tagtd maxwidthonsmartphone ');
print getTitleFieldOfList('', 0);
print ' ';
print '';
// From warehouse
-print '| ';
+print ' | ';
print img_picto($langs->trans("WarehouseSource"), 'stock', 'class="paddingright"').$formproduct->selectWarehouses($id_sw, 'id_sw', 'warehouseopen,warehouseinternal', 1, 0, 0, '', 0, 0, array(), 'minwidth200imp maxwidth200');
print ' | ';
// To warehouse
-print '';
+print ' | ';
print img_picto($langs->trans("WarehouseTarget"), 'stock', 'class="paddingright"').$formproduct->selectWarehouses($id_tw, 'id_tw', 'warehouseopen,warehouseinternal', 1, 0, 0, '', 0, 0, array(), 'minwidth200imp maxwidth200');
print ' | ';
// Product
-print '';
+print ' | ';
$filtertype = 0;
if (!empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
$filtertype = '';
@@ -603,13 +615,13 @@ print $form->select_produits($id_product, 'productid', $filtertype, $limit, 0, -
print ' | ';
// Batch number
if (isModEnabled('productbatch')) {
- print '';
+ print ' | ';
print img_picto($langs->trans("LotSerial"), 'lot', 'class="paddingright"');
- print '';
+ print '';
print ' | ';
}
// Qty
-print ' | ';
+print ' | ';
// Button to add line
print ' | ';
@@ -617,18 +629,25 @@ print ' ';
foreach ($listofdata as $key => $val) {
$productstatic->fetch($val['id_product']);
- $warehousestatics->fetch($val['id_sw']);
- $warehousestatict->fetch($val['id_tw']);
+
+ $warehousestatics->id = 0;
+ $warehousestatict->id = 0;
+ if ($val['id_sw'] > 0) {
+ $warehousestatics->fetch($val['id_sw']);
+ }
+ if ($val['id_tw'] > 0) {
+ $warehousestatict->fetch($val['id_tw']);
+ }
if ($productstatic->id <= 0) {
$error++;
setEventMessages($langs->trans("ObjectNotFound", $langs->transnoentitiesnoconv("Product")), null, 'errors');
}
- if ($warehousestatics->id <= 0) {
+ if ($warehousestatics->id < 0) { // We accept 0 for source warehouse id
$error++;
setEventMessages($langs->trans("ObjectNotFound", $langs->transnoentitiesnoconv("WarehouseSource")), null, 'errors');
}
- if ($warehousestatics->id <= 0) {
+ if ($warehousestatict->id <= 0) {
$error++;
setEventMessages($langs->trans("ObjectNotFound", $langs->transnoentitiesnoconv("WarehouseTarget")), null, 'errors');
}
@@ -636,7 +655,13 @@ foreach ($listofdata as $key => $val) {
if (!$error) {
print '';
print '| ';
- print $warehousestatics->getNomUrl(1);
+ if ($warehousestatics->id > 0) {
+ print $warehousestatics->getNomUrl(1);
+ } else {
+ print '';
+ print $langs->trans("None");
+ print '';
+ }
print ' | ';
print '';
print $warehousestatict->getNomUrl(1);
@@ -649,7 +674,7 @@ foreach ($listofdata as $key => $val) {
print dol_escape_htmltag($val['batch']);
print ' | ';
}
- print ''.price2num((float) $val['qty'], 'MS').' | ';
+ print ''.price2num((float) $val['qty'], 'MS').' | ';
print ''.img_delete($langs->trans("Remove")).' | ';
print ' ';
}
@@ -670,7 +695,7 @@ if (count($listofdata)) {
// Button to record mass movement
$codemove = (GETPOSTISSET("codemove") ? GETPOST("codemove", 'alpha') : dol_print_date(dol_now(), '%Y%m%d%H%M%S'));
- $labelmovement = GETPOST("label") ? GETPOST('label') : $langs->trans("StockTransfer").' '.dol_print_date($now, '%Y-%m-%d %H:%M');
+ $labelmovement = GETPOST("label") ? GETPOST('label') : $langs->trans("MassStockTransferShort").' '.dol_print_date($now, '%Y-%m-%d %H:%M');
print '';
print ''.$langs->trans("InventoryCode").': ';
@@ -696,6 +721,7 @@ if ($action == 'delete') {
llxFooter();
$db->close();
+
/**
* Verify if $haystack startswith $needle
*
diff --git a/htdocs/product/stock/movement_list.php b/htdocs/product/stock/movement_list.php
index 171ee79be9d..56030347d12 100644
--- a/htdocs/product/stock/movement_list.php
+++ b/htdocs/product/stock/movement_list.php
@@ -600,7 +600,6 @@ if (!empty($conf->project->enabled)) {
}
// Build and execute select
-// --------------------------------------------------------------------
$sql = "SELECT p.rowid, p.ref as product_ref, p.label as produit, p.tosell, p.tobuy, p.tobatch, p.fk_product_type as type, p.entity,";
$sql .= " e.ref as warehouse_ref, e.rowid as entrepot_id, e.lieu, e.fk_parent, e.statut,";
$sql .= " m.rowid as mid, m.value as qty, m.datem, m.fk_user_author, m.label, m.inventorycode, m.fk_origin, m.origintype,";
@@ -691,32 +690,6 @@ include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php';
$parameters = array();
$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters); // Note that $action and $object may have been modified by hook
$sql .= $hookmanager->resPrint;
-
-/* If a group by is required
- $sql .= " GROUP BY ";
- foreach($object->fields as $key => $val) {
- $sql .= "t.".$key.", ";
- }
- // Add fields from extrafields
- if (!empty($extrafields->attributes[$object->table_element]['label'])) {
- foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) {
- $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? "ef.".$key.', ' : '');
- }
- }
- // Add where from hooks
- $parameters = array();
- $reshook = $hookmanager->executeHooks('printFieldListGroupBy', $parameters, $object); // Note that $action and $object may have been modified by hook
- $sql .= $hookmanager->resPrint;
- $sql = preg_replace('/,\s*$/', '', $sql);
- */
-
-// Add HAVING from hooks
-/*
- $parameters = array();
- $reshook = $hookmanager->executeHooks('printFieldListHaving', $parameters, $object); // Note that $action and $object may have been modified by hook
- $sql .= empty($hookmanager->resPrint) ? "" : " HAVING 1=1 ".$hookmanager->resPrint;
- */
-
// Count total nb of records
$nbtotalofrecords = '';
if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {
@@ -1369,7 +1342,7 @@ while ($i < ($limit ? min($num, $limit) : $num)) {
print ' ';
// Id movement
if (!empty($arrayfields['m.rowid']['checked'])) {
- print '| ';
+ print ' | ';
print img_picto($langs->trans("StockMovement"), 'movement', 'class="pictofixedwidth"');
print $obj->mid;
print ' | '; // This is primary not movement id
| |