diff --git a/htdocs/compta/facture/list.php b/htdocs/compta/facture/list.php index 80d8bb47020..7c6d65266c9 100644 --- a/htdocs/compta/facture/list.php +++ b/htdocs/compta/facture/list.php @@ -1466,10 +1466,8 @@ if (isModEnabled('prelevement') && $user->hasRight('prelevement', 'bons', 'creer $arrayofmassactions['withdrawrequest'] = img_picto('', 'payment', 'class="pictofixedwidth"').$langs->trans("MakeWithdrawRequest"); } if ($user->hasRight('facture', 'supprimer')) { - if (getDolGlobalString('INVOICE_CAN_REMOVE_DRAFT_ONLY')) { + if (!getDolGlobalString('INVOICE_DIABLE_MASS_DELETION_ON_DRAFT_INVOICES')) { $arrayofmassactions['predeletedraft'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Deletedraft"); - } elseif (getDolGlobalString('INVOICE_CAN_ALWAYS_BE_REMOVED')) { // mass deletion never possible on invoices on such situation - $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete"); } } if (in_array($massaction, array('presend', 'predelete', 'makepayment'))) { diff --git a/htdocs/core/actions_massactions.inc.php b/htdocs/core/actions_massactions.inc.php index b04acf3fb28..1ebe5c9ca5e 100644 --- a/htdocs/core/actions_massactions.inc.php +++ b/htdocs/core/actions_massactions.inc.php @@ -1150,7 +1150,7 @@ if (!$error && ($massaction == 'delete' || ($action == 'delete' && $confirm == ' $result = $objecttmp->fetch($toselectid); if ($result > 0) { // Refuse deletion for some objects/status - if ($objectclass == 'Facture' && !getDolGlobalString('INVOICE_CAN_ALWAYS_BE_REMOVED') && $objecttmp->status != Facture::STATUS_DRAFT) { + if ($objectclass == 'Facture' && $objecttmp->status != Facture::STATUS_DRAFT) { $langs->load("errors"); $nbignored++; $TMsg[] = '
'.$langs->trans('ErrorOnlyDraftStatusCanBeDeletedInMassAction', $objecttmp->ref).'

'; diff --git a/htdocs/core/class/commoninvoice.class.php b/htdocs/core/class/commoninvoice.class.php index 703977c2035..139ac5245d4 100644 --- a/htdocs/core/class/commoninvoice.class.php +++ b/htdocs/core/class/commoninvoice.class.php @@ -777,6 +777,7 @@ abstract class CommonInvoice extends CommonObject $this->fetch_thirdparty(); // We need to have this->thirdparty defined, in case of the numbering rule uses tags that depend on thirdparty (like {t} tag). } $maxref = $this->getNextNumRef($this->thirdparty, 'last'); + // $maxref can be '' (means not found) if there is no invoice yet, but also if there is no invoice for the new period when there is a reset at each period // If invoice to delete is not the last one, we refuse if ($maxref != '' && $maxref != $this->ref) { diff --git a/htdocs/core/lib/admin.lib.php b/htdocs/core/lib/admin.lib.php index 06c4d795345..936aba8d4e9 100644 --- a/htdocs/core/lib/admin.lib.php +++ b/htdocs/core/lib/admin.lib.php @@ -1188,7 +1188,7 @@ function purgeSessions($mysessionid) /** * Enable a module * - * @param string $value Name of module to activate + * @param string $value Name of module to activate (modModuleName) * @param int $withdeps Activate/Disable also all dependencies * @param int $noconfverification Remove verification of $conf variable for module * @return array{nbmodules?:int,errors:string[],nbperms?:int} array('nbmodules'=>nb modules activated with success, 'errors=>array of error messages, 'nbperms'=>Nb permission added); @@ -1249,7 +1249,6 @@ function activateModule($value, $withdeps = 1, $noconfverification = 0) $ret['errors'][] = $langs->trans("ErrorModuleRequireJavascript"); return $ret; } - $const_name = $objMod->const_name; if ($noconfverification == 0) { if (getDolGlobalString($const_name)) { diff --git a/htdocs/core/modules/facture/mod_facture_mercure.php b/htdocs/core/modules/facture/mod_facture_mercure.php index 31a01aa92ba..b5e4b2fe70f 100644 --- a/htdocs/core/modules/facture/mod_facture_mercure.php +++ b/htdocs/core/modules/facture/mod_facture_mercure.php @@ -188,6 +188,7 @@ class mod_facture_mercure extends ModeleNumRefFactures // Get entities $entity = getEntity('invoicenumber', 1, $invoice); + $numFinal = get_next_value($db, $mask, 'facture', 'ref', $where, $objsoc, (empty($invoice) ? dol_now() : $invoice->date), $mode, false, null, $entity); if (!preg_match('/([0-9])+/', $numFinal)) { $this->error = $numFinal; diff --git a/htdocs/langs/en_US/errors.lang b/htdocs/langs/en_US/errors.lang index 05319e52d9b..bf2c9629a9c 100644 --- a/htdocs/langs/en_US/errors.lang +++ b/htdocs/langs/en_US/errors.lang @@ -374,6 +374,7 @@ ErrorBlockLogNeedElement=The unalterbale log object needs element type to be set ErrorBlockLogNeedObject=The unalterbale log object needs object to be set ErrorBadParameterWhenCallingCreateOfBlockedLog=Bad parameter when calling create of blocked log ErrorMaxDecimalsShownTooLowComparedToUnitOrTotal=Value for 'Max. decimals for prices shown on screen' (%s) must be equal to or greater than both 'Max. decimals for unit prices' (%s) and 'Max. decimals for total prices' (%s). This is required to prevent rounding inconsistencies on documents. +ErrorOnlyDraftStatusCanBeDeletedInMassAction=Only elements in draft status can be deleted in mass action # Warnings WarningParamUploadMaxFileSizeHigherThanPostMaxSize=Your PHP parameter upload_max_filesize (%s) is higher than PHP parameter post_max_size (%s). This is not a consistent setup. diff --git a/htdocs/langs/en_US/trips.lang b/htdocs/langs/en_US/trips.lang index bba49dfd54a..9b36906da8e 100644 --- a/htdocs/langs/en_US/trips.lang +++ b/htdocs/langs/en_US/trips.lang @@ -121,7 +121,6 @@ ValideTrip=Approve expense report ExpenseReportPayments=Expense report payments TaxUndefinedForThisCategory = Tax is undefined for this category errorComputeTtcOnMileageExpense=Error on computing mileage expense -ErrorOnlyDraftStatusCanBeDeletedInMassAction=Only elements in draft status can be deleted in mass action ## Dictionary EX_BRE=Breakfast diff --git a/test/phpunit/NumberingModulesTest.php b/test/phpunit/NumberingModulesTest.php index 290e8f6ab27..1550f2b8cea 100644 --- a/test/phpunit/NumberingModulesTest.php +++ b/test/phpunit/NumberingModulesTest.php @@ -29,6 +29,7 @@ global $conf,$user,$langs,$db; //define('TEST_DB_FORCE_TYPE','mysql'); // This is to force using mysql driver //require_once 'PHPUnit/Autoload.php'; require_once dirname(__FILE__).'/../../htdocs/master.inc.php'; +require_once dirname(__FILE__).'/../../htdocs/core/lib/admin.lib.php'; require_once dirname(__FILE__).'/CommonClassTest.class.php'; if (empty($user->id)) { @@ -71,7 +72,7 @@ class NumberingModulesTest extends CommonClassTest $conf->global->FACTURE_MERCURE_MASK_CREDIT = '{yyyy}-{0000}'; $conf->global->FACTURE_MERCURE_MASK_DEPOSIT = '{yyyy}-{0000}'; $conf->global->FACTURE_MERCURE_MASK_REPLACEMENT = '{yyyy}-{0000}'; - $conf->global->INVOICE_CAN_ALWAYS_BE_REMOVED = 0; + $conf->global->FAC_FORCE_DATE_VALIDATION = 0; // We disable option "Force date on validation", so we can make test on old dates $localobject = new Facture($db); $localobject->initAsSpecimen(); @@ -87,16 +88,26 @@ class NumberingModulesTest extends CommonClassTest $result3 = $localobject->validate($user, $result); // create invoice by forcing ref print __METHOD__." result3=".$result."\n"; $this->assertEquals(1, $result3, 'Test validation of invoice with forced ref is ok'); // counter must start to 1 + + // Force enable of BlockedLog (not possible from application, but required to allow the test with sample data)) + activateModule('modBlockedLog', 1, 1); + $result = $localobject->is_erasable(); print __METHOD__." is_erasable=".$result."\n"; - $this->assertGreaterThanOrEqual(1, $result, 'Test for is_erasable, 1st invoice'); // Can be deleted + $this->assertEquals(-7, $result, 'Test for is_erasable, 1st invoice without other invoice'); // Can be deleted + + // Disable module BlockedLog (not possible from application, but required to allow the test with sample data)) + unActivateModule('modBlockedLog'); + + $result = $localobject->is_erasable(); + print __METHOD__." is_erasable=".$result."\n"; + $this->assertGreaterThanOrEqual(1, $result, 'Test for is_erasable, 1st invoice without other invoice'); // Can be deleted // We emulate print on invoice 3 times $localobject->pos_print_counter = 3; $result = $localobject->is_erasable(); print __METHOD__." is_erasable=".$result."\n"; - $this->assertGreaterThanOrEqual(-6, $result, 'Test for is_erasable, 1st invoice already printed'); // Can be deleted - + $this->assertGreaterThanOrEqual(-6, $result, 'Test for is_erasable, 1st invoice already printed'); // Can be deleted $localobject2 = new Facture($db); $localobject2->initAsSpecimen(); @@ -220,6 +231,7 @@ class NumberingModulesTest extends CommonClassTest $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} 2nd invoice'); // counter must be now 2 $result = $localobject2->is_erasable(); @@ -227,7 +239,7 @@ class NumberingModulesTest extends CommonClassTest $this->assertGreaterThanOrEqual(1, $result); // Can be deleted $result = $localobject->is_erasable(); print __METHOD__." is_erasable=".$result."\n"; - $this->assertLessThanOrEqual(0, $result); // Case 1 can not be deleted (because there is an invoice 2) + $this->assertLessThanOrEqual(0, $result, 'Test that invoice '.$localobject->ref.' is not erasable failed'); // Invoice 1 can not be deleted (because there is an invoice 2) $localobject3 = new Facture($db); $localobject3->initAsSpecimen(); @@ -609,11 +621,11 @@ class NumberingModulesTest extends CommonClassTest $localobject->initAsSpecimen(); $localobject->fetch_thirdparty(); - $localobject->date_creation = dol_mktime(12, 0, 0, 1, 1, 1980); // we use year 1915 to be sure to not have existing invoice for this year (useful only if numbering is {0000@1} + $localobject->date_creation = dol_mktime(12, 0, 0, 1, 1, 1980); // we use year 1980 to be sure to not have existing invoice for this year (useful only if numbering is {0000@1} $numbering = new mod_expedition_safor(); $result = $numbering->getNextValue($mysoc, $localobject); print __METHOD__." result=".$result."\n"; - $this->assertEquals('SH8001-0003', $result); // counter must start to 1 + $this->assertEquals('SH8001-0003', $result); // SH8001-0003 is valid with dataset demo } }