Maxi debug and enhancement of module batch.

This commit is contained in:
Laurent Destailleur 2015-02-11 22:54:06 +01:00
parent 7869bc0d7f
commit 179cbbd187
17 changed files with 412 additions and 243 deletions

View File

@ -77,7 +77,7 @@ class PaymentSocialContribution extends CommonObject
// Validate parametres
if (! $this->datepaye)
{
$this->error='ErrorBadValueForParameter';
$this->error='ErrorBadValueForParameterCreatePaymentSocialContrib';
return -1;
}

View File

@ -111,7 +111,7 @@ class Events // extends CommonObject
$this->description=trim($this->description);
// Check parameters
if (empty($this->description)) { $this->error='ErrorBadValueForParameter'; return -1; }
if (empty($this->description)) { $this->error='ErrorBadValueForParameterCreateEventDesc'; return -1; }
// Insert request
$sql = "INSERT INTO ".MAIN_DB_PREFIX."events(";

View File

@ -19,11 +19,15 @@
// \brief File that include javascript functions used when dispatching batch-enabled product
//
function AddLineBatch(index) {
/**
* @param index int number of produt. 0 = first product line
*/
function addLineBatch(index)
{
var nme = 'dluo_0_'+index;
$row=$("tr[name='"+nme+"']").clone(true);
$row.find("input[name^='qty']").val('');
var trs = $("tr[name^='dluo_'][name$='_"+index+"']");
var trs = $("tr[name^='dluo_'][name$='_"+index+"']"); /* trs.length = position of line for batch */
var newrow=$row.html().replace(/_0_/g,"_"+(trs.length)+"_");
$row.html(newrow);
//clear value
@ -31,4 +35,13 @@ function AddLineBatch(index) {
//change name of row
$row.attr('name','dluo_'+trs.length+'_'+index);
$("tr[name^='dluo_'][name$='_"+index+"']:last").after($row);
}
/* Suffix of lines are: _ trs.length _ index */
jQuery("#lot_number_"+trs.length+"_"+index).focus();
nb = jQuery("#qty_"+(trs.length - 1)+"_"+index).val();
if (nb > 0)
{
jQuery("#qty_"+(trs.length - 1)+"_"+index).val(1);
jQuery("#qty_"+trs.length+"_"+index).val(nb - 1);
}
}

View File

@ -1270,7 +1270,7 @@ class CommandeFournisseur extends CommonOrder
/**
* Add a product into a stock warehouse.
* Save a receiving into the tracking table of receiving (commande_fournisseur_dispatch) and add product into stock warehouse.
*
* @param User $user User object making change
* @param int $product Id of product to dispatch
@ -1283,7 +1283,7 @@ class CommandeFournisseur extends CommonOrder
* @param string $batch Lot number
* @return int <0 if KO, >0 if OK
*/
function DispatchProduct($user, $product, $qty, $entrepot, $price=0, $comment='', $eatby='', $sellby='', $batch='')
function dispatchProduct($user, $product, $qty, $entrepot, $price=0, $comment='', $eatby='', $sellby='', $batch='')
{
global $conf;
$error = 0;
@ -1292,12 +1292,12 @@ class CommandeFournisseur extends CommonOrder
// Check parameters
if ($entrepot <= 0 || $qty <= 0)
{
$this->error='BadValueForParameter';
$this->error='BadValueForParameterWarehouseOrQty';
return -1;
}
$dispatchstatus = 1;
if (! empty($conf->global->SUPPLIER_ORDER_USE_DISPATCH_STATUS)) $dispatchstatus = 0; // Setting status will be done manually to 1 if this option is on
if (! empty($conf->global->SUPPLIER_ORDER_USE_DISPATCH_STATUS)) $dispatchstatus = 0; // Setting dispatch status (a validation step after receiving products) will be done manually to 1 if this option is on
$now=dol_now();
@ -1306,10 +1306,12 @@ class CommandeFournisseur extends CommonOrder
$this->db->begin();
$sql = "INSERT INTO ".MAIN_DB_PREFIX."commande_fournisseur_dispatch";
$sql.= " (fk_commande, fk_product, qty, fk_entrepot, fk_user, datec, status, comment) VALUES";
$sql.= " ('".$this->id."','".$product."','".$qty."',".($entrepot>0?"'".$entrepot."'":"null").",'".$user->id."','".$this->db->idate($now)."', ".$dispatchstatus.", '".$this->db->escape($comment)."')";
$sql.= " (fk_commande, fk_product, qty, fk_entrepot, fk_user, datec, status, comment, eatby, sellby, batch) VALUES";
$sql.= " ('".$this->id."','".$product."','".$qty."',".($entrepot>0?"'".$entrepot."'":"null").",'".$user->id."','".$this->db->idate($now)."', ".$dispatchstatus.", '".$this->db->escape($comment)."', ";
$sql.= ($eatby?"'".$this->db->idate($eatby)."'":"null").", ".($sellby?"'".$this->db->idate($sellby)."'":"null").", ".($batch?"'".$batch."'":"null");
$sql.= ")";
dol_syslog(get_class($this)."::DispatchProduct", LOG_DEBUG);
dol_syslog(get_class($this)."::dispatchProduct", LOG_DEBUG);
$resql = $this->db->query($sql);
if ($resql)
{
@ -1329,7 +1331,7 @@ class CommandeFournisseur extends CommonOrder
$this->db->commit();
}
else
{
{
$this->error=$this->db->lasterror();
$error++;
}
@ -1337,6 +1339,7 @@ class CommandeFournisseur extends CommonOrder
// Si module stock gere et que incrementation faite depuis un dispatching en stock
if (!$error && $entrepot > 0 && ! empty($conf->stock->enabled) && ! empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER))
{
$mouv = new MouvementStock($this->db);
if ($product > 0)
{
@ -1346,7 +1349,7 @@ class CommandeFournisseur extends CommonOrder
if ($result < 0)
{
$this->error=$mouv->error;
dol_syslog(get_class($this)."::DispatchProduct ".$this->error, LOG_ERR);
dol_syslog(get_class($this)."::dispatchProduct ".$this->error, LOG_ERR);
$error++;
}
}

View File

@ -4,7 +4,7 @@
* Copyright (C) 2005 Eric Seigne <eric.seigne@ryxeo.com>
* Copyright (C) 2005-2009 Regis Houssin <regis.houssin@capnetworks.com>
* Copyright (C) 2010 Juanjo Menent <jmenent@2byte.es>
* Copyright (C) 2014 C<EFBFBD>dric Gross <c.gross@kreiz-it.fr>
* Copyright (C) 2014 Cedric Gross <c.gross@kreiz-it.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -24,7 +24,7 @@
/**
* \file htdocs/fourn/commande/dispatch.php
* \ingroup commande
* \brief Fiche de ventilation des commandes fournisseurs
* \brief Page to dispatch receiving
*/
require '../../main.inc.php';
@ -63,6 +63,7 @@ $mesg='';
/*
* Actions
*/
if ($_POST["action"] == 'dispatch' && $user->rights->fournisseur->commande->receptionner)
{
$commande = new CommandeFournisseur($db);
@ -74,7 +75,7 @@ if ($_POST["action"] == 'dispatch' && $user->rights->fournisseur->commande->rece
foreach($_POST as $key => $value)
{
if ( preg_match('/^product_([0-9]+)$/i', $key, $reg) )
if (preg_match('/^product_([0-9]+)$/i', $key, $reg))
{
$prod = "product_".$reg[1];
$qty = "qty_".$reg[1];
@ -82,7 +83,7 @@ if ($_POST["action"] == 'dispatch' && $user->rights->fournisseur->commande->rece
$pu = "pu_".$reg[1]; // This is unit price including discount
if (GETPOST($ent,'int') > 0)
{
$result = $commande->DispatchProduct($user, GETPOST($prod,'int'),GETPOST($qty), GETPOST($ent,'int'), GETPOST($pu), GETPOST("comment"));
$result = $commande->dispatchProduct($user, GETPOST($prod,'int'),GETPOST($qty), GETPOST($ent,'int'), GETPOST($pu), GETPOST("comment"));
if ($result < 0)
{
setEventMessages($commande->error, $commande->errors, 'errors');
@ -115,23 +116,26 @@ if ($_POST["action"] == 'dispatch' && $user->rights->fournisseur->commande->rece
setEventMessage($langs->trans('ErrorFieldRequired',$text), 'errors');
$error++;
}
if (!((GETPOST($qty) > 0 ) && ( $_POST[$lot] or $dDLUO or $dDLC) ))
if (! $error)
{
dol_syslog('No dispatch for line '.$key.' as qty is not set or eat-by date are not set');
$text = $langs->transnoentities('atleast1batchfield').', '.$langs->transnoentities('Line').'' .($reg[1]-1);
setEventMessage($langs->trans('ErrorFieldRequired',$text), 'errors');
$error++;
}
else
{
$result = $commande->DispatchProduct($user, GETPOST($prod,'int'),GETPOST($qty), GETPOST($ent,'int'), GETPOST($pu), GETPOST("comment"), $dDLC, $dDLUO, GETPOST($lot));
if ($result < 0)
if (! ((GETPOST($qty) > 0) && ($_POST[$lot] || $dDLUO || $dDLC)))
{
setEventMessages($commande->error, $commande->errors, 'errors');
dol_syslog('No dispatch for line '.$key.' as qty is not set or eat-by date are not set');
$text = $langs->transnoentities('atleast1batchfield').', '.$langs->transnoentities('Line').'' .($reg[1]-1);
setEventMessage($langs->trans('ErrorFieldRequired',$text), 'errors');
$error++;
}
else
{
$result = $commande->dispatchProduct($user, GETPOST($prod,'int'), GETPOST($qty), GETPOST($ent,'int'), GETPOST($pu), GETPOST("comment"), $dDLC, $dDLUO, GETPOST($lot));
if ($result < 0)
{
setEventMessages($commande->error, $commande->errors, 'errors');
$error++;
}
}
}
}
}
@ -168,13 +172,14 @@ if ($_POST["action"] == 'dispatch' && $user->rights->fournisseur->commande->rece
* View
*/
$help_url='EN:CommandeFournisseur';
if (!empty($conf->productbatch->enabled))
{
llxHeader('',$langs->trans("OrderCard"),"CommandeFournisseur",'',0,0,array('/core/js/lib_batch.js'));
llxHeader('',$langs->trans("OrderCard"),$help_url,'',0,0,array('/core/js/lib_batch.js'));
}
else
{
llxHeader('',$langs->trans("OrderCard"),"CommandeFournisseur");
llxHeader('',$langs->trans("OrderCard"),$help_url);
}
$form = new Form($db);
@ -310,20 +315,25 @@ if ($id > 0 || ! empty($ref))
if ($num)
{
print '<tr class="liste_titre">';
print '<td colspan="4" width="40%">'.$langs->trans("Description").'</td>';
print '<td>'.$langs->trans("Description").'</td>';
print '<td></td>';
print '<td></td>';
print '<td></td>';
print '<td align="right">'.$langs->trans("QtyOrdered").'</td>';
print '<td align="right">'.$langs->trans("QtyDispatched").'</td>';
print '<td align="right">'.$langs->trans("QtyDelivered").'</td>';
print '<td align="right">'.$langs->trans("QtyDispatchedShort").'</td>';
print '<td align="right">'.$langs->trans("QtyToDispatchShort").'</td>';
print '<td align="right">'.$langs->trans("Warehouse").'</td>';
print "</tr>\n";
if (!empty($conf->productbatch->enabled)) {
if (! empty($conf->productbatch->enabled))
{
print '<tr class="liste_titre">';
print '<td width="5%">&nbsp;</td>';
print '<td></td>';
print '<td>'.$langs->trans("batch_number").'</td>';
print '<td>'.$langs->trans("l_eatby").'</td>';
print '<td>'.$langs->trans("l_sellby").'</td>';
print '<td>'.$langs->trans("batch_number").'</td>';
print '<td colspan="4" width="50%">&nbsp;</td>';
print '<td colspan="4">&nbsp;</td>';
print "</tr>\n";
}
@ -346,19 +356,47 @@ if ($id > 0 || ! empty($ref))
{
$remaintodispatch=($objp->qty - (empty($products_dispatched[$objp->fk_product])?0:$products_dispatched[$objp->fk_product])); // Calculation of dispatched
if ($remaintodispatch < 0) $remaintodispatch=0;
if ($remaintodispatch)
if ($remaintodispatch || empty($conf->global->SUPPLIER_ORDER_DISABLE_STOCK_DISPATCH_WHEN_TOTAL_REACHED))
{
$nbproduct++;
$var=!$var;
print "<tr ".$bc[$var].">";
print '<td colspan="4">';
print '<a href="'.DOL_URL_ROOT.'/product/fournisseurs.php?id='.$objp->fk_product.'">'.img_object($langs->trans("ShowProduct"),'product').' '.$objp->ref.'</a>';
print ' - '.$objp->label."\n";
$linktoprod='<a href="'.DOL_URL_ROOT.'/product/fournisseurs.php?id='.$objp->fk_product.'">'.img_object($langs->trans("ShowProduct"),'product').' '.$objp->ref.'</a>';
$linktoprod.=' - '.$objp->label."\n";
if (! empty($conf->productbatch->enabled))
{
if ($objp->tobatch)
{
print '<td colspan="4">';
print $linktoprod;
print "</td>";
}
else
{
print '<td>';
print $linktoprod;
print "</td>";
print '<td colspan="3">';
print $langs->trans("ProductDoesNotUseBatchSerial");
print '</td>';
}
}
else
{
print '<td>';
print $linktoprod;
print "</td>";
}
// To show detail cref and description value, we must make calculation by cref
//print ($objp->cref?' ('.$objp->cref.')':'');
//if ($objp->description) print '<br>'.nl2br($objp->description);
if ((empty($conf->productbatch->enabled)) || $objp->tobatch==0) {
if ((empty($conf->productbatch->enabled)) || $objp->tobatch==0)
{
$suffix='_'.$i;
} else {
$suffix='_0_'.$i;
@ -367,32 +405,44 @@ if ($id > 0 || ! empty($ref))
$up_ht_disc=$objp->subprice;
if (! empty($objp->remise_percent) && empty($conf->global->STOCK_EXCLUDE_DISCOUNT_FOR_PMP)) $up_ht_disc=price2num($up_ht_disc * (100 - $objp->remise_percent) / 100, 'MU');
print "</td>\n";
// Qty ordered
print '<td align="right">'.$objp->qty.'</td>';
// Already dispatched
print '<td align="right">'.$products_dispatched[$objp->fk_product].'</td>';
if ( !(empty($conf->productbatch->enabled)) && $objp->tobatch==1) {
print '<td colspan="2" align="center">'.img_picto_common($langs->trans('AddDispatchBatchLine'),'treemenu/plustop2.gif','onClick="AddLineBatch('.$i.')"').'</td>';
if (! empty($conf->productbatch->enabled) && $objp->tobatch==1)
{
print '<td align="right">'.img_picto($langs->trans('AddDispatchBatchLine'),'split.png','onClick="addLineBatch('.$i.')"').'</td>'; // Dispatch column
print '<td></td>'; // Warehouse column
print '</tr>';
print '<tr '.$bc[$var].' name="dluo'.$suffix.'"><td width="5%">';
print '<tr '.$bc[$var].' name="dluo'.$suffix.'">';
print '<td>';
print '<input name="product'.$suffix.'" type="hidden" value="'.$objp->fk_product.'">';
print '<input name="pu'.$suffix.'" type="hidden" value="'.$up_ht_disc.'"><!-- This is a up including discount -->';
print '</td><td>';
$form->select_date('','dlc'.$suffix,'','',1,"");
print '</td><td>';
$form->select_date('','dluo'.$suffix,'','',1,"");
print '</td><td>';
print '<input type="text" name="lot_number'.$suffix.'" size="40" value="">';
print '</td>';
print '<td colspan="2">&nbsp</td>';
} else {
print '<input name="product'.$suffix.'" type="hidden" value="'.$objp->fk_product.'">';
print '<input name="pu'.$suffix.'" type="hidden" value="'.$up_ht_disc.'"><!-- This is a up including discount -->';
print '<td>';
print '<input type="text" id="lot_number'.$suffix.'" name="lot_number'.$suffix.'" size="40" value="">';
print '</td>';
print '<td>';
$form->select_date('','dlc'.$suffix,'','',1,"");
print '</td>';
print '<td>';
$form->select_date('','dluo'.$suffix,'','',1,"");
print '</td>';
print '<td colspan="2">&nbsp</td>'; // Qty ordered + qty already dispatached
}
// Dispatch
print '<td align="right"><input name="qty'.$suffix.'" type="text" size="8" value="'.($remaintodispatch).'"></td>';
print '<td align="right">';
if (empty($conf->productbatch->enabled) || $objp->tobatch!=1)
{
print '<input name="product'.$suffix.'" type="hidden" value="'.$objp->fk_product.'">';
print '<input name="pu'.$suffix.'" type="hidden" value="'.$up_ht_disc.'"><!-- This is a up including discount -->';
}
print '<input id="qty'.$suffix.'" name="qty'.$suffix.'" type="text" size="8" value="'.($remaintodispatch).'">';
print '</td>';
// Warehouse
print '<td align="right">';
@ -409,6 +459,7 @@ if ($id > 0 || ! empty($ref))
print $langs->trans("NoWarehouseDefined");
}
print "</td>\n";
print "</tr>\n";
}
}
@ -430,11 +481,13 @@ if ($id > 0 || ! empty($ref))
print '<input type="text" size="60" maxlength="128" name="comment" value="';
print $_POST["comment"]?GETPOST("comment"):$langs->trans("DispatchSupplierOrder",$commande->ref);
// print ' / '.$commande->ref_supplier; // Not yet available
print '" class="flat"><br><br>';
print '" class="flat"> &nbsp; ';
print '<div class="center"><input type="submit" class="button" value="'.$langs->trans("DispatchVerb").'"';
//print '<div class="center">';
print '<input type="submit" class="button" value="'.$langs->trans("DispatchVerb").'"';
if (count($listwarehouses) <= 0) print ' disabled="disabled"';
print '></div>';
print '>';
//print '</div>';
}
if (! $nbproduct && $nbfreeproduct)
{
@ -449,7 +502,7 @@ if ($id > 0 || ! empty($ref))
// List of already dispatching
$sql = "SELECT p.ref, p.label,";
$sql.= " e.rowid as warehouse_id, e.label as entrepot,";
$sql.= " cfd.rowid, cfd.fk_product, cfd.qty, cfd.comment, cfd.status";
$sql.= " cfd.rowid, cfd.fk_product, cfd.qty, cfd.eatby, cfd.sellby, cfd.batch, cfd.comment, cfd.status";
$sql.= " FROM ".MAIN_DB_PREFIX."product as p,";
$sql.= " ".MAIN_DB_PREFIX."commande_fournisseur_dispatch as cfd";
$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."entrepot as e ON cfd.fk_entrepot = e.rowid";
@ -473,6 +526,12 @@ if ($id > 0 || ! empty($ref))
print '<tr class="liste_titre">';
print '<td>'.$langs->trans("Description").'</td>';
if (! empty($conf->productbatch->enabled))
{
print '<td>'.$langs->trans("batch_number").'</td>';
print '<td>'.$langs->trans("l_eatby").'</td>';
print '<td>'.$langs->trans("l_sellby").'</td>';
}
print '<td align="right">'.$langs->trans("QtyDispatched").'</td>';
print '<td></td>';
print '<td>'.$langs->trans("Warehouse").'</td>';
@ -491,6 +550,13 @@ if ($id > 0 || ! empty($ref))
print ' - '.$objp->label;
print "</td>\n";
if (! empty($conf->productbatch->enabled))
{
print '<td>'.$objp->batch.'</td>';
print '<td>'.dol_print_date($db->jdate($objp->eatby),'day').'</td>';
print '<td>'.dol_print_date($db->jdate($objp->sellby),'day').'</td>';
}
// Qty
print '<td align="right">'.$objp->qty.'</td>';
print '<td>&nbsp;</td>';

View File

@ -105,6 +105,8 @@ ALTER TABLE llx_product_fournisseur_price ADD COLUMN delivery_time_days integer;
ALTER TABLE llx_commande_fournisseur_dispatch ADD COLUMN comment varchar(255);
ALTER TABLE llx_commande_fournisseur_dispatch ADD COLUMN status integer;
ALTER TABLE llx_commande_fournisseur_dispatch ADD COLUMN tms timestamp;
ALTER TABLE llx_commande_fournisseur_dispatch ADD COLUMN eatby date DEFAULT NULL;
ALTER TABLE llx_commande_fournisseur_dispatch ADD COLUMN sellby date DEFAULT NULL;
ALTER TABLE llx_commande_fournisseur_dispatch ADD COLUMN batch varchar(30) DEFAULT NULL;

View File

@ -14,6 +14,9 @@
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- This table is just an history table to track all receiving done for a
-- particular supplier order. A movement with same information is also done
-- into stock_movement so this table may be useless.
-- ===================================================================
create table llx_commande_fournisseur_dispatch
@ -25,6 +28,9 @@ create table llx_commande_fournisseur_dispatch
fk_entrepot integer,
fk_user integer,
comment varchar(255), -- comment on movement
eatby date DEFAULT NULL,
sellby date DEFAULT NULL,
batch varchar(30) DEFAULT NULL,
status integer,
datec datetime,
tms timestamp

View File

@ -158,6 +158,8 @@ ErrorPriceExpression21=Empty result '%s'
ErrorPriceExpression22=Negative result '%s'
ErrorPriceExpressionInternal=Internal error '%s'
ErrorPriceExpressionUnknown=Unknown error '%s'
ErrorSrcAndTargetWarehouseMustDiffers=Source and target warehouses must differs
ErrorTryToMakeMoveOnProductRequiringBatchData=Error, trying to make a stock movement without batch/serial information, on a product requiring batch/serial information
# Warnings
WarningMandatorySetupNotComplete=Mandatory setup parameters are not yet defined

View File

@ -1,9 +1,9 @@
# ProductBATCH language file - en_US - ProductBATCH
ManageLotSerial=Manage batch/serial
ProductStatusOnBatch=Managed
ProductStatusNotOnBatch=Not Managed
ProductStatusOnBatchShort=Managed
ProductStatusNotOnBatchShort=Not Managed
ManageLotSerial=Use batch/serial number
ProductStatusOnBatch=Yes (Batch/serial required)
ProductStatusNotOnBatch=No (Batch/serial not used)
ProductStatusOnBatchShort=Yes
ProductStatusNotOnBatchShort=No
Batch=Batch/Serial
atleast1batchfield=Eat-by date or Sell-by date or Batch number
batch_number=Batch/Serial number
@ -18,3 +18,4 @@ printQty=Qty: %d
AddDispatchBatchLine=Add a line for Shelf Life dispatching
BatchDefaultNumber=Undefined
WhenProductBatchModuleOnOptionAreForced=When module Batch/Serial is on, increase/decrease stock mode is forced to last choice and can't be edited. Other options can be defined as you want.
ProductDoesNotUseBatchSerial=This product does not use batch/serial number

View File

@ -48,6 +48,8 @@ PMPValueShort=WAP
EnhancedValueOfWarehouses=Warehouses value
UserWarehouseAutoCreate=Create a warehouse automatically when creating a user
QtyDispatched=Quantity dispatched
QtyDispatchedShort=Qty dispatched
QtyToDispatchShort=Qty to dispatch
OrderDispatch=Stock dispatching
RuleForStockManagementDecrease=Rule for stock management decrease
RuleForStockManagementIncrease=Rule for stock management increase
@ -125,3 +127,4 @@ StockMustBeEnoughForShipment= Stock level must be enough to add product/service
MovementLabel=Label of movement
InventoryCode=Inventory code
IsInPackage=Contained into package
ShowWarehouse=Show warehouse

View File

@ -122,4 +122,3 @@ RuleForStockAvailability=Règles d'exigence sur les stocks
StockMustBeEnoughForInvoice=Le niveau de stock doit être suffisant pour ajouter un produit/service dans une facture
StockMustBeEnoughForOrder=Le niveau de stock doit être suffisant pour ajouter un produit/service dans une commande
StockMustBeEnoughForShipment= Le niveau de stock doit être suffisant pour ajouter un produit/service dans une expédition

View File

@ -3057,6 +3057,51 @@ class Product extends CommonObject
}
}
/**
* Adjust stock in a warehouse for product with batch number
*
* @param User $user user asking change
* @param int $id_entrepot id of warehouse
* @param double $nbpiece nb of units
* @param int $movement 0 = add, 1 = remove
* @param string $label Label of stock movement
* @param double $price Price to use for stock eval
* @param date $dlc eat-by date
* @param date $dluo sell-by date
* @param string $lot Lot number
* @param string $inventorycode Inventory code
* @return int <0 if KO, >0 if OK
*/
function correct_stock_batch($user, $id_entrepot, $nbpiece, $movement, $label='', $price=0, $dlc='', $dluo='',$lot='', $inventorycode='')
{
if ($id_entrepot)
{
$this->db->begin();
require_once DOL_DOCUMENT_ROOT .'/product/stock/class/mouvementstock.class.php';
$op[0] = "+".trim($nbpiece);
$op[1] = "-".trim($nbpiece);
$movementstock=new MouvementStock($this->db);
$result=$movementstock->_create($user,$this->id,$id_entrepot,$op[$movement],$movement,$price,$label,$inventorycode,'',$dlc,$dluo,$lot);
if ($result >= 0)
{
$this->db->commit();
return 1;
}
else
{
$this->error=$movementstock->error;
$this->errors=$movementstock->errors;
$this->db->rollback();
return -1;
}
}
}
/**
* Load information about stock of a product into stock_warehouse[] and stock_reel
*
@ -3646,48 +3691,6 @@ class Product extends CommonObject
return ($this->status_batch == 1 ? true : false);
}
/**
* Adjust stock in a warehouse for product with batch number
*
* @param User $user user asking change
* @param int $id_entrepot id of warehouse
* @param double $nbpiece nb of units
* @param int $movement 0 = add, 1 = remove
* @param string $label Label of stock movement
* @param double $price Price to use for stock eval
* @param date $dlc eat-by date
* @param date $dluo sell-by date
* @param string $lot Lot number
* @param string $inventorycode Inventory code
* @return int <0 if KO, >0 if OK
*/
function correct_stock_batch($user, $id_entrepot, $nbpiece, $movement, $label='', $price=0, $dlc='', $dluo='',$lot='', $inventorycode='')
{
if ($id_entrepot)
{
$this->db->begin();
require_once DOL_DOCUMENT_ROOT .'/product/stock/class/mouvementstock.class.php';
$op[0] = "+".trim($nbpiece);
$op[1] = "-".trim($nbpiece);
$movementstock=new MouvementStock($this->db);
$result=$movementstock->_create($user,$this->id,$id_entrepot,$op[$movement],$movement,$price,$label,$inventorycode,'',$dlc,$dluo,$lot);
if ($result >= 0)
{
$this->db->commit();
return 1;
}
else
{
$this->error=$movementstock->error;
$this->db->rollback();
return -1;
}
}
}
/**
* Return minimum product recommended price

View File

@ -87,13 +87,12 @@ class Productbatch extends CommonObject
$sql.= "import_key";
$sql.= ") VALUES (";
$sql.= " ".(! isset($this->fk_product_stock)?'NULL':$this->fk_product_stock).",";
$sql.= " ".(! isset($this->sellby) || dol_strlen($this->sellby)==0?'NULL':$this->db->idate($this->sellby)).",";
$sql.= " ".(! isset($this->eatby) || dol_strlen($this->eatby)==0?'NULL':$this->db->idate($this->eatby)).",";
$sql.= " ".(! isset($this->sellby) || dol_strlen($this->sellby)==0?'NULL':"'".$this->db->idate($this->sellby)."'").",";
$sql.= " ".(! isset($this->eatby) || dol_strlen($this->eatby)==0?'NULL':"'".$this->db->idate($this->eatby)."'").",";
$sql.= " ".(! isset($this->batch)?'NULL':"'".$this->db->escape($this->batch)."'").",";
$sql.= " ".(! isset($this->qty)?'NULL':$this->qty).",";
$sql.= " ".(! isset($this->import_key)?'NULL':"'".$this->db->escape($this->import_key)."'")."";
$sql.= ")";
$this->db->begin();
@ -122,11 +121,6 @@ class Productbatch extends CommonObject
// Commit or rollback
if ($error)
{
foreach($this->errors as $errmsg)
{
dol_syslog(get_class($this)."::create ".$errmsg, LOG_ERR);
$this->error.=($this->error?', '.$errmsg:$errmsg);
}
$this->db->rollback();
return -1*$error;
}

View File

@ -510,6 +510,7 @@ class Entrepot extends CommonObject
function getNomUrl($withpicto=0,$option='')
{
global $langs;
$langs->load("stocks");
$result='';
$label = '<u>' . $langs->trans("ShowWarehouse").'</u>';

View File

@ -74,7 +74,7 @@ class MouvementStock extends CommonObject
// Clean parameters
if (empty($price)) $price=0;
$now=(! empty($datem) ? $datem : dol_now());
// Check parameters
if (empty($fk_product)) return 0;
@ -83,7 +83,7 @@ class MouvementStock extends CommonObject
$this->entrepot_id = $entrepot_id;
$this->qty = $qty;
$this->type = $type;
$this->db->begin();
$product = new Product($this->db);
@ -94,7 +94,20 @@ class MouvementStock extends CommonObject
return -1;
}
$product->load_stock();
// Test if product require batch data. If yes, and there is not, we throw an error.
if ($product->hasbatch() && ! $skip_sellby)
{
if (empty($batch) && empty($eatby) && empty($sellby))
{
$this->errors[]="ErrorTryToMakeMoveOnProductRequiringBatchData";
dol_syslog("Try to make a movement of a product with status_batch on without any batch data");
$this->db->rollback();
return -2;
}
}
// Define if we must make the stock change (If product type is a service or if stock is used also for services)
$movestock=0;
if ($product->type != 1 || ! empty($conf->global->STOCK_SUPPORTS_SERVICES)) $movestock=1;
@ -110,7 +123,7 @@ class MouvementStock extends CommonObject
}
$mvid = 0;
$sql = "INSERT INTO ".MAIN_DB_PREFIX."stock_mouvement";
$sql.= " (datem, fk_product, fk_entrepot, value, type_mouvement, fk_user_author, label, inventorycode, price, fk_origin, origintype)";
$sql.= " VALUES ('".$this->db->idate($now)."', ".$this->product_id.", ".$this->entrepot_id.", ".$this->qty.", ".$this->type.",";
@ -127,7 +140,7 @@ class MouvementStock extends CommonObject
if ($resql)
{
$mvid = $this->db->last_insert_id(MAIN_DB_PREFIX."stock_mouvement");
$this->id = $mvid;
$this->id = $mvid;
}
else
{
@ -190,11 +203,11 @@ class MouvementStock extends CommonObject
$this->error=$this->db->lasterror();
$error = -4;
}
$oldqtytouse=($oldqty >= 0?$oldqty:0);
// We make a test on oldpmp>0 to avoid to use normal rule on old data with no pmp field defined
if ($oldpmp > 0) $newpmp=price2num((($oldqtytouse * $oldpmp) + ($qty * $price)) / ($oldqtytouse + $qty), 'MU');
else
else
{
$newpmp=$price; // For this product, PMP was not yet set. We will set it later.
}
@ -208,7 +221,7 @@ class MouvementStock extends CommonObject
}
else if ($type == 1 || $type == 2)
{
// After a stock decrease, we don't change value of PMP for product.
// After a stock decrease, we don't change value of PMP for product.
}
else
{
@ -217,7 +230,7 @@ class MouvementStock extends CommonObject
}
}
*/
// Update denormalized value of stock in product_stock and product
if (! $error)
{
@ -239,7 +252,7 @@ class MouvementStock extends CommonObject
{
$this->error=$this->db->lasterror();
$error = -3;
}
}
else if(empty($fk_product_stock))
{
$fk_product_stock = $this->db->last_insert_id(MAIN_DB_PREFIX."product_stock");
@ -250,7 +263,7 @@ class MouvementStock extends CommonObject
// Update detail stock for sell-by date
if (($product->hasbatch()) && (! $error) && (! $skip_sellby))
{
$param_batch=array('fk_product_stock' =>$fk_product_stock, 'eatby'=>$eatby,'sellby'=>$sellby,'batchnumber'=>$batch);
$param_batch=array('fk_product_stock' =>$fk_product_stock, 'eatby'=>$eatby, 'sellby'=>$sellby, 'batchnumber'=>$batch);
$result=$this->_create_batch($param_batch, $qty);
if ($result<0) $error++;
}
@ -282,7 +295,7 @@ class MouvementStock extends CommonObject
{
// Call trigger
$result=$this->call_trigger('STOCK_MOVEMENT',$user);
if ($result < 0) $error++;
if ($result < 0) $error++;
// End call triggers
}
@ -324,7 +337,7 @@ class MouvementStock extends CommonObject
$sql.= " WHERE fk_product_pere = ".$idProduct;
// TODO Select only subproduct with incdec tag
//$sql.= " AND incdec = 1";
dol_syslog(get_class($this)."::_createSubProduct", LOG_DEBUG);
$resql=$this->db->query($sql);
if ($resql)
@ -427,7 +440,7 @@ class MouvementStock extends CommonObject
/**
* Count number of product in stock before a specific date
*
*
* @param int $productidselected Id of product to count
* @param timestamp $datebefore Date limit
* @return int Number
@ -435,11 +448,11 @@ class MouvementStock extends CommonObject
function calculateBalanceForProductBefore($productidselected, $datebefore)
{
$nb=0;
$sql = 'SELECT SUM(value) as nb from '.MAIN_DB_PREFIX.'stock_mouvement';
$sql.= ' WHERE fk_product = '.$productidselected;
$sql.= " AND datem < '".$this->db->idate($datebefore)."'";
dol_syslog(get_class($this).__METHOD__.'', LOG_DEBUG);
$resql=$this->db->query($sql);
if ($resql)
@ -448,7 +461,7 @@ class MouvementStock extends CommonObject
if ($obj) $nb = $obj->nb;
return (empty($nb)?0:$nb);
}
else
else
{
dol_print_error($this->db);
return -1;
@ -462,10 +475,13 @@ class MouvementStock extends CommonObject
* @param int $qty Quantity of product with batch number
* @return int <0 if KO, else return productbatch id
*/
function _create_batch($dluo, $qty ) {
$pdluo=New Productbatch($this->db);
//Try to find an existing record with batch same batch number or id
function _create_batch($dluo, $qty )
{
$pdluo=new Productbatch($this->db);
$result=0;
// Try to find an existing record with batch same batch number or id
if (is_numeric($dluo)) {
$result=$pdluo->fetch($dluo);
} else if (is_array($dluo)) {
@ -481,25 +497,34 @@ class MouvementStock extends CommonObject
}
} else {
dol_syslog(get_class($this)."::_create_batch error invalid param dluo".$error, LOG_ERR);
$result = -1;
$result = -1;
}
//batch record found so we update it
if ($result>0) {
if ($pdluo->id >0) {
if ($result>0)
{
if ($pdluo->id >0)
{
$pdluo->qty +=$qty;
if ($pdluo->qty == 0) {
$result=$pdluo->delete(0,1);
} else {
$result=$pdluo->update(0,1);
}
} else {
}
else
{
$pdluo->fk_product_stock=$vfk_product_stock;
$pdluo->qty = $qty;
$pdluo->eatby = $veatby;
$pdluo->sellby = $vsellby;
$pdluo->batch = $vbatchnumber;
$result=$pdluo->create(0,1);
if ($result < 0)
{
$this->error=$pdluo->error;
$this->errors=$pdluo->errors;
}
}
return $result;
} else {
@ -537,12 +562,12 @@ class MouvementStock extends CommonObject
require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
$origin = new FactureFournisseur($this->db);
break;
default:
return '';
break;
}
$origin->fetch($fk_origin);
return $origin->getNomUrl(1);
}

View File

@ -78,10 +78,10 @@ if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter")) // Both
* Actions
*/
if ($cancel) $action='';
if ($cancel) $action=''; // Protection to avoid action for all cancel buttons
// Correct stock
if ($action == "correct_stock" && ! $_POST["cancel"])
if ($action == "correct_stock")
{
if (is_numeric($_POST["nbpiece"]) && $product_id)
{
@ -342,7 +342,7 @@ if ($resql)
print '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
print '<input type="submit" class="button" name="cancel" value="'.$langs->trans("Cancel").'">';
print '</div>';
print '</form>';
}

View File

@ -47,13 +47,17 @@ if (! empty($conf->productbatch->enabled)) $langs->load("productbatch");
$action=GETPOST("action");
$cancel=GETPOST('cancel');
// Security check
$id=GETPOST('id', 'int');
$ref=GETPOST('ref', 'alpha');
$stocklimit = GETPOST('stocklimit');
$desiredstock = GETPOST('desiredstock');
$cancel = GETPOST('cancel');
$fieldid = isset($_GET["ref"])?'ref':'rowid';
$d_eatby=dol_mktime(12, 0, 0, $_POST['eatbymonth'], $_POST['eatbyday'], $_POST['eatbyyear']);
$d_sellby=dol_mktime(12, 0, 0, $_POST['sellbymonth'], $_POST['sellbyday'], $_POST['sellbyyear']);
$pdluoid=GETPOST('pdluoid','int');
// Security check
if ($user->societe_id) $socid=$user->societe_id;
$result=restrictedArea($user,'produit&stock',$id,'product&product','','',$fieldid);
@ -128,8 +132,6 @@ if ($action == "correct_stock" && ! $cancel)
}
if ($product->hasbatch())
{
$d_eatby=dol_mktime(12, 0, 0, $_POST['eatbymonth'], $_POST['eatbyday'], $_POST['eatbyyear']);
$d_sellby=dol_mktime(12, 0, 0, $_POST['sellbymonth'], $_POST['sellbyday'], $_POST['sellbyyear']);
$result=$product->correct_stock_batch(
$user,
GETPOST("id_entrepot"),
@ -185,91 +187,116 @@ if ($action == "transfert_stock" && ! $cancel)
$error++;
$action='transfert';
}
if (GETPOST("id_entrepot_source",'int') == GETPOST("id_entrepot_destination",'int'))
{
setEventMessage($langs->trans("ErrorSrcAndTargetWarehouseMustDiffers"), 'errors');
$error++;
$action='transfert';
}
if (! $error)
{
if (GETPOST("id_entrepot_source",'int') <> GETPOST("id_entrepot_destination",'int'))
if ($id)
{
if (GETPOST("nbpiece",'int') && $id)
$product = new Product($db);
$result=$product->fetch($id);
$db->begin();
$product->load_stock(); // Load array product->stock_warehouse
// Define value of products moved
$pricesrc=0;
//if (isset($product->stock_warehouse[GETPOST("id_entrepot_source")]->pmp)) $pricesrc=$product->stock_warehouse[GETPOST("id_entrepot_source")]->pmp;
if (isset($product->pmp)) $pricesrc=$product->pmp;
$pricedest=$pricesrc;
if ($product->hasbatch())
{
$product = new Product($db);
$result=$product->fetch($id);
$pdluo = new Productbatch($db);
$db->begin();
$product->load_stock(); // Load array product->stock_warehouse
// Define value of products moved
$pricesrc=0;
//if (isset($product->stock_warehouse[GETPOST("id_entrepot_source")]->pmp)) $pricesrc=$product->stock_warehouse[GETPOST("id_entrepot_source")]->pmp;
if (isset($product->pmp)) $pricesrc=$product->pmp;
$pricedest=$pricesrc;
$pdluoid=GETPOST('pdluoid','int');
if ($pdluoid>0)
if ($pdluoid > 0)
{
$pdluo = new Productbatch($db);
$result=$pdluo->fetch($pdluoid);
if ($result>0 && $pdluo->id)
{
// Remove stock
$result1=$product->correct_stock_batch(
$user,
$pdluo->warehouseid,
GETPOST("nbpiece",'int'),
1,
GETPOST("label",'san_alpha'),
$pricesrc,
$pdluo->eatby,$pdluo->sellby,$pdluo->batch
);
// Add stock
$result2=$product->correct_stock_batch(
$user,
GETPOST("id_entrepot_destination",'int'),
GETPOST("nbpiece",'int'),
0,
GETPOST("label",'san_alpha'),
$pricedest,
$pdluo->eatby,$pdluo->sellby,$pdluo->batch
);
}
$result=$pdluo->fetch($pdluoid);
if ($result)
{
$srcwarehouseid=$pdluo->warehouseid;
$batch=$pdluo->batch;
$eatby=$pdluo->eatby;
$sellby=$pdluo->sellby;
}
else
{
setEventMessages($pdluo->error, $pdluo->errors, 'errors');
$error++;
}
}
else
{
// Remove stock
$result1=$product->correct_stock(
$user,
GETPOST("id_entrepot_source"),
GETPOST("nbpiece"),
1,
GETPOST("label"),
$pricesrc
);
$srcwarehouseid=GETPOST('id_entrepot_source','int');
$batch=GETPOST('batch_number');
$eatby=$d_eatby;
$sellby=$d_sellby;
}
// Add stock
$result2=$product->correct_stock(
$user,
GETPOST("id_entrepot_destination"),
GETPOST("nbpiece"),
0,
GETPOST("label"),
$pricedest
);
}
if ($result1 >= 0 && $result2 >= 0)
if (! $error)
{
$db->commit();
header("Location: product.php?id=".$product->id);
exit;
}
else
{
setEventMessage($product->error, 'errors');
$db->rollback();
// Remove stock
$result1=$product->correct_stock_batch(
$user,
$srcwarehouseid,
GETPOST("nbpiece",'int'),
1,
GETPOST("label",'san_alpha'),
$pricesrc,
$eatby,$sellby,$batch
);
// Add stock
$result2=$product->correct_stock_batch(
$user,
GETPOST("id_entrepot_destination",'int'),
GETPOST("nbpiece",'int'),
0,
GETPOST("label",'san_alpha'),
$pricedest,
$eatby,$sellby,$batch
);
}
}
else
{
// Remove stock
$result1=$product->correct_stock(
$user,
GETPOST("id_entrepot_source"),
GETPOST("nbpiece"),
1,
GETPOST("label"),
$pricesrc
);
// Add stock
$result2=$product->correct_stock(
$user,
GETPOST("id_entrepot_destination"),
GETPOST("nbpiece"),
0,
GETPOST("label"),
$pricedest
);
}
if (! $error && $result1 >= 0 && $result2 >= 0)
{
$db->commit();
header("Location: product.php?id=".$product->id);
exit;
}
else
{
setEventMessages($product->error, $product->errors, 'errors');
$db->rollback();
$action='transfert';
}
}
}
}
@ -578,14 +605,15 @@ if ($id > 0 || $ref)
print '<td width="20%" class="fieldrequired">'.$langs->trans("NumberOfUnit").'</td><td width="20%"><input class="flat" name="nbpiece" id="nbpiece" size="10" value="'.GETPOST("nbpiece").'"></td>';
print '</tr>';
// Label
// Purchase price
print '<tr>';
print '<td width="20%" colspan="2">'.$langs->trans("UnitPurchaseValue").'</td>';
print '<td colspan="4"><input class="flat" name="price" id="unitprice" size="10" value="'.GETPOST("unitprice").'"></td>';
print '</tr>';
//eat-by date
if ((! empty($conf->productbatch->enabled)) && $product->hasbatch()) {
// Eat-by date
if ((! empty($conf->productbatch->enabled)) && $product->hasbatch())
{
print '<tr>';
print '<td colspan="2">'.$langs->trans("batch_number").'</td><td colspan="4">';
print '<input type="text" name="batch_number" size="40" value="'.GETPOST("batch_number").'">';
@ -609,9 +637,9 @@ if ($id > 0 || $ref)
print '</td>';
print '<td width="20%">'.$langs->trans("InventoryCode").'</td><td width="20%"><input class="flat" name="inventorycode" id="inventorycode" size="10" value="'.GETPOST("inventorycode").'"></td>';
print '</tr>';
print '</table>';
print '<div class="center">';
print '<input type="submit" class="button" value="'.$langs->trans('Save').'">';
print '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
@ -627,9 +655,10 @@ if ($id > 0 || $ref)
{
$pdluoid=GETPOST('pdluoid','int');
$pdluo = new Productbatch($db);
if ($pdluoid > 0)
{
$pdluo = new Productbatch($db);
$result=$pdluo->fetch($pdluoid);
if ($result > 0)
@ -653,25 +682,43 @@ if ($id > 0 || $ref)
print '<table class="border" width="100%">';
print '<tr>';
print '<td width="20%" class="fieldrequired">'.$langs->trans("WarehouseSource").'</td><td width="20%">';
print '<td width="15%" class="fieldrequired">'.$langs->trans("WarehouseSource").'</td><td width="15%">';
if ($pdluoid)
{
print $formproduct->selectWarehouses($pdluo->warehouseid,'id_entrepot_source','',1,1);
}
else
{
print $formproduct->selectWarehouses((GETPOST("dwid")?GETPOT("dwid",'int'):(GETPOST('id_entrepot')?GETPOST('id_entrepot_source','int'):'ifone')),'id_entrepot_source','',1);
print $formproduct->selectWarehouses((GETPOST("dwid")?GETPOT("dwid",'int'):(GETPOST('id_entrepot_source')?GETPOST('id_entrepot_source','int'):'ifone')),'id_entrepot_source','',1);
}
print '</td>';
print '<td width="20%" class="fieldrequired">'.$langs->trans("WarehouseTarget").'</td><td width="20%">';
print '<td width="15%" class="fieldrequired">'.$langs->trans("WarehouseTarget").'</td><td width="15%">';
print $formproduct->selectWarehouses(GETPOST('id_entrepot_destination'),'id_entrepot_destination','',1);
print '</td>';
print '<td width="20%" class="fieldrequired">'.$langs->trans("NumberOfUnit").'</td><td width="20%"><input type="text" class="flat" name="nbpiece" size="10" value="'.dol_escape_htmltag(GETPOST("nbpiece")).'"></td>';
print '<td width="15%" class="fieldrequired">'.$langs->trans("NumberOfUnit").'</td><td width="15%"><input type="text" class="flat" name="nbpiece" size="10" value="'.dol_escape_htmltag(GETPOST("nbpiece")).'"></td>';
print '</tr>';
// Eat-by date
if ((! empty($conf->productbatch->enabled)) && $product->hasbatch())
{
print '<tr>';
print '<td>'.$langs->trans("batch_number").'</td><td colspan="5">';
print '<input type="text" name="batch_number" size="40"'.($pdluoid > 0 ? ' disabled="true"':'').' value="'.(GETPOST('batch_number')?GETPOST('batch_number'):$pdluo->batch).'">'; // If form was opened for a specific pdluoid, field is disabled
print '</td>';
print '</tr><tr>';
print '<td>'.$langs->trans("l_eatby").'</td><td>';
print $form->select_date(($d_eatby?$d_eatby:$pdluo->eatby),'eatby','','',1,"", 1, 0, 1, ($pdluoid > 0 ? 1 : 0)); // If form was opened for a specific pdluoid, field is disabled
print '</td>';
print '<td>'.$langs->trans("l_sellby").'</td><td>';
print $form->select_date(($d_sellby?$d_sellby:$pdluo->sellby),'sellby','','',1,"", 1, 0, 1, ($pdluoid > 0 ? 1 : 0)); // If form was opened for a specific pdluoid, field is disabled
print '</td>';
print '<td colspan="2"></td>';
print '</tr>';
}
// Label
print '<tr>';
print '<td width="20%">'.$langs->trans("LabelMovement").'</td>';
print '<td width="15%">'.$langs->trans("MovementLabel").'</td>';
print '<td colspan="5">';
print '<input type="text" name="label" size="80" value="'.dol_escape_htmltag(GETPOST("label")).'">';
print '</td>';
@ -699,9 +746,9 @@ if ($id > 0 || $ref)
print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
print '<input type="hidden" name="action" value="create_stock">';
print '<table class="border" width="100%"><tr>';
print '<td width="20%">'.$langs->trans("Warehouse").'</td><td width="40%">';
print '<td width="15%">'.$langs->trans("Warehouse").'</td><td width="40%">';
print $formproduct->selectWarehouses('','id_entrepot','',1);
print '</td><td width="20%">'.$langs->trans("NumberOfUnit").'</td><td width="20%"><input name="nbpiece" size="10" value=""></td></tr>';
print '</td><td width="15%">'.$langs->trans("NumberOfUnit").'</td><td width="15%"><input name="nbpiece" size="10" value=""></td></tr>';
print '<tr><td colspan="4" align="center"><input type="submit" class="button" value="'.$langs->trans('Save').'">&nbsp;';
print '<input type="submit" class="button" name="cancel" value="'.$langs->trans('Cancel').'"></td></tr>';
print '</table>';
@ -731,7 +778,8 @@ if (empty($action) && $product->id)
print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$product->id.'&amp;action=correction">'.$langs->trans("StockCorrection").'</a>';
}
if (($user->rights->stock->mouvement->creer) && !$product->hasbatch())
//if (($user->rights->stock->mouvement->creer) && ! $product->hasbatch())
if (($user->rights->stock->mouvement->creer))
{
print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$product->id.'&amp;action=transfert">'.$langs->trans("StockMovement").'</a>';
}
@ -753,7 +801,8 @@ print '<td align="right">'.$langs->trans("EstimatedStockValueShort").'</td>';
print '<td align="right">'.$langs->trans("SellPriceMin").'</td>';
print '<td align="right">'.$langs->trans("EstimatedStockValueSellShort").'</td>';
print '</tr>';
if ( (! empty($conf->productbatch->enabled)) && $product->hasbatch()) {
if ((! empty($conf->productbatch->enabled)) && $product->hasbatch())
{
print '<tr class="liste_titre"><td width="10%"></td>';
print '<td align="right" width="10%">'.$langs->trans("batch_number").'</td>';
print '<td align="right" width="10%">'.$langs->trans("l_eatby").'</td>';
@ -798,7 +847,7 @@ if ($resql)
print '<td align="right">';
if (empty($conf->global->PRODUIT_MULTI_PRICES)) print price(price2num($product->price,'MU'),1);
else print $langs->trans("Variable");
print '</td>'; // Ditto : Show PMP from movement or from product
print '</td>';
// Value sell
print '<td align="right">';
if (empty($conf->global->PRODUIT_MULTI_PRICES)) print price(price2num($product->price*$obj->reel,'MT'),1).'</td>'; // Ditto : Show PMP from movement or from product
@ -835,8 +884,10 @@ if ($resql)
{
print "\n".'<tr><td align="right">';
print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$product->id.'&amp;action=transfert&amp;pdluoid='.$pdluo->id.'">'.$langs->trans("StockMovement").'</a>';
print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$id.'&amp;action=editline&amp;lineid='.$pdluo->id.'#'.$pdluo->id.'">';
print img_edit().'</a></td>';
// Disabled, because edition of stock content must use the "Correct stock menu".
// Do not use this, or data will be wrong (bad tracking of movement label, inventory code, ...
//print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$id.'&amp;action=editline&amp;lineid='.$pdluo->id.'#'.$pdluo->id.'">';
//print img_edit().'</a></td>';
print '<td align="right">'.$pdluo->batch.'</td>';
print '<td align="right">'. dol_print_date($pdluo->eatby,'day') .'</td>';
print '<td align="right">'. dol_print_date($pdluo->sellby,'day') .'</td>';