diff --git a/app/Console/Commands/Correction/CorrectOpeningBalanceCurrencies.php b/app/Console/Commands/Correction/CorrectOpeningBalanceCurrencies.php index d0556c7080..29cdbdf516 100644 --- a/app/Console/Commands/Correction/CorrectOpeningBalanceCurrencies.php +++ b/app/Console/Commands/Correction/CorrectOpeningBalanceCurrencies.php @@ -32,6 +32,7 @@ use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionType; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use Illuminate\Console\Command; +use JsonException; use Log; /** @@ -60,6 +61,7 @@ class CorrectOpeningBalanceCurrencies extends Command */ public function handle(): int { + Log::debug(sprintf('Now in %s', __METHOD__)); // get all OB journals: $set = TransactionJournal ::leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') @@ -70,16 +72,23 @@ class CorrectOpeningBalanceCurrencies extends Command $count = 0; /** @var TransactionJournal $journal */ foreach ($set as $journal) { + Log::debug(sprintf('Going to fix journal #%d', $journal->id)); $count += $this->correctJournal($journal); + Log::debug(sprintf('Done, count is now %d', $count)); } if ($count > 0) { - $this->line(sprintf('Corrected %d opening balance transactions.', $count)); + $message = sprintf('Corrected %d opening balance transaction(s).', $count); + Log::debug($message); + $this->line($message); } if (0 === $count) { - $this->info('There was nothing to fix in the opening balance transactions.'); + $message = 'There was nothing to fix in the opening balance transactions.'; + Log::debug($message); + $this->info($message); } + Log::debug(sprintf('Done with %s', __METHOD__)); return 0; } @@ -94,18 +103,18 @@ class CorrectOpeningBalanceCurrencies extends Command // get the asset account for this opening balance: $account = $this->getAccount($journal); if (null === $account) { - $this->warn(sprintf('Transaction journal #%d has no valid account. Cant fix this line.', $journal->id)); + $message = sprintf('Transaction journal #%d has no valid account. Cant fix this line.', $journal->id); + Log::warning($message); + $this->warn($message); return 0; } - Log::debug(sprintf('Found %s #%d "%s".', $account->accountType->type, $account->id, $account->name)); + Log::debug(sprintf('Found "%s" #%d "%s".', $account->accountType->type, $account->id, $account->name)); $currency = $this->getCurrency($account); Log::debug(sprintf('Found currency #%d (%s)', $currency->id, $currency->code)); // update journal and all transactions: - $this->setCurrency($journal, $currency); - - return 1; + return $this->setCurrency($journal, $currency); } /** @@ -115,22 +124,27 @@ class CorrectOpeningBalanceCurrencies extends Command */ private function getAccount(TransactionJournal $journal): ?Account { - $transactions = $journal->transactions()->with(['account', 'account.accountType'])->get(); + $transactions = $journal->transactions()->get(); + Log::debug(sprintf('Found %d transactions for journal #%d.', $transactions->count(), $journal->id)); /** @var Transaction $transaction */ foreach ($transactions as $transaction) { - $account = $transaction->account; - if ((null !== $account) && AccountType::INITIAL_BALANCE !== $account->accountType->type) { + Log::debug(sprintf('Testing transaction #%d', $transaction->id)); + /** @var Account $account */ + $account = $transaction->account()->first(); + if (null !== $account && AccountType::INITIAL_BALANCE !== $account->accountType()->first()->type) { + Log::debug(sprintf('Account of transaction #%d is opposite of IB account (%s).', $transaction->id, $account->accountType()->first()->type)); return $account; } } + Log::debug('Found no IB account in transactions of journal.'); return null; } /** * @param Account $account - * * @return TransactionCurrency + * @throws JsonException */ private function getCurrency(Account $account): TransactionCurrency { @@ -144,16 +158,30 @@ class CorrectOpeningBalanceCurrencies extends Command /** * @param TransactionJournal $journal * @param TransactionCurrency $currency + * @return int */ - private function setCurrency(TransactionJournal $journal, TransactionCurrency $currency): void + private function setCurrency(TransactionJournal $journal, TransactionCurrency $currency): int { - $journal->transaction_currency_id = $currency->id; - $journal->save(); + Log::debug('Now in setCurrency'); + $count = 0; + if ((int) $journal->transaction_currency_id !== (int) $currency->id) { + Log::debug(sprintf('Currency ID of journal #%d was #%d, now set to #%d', $journal->id, $journal->transaction_currency_id, $currency->id)); + $journal->transaction_currency_id = $currency->id; + $journal->save(); + $count = 1; + } /** @var Transaction $transaction */ foreach ($journal->transactions as $transaction) { - $transaction->transaction_currency_id = $currency->id; - $transaction->save(); + if ((int) $transaction->transaction_currency_id !== (int) $currency->id) { + Log::debug(sprintf('Currency ID of transaction #%d was #%d, now set to #%d', $transaction->id, $transaction->transaction_currency_id, $currency->id)); + $transaction->transaction_currency_id = $currency->id; + $transaction->save(); + $count = 1; + } } + Log::debug(sprintf('Return %d', $count)); + + return $count; } } diff --git a/app/Support/Amount.php b/app/Support/Amount.php index cb3769634d..744f6d4623 100644 --- a/app/Support/Amount.php +++ b/app/Support/Amount.php @@ -301,9 +301,6 @@ class Amount */ public function getDefaultCurrencyByUser(User $user): TransactionCurrency { - if ('testing' === config('app.env')) { - Log::warning(sprintf('%s should NOT be called in the TEST environment!', __METHOD__)); - } $cache = new CacheProperties; $cache->addProperty('getDefaultCurrency'); $cache->addProperty($user->id); @@ -314,7 +311,7 @@ class Amount $currencyPrefStr = $currencyPreference ? $currencyPreference->data : 'EUR'; // at this point the currency preference could be encrypted, if coming from an old version. - Log::debug('Going to try to decrypt users currency preference.'); + //Log::debug('Going to try to decrypt users currency preference.'); $currencyCode = $this->tryDecrypt((string) $currencyPrefStr); // could still be json encoded: @@ -354,7 +351,7 @@ class Amount try { $value = Crypt::decrypt($value); // verified } catch (DecryptException $e) { - Log::debug(sprintf('Could not decrypt "%s". %s', $value, $e->getMessage())); + //Log::debug(sprintf('Could not decrypt "%s". %s', $value, $e->getMessage())); } return $value; diff --git a/app/Support/Search/OperatorQuerySearch.php b/app/Support/Search/OperatorQuerySearch.php index 3f919b8f22..59cc2c7321 100644 --- a/app/Support/Search/OperatorQuerySearch.php +++ b/app/Support/Search/OperatorQuerySearch.php @@ -607,7 +607,7 @@ class OperatorQuerySearch implements SearchInterface $accounts = $this->accountRepository->searchAccount($value, $searchTypes, 25); if (0 === $accounts->count()) { Log::debug('Found zero accounts, search for invalid account.'); - $account = new Account; + $account = new Account; $account->id = 0; $this->collector->$collectorMethod(new Collection([$account])); @@ -620,7 +620,7 @@ class OperatorQuerySearch implements SearchInterface if (0 === $filtered->count()) { Log::debug('Left with zero accounts, search for invalid account.'); - $account = new Account; + $account = new Account; $account->id = 0; $this->collector->$collectorMethod(new Collection([$account])); return; @@ -669,7 +669,7 @@ class OperatorQuerySearch implements SearchInterface $accounts = $this->accountRepository->searchAccountNr($value, $searchTypes, 25); if (0 === $accounts->count()) { Log::debug('Found zero accounts, search for invalid account.'); - $account = new Account; + $account = new Account; $account->id = 0; $this->collector->$collectorMethod(new Collection([$account])); return; @@ -679,7 +679,7 @@ class OperatorQuerySearch implements SearchInterface Log::debug(sprintf('Found %d accounts, will filter.', $accounts->count())); $filtered = $accounts->filter(function (Account $account) use ($value, $stringMethod) { // either IBAN or account number! - $ibanMatch = $stringMethod(strtolower($account->iban), strtolower($value)); + $ibanMatch = $stringMethod(strtolower((string) $account->iban), strtolower((string) $value)); $accountNrMatch = false; /** @var AccountMeta $meta */ foreach ($account->accountMeta as $meta) { @@ -692,7 +692,7 @@ class OperatorQuerySearch implements SearchInterface if (0 === $filtered->count()) { Log::debug('Left with zero, search for invalid account'); - $account = new Account; + $account = new Account; $account->id = 0; $this->collector->$collectorMethod(new Collection([$account])); return; diff --git a/database/factories/AccountFactory.php b/database/factories/AccountFactory.php new file mode 100644 index 0000000000..65f01fb00d --- /dev/null +++ b/database/factories/AccountFactory.php @@ -0,0 +1,37 @@ +define(Account::class, function (Faker $faker) { + return [ + 'user_id' => 1, + 'account_type_id' => 1, + 'name' => $faker->words(3, true), + 'virtual_balance' => '0', + 'active' => 1, + 'encrypted' => 0, + 'order' => 1, + ]; +}); + +$factory->state(Account::class, AccountType::ASSET, function ($faker) { + return [ + 'account_type_id' => 3, + ]; +}); + +$factory->state(Account::class, AccountType::INITIAL_BALANCE, function ($faker) { + return [ + 'account_type_id' => 6, + ]; +}); + +$factory->state(Account::class, AccountType::EXPENSE, function ($faker) { + return [ + 'account_type_id' => 4, + ]; +}); \ No newline at end of file diff --git a/database/factories/OBFactory.php b/database/factories/OBFactory.php new file mode 100644 index 0000000000..684a0aa397 --- /dev/null +++ b/database/factories/OBFactory.php @@ -0,0 +1,66 @@ +define(TransactionJournal::class, function (Faker $faker) { + return [ + 'user_id' => 1, + 'transaction_type_id' => 1, + 'description' => $faker->words(3, true), + 'tag_count' => 0, + 'date' => $faker->date('Y-m-d'), + ]; +}); + +$factory->state(TransactionJournal::class, TransactionType::OPENING_BALANCE, function ($faker) { + return [ + 'transaction_type_id' => 4, + ]; +}); + +$factory->state(TransactionJournal::class, 'ob_broken', function ($faker) { + return [ + 'transaction_type_id' => 4, + ]; +}); + +$factory->afterCreatingState(TransactionJournal::class, TransactionType::OPENING_BALANCE, function ($journal, $faker) { + $obAccount = factory(Account::class)->state(AccountType::INITIAL_BALANCE)->create(); + $assetAccount = factory(Account::class)->state(AccountType::ASSET)->create(); + $sourceTransaction = factory(Transaction::class)->create( + [ + 'account_id' => $obAccount->id, + 'transaction_journal_id' => $journal->id, + ]); + + $destTransaction = factory(Transaction::class)->create( + [ + 'account_id' => $assetAccount->id, + 'transaction_journal_id' => $journal->id, + ]); +}); + +$factory->afterCreatingState(TransactionJournal::class, 'ob_broken', function ($journal, $faker) { + $ob1 = factory(Account::class)->state(AccountType::INITIAL_BALANCE)->create(); + $ob2 = factory(Account::class)->state(AccountType::INITIAL_BALANCE)->create(); + + $sourceTransaction = factory(Transaction::class)->create( + [ + 'account_id' => $ob1->id, + 'transaction_journal_id' => $journal->id, + ]); + + $destTransaction = factory(Transaction::class)->create( + [ + 'account_id' => $ob2->id, + 'transaction_journal_id' => $journal->id, + ]); +}); \ No newline at end of file diff --git a/database/factories/TransactionFactory.php b/database/factories/TransactionFactory.php new file mode 100644 index 0000000000..e81f1fa0ac --- /dev/null +++ b/database/factories/TransactionFactory.php @@ -0,0 +1,14 @@ +define(Transaction::class, function (Faker $faker) { + return [ + 'transaction_journal_id' => 0, + 'account_id' => 0, + 'amount' => 5, + ]; +}); diff --git a/phpunit.xml b/phpunit.xml index 701c47021b..aa554c3e3b 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -35,20 +35,31 @@ - + + + + + 1000 + + + + + + ./tests/Feature + + + + ./tests/Unit + --> diff --git a/tests/Feature/Console/Commands/Correction/CorrectOpeningBalanceCurrenciesTest.php b/tests/Feature/Console/Commands/Correction/CorrectOpeningBalanceCurrenciesTest.php new file mode 100644 index 0000000000..8c7f2aa4b5 --- /dev/null +++ b/tests/Feature/Console/Commands/Correction/CorrectOpeningBalanceCurrenciesTest.php @@ -0,0 +1,86 @@ +. + */ + +namespace Tests\Feature\Console\Commands\Correction; + + +use FireflyIII\Models\TransactionJournal; +use FireflyIII\Models\TransactionType; +use Log; +use Tests\TestCase; + +/** + * Class CorrectOpeningBalanceCurrenciesTest + * @package Tests\Feature\Console\Commands\Correction + */ +class CorrectOpeningBalanceCurrenciesTest extends TestCase +{ + + /** + * @covers \FireflyIII\Console\Commands\Correction\CorrectOpeningBalanceCurrencies + */ + public function testBasic(): void + { + $this->assertTrue(true); + } + + /** + * @covers \FireflyIII\Console\Commands\Correction\CorrectOpeningBalanceCurrencies + */ + public function testHandleOK(): void + { + // run command + $this->artisan('firefly-iii:fix-ob-currencies') + ->expectsOutput('There was nothing to fix in the opening balance transactions.') + ->assertExitCode(0); + } + + /** + * @covers \FireflyIII\Console\Commands\Correction\CorrectOpeningBalanceCurrencies + */ + public function testHandleBroken(): void + { + // create opening balance journal for test. Is enough to trigger this test. + $journal = factory(TransactionJournal::class)->state(TransactionType::OPENING_BALANCE)->create(); + + // run command + $this->artisan('firefly-iii:fix-ob-currencies') + ->expectsOutput('Corrected 1 opening balance transaction(s).') + ->assertExitCode(0); + } + + /** + * @covers \FireflyIII\Console\Commands\Correction\CorrectOpeningBalanceCurrencies + */ + public function testHandleNoAccount(): void + { + Log::debug('Now in testHandleNoAccount'); + // create opening balance journal for test. Is enough to trigger this test. + $journal = factory(TransactionJournal::class)->state('ob_broken')->create(); + + // run command + $this->artisan('firefly-iii:fix-ob-currencies') + ->expectsOutput(sprintf('Transaction journal #%d has no valid account. Cant fix this line.', $journal->id)) + //->expectsOutput('Cant fix this line.') + ->assertExitCode(0); + } + +} \ No newline at end of file diff --git a/tests/TestCase.php b/tests/TestCase.php index ceb7e0842b..677cb97e19 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -34,7 +34,7 @@ use Tests\Traits\TestHelpers; */ abstract class TestCase extends BaseTestCase { - use CreatesApplication, MocksDefaultValues, TestHelpers, CollectsValues; + use CreatesApplication, CollectsValues;//, MocksDefaultValues, TestHelpers, ; /** * @return array