diff --git a/htdocs/core/class/html.formother.class.php b/htdocs/core/class/html.formother.class.php
index 5dd0580e3c7..3b8c0b45c5a 100644
--- a/htdocs/core/class/html.formother.class.php
+++ b/htdocs/core/class/html.formother.class.php
@@ -77,7 +77,10 @@ class FormOther
$out .= ' Scan a product barcode
';
$out .= ' Scan a product lot or serial number
';
- $out .= $langs->trans("QtyToAddAfterBarcodeScan").'
';
+ $stringaddbarcode = $langs->trans("QtyToAddAfterBarcodeScan", "tmphtml");
+ $htmltoreplaceby = '';
+ $stringaddbarcode = str_replace("tmphtml", $htmltoreplaceby, $stringaddbarcode);
+ $out .= $stringaddbarcode.'
';
$out .= '';
/*print '
'.$langs->trans("or").'
';
diff --git a/htdocs/langs/en_US/productbatch.lang b/htdocs/langs/en_US/productbatch.lang
index 71e44e8f281..dd1e0ea4027 100644
--- a/htdocs/langs/en_US/productbatch.lang
+++ b/htdocs/langs/en_US/productbatch.lang
@@ -30,7 +30,7 @@ ManageLotMask=Custom mask
CustomMasks=Option to define a different numbering mask for each product
BatchLotNumberingModules=Numbering rule for automatic generation of lot number
BatchSerialNumberingModules=Numbering rule for automatic generation of serial number (for products with property 1 unique lot/serial for each product)
-QtyToAddAfterBarcodeScan=Qty to add for each barcode/lot/serial scanned
+QtyToAddAfterBarcodeScan=Qty to %s for each barcode/lot/serial scanned
LifeTime=Life span (in days)
EndOfLife=End of life
ManufacturingDate=Manufacturing date
@@ -42,3 +42,4 @@ HideLots=Hide lots
#Traceability - qc status
OutOfOrder=Out of order
InWorkingOrder=In working order
+ToReplace=Replace
\ No newline at end of file
diff --git a/htdocs/langs/en_US/stocks.lang b/htdocs/langs/en_US/stocks.lang
index 75b6ea1bd4e..c26a8819a1d 100644
--- a/htdocs/langs/en_US/stocks.lang
+++ b/htdocs/langs/en_US/stocks.lang
@@ -265,4 +265,5 @@ ProductBarcodeDoesNotExist=Product with barcode does not exist
WarehouseId=Warehouse ID
WarehouseRef=Warehouse Ref
SaveQtyFirst=Save the real inventoried quantities first, before asking creation of the stock movement.
-InventoryStartedShort=Started
\ No newline at end of file
+InventoryStartedShort=Started
+ErrorOnElementsInventory=Scan was aborted due to following barcode or batch number on error
\ No newline at end of file
diff --git a/htdocs/langs/fr_FR/productbatch.lang b/htdocs/langs/fr_FR/productbatch.lang
index 40c8b0be477..adff64b70a1 100644
--- a/htdocs/langs/fr_FR/productbatch.lang
+++ b/htdocs/langs/fr_FR/productbatch.lang
@@ -30,7 +30,7 @@ ManageLotMask=Masque personnalisé
CustomMasks=Option pour définir un masque de numérotation différent pour chaque produit
BatchLotNumberingModules=Règle de numérotation pour la génération automatique de numéro de lot
BatchSerialNumberingModules=Règle de numérotation pour la génération automatique de numéro de série (pour les produits avec propriété 1 lot/série unique pour chaque produit)
-QtyToAddAfterBarcodeScan=Quantité à ajouter pour chaque code à barres/lot/série scanné
+QtyToAddAfterBarcodeScan=Quantité à %s pour chaque code à barres/lot/série scanné
LifeTime=Durée de vie (en jours)
EndOfLife=Fin d'utilisation
ManufacturingDate=Date de fabrication
diff --git a/htdocs/product/inventory/ajax/ajax.inventory.php b/htdocs/product/inventory/ajax/ajax.inventory.php
deleted file mode 100644
index 920607f4c1e..00000000000
--- a/htdocs/product/inventory/ajax/ajax.inventory.php
+++ /dev/null
@@ -1,47 +0,0 @@
-rights->stock->creer)) {
- echo -1; exit;
- }
-
- $fk_det_inventory = GETPOST('fk_det_inventory');
-
- $det = new InventoryLine($db);
- if ($det->fetch($fk_det_inventory)) {
- $det->qty_view += GETPOST('qty');
- $res = $det->update($user);
-
- echo $det->qty_view;
- } else {
- echo -2;
- }
-
- break;
-
- case 'pmp':
- if (empty($user->rights->stock->creer) || empty($user->rights->stock->changePMP)) {
- echo -1; exit;
- }
-
- $fk_det_inventory = GETPOST('fk_det_inventory');
-
- $det = new InventoryLine($db);
- if ($det->fetch($fk_det_inventory)) {
- $det->new_pmp = price2num(GETPOST('pmp'));
- $det->update($user);
-
- echo $det->new_pmp;
- } else {
- echo -2;
- }
-
- break;
-}
diff --git a/htdocs/product/inventory/ajax/searchfrombarcode.php b/htdocs/product/inventory/ajax/searchfrombarcode.php
new file mode 100644
index 00000000000..68ffee43c23
--- /dev/null
+++ b/htdocs/product/inventory/ajax/searchfrombarcode.php
@@ -0,0 +1,135 @@
+.
+ */
+
+/**
+ * \file /htdocs/product/inventory/ajax/searchfrombarcode.php
+ * \brief File to make Ajax action on product and stock
+ */
+
+if (!defined('NOTOKENRENEWAL')) {
+ define('NOTOKENRENEWAL', 1); // Disables token renewal
+}
+if (!defined('NOREQUIREMENU')) {
+ define('NOREQUIREMENU', '1');
+}
+if (!defined('NOREQUIREHTML')) {
+ define('NOREQUIREHTML', '1');
+}
+if (!defined('NOREQUIREAJAX')) {
+ define('NOREQUIREAJAX', '1');
+}
+if (!defined('NOREQUIRESOC')) {
+ define('NOREQUIRESOC', '1');
+}
+if (!defined('NOCSRFCHECK')) {
+ define('NOCSRFCHECK', '1');
+}
+require '../../../main.inc.php';
+require_once DOL_DOCUMENT_ROOT."/product/stock/class/entrepot.class.php";
+$warehouse = new Entrepot($db);
+
+$action = GETPOST("action", "alpha");
+$barcode = GETPOST("barcode", "aZ09");
+$product = GETPOST("product");
+$response = "";
+
+$fk_entrepot = GETPOST("fk_entrepot", "int");
+$fk_inventory = GETPOST("fk_inventory", "int");
+$fk_product = GETPOST("fk_product", "int");
+$reelqty = GETPOST("reelqty", "int");
+$batch = GETPOST("batch", "int");
+$mode = GETPOST("mode", "aZ");
+
+$warehousefound = 0;
+$warehouseid = 0;
+$objectreturn = array();
+
+if ($action == "existbarcode" && !empty($barcode)) {
+ if (!empty($mode) && $mode == "lotserial") {
+ $sql = "SELECT ps.fk_entrepot, ps.fk_product, p.barcode, ps.reel, pb.batch";
+ $sql .= " FROM ".MAIN_DB_PREFIX."product_batch as pb";
+ $sql .= " JOIN ".MAIN_DB_PREFIX."product_stock as ps ON pb.fk_product_stock = ps.rowid JOIN ".MAIN_DB_PREFIX."product as p ON ps.fk_product = p.rowid";
+ $sql .= " WHERE pb.batch = '".$db->escape($barcode)."'";
+ } else {
+ $sql = "SELECT ps.fk_entrepot, ps.fk_product, p.barcode,ps.reel";
+ $sql .= " FROM ".MAIN_DB_PREFIX."product_stock as ps JOIN ".MAIN_DB_PREFIX."product as p ON ps.fk_product = p.rowid";
+ $sql .= " WHERE p.barcode = '".$db->escape($barcode)."'";
+ }
+ if (!empty($fk_entrepot)) {
+ $sql .= " AND ps.fk_entrepot = '".$db->escape($fk_entrepot)."'";
+ }
+ if (!empty($fk_product)) {
+ $sql .= " AND ps.fk_product = '".$db->escape($fk_product)."'";
+ }
+ $result = $db->query($sql);
+ if ($result) {
+ $nbline = $db->num_rows($result);
+ for ($i=0; $i < $nbline; $i++) {
+ $object = $db->fetch_object($result);
+ if (($mode == "barcode" && $barcode == $object->barcode) || ($mode == "lotserial" && $barcode == $object->batch)) {
+ $warehouse->fetch(0, $product["Warehouse"]);
+ if (!empty($object->fk_entrepot) && $warehouse->id == $object->fk_entrepot) {
+ $warehousefound++;
+ $warehouseid = $object->fk_entrepot;
+ $fk_product = $object->fk_product;
+ $reelqty = $object->reel;
+
+ $objectreturn = array('fk_warehouse'=>$warehouseid,'fk_product'=>$fk_product,'reelqty'=>$reelqty);
+ }
+ }
+ }
+ if ($warehousefound < 1) {
+ $response = array('status'=>'error','errorcode'=>'NotFound','message'=>'No warehouse found for barcode'.$barcode);
+ } elseif ($warehousefound > 1) {
+ $response = array('status'=>'error','errorcode'=>'TooManyWarehouse','message'=>'Too many warehouse found');
+ } else {
+ $response = array('status'=>'success','message'=>'Warehouse found','object'=>$objectreturn);
+ }
+ } else {
+ $response = array('status'=>'error','errorcode'=>'NotFound','message'=>"No results found for barcode");
+ }
+} else {
+ $response = array('status'=>'error','errorcode'=>'ActionError','message'=>"Error on action");
+}
+
+if ($action == "addnewlineproduct") {
+ require_once DOL_DOCUMENT_ROOT."/product/inventory/class/inventory.class.php";
+ $inventoryline = new InventoryLine($db);
+ if (!empty($fk_inventory)) {
+ $inventoryline->fk_inventory = $fk_inventory;
+
+ $inventoryline->fk_warehouse = $fk_entrepot;
+ $inventoryline->fk_product = $fk_product;
+ $inventoryline->qty_stock = $reelqty;
+ if (!empty($batch)) {
+ $inventoryline->batch = $batch;
+ }
+ $inventoryline->datec = dol_now();
+
+ $result = $inventoryline->create($user);
+ if ($result > 0) {
+ $response = array('status'=>'success','message'=>'Success on creating line','id_line'=>$result);
+ } else {
+ $response = array('status'=>'error','errorcode'=>'ErrorCreation','message'=>"Error on line creation");
+ }
+ } else {
+ $response = array('status'=>'error','errorcode'=>'NoIdForInventory','message'=>"No id for inventory");
+ }
+}
+
+$response = json_encode($response);
+echo $response;
diff --git a/htdocs/product/inventory/class/inventory.class.php b/htdocs/product/inventory/class/inventory.class.php
index b972e44245b..092d98ea854 100644
--- a/htdocs/product/inventory/class/inventory.class.php
+++ b/htdocs/product/inventory/class/inventory.class.php
@@ -26,6 +26,7 @@
// Put here all includes required by your class file
require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
+require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php';
//require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
//require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
diff --git a/htdocs/product/inventory/inventory.php b/htdocs/product/inventory/inventory.php
index f4cb6593b49..5346e37aec4 100644
--- a/htdocs/product/inventory/inventory.php
+++ b/htdocs/product/inventory/inventory.php
@@ -452,7 +452,7 @@ if ($object->id > 0) {
print dol_get_fiche_end();
- print '