Finish command tests

This commit is contained in:
James Cole 2019-06-13 15:48:35 +02:00
parent 6bcb2ec144
commit 6964424bdc
No known key found for this signature in database
GPG Key ID: C16961E655E74B5E
29 changed files with 783 additions and 531 deletions

View File

@ -69,7 +69,7 @@ class CorrectDatabase extends Command
'firefly-iii:delete-empty-journals', 'firefly-iii:delete-empty-journals',
'firefly-iii:delete-empty-groups', 'firefly-iii:delete-empty-groups',
'firefly-iii:fix-account-types', 'firefly-iii:fix-account-types',
'firefly-iii:rename-meta-fields' 'firefly-iii:rename-meta-fields',
]; ];
foreach ($commands as $command) { foreach ($commands as $command) {
$this->line(sprintf('Now executing %s', $command)); $this->line(sprintf('Now executing %s', $command));

View File

@ -58,7 +58,7 @@ class CreateAccessTokens extends Command
$start = microtime(true); $start = microtime(true);
$count = 0; $count = 0;
$users= $repository->all(); $users = $repository->all();
/** @var User $user */ /** @var User $user */
foreach ($users as $user) { foreach ($users as $user) {
$pref = app('preferences')->getForUser($user, 'access_token', null); $pref = app('preferences')->getForUser($user, 'access_token', null);

View File

@ -47,12 +47,12 @@ class DeleteEmptyGroups extends Command
/** /**
* Execute the console command. * Execute the console command.
* *
* @throws Exception;
* @return mixed * @return mixed
* @throws Exception;
*/ */
public function handle(): int public function handle(): int
{ {
$start = microtime(true); $start = microtime(true);
$groups = array_unique(TransactionJournal::get(['transaction_group_id'])->pluck('transaction_group_id')->toArray()); $groups = array_unique(TransactionJournal::get(['transaction_group_id'])->pluck('transaction_group_id')->toArray());
$count = TransactionGroup::whereNull('deleted_at')->whereNotIn('id', $groups)->count(); $count = TransactionGroup::whereNull('deleted_at')->whereNotIn('id', $groups)->count();
if (0 === $count) { if (0 === $count) {

View File

@ -22,10 +22,10 @@
namespace FireflyIII\Console\Commands\Correction; namespace FireflyIII\Console\Commands\Correction;
use DB; use DB;
use Exception;
use FireflyIII\Models\Transaction; use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use Exception;
use Log; use Log;
/** /**
@ -105,7 +105,7 @@ class DeleteEmptyJournals extends Command
try { try {
TransactionJournal::find((int)$row->transaction_journal_id)->delete(); TransactionJournal::find((int)$row->transaction_journal_id)->delete();
// @codeCoverageIgnoreStart // @codeCoverageIgnoreStart
} catch(Exception $e) { } catch (Exception $e) {
Log::info(sprintf('Could not delete journal: %s', $e->getMessage())); Log::info(sprintf('Could not delete journal: %s', $e->getMessage()));
} }
// @codeCoverageIgnoreEnd // @codeCoverageIgnoreEnd

View File

@ -21,11 +21,11 @@
namespace FireflyIII\Console\Commands\Correction; namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Models\TransactionJournal; use Exception;
use FireflyIII\Models\Transaction; use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Exception;
/** /**
* Class DeleteZeroAmount * Class DeleteZeroAmount
@ -52,8 +52,8 @@ class DeleteZeroAmount extends Command
public function handle(): int public function handle(): int
{ {
$start = microtime(true); $start = microtime(true);
$set = Transaction::where('amount', 0)->get(['transaction_journal_id'])->pluck('transaction_journal_id')->toArray(); $set = Transaction::where('amount', 0)->get(['transaction_journal_id'])->pluck('transaction_journal_id')->toArray();
$set = array_unique($set); $set = array_unique($set);
/** @var Collection $journals */ /** @var Collection $journals */
$journals = TransactionJournal::whereIn('id', $set)->get(); $journals = TransactionJournal::whereIn('id', $set)->get();
/** @var TransactionJournal $journal */ /** @var TransactionJournal $journal */
@ -74,6 +74,7 @@ class DeleteZeroAmount extends Command
$end = round(microtime(true) - $start, 2); $end = round(microtime(true) - $start, 2);
$this->info(sprintf('Verified zero-amount integrity in %s seconds', $end)); $this->info(sprintf('Verified zero-amount integrity in %s seconds', $end));
return 0; return 0;
} }
} }

View File

@ -55,15 +55,6 @@ class FixAccountTypes extends Command
/** @var int */ /** @var int */
private $count; private $count;
/**
* FixAccountTypes constructor.
*/
public function __construct()
{
parent::__construct();
$this->count = 0;
}
/** /**
* Execute the console command. * Execute the console command.
* *
@ -72,6 +63,7 @@ class FixAccountTypes extends Command
*/ */
public function handle(): int public function handle(): int
{ {
$this->stupidLaravel();
$start = microtime(true); $start = microtime(true);
$this->factory = app(AccountFactory::class); $this->factory = app(AccountFactory::class);
// some combinations can be fixed by this script: // some combinations can be fixed by this script:
@ -110,6 +102,18 @@ class FixAccountTypes extends Command
return 0; return 0;
} }
/**
* Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is
* executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should
* be called from the handle method instead of using the constructor to initialize the command.
*
* @codeCoverageIgnore
*/
private function stupidLaravel(): void
{
$this->count = 0;
}
/** /**
* @param TransactionJournal $journal * @param TransactionJournal $journal
* @param string $type * @param string $type

View File

@ -22,7 +22,6 @@
namespace FireflyIII\Console\Commands\Correction; namespace FireflyIII\Console\Commands\Correction;
use DB; use DB;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Transaction; use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use Illuminate\Console\Command; use Illuminate\Console\Command;
@ -93,7 +92,7 @@ class FixUnevenAmount extends Command
// fix amount of destination: // fix amount of destination:
/** @var Transaction $destination */ /** @var Transaction $destination */
$destination = $journal->transactions()->where('amount', '>', 0)->first(); $destination = $journal->transactions()->where('amount', '>', 0)->first();
$destination->amount = $amount; $destination->amount = $amount;
$destination->save(); $destination->save();

View File

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

View File

@ -67,22 +67,12 @@ class CreateCSVImport extends Command
/** @var ImportJob */ /** @var ImportJob */
private $importJob; private $importJob;
/**
* CreateCSVImport constructor.
*/
public function __construct()
{
parent::__construct();
$this->userRepository = app(UserRepositoryInterface::class);
$this->importRepository = app(ImportJobRepositoryInterface::class);
}
/** /**
* Run the command. * Run the command.
*/ */
public function handle(): int public function handle(): int
{ {
$this->stupidLaravel();
// @codeCoverageIgnoreStart // @codeCoverageIgnoreStart
if (!$this->verifyAccessToken()) { if (!$this->verifyAccessToken()) {
$this->errorLine('Invalid access token.'); $this->errorLine('Invalid access token.');
@ -156,6 +146,19 @@ class CreateCSVImport extends Command
return 0; return 0;
} }
/**
* Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is
* executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should
* be called from the handle method instead of using the constructor to initialize the command.
*
* @codeCoverageIgnore
*/
private function stupidLaravel(): void
{
$this->userRepository = app(UserRepositoryInterface::class);
$this->importRepository = app(ImportJobRepositoryInterface::class);
}
/** /**
* @param string $message * @param string $message
* @param array|null $data * @param array|null $data

View File

@ -124,7 +124,7 @@ class ReportEmptyObjects extends Command
/** @var stdClass $entry */ /** @var stdClass $entry */
foreach ($set as $entry) { foreach ($set as $entry) {
$line = sprintf( $line = sprintf(
'User #%d (%s) has budget #%d ("%s") which has no transaction journals.', 'User #%d (%s) has budget #%d ("%s") which has no transaction journals.',
$entry->user_id, $entry->user_id,
$entry->email, $entry->email,

View File

@ -24,9 +24,9 @@ declare(strict_types=1);
namespace FireflyIII\Console\Commands\Integrity; namespace FireflyIII\Console\Commands\Integrity;
use Artisan;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use Schema; use Schema;
use Artisan;
/** /**
* Class ReportIntegrity * Class ReportIntegrity

View File

@ -92,24 +92,6 @@ class ApplyRules extends Command
/** @var RuleGroupRepositoryInterface */ /** @var RuleGroupRepositoryInterface */
private $ruleGroupRepository; private $ruleGroupRepository;
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
$this->allRules = false;
$this->accounts = new Collection;
$this->ruleSelection = [];
$this->ruleGroupSelection = [];
$this->ruleRepository = app(RuleRepositoryInterface::class);
$this->ruleGroupRepository = app(RuleGroupRepositoryInterface::class);
$this->acceptedAccounts = [AccountType::DEFAULT, AccountType::DEBT, AccountType::ASSET, AccountType::LOAN, AccountType::MORTGAGE];
$this->groups = new Collection;
}
/** /**
* Execute the console command. * Execute the console command.
* *
@ -118,6 +100,7 @@ class ApplyRules extends Command
*/ */
public function handle(): int public function handle(): int
{ {
$this->stupidLaravel();
// @codeCoverageIgnoreStart // @codeCoverageIgnoreStart
if (!$this->verifyAccessToken()) { if (!$this->verifyAccessToken()) {
$this->error('Invalid access token.'); $this->error('Invalid access token.');
@ -183,6 +166,25 @@ class ApplyRules extends Command
return 0; return 0;
} }
/**
* Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is
* executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should
* be called from the handle method instead of using the constructor to initialize the command.
*
* @codeCoverageIgnore
*/
private function stupidLaravel(): void
{
$this->allRules = false;
$this->accounts = new Collection;
$this->ruleSelection = [];
$this->ruleGroupSelection = [];
$this->ruleRepository = app(RuleRepositoryInterface::class);
$this->ruleGroupRepository = app(RuleGroupRepositoryInterface::class);
$this->acceptedAccounts = [AccountType::DEFAULT, AccountType::DEBT, AccountType::ASSET, AccountType::LOAN, AccountType::MORTGAGE];
$this->groups = new Collection;
}
/** /**
* @return bool * @return bool
* @throws FireflyException * @throws FireflyException

View File

@ -57,17 +57,6 @@ class AccountCurrencies extends Command
/** @var int */ /** @var int */
private $count; private $count;
/**
* AccountCurrencies constructor.
*/
public function __construct()
{
parent::__construct();
$this->accountRepos = app(AccountRepositoryInterface::class);
$this->userRepos = app(UserRepositoryInterface::class);
$this->count = 0;
}
/** /**
* Each (asset) account must have a reference to a preferred currency. If the account does not have one, it's forced upon the account. * Each (asset) account must have a reference to a preferred currency. If the account does not have one, it's forced upon the account.
* *
@ -75,6 +64,7 @@ class AccountCurrencies extends Command
*/ */
public function handle(): int public function handle(): int
{ {
$this->stupidLaravel();
$start = microtime(true); $start = microtime(true);
if ($this->isExecuted() && true !== $this->option('force')) { if ($this->isExecuted() && true !== $this->option('force')) {
$this->warn('This command has already been executed.'); $this->warn('This command has already been executed.');
@ -98,6 +88,20 @@ class AccountCurrencies extends Command
return 0; return 0;
} }
/**
* Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is
* executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should
* be called from the handle method instead of using the constructor to initialize the command.
*
* @codeCoverageIgnore
*/
private function stupidLaravel(): void
{
$this->accountRepos = app(AccountRepositoryInterface::class);
$this->userRepos = app(UserRepositoryInterface::class);
$this->count = 0;
}
/** /**
* @return bool * @return bool
*/ */
@ -141,6 +145,7 @@ class AccountCurrencies extends Command
AccountMeta::create(['account_id' => $account->id, 'name' => 'currency_id', 'data' => $currency->id]); AccountMeta::create(['account_id' => $account->id, 'name' => 'currency_id', 'data' => $currency->id]);
$this->line(sprintf('Account #%d ("%s") now has a currency setting (%s).', $account->id, $account->name, $currency->code)); $this->line(sprintf('Account #%d ("%s") now has a currency setting (%s).', $account->id, $account->name, $currency->code));
$this->count++; $this->count++;
return; return;
} }

View File

@ -54,7 +54,7 @@ class BudgetLimitCurrency extends Command
*/ */
public function handle(): int public function handle(): int
{ {
$start = microtime(true); $start = microtime(true);
// @codeCoverageIgnoreStart // @codeCoverageIgnoreStart
if ($this->isExecuted() && true !== $this->option('force')) { if ($this->isExecuted() && true !== $this->option('force')) {
$this->warn('This command has already been executed.'); $this->warn('This command has already been executed.');

View File

@ -71,6 +71,7 @@ class CCLiabilities extends Command
$debtType = AccountType::where('type', AccountType::DEBT)->first(); $debtType = AccountType::where('type', AccountType::DEBT)->first();
if (null === $ccType || null === $debtType) { if (null === $ccType || null === $debtType) {
$this->info('No incorrectly stored credit card liabilities.'); $this->info('No incorrectly stored credit card liabilities.');
return 0; return 0;
} }
/** @var Collection $accounts */ /** @var Collection $accounts */

View File

@ -95,7 +95,7 @@ class MigrateAttachments extends Command
$this->line('All attachments are OK.'); $this->line('All attachments are OK.');
} }
if (0 !== $count) { if (0 !== $count) {
$this->line(sprintf('Updated %d attachment(s).',$count)); $this->line(sprintf('Updated %d attachment(s).', $count));
} }
$end = round(microtime(true) - $start, 2); $end = round(microtime(true) - $start, 2);
$this->info(sprintf('Migrated attachment notes in %s seconds.', $end)); $this->info(sprintf('Migrated attachment notes in %s seconds.', $end));

View File

@ -62,20 +62,6 @@ class MigrateToGroups extends Command
private $service; private $service;
private $count; private $count;
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
$this->count = 0;
$this->journalRepository = app(JournalRepositoryInterface::class);
$this->service = app(JournalDestroyService::class);
$this->groupFactory = app(TransactionGroupFactory::class);
}
/** /**
* Execute the console command. * Execute the console command.
* *
@ -84,6 +70,7 @@ class MigrateToGroups extends Command
*/ */
public function handle(): int public function handle(): int
{ {
$this->stupidLaravel();
$start = microtime(true); $start = microtime(true);
// @codeCoverageIgnoreStart // @codeCoverageIgnoreStart
if ($this->isMigrated() && true !== $this->option('force')) { if ($this->isMigrated() && true !== $this->option('force')) {
@ -122,6 +109,21 @@ class MigrateToGroups extends Command
return 0; return 0;
} }
/**
* Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is
* executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should
* be called from the handle method instead of using the constructor to initialize the command.
*
* @codeCoverageIgnore
*/
private function stupidLaravel(): void
{
$this->count = 0;
$this->journalRepository = app(JournalRepositoryInterface::class);
$this->service = app(JournalDestroyService::class);
$this->groupFactory = app(TransactionGroupFactory::class);
}
/** /**
* @param TransactionJournal $journal * @param TransactionJournal $journal
* @param Transaction $transaction * @param Transaction $transaction

View File

@ -64,19 +64,6 @@ class MigrateToRules extends Command
private $ruleRepository; private $ruleRepository;
private $count; private $count;
/**
* MigrateToRules constructor.
*/
public function __construct()
{
parent::__construct();
$this->count = 0;
$this->userRepository = app(UserRepositoryInterface::class);
$this->ruleGroupRepository = app(RuleGroupRepositoryInterface::class);
$this->billRepository = app(BillRepositoryInterface::class);
$this->ruleRepository = app(RuleRepositoryInterface::class);
}
/** /**
* Execute the console command. * Execute the console command.
* *
@ -85,6 +72,7 @@ class MigrateToRules extends Command
*/ */
public function handle(): int public function handle(): int
{ {
$this->stupidLaravel();
$start = microtime(true); $start = microtime(true);
// @codeCoverageIgnoreStart // @codeCoverageIgnoreStart
@ -115,6 +103,22 @@ class MigrateToRules extends Command
return 0; return 0;
} }
/**
* Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is
* executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should
* be called from the handle method instead of using the constructor to initialize the command.
*
* @codeCoverageIgnore
*/
private function stupidLaravel(): void
{
$this->count = 0;
$this->userRepository = app(UserRepositoryInterface::class);
$this->ruleGroupRepository = app(RuleGroupRepositoryInterface::class);
$this->billRepository = app(BillRepositoryInterface::class);
$this->ruleRepository = app(RuleRepositoryInterface::class);
}
/** /**
* @return bool * @return bool
*/ */

View File

@ -64,19 +64,6 @@ class OtherCurrenciesCorrections extends Command
/** @var int */ /** @var int */
private $count; private $count;
/**
* JournalCurrencies constructor.
*/
public function __construct()
{
parent::__construct();
$this->count = 0;
$this->accountCurrencies = [];
$this->accountRepos = app(AccountRepositoryInterface::class);
$this->currencyRepos = app(CurrencyRepositoryInterface::class);
$this->journalRepos = app(JournalRepositoryInterface::class);
}
/** /**
* Execute the console command. * Execute the console command.
* *
@ -84,6 +71,7 @@ class OtherCurrenciesCorrections extends Command
*/ */
public function handle(): int public function handle(): int
{ {
$this->stupidLaravel();
$start = microtime(true); $start = microtime(true);
// @codeCoverageIgnoreStart // @codeCoverageIgnoreStart
if ($this->isExecuted() && true !== $this->option('force')) { if ($this->isExecuted() && true !== $this->option('force')) {
@ -103,6 +91,22 @@ class OtherCurrenciesCorrections extends Command
return 0; return 0;
} }
/**
* Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is
* executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should
* be called from the handle method instead of using the constructor to initialize the command.
*
* @codeCoverageIgnore
*/
private function stupidLaravel(): void
{
$this->count = 0;
$this->accountCurrencies = [];
$this->accountRepos = app(AccountRepositoryInterface::class);
$this->currencyRepos = app(CurrencyRepositoryInterface::class);
$this->journalRepos = app(JournalRepositoryInterface::class);
}
/** /**
* @param Account $account * @param Account $account
* *

View File

@ -54,13 +54,6 @@ class TransactionIdentifier extends Command
/** @var int */ /** @var int */
private $count; private $count;
public function __construct()
{
parent::__construct();
$this->journalRepository = app(JournalRepositoryInterface::class);
$this->count = 0;
}
/** /**
* This method gives all transactions which are part of a split journal (so more than 2) a sort of "order" so they are easier * This method gives all transactions which are part of a split journal (so more than 2) a sort of "order" so they are easier
* to easier to match to their counterpart. When a journal is split, it has two or three transactions: -3, -4 and -5 for example. * to easier to match to their counterpart. When a journal is split, it has two or three transactions: -3, -4 and -5 for example.
@ -74,6 +67,7 @@ class TransactionIdentifier extends Command
*/ */
public function handle(): int public function handle(): int
{ {
$this->stupidLaravel();
$start = microtime(true); $start = microtime(true);
// @codeCoverageIgnoreStart // @codeCoverageIgnoreStart
if ($this->isExecuted() && true !== $this->option('force')) { if ($this->isExecuted() && true !== $this->option('force')) {
@ -107,6 +101,19 @@ class TransactionIdentifier extends Command
return 0; return 0;
} }
/**
* Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is
* executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should
* be called from the handle method instead of using the constructor to initialize the command.
*
* @codeCoverageIgnore
*/
private function stupidLaravel(): void
{
$this->journalRepository = app(JournalRepositoryInterface::class);
$this->count = 0;
}
/** /**
* @return bool * @return bool
*/ */
@ -184,6 +191,7 @@ class TransactionIdentifier extends Command
return null; return null;
} }
// @codeCoverageIgnoreEnd // @codeCoverageIgnoreEnd
return $opposing; return $opposing;

View File

@ -76,21 +76,6 @@ class TransferCurrenciesCorrections extends Command
/** @var TransactionCurrency The currency preference of the destination account of the current journal. */ /** @var TransactionCurrency The currency preference of the destination account of the current journal. */
private $destinationCurrency; private $destinationCurrency;
/**
* JournalCurrencies constructor.
*/
public function __construct()
{
parent::__construct();
$this->count = 0;
$this->accountRepos = app(AccountRepositoryInterface::class);
$this->currencyRepos = app(CurrencyRepositoryInterface::class);
$this->journalRepos = app(JournalRepositoryInterface::class);
$this->accountCurrencies = [];
$this->resetInformation();
}
/** /**
* Execute the console command. * Execute the console command.
* *
@ -98,6 +83,7 @@ class TransferCurrenciesCorrections extends Command
*/ */
public function handle(): int public function handle(): int
{ {
$this->stupidLaravel();
$start = microtime(true); $start = microtime(true);
// @codeCoverageIgnoreStart // @codeCoverageIgnoreStart
if ($this->isExecuted() && true !== $this->option('force')) { if ($this->isExecuted() && true !== $this->option('force')) {
@ -111,10 +97,14 @@ class TransferCurrenciesCorrections extends Command
$this->markAsExecuted(); $this->markAsExecuted();
if (0 === $this->count) { if (0 === $this->count) {
$this->line('All transfers have correct currency information.'); $message = 'All transfers have correct currency information.';
$this->line($message);
Log::debug($message);
} }
if (0 !== $this->count) { if (0 !== $this->count) {
$this->line(sprintf('Verified currency information of %d transfer(s).', $this->count)); $message = sprintf('Verified currency information of %d transfer(s).', $this->count);
$this->line($message);
Log::debug($message);
} }
$end = round(microtime(true) - $start, 2); $end = round(microtime(true) - $start, 2);
$this->info(sprintf('Verified and fixed currency information for transfers in %s seconds.', $end)); $this->info(sprintf('Verified and fixed currency information for transfers in %s seconds.', $end));
@ -122,6 +112,23 @@ class TransferCurrenciesCorrections extends Command
return 0; return 0;
} }
/**
* Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is
* executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should
* be called from the handle method instead of using the constructor to initialize the command.
*
* @codeCoverageIgnore
*/
private function stupidLaravel(): void
{
$this->count = 0;
$this->accountRepos = app(AccountRepositoryInterface::class);
$this->currencyRepos = app(CurrencyRepositoryInterface::class);
$this->journalRepos = app(JournalRepositoryInterface::class);
$this->accountCurrencies = [];
$this->resetInformation();
}
/** /**
* @param Account $account * @param Account $account
* *
@ -131,17 +138,19 @@ class TransferCurrenciesCorrections extends Command
{ {
$accountId = $account->id; $accountId = $account->id;
if (isset($this->accountCurrencies[$accountId]) && 0 === $this->accountCurrencies[$accountId]) { if (isset($this->accountCurrencies[$accountId]) && 0 === $this->accountCurrencies[$accountId]) {
return null; return null; // @codeCoverageIgnore
} }
if (isset($this->accountCurrencies[$accountId]) && $this->accountCurrencies[$accountId] instanceof TransactionCurrency) { if (isset($this->accountCurrencies[$accountId]) && $this->accountCurrencies[$accountId] instanceof TransactionCurrency) {
return $this->accountCurrencies[$accountId]; return $this->accountCurrencies[$accountId]; // @codeCoverageIgnore
} }
$currencyId = (int)$this->accountRepos->getMetaValue($account, 'currency_id'); $currencyId = (int)$this->accountRepos->getMetaValue($account, 'currency_id');
$result = $this->currencyRepos->findNull($currencyId); $result = $this->currencyRepos->findNull($currencyId);
if (null === $result) { if (null === $result) {
// @codeCoverageIgnoreStart
$this->accountCurrencies[$accountId] = 0; $this->accountCurrencies[$accountId] = 0;
return null; return null;
// @codeCoverageIgnoreEnd
} }
$this->accountCurrencies[$accountId] = $result; $this->accountCurrencies[$accountId] = $result;
@ -154,20 +163,22 @@ class TransferCurrenciesCorrections extends Command
* @param TransactionJournal $transfer * @param TransactionJournal $transfer
* *
* @return Transaction|null * @return Transaction|null
* @codeCoverageIgnore
*/ */
private function getDestinationTransaction(TransactionJournal $transfer): ?Transaction private function getDestinationTransaction(TransactionJournal $transfer): ?Transaction
{ {
return $transfer->transactions->firstWhere('amount', '>', 0); return $transfer->transactions()->where('amount', '>', 0)->first();
} }
/** /**
* @param TransactionJournal $transfer * @param TransactionJournal $transfer
* *
* @return Transaction|null * @return Transaction|null
* @codeCoverageIgnore
*/ */
private function getSourceTransaction(TransactionJournal $transfer): ?Transaction private function getSourceTransaction(TransactionJournal $transfer): ?Transaction
{ {
return $transfer->transactions->firstWhere('amount', '<', 0); return $transfer->transactions()->where('amount', '<', 0)->first();
} }
/** /**
@ -198,19 +209,19 @@ class TransferCurrenciesCorrections extends Command
*/ */
private function fixTransactionJournalCurrency(TransactionJournal $journal): void private function fixTransactionJournalCurrency(TransactionJournal $journal): void
{ {
if ($journal->transaction_currency_id !== $this->sourceCurrency->id) { if ((int)$journal->transaction_currency_id !== (int)$this->sourceCurrency->id) {
$oldCurrencyCode = $journal->transactionCurrency->code ?? '(nothing)'; $oldCurrencyCode = $journal->transactionCurrency->code ?? '(nothing)';
$journal->transaction_currency_id = $this->sourceCurrency->id; $journal->transaction_currency_id = $this->sourceCurrency->id;
$this->count++; $message = sprintf(
$this->line( 'Transfer #%d ("%s") has been updated to use %s instead of %s.',
sprintf( $journal->id,
'Transfer #%d ("%s") has been updated to use %s instead of %s.', $journal->description,
$journal->id, $this->sourceCurrency->code,
$journal->description, $oldCurrencyCode
$this->sourceCurrency->code,
$oldCurrencyCode
)
); );
$this->count++;
$this->line($message);
Log::debug($message);
$journal->save(); $journal->save();
} }
} }
@ -235,7 +246,8 @@ class TransferCurrenciesCorrections extends Command
} }
/** /**
* Reset all the class fields for the current transfer * Reset all the class fields for the current transfer.
* @codeCoverageIgnore
*/ */
private function resetInformation(): void private function resetInformation(): void
{ {
@ -249,7 +261,9 @@ class TransferCurrenciesCorrections extends Command
/** /**
* Extract source transaction, source account + source account currency from the journal. * Extract source transaction, source account + source account currency from the journal.
*
* @param TransactionJournal $journal * @param TransactionJournal $journal
* @codeCoverageIgnore
*/ */
private function getSourceInformation(TransactionJournal $journal): void private function getSourceInformation(TransactionJournal $journal): void
{ {
@ -260,7 +274,9 @@ class TransferCurrenciesCorrections extends Command
/** /**
* Extract destination transaction, destination account + destination account currency from the journal. * Extract destination transaction, destination account + destination account currency from the journal.
*
* @param TransactionJournal $journal * @param TransactionJournal $journal
* @codeCoverageIgnore
*/ */
private function getDestinationInformation(TransactionJournal $journal): void private function getDestinationInformation(TransactionJournal $journal): void
{ {
@ -276,26 +292,37 @@ class TransferCurrenciesCorrections extends Command
*/ */
private function updateTransferCurrency(TransactionJournal $transfer): void private function updateTransferCurrency(TransactionJournal $transfer): void
{ {
$this->resetInformation(); $this->resetInformation();
// @codeCoverageIgnoreStart
if ($this->isSplitJournal($transfer)) { if ($this->isSplitJournal($transfer)) {
$this->line(sprintf(sprintf('Transaction journal #%d is a split journal. Cannot continue.', $transfer->id))); $this->line(sprintf(sprintf('Transaction journal #%d is a split journal. Cannot continue.', $transfer->id)));
return;
} }
// @codeCoverageIgnoreEnd
$this->getSourceInformation($transfer); $this->getSourceInformation($transfer);
$this->getDestinationInformation($transfer); $this->getDestinationInformation($transfer);
// unexpectedly, either one is null: // unexpectedly, either one is null:
// @codeCoverageIgnoreStart
if ($this->isEmptyTransactions()) { if ($this->isEmptyTransactions()) {
$this->error(sprintf('Source or destination information for transaction journal #%d is null. Cannot fix this one.', $transfer->id)); $this->error(sprintf('Source or destination information for transaction journal #%d is null. Cannot fix this one.', $transfer->id));
return; return;
} }
// @codeCoverageIgnoreEnd
// both accounts must have currency preference: // both accounts must have currency preference:
// @codeCoverageIgnoreStart
if ($this->isNoCurrencyPresent()) { if ($this->isNoCurrencyPresent()) {
return; return;
} }
// @codeCoverageIgnoreEnd
// fix source transaction having no currency. // fix source transaction having no currency.
$this->fixSourceNoCurrency(); $this->fixSourceNoCurrency();
@ -311,16 +338,17 @@ class TransferCurrenciesCorrections extends Command
// remove foreign currency information if not necessary. // remove foreign currency information if not necessary.
$this->fixInvalidForeignCurrency(); $this->fixInvalidForeignCurrency();
// correct foreign currency info if necessary. // correct foreign currency info if necessary.
$this->fixMismatchedForeignCurrency(); $this->fixMismatchedForeignCurrency();
// restore missing foreign currency amount. // restore missing foreign currency amount.
$this->fixSourceNullForeignAmount(); $this->fixSourceNullForeignAmount();
$this->fixDestNullForeignAmount(); $this->fixDestNullForeignAmount();
// fix journal itself: // fix journal itself:
$this->fixTransactionJournalCurrency($transfer); $this->fixTransactionJournalCurrency($transfer);
} }
/** /**
@ -416,6 +444,7 @@ class TransferCurrenciesCorrections extends Command
* *
* @param TransactionJournal $transfer * @param TransactionJournal $transfer
* @return bool * @return bool
* @codeCoverageIgnore
*/ */
private function isSplitJournal(TransactionJournal $transfer): bool private function isSplitJournal(TransactionJournal $transfer): bool
{ {
@ -425,6 +454,7 @@ class TransferCurrenciesCorrections extends Command
/** /**
* Is either the source or destination transaction NULL? * Is either the source or destination transaction NULL?
* @return bool * @return bool
* @codeCoverageIgnore
*/ */
private function isEmptyTransactions(): bool private function isEmptyTransactions(): bool
{ {
@ -436,6 +466,7 @@ class TransferCurrenciesCorrections extends Command
* If the destination account currency is the same as the source currency, * If the destination account currency is the same as the source currency,
* both foreign_amount and foreign_currency_id fields must be NULL * both foreign_amount and foreign_currency_id fields must be NULL
* for both transactions (because foreign currency info would not make sense) * for both transactions (because foreign currency info would not make sense)
*
*/ */
private function fixInvalidForeignCurrency(): void private function fixInvalidForeignCurrency(): void
{ {
@ -459,21 +490,21 @@ class TransferCurrenciesCorrections extends Command
$this->sourceTransaction->id, $this->destinationTransaction->id, $this->sourceCurrency->code $this->sourceTransaction->id, $this->destinationTransaction->id, $this->sourceCurrency->code
) )
); );
$this->count++;
return;
} }
} }
/** /**
* If destination account currency is different from source account currency, then * If destination account currency is different from source account currency,
* both transactions must have each others currency as foreign currency id. * then both transactions must get the source account's currency as normal currency
* and the opposing account's currency as foreign currency.
*/ */
private function fixMismatchedForeignCurrency(): void private function fixMismatchedForeignCurrency(): void
{ {
if ((int)$this->sourceCurrency->id !== (int)$this->destinationCurrency->id) { if ((int)$this->sourceCurrency->id !== (int)$this->destinationCurrency->id) {
$this->sourceTransaction->foreign_currency_id = $this->destinationCurrency->id; $this->sourceTransaction->transaction_currency_id = $this->sourceCurrency->id;
$this->destinationTransaction->foreign_currency_id = $this->sourceCurrency->id; $this->sourceTransaction->foreign_currency_id = $this->destinationCurrency->id;
$this->destinationTransaction->transaction_currency_id = $this->sourceCurrency->id;
$this->destinationTransaction->foreign_currency_id = $this->destinationCurrency->id;
$this->sourceTransaction->save(); $this->sourceTransaction->save();
$this->destinationTransaction->save(); $this->destinationTransaction->save();
@ -514,6 +545,7 @@ class TransferCurrenciesCorrections extends Command
/** /**
* @return bool * @return bool
* @codeCoverageIgnore
*/ */
private function isNoCurrencyPresent(): bool private function isNoCurrencyPresent(): bool
{ {
@ -523,7 +555,7 @@ class TransferCurrenciesCorrections extends Command
Log::error($message); Log::error($message);
$this->error($message); $this->error($message);
return false; return true;
} }
// destination account must have a currency preference. // destination account must have a currency preference.
@ -533,10 +565,10 @@ class TransferCurrenciesCorrections extends Command
Log::error($message); Log::error($message);
$this->error($message); $this->error($message);
return false; return true;
} }
return true; return false;
} }
} }

View File

@ -45,16 +45,6 @@ class UpgradeDatabase extends Command
*/ */
protected $signature = 'firefly-iii:upgrade-database {--F|force : Force all upgrades.}'; protected $signature = 'firefly-iii:upgrade-database {--F|force : Force all upgrades.}';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/** /**
* Execute the console command. * Execute the console command.
* *

View File

@ -41,8 +41,6 @@ declare(strict_types=1);
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>. * along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/ */
use Illuminate\Foundation\Inspiring;
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Console Routes | Console Routes
@ -53,9 +51,3 @@ use Illuminate\Foundation\Inspiring;
| simple approach to interacting with each command's IO methods. | simple approach to interacting with each command's IO methods.
| |
*/ */
Artisan::command(
'inspire', function () {
$this->comment(Inspiring::quote());
}
)->describe('Display an inspiring quote');

View File

@ -28,6 +28,7 @@ use FireflyIII\Helpers\Collector\TransactionCollectorInterface;
use FireflyIII\Models\Preference; use FireflyIII\Models\Preference;
use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\Transformers\CurrencyTransformer; use FireflyIII\Transformers\CurrencyTransformer;
use Laravel\Passport\Passport; use Laravel\Passport\Passport;
use Log; use Log;
@ -64,6 +65,7 @@ class CurrencyControllerTest extends TestCase
$currency = TransactionCurrency::first(); $currency = TransactionCurrency::first();
$repository = $this->mock(CurrencyRepositoryInterface::class); $repository = $this->mock(CurrencyRepositoryInterface::class);
$transformer = $this->mock(CurrencyTransformer::class); $transformer = $this->mock(CurrencyTransformer::class);
$userRepository = $this->mock(UserRepositoryInterface::class);
// mock transformer // mock transformer
$transformer->shouldReceive('setParameters')->withAnyArgs()->atLeast()->once(); $transformer->shouldReceive('setParameters')->withAnyArgs()->atLeast()->once();
@ -103,6 +105,7 @@ class CurrencyControllerTest extends TestCase
$currency = TransactionCurrency::first(); $currency = TransactionCurrency::first();
$repository = $this->mock(CurrencyRepositoryInterface::class); $repository = $this->mock(CurrencyRepositoryInterface::class);
$transformer = $this->mock(CurrencyTransformer::class); $transformer = $this->mock(CurrencyTransformer::class);
$userRepository = $this->mock(UserRepositoryInterface::class);
// mock transformer // mock transformer
$transformer->shouldReceive('setParameters')->withAnyArgs()->atLeast()->once(); $transformer->shouldReceive('setParameters')->withAnyArgs()->atLeast()->once();
@ -148,6 +151,7 @@ class CurrencyControllerTest extends TestCase
$currency = TransactionCurrency::first(); $currency = TransactionCurrency::first();
$repository = $this->mock(CurrencyRepositoryInterface::class); $repository = $this->mock(CurrencyRepositoryInterface::class);
$transformer = $this->mock(CurrencyTransformer::class); $transformer = $this->mock(CurrencyTransformer::class);
$this->mock(UserRepositoryInterface::class);
// mock transformer // mock transformer
$transformer->shouldReceive('setParameters')->withAnyArgs()->atLeast()->once(); $transformer->shouldReceive('setParameters')->withAnyArgs()->atLeast()->once();
@ -187,6 +191,7 @@ class CurrencyControllerTest extends TestCase
$currency = TransactionCurrency::first(); $currency = TransactionCurrency::first();
$repository = $this->mock(CurrencyRepositoryInterface::class); $repository = $this->mock(CurrencyRepositoryInterface::class);
$transformer = $this->mock(CurrencyTransformer::class); $transformer = $this->mock(CurrencyTransformer::class);
$this->mock(UserRepositoryInterface::class);
$preference = new Preference; $preference = new Preference;
$preference->data = 'EUR'; $preference->data = 'EUR';

View File

@ -181,6 +181,7 @@ class LinkTypeControllerTest extends TestCase
{ {
// mock stuff: // mock stuff:
$repository = $this->mock(LinkTypeRepositoryInterface::class); $repository = $this->mock(LinkTypeRepositoryInterface::class);
$userRepository = $this->mock(UserRepositoryInterface::class);
// create editable link type: // create editable link type:
$linkType = LinkType::create( $linkType = LinkType::create(

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace Tests\Api\V1\Controllers; namespace Tests\Api\V1\Controllers;
use FireflyIII\Models\Preference; use FireflyIII\Models\Preference;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Transformers\PreferenceTransformer; use FireflyIII\Transformers\PreferenceTransformer;
use Laravel\Passport\Passport; use Laravel\Passport\Passport;
use Log; use Log;
@ -56,6 +57,7 @@ class PreferencesControllerTest extends TestCase
public function testUpdateArray(): void public function testUpdateArray(): void
{ {
$transformer = $this->mock(PreferenceTransformer::class); $transformer = $this->mock(PreferenceTransformer::class);
$accountRepos = $this->mock(AccountRepositoryInterface::class);
// mock calls to transformer: // mock calls to transformer:
$transformer->shouldReceive('setParameters')->withAnyArgs()->atLeast()->once(); $transformer->shouldReceive('setParameters')->withAnyArgs()->atLeast()->once();
@ -63,6 +65,7 @@ class PreferencesControllerTest extends TestCase
$transformer->shouldReceive('getDefaultIncludes')->withAnyArgs()->atLeast()->once()->andReturn([]); $transformer->shouldReceive('getDefaultIncludes')->withAnyArgs()->atLeast()->once()->andReturn([]);
$transformer->shouldReceive('getAvailableIncludes')->withAnyArgs()->atLeast()->once()->andReturn([]); $transformer->shouldReceive('getAvailableIncludes')->withAnyArgs()->atLeast()->once()->andReturn([]);
$transformer->shouldReceive('transform')->atLeast()->once()->andReturn(['id' => 5]); $transformer->shouldReceive('transform')->atLeast()->once()->andReturn(['id' => 5]);
$accountRepos->shouldReceive('setUser')->atLeast()->once();
/** @var Preference $preference */ /** @var Preference $preference */
$preference = Preferences::setForUser($this->user(), 'frontPageAccounts', [1, 2, 3]); $preference = Preferences::setForUser($this->user(), 'frontPageAccounts', [1, 2, 3]);
@ -78,6 +81,7 @@ class PreferencesControllerTest extends TestCase
public function testUpdateBoolean(): void public function testUpdateBoolean(): void
{ {
$transformer = $this->mock(PreferenceTransformer::class); $transformer = $this->mock(PreferenceTransformer::class);
$accountRepos = $this->mock(AccountRepositoryInterface::class);
// mock calls to transformer: // mock calls to transformer:
$transformer->shouldReceive('setParameters')->withAnyArgs()->atLeast()->once(); $transformer->shouldReceive('setParameters')->withAnyArgs()->atLeast()->once();
@ -85,6 +89,7 @@ class PreferencesControllerTest extends TestCase
$transformer->shouldReceive('getDefaultIncludes')->withAnyArgs()->atLeast()->once()->andReturn([]); $transformer->shouldReceive('getDefaultIncludes')->withAnyArgs()->atLeast()->once()->andReturn([]);
$transformer->shouldReceive('getAvailableIncludes')->withAnyArgs()->atLeast()->once()->andReturn([]); $transformer->shouldReceive('getAvailableIncludes')->withAnyArgs()->atLeast()->once()->andReturn([]);
$transformer->shouldReceive('transform')->atLeast()->once()->andReturn(['id' => 5]); $transformer->shouldReceive('transform')->atLeast()->once()->andReturn(['id' => 5]);
$accountRepos->shouldReceive('setUser')->atLeast()->once();
/** @var Preference $preference */ /** @var Preference $preference */
$preference = Preferences::setForUser($this->user(), 'twoFactorAuthEnabled', false); $preference = Preferences::setForUser($this->user(), 'twoFactorAuthEnabled', false);
@ -101,6 +106,7 @@ class PreferencesControllerTest extends TestCase
public function testUpdateDefault(): void public function testUpdateDefault(): void
{ {
$transformer = $this->mock(PreferenceTransformer::class); $transformer = $this->mock(PreferenceTransformer::class);
$accountRepos = $this->mock(AccountRepositoryInterface::class);
// mock calls to transformer: // mock calls to transformer:
$transformer->shouldReceive('setParameters')->withAnyArgs()->atLeast()->once(); $transformer->shouldReceive('setParameters')->withAnyArgs()->atLeast()->once();
@ -108,6 +114,7 @@ class PreferencesControllerTest extends TestCase
$transformer->shouldReceive('getDefaultIncludes')->withAnyArgs()->atLeast()->once()->andReturn([]); $transformer->shouldReceive('getDefaultIncludes')->withAnyArgs()->atLeast()->once()->andReturn([]);
$transformer->shouldReceive('getAvailableIncludes')->withAnyArgs()->atLeast()->once()->andReturn([]); $transformer->shouldReceive('getAvailableIncludes')->withAnyArgs()->atLeast()->once()->andReturn([]);
$transformer->shouldReceive('transform')->atLeast()->once()->andReturn(['id' => 5]); $transformer->shouldReceive('transform')->atLeast()->once()->andReturn(['id' => 5]);
$accountRepos->shouldReceive('setUser')->atLeast()->once();
/** @var Preference $preference */ /** @var Preference $preference */
$preference = Preferences::setForUser($this->user(), 'currencyPreference', false); $preference = Preferences::setForUser($this->user(), 'currencyPreference', false);
@ -123,6 +130,7 @@ class PreferencesControllerTest extends TestCase
public function testUpdateInteger(): void public function testUpdateInteger(): void
{ {
$transformer = $this->mock(PreferenceTransformer::class); $transformer = $this->mock(PreferenceTransformer::class);
$accountRepos = $this->mock(AccountRepositoryInterface::class);
// mock calls to transformer: // mock calls to transformer:
$transformer->shouldReceive('setParameters')->withAnyArgs()->atLeast()->once(); $transformer->shouldReceive('setParameters')->withAnyArgs()->atLeast()->once();
@ -130,6 +138,7 @@ class PreferencesControllerTest extends TestCase
$transformer->shouldReceive('getDefaultIncludes')->withAnyArgs()->atLeast()->once()->andReturn([]); $transformer->shouldReceive('getDefaultIncludes')->withAnyArgs()->atLeast()->once()->andReturn([]);
$transformer->shouldReceive('getAvailableIncludes')->withAnyArgs()->atLeast()->once()->andReturn([]); $transformer->shouldReceive('getAvailableIncludes')->withAnyArgs()->atLeast()->once()->andReturn([]);
$transformer->shouldReceive('transform')->atLeast()->once()->andReturn(['id' => 5]); $transformer->shouldReceive('transform')->atLeast()->once()->andReturn(['id' => 5]);
$accountRepos->shouldReceive('setUser')->atLeast()->once();
/** @var Preference $preference */ /** @var Preference $preference */
$preference = Preferences::setForUser($this->user(), 'listPageSize', 13); $preference = Preferences::setForUser($this->user(), 'listPageSize', 13);

View File

@ -157,7 +157,8 @@ abstract class TestCase extends BaseTestCase
return $this->getRandomAccount(AccountType::INITIAL_BALANCE, null); return $this->getRandomAccount(AccountType::INITIAL_BALANCE, null);
} }
public function getRandomReconciliation(): Account { public function getRandomReconciliation(): Account
{
return $this->getRandomAccount(AccountType::RECONCILIATION, null); return $this->getRandomAccount(AccountType::RECONCILIATION, null);
} }
@ -233,6 +234,14 @@ abstract class TestCase extends BaseTestCase
return TransactionCurrency::find(1); return TransactionCurrency::find(1);
} }
/**
* @return TransactionCurrency
*/
protected function getDollar(): TransactionCurrency
{
return TransactionCurrency::where('code', 'USD')->first();
}
/** /**
* @return TransactionGroup * @return TransactionGroup
*/ */
@ -257,7 +266,7 @@ abstract class TestCase extends BaseTestCase
if (in_array($class, $deprecated, true)) { if (in_array($class, $deprecated, true)) {
throw new RuntimeException(strtoupper('Must not be mocking the transaction collector or transformer.')); throw new RuntimeException(strtoupper('Must not be mocking the transaction collector or transformer.'));
} }
Log::debug(sprintf('Will now mock %s', $class)); //Log::debug(sprintf('Will now mock %s', $class));
$object = Mockery::mock($class); $object = Mockery::mock($class);
$this->app->instance($class, $object); $this->app->instance($class, $object);
@ -345,7 +354,7 @@ abstract class TestCase extends BaseTestCase
DB::raw('COUNT(transaction_journal_id) as ct'), DB::raw('COUNT(transaction_journal_id) as ct'),
] ]
)->first(); )->first();
if(null === $result) { if (null === $result) {
throw new FireflyException(sprintf('Cannot find suitable %s to use.', $type)); throw new FireflyException(sprintf('Cannot find suitable %s to use.', $type));
} }

View File

@ -1,354 +0,0 @@
<?php
/**
* JournalCurrenciesTest.php
* Copyright (c) 2019 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Tests\Unit\Console\Commands\Upgrade;
use FireflyConfig;
use FireflyIII\Models\Account;
use FireflyIII\Models\Configuration;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use Illuminate\Support\Collection;
use Log;
use Mockery;
use Tests\TestCase;
/**
* Class JournalCurrenciesTest
*/
class JournalCurrenciesTest extends TestCase
{
/**
*
*/
public function setUp(): void
{
parent::setUp();
Log::info(sprintf('Now in %s.', get_class($this)));
}
//
// /**
// * Basic run. Would not change anything.
// *
// * @covers \FireflyIII\Console\Commands\Upgrade\JournalCurrencies
// */
// public function testHandle(): void
// {
// // mock classes
// $accountRepos = $this->mock(AccountRepositoryInterface::class);
// $currencyRepos = $this->mock(CurrencyRepositoryInterface::class);
// $journalRepos = $this->mock(JournalRepositoryInterface::class);
// $euro = TransactionCurrency::find(1);
//
// // update transfer if necessary for the test:
// $false = new Configuration;
// $false->data = false;
// FireflyConfig::shouldReceive('get')->withArgs(['4780_journal_currencies', false])->andReturn($false);
// FireflyConfig::shouldReceive('set')->withArgs(['4780_journal_currencies', true]);
//
// // mock stuff
// $journalRepos->shouldReceive('getAllJournals')->atLeast()->once()
// ->withArgs([[TransactionType::TRANSFER]])
// ->andReturn(new Collection);
//
// // for the "other journals" check, return nothing.
// $journalRepos->shouldReceive('getAllJournals')->atLeast()->once()
// ->withArgs([[TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::OPENING_BALANCE, TransactionType::RECONCILIATION,]])
// ->andReturn(new Collection);
//
// // transaction would be verified, nothing more.
// $this->artisan('firefly-iii:journal-currencies')
// ->expectsOutput('All transactions are correct.')
// ->assertExitCode(0);
// // nothing changed, so no verification.
//
// }
//
// /**
// * Submit a single transfer which has no issues.
// *
// * @covers \FireflyIII\Console\Commands\Upgrade\JournalCurrencies
// */
// public function testHandleTransfer(): void
// {
// // mock classes
// $accountRepos = $this->mock(AccountRepositoryInterface::class);
// $currencyRepos = $this->mock(CurrencyRepositoryInterface::class);
// $journalRepos = $this->mock(JournalRepositoryInterface::class);
// $euro = TransactionCurrency::find(1);
// $transfer = $this->getRandomTransfer();
//
// // update transfer if necessary for the test:
// $collection = new Collection([$transfer]);
// $false = new Configuration;
// $false->data = false;
// FireflyConfig::shouldReceive('get')->withArgs(['4780_journal_currencies', false])->andReturn($false);
// FireflyConfig::shouldReceive('set')->withArgs(['4780_journal_currencies', true]);
//
// // mock stuff
// $accountRepos->shouldReceive('setUser')->atLeast()->once();
// $journalRepos->shouldReceive('setUser')->atLeast()->once();
// $currencyRepos->shouldReceive('setUser')->atLeast()->once();
//
// // return single tranfer
// $journalRepos->shouldReceive('getAllJournals')->atLeast()->once()
// ->withArgs([[TransactionType::TRANSFER]])
// ->andReturn($collection);
//
// // for the "other journals" check, return nothing.
// $journalRepos->shouldReceive('getAllJournals')->atLeast()->once()
// ->withArgs([[TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::OPENING_BALANCE, TransactionType::RECONCILIATION,]])
// ->andReturn(new Collection);
//
// $accountRepos->shouldReceive('getMetaValue')->atLeast()->once()->withArgs([Mockery::any(), 'currency_id'])->andReturn($euro->id);
// $currencyRepos->shouldReceive('findNull')->atLeast()->once()->andReturn($euro);
//
// // transaction would be verified, nothing more.
// $this->artisan('firefly-iii:journal-currencies')
// ->expectsOutput('Verified 1 transaction(s) and journal(s).')
// ->assertExitCode(0);
// // nothing changed, so no verification.
// }
//
// /**
// * Submit a single transfer where the source account has no currency preference.
// *
// * @covers \FireflyIII\Console\Commands\Upgrade\JournalCurrencies
// */
// public function testHandleTransferSourceNoPref(): void
// {
// // mock classes
// $accountRepos = $this->mock(AccountRepositoryInterface::class);
// $currencyRepos = $this->mock(CurrencyRepositoryInterface::class);
// $journalRepos = $this->mock(JournalRepositoryInterface::class);
// $euro = TransactionCurrency::find(1);
// $transfer = $this->getRandomTransfer();
//
// // edit source to remove currency preference:
// /** @var Account $source */
// $source = $transfer->transactions()->where('amount', '<', 0)->first()->account;
//// AccountMeta::where('account_id', $source->id)->where('name', 'currency_id')->delete();
//
// // update transfer if necessary for the test:
// $collection = new Collection([$transfer]);
// $false = new Configuration;
// $false->data = false;
// FireflyConfig::shouldReceive('get')->withArgs(['4780_journal_currencies', false])->andReturn($false);
// FireflyConfig::shouldReceive('set')->withArgs(['4780_journal_currencies', true]);
//
// // mock stuff
// $accountRepos->shouldReceive('setUser')->atLeast()->once();
// $journalRepos->shouldReceive('setUser')->atLeast()->once();
// $currencyRepos->shouldReceive('setUser')->atLeast()->once();
//
// // return single transfer
// $journalRepos->shouldReceive('getAllJournals')->atLeast()->once()
// ->withArgs([[TransactionType::TRANSFER]])
// ->andReturn($collection);
//
// // for the "other journals" check, return nothing.
// $journalRepos->shouldReceive('getAllJournals')->atLeast()->once()
// ->withArgs([[TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::OPENING_BALANCE, TransactionType::RECONCILIATION,]])
// ->andReturn(new Collection);
//
// // return NULL for first currency ID and currency.
// $accountRepos->shouldReceive('getMetaValue')->atLeast()->once()->withArgs([Mockery::any(), 'currency_id'])->andReturnNull();
// $currencyRepos->shouldReceive('findNull')->atLeast()->once()->andReturnNull();
//
// // transaction would be verified, nothing more.
// $this->artisan('firefly-iii:journal-currencies')
// ->expectsOutput(sprintf('Account #%d ("%s") must have currency preference but has none.', $source->id, $source->name))
// ->assertExitCode(0);
// // nothing changed, so no verification.
//
// }
//
// /**
// * Submit a single transfer where the source transaction has no currency set.
// * Because this is not done over repositories, we must edit the DB.
// *
// * @covers \FireflyIII\Console\Commands\Upgrade\JournalCurrencies
// */
// public function testHandleTransferSourceNoCurrency(): void
// {
// // mock classes
// $accountRepos = $this->mock(AccountRepositoryInterface::class);
// $currencyRepos = $this->mock(CurrencyRepositoryInterface::class);
// $journalRepos = $this->mock(JournalRepositoryInterface::class);
// $euro = TransactionCurrency::find(1);
// $transfer = $this->getRandomTransfer();
// /** @var Transaction $source */
// $source = $transfer->transactions()->where('amount', '<', 0)->first();
// $source->transaction_currency_id = null;
// $source->save();
//
// // update transfer if necessary for the test:
// $collection = new Collection([$transfer]);
// $false = new Configuration;
// $false->data = false;
// FireflyConfig::shouldReceive('get')->withArgs(['4780_journal_currencies', false])->andReturn($false);
// FireflyConfig::shouldReceive('set')->withArgs(['4780_journal_currencies', true]);
//
// // mock stuff
// $accountRepos->shouldReceive('setUser')->atLeast()->once();
// $journalRepos->shouldReceive('setUser')->atLeast()->once();
// $currencyRepos->shouldReceive('setUser')->atLeast()->once();
//
// // return single tranfer
// $journalRepos->shouldReceive('getAllJournals')->atLeast()->once()
// ->withArgs([[TransactionType::TRANSFER]])
// ->andReturn($collection);
//
// // for the "other journals" check, return nothing.
// $journalRepos->shouldReceive('getAllJournals')->atLeast()->once()
// ->withArgs([[TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::OPENING_BALANCE, TransactionType::RECONCILIATION,]])
// ->andReturn(new Collection);
//
// $accountRepos->shouldReceive('getMetaValue')->atLeast()->once()->withArgs([Mockery::any(), 'currency_id'])->andReturn($euro->id);
// $currencyRepos->shouldReceive('findNull')->atLeast()->once()->andReturn($euro);
//
// // transaction would be verified, nothing more.
// $this->artisan('firefly-iii:journal-currencies')
// ->expectsOutput(sprintf('Transaction #%d has no currency setting, now set to %s.', $source->id, $euro->code))
// ->expectsOutput('Verified 2 transaction(s) and journal(s).')
// ->assertExitCode(0);
//
// // check transaction
// $this->assertCount(1, Transaction::where('id', $source->id)->where('transaction_currency_id', $euro->id)->get());
// }
//
// /**
// * Submit a single transfer where the source transaction has a different currency than the source account does.
// *
// * @covers \FireflyIII\Console\Commands\Upgrade\JournalCurrencies
// */
// public function testHandleMismatchedTransfer(): void
// {
// // mock classes
// $accountRepos = $this->mock(AccountRepositoryInterface::class);
// $currencyRepos = $this->mock(CurrencyRepositoryInterface::class);
// $journalRepos = $this->mock(JournalRepositoryInterface::class);
// $euro = TransactionCurrency::find(1);
// $usd = TransactionCurrency::where('code', 'USD')->first();
// $transfer = $this->getRandomTransfer();
//
// /** @var Transaction $source */
// $source = $transfer->transactions()->where('amount', '<', 0)->first();
// $source->transaction_currency_id = $usd->id;
// $source->save();
//
// // update transfer if necessary for the test:
// $collection = new Collection([$transfer]);
// $false = new Configuration;
// $false->data = false;
// FireflyConfig::shouldReceive('get')->withArgs(['4780_journal_currencies', false])->andReturn($false);
// FireflyConfig::shouldReceive('set')->withArgs(['4780_journal_currencies', true]);
//
// // mock stuff
// $accountRepos->shouldReceive('setUser')->atLeast()->once();
// $journalRepos->shouldReceive('setUser')->atLeast()->once();
// $currencyRepos->shouldReceive('setUser')->atLeast()->once();
//
// // return single tranfer
// $journalRepos->shouldReceive('getAllJournals')->atLeast()->once()
// ->withArgs([[TransactionType::TRANSFER]])
// ->andReturn($collection);
//
// // for the "other journals" check, return nothing.
// $journalRepos->shouldReceive('getAllJournals')->atLeast()->once()
// ->withArgs([[TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::OPENING_BALANCE, TransactionType::RECONCILIATION,]])
// ->andReturn(new Collection);
//
// $accountRepos->shouldReceive('getMetaValue')->atLeast()->once()->withArgs([Mockery::any(), 'currency_id'])->andReturn($euro->id);
// $currencyRepos->shouldReceive('findNull')->atLeast()->once()->andReturn($euro);
//
// // transaction would be verified, nothing more.
// $this->artisan('firefly-iii:journal-currencies')
// ->expectsOutput(
// sprintf(
// 'Transaction #%d has a currency setting #%d that should be #%d. Amount remains %s, currency is changed.',
// $source->id,
// $source->transaction_currency_id,
// $euro->id,
// $source->amount
// )
// )
// ->expectsOutput('Verified 2 transaction(s) and journal(s).')
// ->assertExitCode(0);
// // nothing changed, so no verification.
// }
//
// /**
// * Submit a single transfer where the destination account has no currency preference.
// *
// * @covers \FireflyIII\Console\Commands\Upgrade\JournalCurrencies
// */
// public function testHandleTransferNoDestinationCurrency(): void
// {
// // mock classes
// $accountRepos = $this->mock(AccountRepositoryInterface::class);
// $currencyRepos = $this->mock(CurrencyRepositoryInterface::class);
// $journalRepos = $this->mock(JournalRepositoryInterface::class);
// $euro = TransactionCurrency::find(1);
// $transfer = $this->getRandomTransfer();
//
// /** @var Account $destination */
// $destination = $transfer->transactions()->where('amount', '>', 0)->first()->account;
//
// // update transfer if necessary for the test:
// $collection = new Collection([$transfer]);
// $false = new Configuration;
// $false->data = false;
// FireflyConfig::shouldReceive('get')->withArgs(['4780_journal_currencies', false])->andReturn($false);
// FireflyConfig::shouldReceive('set')->withArgs(['4780_journal_currencies', true]);
//
// // mock stuff
// $accountRepos->shouldReceive('setUser')->atLeast()->once();
// $journalRepos->shouldReceive('setUser')->atLeast()->once();
// $currencyRepos->shouldReceive('setUser')->atLeast()->once();
//
// // return single tranfer
// $journalRepos->shouldReceive('getAllJournals')->atLeast()->once()
// ->withArgs([[TransactionType::TRANSFER]])
// ->andReturn($collection);
//
// // for the "other journals" check, return nothing.
// $journalRepos->shouldReceive('getAllJournals')->atLeast()->once()
// ->withArgs([[TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::OPENING_BALANCE, TransactionType::RECONCILIATION,]])
// ->andReturn(new Collection);
//
// $accountRepos->shouldReceive('getMetaValue')->atLeast()->once()->withArgs([Mockery::any(), 'currency_id'])->andReturn($euro->id, 0);
// $currencyRepos->shouldReceive('findNull')->atLeast()->once()->andReturn($euro, null);
//
// // transaction would be verified, nothing more.
// $this->artisan('firefly-iii:journal-currencies')
// ->expectsOutput(sprintf('Account #%d ("%s") must have currency preference but has none.', $destination->id, $destination->name))
// ->assertExitCode(0);
// // nothing changed, so no verification.
// }
}

View File

@ -0,0 +1,535 @@
<?php
/**
* TransferCurrenciesCorrectionsTest.php
* Copyright (c) 2019 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Tests\Unit\Console\Commands\Upgrade;
use FireflyConfig;
use FireflyIII\Models\Configuration;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use Illuminate\Support\Collection;
use Log;
use Mockery;
use Tests\TestCase;
/**
* Class TransferCurrenciesCorrectionsTest
*/
class TransferCurrenciesCorrectionsTest extends TestCase
{
/**
*
*/
public function setUp(): void
{
parent::setUp();
Log::info(sprintf('Now in %s.', get_class($this)));
}
/**
* Basic test. Assume nothing is wrong.
*
* @covers \FireflyIII\Console\Commands\Upgrade\TransferCurrenciesCorrections
*/
public function testHandle(): void
{
$accountRepos = $this->mock(AccountRepositoryInterface::class);
$currencyRepos = $this->mock(CurrencyRepositoryInterface::class);
$journalRepos = $this->mock(JournalRepositoryInterface::class);
// mock calls:
$journalRepos->shouldReceive('getAllJournals')
->withArgs([[TransactionType::TRANSFER]])
->atLeast()->once()->andReturn(new Collection);
// configuration
$false = new Configuration;
$false->data = false;
FireflyConfig::shouldReceive('get')->withArgs(['4780_transfer_currencies', false])->andReturn($false);
FireflyConfig::shouldReceive('set')->withArgs(['4780_transfer_currencies', true]);
// assume all is well.
$this->artisan('firefly-iii:transfer-currencies')
->expectsOutput('All transfers have correct currency information.')
->assertExitCode(0);
}
/**
* Basic test. Assume the transfer is OK.
*
* @covers \FireflyIII\Console\Commands\Upgrade\TransferCurrenciesCorrections
*/
public function testHandleCorrectTransfer(): void
{
$accountRepos = $this->mock(AccountRepositoryInterface::class);
$currencyRepos = $this->mock(CurrencyRepositoryInterface::class);
$journalRepos = $this->mock(JournalRepositoryInterface::class);
$transfer = $this->getRandomTransfer();
$euro = $this->getEuro();
// mock calls:
$journalRepos->shouldReceive('getAllJournals')
->withArgs([[TransactionType::TRANSFER]])
->atLeast()->once()->andReturn(new Collection([$transfer]));
// account repos
$accountRepos->shouldReceive('getMetaValue')
->atLeast()->once()
->withArgs([Mockery::any(), 'currency_id'])->andReturn('1');
// currency repos
$currencyRepos->shouldReceive('findNull')
->atLeast()->once()
->withArgs([1])->andReturn($euro);
// configuration
$false = new Configuration;
$false->data = false;
FireflyConfig::shouldReceive('get')->withArgs(['4780_transfer_currencies', false])->andReturn($false);
FireflyConfig::shouldReceive('set')->withArgs(['4780_transfer_currencies', true]);
// assume all is well.
$this->artisan('firefly-iii:transfer-currencies')
->expectsOutput('All transfers have correct currency information.')
->assertExitCode(0);
}
/**
* Journal has bad currency info.
*
* @covers \FireflyIII\Console\Commands\Upgrade\TransferCurrenciesCorrections
*/
public function testHandleInvalidJournalCurrency(): void
{
$accountRepos = $this->mock(AccountRepositoryInterface::class);
$currencyRepos = $this->mock(CurrencyRepositoryInterface::class);
$journalRepos = $this->mock(JournalRepositoryInterface::class);
$transfer = $this->getRandomTransfer();
$euro = $this->getEuro();
$dollar = $this->getDollar();
$transfer->transaction_currency_id = $dollar->id;
$transfer->save();
// mock calls:
$journalRepos->shouldReceive('getAllJournals')
->withArgs([[TransactionType::TRANSFER]])
->atLeast()->once()->andReturn(new Collection([$transfer]));
// account repos
$accountRepos->shouldReceive('getMetaValue')
->atLeast()->once()
->withArgs([Mockery::any(), 'currency_id'])->andReturn('1');
// currency repos
$currencyRepos->shouldReceive('findNull')
->atLeast()->once()
->withArgs([1])->andReturn($euro);
// configuration
$false = new Configuration;
$false->data = false;
FireflyConfig::shouldReceive('get')->withArgs(['4780_transfer_currencies', false])->andReturn($false);
FireflyConfig::shouldReceive('set')->withArgs(['4780_transfer_currencies', true]);
$this->artisan('firefly-iii:transfer-currencies')
->expectsOutput('Verified currency information of 1 transfer(s).')
->assertExitCode(0);
$this->assertCount(1, TransactionJournal::where('id', $transfer->id)->where('transaction_currency_id', 1)->get());
}
/**
* Missing source foreign amount information.
*
* @covers \FireflyIII\Console\Commands\Upgrade\TransferCurrenciesCorrections
*/
public function testHandleMissingSourceForeignAmount(): void
{
$accountRepos = $this->mock(AccountRepositoryInterface::class);
$currencyRepos = $this->mock(CurrencyRepositoryInterface::class);
$journalRepos = $this->mock(JournalRepositoryInterface::class);
$transfer = $this->getRandomTransfer();
$euro = $this->getEuro();
$dollar = $this->getDollar();
/** @var Transaction $destination */
$destination = $transfer->transactions()->where('amount', '>', 0)->first();
$destination->foreign_amount = '100';
$destination->save();
/** @var Transaction $destination */
$source = $transfer->transactions()->where('amount', '<', 0)->first();
// mock calls:
$journalRepos->shouldReceive('getAllJournals')
->withArgs([[TransactionType::TRANSFER]])
->atLeast()->once()->andReturn(new Collection([$transfer]));
// account repos
$accountRepos->shouldReceive('getMetaValue')
->atLeast()->once()
->withArgs([Mockery::any(), 'currency_id'])->andReturn('1', $dollar->id);
// currency repos
$currencyRepos->shouldReceive('findNull')
->atLeast()->once()
->withArgs([1])->andReturn($euro);
$currencyRepos->shouldReceive('findNull')
->atLeast()->once()
->withArgs([$dollar->id])->andReturn($dollar);
// configuration
$false = new Configuration;
$false->data = false;
FireflyConfig::shouldReceive('get')->withArgs(['4780_transfer_currencies', false])->andReturn($false);
FireflyConfig::shouldReceive('set')->withArgs(['4780_transfer_currencies', true]);
$this->artisan('firefly-iii:transfer-currencies')
->expectsOutput('Verified currency information of 2 transfer(s).')
->assertExitCode(0);
$this->assertCount(1, Transaction::where('id', $source->id)
->where('foreign_amount', '-100')->get()
);
}
/**
* Missing source foreign amount information.
*
* @covers \FireflyIII\Console\Commands\Upgrade\TransferCurrenciesCorrections
*/
public function testHandleMissingDestForeignAmount(): void
{
$accountRepos = $this->mock(AccountRepositoryInterface::class);
$currencyRepos = $this->mock(CurrencyRepositoryInterface::class);
$journalRepos = $this->mock(JournalRepositoryInterface::class);
$transfer = $this->getRandomTransfer();
$euro = $this->getEuro();
$dollar = $this->getDollar();
/** @var Transaction $destination */
$destination = $transfer->transactions()->where('amount', '>', 0)->first();
$destination->foreign_amount = null;
$destination->save();
/** @var Transaction $destination */
$source = $transfer->transactions()->where('amount', '<', 0)->first();
$source->foreign_amount = '-100';
$source->save();
// mock calls:
$journalRepos->shouldReceive('getAllJournals')
->withArgs([[TransactionType::TRANSFER]])
->atLeast()->once()->andReturn(new Collection([$transfer]));
// account repos
$accountRepos->shouldReceive('getMetaValue')
->atLeast()->once()
->withArgs([Mockery::any(), 'currency_id'])->andReturn('1', $dollar->id);
// currency repos
$currencyRepos->shouldReceive('findNull')
->atLeast()->once()
->withArgs([1])->andReturn($euro);
$currencyRepos->shouldReceive('findNull')
->atLeast()->once()
->withArgs([$dollar->id])->andReturn($dollar);
// configuration
$false = new Configuration;
$false->data = false;
FireflyConfig::shouldReceive('get')->withArgs(['4780_transfer_currencies', false])->andReturn($false);
FireflyConfig::shouldReceive('set')->withArgs(['4780_transfer_currencies', true]);
$this->artisan('firefly-iii:transfer-currencies')
->expectsOutput('Verified currency information of 3 transfer(s).')
->assertExitCode(0);
$this->assertCount(1, Transaction::where('id', $destination->id)
->where('foreign_amount', '100')->get()
);
}
/**
* Basic test. The foreign currency is broken and should be corrected.
*
* @covers \FireflyIII\Console\Commands\Upgrade\TransferCurrenciesCorrections
*/
public function testHandleMismatchedForeignCurrency(): void
{
$accountRepos = $this->mock(AccountRepositoryInterface::class);
$currencyRepos = $this->mock(CurrencyRepositoryInterface::class);
$journalRepos = $this->mock(JournalRepositoryInterface::class);
$transfer = $this->getRandomTransfer();
$euro = $this->getEuro();
$dollar = $this->getDollar();
$source = $transfer->transactions()->where('amount', '<', 0)->first();
// mock calls:
$journalRepos->shouldReceive('getAllJournals')
->withArgs([[TransactionType::TRANSFER]])
->atLeast()->once()->andReturn(new Collection([$transfer]));
// account repos
$accountRepos->shouldReceive('getMetaValue')
->atLeast()->once()
->withArgs([Mockery::any(), 'currency_id'])->andReturn('1', $dollar->id);
// currency repos
$currencyRepos->shouldReceive('findNull')
->atLeast()->once()
->withArgs([1])->andReturn($euro);
$currencyRepos->shouldReceive('findNull')
->atLeast()->once()
->withArgs([$dollar->id])->andReturn($dollar);
// configuration
$false = new Configuration;
$false->data = false;
FireflyConfig::shouldReceive('get')->withArgs(['4780_transfer_currencies', false])->andReturn($false);
FireflyConfig::shouldReceive('set')->withArgs(['4780_transfer_currencies', true]);
$this->artisan('firefly-iii:transfer-currencies')
->expectsOutput('Verified currency information of 2 transfer(s).')
->assertExitCode(0);
// source and destination transaction should be corrected:
$this->assertCount(1, Transaction::where('id', $source->id)
->where('transaction_currency_id', $euro->id)
->where('foreign_currency_id', $dollar->id)
->get());
}
/**
* Basic test. Source transaction has no currency.
*
* @covers \FireflyIII\Console\Commands\Upgrade\TransferCurrenciesCorrections
*/
public function testHandleTransferNoSourceCurrency(): void
{
$accountRepos = $this->mock(AccountRepositoryInterface::class);
$currencyRepos = $this->mock(CurrencyRepositoryInterface::class);
$journalRepos = $this->mock(JournalRepositoryInterface::class);
$transfer = $this->getRandomTransfer();
$euro = $this->getEuro();
// get source transaction and remove currency:
/** @var Transaction $source */
$source = $transfer->transactions()->where('amount', '<', 0)->first();
$source->transaction_currency_id = null;
$source->save();
// mock calls:
$journalRepos->shouldReceive('getAllJournals')
->withArgs([[TransactionType::TRANSFER]])
->atLeast()->once()->andReturn(new Collection([$transfer]));
// account repos
$accountRepos->shouldReceive('getMetaValue')
->atLeast()->once()
->withArgs([Mockery::any(), 'currency_id'])->andReturn('1');
// currency repos
$currencyRepos->shouldReceive('findNull')
->atLeast()->once()
->withArgs([1])->andReturn($euro);
// configuration
$false = new Configuration;
$false->data = false;
FireflyConfig::shouldReceive('get')->withArgs(['4780_transfer_currencies', false])->andReturn($false);
FireflyConfig::shouldReceive('set')->withArgs(['4780_transfer_currencies', true]);
$this->artisan('firefly-iii:transfer-currencies')
->expectsOutput('Verified currency information of 1 transfer(s).')
->assertExitCode(0);
// assume problem is fixed:
$this->assertCount(1, Transaction::where('id', $source->id)->where('transaction_currency_id', 1)->get());
}
/**
* Basic test. Destination transaction has no currency.
*
* @covers \FireflyIII\Console\Commands\Upgrade\TransferCurrenciesCorrections
*/
public function testHandleTransferNoDestCurrency(): void
{
$accountRepos = $this->mock(AccountRepositoryInterface::class);
$currencyRepos = $this->mock(CurrencyRepositoryInterface::class);
$journalRepos = $this->mock(JournalRepositoryInterface::class);
$transfer = $this->getRandomTransfer();
$euro = $this->getEuro();
// get source transaction and remove currency:
/** @var Transaction $destination */
$destination = $transfer->transactions()->where('amount', '>', 0)->first();
$destination->transaction_currency_id = null;
$destination->save();
// mock calls:
$journalRepos->shouldReceive('getAllJournals')
->withArgs([[TransactionType::TRANSFER]])
->atLeast()->once()->andReturn(new Collection([$transfer]));
// account repos
$accountRepos->shouldReceive('getMetaValue')
->atLeast()->once()
->withArgs([Mockery::any(), 'currency_id'])->andReturn('1');
// currency repos
$currencyRepos->shouldReceive('findNull')
->atLeast()->once()
->withArgs([1])->andReturn($euro);
// configuration
$false = new Configuration;
$false->data = false;
FireflyConfig::shouldReceive('get')->withArgs(['4780_transfer_currencies', false])->andReturn($false);
FireflyConfig::shouldReceive('set')->withArgs(['4780_transfer_currencies', true]);
$this->artisan('firefly-iii:transfer-currencies')
->expectsOutput('Verified currency information of 1 transfer(s).')
->assertExitCode(0);
// assume problem is fixed:
$this->assertCount(1, Transaction::where('id', $destination->id)->where('transaction_currency_id', 1)->get());
}
/**
* Basic test. Source transaction has bad currency.
*
* @covers \FireflyIII\Console\Commands\Upgrade\TransferCurrenciesCorrections
*/
public function testHandleTransferBadSourceCurrency(): void
{
$accountRepos = $this->mock(AccountRepositoryInterface::class);
$currencyRepos = $this->mock(CurrencyRepositoryInterface::class);
$journalRepos = $this->mock(JournalRepositoryInterface::class);
$transfer = $this->getRandomTransfer();
$euro = $this->getEuro();
// get source transaction and remove currency:
/** @var Transaction $source */
$source = $transfer->transactions()->where('amount', '<', 0)->first();
$source->transaction_currency_id = 2;
$source->save();
// mock calls:
$journalRepos->shouldReceive('getAllJournals')
->withArgs([[TransactionType::TRANSFER]])
->atLeast()->once()->andReturn(new Collection([$transfer]));
// account repos
$accountRepos->shouldReceive('getMetaValue')
->atLeast()->once()
->withArgs([Mockery::any(), 'currency_id'])->andReturn('1');
// currency repos
$currencyRepos->shouldReceive('findNull')
->atLeast()->once()
->withArgs([1])->andReturn($euro);
// configuration
$false = new Configuration;
$false->data = false;
FireflyConfig::shouldReceive('get')->withArgs(['4780_transfer_currencies', false])->andReturn($false);
FireflyConfig::shouldReceive('set')->withArgs(['4780_transfer_currencies', true]);
$this->artisan('firefly-iii:transfer-currencies')
->expectsOutput('Verified currency information of 1 transfer(s).')
->assertExitCode(0);
// assume problem is fixed:
$this->assertCount(1, Transaction::where('id', $source->id)->where('transaction_currency_id', 1)->get());
}
/**
* Basic test. Source transaction has bad currency.
*
* @covers \FireflyIII\Console\Commands\Upgrade\TransferCurrenciesCorrections
*/
public function testHandleTransferBadDestCurrency(): void
{
$accountRepos = $this->mock(AccountRepositoryInterface::class);
$currencyRepos = $this->mock(CurrencyRepositoryInterface::class);
$journalRepos = $this->mock(JournalRepositoryInterface::class);
$transfer = $this->getRandomTransfer();
$euro = $this->getEuro();
// get destination transaction and remove currency:
/** @var Transaction $destination */
$destination = $transfer->transactions()->where('amount', '>', 0)->first();
$destination->transaction_currency_id = 2;
$destination->save();
// mock calls:
$journalRepos->shouldReceive('getAllJournals')
->withArgs([[TransactionType::TRANSFER]])
->atLeast()->once()->andReturn(new Collection([$transfer]));
// account repos
$accountRepos->shouldReceive('getMetaValue')
->atLeast()->once()
->withArgs([Mockery::any(), 'currency_id'])->andReturn('1');
// currency repos
$currencyRepos->shouldReceive('findNull')
->atLeast()->once()
->withArgs([1])->andReturn($euro);
// configuration
$false = new Configuration;
$false->data = false;
FireflyConfig::shouldReceive('get')->withArgs(['4780_transfer_currencies', false])->andReturn($false);
FireflyConfig::shouldReceive('set')->withArgs(['4780_transfer_currencies', true]);
$this->artisan('firefly-iii:transfer-currencies')
->expectsOutput('Verified currency information of 1 transfer(s).')
->assertExitCode(0);
// assume problem is fixed:
$this->assertCount(1, Transaction::where('id', $destination->id)->where('transaction_currency_id', 1)->get());
}
}