Pārlūkot izejas kodu

Fix/debug the numbering module to autocalculate a new lot.

Laurent Destailleur 3 gadi atpakaļ
vecāks
revīzija
97ac547fe2

+ 2 - 2
htdocs/core/modules/modProductBatch.class.php

@@ -84,14 +84,14 @@ class modProductBatch extends DolibarrModules
 		$this->const[$r][0] = "PRODUCTBATCH_LOT_ADDON";
 		$this->const[$r][1] = "chaine";
 		$this->const[$r][2] = "mod_lot_free";
-		$this->const[$r][3] = 'Module to control product codes';
+		$this->const[$r][3] = 'Module to control lot number';
 		$this->const[$r][4] = 0;
 		$r++;
 
 		$this->const[$r][0] = "PRODUCTBATCH_SN_ADDON";
 		$this->const[$r][1] = "chaine";
 		$this->const[$r][2] = "mod_sn_free";
-		$this->const[$r][3] = 'Module to control product codes';
+		$this->const[$r][3] = 'Module to control serial number';
 		$this->const[$r][4] = 0;
 		$r++;
 

+ 5 - 5
htdocs/core/modules/product_batch/mod_lot_advanced.php

@@ -128,27 +128,27 @@ class mod_lot_advanced extends ModeleNumRefBatch
 	/**
 	 * 	Return next free value
 	 *
-	 *  @param	Product		$objprod    Object product
+	 *  @param	Societe		$objsoc	    Object Societe
 	 *  @param  Object		$object		Object we need next value for
 	 *  @return string      			Value if KO, <0 if KO
 	 */
-	public function getNextValue($objprod, $object)
+	public function getNextValue($objsoc, $object)
 	{
 		global $db, $conf;
 
 		require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
 
 		// We get cursor rule
-		$mask = $conf->global->BATCH_ADVANCED_MASK;
+		$mask = $conf->global->LOT_ADVANCED_MASK;
 
 		if (!$mask) {
 			$this->error = 'NotConfigured';
 			return 0;
 		}
 
-		$date = $object->date;
+		$date = dol_now();
 
-		$numFinal = get_next_value($db, $mask, 'product_lot', 'ref', '', null, $date);
+		$numFinal = get_next_value($db, $mask, 'product_lot', 'batch', '', null, $date);
 
 		return  $numFinal;
 	}

+ 17 - 10
htdocs/core/modules/product_batch/mod_lot_standard.php

@@ -85,17 +85,21 @@ class mod_lot_standard extends ModeleNumRefBatch
 		$coyymm = ''; $max = '';
 
 		$posindice = strlen($this->prefix) + 6;
-		$sql = "SELECT MAX(CAST(SUBSTRING(ref FROM ".$posindice.") AS SIGNED)) as max";
+		$sql = "SELECT MAX(CAST(SUBSTRING(batch FROM ".$posindice.") AS SIGNED)) as max";
 		$sql .= " FROM ".MAIN_DB_PREFIX."product_lot";
-		$sql .= " WHERE ref LIKE '".$db->escape($this->prefix)."____-%'";
+		$sql .= " WHERE batch LIKE '".$db->escape($this->prefix)."____-%'";
 		$sql .= " AND entity = ".$conf->entity;
 
 		$resql = $db->query($sql);
 		if ($resql) {
-			$row = $db->fetch_row($resql);
-			if ($row) { $coyymm = substr($row[0], 0, 6); $max = $row[0]; }
+			$obj = $db->fetch_object($resql);
+			if ($obj) {
+				$max = intval($obj->max);
+			} else {
+				$max = 0;
+			}
 		}
