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();