From 179cbbd1872329f0612a0f86b9e062f8925e4450 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 11 Feb 2015 22:54:06 +0100 Subject: [PATCH] Maxi debug and enhancement of module batch. --- .../class/paymentsocialcontribution.class.php | 2 +- htdocs/core/class/events.class.php | 2 +- htdocs/core/js/lib_batch.js | 19 +- .../class/fournisseur.commande.class.php | 21 +- htdocs/fourn/commande/dispatch.php | 166 +++++++++---- .../install/mysql/migration/3.7.0-3.8.0.sql | 4 +- .../llx_commande_fournisseur_dispatch.sql | 6 + htdocs/langs/en_US/errors.lang | 2 + htdocs/langs/en_US/productbatch.lang | 11 +- htdocs/langs/en_US/stocks.lang | 3 + htdocs/langs/fr_FR/stocks.lang | 1 - htdocs/product/class/product.class.php | 87 +++---- htdocs/product/class/productbatch.class.php | 10 +- htdocs/product/stock/class/entrepot.class.php | 1 + .../stock/class/mouvementstock.class.php | 79 ++++-- htdocs/product/stock/mouvement.php | 6 +- htdocs/product/stock/product.php | 235 +++++++++++------- 17 files changed, 412 insertions(+), 243 deletions(-) diff --git a/htdocs/compta/sociales/class/paymentsocialcontribution.class.php b/htdocs/compta/sociales/class/paymentsocialcontribution.class.php index cf407e091f4..d6d3ec04771 100644 --- a/htdocs/compta/sociales/class/paymentsocialcontribution.class.php +++ b/htdocs/compta/sociales/class/paymentsocialcontribution.class.php @@ -77,7 +77,7 @@ class PaymentSocialContribution extends CommonObject // Validate parametres if (! $this->datepaye) { - $this->error='ErrorBadValueForParameter'; + $this->error='ErrorBadValueForParameterCreatePaymentSocialContrib'; return -1; } diff --git a/htdocs/core/class/events.class.php b/htdocs/core/class/events.class.php index 299026a84bb..4ab3ce8f6fe 100644 --- a/htdocs/core/class/events.class.php +++ b/htdocs/core/class/events.class.php @@ -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("; diff --git a/htdocs/core/js/lib_batch.js b/htdocs/core/js/lib_batch.js index 65c138b73aa..e833cef4321 100644 --- a/htdocs/core/js/lib_batch.js +++ b/htdocs/core/js/lib_batch.js @@ -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); -} \ No newline at end of file + + /* 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); + } +} diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index 69a8f70580b..64131be840b 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -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++; } } diff --git a/htdocs/fourn/commande/dispatch.php b/htdocs/fourn/commande/dispatch.php index 731f91485f0..859ab318397 100644 --- a/htdocs/fourn/commande/dispatch.php +++ b/htdocs/fourn/commande/dispatch.php @@ -4,7 +4,7 @@ * Copyright (C) 2005 Eric Seigne * Copyright (C) 2005-2009 Regis Houssin * Copyright (C) 2010 Juanjo Menent - * Copyright (C) 2014 C�dric Gross + * Copyright (C) 2014 Cedric Gross * * 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 ''; - print ''.$langs->trans("Description").''; + print ''.$langs->trans("Description").''; + print ''; + print ''; + print ''; print ''.$langs->trans("QtyOrdered").''; - print ''.$langs->trans("QtyDispatched").''; - print ''.$langs->trans("QtyDelivered").''; + print ''.$langs->trans("QtyDispatchedShort").''; + print ''.$langs->trans("QtyToDispatchShort").''; print ''.$langs->trans("Warehouse").''; print "\n"; - if (!empty($conf->productbatch->enabled)) { + + if (! empty($conf->productbatch->enabled)) + { print ''; - print ' '; + print ''; + print ''.$langs->trans("batch_number").''; print ''.$langs->trans("l_eatby").''; print ''.$langs->trans("l_sellby").''; - print ''.$langs->trans("batch_number").''; - print ' '; + print ' '; print "\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 ""; - print ''; - print ''.img_object($langs->trans("ShowProduct"),'product').' '.$objp->ref.''; - print ' - '.$objp->label."\n"; + + $linktoprod=''.img_object($langs->trans("ShowProduct"),'product').' '.$objp->ref.''; + $linktoprod.=' - '.$objp->label."\n"; + + if (! empty($conf->productbatch->enabled)) + { + if ($objp->tobatch) + { + print ''; + print $linktoprod; + print ""; + } + else + { + print ''; + print $linktoprod; + print ""; + print ''; + print $langs->trans("ProductDoesNotUseBatchSerial"); + print ''; + } + } + else + { + print ''; + print $linktoprod; + print ""; + } + // To show detail cref and description value, we must make calculation by cref //print ($objp->cref?' ('.$objp->cref.')':''); //if ($objp->description) print '
'.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 "\n"; - + // Qty ordered print ''.$objp->qty.''; + + // Already dispatched print ''.$products_dispatched[$objp->fk_product].''; - if ( !(empty($conf->productbatch->enabled)) && $objp->tobatch==1) { - print ''.img_picto_common($langs->trans('AddDispatchBatchLine'),'treemenu/plustop2.gif','onClick="AddLineBatch('.$i.')"').''; + if (! empty($conf->productbatch->enabled) && $objp->tobatch==1) + { + print ''.img_picto($langs->trans('AddDispatchBatchLine'),'split.png','onClick="addLineBatch('.$i.')"').''; // Dispatch column + print ''; // Warehouse column print ''; - print ''; + + print ''; + print ''; print ''; print ''; - print ''; - $form->select_date('','dlc'.$suffix,'','',1,""); - print ''; - $form->select_date('','dluo'.$suffix,'','',1,""); - print ''; - print ''; print ''; - print ' '; - } else { - print ''; - print ''; + print ''; + print ''; + print ''; + print ''; + $form->select_date('','dlc'.$suffix,'','',1,""); + print ''; + print ''; + $form->select_date('','dluo'.$suffix,'','',1,""); + print ''; + print ' '; // Qty ordered + qty already dispatached } // Dispatch - print ''; + print ''; + if (empty($conf->productbatch->enabled) || $objp->tobatch!=1) + { + print ''; + print ''; + } + print ''; + print ''; // Warehouse print ''; @@ -409,6 +459,7 @@ if ($id > 0 || ! empty($ref)) print $langs->trans("NoWarehouseDefined"); } print "\n"; + print "\n"; } } @@ -430,11 +481,13 @@ if ($id > 0 || ! empty($ref)) print 'trans("DispatchSupplierOrder",$commande->ref); // print ' / '.$commande->ref_supplier; // Not yet available - print '" class="flat">