-		if ($coyymm && !preg_match('/'.$this->prefix.'[0-9][0-9][0-9][0-9]/i', $coyymm)) {
+		if ($max && !preg_match('/'.$this->prefix.'[0-9][0-9][0-9][0-9]/i', $max)) {
 			$langs->load("errors");
 			$this->error = $langs->trans('ErrorNumRefModel', $max);
 			return false;
@@ -117,23 +121,26 @@ class mod_lot_standard extends ModeleNumRefBatch
 
 		// First, we get the max value
 		$posindice = strlen($this->prefix) + 6;
-		$sql = "SELECT MAX(CAST(SUBSTRING(ref FROM ".$posindice.") AS SIGNED)) as max";
+		$sql = "SELECT MAX(CAST(SUBSTRING(batch FROM ".$posindice.") AS SIGNED)) as max";
 		$sql .= " FROM ".MAIN_DB_PREFIX."product_lot";
-		$sql .= " WHERE ref LIKE '".$db->escape($this->prefix)."____-%'";
+		$sql .= " WHERE batch LIKE '".$db->escape($this->prefix)."____-%'";
 		$sql .= " AND entity = ".$conf->entity;
 
 		$resql = $db->query($sql);
 		if ($resql)	{
 			$obj = $db->fetch_object($resql);
-			if ($obj) $max = intval($obj->max);
-			else $max = 0;
+			if ($obj) {
+				$max = intval($obj->max);
+			} else {
+				$max = 0;
+			}
 		} else {
 			dol_syslog("mod_lot_standard::getNextValue", LOG_DEBUG);
 			return -1;
 		}
 
 		//$date=time();
-		$date = $object->date_creation;
+		$date = dol_now();
 		$yymm = strftime("%y%m", $date);
 
 		if ($max >= (pow(10, 4) - 1)) $num = $max + 1; // If counter > 9999, we do not format on 4 chars, we take number as it is

+ 3 - 3
htdocs/core/modules/product_batch/mod_sn_advanced.php

@@ -139,16 +139,16 @@ class mod_sn_advanced extends ModeleNumRefBatch
 		require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
 
 		// We get cursor rule
-		$mask = $conf->global->BATCH_ADVANCED_MASK;
+		$mask = $conf->global->SN_ADVANCED_MASK;
 
 		if (!$mask)	{
 			$this->error = 'NotConfigured';
 			return 0;
 		}
 
-		$date = $object->date;
+		$date = dol_now();
 
-		$numFinal = get_next_value($db, $mask, 'product_sn', 'ref', '', null, $date);
+		$numFinal = get_next_value($db, $mask, 'product_lot', 'batch', '', null, $date);
 
 		return  $numFinal;
 	}

+ 19 - 12
htdocs/core/modules/product_batch/mod_sn_standard.php

@@ -85,17 +85,21 @@ class mod_sn_standard extends ModeleNumRefBatch
 		$coyymm = ''; $max = '';
 
 		$posindice = strlen($this->prefix) + 6;
-		$sql = "SELECT MAX(CAST(SUBSTRING(ref FROM ".$posindice.") AS SIGNED)) as max";
+		$sql = "SELECT MAX(CAST(SUBSTRING(batch FROM ".$posindice.") AS SIGNED)) as max";
 		$sql .= " FROM ".MAIN_DB_PREFIX."product_lot";
-		$sql .= " WHERE ref LIKE '".$db->escape($this->prefix)."____-%'";
+		$sql .= " WHERE batch LIKE '".$db->escape($this->prefix)."____-%'";
 		$sql .= " AND entity = ".$conf->entity;
 
 		$resql = $db->query($sql);
 		if ($resql)	{
-			$row = $db->fetch_row($resql);
-			if ($row) { $coyymm = substr($row[0], 0, 6); $max = $row[0]; }
+			$obj = $db->fetch_object($resql);
+			if ($obj) {
+				$max = intval($obj->max);
+			} else {
+				$max = 0;
+			}
 		}
-		if ($coyymm && !preg_match('/'.$this->prefix.'[0-9][0-9][0-9][0-9]/i', $coyymm)) {
+		if ($max && !preg_match('/'.$this->prefix.'[0-9][0-9][0-9][0-9]/i', $max)) {
 			$langs->load("errors");
 			$this->error = $langs->trans('ErrorNumRefModel', $max);
 			return false;
@@ -107,33 +111,36 @@ class mod_sn_standard extends ModeleNumRefBatch
 	/**
 	 * 	Return next free value
 	 *
-	 *  @param	Product		$objprod    Object product
+	 *  @param	Societe		$objsoc     Object product
 	 *  @param  Object		$object		Object we need next value for
 	 *  @return string      			Value if KO, <0 if KO
 	 */
-	public function getNextValue($objprod, $object)
+	public function getNextValue($objsoc, $object)
 	{
 		global $db, $conf;
 
 		// First, we get the max value
 		$posindice = strlen($this->prefix) + 6;
-		$sql = "SELECT MAX(CAST(SUBSTRING(ref FROM ".$posindice.") AS SIGNED)) as max";
+		$sql = "SELECT MAX(CAST(SUBSTRING(batch FROM ".$posindice.") AS SIGNED)) as max";
 		$sql .= " FROM ".MAIN_DB_PREFIX."product_lot";
-		$sql .= " WHERE ref LIKE '".$db->escape($this->prefix)."____-%'";
+		$sql .= " WHERE batch LIKE '".$db->escape($this->prefix)."____-%'";
 		$sql .= " AND entity = ".$conf->entity;
 
 		$resql = $db->query($sql);
 		if ($resql)	{
 			$obj = $db->fetch_object($resql);
-			if ($obj) $max = intval($obj->max);
-			else $max = 0;
+			if ($obj) {
+				$max = intval($obj->max);
+			} else {
+				$max = 0;
+			}
 		} else {
 			dol_syslog("mod_sn_standard::getNextValue", LOG_DEBUG);
 			return -1;
 		}
 
 		//$date=time();
-		$date = $object->date_creation;
+		$date = dol_now();
 		$yymm = strftime("%y%m", $date);
 
 		if ($max >= (pow(10, 4) - 1)) $num = $max + 1; // If counter > 9999, we do not format on 4 chars, we take number as it is

+ 3 - 5
htdocs/langs/en_US/productbatch.lang

@@ -26,12 +26,10 @@ ShowLogOfMovementIfLot=Show log of movements for couple product/lot
 StockDetailPerBatch=Stock detail per lot
 SerialNumberAlreadyInUse=Serial number %s is already used for product %s
 TooManyQtyForSerialNumber=You can only have one product %s for serial number %s
-BatchLotNumberingModules=Options for automatic generation of batch products managed by lots
-BatchSerialNumberingModules=Options for automatic generation of batch products managed by serial numbers
 ManageLotMask=Custom mask
-CustomMasks=Adds an option to define mask in the product card
-LotProductTooltip=Adds an option in the product card to define a dedicated batch number mask
-SNProductTooltip=Adds an option in the product card to define a dedicated serial number 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
 LifeTime=Life span (in days)
 EndOfLife=End of life

+ 167 - 158
htdocs/product/admin/product_lot.php

@@ -101,188 +101,197 @@ $head = product_lot_admin_prepare_head();
 
 print dol_get_fiche_head($head, 'settings', $langs->trans("Batch"), -1, 'lot');
 
-/*
- * Lot Numbering models
- */
 
-print load_fiche_titre($langs->trans("BatchLotNumberingModules"), '', '');
-
-print '<table class="noborder centpercent">';
-print '<tr class="liste_titre">';
-print '<td>'.$langs->trans("Name").'</td>';
-print '<td>'.$langs->trans("Description").'</td>';
-print '<td class="nowrap">'.$langs->trans("Example").'</td>';
-print '<td class="center" width="60">'.$langs->trans("Status").'</td>';
-print '<td class="center" width="16">'.$langs->trans("ShortInfo").'</td>';
-print '</tr>'."\n";
-
-clearstatcache();
-
-foreach ($dirmodels as $reldir) {
-	$dir = dol_buildpath($reldir."core/modules/product_batch/");
-
-	if (is_dir($dir)) {
-		$handle = opendir($dir);
-		if (is_resource($handle)) {
-			while (($file = readdir($handle)) !== false) {
-				if (substr($file, 0, 8) == 'mod_lot_' && substr($file, dol_strlen($file) - 3, 3) == 'php') {
-					$file = substr($file, 0, dol_strlen($file) - 4);
-
-					require_once $dir.$file.'.php';
-
-					$module = new $file($db);
-
-					// Show modules according to features level
-					if ($module->version == 'development' && $conf->global->MAIN_FEATURES_LEVEL < 2) continue;
-					if ($module->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1) continue;
-
-					if ($module->isEnabled()) {
-						print '<tr class="oddeven"><td>'.$module->name."</td><td>\n";
-						print $module->info();
-						print '</td>';
-
-						// Show example of numbering model
-						print '<td class="nowrap">';
-						$tmp = $module->getExample();
-						if (preg_match('/^Error/', $tmp)) print '<div class="error">'.$langs->trans($tmp).'</div>';
-						elseif ($tmp == 'NotConfigured') print $langs->trans($tmp);
-						else print $tmp;
-						print '</td>'."\n";
-
-						print '<td class="center">';
-						if ($conf->global->PRODUCTBATCH_LOT_ADDON == $file) {
-							print img_picto($langs->trans("Activated"), 'switch_on');
-						} else {
-							print '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?action=setmodlot&amp;value='.$file.'">';
-							print img_picto($langs->trans("Disabled"), 'switch_off');
-							print '</a>';
-						}
-						print '</td>';
-
-						$batch = new Productlot($db);
-						$batch->initAsSpecimen();
-
-						// Info
-						$htmltooltip = '';
-						$htmltooltip .= ''.$langs->trans("Version").': <b>'.$module->getVersion().'</b><br>';
-						$nextval = $module->getNextValue($mysoc, $batch);
-						if ("$nextval" != $langs->trans("NotAvailable")) {  // Keep " on nextval
-							$htmltooltip .= ''.$langs->trans("NextValue").': ';
-							if ($nextval) {
-								if (preg_match('/^Error/', $nextval) || $nextval == 'NotConfigured')
-									$nextval = $langs->trans($nextval);
-								$htmltooltip .= $nextval.'<br>';
+if ($conf->global->MAIN_FEATURES_LEVEL < 2) {
+	// The feature to define the numbering module of lot or serial is no enabled bcause it is not used anywhere in Dolibarr code: You can set it
+	// but the numbering module is not used.
+	// TODO Use it on lot creation page, when you create a lot and when the lot number is kept empty to define the lot according
+	// to the selected product.
+	print $langs->trans("NothingToSetup");
+} else {
+	/*
+	 * Lot Numbering models
+	 */
+
+	print load_fiche_titre($langs->trans("BatchLotNumberingModules"), '', '');
+
+	print '<table class="noborder centpercent">';
+	print '<tr class="liste_titre">';
+	print '<td>'.$langs->trans("Name").'</td>';
+	print '<td>'.$langs->trans("Description").'</td>';
+	print '<td class="nowrap">'.$langs->trans("Example").'</td>';
+	print '<td class="center" width="60">'.$langs->trans("Status").'</td>';
+	print '<td class="center" width="16">'.$langs->trans("ShortInfo").'</td>';
+	print '</tr>'."\n";
+
+	clearstatcache();
+
+	foreach ($dirmodels as $reldir) {
+		$dir = dol_buildpath($reldir."core/modules/product_batch/");
+
+		if (is_dir($dir)) {
+			$handle = opendir($dir);
+			if (is_resource($handle)) {
+				while (($file = readdir($handle)) !== false) {
+					if (substr($file, 0, 8) == 'mod_lot_' && substr($file, dol_strlen($file) - 3, 3) == 'php') {
+						$file = substr($file, 0, dol_strlen($file) - 4);
+
+						require_once $dir.$file.'.php';
+
+						$module = new $file($db);
+
+						// Show modules according to features level
+						if ($module->version == 'development' && $conf->global->MAIN_FEATURES_LEVEL < 2) continue;
+						if ($module->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1) continue;
+
+						if ($module->isEnabled()) {
+							print '<tr class="oddeven"><td>'.$module->name."</td><td>\n";
+							print $module->info();
+							print '</td>';
+
+							// Show example of numbering model
+							print '<td class="nowrap">';
+							$tmp = $module->getExample();
+							if (preg_match('/^Error/', $tmp)) print '<div class="error">'.$langs->trans($tmp).'</div>';
+							elseif ($tmp == 'NotConfigured') print $langs->trans($tmp);
+							else print $tmp;
+							print '</td>'."\n";
+
+							print '<td class="center">';
+							if ($conf->global->PRODUCTBATCH_LOT_ADDON == $file) {
+								print img_picto($langs->trans("Activated"), 'switch_on');
 							} else {
-								$htmltooltip .= $langs->trans($module->error).'<br>';
+								print '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?action=setmodlot&amp;value='.$file.'">';
+								print img_picto($langs->trans("Disabled"), 'switch_off');
+								print '</a>';
+							}
+							print '</td>';
+
+							$batch = new Productlot($db);
+							$batch->initAsSpecimen();
+
+							// Info
+							$htmltooltip = '';
+							$htmltooltip .= ''.$langs->trans("Version").': <b>'.$module->getVersion().'</b><br>';
+							$nextval = $module->getNextValue($mysoc, $batch);
+							if ("$nextval" != $langs->trans("NotAvailable")) {  // Keep " on nextval
+								$htmltooltip .= ''.$langs->trans("NextValue").': ';
+								if ($nextval) {
+									if (preg_match('/^Error/', $nextval) || $nextval == 'NotConfigured')
+										$nextval = $langs->trans($nextval);
+									$htmltooltip .= $nextval.'<br>';
+								} else {
+									$htmltooltip .= $langs->trans($module->error).'<br>';
+								}
 							}
-						}
 
-						print '<td class="center">';
-						print $form->textwithpicto('', $htmltooltip, 1, 0);
-						print '</td>';
+							print '<td class="center">';
+							print $form->textwithpicto('', $htmltooltip, 1, 0);
+							print '</td>';
 
-						print "</tr>\n";
+							print "</tr>\n";
+						}
 					}
 				}
+				closedir($handle);
 			}
-			closedir($handle);
 		}
 	}
-}
 
-print "</table><br>\n";
+	print "</table><br>\n";
 
 
-/*
- * Serials Numbering models
- */
+	/*
+	 * Serials Numbering models
+	 */
 
-print load_fiche_titre($langs->trans("BatchSerialNumberingModules"), '', '');
-
-print '<table class="noborder centpercent">';
-print '<tr class="liste_titre">';
-print '<td>'.$langs->trans("Name").'</td>';
-print '<td>'.$langs->trans("Description").'</td>';
-print '<td class="nowrap">'.$langs->trans("Example").'</td>';
-print '<td class="center" width="60">'.$langs->trans("Status").'</td>';
-print '<td class="center" width="16">'.$langs->trans("ShortInfo").'</td>';
-print '</tr>'."\n";
-
-clearstatcache();
-
-foreach ($dirmodels as $reldir) {
-	$dir = dol_buildpath($reldir."core/modules/product_batch/");
-
-	if (is_dir($dir)) {
-		$handle = opendir($dir);
-		if (is_resource($handle)) {
-			while (($file = readdir($handle)) !== false) {
-				if (substr($file, 0, 7) == 'mod_sn_' && substr($file, dol_strlen($file) - 3, 3) == 'php') {
-					$file = substr($file, 0, dol_strlen($file) - 4);
-
-					require_once $dir.$file.'.php';
-
-					$module = new $file($db);
-
-					// Show modules according to features level
-					if ($module->version == 'development' && $conf->global->MAIN_FEATURES_LEVEL < 2) continue;
-					if ($module->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1) continue;
-
-					if ($module->isEnabled()) {
-						print '<tr class="oddeven"><td>'.$module->name."</td><td>\n";
-						print $module->info();
-						print '</td>';
-
-						// Show example of numbering model
-						print '<td class="nowrap">';
-						$tmp = $module->getExample();
-						if (preg_match('/^Error/', $tmp)) print '<div class="error">'.$langs->trans($tmp).'</div>';
-						elseif ($tmp == 'NotConfigured') print $langs->trans($tmp);
-						else print $tmp;
-						print '</td>'."\n";
-
-						print '<td class="center">';
-						if ($conf->global->PRODUCTBATCH_SN_ADDON == $file) {
-							print img_picto($langs->trans("Activated"), 'switch_on');
-						} else {
-							print '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?action=setmodsn&amp;value='.$file.'">';
-							print img_picto($langs->trans("Disabled"), 'switch_off');
-							print '</a>';
-						}
-						print '</td>';
-
-						$batch = new Productlot($db);
-						$batch->initAsSpecimen();
-
-						// Info
-						$htmltooltip = '';
-						$htmltooltip .= ''.$langs->trans("Version").': <b>'.$module->getVersion().'</b><br>';
-						$nextval = $module->getNextValue($mysoc, $batch);
-						if ("$nextval" != $langs->trans("NotAvailable")) {  // Keep " on nextval
-							$htmltooltip .= ''.$langs->trans("NextValue").': ';
-							if ($nextval) {
-								if (preg_match('/^Error/', $nextval) || $nextval == 'NotConfigured')
-									$nextval = $langs->trans($nextval);
-								$htmltooltip .= $nextval.'<br>';
+	print load_fiche_titre($langs->trans("BatchSerialNumberingModules"), '', '');
+
+	print '<table class="noborder centpercent">';
+	print '<tr class="liste_titre">';
+	print '<td>'.$langs->trans("Name").'</td>';
+	print '<td>'.$langs->trans("Description").'</td>';
+	print '<td class="nowrap">'.$langs->trans("Example").'</td>';
+	print '<td class="center" width="60">'.$langs->trans("Status").'</td>';
+	print '<td class="center" width="16">'.$langs->trans("ShortInfo").'</td>';
+	print '</tr>'."\n";
+
+	clearstatcache();
+
+	foreach ($dirmodels as $reldir) {
+		$dir = dol_buildpath($reldir."core/modules/product_batch/");
+
+		if (is_dir($dir)) {
+			$handle = opendir($dir);
+			if (is_resource($handle)) {
+				while (($file = readdir($handle)) !== false) {
+					if (substr($file, 0, 7) == 'mod_sn_' && substr($file, dol_strlen($file) - 3, 3) == 'php') {
+						$file = substr($file, 0, dol_strlen($file) - 4);
+
+						require_once $dir.$file.'.php';
+
+						$module = new $file($db);
+
+						// Show modules according to features level
+						if ($module->version == 'development' && $conf->global->MAIN_FEATURES_LEVEL < 2) continue;
+						if ($module->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1) continue;
+
+						if ($module->isEnabled()) {
+							print '<tr class="oddeven"><td>'.$module->name."</td><td>\n";
+							print $module->info();
+							print '</td>';
+
+							// Show example of numbering model
+							print '<td class="nowrap">';
+							$tmp = $module->getExample();
+							if (preg_match('/^Error/', $tmp)) print '<div class="error">'.$langs->trans($tmp).'</div>';
+							elseif ($tmp == 'NotConfigured') print $langs->trans($tmp);
+							else print $tmp;
+							print '</td>'."\n";
+
+							print '<td class="center">';
+							if ($conf->global->PRODUCTBATCH_SN_ADDON == $file) {
+								print img_picto($langs->trans("Activated"), 'switch_on');
 							} else {
-								$htmltooltip .= $langs->trans($module->error).'<br>';
+								print '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?action=setmodsn&amp;value='.$file.'">';
+								print img_picto($langs->trans("Disabled"), 'switch_off');
+								print '</a>';
+							}
+							print '</td>';
+
+							$batch = new Productlot($db);
+							$batch->initAsSpecimen();
+
+							// Info
+							$htmltooltip = '';
+							$htmltooltip .= ''.$langs->trans("Version").': <b>'.$module->getVersion().'</b><br>';
+							$nextval = $module->getNextValue($mysoc, $batch);
+							if ("$nextval" != $langs->trans("NotAvailable")) {  // Keep " on nextval
+								$htmltooltip .= ''.$langs->trans("NextValue").': ';
+								if ($nextval) {
+									if (preg_match('/^Error/', $nextval) || $nextval == 'NotConfigured')
+										$nextval = $langs->trans($nextval);
+									$htmltooltip .= $nextval.'<br>';
+								} else {
+									$htmltooltip .= $langs->trans($module->error).'<br>';
+								}
 							}
-						}
 
-						print '<td class="center">';
-						print $form->textwithpicto('', $htmltooltip, 1, 0);
-						print '</td>';
+							print '<td class="center">';
+							print $form->textwithpicto('', $htmltooltip, 1, 0);
+							print '</td>';
 
-						print "</tr>\n";
+							print "</tr>\n";
+						}
 					}
 				}
+				closedir($handle);
 			}
-			closedir($handle);
 		}
 	}
-}
 
-print "</table><br>\n";
+	print "</table><br>\n";
+}
 
 // End of page
 llxFooter();

+ 1 - 1
htdocs/product/stock/class/productlot.class.php

@@ -87,7 +87,7 @@ class Productlot extends CommonObject
 	 */
 	public $fields = array(
 		'rowid'         => array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>1, 'visible'=>-2, 'noteditable'=>1, 'notnull'=> 1, 'index'=>1, 'position'=>1, 'comment'=>'Id', 'css'=>'left'),
-		'fk_product'    => array('type'=>'integer:Product:product/class/product.class.php', 'label'=>'Product', 'enabled'=>1, 'visible'=>1, 'position'=>15, 'notnull'=>1, 'index'=>1, 'searchall'=>1),
+		'fk_product'    => array('type'=>'integer:Product:product/class/product.class.php', 'label'=>'Product', 'enabled'=>1, 'visible'=>1, 'position'=>5, 'notnull'=>1, 'index'=>1, 'searchall'=>1),
 		'batch'         => array('type'=>'varchar(30)', 'label'=>'Batch', 'enabled'=>1, 'visible'=>1, 'notnull'=>0, 'showoncombobox'=>1, 'index'=>1, 'position'=>10, 'comment'=>'Batch', 'searchall'=>1),
 		'entity'        => array('type'=>'integer', 'label'=>'Entity', 'enabled'=>1, 'visible'=>0, 'default'=>1, 'notnull'=>1, 'index'=>1, 'position'=>20),
 		'sellby'        => array('type'=>'date', 'label'=>'SellByDate', 'enabled'=>'empty($conf->global->PRODUCT_DISABLE_SELLBY)?1:0', 'visible'=>5, 'position'=>60),