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

This commit is contained in:
Laurent Destailleur 2021-07-11 00:44:36 +02:00
parent 9e9af8548d
commit 97ac547fe2
8 changed files with 198 additions and 177 deletions

View File

@ -84,14 +84,14 @@ class modProductBatch extends DolibarrModules
$this->const[$r][0] = "PRODUCTBATCH_LOT_ADDON"; $this->const[$r][0] = "PRODUCTBATCH_LOT_ADDON";
$this->const[$r][1] = "chaine"; $this->const[$r][1] = "chaine";
$this->const[$r][2] = "mod_lot_free"; $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; $this->const[$r][4] = 0;
$r++; $r++;
$this->const[$r][0] = "PRODUCTBATCH_SN_ADDON"; $this->const[$r][0] = "PRODUCTBATCH_SN_ADDON";
$this->const[$r][1] = "chaine"; $this->const[$r][1] = "chaine";
$this->const[$r][2] = "mod_sn_free"; $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; $this->const[$r][4] = 0;
$r++; $r++;

View File

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

View File

@ -85,17 +85,21 @@ class mod_lot_standard extends ModeleNumRefBatch
$coyymm = ''; $max = ''; $coyymm = ''; $max = '';
$posindice = strlen($this->prefix) + 6; $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 .= " 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; $sql .= " AND entity = ".$conf->entity;
$resql = $db->query($sql); $resql = $db->query($sql);
if ($resql) { if ($resql) {
$row = $db->fetch_row($resql); $obj = $db->fetch_object($resql);
if ($row) { $coyymm = substr($row[0], 0, 6); $max = $row[0]; } 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"); $langs->load("errors");
$this->error = $langs->trans('ErrorNumRefModel', $max); $this->error = $langs->trans('ErrorNumRefModel', $max);
return false; return false;
@ -117,23 +121,26 @@ class mod_lot_standard extends ModeleNumRefBatch
// First, we get the max value // First, we get the max value
$posindice = strlen($this->prefix) + 6; $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 .= " 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; $sql .= " AND entity = ".$conf->entity;
$resql = $db->query($sql); $resql = $db->query($sql);
if ($resql) { if ($resql) {
$obj = $db->fetch_object($resql); $obj = $db->fetch_object($resql);
if ($obj) $max = intval($obj->max); if ($obj) {
else $max = 0; $max = intval($obj->max);
} else {
$max = 0;
}
} else { } else {
dol_syslog("mod_lot_standard::getNextValue", LOG_DEBUG); dol_syslog("mod_lot_standard::getNextValue", LOG_DEBUG);
return -1; return -1;
} }
//$date=time(); //$date=time();
$date = $object->date_creation; $date = dol_now();
$yymm = strftime("%y%m", $date); $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 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

View File

@ -139,16 +139,16 @@ class mod_sn_advanced extends ModeleNumRefBatch
require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
// We get cursor rule // We get cursor rule
$mask = $conf->global->BATCH_ADVANCED_MASK; $mask = $conf->global->SN_ADVANCED_MASK;
if (!$mask) { if (!$mask) {
$this->error = 'NotConfigured'; $this->error = 'NotConfigured';
return 0; 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; return $numFinal;
} }

View File

@ -85,17 +85,21 @@ class mod_sn_standard extends ModeleNumRefBatch
$coyymm = ''; $max = ''; $coyymm = ''; $max = '';
$posindice = strlen($this->prefix) + 6; $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 .= " 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; $sql .= " AND entity = ".$conf->entity;
$resql = $db->query($sql); $resql = $db->query($sql);
if ($resql) { if ($resql) {
$row = $db->fetch_row($resql); $obj = $db->fetch_object($resql);
if ($row) { $coyymm = substr($row[0], 0, 6); $max = $row[0]; } 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"); $langs->load("errors");
$this->error = $langs->trans('ErrorNumRefModel', $max); $this->error = $langs->trans('ErrorNumRefModel', $max);
return false; return false;
@ -107,33 +111,36 @@ class mod_sn_standard extends ModeleNumRefBatch
/** /**
* Return next free value * Return next free value
* *
* @param Product $objprod Object product * @param Societe $objsoc Object product
* @param Object $object Object we need next value for * @param Object $object Object we need next value for
* @return string Value if KO, <0 if KO * @return string Value if KO, <0 if KO
*/ */
public function getNextValue($objprod, $object) public function getNextValue($objsoc, $object)
{ {
global $db, $conf; global $db, $conf;
// First, we get the max value // First, we get the max value
$posindice = strlen($this->prefix) + 6; $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 .= " 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; $sql .= " AND entity = ".$conf->entity;
$resql = $db->query($sql); $resql = $db->query($sql);
if ($resql) { if ($resql) {
$obj = $db->fetch_object($resql); $obj = $db->fetch_object($resql);
if ($obj) $max = intval($obj->max); if ($obj) {
else $max = 0; $max = intval($obj->max);
} else {
$max = 0;
}
} else { } else {
dol_syslog("mod_sn_standard::getNextValue", LOG_DEBUG); dol_syslog("mod_sn_standard::getNextValue", LOG_DEBUG);
return -1; return -1;
} }
//$date=time(); //$date=time();
$date = $object->date_creation; $date = dol_now();
$yymm = strftime("%y%m", $date); $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 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

View File

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

View File

@ -101,6 +101,14 @@ $head = product_lot_admin_prepare_head();
print dol_get_fiche_head($head, 'settings', $langs->trans("Batch"), -1, 'lot'); print dol_get_fiche_head($head, 'settings', $langs->trans("Batch"), -1, 'lot');
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 * Lot Numbering models
*/ */
@ -283,6 +291,7 @@ foreach ($dirmodels as $reldir) {
} }
print "</table><br>\n"; print "</table><br>\n";
}
// End of page // End of page
llxFooter(); llxFooter();

View File

@ -87,7 +87,7 @@ class Productlot extends CommonObject
*/ */
public $fields = array( 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'), '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), '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), '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), 'sellby' => array('type'=>'date', 'label'=>'SellByDate', 'enabled'=>'empty($conf->global->PRODUCT_DISABLE_SELLBY)?1:0', 'visible'=>5, 'position'=>60),