NEW Page for mass stock transfer can be used with no source stock

This commit is contained in:
Laurent Destailleur 2022-11-12 02:16:50 +01:00
parent e466ba0d3a
commit e6d9b02fe0
7 changed files with 89 additions and 89 deletions

View File

@ -1091,7 +1091,7 @@ if (isModEnabled('commande') && $user->rights->commande->lire) {
print '</table>';
print '</td>';
print '<td class="nowrap">'.$companystatic->getNomUrl(1, 'customer', 44).'</td>';
print '<td class="tdoverflowmax150">'.$companystatic->getNomUrl(1, 'customer', 44).'</td>';
$datem = $db->jdate($obj->dv);
print '<td class="center tddate" title="'.dol_escape_htmltag($langs->trans("DateValue").': '.dol_print_date($datem, 'day', 'tzserver')).'">';
print dol_print_date($datem, 'day', 'tzserver');

View File

@ -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&amp;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&amp;leftmenu=cat&amp;type=0', 'Categories', 0, 'categories', '$user->rights->categorie->lire', '', 2, 4, __ENTITY__);

View File

@ -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'));
}

View File

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

View File

@ -162,7 +162,7 @@ if ($resql) {
print '<div class="div-table-responsive-no-min">';
print '<table class="noborder centpercent">';
print "<tr class=\"liste_titre\">";
print '<tr class="liste_titre">';
print '<th>'.$langs->trans("LastMovements", min($num, $max)).'</th>';
print '<th>'.$langs->trans("Product").'</th>';
if (isModEnabled('productbatch')) {
@ -202,7 +202,7 @@ if ($resql) {
print '<tr class="oddeven">';
print '<td class="nowraponall">'.img_picto($langs->trans("Ref").' '.$objp->mid, 'movement', 'class="pictofixedwidth"').dol_print_date($db->jdate($objp->datem), 'dayhour').'</td>';
print '<td class="tdoverflowmax200">';
print '<td class="tdoverflowmax150">';
print $producttmp->getNomUrl(1);
print "</td>\n";
if (isModEnabled('productbatch')) {
@ -216,7 +216,7 @@ if ($resql) {
print '<td>'.dol_print_date($db->jdate($objp->eatby), 'day').'</td>';
}*/
}
print '<td class="tdoverflowmax200">';
print '<td class="tdoverflowmax150">';
print $warehouse->getNomUrl(1);
print "</td>\n";
print '<td class="right">';

View File

@ -1,5 +1,5 @@
<?php
/* Copyright (C) 2013-2021 Laurent Destaileur <ely@users.sourceforge.net>
/* Copyright (C) 2013-2022 Laurent Destaileur <ely@users.sourceforge.net>
* Copyright (C) 2014 Regis Houssin <regis.houssin@inodbox.com>
*
* 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 '<span class="opacitymedium">'.$langs->trans("SelectProductInAndOutWareHouse", $titletoaddnoent, $buttonrecordnoent).'</span><br>';
print '<br>';
@ -569,25 +581,25 @@ $param = '';
print '<tr class="liste_titre">';
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 '</tr>';
print '<tr class="oddeven">';
// From warehouse
print '<td>';
print '<td class="nowraponall">';
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 '</td>';
// To warehouse
print '<td>';
print '<td class="nowraponall">';
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 '</td>';
// Product
print '<td>';
print '<td class="nowraponall">';
$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 '</td>';
// Batch number
if (isModEnabled('productbatch')) {
print '<td>';
print '<td class="nowraponall">';
print img_picto($langs->trans("LotSerial"), 'lot', 'class="paddingright"');
print '<input type="text" name="batch" class="flat maxwidth50" value="'.dol_escape_htmltag($batch).'">';
print '<input type="text" name="batch" class="flat maxwidth75" value="'.dol_escape_htmltag($batch).'">';
print '</td>';
}
// Qty
print '<td class="center"><input type="text" class="flat maxwidth50" name="qty" value="'.price2num((float) $qty, 'MS').'"></td>';
print '<td class="right"><input type="text" class="flat maxwidth50 right" name="qty" value="'.price2num((float) $qty, 'MS').'"></td>';
// Button to add line
print '<td class="right"><input type="submit" class="button" name="addline" value="'.dol_escape_htmltag($titletoadd).'"></td>';
@ -617,18 +629,25 @@ print '</tr>';
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 '<tr class="oddeven">';
print '<td>';
print $warehousestatics->getNomUrl(1);
if ($warehousestatics->id > 0) {
print $warehousestatics->getNomUrl(1);
} else {
print '<span class="opacitymedium">';
print $langs->trans("None");
print '</span>';
}
print '</td>';
print '<td>';
print $warehousestatict->getNomUrl(1);
@ -649,7 +674,7 @@ foreach ($listofdata as $key => $val) {
print dol_escape_htmltag($val['batch']);
print '</td>';
}
print '<td class="center">'.price2num((float) $val['qty'], 'MS').'</td>';
print '<td class="right">'.price2num((float) $val['qty'], 'MS').'</td>';
print '<td class="right"><a href="'.$_SERVER["PHP_SELF"].'?action=delline&token='.newToken().'&idline='.$val['id'].'">'.img_delete($langs->trans("Remove")).'</a></td>';
print '</tr>';
}
@ -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 '<div class="center">';
print '<span class="fieldrequired">'.$langs->trans("InventoryCode").':</span> ';
@ -696,6 +721,7 @@ if ($action == 'delete') {
llxFooter();
$db->close();
/**
* Verify if $haystack startswith $needle
*

View File

@ -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 '<tr class="oddeven">';
// Id movement
if (!empty($arrayfields['m.rowid']['checked'])) {
print '<td>';
print '<td class="nowraponall">';
print img_picto($langs->trans("StockMovement"), 'movement', 'class="pictofixedwidth"');
print $obj->mid;
print '</td>'; // This is primary not movement id