2
0
forked from Wavyzz/dolibarr

New: Can use tag {mm} before {yy} even when there is a reset into

numbering masks.
Qual: Enhance phpunit tests to include this case.
This commit is contained in:
Laurent Destailleur
2013-09-11 14:18:56 +02:00
parent 50ce834dd0
commit 0bb18cb05c
3 changed files with 113 additions and 62 deletions

View File

@@ -46,16 +46,17 @@ For users:
- New: [ task #1016 ] Can define a specific numbering for deposits - New: [ task #1016 ] Can define a specific numbering for deposits
- New: [ task #918 ] Stock replenishment - New: [ task #918 ] Stock replenishment
- Fix: [ bug #992 ] Proforma invoices don't have a separated numeric count - Fix: [ bug #992 ] Proforma invoices don't have a separated numeric count
- New : Add pdf link into supplier invoice list and supplier order list - New: Add pdf link into supplier invoice list and supplier order list
- New : Genrate auto the PDF for supplier invoice - New: Genrate auto the PDF for supplier invoice
- New : Add category into filter webservice thirdparty method getListOfThirdParties - New: Add category into filter webservice thirdparty method getListOfThirdParties
- New : Allow to define margin or mark rate during quoting, ordering, invoicing - New: Allow to define margin or mark rate during quoting, ordering, invoicing
- New : User permissions on margin module - New: User permissions on margin module
- New : Add ref supplier into muscadet model - New: Add ref supplier into muscadet model
- New: Can use tag {mm} before {yy} even when there is a reset into numbering masks.
For translators: For translators:
- Qual: Normalized sort order of all languages files with english reference files. - Qual: Normalized sort order of all languages files with english reference files.
- New: Add language code files for South Africa. - New: Add language code files for South Africa, France new caledonia.
- New: Translate the email to change password. - New: Translate the email to change password.
For developers: For developers:
@@ -98,7 +99,7 @@ Goal is to fix old compatibility code that does not match hook specifications:
All content added must be tagged by a '<div>' with css class="login_block_elem" All content added must be tagged by a '<div>' with css class="login_block_elem"
3) Some methods object->addline used a first parameter that was object->id, some not. Of course 3) Some methods object->addline used a first parameter that was object->id, some not. Of course
this was not a good pratice, since object->id is already known so no need to provide it as this was not a good pratice, since object->id is already known, there is no need to provide id as
parameter. All methods addline in this case were modified to remove this parameter. parameter. All methods addline in this case were modified to remove this parameter.

View File

@@ -549,6 +549,7 @@ function get_next_value($db,$mask,$table,$field,$where='',$objsoc='',$date='',$m
$maskcounter=$reg[1]; $maskcounter=$reg[1];
$maskraz=-1; $maskraz=-1;
$maskoffset=0; $maskoffset=0;
$resetEveryMonth=false;
if (dol_strlen($maskcounter) < 3) return 'CounterMustHaveMoreThan3Digits'; if (dol_strlen($maskcounter) < 3) return 'CounterMustHaveMoreThan3Digits';
// Extract value for third party mask counter // Extract value for third party mask counter
@@ -622,21 +623,32 @@ function get_next_value($db,$mask,$table,$field,$where='',$objsoc='',$date='',$m
if ($maskraz > 12) return 'ErrorBadMaskBadRazMonth'; if ($maskraz > 12) return 'ErrorBadMaskBadRazMonth';
// Define posy, posm and reg // Define posy, posm and reg
if ($maskraz > 0) if ($maskraz > 1) // if reset is not first month, we need month and year into mask
{ {
if (! preg_match('/^(.*)\{(y+)\}\{(m+)\}/i',$maskwithonlyymcode)
&& ! preg_match('/^(.*)\{(m+)\}\{(y+)\}/i',$maskwithonlyymcode)) return 'ErrorCantUseRazInStartedYearIfNoYearMonthInMask';
if (preg_match('/^(.*)\{(y+)\}\{(m+)\}/i',$maskwithonlyymcode,$reg)) { $posy=2; $posm=3; } if (preg_match('/^(.*)\{(y+)\}\{(m+)\}/i',$maskwithonlyymcode,$reg)) { $posy=2; $posm=3; }
elseif (preg_match('/^(.*)\{(m+)\}\{(y+)\}/i',$maskwithonlyymcode,$reg)) { $posy=3; $posm=2; } elseif (preg_match('/^(.*)\{(m+)\}\{(y+)\}/i',$maskwithonlyymcode,$reg)) { $posy=3; $posm=2; }
else return 'ErrorCantUseRazInStartedYearIfNoYearMonthInMask';
if (dol_strlen($reg[$posy]) < 2) return 'ErrorCantUseRazWithYearOnOneDigit'; if (dol_strlen($reg[$posy]) < 2) return 'ErrorCantUseRazWithYearOnOneDigit';
} }
else else // if reset is for a specific month in year, we need year
{ {
if (! preg_match('/^(.*)\{(y+)\}/i',$maskwithonlyymcode)) return 'ErrorCantUseRazIfNoYearInMask'; if (preg_match('/^(.*)\{(m+)\}\{(y+)\}/i',$maskwithonlyymcode,$reg)) { $posy=3; $posm=2; }
if (preg_match('/^(.*)\{(y+)\}/i',$maskwithonlyymcode,$reg)) { $posy=2; $posm=0; } else if (preg_match('/^(.*)\{(y+)\}\{(m+)\}/i',$maskwithonlyymcode,$reg)) { $posy=2; $posm=3; }
else if (preg_match('/^(.*)\{(y+)\}/i',$maskwithonlyymcode,$reg)) { $posy=2; $posm=0; }
else return 'ErrorCantUseRazIfNoYearInMask';
} }
//print "x".$maskwithonlyymcode." ".$maskraz." ".$posy." ".$posm; // Define length
//var_dump($reg); $yearlen = $posy?dol_strlen($reg[$posy]):0;
$monthlen = $posm?dol_strlen($reg[$posm]):0;
// Define pos
$yearpos = (dol_strlen($reg[1])+1);
$monthpos = ($yearpos+$yearlen);
if ($posy == 3 && $posm == 2) { // if month is before year
$monthpos = (dol_strlen($reg[1])+1);
$yearpos = ($monthpos+$monthlen);
}
//print "xxx ".$maskwithonlyymcode." maskraz=".$maskraz." posy=".$posy." yearlen=".$yearlen." yearpos=".$yearpos." posm=".$posm." monthlen=".$monthlen." monthpos=".$monthpos." yearoffsettype=".$yearoffsettype." resetEveryMonth=".$resetEveryMonth."\n";
// Define $yearcomp and $monthcomp (that will be use in the select where to search max number) // Define $yearcomp and $monthcomp (that will be use in the select where to search max number)
$monthcomp=$maskraz; $monthcomp=$maskraz;
@@ -662,7 +674,6 @@ function get_next_value($db,$mask,$table,$field,$where='',$objsoc='',$date='',$m
// For backward compatibility // For backward compatibility
else if (date("m",$date) < $maskraz && empty($resetEveryMonth)) { $yearoffset=-1; } // If current month lower that month of return to zero, year is previous year else if (date("m",$date) < $maskraz && empty($resetEveryMonth)) { $yearoffset=-1; } // If current month lower that month of return to zero, year is previous year
$yearlen = dol_strlen($reg[$posy]);
if ($yearlen == 4) $yearcomp=sprintf("%04d",date("Y",$date)+$yearoffset); if ($yearlen == 4) $yearcomp=sprintf("%04d",date("Y",$date)+$yearoffset);
elseif ($yearlen == 2) $yearcomp=sprintf("%02d",date("y",$date)+$yearoffset); elseif ($yearlen == 2) $yearcomp=sprintf("%02d",date("y",$date)+$yearoffset);
elseif ($yearlen == 1) $yearcomp=substr(date("y",$date),2,1)+$yearoffset; elseif ($yearlen == 1) $yearcomp=substr(date("y",$date),2,1)+$yearoffset;
@@ -671,14 +682,6 @@ function get_next_value($db,$mask,$table,$field,$where='',$objsoc='',$date='',$m
if ($yearlen == 4) $yearcomp1=sprintf("%04d",date("Y",$date)+$yearoffset+1); if ($yearlen == 4) $yearcomp1=sprintf("%04d",date("Y",$date)+$yearoffset+1);
elseif ($yearlen == 2) $yearcomp1=sprintf("%02d",date("y",$date)+$yearoffset+1); elseif ($yearlen == 2) $yearcomp1=sprintf("%02d",date("y",$date)+$yearoffset+1);
$monthlen = dol_strlen($reg[$posm]);
$yearpos = (dol_strlen($reg[1])+1);
$monthpos = ($yearpos+$yearlen);
if ($posy == 3) {
$monthpos = (dol_strlen($reg[1])+1);
$yearpos = ($monthpos+$monthlen);
}
$sqlwhere.="("; $sqlwhere.="(";
$sqlwhere.=" (SUBSTRING(".$field.", ".$yearpos.", ".$yearlen.") = '".$yearcomp."'"; $sqlwhere.=" (SUBSTRING(".$field.", ".$yearpos.", ".$yearlen.") = '".$yearcomp."'";
$sqlwhere.=" AND SUBSTRING(".$field.", ".$monthpos.", ".$monthlen.") >= '".str_pad($monthcomp, $monthlen, '0', STR_PAD_LEFT)."')"; $sqlwhere.=" AND SUBSTRING(".$field.", ".$monthpos.", ".$monthlen.") >= '".str_pad($monthcomp, $monthlen, '0', STR_PAD_LEFT)."')";
@@ -687,20 +690,14 @@ function get_next_value($db,$mask,$table,$field,$where='',$objsoc='',$date='',$m
$sqlwhere.=" AND SUBSTRING(".$field.", ".$monthpos.", ".$monthlen.") < '".str_pad($monthcomp, $monthlen, '0', STR_PAD_LEFT)."') "; $sqlwhere.=" AND SUBSTRING(".$field.", ".$monthpos.", ".$monthlen.") < '".str_pad($monthcomp, $monthlen, '0', STR_PAD_LEFT)."') ";
$sqlwhere.=')'; $sqlwhere.=')';
} }
else if($resetEveryMonth) { else if ($resetEveryMonth)
$monthlen = dol_strlen($reg[$posm]); {
$yearpos = (dol_strlen($reg[1])+1); $sqlwhere.="(SUBSTRING(".$field.", ".$yearpos.", ".$yearlen.") = '".$yearcomp."'";
$monthpos = ($yearpos+$yearlen); $sqlwhere.=" AND SUBSTRING(".$field.", ".$monthpos.", ".$monthlen.") = '".str_pad($monthcomp, $monthlen, '0', STR_PAD_LEFT)."')";
if ($posy == 3) {
$monthpos = (dol_strlen($reg[1])+1);
$yearpos = ($monthpos+$monthlen);
}
$sqlwhere.=" SUBSTRING(".$field.", ".$yearpos.", ".$yearlen.") = '".$yearcomp."'";
$sqlwhere.=" AND SUBSTRING(".$field.", ".$monthpos.", ".$monthlen.") = '".str_pad($monthcomp, $monthlen, '0', STR_PAD_LEFT)."' ";
} }
else // reset is done on january else // reset is done on january
{ {
$sqlwhere.='(SUBSTRING('.$field.', '.(dol_strlen($reg[1])+1).', '.dol_strlen($reg[2]).") = '".$yearcomp."')"; $sqlwhere.='(SUBSTRING('.$field.', '.$yearpos.', '.$yearlen.") = '".$yearcomp."')";
} }
} }
//print "sqlwhere=".$sqlwhere." yearcomp=".$yearcomp."<br>\n"; // sqlwhere and yearcomp defined only if we ask a reset //print "sqlwhere=".$sqlwhere." yearcomp=".$yearcomp."<br>\n"; // sqlwhere and yearcomp defined only if we ask a reset
@@ -1451,46 +1448,46 @@ function dolGetElementUrl($objectid,$objecttype,$withpicto=0,$option='')
// To work with non standard path // To work with non standard path
if ($objecttype == 'facture' || $objecttype == 'invoice') { if ($objecttype == 'facture' || $objecttype == 'invoice') {
$classpath = 'compta/facture/class'; $classpath = 'compta/facture/class';
$module='facture'; $module='facture';
$subelement='facture'; $subelement='facture';
} }
if ($objecttype == 'commande' || $objecttype == 'order') { if ($objecttype == 'commande' || $objecttype == 'order') {
$classpath = 'commande/class'; $classpath = 'commande/class';
$module='commande'; $module='commande';
$subelement='commande'; $subelement='commande';
} }
if ($objecttype == 'propal') { if ($objecttype == 'propal') {
$classpath = 'comm/propal/class'; $classpath = 'comm/propal/class';
} }
if ($objecttype == 'shipping') { if ($objecttype == 'shipping') {
$classpath = 'expedition/class'; $classpath = 'expedition/class';
$subelement = 'expedition'; $subelement = 'expedition';
$module = 'expedition_bon'; $module = 'expedition_bon';
} }
if ($objecttype == 'delivery') { if ($objecttype == 'delivery') {
$classpath = 'livraison/class'; $classpath = 'livraison/class';
$subelement = 'livraison'; $subelement = 'livraison';
$module = 'livraison_bon'; $module = 'livraison_bon';
} }
if ($objecttype == 'contract') { if ($objecttype == 'contract') {
$classpath = 'contrat/class'; $classpath = 'contrat/class';
$module='contrat'; $module='contrat';
$subelement='contrat'; $subelement='contrat';
} }
if ($objecttype == 'member') { if ($objecttype == 'member') {
$classpath = 'adherents/class'; $classpath = 'adherents/class';
$module='adherent'; $module='adherent';
$subelement='adherent'; $subelement='adherent';
} }
if ($objecttype == 'cabinetmed_cons') { if ($objecttype == 'cabinetmed_cons') {
$classpath = 'cabinetmed/class'; $classpath = 'cabinetmed/class';
$module='cabinetmed'; $module='cabinetmed';
$subelement='cabinetmedcons'; $subelement='cabinetmedcons';
} }
if ($objecttype == 'fichinter') { if ($objecttype == 'fichinter') {
$classpath = 'fichinter/class'; $classpath = 'fichinter/class';
$module='ficheinter'; $module='ficheinter';
$subelement='fichinter'; $subelement='fichinter';
} }
@@ -1498,13 +1495,13 @@ function dolGetElementUrl($objectid,$objecttype,$withpicto=0,$option='')
$classfile = strtolower($subelement); $classname = ucfirst($subelement); $classfile = strtolower($subelement); $classname = ucfirst($subelement);
if ($objecttype == 'invoice_supplier') { if ($objecttype == 'invoice_supplier') {
$classfile = 'fournisseur.facture'; $classfile = 'fournisseur.facture';
$classname='FactureFournisseur'; $classname='FactureFournisseur';
$classpath = 'fourn/class'; $classpath = 'fourn/class';
$module='fournisseur'; $module='fournisseur';
} }
if ($objecttype == 'order_supplier') { if ($objecttype == 'order_supplier') {
$classfile = 'fournisseur.commande'; $classfile = 'fournisseur.commande';
$classname='CommandeFournisseur'; $classname='CommandeFournisseur';
$classpath = 'fourn/class'; $classpath = 'fourn/class';
$module='fournisseur'; $module='fournisseur';

View File

@@ -146,7 +146,7 @@ class NumberingModulesTest extends PHPUnit_Framework_TestCase
$this->assertEquals('1915-0001', $result); // counter must start to 1 $this->assertEquals('1915-0001', $result); // counter must start to 1
$result=$localobject->is_erasable(); $result=$localobject->is_erasable();
print __METHOD__." is_erasable=".$result."\n"; print __METHOD__." is_erasable=".$result."\n";
$this->assertEquals(1, $result); // Can be deleted $this->assertEquals(1, $result, 'Test for {yyyy}-{0000}, 1st invoice'); // Can be deleted
$localobject2=new Facture($this->savdb); $localobject2=new Facture($this->savdb);
$localobject2->initAsSpecimen(); $localobject2->initAsSpecimen();
@@ -159,13 +159,13 @@ class NumberingModulesTest extends PHPUnit_Framework_TestCase
$result2=$localobject2->create($user,1); $result2=$localobject2->create($user,1);
$result3=$localobject2->validate($user, $result); // create invoice by forcing ref $result3=$localobject2->validate($user, $result); // create invoice by forcing ref
print __METHOD__." result=".$result."\n"; print __METHOD__." result=".$result."\n";
$this->assertEquals('1916-0002', $result); // counter must not be reseted so be 2 $this->assertEquals('1916-0002', $result); // counter must be now 2 (not reseted)
$result=$localobject2->is_erasable(); $result=$localobject2->is_erasable();
print __METHOD__." is_erasable=".$result."\n"; print __METHOD__." is_erasable=".$result."\n";
$this->assertEquals(1, $result); // Can be deleted $this->assertEquals(1, $result); // Can be deleted
$result=$localobject->is_erasable(); $result=$localobject->is_erasable();
print __METHOD__." is_erasable=".$result."\n"; print __METHOD__." is_erasable=".$result."\n";
$this->assertEquals(0, $result); // Case 1 can not be deleted (case 2 is more recent) $this->assertEquals(0, $result, 'Test for {yyyy}-{0000} that is_erasable is 0 for 1st invoice'); // 1 can no more be deleted (2 is more recent
// Now we try with a reset // Now we try with a reset
$conf->global->FACTURE_MERCURE_MASK_CREDIT='{yyyy}-{0000@1}'; $conf->global->FACTURE_MERCURE_MASK_CREDIT='{yyyy}-{0000@1}';
@@ -176,10 +176,26 @@ class NumberingModulesTest extends PHPUnit_Framework_TestCase
$localobject->date=dol_mktime(12, 0, 0, 1, 1, 1910); // we use year 1910 to be sure to not have existing invoice for this year $localobject->date=dol_mktime(12, 0, 0, 1, 1, 1910); // we use year 1910 to be sure to not have existing invoice for this year
$numbering=new mod_facture_mercure(); $numbering=new mod_facture_mercure();
$result=$numbering->getNextValue($mysoc, $localobject); $result=$numbering->getNextValue($mysoc, $localobject);
$result2=$localobject->create($user,1);
$result3=$localobject->validate($user, $result);
print __METHOD__." result=".$result."\n"; print __METHOD__." result=".$result."\n";
$this->assertEquals('1910-0001', $result); // counter must start to 1 $this->assertEquals('1910-0001', $result, 'Test for {yyyy}-{0000@1} 1st invoice'); // counter must start to 1
$localobject2=new Facture($this->savdb);
$localobject2->initAsSpecimen();
$localobject2->date=dol_mktime(12, 0, 0, 1, 1, 1910); // we use same year for second invoice (and there is a reset required)
$numbering=new mod_facture_mercure();
$result=$numbering->getNextValue($mysoc, $localobject2);
print __METHOD__." result=".$result."\n";
$this->assertEquals('1910-0002', $result, 'Test for {yyyy}-{0000@1} 2nd invoice, same day'); // counter must be now 2
$localobject3=new Facture($this->savdb);
$localobject3->initAsSpecimen();
$localobject3->date=dol_mktime(12, 0, 0, 1, 1, 1911); // we use next year for third invoice (and there is a reset required)
$numbering=new mod_facture_mercure();
$result=$numbering->getNextValue($mysoc, $localobject3);
print __METHOD__." result=".$result."\n";
$this->assertEquals('1911-0001', $result, 'Test for {yyyy}-{0000@1} 3nd invoice, same day'); // counter must be now 1
// Same mask but we add month // Same but we add month after year
$conf->global->FACTURE_MERCURE_MASK_CREDIT='{yyyy}{mm}-{0000@1}'; $conf->global->FACTURE_MERCURE_MASK_CREDIT='{yyyy}{mm}-{0000@1}';
$conf->global->FACTURE_MERCURE_MASK_INVOICE='{yyyy}{mm}-{0000@1}'; $conf->global->FACTURE_MERCURE_MASK_INVOICE='{yyyy}{mm}-{0000@1}';
$localobject=new Facture($this->savdb); $localobject=new Facture($this->savdb);
@@ -190,11 +206,10 @@ class NumberingModulesTest extends PHPUnit_Framework_TestCase
$result2=$localobject->create($user,1); $result2=$localobject->create($user,1);
$result3=$localobject->validate($user, $result); $result3=$localobject->validate($user, $result);
print __METHOD__." result=".$result."\n"; print __METHOD__." result=".$result."\n";
$this->assertEquals('192001-0001', $result); // counter must start to 1 $this->assertEquals('192001-0001', $result, 'Test for {yyyy}{mm}-{0000@1} 1st invoice'); // counter must start to 1
$result=$localobject->is_erasable(); $result=$localobject->is_erasable();
print __METHOD__." is_erasable=".$result."\n"; print __METHOD__." is_erasable=".$result."\n";
$this->assertEquals(1, $result); // Can be deleted $this->assertEquals(1, $result); // Can be deleted
$localobject2=new Facture($this->savdb); $localobject2=new Facture($this->savdb);
$localobject2->initAsSpecimen(); $localobject2->initAsSpecimen();
$localobject2->date=dol_mktime(12, 0, 0, 1, 1, 1921); // we use following year for second invoice (and there is a reset required) $localobject2->date=dol_mktime(12, 0, 0, 1, 1, 1921); // we use following year for second invoice (and there is a reset required)
@@ -211,6 +226,44 @@ class NumberingModulesTest extends PHPUnit_Framework_TestCase
print __METHOD__." is_erasable=".$result."\n"; print __METHOD__." is_erasable=".$result."\n";
$this->assertEquals(1, $result); // Case 1 can be deleted (because there was a reset for case 2) $this->assertEquals(1, $result); // Case 1 can be deleted (because there was a reset for case 2)
// Same but we add month before year and use a year on 2 digits
$conf->global->FACTURE_MERCURE_MASK_CREDIT='[mm}{yy}-{0000@1}';
$conf->global->FACTURE_MERCURE_MASK_INVOICE='{mm}{yy}-{0000@1}';
$localobject=new Facture($this->savdb);
$localobject->initAsSpecimen();
$localobject->date=dol_mktime(12, 0, 0, 1, 1, 1925); // we use year 1925 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('0125-0001', $result, 'Test for {mm}{yy}-{0000@1} 1st invoice'); // counter must start to 1
$result=$localobject->is_erasable(); // This call get getNextNumRef with param 'last'
print __METHOD__." is_erasable=".$result."\n";
$this->assertEquals(1, $result); // Can be deleted
$localobject2=new Facture($this->savdb);
$localobject2->initAsSpecimen();
$localobject2->date=dol_mktime(12, 0, 0, 1, 1, 1925); // we use same year 1925 for second invoice (and there is a reset required)
$numbering=new mod_facture_mercure();
$result=$numbering->getNextValue($mysoc, $localobject2);
$result2=$localobject2->create($user,1);
$result3=$localobject2->validate($user, $result);
print __METHOD__." result=".$result."\n";
$this->assertEquals('0125-0002', $result, 'Test for {mm}{yy}-{0000@1} 2st invoice'); // counter must be now 2
$result=$localobject2->is_erasable();
print __METHOD__." is_erasable=".$result."\n";
$this->assertEquals(1, $result); // Can be deleted
$result=$localobject->is_erasable();
print __METHOD__." is_erasable=".$result."\n";
$this->assertEquals(0, $result); // Case 1 can not be deleted (because there is an invoice 2)
$localobject3=new Facture($this->savdb);
$localobject3->initAsSpecimen();
$localobject3->date=dol_mktime(12, 0, 0, 1, 1, 1926); // we use following year for third invoice (and there is a reset required)
$numbering=new mod_facture_mercure();
$result=$numbering->getNextValue($mysoc, $localobject3);
print __METHOD__." result=".$result."\n";
$this->assertEquals('0126-0001', $result, 'Test for {mm}{yy}-{0000@1} 3rd invoice'); // counter must be now 1
// Try an offset when an invoice already exists // Try an offset when an invoice already exists
$conf->global->FACTURE_MERCURE_MASK_CREDIT='{yyyy}{mm}-{0000+9990}'; $conf->global->FACTURE_MERCURE_MASK_CREDIT='{yyyy}{mm}-{0000+9990}';
$conf->global->FACTURE_MERCURE_MASK_INVOICE='{yyyy}{mm}-{0000+9990}'; $conf->global->FACTURE_MERCURE_MASK_INVOICE='{yyyy}{mm}-{0000+9990}';