diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index cf7b89be7aa..2333802cc40 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -1576,7 +1576,7 @@ class Facture extends CommonInvoice $now=dol_now(); $error=0; - dol_syslog(get_class($this).'::validate user='.$user->id.', force_number='.$force_number.', idwarehouse='.$idwarehouse, LOG_WARNING); + dol_syslog(get_class($this).'::validate user='.$user->id.', force_number='.$force_number.', idwarehouse='.$idwarehouse); // Check parameters if (! $this->brouillon) @@ -2554,11 +2554,10 @@ class Facture extends CommonInvoice { $maxfacnumber = $this->getNextNumRef($this->client,'last'); $ventilExportCompta = $this->getVentilExportCompta(); - // Si derniere facture et si non ventilee, on peut supprimer - if ($maxfacnumber == $this->ref && $ventilExportCompta == 0) - { - return 1; - } + // If there is no invoice into the reset range and not already dispatched, we can delete + if ($maxfacnumber == '' && $ventilExportCompta == 0) return 1; + // If invoice to delete is last one and not already dispatched, we can delete + if ($maxfacnumber == $this->ref && $ventilExportCompta == 0) return 1; } else if ($this->statut == 0 && $facref == 'PROV') // Si facture brouillon et provisoire { diff --git a/htdocs/core/lib/functions2.lib.php b/htdocs/core/lib/functions2.lib.php index 40c52cbc200..63ad0667ca3 100644 --- a/htdocs/core/lib/functions2.lib.php +++ b/htdocs/core/lib/functions2.lib.php @@ -506,7 +506,7 @@ function array2table($data,$tableMarkup=1,$tableoptions='',$troptions='',$tdopti } /** - * Return next value for a mask + * Return last or next value for a mask (according to area we should not reset) * * @param DoliDB $db Database handler * @param string $mask Mask to use @@ -688,7 +688,6 @@ function get_next_value($db,$mask,$table,$field,$where='',$objsoc='',$date='',$m $posnumstart=strpos($maskwithnocode,$maskcounter); // Pos of counter in final string (from 0 to ...) if ($posnumstart < 0) return 'ErrorBadMaskFailedToLocatePosOfSequence'; $sqlstring='SUBSTRING('.$field.', '.($posnumstart+1).', '.dol_strlen($maskcounter).')'; - //print "x".$sqlstring; // Define $maskLike $maskLike = dol_string_nospecial($mask); @@ -701,7 +700,6 @@ function get_next_value($db,$mask,$table,$field,$where='',$objsoc='',$date='',$m $maskLike = preg_replace('/\{dd\}/i','__',$maskLike); $maskLike = str_replace(dol_string_nospecial('{'.$masktri.'}'),str_pad("",dol_strlen($maskcounter),"_"),$maskLike); if ($maskrefclient) $maskLike = str_replace(dol_string_nospecial('{'.$maskrefclient.'}'),str_pad("",dol_strlen($maskrefclient),"_"),$maskLike); - //if ($masktype) $maskLike = str_replace(dol_string_nospecial('{'.$masktype.'}'),str_pad("",dol_strlen($masktype),"_"),$maskLike); if ($masktype) $maskLike = str_replace(dol_string_nospecial('{'.$masktype.'}'),$masktype_value,$maskLike); // Get counter in database @@ -715,7 +713,7 @@ function get_next_value($db,$mask,$table,$field,$where='',$objsoc='',$date='',$m if ($sqlwhere) $sql.=' AND '.$sqlwhere; //print $sql.'
'; - dol_syslog("functions2::get_next_value sql=".$sql, LOG_DEBUG); + dol_syslog("functions2::get_next_value mode=".$mode." sql=".$sql, LOG_DEBUG); $resql=$db->query($sql); if ($resql) { @@ -725,30 +723,32 @@ function get_next_value($db,$mask,$table,$field,$where='',$objsoc='',$date='',$m else dol_print_error($db); if (empty($counter) || preg_match('/[^0-9]/i',$counter)) $counter=$maskoffset; - if ($mode == 'last') + if ($mode == 'last') // We found value for counter = last counter value. Now need to get corresponding ref of invoice. { $counterpadded=str_pad($counter,dol_strlen($maskcounter),"0",STR_PAD_LEFT); - // Define $maskLike - $maskLike = dol_string_nospecial($mask); - $maskLike = str_replace("%","_",$maskLike); - // Replace protected special codes with matching number of _ as wild card caracter - $maskLike = preg_replace('/\{yyyy\}/i','____',$maskLike); - $maskLike = preg_replace('/\{yy\}/i','__',$maskLike); - $maskLike = preg_replace('/\{y\}/i','_',$maskLike); - $maskLike = preg_replace('/\{mm\}/i','__',$maskLike); - $maskLike = preg_replace('/\{dd\}/i','__',$maskLike); - $maskLike = str_replace(dol_string_nospecial('{'.$masktri.'}'),$counterpadded,$maskLike); - if ($maskrefclient) $maskLike = str_replace(dol_string_nospecial('{'.$maskrefclient.'}'),str_pad("",dol_strlen($maskrefclient),"_"),$maskLike); - //if ($masktype) $maskLike = str_replace(dol_string_nospecial('{'.$masktype.'}'),str_pad("",dol_strlen($masktype),"_"),$maskLike); - if ($masktype) $maskLike = str_replace(dol_string_nospecial('{'.$masktype.'}'),$masktype_value,$maskLike); - + // Define $maskLike + $maskLike = dol_string_nospecial($mask); + $maskLike = str_replace("%","_",$maskLike); + // Replace protected special codes with matching number of _ as wild card caracter + $maskLike = preg_replace('/\{yyyy\}/i','____',$maskLike); + $maskLike = preg_replace('/\{yy\}/i','__',$maskLike); + $maskLike = preg_replace('/\{y\}/i','_',$maskLike); + $maskLike = preg_replace('/\{mm\}/i','__',$maskLike); + $maskLike = preg_replace('/\{dd\}/i','__',$maskLike); + $maskLike = str_replace(dol_string_nospecial('{'.$masktri.'}'),$counterpadded,$maskLike); + if ($maskrefclient) $maskLike = str_replace(dol_string_nospecial('{'.$maskrefclient.'}'),str_pad("",dol_strlen($maskrefclient),"_"),$maskLike); + if ($masktype) $maskLike = str_replace(dol_string_nospecial('{'.$masktype.'}'),$masktype_value,$maskLike); + $ref=''; - $sql = "SELECT facnumber as ref"; - $sql.= " FROM ".MAIN_DB_PREFIX."facture"; - $sql.= " WHERE facnumber LIKE '".$maskLike."'"; + $sql = "SELECT ".$field." as ref"; + $sql.= " FROM ".MAIN_DB_PREFIX.$table; + $sql.= " WHERE ".$field." LIKE '".$maskLike."'"; + $sql.= " AND ".$field." NOT LIKE '%PROV%'"; $sql.= " AND entity IN (".getEntity($table, 1).")"; - + if ($where) $sql.=$where; + if ($sqlwhere) $sql.=' AND '.$sqlwhere; + dol_syslog("functions2::get_next_value sql=".$sql); $resql=$db->query($sql); if ($resql) diff --git a/test/phpunit/NumberingModulesTest.php b/test/phpunit/NumberingModulesTest.php index 59d13c7606f..1f121d6c9e3 100644 --- a/test/phpunit/NumberingModulesTest.php +++ b/test/phpunit/NumberingModulesTest.php @@ -134,23 +134,25 @@ class NumberingModulesTest extends PHPUnit_Framework_TestCase $conf->global->FACTURE_MERCURE_MASK_CREDIT='{yyyy}-{0000}'; $conf->global->FACTURE_MERCURE_MASK_INVOICE='{yyyy}-{0000}'; - $localobject=new Facture($this->savdb); - $localobject->initAsSpecimen(); - $localobject->date=dol_mktime(12, 0, 0, 1, 1, 1915); // we use year 1915 to be sure to not have existing invoice for this year - $numbering=new mod_facture_mercure(); - $result=$numbering->getNextValue($mysoc, $localobject); - $result2=$localobject->create($user,1); - $result3=$localobject->validate($user, $result); - print __METHOD__." result=".$result."\n"; - $this->assertEquals('1915-0001', $result); // counter must start to 1 - - $localobject=new Facture($this->savdb); - $localobject->initAsSpecimen(); - $localobject->date=dol_mktime(12, 0, 0, 1, 1, 1916); // we use following year for second invoice - $numbering=new mod_facture_mercure(); - $result=$numbering->getNextValue($mysoc, $localobject); - print __METHOD__." result=".$result."\n"; - $this->assertEquals('1916-0002', $result); // counter must not be reset + $localobject=new Facture($this->savdb); + $localobject->initAsSpecimen(); + $localobject->date=dol_mktime(12, 0, 0, 1, 1, 1915); // we use year 1915 to be sure to not have existing invoice for this year + $numbering=new mod_facture_mercure(); + $result=$numbering->getNextValue($mysoc, $localobject); + $result2=$localobject->create($user,1); + $result3=$localobject->validate($user, $result); // create invoice by forcing ref + print __METHOD__." result=".$result."\n"; + $this->assertEquals('1915-0001', $result); // counter must start to 1 + + $localobject=new Facture($this->savdb); + $localobject->initAsSpecimen(); + $localobject->date=dol_mktime(12, 0, 0, 1, 1, 1916); // we use following year for second invoice (there is no reset into mask) + $numbering=new mod_facture_mercure(); + $result=$numbering->getNextValue($mysoc, $localobject, 'last'); + $this->assertEquals('1915-0001', $result); + $result=$numbering->getNextValue($mysoc, $localobject); + print __METHOD__." result=".$result."\n"; + $this->assertEquals('1916-0002', $result); // counter must not be reseted so be 2 // Now we try with a reset $conf->global->FACTURE_MERCURE_MASK_CREDIT='{yyyy}-{0000@1}'; @@ -162,7 +164,7 @@ class NumberingModulesTest extends PHPUnit_Framework_TestCase $numbering=new mod_facture_mercure(); $result=$numbering->getNextValue($mysoc, $localobject); print __METHOD__." result=".$result."\n"; - $this->assertEquals('1910-0001', $result); // counter must start to 1 + $this->assertEquals('1910-0001', $result); // counter must start to 1 // Same mask but we add month $conf->global->FACTURE_MERCURE_MASK_CREDIT='{yyyy}{mm}-{0000@1}'; @@ -175,35 +177,44 @@ class NumberingModulesTest extends PHPUnit_Framework_TestCase $result2=$localobject->create($user,1); $result3=$localobject->validate($user, $result); print __METHOD__." result=".$result."\n"; - $this->assertEquals('192001-0001', $result); // counter must start to 1 + $this->assertEquals('192001-0001', $result); // counter must start to 1 $localobject=new Facture($this->savdb); $localobject->initAsSpecimen(); - $localobject->date=dol_mktime(12, 0, 0, 1, 1, 1921); // we use following year for second invoice + $localobject->date=dol_mktime(12, 0, 0, 1, 1, 1921); // we use following year for second invoice (and there is a reset required) $numbering=new mod_facture_mercure(); $result=$numbering->getNextValue($mysoc, $localobject); print __METHOD__." result=".$result."\n"; - $this->assertEquals('192101-0001', $result); // counter must be resete to 1 + $this->assertEquals('192101-0001', $result); // counter must be reseted to 1 // Now we try with a different fiscal month (forced by mask) - $conf->global->FACTURE_MERCURE_MASK_CREDIT='{yyyy}{mm}-{0000@6}'; - $conf->global->FACTURE_MERCURE_MASK_INVOICE='{yyyy}{mm}-{0000@6}'; - - $localobject=new Facture($this->savdb); - $localobject->initAsSpecimen(); - $localobject->date=dol_mktime(12, 0, 0, 1, 1, 1930); // we use year 1930 to be sure to not have existing invoice for this year - $numbering=new mod_facture_mercure(); - $result=$numbering->getNextValue($mysoc, $localobject); - $result2=$localobject->create($user,1); - $result3=$localobject->validate($user, $result); - print __METHOD__." result=".$result."\n"; - $this->assertEquals('193001-0001', $result); // counter must start to 1 - + $conf->global->FACTURE_MERCURE_MASK_CREDIT='{yyyy}{mm}-{0000@6}'; + $conf->global->FACTURE_MERCURE_MASK_INVOICE='{yyyy}{mm}-{0000@6}'; + + $localobject=new Facture($this->savdb); + $localobject->initAsSpecimen(); + $localobject->date=dol_mktime(12, 0, 0, 1, 1, 1930); // we use year 1930 to be sure to not have existing invoice for this year + $numbering=new mod_facture_mercure(); + $result=$numbering->getNextValue($mysoc, $localobject, 'last'); + print __METHOD__." result for last=".$result."\n"; + $this->assertEquals('', $result); // no existing ref into reset range + $result=$numbering->getNextValue($mysoc, $localobject); + $result2=$localobject->create($user,1); + $result3=$localobject->validate($user, $result); + print __METHOD__." result=".$result."\n"; + $this->assertEquals('193001-0001', $result); // counter must start to 1 + $result=$numbering->getNextValue($mysoc, $localobject, 'last'); + print __METHOD__." result for last=".$result."\n"; + $this->assertEquals('193001-0001', $result); // last ref into reset range should be same than last created + $localobject=new Facture($this->savdb); $localobject->initAsSpecimen(); $localobject->date=dol_mktime(12, 0, 0, 12, 1, 1930); // we use same year but fiscal month after $numbering=new mod_facture_mercure(); + $result=$numbering->getNextValue($mysoc, $localobject, 'last'); + print __METHOD__." result for last=".$result."\n"; + $this->assertEquals('', $result); // last ref into reset range should be '' $result=$numbering->getNextValue($mysoc, $localobject); $result2=$localobject->create($user,1); $result3=$localobject->validate($user, $result); @@ -408,4 +419,4 @@ class NumberingModulesTest extends PHPUnit_Framework_TestCase } } -?> \ No newline at end of file +?>