diff --git a/htdocs/core/lib/pdf.lib.php b/htdocs/core/lib/pdf.lib.php
index 3b0c2250c49..b7209dd1db0 100644
--- a/htdocs/core/lib/pdf.lib.php
+++ b/htdocs/core/lib/pdf.lib.php
@@ -1644,7 +1644,17 @@ function pdf_getlinedesc($object, $i, $outputlangs, $hideref = 0, $hidedesc = 0,
//print $libelleproduitservice;
}
+ // Show information for lot
if ($dbatch) {
+ // $object is a shipment.
+ //var_dump($object->lines[$i]->details_entrepot); // array from llx_expeditiondet (we can have seral lines for one fk_origin_line)
+ //var_dump($object->lines[$i]->detail_batch); // array from llx_expeditiondet_batch (each line with a lot is linked to llx_expeditiondet)
+
+ include_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
+ include_once DOL_DOCUMENT_ROOT.'/product/class/productbatch.class.php';
+ $tmpwarehouse = new Entrepot($db);
+ $tmpproductbatch = new Productbatch($db);
+
$format = 'day';
foreach ($dbatch as $detail) {
$dte = array();
@@ -1658,8 +1668,24 @@ function pdf_getlinedesc($object, $i, $outputlangs, $hideref = 0, $hidedesc = 0,
$dte[] = $outputlangs->transnoentitiesnoconv('printBatch', $detail->batch);
}
$dte[] = $outputlangs->transnoentitiesnoconv('printQty', $detail->qty);
+
+ // Add also info of planned warehouse for lot
+ if ($object->element == 'shipping' && $detail->fk_origin_stock > 0 && getDolGlobalInt('PRODUCTBATCH_SHOW_WAREHOUSE_ON_SHIPMENT')) {
+ $resproductbatch = $tmpproductbatch->fetch($detail->fk_origin_stock);
+ if ($resproductbatch > 0) {
+ $reswarehouse = $tmpwarehouse->fetch($tmpproductbatch->warehouseid);
+ if ($reswarehouse > 0) {
+ $dte[] = $tmpwarehouse->ref;
+ }
+ }
+ }
+
$libelleproduitservice .= "__N__ ".implode(" - ", $dte);
}
+ } else {
+ if (getDolGlobalInt('PRODUCTBATCH_SHOW_WAREHOUSE_ON_SHIPMENT')) {
+ // TODO Show warehouse for shipment line without batch
+ }
}
// Now we convert \n into br
diff --git a/htdocs/expedition/card.php b/htdocs/expedition/card.php
index 60b3695609d..e46fea6790b 100644
--- a/htdocs/expedition/card.php
+++ b/htdocs/expedition/card.php
@@ -285,12 +285,13 @@ if (empty($reshook)) {
$totalqty += $subtotalqty;
} else {
- // No detail were provided for lots, so if a qty was provided, we can show an error.
+ // No detail were provided for lots, so if a qty was provided, we can throw an error.
if (GETPOST($qty)) {
// We try to set an amount
// Case we dont use the list of available qty for each warehouse/lot
// GUI does not allow this yet
- setEventMessages($langs->trans("StockIsRequiredToChooseWhichLotToUse"), null, 'errors');
+ setEventMessages($langs->trans("StockIsRequiredToChooseWhichLotToUse").' ('.$langs->trans("Line").' '.GETPOST($idl, 'int').')', null, 'errors');
+ $error++;
}
}
} elseif (GETPOSTISSET($stockLocation)) {
@@ -328,7 +329,7 @@ if (empty($reshook)) {
//var_dump($batch_line[2]);
- if ($totalqty > 0) { // There is at least one thing to ship
+ if ($totalqty > 0 && !$error) { // There is at least one thing to ship and no error
for ($i = 0; $i < $num; $i++) {
$qty = "qtyl".$i;
if (!isset($batch_line[$i])) {
@@ -388,7 +389,7 @@ if (empty($reshook)) {
$error++;
}
}
- } else {
+ } elseif (!$error) {
$labelfieldmissing = $langs->transnoentitiesnoconv("QtyToShip");
if (!empty($conf->stock->enabled)) {
$labelfieldmissing .= '/'.$langs->transnoentitiesnoconv("Warehouse");
@@ -1120,12 +1121,15 @@ if ($action == 'create') {
$type = 1;
}
- print ''."\n";
- print '
'."\n";
+ print ''."\n";
+ print '
'."\n";
// Product label
if ($line->fk_product > 0) { // If predefined product
- $product->fetch($line->fk_product);
+ $res = $product->fetch($line->fk_product);
+ if ($res < 0) {
+ dol_print_error($db, $product->error, $product->errors);
+ }
$product->load_stock('warehouseopen'); // Load all $product->stock_warehouse[idwarehouse]->detail_batch
//var_dump($product->stock_warehouse[1]);
diff --git a/htdocs/expedition/class/expedition.class.php b/htdocs/expedition/class/expedition.class.php
index b1a767e197d..6a674a770ec 100644
--- a/htdocs/expedition/class/expedition.class.php
+++ b/htdocs/expedition/class/expedition.class.php
@@ -771,7 +771,7 @@ class Expedition extends CommonObject
// line with batch detail
// We decrement stock of product (and sub-products) -> update table llx_product_stock (key of this table is fk_product+fk_entrepot) and add a movement record.
- // Note: ->fk_origin_stock = id into table llx_product_batch (may be rename into llx_product_stock_batch in another version)
+ // Note: ->fk_origin_stock = id into table llx_product_batch (may be renamed into llx_product_stock_batch in another version)
$result = $mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, $qty, $obj->subprice, $langs->trans("ShipmentValidatedInDolibarr", $numref), '', $this->db->jdate($obj->eatby), $this->db->jdate($obj->sellby), $obj->batch, $obj->fk_origin_stock, '', 1);
if ($result < 0) {
$error++;
@@ -965,8 +965,9 @@ class Expedition extends CommonObject
}
// If product need a batch number, we should not have called this function but addline_batch instead.
+ // If this happen, we may have a bug in card.php page
if (isModEnabled('productbatch') && !empty($orderline->fk_product) && !empty($orderline->product_tobatch)) {
- $this->error = 'ADDLINE_WAS_CALLED_INSTEAD_OF_ADDLINEBATCH';
+ $this->error = 'ADDLINE_WAS_CALLED_INSTEAD_OF_ADDLINEBATCH '.$orderline->id.' '.$orderline->fk_product; //
return -4;
}
@@ -2498,12 +2499,28 @@ class ExpeditionLigne extends CommonObjectLine
*/
public $table_element = 'expeditiondet';
+
+ /**
+ * Id of the line. Duplicate of $id.
+ *
+ * @var int
+ * @deprecated
+ */
+ public $line_id; // deprecated
+
/**
* @deprecated
* @see $fk_origin_line
*/
public $origin_line_id;
+ /**
+ * Code of object line that is origin of the shipment line.
+ *
+ * @var string
+ */
+ public $fk_origin; // Example: 'orderline'
+
/**
* @var int ID
*/
@@ -2533,8 +2550,16 @@ class ExpeditionLigne extends CommonObjectLine
* @var int Id of product
*/
public $fk_product;
+
+ // detail of lot and qty = array(id in llx_expeditiondet_batch, fk_expeditiondet, batch, qty, fk_origin_stock)
+ // We can use this to know warehouse planned to be used for each lot.
public $detail_batch;
+ // detail of warehouses and qty
+ // We can use this to know warehouse when there is no lot.
+ public $details_entrepot;
+
+
/**
* @var int Id of warehouse
*/
diff --git a/htdocs/expedition/class/expeditionlinebatch.class.php b/htdocs/expedition/class/expeditionlinebatch.class.php
index b2562734447..5d99d1c7a74 100644
--- a/htdocs/expedition/class/expeditionlinebatch.class.php
+++ b/htdocs/expedition/class/expeditionlinebatch.class.php
@@ -44,7 +44,7 @@ class ExpeditionLineBatch extends CommonObject
public $qty;
public $dluo_qty; // deprecated, use qty
public $entrepot_id;
- public $fk_origin_stock;
+ public $fk_origin_stock; // rowid in llx_product_batch table
public $fk_expeditiondet;
diff --git a/htdocs/langs/en_US/productbatch.lang b/htdocs/langs/en_US/productbatch.lang
index 4bd64f44577..a1039e05e62 100644
--- a/htdocs/langs/en_US/productbatch.lang
+++ b/htdocs/langs/en_US/productbatch.lang
@@ -17,6 +17,7 @@ printBatch=Lot/Serial: %s
printEatby=Eat-by: %s
printSellby=Sell-by: %s
printQty=Qty: %d
+printPlannedWarehouse=Warehouse: %s
AddDispatchBatchLine=Add a line for Shelf Life dispatching
WhenProductBatchModuleOnOptionAreForced=When module Lot/Serial is on, automatic stock decrease is forced to 'Decrease real stocks on shipping validation' and automatic increase mode is forced to 'Increase real stocks on manual dispatching into warehouses' and can't be edited. Other options can be defined as you want.
ProductDoesNotUseBatchSerial=This product does not use lot/serial number
diff --git a/htdocs/langs/en_US/stocks.lang b/htdocs/langs/en_US/stocks.lang
index 492cdd48864..5332b8123e0 100644
--- a/htdocs/langs/en_US/stocks.lang
+++ b/htdocs/langs/en_US/stocks.lang
@@ -235,7 +235,7 @@ StockIncrease=Stock increase
StockDecrease=Stock decrease
InventoryForASpecificWarehouse=Inventory for a specific warehouse
InventoryForASpecificProduct=Inventory for a specific product
-StockIsRequiredToChooseWhichLotToUse=Stock is required to choose which lot to use
+StockIsRequiredToChooseWhichLotToUse=An existing stock is required to be able to choose which lot to use
ForceTo=Force to
AlwaysShowFullArbo=Display full tree of warehouse on popup of warehouse links (Warning: This may decrease dramatically performances)
StockAtDatePastDesc=You can view here the stock (real stock) at a given date in the past
diff --git a/htdocs/langs/fr_FR/stocks.lang b/htdocs/langs/fr_FR/stocks.lang
index a0642c4c627..2b3559787d3 100644
--- a/htdocs/langs/fr_FR/stocks.lang
+++ b/htdocs/langs/fr_FR/stocks.lang
@@ -234,7 +234,7 @@ StockIncrease=Augmentation du stock
StockDecrease=Diminution du stock
InventoryForASpecificWarehouse=Inventaire pour un entrepôt spécifique
InventoryForASpecificProduct=Inventaire pour un produit spécifique
-StockIsRequiredToChooseWhichLotToUse=Le module Stock est requis pour choisir une lot
+StockIsRequiredToChooseWhichLotToUse=Un stock existant est requis pour pouvoir choisir un lot
ForceTo=Forcer à
AlwaysShowFullArbo=Afficher l'arborescence complète de l'entrepôt sur la popup du lien entrepôt (Avertissement: cela peut réduire considérablement les performances)
StockAtDatePastDesc=Vous pouvez voir ici le stock (stock réel) à une date donnée dans le passé
diff --git a/htdocs/product/class/productbatch.class.php b/htdocs/product/class/productbatch.class.php
index f42563ceb19..00d2dc80fee 100644
--- a/htdocs/product/class/productbatch.class.php
+++ b/htdocs/product/class/productbatch.class.php
@@ -136,7 +136,6 @@ class Productbatch extends CommonObject
global $langs;
$sql = "SELECT";
$sql .= " t.rowid,";
-
$sql .= " t.tms,";
$sql .= " t.fk_product_stock,";
$sql .= " t.sellby as oldsellby,";
@@ -148,8 +147,8 @@ class Productbatch extends CommonObject
$sql .= " w.fk_product,";
$sql .= " pl.eatby,";
$sql .= " pl.sellby";
-
- $sql .= " FROM ".$this->db->prefix()."product_batch as t INNER JOIN ".$this->db->prefix()."product_stock w on t.fk_product_stock = w.rowid";
+ $sql .= " FROM ".$this->db->prefix()."product_batch as t";
+ $sql .= " INNER JOIN ".$this->db->prefix()."product_stock w on t.fk_product_stock = w.rowid"; // llx_product_stock is a parent table so this link does NOT generate duplicate record
$sql .= " LEFT JOIN ".$this->db->prefix()."product_lot as pl on pl.fk_product = w.fk_product and pl.batch = t.batch";
$sql .= " WHERE t.rowid = ".((int) $id);
diff --git a/htdocs/product/stock/class/productstockentrepot.class.php b/htdocs/product/stock/class/productstockentrepot.class.php
index 95da65cd540..a0310a16359 100644
--- a/htdocs/product/stock/class/productstockentrepot.class.php
+++ b/htdocs/product/stock/class/productstockentrepot.class.php
@@ -114,23 +114,17 @@ class ProductStockEntrepot extends CommonObject
// Insert request
$sql = 'INSERT INTO '.$this->db->prefix().$this->table_element.'(';
-
$sql .= 'fk_product,';
$sql .= 'fk_entrepot,';
$sql .= 'seuil_stock_alerte,';
$sql .= 'desiredstock,';
$sql .= 'import_key';
-
-
$sql .= ') VALUES (';
-
$sql .= ' '.(!isset($this->fk_product) ? 'NULL' : $this->fk_product).',';
$sql .= ' '.(!isset($this->fk_entrepot) ? 'NULL' : $this->fk_entrepot).',';
$sql .= ' '.(!isset($this->seuil_stock_alerte) ? '0' : $this->seuil_stock_alerte).',';
$sql .= ' '.(!isset($this->desiredstock) ? '0' : $this->desiredstock).',';
$sql .= ' '.(!isset($this->import_key) ? 'NULL' : "'".$this->db->escape($this->import_key)."'");
-
-
$sql .= ')';
$this->db->begin();