'; + print '" class="flat">   '; - print '
'; + print '
'; + print '>'; + //print ''; } 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 ''; print ''.$langs->trans("Description").''; + if (! empty($conf->productbatch->enabled)) + { + print ''.$langs->trans("batch_number").''; + print ''.$langs->trans("l_eatby").''; + print ''.$langs->trans("l_sellby").''; + } print ''.$langs->trans("QtyDispatched").''; print ''; print ''.$langs->trans("Warehouse").''; @@ -491,6 +550,13 @@ if ($id > 0 || ! empty($ref)) print ' - '.$objp->label; print "\n"; + if (! empty($conf->productbatch->enabled)) + { + print ''.$objp->batch.''; + print ''.dol_print_date($db->jdate($objp->eatby),'day').''; + print ''.dol_print_date($db->jdate($objp->sellby),'day').''; + } + // Qty print ''.$objp->qty.''; print ' '; diff --git a/htdocs/install/mysql/migration/3.7.0-3.8.0.sql b/htdocs/install/mysql/migration/3.7.0-3.8.0.sql index 573646b94c3..b08cc76c4e8 100755 --- a/htdocs/install/mysql/migration/3.7.0-3.8.0.sql +++ b/htdocs/install/mysql/migration/3.7.0-3.8.0.sql @@ -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; \ No newline at end of file diff --git a/htdocs/install/mysql/tables/llx_commande_fournisseur_dispatch.sql b/htdocs/install/mysql/tables/llx_commande_fournisseur_dispatch.sql index 56709573721..912ea14d1f2 100644 --- a/htdocs/install/mysql/tables/llx_commande_fournisseur_dispatch.sql +++ b/htdocs/install/mysql/tables/llx_commande_fournisseur_dispatch.sql @@ -14,6 +14,9 @@ -- You should have received a copy of the GNU General Public License -- along with this program. If not, see . -- +-- 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 diff --git a/htdocs/langs/en_US/errors.lang b/htdocs/langs/en_US/errors.lang index 08b031690b4..79e55f7f597 100755 --- a/htdocs/langs/en_US/errors.lang +++ b/htdocs/langs/en_US/errors.lang @@ -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 diff --git a/htdocs/langs/en_US/productbatch.lang b/htdocs/langs/en_US/productbatch.lang index ca3e49749ab..8dd31df3412 100644 --- a/htdocs/langs/en_US/productbatch.lang +++ b/htdocs/langs/en_US/productbatch.lang @@ -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 \ No newline at end of file diff --git a/htdocs/langs/en_US/stocks.lang b/htdocs/langs/en_US/stocks.lang index 66e23987f09..27bad0cdbbb 100644 --- a/htdocs/langs/en_US/stocks.lang +++ b/htdocs/langs/en_US/stocks.lang @@ -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 diff --git a/htdocs/langs/fr_FR/stocks.lang b/htdocs/langs/fr_FR/stocks.lang index 8749207cd83..81dbd123038 100644 --- a/htdocs/langs/fr_FR/stocks.lang +++ b/htdocs/langs/fr_FR/stocks.lang @@ -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 - diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 1bca1a64f4e..a478f65a8ca 100755 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -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 diff --git a/htdocs/product/class/productbatch.class.php b/htdocs/product/class/productbatch.class.php index 088dccf6861..4362d54a403 100644 --- a/htdocs/product/class/productbatch.class.php +++ b/htdocs/product/class/productbatch.class.php @@ -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; } diff --git a/htdocs/product/stock/class/entrepot.class.php b/htdocs/product/stock/class/entrepot.class.php index 3c3d127223e..09c7c21a0d5 100644 --- a/htdocs/product/stock/class/entrepot.class.php +++ b/htdocs/product/stock/class/entrepot.class.php @@ -510,6 +510,7 @@ class Entrepot extends CommonObject function getNomUrl($withpicto=0,$option='') { global $langs; + $langs->load("stocks"); $result=''; $label = '' . $langs->trans("ShowWarehouse").''; diff --git a/htdocs/product/stock/class/mouvementstock.class.php b/htdocs/product/stock/class/mouvementstock.class.php index 0c8553e424d..e4e231906a9 100644 --- a/htdocs/product/stock/class/mouvementstock.class.php +++ b/htdocs/product/stock/class/mouvementstock.class.php @@ -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); } diff --git a/htdocs/product/stock/mouvement.php b/htdocs/product/stock/mouvement.php index c9451a2d744..682d20e7318 100644 --- a/htdocs/product/stock/mouvement.php +++ b/htdocs/product/stock/mouvement.php @@ -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 '     '; print ''; print ''; - + print ''; } diff --git a/htdocs/product/stock/product.php b/htdocs/product/stock/product.php index 8517a384f06..5a4e619dd05 100644 --- a/htdocs/product/stock/product.php +++ b/htdocs/product/stock/product.php @@ -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 ''.$langs->trans("NumberOfUnit").''; print ''; - // Label + // Purchase price print ''; print ''.$langs->trans("UnitPurchaseValue").''; print ''; print ''; - //eat-by date - if ((! empty($conf->productbatch->enabled)) && $product->hasbatch()) { + // Eat-by date + if ((! empty($conf->productbatch->enabled)) && $product->hasbatch()) + { print ''; print ''.$langs->trans("batch_number").''; print ''; @@ -609,9 +637,9 @@ if ($id > 0 || $ref) print ''; print ''.$langs->trans("InventoryCode").''; print ''; - + print ''; - + print '
'; print ''; print '     '; @@ -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 ''; print ''; - print ''; - print ''; - print ''; + print ''; print ''; + // Eat-by date + if ((! empty($conf->productbatch->enabled)) && $product->hasbatch()) + { + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + } + // Label print ''; - print ''; + print ''; print ''; @@ -699,9 +746,9 @@ if ($id > 0 || $ref) print ''; print ''; print '
'.$langs->trans("WarehouseSource").''; + print ''.$langs->trans("WarehouseSource").''; 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 ''.$langs->trans("WarehouseTarget").''; + print ''.$langs->trans("WarehouseTarget").''; print $formproduct->selectWarehouses(GETPOST('id_entrepot_destination'),'id_entrepot_destination','',1); print ''.$langs->trans("NumberOfUnit").''.$langs->trans("NumberOfUnit").'
'.$langs->trans("batch_number").''; + print ' 0 ? ' disabled="true"':'').' value="'.(GETPOST('batch_number')?GETPOST('batch_number'):$pdluo->batch).'">'; // If form was opened for a specific pdluoid, field is disabled + print '
'.$langs->trans("l_eatby").''; + 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 ''.$langs->trans("l_sellby").''; + 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 '
'.$langs->trans("LabelMovement").''.$langs->trans("MovementLabel").''; print ''; print '
'; - print ''; + print ''; print ''; print '
'.$langs->trans("Warehouse").''; + print ''.$langs->trans("Warehouse").''; print $formproduct->selectWarehouses('','id_entrepot','',1); - print ''.$langs->trans("NumberOfUnit").'
'.$langs->trans("NumberOfUnit").'
 '; print '
