From 431cf084014c4f73401e9d159a876e4cdfe52830 Mon Sep 17 00:00:00 2001 From: James Cole Date: Fri, 8 Mar 2019 05:47:51 +0100 Subject: [PATCH] Various improvements. --- app/Console/Commands/MigrateToGroups.php | 133 +++-- app/Factory/BillFactory.php | 16 +- app/Factory/TransactionFactory.php | 357 ++++++++---- app/Factory/TransactionJournalFactory.php | 537 ++++++++++-------- app/Providers/FireflyServiceProvider.php | 5 +- .../Currency/CurrencyRepository.php | 35 ++ .../Currency/CurrencyRepositoryInterface.php | 11 + .../TransactionTypeRepository.php | 64 +++ .../TransactionTypeRepositoryInterface.php | 47 ++ .../Internal/Support/JournalServiceTrait.php | 26 +- .../Support/TransactionServiceTrait.php | 12 +- 11 files changed, 813 insertions(+), 430 deletions(-) create mode 100644 app/Repositories/TransactionType/TransactionTypeRepository.php create mode 100644 app/Repositories/TransactionType/TransactionTypeRepositoryInterface.php diff --git a/app/Console/Commands/MigrateToGroups.php b/app/Console/Commands/MigrateToGroups.php index 9245aecf22..c835f949c4 100644 --- a/app/Console/Commands/MigrateToGroups.php +++ b/app/Console/Commands/MigrateToGroups.php @@ -96,42 +96,13 @@ class MigrateToGroups extends Command $data = [ // mandatory fields. - 'type' => strtolower($journal->transactionType->type), - 'date' => $journal->date, - 'user' => $journal->user_id, + 'type' => strtolower($journal->transactionType->type), + 'date' => $journal->date, + 'user' => $journal->user_id, + 'description' => $journal->description, - // currency fields: - 'currency' => null, - 'currency_id' => null, - 'currency_code' => null, - - // all custom fields: - 'internal_reference' => $this->journalRepository->getMetaField($journal, 'internal-reference'), - 'sepa-cc' => $this->journalRepository->getMetaField($journal, 'sepa-cc'), - 'sepa-ct-op' => $this->journalRepository->getMetaField($journal, 'sepa-ct-op'), - 'sepa-ct-id' => $this->journalRepository->getMetaField($journal, 'sepa-ct-id'), - 'sepa-db' => $this->journalRepository->getMetaField($journal, 'sepa-db'), - 'sepa-country' => $this->journalRepository->getMetaField($journal, 'sepa-country'), - 'sepa-ep' => $this->journalRepository->getMetaField($journal, 'sepa-ep'), - 'sepa-ci' => $this->journalRepository->getMetaField($journal, 'sepa-ci'), - 'sepa-batch-id' => $this->journalRepository->getMetaField($journal, 'sepa-batch-id'), - 'interest_date' => $this->journalRepository->getMetaDateString($journal, 'interest_date'), - 'book_date' => $this->journalRepository->getMetaDateString($journal, 'book_date'), - 'process_date' => $this->journalRepository->getMetaDateString($journal, 'process_date'), - 'due_date' => $this->journalRepository->getMetaDateString($journal, 'due_date'), - 'payment_date' => $this->journalRepository->getMetaDateString($journal, 'payment_date'), - 'invoice_date' => $this->journalRepository->getMetaDateString($journal, 'invoice_date'), - 'external_id' => $this->journalRepository->getMetaField($journal, 'external-id'), - 'original-source' => $this->journalRepository->getMetaField($journal, 'original-source'), - // journal data: - 'description' => $journal->description, - 'piggy_bank_id' => null, - 'piggy_bank_name' => null, - 'bill_id' => $journal->bill_id, - 'bill_name' => null, - 'tags' => null, - 'notes' => null, - 'transactions' => [], + // transactions: + 'transactions' => [], ]; @@ -157,40 +128,88 @@ class MigrateToGroups extends Command return; } - $tArray = [ - 'notes' => $this->journalRepository->getNoteText($journal), - 'tags' => $journal->tags->pluck('tag')->toArray(), - 'currency' => null, + $tArray = [ + + // currency and foreign currency + 'currency' => null, 'currency_id' => $transaction->transaction_currency_id, 'currency_code' => null, - 'description' => $transaction->description, - 'amount' => $transaction->amount, - 'budget' => null, - 'budget_id' => $budgetId, - 'budget_name' => null, - 'category' => null, - 'category_id' => $categoryId, - 'category_name' => null, - 'source' => null, - 'source_id' => $opposing->account_id, - 'source_name' => null, - 'destination' => null, - 'destination_id' => $transaction->account_id, - 'destination_name' => null, - 'foreign_currency' => null, + 'foreign_currency' => null, 'foreign_currency_id' => $transaction->foreign_currency_id, 'foreign_currency_code' => null, + + // amount and foreign amount + 'amount' => $transaction->amount, 'foreign_amount' => $transaction->foreign_amount, + + // description + 'description' => $transaction->description, + + // source + 'source' => null, + 'source_id' => $opposing->account_id, + 'source_name' => null, + + // destination + 'destination' => null, + 'destination_id' => $transaction->account_id, + 'destination_name' => null, + + // budget + 'budget' => null, + 'budget_id' => $budgetId, + 'budget_name' => null, + + // category + 'category' => null, + 'category_id' => $categoryId, + 'category_name' => null, + + // piggy bank (if transfer) + 'piggy_bank' => null, + 'piggy_bank_id' => null, + 'piggy_bank_name' => null, + + // bill (if withdrawal) + 'bill' => null, + 'bill_id' => $journal->bill_id, + 'bill_name' => null, + + // some other interesting properties 'reconciled' => false, + 'notes' => $this->journalRepository->getNoteText($journal), + 'tags' => $journal->tags->pluck('tag')->toArray(), + + // all custom fields: + 'internal_reference' => $this->journalRepository->getMetaField($journal, 'internal-reference'), + 'sepa-cc' => $this->journalRepository->getMetaField($journal, 'sepa-cc'), + 'sepa-ct-op' => $this->journalRepository->getMetaField($journal, 'sepa-ct-op'), + 'sepa-ct-id' => $this->journalRepository->getMetaField($journal, 'sepa-ct-id'), + 'sepa-db' => $this->journalRepository->getMetaField($journal, 'sepa-db'), + 'sepa-country' => $this->journalRepository->getMetaField($journal, 'sepa-country'), + 'sepa-ep' => $this->journalRepository->getMetaField($journal, 'sepa-ep'), + 'sepa-ci' => $this->journalRepository->getMetaField($journal, 'sepa-ci'), + 'sepa-batch-id' => $this->journalRepository->getMetaField($journal, 'sepa-batch-id'), + 'interest_date' => $this->journalRepository->getMetaDate($journal, 'interest_date'), + 'book_date' => $this->journalRepository->getMetaDate($journal, 'book_date'), + 'process_date' => $this->journalRepository->getMetaDate($journal, 'process_date'), + 'due_date' => $this->journalRepository->getMetaDate($journal, 'due_date'), + 'payment_date' => $this->journalRepository->getMetaDate($journal, 'payment_date'), + 'invoice_date' => $this->journalRepository->getMetaDate($journal, 'invoice_date'), + 'external_id' => $this->journalRepository->getMetaField($journal, 'external-id'), + 'original-source' => $this->journalRepository->getMetaField($journal, 'original-source'), + 'recurrence_id' => $this->journalRepository->getMetaField($journal, 'recurrence_id'), + 'bunq_payment_id' => $this->journalRepository->getMetaField($journal, 'bunq_payment_id'), + 'importHash' => $this->journalRepository->getMetaField($journal, 'importHash'), + 'importHashV2' => $this->journalRepository->getMetaField($journal, 'importHashV2'), ]; - - $data['transactions'][] = $tArray; } - $this->journalFactory->create($data); + $result = $this->journalFactory->create($data); // create a new transaction journal based on this particular transaction using the factory. // delete the old transaction journal. //$journal->delete(); + Log::debug(sprintf('Migrated journal #%d into %s', $journal->id, implode(', ', $result->pluck('id')->toArray()))); } /** diff --git a/app/Factory/BillFactory.php b/app/Factory/BillFactory.php index e9a7363fd8..78ae84528f 100644 --- a/app/Factory/BillFactory.php +++ b/app/Factory/BillFactory.php @@ -28,7 +28,6 @@ use FireflyIII\Models\Bill; use FireflyIII\Models\TransactionCurrency; use FireflyIII\Services\Internal\Support\BillServiceTrait; use FireflyIII\User; -use Illuminate\Support\Collection; use Log; /** @@ -126,20 +125,9 @@ class BillFactory */ public function findByName(string $name): ?Bill { - /** @var Collection $collection */ - $collection = $this->user->bills()->get(); - $return = null; - /** @var Bill $bill */ - foreach ($collection as $bill) { - Log::debug(sprintf('"%s" vs. "%s"', $bill->name, $name)); - if ($bill->name === $name) { - $return = $bill; - break; - } - } - Log::debug(sprintf('Bill::find("%s") by name returns null? %s', $name, var_export($return, true))); + $query = sprintf('%%%s%%', $name); - return $return; + return $this->user->bills()->where('name', 'LIKE', $query)->first(); } /** diff --git a/app/Factory/TransactionFactory.php b/app/Factory/TransactionFactory.php index f88d4bd9ea..8dd3a3cd40 100644 --- a/app/Factory/TransactionFactory.php +++ b/app/Factory/TransactionFactory.php @@ -26,11 +26,13 @@ namespace FireflyIII\Factory; use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; use FireflyIII\Models\Transaction; +use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionType; -use FireflyIII\Services\Internal\Support\TransactionServiceTrait; +use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\User; use Illuminate\Support\Collection; use Log; @@ -40,11 +42,13 @@ use Log; */ class TransactionFactory { + /** @var AccountRepositoryInterface */ + private $accountRepository; + /** @var TransactionJournal */ + private $journal; /** @var User */ private $user; - use TransactionServiceTrait; - /** * Constructor. */ @@ -53,108 +57,151 @@ class TransactionFactory if ('testing' === config('app.env')) { Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this))); } + $this->accountRepository = app(AccountRepositoryInterface::class); } - /** - * @param array $data - * - * @return Transaction - */ - public function create(array $data): ?Transaction - { - $data['foreign_amount'] = '' === (string)$data['foreign_amount'] ? null : $data['foreign_amount']; - Log::debug(sprintf('Create transaction for account #%d ("%s") with amount %s', $data['account']->id, $data['account']->name, $data['amount'])); + //use TransactionServiceTrait; - return Transaction::create( + /** + * @param Account $account + * @param TransactionCurrency $currency + * @param string $amount + * + * @return Transaction|null + */ + public function create(Account $account, TransactionCurrency $currency, string $amount): ?Transaction + { + $result = Transaction::create( [ - 'reconciled' => $data['reconciled'], - 'account_id' => $data['account']->id, - 'transaction_journal_id' => $data['transaction_journal']->id, - 'description' => $data['description'], - 'transaction_currency_id' => $data['currency']->id, - 'amount' => $data['amount'], - 'foreign_amount' => $data['foreign_amount'], - 'foreign_currency_id' => $data['foreign_currency'] ? $data['foreign_currency']->id : null, + 'reconciled' => false, + 'account_id' => $account->id, + 'transaction_journal_id' => $this->journal->id, + 'description' => null, + 'transaction_currency_id' => $currency->id, + 'amount' => $amount, + 'foreign_amount' => null, + 'foreign_currency_id' => null, 'identifier' => 0, ] ); + if (null !== $result) { + Log::debug( + sprintf( + 'Created transaction #%d (%s %s), part of journal #%d', $result->id, + $currency->code, $amount, $this->journal->id + ) + ); + } + + return $result; } /** - * Create a pair of transactions based on the data given in the array. - * - * @param TransactionJournal $journal - * @param array $data + * @param TransactionCurrency $currency + * @param array $data * * @return Collection * @throws FireflyException - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.NPathComplexity) - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ - public function createPair(TransactionJournal $journal, array $data): Collection + public function createPair(TransactionCurrency $currency, array $data): Collection { - Log::debug('Start of TransactionFactory::createPair()' ); + $sourceAccount = $this->getAccount('source', $data['source'], $data['source_id'], $data['source_name']); + $destinationAccount = $this->getAccount('destination', $data['destination'], $data['destination_id'], $data['destination_name']); + $amount = $this->getAmount($data['amount']); - // type of source account and destination account depends on journal type: - $sourceType = $this->accountType($journal, 'source'); - $destinationType = $this->accountType($journal, 'destination'); + $one = $this->create($sourceAccount, $currency, app('steam')->negative($amount)); + $two = $this->create($destinationAccount, $currency, app('steam')->positive($amount)); - Log::debug(sprintf('Journal is a %s.', $journal->transactionType->type)); - Log::debug(sprintf('Expect source account to be of type "%s"', $sourceType)); - Log::debug(sprintf('Expect source destination to be of type "%s"', $destinationType)); + return new Collection([$one, $two]); - // find source and destination account: - $sourceAccount = $this->findAccount($sourceType, (int)$data['source_id'], $data['source_name']); - $destinationAccount = $this->findAccount($destinationType, (int)$data['destination_id'], $data['destination_name']); + // Log::debug('Start of TransactionFactory::createPair()' ); + // + // // type of source account and destination account depends on journal type: + // $sourceType = $this->accountType($journal, 'source'); + // $destinationType = $this->accountType($journal, 'destination'); + // + // Log::debug(sprintf('Journal is a %s.', $journal->transactionType->type)); + // Log::debug(sprintf('Expect source account to be of type "%s"', $sourceType)); + // Log::debug(sprintf('Expect source destination to be of type "%s"', $destinationType)); + // + // // find source and destination account: + // $sourceAccount = $this->findAccount($sourceType, $data['source'], (int)$data['source_id'], $data['source_name']); + // $destinationAccount = $this->findAccount($destinationType, $data['destination'], (int)$data['destination_id'], $data['destination_name']); + // + // if (null === $sourceAccount || null === $destinationAccount) { + // $debugData = $data; + // $debugData['source_type'] = $sourceType; + // $debugData['dest_type'] = $destinationType; + // Log::error('Info about source/dest:', $debugData); + // throw new FireflyException('Could not determine source or destination account.'); + // } + // + // Log::debug(sprintf('Source type is "%s", destination type is "%s"', $sourceAccount->accountType->type, $destinationAccount->accountType->type)); + // + // // based on the source type, destination type and transaction type, the system can start throwing FireflyExceptions. + // $this->validateTransaction($sourceAccount->accountType->type, $destinationAccount->accountType->type, $journal->transactionType->type); + // $source = $this->create( + // [ + // 'description' => null, + // 'amount' => app('steam')->negative((string)$data['amount']), + // 'foreign_amount' => $data['foreign_amount'] ? app('steam')->negative((string)$data['foreign_amount']): null, + // 'currency' => $data['currency'], + // 'foreign_currency' => $data['foreign_currency'], + // 'account' => $sourceAccount, + // 'transaction_journal' => $journal, + // 'reconciled' => $data['reconciled'], + // ] + // ); + // $dest = $this->create( + // [ + // 'description' => null, + // 'amount' => app('steam')->positive((string)$data['amount']), + // 'foreign_amount' => $data['foreign_amount'] ? app('steam')->positive((string)$data['foreign_amount']): null, + // 'currency' => $data['currency'], + // 'foreign_currency' => $data['foreign_currency'], + // 'account' => $destinationAccount, + // 'transaction_journal' => $journal, + // 'reconciled' => $data['reconciled'], + // ] + // ); + // if (null === $source || null === $dest) { + // throw new FireflyException('Could not create transactions.'); // @codeCoverageIgnore + // } + // + // return new Collection([$source, $dest]); + } - if (null === $sourceAccount || null === $destinationAccount) { - $debugData = $data; - $debugData['source_type'] = $sourceType; - $debugData['dest_type'] = $destinationType; - Log::error('Info about source/dest:', $debugData); - throw new FireflyException('Could not determine source or destination account.'); - } + // /** + // * @param array $data + // * + // * @return Transaction + // */ + // public function create(array $data): ?Transaction + // { + // $data['foreign_amount'] = '' === (string)$data['foreign_amount'] ? null : $data['foreign_amount']; + // Log::debug(sprintf('Create transaction for account #%d ("%s") with amount %s', $data['account']->id, $data['account']->name, $data['amount'])); + // + // return Transaction::create( + // [ + // 'reconciled' => $data['reconciled'], + // 'account_id' => $data['account']->id, + // 'transaction_journal_id' => $data['transaction_journal']->id, + // 'description' => $data['description'], + // 'transaction_currency_id' => $data['currency']->id, + // 'amount' => $data['amount'], + // 'foreign_amount' => $data['foreign_amount'], + // 'foreign_currency_id' => $data['foreign_currency'] ? $data['foreign_currency']->id : null, + // 'identifier' => 0, + // ] + // ); + // } - Log::debug(sprintf('Source type is "%s", destination type is "%s"', $sourceAccount->accountType->type, $destinationAccount->accountType->type)); - - // based on the source type, destination type and transaction type, the system can start throwing FireflyExceptions. - $this->validateTransaction($sourceAccount->accountType->type, $destinationAccount->accountType->type, $journal->transactionType->type); - $source = $this->create( - [ - 'description' => $data['description'], - 'amount' => app('steam')->negative((string)$data['amount']), - 'foreign_amount' => null, - 'currency' => $data['currency'], - 'foreign_currency' => $data['foreign_currency'], - 'account' => $sourceAccount, - 'transaction_journal' => $journal, - 'reconciled' => $data['reconciled'], - ] - ); - $dest = $this->create( - [ - 'description' => $data['description'], - 'amount' => app('steam')->positive((string)$data['amount']), - 'foreign_amount' => null, - 'currency' => $data['currency'], - 'foreign_currency' => $data['foreign_currency'], - 'account' => $destinationAccount, - 'transaction_journal' => $journal, - 'reconciled' => $data['reconciled'], - ] - ); - if (null === $source || null === $dest) { - throw new FireflyException('Could not create transactions.'); // @codeCoverageIgnore - } - - // set foreign amount: - if (null !== $data['foreign_amount']) { - $this->setForeignAmount($source, app('steam')->negative((string)$data['foreign_amount'])); - $this->setForeignAmount($dest, app('steam')->positive((string)$data['foreign_amount'])); - } - - return new Collection([$source, $dest]); + /** + * @param TransactionJournal $journal + */ + public function setJournal(TransactionJournal $journal): void + { + $this->journal = $journal; } /** @@ -163,30 +210,142 @@ class TransactionFactory public function setUser(User $user): void { $this->user = $user; + $this->accountRepository->setUser($user); } /** - * @param string $sourceType - * @param string $destinationType - * @param string $transactionType + * @param string $direction + * @param Account|null $source + * @param int|null $sourceId + * @param string|null $sourceName * + * @return Account * @throws FireflyException */ - private function validateTransaction(string $sourceType, string $destinationType, string $transactionType): void + private function getAccount(string $direction, ?Account $source, ?int $sourceId, ?string $sourceName): Account { - // throw big fat error when source type === dest type and it's not a transfer or reconciliation. - if ($sourceType === $destinationType && $transactionType !== TransactionType::TRANSFER) { - throw new FireflyException(sprintf('Source and destination account cannot be both of the type "%s"', $destinationType)); + // expected type of source account, in order of preference + $array = [ + 'source' => [ + TransactionType::WITHDRAWAL => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE], + TransactionType::DEPOSIT => [AccountType::REVENUE, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE], + TransactionType::TRANSFER => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE], + TransactionType::OPENING_BALANCE => [AccountType::INITIAL_BALANCE, AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, + AccountType::MORTGAGE], + TransactionType::RECONCILIATION => [AccountType::RECONCILIATION, AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, + AccountType::MORTGAGE], + ], + 'destination' => [ + TransactionType::WITHDRAWAL => [AccountType::EXPENSE, AccountType::ASSET], + TransactionType::DEPOSIT => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE], + TransactionType::TRANSFER => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE], + TransactionType::OPENING_BALANCE => [AccountType::INITIAL_BALANCE, AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, + AccountType::MORTGAGE], + TransactionType::RECONCILIATION => [AccountType::RECONCILIATION, AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, + AccountType::MORTGAGE], + ], + ]; + $expectedTypes = $array[$direction]; + unset($array); + + // and now try to find it, based on the type of transaction. + $transactionType = $this->journal->transactionType->type; + Log::debug( + sprintf( + 'Based on the fact that the transaction is a %s, the %s account should be in %s', $transactionType, $direction, + implode(', ', $expectedTypes[$transactionType]) + ) + ); + + + // first attempt, check the "source" object. + if (null !== $source && $source->user_id === $this->user->id && \in_array($source->accountType->type, $expectedTypes[$transactionType], true)) { + Log::debug(sprintf('Found "account" object for %s: #%d, %s', $direction, $source->id, $source->name)); + + return $source; } - // source must be in this list AND dest must be in this list: - $list = [AccountType::DEFAULT, AccountType::ASSET, AccountType::CREDITCARD, AccountType::CASH, AccountType::DEBT, AccountType::MORTGAGE, - AccountType::LOAN, AccountType::MORTGAGE]; - if ( - !\in_array($sourceType, $list, true) - && !\in_array($destinationType, $list, true)) { - throw new FireflyException(sprintf('At least one of the accounts must be an asset account (%s, %s).', $sourceType, $destinationType)); + + // second attempt, find by ID. + if (null !== $sourceId) { + $source = $this->accountRepository->findNull($sourceId); + if (null !== $source && \in_array($source->accountType->type, $expectedTypes[$transactionType], true)) { + Log::debug(sprintf('Found "account_id" object for %s: #%d, %s', $direction, $source->id, $source->name)); + + return $source; + } } + + // third attempt, find by name. + if (null !== $sourceName) { + // find by preferred type. + $source = $this->accountRepository->findByName($sourceName, [$expectedTypes[$transactionType][0]]); + // or any type. + $source = $source ?? $this->accountRepository->findByName($sourceName, $expectedTypes[$transactionType]); + + if (null !== $source) { + Log::debug(sprintf('Found "account_name" object for %s: #%d, %s', $direction, $source->id, $source->name)); + + return $source; + } + } + + // final attempt, create it. + $preferredType = $expectedTypes[$transactionType][0]; + if (AccountType::ASSET === $preferredType) { + throw new FireflyException(sprintf('TransactionFactory: Cannot create asset account with ID #%d or name "%s".', $sourceId, $sourceName)); + } + + return $this->accountRepository->store( + [ + 'account_type_id' => null, + 'accountType' => $preferredType, + 'name' => $sourceName, + 'active' => true, + 'iban' => null, + ] + ); } + /** + * @param string $amount + * + * @return string + * @throws FireflyException + */ + private function getAmount(string $amount): string + { + if ('' === $amount) { + throw new FireflyException(sprintf('The amount cannot be an empty string: "%s"', $amount)); + } + if (0 === bccomp('0', $amount)) { + throw new FireflyException(sprintf('The amount seems to be zero: "%s"', $amount)); + } + + return $amount; + } + // + // /** + // * @param string $sourceType + // * @param string $destinationType + // * @param string $transactionType + // * + // * @throws FireflyException + // */ + // private function validateTransaction(string $sourceType, string $destinationType, string $transactionType): void + // { + // // throw big fat error when source type === dest type and it's not a transfer or reconciliation. + // if ($sourceType === $destinationType && $transactionType !== TransactionType::TRANSFER) { + // throw new FireflyException(sprintf('Source and destination account cannot be both of the type "%s"', $destinationType)); + // } + // // source must be in this list AND dest must be in this list: + // $list = [AccountType::DEFAULT, AccountType::ASSET, AccountType::CREDITCARD, AccountType::CASH, AccountType::DEBT, AccountType::MORTGAGE, + // AccountType::LOAN, AccountType::MORTGAGE]; + // if ( + // !\in_array($sourceType, $list, true) + // && !\in_array($destinationType, $list, true)) { + // throw new FireflyException(sprintf('At least one of the accounts must be an asset account (%s, %s).', $sourceType, $destinationType)); + // } + // } + } diff --git a/app/Factory/TransactionJournalFactory.php b/app/Factory/TransactionJournalFactory.php index 520653e86c..c88a55170d 100644 --- a/app/Factory/TransactionJournalFactory.php +++ b/app/Factory/TransactionJournalFactory.php @@ -24,12 +24,11 @@ declare(strict_types=1); namespace FireflyIII\Factory; -use FireflyIII\Exceptions\FireflyException; -use FireflyIII\Models\TransactionCurrency; -use FireflyIII\Models\TransactionGroup; +use Carbon\Carbon; +use Exception; use FireflyIII\Models\TransactionJournal; -use FireflyIII\Services\Internal\Support\JournalServiceTrait; -use FireflyIII\Services\Internal\Support\TransactionTypeTrait; +use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; +use FireflyIII\Repositories\TransactionType\TransactionTypeRepositoryInterface; use FireflyIII\User; use Illuminate\Support\Collection; use Log; @@ -39,23 +38,36 @@ use Log; */ class TransactionJournalFactory { - private $fields; + /** @var CurrencyRepositoryInterface */ + private $currencyRepository; + + /** @var TransactionFactory */ + private $transactionFactory; + + /** @var TransactionTypeRepositoryInterface */ + private $typeRepository; + + // private $fields; /** @var User The user */ private $user; - use JournalServiceTrait, TransactionTypeTrait; + // + // use JournalServiceTrait, TransactionTypeTrait; /** * Constructor. */ public function __construct() { - $this->fields = ['sepa-cc', 'sepa-ct-op', 'sepa-ct-id', 'sepa-db', 'sepa-country', 'sepa-ep', 'sepa-ci', 'interest_date', 'book_date', 'process_date', - 'due_date', 'recurrence_id', 'payment_date', 'invoice_date', 'internal_reference', 'bunq_payment_id', 'importHash', 'importHashV2', - 'external_id', 'sepa-batch-id', 'original-source']; + // $this->fields = ['sepa-cc', 'sepa-ct-op', 'sepa-ct-id', 'sepa-db', 'sepa-country', 'sepa-ep', 'sepa-ci', 'interest_date', 'book_date', 'process_date', + // 'due_date', 'recurrence_id', 'payment_date', 'invoice_date', 'internal_reference', 'bunq_payment_id', 'importHash', 'importHashV2', + // 'external_id', 'sepa-batch-id', 'original-source']; if ('testing' === config('app.env')) { Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this))); } + $this->currencyRepository = app(CurrencyRepositoryInterface::class); + $this->typeRepository = app(TransactionTypeRepositoryInterface::class); + $this->transactionFactory = app(TransactionFactory::class); } /** @@ -64,46 +76,31 @@ class TransactionJournalFactory * @param array $data * * @return Collection - * @throws FireflyException + * @throws Exception */ public function create(array $data): Collection { Log::debug('Start of TransactionJournalFactory::create()'); - - $factory = app(TransactionFactory::class); - $journals = new Collection; - $carbon = $data['date']; - $type = $this->findTransactionType($data['type']); - $description = app('steam')->cleanString($data['description']); - + $collection = new Collection; + $transactions = $data['transactions'] ?? []; + $type = $this->typeRepository->findTransactionType(null, $data['type']); + $description = app('steam')->cleanString($data['description']); + $carbon = $data['date'] ?? new Carbon; $carbon->setTimezone(config('app.timezone')); - $factory->setUser($this->user); - Log::debug(sprintf('New journal(group): %s with description "%s"', $type->type, $description)); + /** @var array $transaction */ + foreach ($transactions as $transaction) { - // loop each transaction. - /** - * @var int $index - * @var array $transactionData - */ - foreach ($data['transactions'] as $index => $transactionData) { - Log::debug(sprintf('Now at journal #%d from %d', $index + 1, count($data['transactions']))); + /** Get basic fields */ + $currency = $this->currencyRepository->findCurrency($transaction['currency'], $transaction['currency_id'], $transaction['currency_code']); - // catch to stop empty amounts: - if ('' === (string)$transactionData['amount'] || 0.0 === (float)$transactionData['amount']) { - continue; - } - // currency & foreign currency - $transactionData['currency'] = $this->getCurrency($data, $index); - $transactionData['foreign_currency'] = $this->getForeignCurrency($data, $index); - - // store basic journal first. + /** Create a basic journal. */ $journal = TransactionJournal::create( [ - 'user_id' => $data['user'], + 'user_id' => $this->user->id, 'transaction_type_id' => $type->id, 'bill_id' => null, - 'transaction_currency_id' => $transactionData['currency']->id, + 'transaction_currency_id' => $currency->id, 'description' => $description, 'date' => $carbon->format('Y-m-d H:i:s'), 'order' => 0, @@ -111,65 +108,128 @@ class TransactionJournalFactory 'completed' => 0, ] ); - Log::debug(sprintf('Stored journal under ID #%d', $journal->id)); - // store transactions for this journal: - $factory->createPair($journal, $transactionData); + /** Create two transactions. */ + $this->transactionFactory->setJournal($journal); + $children = $this->transactionFactory->createPair($currency, $transaction); - // save journal: - $journal->completed = true; - $journal->save(); - // // link bill TODO - // $this->connectBill($journal, $data); - // - // // link piggy bank (if transfer) TODO - // $this->connectPiggyBank($journal, $data); - // - // // link tags: TODO - // $this->connectTags($journal, $transactionData); - // - // // store note: TODO - // $this->storeNote($journal, $transactionData['notes']); - // - // if ($journal->transactionType->type !== TransactionType::WITHDRAWAL) { - // $transactionData['budget_id'] = null; - // $transactionData['budget_name'] = null; - // } - // // save budget TODO - // $budget = $this->findBudget($data['budget_id'], $data['budget_name']); - // $this->setBudget($journal, $budget); - // - // // set category TODO - // $category = $this->findCategory($data['category_id'], $data['category_name']); - // $this->setCategory($journal, $category); - // - // // store meta data TODO - // foreach ($this->fields as $field) { - // $this->storeMeta($journal, $data, $field); - // } - // add to array - $journals->push($journal); - } - // create group if necessary - if ($journals->count() > 1) { - $group = new TransactionGroup; - $group->user()->associate($this->user); - $group->title = $description; - $group->save(); - $group->transactionJournals()->saveMany($journals); + $collection->push($journal); + Log::debug(sprintf('Created journal #%d', $journal->id)); - Log::debug(sprintf('More than one journal, created group #%d.', $group->id)); + return $collection; + + + /** Create two basic transactions */ } - Log::debug('End of TransactionJournalFactory::create()'); - // invalidate cache. - app('preferences')->mark(); - - return $journals; + // /** @var TransactionFactory $factory */ + // $factory = app(TransactionFactory::class); + // $journals = new Collection; + // ; + // $type = $this->findTransactionType($data['type']); + // + // + // + // $factory->setUser($this->user); + // + // Log::debug(sprintf('New journal(group): %s with description "%s"', $type->type, $description)); + // + // // loop each transaction. + // /** + // * @var int $index + // * @var array $transactionData + // */ + // foreach ($data['transactions'] as $index => $transactionData) { + // Log::debug(sprintf('Now at journal #%d from %d', $index + 1, count($data['transactions']))); + // + // // catch to stop empty amounts: + // if ('' === (string)$transactionData['amount'] || 0.0 === (float)$transactionData['amount']) { + // continue; + // } + // // currency & foreign currency + // $transactionData['currency'] = $this->getCurrency($transactionData, $index); + // $transactionData['foreign_currency'] = $this->getForeignCurrency($transactionData, $index); + // + // // store basic journal first. + // $journal = TransactionJournal::create( + // [ + // 'user_id' => $data['user'], + // 'transaction_type_id' => $type->id, + // 'bill_id' => null, + // 'transaction_currency_id' => $transactionData['currency']->id, + // 'description' => $description, + // 'date' => $carbon->format('Y-m-d H:i:s'), + // 'order' => 0, + // 'tag_count' => 0, + // 'completed' => 0, + // ] + // ); + // Log::debug(sprintf('Stored journal under ID #%d', $journal->id)); + // + // // store transactions for this journal: + // $factory->createPair($journal, $transactionData); + // + // // link bill + // Log::debug('Connect bill'); + // $this->connectBill($journal, $transactionData); + // + // // link piggy bank (if transfer) + // $this->connectPiggyBank($journal, $transactionData); + // + // // link tags + // $this->connectTags($journal, $transactionData); + // + // // store note + // $this->storeNote($journal, $transactionData['notes']); + // + // // save journal: + // $journal->completed = true; + // $journal->save(); + // + // + // + // // if ($journal->transactionType->type !== TransactionType::WITHDRAWAL) { + // // $transactionData['budget_id'] = null; + // // $transactionData['budget_name'] = null; + // // } + // // // save budget TODO + // // $budget = $this->findBudget($data['budget_id'], $data['budget_name']); + // // $this->setBudget($journal, $budget); + // // + // // // set category TODO + // // $category = $this->findCategory($data['category_id'], $data['category_name']); + // // $this->setCategory($journal, $category); + // // + // // // store meta data TODO + // // foreach ($this->fields as $field) { + // // $this->storeMeta($journal, $data, $field); + // // } + // + // // add to array + // $journals->push($journal); + // } + // + // // create group if necessary + // if ($journals->count() > 1) { + // $group = new TransactionGroup; + // $group->user()->associate($this->user); + // $group->title = $description; + // $group->save(); + // $group->transactionJournals()->saveMany($journals); + // + // Log::debug(sprintf('More than one journal, created group #%d.', $group->id)); + // } + // + // + // Log::debug('End of TransactionJournalFactory::create()'); + // // invalidate cache. + // app('preferences')->mark(); + // + // return $journals; } @@ -181,148 +241,167 @@ class TransactionJournalFactory public function setUser(User $user): void { $this->user = $user; + $this->currencyRepository->setUser($this->user); + $this->transactionFactory->setUser($this->user); } - /** - * Link a piggy bank to this journal. - * - * @param TransactionJournal $journal - * @param array $data - */ - protected function connectPiggyBank(TransactionJournal $journal, array $data): void - { - /** @var PiggyBankFactory $factory */ - $factory = app(PiggyBankFactory::class); - $factory->setUser($this->user); - - $piggyBank = $factory->find($data['piggy_bank_id'], $data['piggy_bank_name']); - if (null !== $piggyBank) { - /** @var PiggyBankEventFactory $factory */ - $factory = app(PiggyBankEventFactory::class); - $factory->create($journal, $piggyBank); - } - } - - /** - * @param array $data - * @param int $index - * - * @return TransactionCurrency - */ - private function getCurrency(array $data, int $index): TransactionCurrency - { - // first check the transaction row itself. - $row = $data['transactions'][$index]; - $currency = null; - - // check currency object: - if (null === $currency && isset($row['currency']) && $row['currency'] instanceof TransactionCurrency) { - $currency = $row['currency']; - } - - // check currency ID: - if (null === $currency && isset($row['currency_id']) && (int)$row['currency_id'] > 0) { - $currencyId = (int)$row['currency_id']; - $currency = TransactionCurrency::find($currencyId); - } - - // check currency code - if (null === $currency && isset($row['currency_code']) && 3 === \strlen($row['currency_code'])) { - $currency = TransactionCurrency::whereCode($row['currency_code'])->first(); - } - - // continue with journal itself. - - // check currency object: - if (null === $currency && isset($data['currency']) && $data['currency'] instanceof TransactionCurrency) { - $currency = $data['currency']; - } - - // check currency ID: - if (null === $currency && isset($data['currency_id']) && (int)$data['currency_id'] > 0) { - $currencyId = (int)$data['currency_id']; - $currency = TransactionCurrency::find($currencyId); - } - - // check currency code - if (null === $currency && isset($data['currency_code']) && 3 === \strlen($data['currency_code'])) { - $currency = TransactionCurrency::whereCode($data['currency_code'])->first(); - } - if (null === $currency) { - // return user's default currency: - $currency = app('amount')->getDefaultCurrencyByUser($this->user); - } - - // enable currency: - if (false === $currency->enabled) { - $currency->enabled = true; - $currency->save(); - } - Log::debug(sprintf('Journal currency will be #%d (%s)', $currency->id, $currency->code)); - - return $currency; - - } - - /** - * @param array $data - * @param int $index - * - * @return TransactionCurrency|null - */ - private function getForeignCurrency(array $data, int $index): ?TransactionCurrency - { - // first check the transaction row itself. - $row = $data['transactions'][$index]; - $currency = null; - - // check currency object: - if (null === $currency && isset($row['foreign_currency']) && $row['foreign_currency'] instanceof TransactionCurrency) { - $currency = $row['foreign_currency']; - } - - // check currency ID: - if (null === $currency && isset($row['foreign_currency_id']) && (int)$row['foreign_currency_id'] > 0) { - $currencyId = (int)$row['foreign_currency_id']; - $currency = TransactionCurrency::find($currencyId); - } - - // check currency code - if (null === $currency && isset($row['foreign_currency_code']) && 3 === \strlen($row['foreign_currency_code'])) { - $currency = TransactionCurrency::whereCode($row['foreign_currency_code'])->first(); - } - - // continue with journal itself. - - // check currency object: - if (null === $currency && isset($data['foreign_currency']) && $data['foreign_currency'] instanceof TransactionCurrency) { - $currency = $data['foreign_currency']; - } - - // check currency ID: - if (null === $currency && isset($data['foreign_currency_id']) && (int)$data['foreign_currency_id'] > 0) { - $currencyId = (int)$data['foreign_currency_id']; - $currency = TransactionCurrency::find($currencyId); - } - - // check currency code - if (null === $currency && isset($data['foreign_currency_code']) && 3 === \strlen($data['foreign_currency_code'])) { - $currency = TransactionCurrency::whereCode($data['foreign_currency_code'])->first(); - } - - // enable currency: - if (null !== $currency && false === $currency->enabled) { - $currency->enabled = true; - $currency->save(); - } - if (null !== $currency) { - Log::debug(sprintf('Journal foreign currency will be #%d (%s)', $currency->id, $currency->code)); - } - if (null === $currency) { - Log::debug('Journal foreign currency will be NULL'); - } - - return $currency; - } + // /** + // * Connect bill if present. + // * + // * @param TransactionJournal $journal + // * @param array $data + // */ + // protected function connectBill(TransactionJournal $journal, array $data): void + // { + // if (!$journal->isWithdrawal()) { + // Log::debug(sprintf('Journal #%d is not a withdrawal', $journal->id)); + // + // return; + // } + // /** @var BillFactory $factory */ + // $factory = app(BillFactory::class); + // $factory->setUser($journal->user); + // + // $bill = null; + // + // if (isset($data['bill']) && $data['bill'] instanceof Bill && $data['bill']->user_id === $this->user->id) { + // Log::debug('Bill object found and belongs to user'); + // $bill = $data['bill']; + // } + // if (null === $data['bill']) { + // Log::debug('Bill object not found, search by bill data.'); + // $bill = $factory->find((int)$data['bill_id'], $data['bill_name']); + // } + // + // if (null !== $bill) { + // Log::debug(sprintf('Connected bill #%d (%s) to journal #%d', $bill->id, $bill->name, $journal->id)); + // $journal->bill_id = $bill->id; + // $journal->save(); + // + // return; + // } + // Log::debug('Bill data is NULL.'); + // $journal->bill_id = null; + // $journal->save(); + // + // } + // + // /** + // * Link a piggy bank to this journal. + // * + // * @param TransactionJournal $journal + // * @param array $data + // */ + // protected function connectPiggyBank(TransactionJournal $journal, array $data): void + // { + // if (!$journal->isTransfer()) { + // + // return; + // } + // /** @var PiggyBankFactory $factory */ + // $factory = app(PiggyBankFactory::class); + // $factory->setUser($this->user); + // $piggyBank = null; + // + // if (isset($data['piggy_bank']) && $data['piggy_bank'] instanceof PiggyBank && $data['piggy_bank']->account->user_id === $this->user->id) { + // Log::debug('Piggy found and belongs to user'); + // $piggyBank = $data['piggy_bank']; + // } + // if (null === $data['piggy_bank']) { + // Log::debug('Piggy not found, search by piggy data.'); + // $piggyBank = $factory->find($data['piggy_bank_id'], $data['piggy_bank_name']); + // } + // + // if (null !== $piggyBank) { + // /** @var PiggyBankEventFactory $factory */ + // $factory = app(PiggyBankEventFactory::class); + // $factory->create($journal, $piggyBank); + // Log::debug('Create piggy event.'); + // + // return; + // } + // Log::debug('Create no piggy event'); + // } + // + // /** + // * @param array $data + // * @param int $index + // * + // * @return TransactionCurrency + // */ + // private function getCurrency(array $data, int $index): TransactionCurrency + // { + // $currency = null; + // // check currency object: + // if (null === $currency && isset($data['currency']) && $data['currency'] instanceof TransactionCurrency) { + // $currency = $data['currency']; + // } + // + // // check currency ID: + // if (null === $currency && isset($data['currency_id']) && (int)$data['currency_id'] > 0) { + // $currencyId = (int)$data['currency_id']; + // $currency = TransactionCurrency::find($currencyId); + // } + // + // // check currency code + // if (null === $currency && isset($data['currency_code']) && 3 === \strlen($data['currency_code'])) { + // $currency = TransactionCurrency::whereCode($data['currency_code'])->first(); + // } + // if (null === $currency) { + // // return user's default currency: + // $currency = app('amount')->getDefaultCurrencyByUser($this->user); + // } + // + // // enable currency: + // if (false === $currency->enabled) { + // $currency->enabled = true; + // $currency->save(); + // } + // Log::debug(sprintf('Journal currency will be #%d (%s)', $currency->id, $currency->code)); + // + // return $currency; + // + // } + // + // /** + // * @param array $data + // * @param int $index + // * + // * @return TransactionCurrency|null + // */ + // private function getForeignCurrency(array $data, int $index): ?TransactionCurrency + // { + // $currency = null; + // + // // check currency object: + // if (null === $currency && isset($data['foreign_currency']) && $data['foreign_currency'] instanceof TransactionCurrency) { + // $currency = $data['foreign_currency']; + // } + // + // // check currency ID: + // if (null === $currency && isset($data['foreign_currency_id']) && (int)$data['foreign_currency_id'] > 0) { + // $currencyId = (int)$data['foreign_currency_id']; + // $currency = TransactionCurrency::find($currencyId); + // } + // + // // check currency code + // if (null === $currency && isset($data['foreign_currency_code']) && 3 === \strlen($data['foreign_currency_code'])) { + // $currency = TransactionCurrency::whereCode($data['foreign_currency_code'])->first(); + // } + // + // // enable currency: + // if (null !== $currency && false === $currency->enabled) { + // $currency->enabled = true; + // $currency->save(); + // } + // if (null !== $currency) { + // Log::debug(sprintf('Journal foreign currency will be #%d (%s)', $currency->id, $currency->code)); + // } + // if (null === $currency) { + // Log::debug('Journal foreign currency will be NULL'); + // } + // + // return $currency; + // } } diff --git a/app/Providers/FireflyServiceProvider.php b/app/Providers/FireflyServiceProvider.php index fe10390d62..ade39b6866 100644 --- a/app/Providers/FireflyServiceProvider.php +++ b/app/Providers/FireflyServiceProvider.php @@ -45,6 +45,8 @@ use FireflyIII\Helpers\Report\PopupReport; use FireflyIII\Helpers\Report\PopupReportInterface; use FireflyIII\Helpers\Report\ReportHelper; use FireflyIII\Helpers\Report\ReportHelperInterface; +use FireflyIII\Repositories\TransactionType\TransactionTypeRepository; +use FireflyIII\Repositories\TransactionType\TransactionTypeRepositoryInterface; use FireflyIII\Repositories\User\UserRepository; use FireflyIII\Repositories\User\UserRepositoryInterface; use FireflyIII\Services\Currency\ExchangeRateInterface; @@ -71,8 +73,6 @@ use FireflyIII\Validation\FireflyValidator; use Illuminate\Foundation\Application; use Illuminate\Support\ServiceProvider; use Twig; -use Twig_Extension_Debug; -use TwigBridge\Extension\Loader\Functions; use Validator; /** @@ -176,6 +176,7 @@ class FireflyServiceProvider extends ServiceProvider // export: $this->app->bind(ProcessorInterface::class, ExpandedProcessor::class); $this->app->bind(UserRepositoryInterface::class, UserRepository::class); + $this->app->bind(TransactionTypeRepositoryInterface::class, TransactionTypeRepository::class); $this->app->bind(AttachmentHelperInterface::class, AttachmentHelper::class); // more generators: diff --git a/app/Repositories/Currency/CurrencyRepository.php b/app/Repositories/Currency/CurrencyRepository.php index 8a6575f39d..306a05a5e9 100644 --- a/app/Repositories/Currency/CurrencyRepository.php +++ b/app/Repositories/Currency/CurrencyRepository.php @@ -255,6 +255,41 @@ class CurrencyRepository implements CurrencyRepositoryInterface return TransactionCurrency::whereSymbol($currencySymbol)->first(); } + /** + * Find by object, ID or code. Returns user default or system default. + * + * @param TransactionCurrency|null $currency + * @param int|null $currencyId + * @param string|null $currencyCode + * + * @return TransactionCurrency|null + */ + public function findCurrency(?TransactionCurrency $currency, ?int $currencyId, ?string $currencyCode): TransactionCurrency + { + $result = null; + if (null !== $currency) { + $result = $currency; + } + + if (null === $result) { + $result = $this->find((int)$currencyId); + } + if (null === $result) { + $result = $this->findByCode((string)$currencyCode); + } + if (null === $result) { + $result = app('amount')->getDefaultCurrencyByUser($this->user); + } + if (null === $result) { + $result = $this->findByCode('EUR'); + } + if (false === $result->enabled) { + $this->enable($result); + } + + return $result; + } + /** * Find by ID, return NULL if not found. * Used in Import Currency! diff --git a/app/Repositories/Currency/CurrencyRepositoryInterface.php b/app/Repositories/Currency/CurrencyRepositoryInterface.php index 0adb767196..665ff6633c 100644 --- a/app/Repositories/Currency/CurrencyRepositoryInterface.php +++ b/app/Repositories/Currency/CurrencyRepositoryInterface.php @@ -132,6 +132,17 @@ interface CurrencyRepositoryInterface */ public function findBySymbolNull(string $currencySymbol): ?TransactionCurrency; + /** + * Find by object, ID or code. Returns user default or system default. + * + * @param TransactionCurrency|null $currency + * @param int|null $currencyId + * @param string|null $currencyCode + * + * @return TransactionCurrency|null + */ + public function findCurrency(?TransactionCurrency $currency, ?int $currencyId, ?string $currencyCode): TransactionCurrency; + /** * Find by ID, return NULL if not found. * diff --git a/app/Repositories/TransactionType/TransactionTypeRepository.php b/app/Repositories/TransactionType/TransactionTypeRepository.php new file mode 100644 index 0000000000..899577b846 --- /dev/null +++ b/app/Repositories/TransactionType/TransactionTypeRepository.php @@ -0,0 +1,64 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Repositories\TransactionType; + +use FireflyIII\Models\TransactionType; + +/** + * Class TransactionTypeRepository + */ +class TransactionTypeRepository implements TransactionTypeRepositoryInterface +{ + + /** + * @param string $type + * + * @return TransactionType|null + */ + public function findByType(string $type): ?TransactionType + { + $search = ucfirst($type); + + return TransactionType::whereType($search)->first(); + } + + /** + * @param TransactionType|null $type + * @param string|null $typeString + * + * @return TransactionType + */ + public function findTransactionType(?TransactionType $type, ?string $typeString): TransactionType + { + if (null !== $type) { + return $type; + } + $search = $this->findByType($typeString); + if (null === $search) { + $search = $this->findByType(TransactionType::WITHDRAWAL); + } + + return $search; + } +} \ No newline at end of file diff --git a/app/Repositories/TransactionType/TransactionTypeRepositoryInterface.php b/app/Repositories/TransactionType/TransactionTypeRepositoryInterface.php new file mode 100644 index 0000000000..d6e4f2679f --- /dev/null +++ b/app/Repositories/TransactionType/TransactionTypeRepositoryInterface.php @@ -0,0 +1,47 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Repositories\TransactionType; + +use FireflyIII\Models\TransactionType; + +/** + * Interface TransactionTypeRepositoryInterface + */ +interface TransactionTypeRepositoryInterface +{ + /** + * @param TransactionType|null $type + * @param string|null $typeString + * + * @return TransactionType + */ + public function findTransactionType(?TransactionType $type, ?string $typeString): TransactionType; + + /** + * @param string $type + * + * @return TransactionType|null + */ + public function findByType(string $type): ?TransactionType; +} \ No newline at end of file diff --git a/app/Services/Internal/Support/JournalServiceTrait.php b/app/Services/Internal/Support/JournalServiceTrait.php index 32e07438c6..0373ea19ce 100644 --- a/app/Services/Internal/Support/JournalServiceTrait.php +++ b/app/Services/Internal/Support/JournalServiceTrait.php @@ -29,6 +29,7 @@ use FireflyIII\Factory\BudgetFactory; use FireflyIII\Factory\CategoryFactory; use FireflyIII\Factory\TagFactory; use FireflyIII\Factory\TransactionJournalMetaFactory; +use FireflyIII\Models\Bill; use FireflyIII\Models\Budget; use FireflyIII\Models\Category; use FireflyIII\Models\Note; @@ -59,7 +60,7 @@ trait JournalServiceTrait return; // @codeCoverageIgnore } foreach ($data['tags'] as $string) { - if ('' != $string) { + if ('' !== $string) { $tag = $factory->findOrCreate($string); if (null !== $tag) { $set[] = $tag->id; @@ -69,29 +70,6 @@ trait JournalServiceTrait $journal->tags()->sync($set); } - /** - * Connect bill if present. - * - * @param TransactionJournal $journal - * @param array $data - */ - protected function connectBill(TransactionJournal $journal, array $data): void - { - /** @var BillFactory $factory */ - $factory = app(BillFactory::class); - $factory->setUser($journal->user); - $bill = $factory->find((int)$data['bill_id'], $data['bill_name']); - - if (null !== $bill) { - $journal->bill_id = $bill->id; - $journal->save(); - - return; - } - $journal->bill_id = null; - $journal->save(); - - } /** * @param int|null $budgetId diff --git a/app/Services/Internal/Support/TransactionServiceTrait.php b/app/Services/Internal/Support/TransactionServiceTrait.php index 3a39fdb3fa..2cb72011c4 100644 --- a/app/Services/Internal/Support/TransactionServiceTrait.php +++ b/app/Services/Internal/Support/TransactionServiceTrait.php @@ -25,13 +25,9 @@ namespace FireflyIII\Services\Internal\Support; use FireflyIII\Factory\AccountFactory; -use FireflyIII\Factory\BudgetFactory; -use FireflyIII\Factory\CategoryFactory; use FireflyIII\Factory\TransactionCurrencyFactory; use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; -use FireflyIII\Models\Budget; -use FireflyIII\Models\Category; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionJournal; @@ -86,8 +82,14 @@ trait TransactionServiceTrait * @throws \FireflyIII\Exceptions\FireflyException * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ - public function findAccount(?string $expectedType, ?int $accountId, ?string $accountName): ?Account + public function findAccount(?string $expectedType, ?Account $account, ?int $accountId, ?string $accountName): ?Account { + $result = null; + + if (null !== $account && $account->user_id === $this->user->id) { + return $account; + } + $accountId = (int)$accountId; $accountName = (string)$accountName; $repository = app(AccountRepositoryInterface::class);