Improve test coverage.

This commit is contained in:
James Cole
2019-06-10 20:14:00 +02:00
parent 8efb73694d
commit 2ab9d2e6ee
75 changed files with 4672 additions and 484 deletions

View File

@@ -30,6 +30,7 @@ use Schema;
/**
* Class CorrectDatabase
* @codeCoverageIgnore
*/
class CorrectDatabase extends Command
{
@@ -38,7 +39,7 @@ class CorrectDatabase extends Command
*
* @var string
*/
protected $description = 'Will correct the integrity of your database, of necessary.';
protected $description = 'Will correct the integrity of your database, if necessary.';
/**
* The name and signature of the console command.
*

View File

@@ -22,6 +22,7 @@
namespace FireflyIII\Console\Commands\Correction;
use Exception;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\User;
use Illuminate\Console\Command;
@@ -35,7 +36,7 @@ class CreateAccessTokens extends Command
*
* @var string
*/
protected $description = 'Creates user access tokens.';
protected $description = 'Creates user access tokens which are used for command line access to personal data.';
/**
* The name and signature of the console command.
*
@@ -51,9 +52,13 @@ class CreateAccessTokens extends Command
*/
public function handle(): int
{
// make repository:
/** @var UserRepositoryInterface $repository */
$repository = app(UserRepositoryInterface::class);
$start = microtime(true);
$count = 0;
$users = User::get();
$users= $repository->all();
/** @var User $user */
foreach ($users as $user) {
$pref = app('preferences')->getForUser($user, 'access_token', null);

View File

@@ -58,12 +58,13 @@ class CreateLinkTypes extends Command
'Reimbursement' => ['(partially) reimburses', 'is (partially) reimbursed by'],
];
foreach ($set as $name => $values) {
$link = LinkType::where('name', $name)->where('outward', $values[0])->where('inward', $values[1])->first();
$link = LinkType::where('name', $name)
->first();
if (null === $link) {
$link = new LinkType;
$link->name = $name;
$link->outward = $values[0];
$link->inward = $values[1];
$link->outward = $values[0];
++$count;
$this->line(sprintf('Created missing link type "%s"', $name));
}

View File

@@ -59,7 +59,7 @@ class DeleteEmptyGroups extends Command
$this->info('No empty transaction groups.');
}
if ($count > 0) {
$this->info(sprintf('Deleted %d empty transaction groups.', $count));
$this->info(sprintf('Deleted %d empty transaction group(s).', $count));
TransactionGroup::whereNull('deleted_at')->whereNotIn('id', $groups)->delete();
}
$end = round(microtime(true) - $start, 2);

View File

@@ -72,9 +72,12 @@ class DeleteEmptyJournals extends Command
foreach ($set as $entry) {
try {
TransactionJournal::find($entry->id)->delete();
// @codeCoverageIgnoreStart
} catch (Exception $e) {
Log::info(sprintf('Could not delete entry: %s', $e->getMessage()));
}
// @codeCoverageIgnoreEnd
$this->info(sprintf('Deleted empty transaction journal #%d', $entry->id));
++$count;
}
@@ -90,15 +93,6 @@ class DeleteEmptyJournals extends Command
*/
private function deleteUnevenJournals(): void
{
/**
* select count(transactions.transaction_journal_id) as the_count, transactions.transaction_journal_id from transactions
*
* where transactions.deleted_at is null
*
* group by transactions.transaction_journal_id
* having the_count in ()
*/
$set = Transaction
::whereNull('deleted_at')
->having('the_count', '!=', '2')
@@ -111,9 +105,12 @@ class DeleteEmptyJournals extends Command
// uneven number, delete journal and transactions:
try {
TransactionJournal::find((int)$row->transaction_journal_id)->delete();
// @codeCoverageIgnoreStart
} catch(Exception $e) {
Log::info(sprintf('Could not delete journal: %s', $e->getMessage()));
}
// @codeCoverageIgnoreEnd
Transaction::where('transaction_journal_id', (int)$row->transaction_journal_id)->delete();
$this->info(sprintf('Deleted transaction journal #%d because it had an uneven number of transactions.', $row->transaction_journal_id));
$total++;

View File

@@ -25,8 +25,8 @@ use Exception;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Console\Command;
use stdClass;
use Log;
use stdClass;
/**
* Deletes transactions where the journal has been deleted.
@@ -81,17 +81,20 @@ class DeleteOrphanedTransactions extends Command
if ($journal) {
try {
$journal->delete();
// @codeCoverageIgnoreStart
} catch (Exception $e) {
Log::info(sprintf('Could not delete transaction %s', $e->getMessage()));
Log::info(sprintf('Could not delete journal %s', $e->getMessage()));
}
// @codeCoverageIgnoreEnd
}
Transaction::where('transaction_journal_id', (int)$transaction->transaction_journal_id)->delete();
$this->line(
sprintf('Deleted transaction journal #%d because account #%d was already deleted.', $transaction->transaction_journal_id, $transaction->account_id)
sprintf('Deleted transaction journal #%d because account #%d was already deleted.',
$transaction->transaction_journal_id, $transaction->account_id)
);
$count++;
}
if(0===$count) {
if (0 === $count) {
$this->info('No orphaned accounts.');
}
}

View File

@@ -47,7 +47,6 @@ class DeleteZeroAmount extends Command
/**
* Execute the console command.
* @throws Exception
* @return int
*/
public function handle(): int
@@ -60,7 +59,13 @@ class DeleteZeroAmount extends Command
/** @var TransactionJournal $journal */
foreach ($journals as $journal) {
$this->info(sprintf('Deleted transaction journal #%d because the amount is zero (0.00).', $journal->id));
$journal->delete();
try {
$journal->delete();
// @codeCoverageIgnoreStart
} catch (Exception $e) {
$this->line($e->getMessage());
}
// @codeCoverageIgnoreEnd
Transaction::where('transaction_journal_id', $journal->id)->delete();
}
if (0 === $journals->count()) {

View File

@@ -86,9 +86,13 @@ class EnableCurrencies extends Command
$found = array_unique($found);
$this->info(sprintf('%d different currencies are currently in use.', count($found)));
$disabled = TransactionCurrency::whereIn('id', $found)->where('enabled', false)->count();
if ($disabled > 0) {
$this->info(sprintf('%d were still disabled. This has been corrected.', $disabled));
$this->info(sprintf('%d were (was) still disabled. This has been corrected.', $disabled));
}
if (0 === $disabled) {
$this->info('All currencies are correctly enabled or disabled.');
}
TransactionCurrency::whereIn('id', $found)->update(['enabled' => true]);

View File

@@ -52,82 +52,16 @@ class FixAccountTypes extends Command
private $factory;
/** @var array */
private $fixable;
/** @var int */
private $count;
/**
* @param TransactionJournal $journal
* @param string $type
* @param Transaction $source
* @param Transaction $dest
* @throws FireflyException
* FixAccountTypes constructor.
*/
public function fixJournal(TransactionJournal $journal, string $type, Transaction $source, Transaction $dest): void
public function __construct()
{
// variables:
$combination = sprintf('%s%s%s', $type, $source->account->accountType->type, $dest->account->accountType->type);
switch ($combination) {
case sprintf('%s%s%s', TransactionType::TRANSFER, AccountType::ASSET, AccountType::LOAN):
case sprintf('%s%s%s', TransactionType::TRANSFER, AccountType::ASSET, AccountType::DEBT):
case sprintf('%s%s%s', TransactionType::TRANSFER, AccountType::ASSET, AccountType::MORTGAGE):
// from an asset to a liability should be a withdrawal:
$withdrawal = TransactionType::whereType(TransactionType::WITHDRAWAL)->first();
$journal->transactionType()->associate($withdrawal);
$journal->save();
$this->info(sprintf('Converted transaction #%d from a transfer to a withdrawal', $journal->id));
// check it again:
$this->inspectJournal($journal);
break;
case sprintf('%s%s%s', TransactionType::TRANSFER, AccountType::LOAN, AccountType::ASSET):
case sprintf('%s%s%s', TransactionType::TRANSFER, AccountType::DEBT, AccountType::ASSET):
case sprintf('%s%s%s', TransactionType::TRANSFER, AccountType::MORTGAGE, AccountType::ASSET):
// from a liability to an asset should be a deposit.
$deposit = TransactionType::whereType(TransactionType::DEPOSIT)->first();
$journal->transactionType()->associate($deposit);
$journal->save();
$this->info(sprintf('Converted transaction #%d from a transfer to a deposit', $journal->id));
// check it again:
$this->inspectJournal($journal);
break;
case sprintf('%s%s%s', TransactionType::WITHDRAWAL, AccountType::ASSET, AccountType::REVENUE):
// withdrawals with a revenue account as destination instead of an expense account.
$this->factory->setUser($journal->user);
$result = $this->factory->findOrCreate($source->account->name, AccountType::EXPENSE);
$dest->account()->associate($result);
$dest->save();
$this->info(
sprintf(
'Transaction journal #%d, destination account changed from #%d ("%s") to #%d ("%s").', $journal->id,
$source->account->id, $source->account->name,
$result->id, $result->name
)
);
$this->inspectJournal($journal);
break;
case sprintf('%s%s%s', TransactionType::DEPOSIT, AccountType::EXPENSE, AccountType::ASSET):
// deposits with an expense account as source instead of a revenue account.
// find revenue account.
$this->factory->setUser($journal->user);
$result = $this->factory->findOrCreate($source->account->name, AccountType::REVENUE);
$source->account()->associate($result);
$source->save();
$this->info(
sprintf(
'Transaction journal #%d, source account changed from #%d ("%s") to #%d ("%s").', $journal->id,
$source->account->id, $source->account->name,
$result->id, $result->name
)
);
$this->inspectJournal($journal);
break;
break;
default:
$this->info(sprintf('The source account of %s #%d cannot be of type "%s".', $type, $journal->id, $source->account->accountType->type));
$this->info(sprintf('The destination account of %s #%d cannot be of type "%s".', $type, $journal->id, $dest->account->accountType->type));
break;
}
parent::__construct();
$this->count = 0;
}
/**
@@ -159,19 +93,103 @@ class FixAccountTypes extends Command
$this->expected = config('firefly.source_dests');
$journals = TransactionJournal
::with(['TransactionType', 'transactions', 'transactions.account', 'transactions.account.accounttype'])->get();
$journals = TransactionJournal::with(['TransactionType', 'transactions', 'transactions.account', 'transactions.account.accounttype'])->get();
foreach ($journals as $journal) {
$this->inspectJournal($journal);
}
if (0 === $this->count) {
$this->info('All account types are OK!');
}
if (0 !== $this->count) {
$this->info(sprintf('Acted on %d transaction(s)!', $this->count));
}
$end = round(microtime(true) - $start, 2);
$this->info(sprintf('Verified account types in %s seconds', $end));
$this->info(sprintf('Verifying account types took %s seconds', $end));
return 0;
}
/**
* @param TransactionJournal $journal
* @param string $type
* @param Transaction $source
* @param Transaction $dest
* @throws FireflyException
*/
private function fixJournal(TransactionJournal $journal, string $type, Transaction $source, Transaction $dest): void
{
$this->count++;
// variables:
$combination = sprintf('%s%s%s', $type, $source->account->accountType->type, $dest->account->accountType->type);
switch ($combination) {
case sprintf('%s%s%s', TransactionType::TRANSFER, AccountType::ASSET, AccountType::LOAN):
case sprintf('%s%s%s', TransactionType::TRANSFER, AccountType::ASSET, AccountType::DEBT):
case sprintf('%s%s%s', TransactionType::TRANSFER, AccountType::ASSET, AccountType::MORTGAGE):
// from an asset to a liability should be a withdrawal:
$withdrawal = TransactionType::whereType(TransactionType::WITHDRAWAL)->first();
$journal->transactionType()->associate($withdrawal);
$journal->save();
$this->info(sprintf('Converted transaction #%d from a transfer to a withdrawal.', $journal->id));
// check it again:
$this->inspectJournal($journal);
break;
case sprintf('%s%s%s', TransactionType::TRANSFER, AccountType::LOAN, AccountType::ASSET):
case sprintf('%s%s%s', TransactionType::TRANSFER, AccountType::DEBT, AccountType::ASSET):
case sprintf('%s%s%s', TransactionType::TRANSFER, AccountType::MORTGAGE, AccountType::ASSET):
// from a liability to an asset should be a deposit.
$deposit = TransactionType::whereType(TransactionType::DEPOSIT)->first();
$journal->transactionType()->associate($deposit);
$journal->save();
$this->info(sprintf('Converted transaction #%d from a transfer to a deposit.', $journal->id));
// check it again:
$this->inspectJournal($journal);
break;
case sprintf('%s%s%s', TransactionType::WITHDRAWAL, AccountType::ASSET, AccountType::REVENUE):
// withdrawals with a revenue account as destination instead of an expense account.
$this->factory->setUser($journal->user);
$oldDest = $dest->account;
$result = $this->factory->findOrCreate($dest->account->name, AccountType::EXPENSE);
$dest->account()->associate($result);
$dest->save();
$this->info(
sprintf(
'Transaction journal #%d, destination account changed from #%d ("%s") to #%d ("%s").', $journal->id,
$oldDest->id, $oldDest->name,
$result->id, $result->name
)
);
$this->inspectJournal($journal);
break;
case sprintf('%s%s%s', TransactionType::DEPOSIT, AccountType::EXPENSE, AccountType::ASSET):
// deposits with an expense account as source instead of a revenue account.
// find revenue account.
$this->factory->setUser($journal->user);
$result = $this->factory->findOrCreate($source->account->name, AccountType::REVENUE);
$oldSource = $dest->account;
$source->account()->associate($result);
$source->save();
$this->info(
sprintf(
'Transaction journal #%d, source account changed from #%d ("%s") to #%d ("%s").', $journal->id,
$oldSource->id, $oldSource->name,
$result->id, $result->name
)
);
$this->inspectJournal($journal);
break;
default:
$this->info(sprintf('The source account of %s #%d cannot be of type "%s".', $type, $journal->id, $source->account->accountType->type));
$this->info(sprintf('The destination account of %s #%d cannot be of type "%s".', $type, $journal->id, $dest->account->accountType->type));
break;
}
}
/**
* @param TransactionJournal $journal
*
@@ -201,7 +219,7 @@ class FixAccountTypes extends Command
{
$count = $journal->transactions()->count();
if (2 !== $count) {
$this->info(sprintf('Cannot inspect transaction journal #%d because it has %d transactions instead of 2.', $journal->id, $count));
$this->info(sprintf('Cannot inspect transaction journal #%d because it has %d transaction(s) instead of 2.', $journal->id, $count));
return;
}
@@ -213,9 +231,11 @@ class FixAccountTypes extends Command
$destAccount = $destTransaction->account;
$destAccountType = $destAccount->accountType->type;
if (!isset($this->expected[$type])) {
// @codeCoverageIgnoreStart
$this->info(sprintf('No source/destination info for transaction type %s.', $type));
return;
// @codeCoverageIgnoreEnd
}
if (!isset($this->expected[$type][$sourceAccountType])) {
$this->fixJournal($journal, $type, $sourceTransaction, $destTransaction);

View File

@@ -46,6 +46,9 @@ class FixPiggies extends Command
*/
protected $signature = 'firefly-iii:fix-piggies';
/** @var int */
private $count;
/**
* Execute the console command.
*
@@ -53,29 +56,43 @@ class FixPiggies extends Command
*/
public function handle(): int
{
$start = microtime(true);
$set = PiggyBankEvent::with(['PiggyBank', 'TransactionJournal', 'TransactionJournal.TransactionType'])->get();
$set->each(
function (PiggyBankEvent $event) {
if (null === $event->transaction_journal_id) {
return true;
}
/** @var TransactionJournal $journal */
$journal = $event->transactionJournal()->first();
if (null === $journal) {
return true;
}
$this->count = 0;
$start = microtime(true);
$set = PiggyBankEvent::with(['PiggyBank', 'TransactionJournal', 'TransactionJournal.TransactionType'])->get();
$type = $journal->transactionType->type;
if (TransactionType::TRANSFER !== $type) {
$event->transaction_journal_id = null;
$event->save();
$this->line(sprintf('Piggy bank #%d was referenced by an invalid event. This has been fixed.', $event->piggy_bank_id));
}
/** @var PiggyBankEvent $event */
foreach ($set as $event) {
return true;
if (null === $event->transaction_journal_id) {
continue;
}
);
/** @var TransactionJournal $journal */
$journal = $event->transactionJournal;
// @codeCoverageIgnoreStart
if (null === $journal) {
$event->transaction_journal_id = null;
$event->save();
$this->count++;
continue;
}
// @codeCoverageIgnoreEnd
$type = $journal->transactionType->type;
if (TransactionType::TRANSFER !== $type) {
$event->transaction_journal_id = null;
$event->save();
$this->line(sprintf('Piggy bank #%d was referenced by an invalid event. This has been fixed.', $event->piggy_bank_id));
$this->count++;
continue;
}
}
if (0 === $this->count) {
$this->line('All piggy bank events are correct.');
}
if (0 !== $this->count) {
$this->line(sprintf('Fixed %d piggy bank event(s).', $this->count));
}
$end = round(microtime(true) - $start, 2);
$this->line(sprintf('Verified the content of %d piggy bank events in %s seconds.', $set->count(), $end));

View File

@@ -22,6 +22,7 @@
namespace FireflyIII\Console\Commands\Correction;
use DB;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Console\Command;
@@ -84,7 +85,7 @@ class FixUnevenAmount extends Command
// one of the transactions is bad.
$journal = TransactionJournal::find($param);
if (!$journal) {
return;
return; // @codeCoverageIgnore
}
/** @var Transaction $source */
$source = $journal->transactions()->where('amount', '<', 0)->first();
@@ -92,11 +93,11 @@ class FixUnevenAmount extends Command
// fix amount of destination:
/** @var Transaction $destination */
$destination = $journal->transactions()->where('amount', '>', 0)->first();
$destination = $journal->transactions()->where('amount', '>', 0)->first();
$destination->amount = $amount;
$destination->save();
$this->line(sprintf('Corrected amount in transaction journal #%d', $param));
$message = sprintf('Corrected amount in transaction journal #%d', $param);
$this->line($message);
}
}

View File

@@ -42,6 +42,9 @@ class RenameMetaFields extends Command
*/
protected $signature = 'firefly-iii:rename-meta-fields';
/** @var int */
private $count;
/**
* Execute the console command.
*
@@ -49,7 +52,8 @@ class RenameMetaFields extends Command
*/
public function handle(): int
{
$start = microtime(true);
$this->count = 0;
$start = microtime(true);
$changes = [
'original-source' => 'original_source',
@@ -67,6 +71,12 @@ class RenameMetaFields extends Command
foreach ($changes as $original => $update) {
$this->rename($original, $update);
}
if (0 === $this->count) {
$this->line('All meta fields are correct.');
}
if (0 !== $this->count) {
$this->line(sprintf('Renamed %d meta field(s).', $this->count));
}
$end = round(microtime(true) - $start, 2);
$this->info(sprintf('Renamed meta fields in %s seconds', $end));
@@ -80,8 +90,9 @@ class RenameMetaFields extends Command
*/
private function rename(string $original, string $update): void
{
DB::table('journal_meta')
->where('name', '=', $original)
->update(['name' => $update]);
$count = DB::table('journal_meta')
->where('name', '=', $original)
->update(['name' => $update]);
$this->count += $count;
}
}

View File

@@ -66,6 +66,9 @@ class TransferBudgets extends Command
if (0 === $count) {
$this->info('No invalid budget/journal entries.');
}
if(0 !== $count) {
$this->line(sprintf('Corrected %d invalid budget/journal entries (entry).', $count));
}
$end = round(microtime(true) - $start, 2);
$this->info(sprintf('Verified budget/journals in %s seconds.', $end));