diff --git a/app/Import/Storage/ImportArrayStorage.php b/app/Import/Storage/ImportArrayStorage.php index 040e6ca848..1f1add01cd 100644 --- a/app/Import/Storage/ImportArrayStorage.php +++ b/app/Import/Storage/ImportArrayStorage.php @@ -232,7 +232,7 @@ class ImportArrayStorage try { DB::table('tag_transaction_journal')->insert(['transaction_journal_id' => $journalId, 'tag_id' => $tagId]); } catch (QueryException $e) { - Log::error('Could not link journal #%d to tag #%d because: %s', $journalIds, $tagId, $e->getMessage()); + Log::error(sprintf('Could not link journal #%d to tag #%d because: %s', $journalId, $tagId, $e->getMessage())); Log::error($e->getTraceAsString()); } } @@ -411,7 +411,7 @@ class ImportArrayStorage // compare description: Log::debug(sprintf('Comparing "%s" to "%s"', $description, $transfer->description)); if ($description !== $transfer->description) { - continue; + continue; // @codeCoverageIgnore } ++$hits; Log::debug(sprintf('Comparison is a hit! (%s)', $hits)); @@ -420,7 +420,7 @@ class ImportArrayStorage $transferDate = $transfer->date->format('Y-m-d'); Log::debug(sprintf('Comparing dates "%s" to "%s"', $transaction['date'], $transferDate)); if ($transaction['date'] !== $transferDate) { - continue; + continue; // @codeCoverageIgnore } ++$hits; Log::debug(sprintf('Comparison is a hit! (%s)', $hits)); @@ -442,8 +442,10 @@ class ImportArrayStorage Log::debug('Comparing current transaction source+dest names', $currentSourceNames); Log::debug('.. with current transfer source+dest names', $transferSource); if ($currentSourceNames === $transferSource) { + // @codeCoverageIgnoreStart Log::debug(sprintf('Source names are the same! (%d)', $hits)); ++$hits; + // @codeCoverageIgnoreEnd } $totalHits += $hits; if ($totalHits >= $requiredHits) { diff --git a/app/Support/Import/Configuration/Bunq/HaveAccounts.php b/app/Support/Import/Configuration/Bunq/HaveAccounts.php index 33128731ba..ecdd214b2e 100644 --- a/app/Support/Import/Configuration/Bunq/HaveAccounts.php +++ b/app/Support/Import/Configuration/Bunq/HaveAccounts.php @@ -31,6 +31,7 @@ use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Support\Import\Configuration\ConfigurationInterface; /** + * @codeCoverageIgnore * @deprecated * Class HaveAccounts */ diff --git a/app/Support/Import/Configuration/File/Initial.php b/app/Support/Import/Configuration/File/Initial.php index b573de01af..0b7c3a7763 100644 --- a/app/Support/Import/Configuration/File/Initial.php +++ b/app/Support/Import/Configuration/File/Initial.php @@ -29,6 +29,7 @@ use Log; /** * @deprecated + * @codeCoverageIgnore * Class Initial. */ class Initial implements ConfigurationInterface diff --git a/app/Support/Import/Configuration/File/Map.php b/app/Support/Import/Configuration/File/Map.php index 8ea9bd423b..c2e1831eb6 100644 --- a/app/Support/Import/Configuration/File/Map.php +++ b/app/Support/Import/Configuration/File/Map.php @@ -35,6 +35,7 @@ use Log; /** * @deprecated + * @codeCoverageIgnore * Class Mapping. */ class Map implements ConfigurationInterface diff --git a/app/Support/Import/Configuration/File/Roles.php b/app/Support/Import/Configuration/File/Roles.php index 35c69148f6..c62385b08d 100644 --- a/app/Support/Import/Configuration/File/Roles.php +++ b/app/Support/Import/Configuration/File/Roles.php @@ -32,6 +32,7 @@ use Log; /** * @deprecated + * @codeCoverageIgnore * Class Roles. */ class Roles implements ConfigurationInterface diff --git a/app/Support/Import/Configuration/File/UploadConfig.php b/app/Support/Import/Configuration/File/UploadConfig.php index 6bf84df511..9b2c852565 100644 --- a/app/Support/Import/Configuration/File/UploadConfig.php +++ b/app/Support/Import/Configuration/File/UploadConfig.php @@ -31,6 +31,7 @@ use Log; /** * @deprecated + * @codeCoverageIgnore * Class UploadConfig. */ class UploadConfig implements ConfigurationInterface diff --git a/app/Support/Import/Configuration/Spectre/HaveAccounts.php b/app/Support/Import/Configuration/Spectre/HaveAccounts.php index 96752061ae..c3831dfabe 100644 --- a/app/Support/Import/Configuration/Spectre/HaveAccounts.php +++ b/app/Support/Import/Configuration/Spectre/HaveAccounts.php @@ -34,6 +34,7 @@ use Illuminate\Support\Collection; /** * @deprecated + * @codeCoverageIgnore * Class HaveAccounts */ class HaveAccounts implements ConfigurationInterface diff --git a/app/Support/Import/Information/BunqInformation.php b/app/Support/Import/Information/BunqInformation.php index e73673059b..afd170c1b5 100644 --- a/app/Support/Import/Information/BunqInformation.php +++ b/app/Support/Import/Information/BunqInformation.php @@ -37,6 +37,7 @@ use Log; use Preferences; /** + * @codeCoverageIgnore * @deprecated * Class BunqInformation. */ diff --git a/app/Support/Import/Routine/Fake/StageAhoyHandler.php b/app/Support/Import/Routine/Fake/StageAhoyHandler.php index 32bbad15fd..d26f3db8c4 100644 --- a/app/Support/Import/Routine/Fake/StageAhoyHandler.php +++ b/app/Support/Import/Routine/Fake/StageAhoyHandler.php @@ -27,6 +27,7 @@ use FireflyIII\Exceptions\FireflyException; use Log; /** + * @codeCoverageIgnore * Class StageAhoyHandler */ class StageAhoyHandler diff --git a/app/Support/Import/Routine/Fake/StageFinalHandler.php b/app/Support/Import/Routine/Fake/StageFinalHandler.php index c849eb538a..b16c74ac0c 100644 --- a/app/Support/Import/Routine/Fake/StageFinalHandler.php +++ b/app/Support/Import/Routine/Fake/StageFinalHandler.php @@ -5,6 +5,7 @@ namespace FireflyIII\Support\Import\Routine\Fake; use Carbon\Carbon; /** + * @codeCoverageIgnore * Class StageFinalHandler * * @package FireflyIII\Support\Import\Routine\Fake diff --git a/app/Support/Import/Routine/Fake/StageNewHandler.php b/app/Support/Import/Routine/Fake/StageNewHandler.php index 3d31a008f5..6051c199ac 100644 --- a/app/Support/Import/Routine/Fake/StageNewHandler.php +++ b/app/Support/Import/Routine/Fake/StageNewHandler.php @@ -27,6 +27,7 @@ use FireflyIII\Exceptions\FireflyException; use Log; /** + * @codeCoverageIgnore * Class StageNewHandler */ class StageNewHandler diff --git a/tests/Unit/Import/Storage/ImportArrayStorageTest.php b/tests/Unit/Import/Storage/ImportArrayStorageTest.php index 05cc146b84..a790682da7 100644 --- a/tests/Unit/Import/Storage/ImportArrayStorageTest.php +++ b/tests/Unit/Import/Storage/ImportArrayStorageTest.php @@ -25,11 +25,13 @@ namespace tests\Unit\Import\Storage; use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Helpers\Collector\JournalCollector; use FireflyIII\Helpers\Collector\JournalCollectorInterface; use FireflyIII\Helpers\Filter\InternalTransferFilter; use FireflyIII\Import\Storage\ImportArrayStorage; use FireflyIII\Models\ImportJob; use FireflyIII\Models\Rule; +use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournalMeta; use FireflyIII\Models\TransactionType; use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface; @@ -350,6 +352,12 @@ class ImportArrayStorageTest extends TestCase ->inRandomOrder()->where('transaction_type_id', 3) ->first(); + // get transfer as a collection, so the compare routine works. + $journalCollector = new JournalCollector(); + $journalCollector->setUser($this->user()); + $journalCollector->setJournals(new Collection([$transfer])); + $transferCollection = $journalCollector->withOpposingAccount()->getJournals(); + // get some stuff: $tag = $this->user()->tags()->inRandomOrder()->first(); $journal = $this->user()->transactionJournals()->inRandomOrder()->first(); @@ -382,7 +390,7 @@ class ImportArrayStorageTest extends TestCase $collector->shouldReceive('setTypes')->withArgs([[TransactionType::TRANSFER]])->once()->andReturnSelf(); $collector->shouldReceive('withOpposingAccount')->once()->andReturnSelf(); $collector->shouldReceive('removeFilter')->withArgs([InternalTransferFilter::class])->once()->andReturnSelf(); - $collector->shouldReceive('getJournals')->andReturn(new Collection([$transfer])); + $collector->shouldReceive('getJournals')->andReturn($transferCollection); $storage = new ImportArrayStorage; $storage->setJob($job); @@ -395,6 +403,140 @@ class ImportArrayStorageTest extends TestCase $this->assertCount(2, $result); } + /** + * @covers \FireflyIII\Import\Storage\ImportArrayStorage + */ + public function testBasicStoreDoubleTransferWithRules(): void + { + // get a transfer: + /** @var TransactionJournal $transfer */ + $transfer = $this->user()->transactionJournals() + ->inRandomOrder()->where('transaction_type_id', 3) + ->first(); + + // get transfer as a collection, so the compare routine works. + $journalCollector = new JournalCollector(); + $journalCollector->setUser($this->user()); + $journalCollector->setJournals(new Collection([$transfer])); + $transferCollection = $journalCollector->withOpposingAccount()->getJournals(); + + // make fake job + $job = new ImportJob; + $job->user()->associate($this->user()); + $job->key = 'a_storage' . random_int(1, 1000); + $job->status = 'new'; + $job->stage = 'new'; + $job->provider = 'fake'; + $job->file_type = ''; + $job->configuration = ['apply-rules' => true]; + $job->transactions = [$this->singleTransfer(), $this->singleWithdrawal(), $this->basedOnTransfer($transfer)]; + $job->save(); + + + // get some stuff: + $tag = $this->user()->tags()->inRandomOrder()->first(); + $journal = $this->user()->transactionJournals()->inRandomOrder()->first(); + $ruleOne = new Rule; + $ruleOne->stop_processing = false; + $ruleTwo = new Rule; + $ruleTwo->stop_processing = true; + + // mock stuff + $repository = $this->mock(ImportJobRepositoryInterface::class); + $collector = $this->mock(JournalCollectorInterface::class); + $tagRepos = $this->mock(TagRepositoryInterface::class); + $ruleRepos = $this->mock(RuleRepositoryInterface::class); + $journalRepos = $this->mock(JournalRepositoryInterface::class); + + // mock calls: + $repository->shouldReceive('setUser')->once(); + $repository->shouldReceive('setStatus')->withAnyArgs(); + $ruleRepos->shouldReceive('setUser')->once(); + $tagRepos->shouldReceive('setUser')->once(); + $tagRepos->shouldReceive('store')->once()->andReturn($tag); + $repository->shouldReceive('setTag')->once(); + $ruleRepos->shouldReceive('getForImport')->andReturn(new Collection([$ruleOne, $ruleTwo])); + $journalRepos->shouldReceive('setUser')->once(); + $journalRepos->shouldReceive('store')->twice()->andReturn($journal); + $journalRepos->shouldReceive('findByHash')->andReturn(null)->times(3); + $repository->shouldReceive('addErrorMessage')->withArgs( + [Mockery::any(), 'Entry #2 ("' . $transfer->description . '") could not be imported. Such a transfer already exists.'] + )->once(); + + + // mock collector so it will return some transfers: + $collector->shouldReceive('setAllAssetAccounts')->once()->andReturnSelf(); + $collector->shouldReceive('setTypes')->withArgs([[TransactionType::TRANSFER]])->once()->andReturnSelf(); + $collector->shouldReceive('withOpposingAccount')->once()->andReturnSelf(); + $collector->shouldReceive('removeFilter')->withArgs([InternalTransferFilter::class])->once()->andReturnSelf(); + $collector->shouldReceive('getJournals')->andReturn($transferCollection); + + $storage = new ImportArrayStorage; + $storage->setJob($job); + $result = new Collection; + try { + $result = $storage->store(); + } catch (FireflyException $e) { + $this->assertTrue(false, $e->getMessage()); + } + $this->assertCount(2, $result); + } + + /** + * @param TransactionJournal $transfer + * + * @return array + */ + private function basedOnTransfer(TransactionJournal $transfer): array + { + $destination = $transfer->transactions()->where('amount', '>', 0)->first(); + $source = $transfer->transactions()->where('amount', '<', 0)->first(); + $amount = $destination->amount; + + return + [ + 'type' => 'transfer', + 'date' => $transfer->date->format('Y-m-d'), + 'tags' => '', + 'user' => $this->user()->id, + + // all custom fields: + 'internal_reference' => null, + 'notes' => null, + + // journal data: + 'description' => $transfer->description, + 'piggy_bank_id' => null, + 'piggy_bank_name' => null, + 'bill_id' => null, + 'bill_name' => null, + + // transaction data: + 'transactions' => [ + [ + 'currency_id' => null, + 'currency_code' => 'EUR', + 'description' => null, + 'amount' => $amount, + 'budget_id' => null, + 'budget_name' => null, + 'category_id' => null, + 'category_name' => null, + 'source_id' => $source->account_id, + 'source_name' => null, + 'destination_id' => $destination->account_id, + 'destination_name' => null, + 'foreign_currency_id' => null, + 'foreign_currency_code' => null, + 'foreign_amount' => null, + 'reconciled' => false, + 'identifier' => 0, + ], + ], + ]; + + } + /** * @return array */