'; @@ -731,7 +778,8 @@ if (empty($action) && $product->id) print ''.$langs->trans("StockCorrection").''; } - if (($user->rights->stock->mouvement->creer) && !$product->hasbatch()) + //if (($user->rights->stock->mouvement->creer) && ! $product->hasbatch()) + if (($user->rights->stock->mouvement->creer)) { print ''.$langs->trans("StockMovement").''; } @@ -753,7 +801,8 @@ print ''.$langs->trans("EstimatedStockValueShort").''; print ''.$langs->trans("SellPriceMin").''; print ''.$langs->trans("EstimatedStockValueSellShort").''; print ''; -if ( (! empty($conf->productbatch->enabled)) && $product->hasbatch()) { +if ((! empty($conf->productbatch->enabled)) && $product->hasbatch()) +{ print ''; print ''.$langs->trans("batch_number").''; print ''.$langs->trans("l_eatby").''; @@ -798,7 +847,7 @@ if ($resql) print ''; if (empty($conf->global->PRODUIT_MULTI_PRICES)) print price(price2num($product->price,'MU'),1); else print $langs->trans("Variable"); - print ''; // Ditto : Show PMP from movement or from product + print ''; // Value sell print ''; if (empty($conf->global->PRODUIT_MULTI_PRICES)) print price(price2num($product->price*$obj->reel,'MT'),1).''; // Ditto : Show PMP from movement or from product @@ -835,8 +884,10 @@ if ($resql) { print "\n".''; print 'id.'">'.$langs->trans("StockMovement").''; - print 'id.'#'.$pdluo->id.'">'; - print img_edit().''; + // 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 'id.'#'.$pdluo->id.'">'; + //print img_edit().''; print ''.$pdluo->batch.''; print ''. dol_print_date($pdluo->eatby,'day') .''; print ''. dol_print_date($pdluo->sellby,'day') .'';