diff --git a/app/Services/Internal/Destroy/AccountDestroyService.php b/app/Services/Internal/Destroy/AccountDestroyService.php index 80c8b1d301..b54bc98ded 100644 --- a/app/Services/Internal/Destroy/AccountDestroyService.php +++ b/app/Services/Internal/Destroy/AccountDestroyService.php @@ -76,28 +76,6 @@ class AccountDestroyService } } - /** - * @param Account $account - */ - private function destroyJournals(Account $account): void - { - - /** @var JournalDestroyService $service */ - $service = app(JournalDestroyService::class); - - Log::debug('Now trigger account delete response #' . $account->id); - /** @var Transaction $transaction */ - foreach ($account->transactions()->get() as $transaction) { - Log::debug('Now at transaction #' . $transaction->id); - /** @var TransactionJournal $journal */ - $journal = $transaction->transactionJournal()->first(); - if (null !== $journal) { - Log::debug('Call for deletion of journal #' . $journal->id); - $service->destroy($journal); - } - } - } - /** * @param Account $account */ @@ -135,6 +113,47 @@ class AccountDestroyService } } + /** + * @param Account $account + * @param Account $moveTo + */ + private function moveTransactions(Account $account, Account $moveTo): void + { + DB::table('transactions')->where('account_id', $account->id)->update(['account_id' => $moveTo->id]); + } + + /** + * @param Account $account + * @param Account $moveTo + */ + private function updateRecurrences(Account $account, Account $moveTo): void + { + DB::table('recurrences_transactions')->where('source_id', $account->id)->update(['source_id' => $moveTo->id]); + DB::table('recurrences_transactions')->where('destination_id', $account->id)->update(['destination_id' => $moveTo->id]); + } + + /** + * @param Account $account + */ + private function destroyJournals(Account $account): void + { + + /** @var JournalDestroyService $service */ + $service = app(JournalDestroyService::class); + + Log::debug('Now trigger account delete response #' . $account->id); + /** @var Transaction $transaction */ + foreach ($account->transactions()->get() as $transaction) { + Log::debug('Now at transaction #' . $transaction->id); + /** @var TransactionJournal $journal */ + $journal = $transaction->transactionJournal()->first(); + if (null !== $journal) { + Log::debug('Call for deletion of journal #' . $journal->id); + $service->destroy($journal); + } + } + } + /** * @param Account $account */ @@ -155,24 +174,4 @@ class AccountDestroyService } } - - /** - * @param Account $account - * @param Account $moveTo - */ - private function moveTransactions(Account $account, Account $moveTo): void - { - DB::table('transactions')->where('account_id', $account->id)->update(['account_id' => $moveTo->id]); - } - - /** - * @param Account $account - * @param Account $moveTo - */ - private function updateRecurrences(Account $account, Account $moveTo): void - { - DB::table('recurrences_transactions')->where('source_id', $account->id)->update(['source_id' => $moveTo->id]); - DB::table('recurrences_transactions')->where('destination_id', $account->id)->update(['destination_id' => $moveTo->id]); - } - } diff --git a/app/Services/Internal/Destroy/BudgetDestroyService.php b/app/Services/Internal/Destroy/BudgetDestroyService.php index 41280b83fb..3fb5897e05 100644 --- a/app/Services/Internal/Destroy/BudgetDestroyService.php +++ b/app/Services/Internal/Destroy/BudgetDestroyService.php @@ -30,6 +30,7 @@ use Log; /** * Class BudgetDestroyService + * * @codeCoverageIgnore */ class BudgetDestroyService diff --git a/app/Services/Internal/Destroy/CategoryDestroyService.php b/app/Services/Internal/Destroy/CategoryDestroyService.php index 75ae8e5010..a161b16770 100644 --- a/app/Services/Internal/Destroy/CategoryDestroyService.php +++ b/app/Services/Internal/Destroy/CategoryDestroyService.php @@ -30,6 +30,7 @@ use Log; /** * Class CategoryDestroyService + * * @codeCoverageIgnore */ class CategoryDestroyService diff --git a/app/Services/Internal/Destroy/CurrencyDestroyService.php b/app/Services/Internal/Destroy/CurrencyDestroyService.php index bdec425c5d..358f223246 100644 --- a/app/Services/Internal/Destroy/CurrencyDestroyService.php +++ b/app/Services/Internal/Destroy/CurrencyDestroyService.php @@ -29,6 +29,7 @@ use Log; /** * Class CurrencyDestroyService + * * @codeCoverageIgnore */ class CurrencyDestroyService diff --git a/app/Services/Internal/Destroy/RecurrenceDestroyService.php b/app/Services/Internal/Destroy/RecurrenceDestroyService.php index 6e704bbb2b..3f7ce76bc7 100644 --- a/app/Services/Internal/Destroy/RecurrenceDestroyService.php +++ b/app/Services/Internal/Destroy/RecurrenceDestroyService.php @@ -34,6 +34,21 @@ use Log; */ class RecurrenceDestroyService { + /** + * Delete recurrence by ID + * + * @param int $recurrenceId + */ + public function destroyById(int $recurrenceId): void + { + $recurrence = Recurrence::find($recurrenceId); + if (null === $recurrence) { + return; + } + $this->destroy($recurrence); + + } + /** * Delete recurrence. * @@ -69,19 +84,4 @@ class RecurrenceDestroyService } } - /** - * Delete recurrence by ID - * - * @param int $recurrenceId - */ - public function destroyById(int $recurrenceId): void - { - $recurrence = Recurrence::find($recurrenceId); - if (null === $recurrence) { - return; - } - $this->destroy($recurrence); - - } - } diff --git a/app/Services/Internal/Destroy/TransactionGroupDestroyService.php b/app/Services/Internal/Destroy/TransactionGroupDestroyService.php index f39269d43a..e04736266a 100644 --- a/app/Services/Internal/Destroy/TransactionGroupDestroyService.php +++ b/app/Services/Internal/Destroy/TransactionGroupDestroyService.php @@ -28,6 +28,7 @@ use FireflyIII\Models\TransactionGroup; /** * Class TransactionGroupDestroyService + * * @codeCoverageIgnore */ class TransactionGroupDestroyService diff --git a/app/Services/Internal/Support/AccountServiceTrait.php b/app/Services/Internal/Support/AccountServiceTrait.php index 563d2b89aa..a7ca109c2f 100644 --- a/app/Services/Internal/Support/AccountServiceTrait.php +++ b/app/Services/Internal/Support/AccountServiceTrait.php @@ -71,6 +71,32 @@ trait AccountServiceTrait return $iban; } + /** + * Returns true if the data in the array is submitted but empty. + * + * @param array $data + * + * @return bool + */ + public function isEmptyOBData(array $data): bool + { + if (!array_key_exists('opening_balance', $data) + && !array_key_exists('opening_balance_date', $data) + ) { + // not set, so false. + return false; + } + // if isset, but is empty: + if ( + (array_key_exists('opening_balance', $data) && '' === $data['opening_balance']) + || (array_key_exists('opening_balance_date', $data) && '' === $data['opening_balance_date']) + ) { + return true; + } + + return false; + } + /** * Update meta data for account. Depends on type which fields are valid. * @@ -173,29 +199,122 @@ trait AccountServiceTrait } /** - * Returns true if the data in the array is submitted but empty. + * Delete TransactionGroup with opening balance in it. * - * @param array $data - * - * @return bool + * @param Account $account */ - public function isEmptyOBData(array $data): bool + protected function deleteOBGroup(Account $account): void { - if (!array_key_exists('opening_balance', $data) - && !array_key_exists('opening_balance_date', $data) - ) { - // not set, so false. - return false; + Log::debug(sprintf('deleteOB() for account #%d', $account->id)); + $openingBalanceGroup = $this->getOBGroup($account); + + // opening balance data? update it! + if (null !== $openingBalanceGroup) { + Log::debug('Opening balance journal found, delete journal.'); + /** @var TransactionGroupDestroyService $service */ + $service = app(TransactionGroupDestroyService::class); + $service->destroy($openingBalanceGroup); } - // if isset, but is empty: - if ( - (array_key_exists('opening_balance', $data) && '' === $data['opening_balance']) - || (array_key_exists('opening_balance_date', $data) && '' === $data['opening_balance_date']) - ) { - return true; + } + + /** + * Returns the opening balance group, or NULL if it does not exist. + * + * @param Account $account + * + * @return TransactionGroup|null + */ + protected function getOBGroup(Account $account): ?TransactionGroup + { + return $this->accountRepository->getOpeningBalanceGroup($account); + } + + /** + * @param int $currencyId + * @param string $currencyCode + * + * @return TransactionCurrency + */ + protected function getCurrency(int $currencyId, string $currencyCode): TransactionCurrency + { + // find currency, or use default currency instead. + /** @var TransactionCurrencyFactory $factory */ + $factory = app(TransactionCurrencyFactory::class); + /** @var TransactionCurrency $currency */ + $currency = $factory->find($currencyId, $currencyCode); + + if (null === $currency) { + // use default currency: + $currency = app('amount')->getDefaultCurrencyByUser($this->user); + } + $currency->enabled = true; + $currency->save(); + + return $currency; + } + + /** + * Update or create the opening balance group. Assumes valid data in $data. + * + * Returns null if this fails. + * + * @param Account $account + * @param array $data + * + * @return TransactionGroup|null + */ + protected function updateOBGroup(Account $account, array $data): ?TransactionGroup + { + $obGroup = $this->getOBGroup($account); + if (null === $obGroup) { + return $this->createOBGroup($account, $data); } - return false; + // $data['currency_id'] is empty so creating a new journal may break. + if (!array_key_exists('currency_id', $data)) { + $currency = $this->accountRepository->getAccountCurrency($account); + if (null === $currency) { + $currency = app('default')->getDefaultCurrencyByUser($account->user); + } + $data['currency_id'] = $currency->id; + } + + /** @var TransactionJournal $journal */ + $journal = $obGroup->transactionJournals()->first(); + $journal->date = $data['opening_balance_date'] ?? $journal->date; + $journal->transaction_currency_id = $data['currency_id']; + + /** @var Transaction $obTransaction */ + $obTransaction = $journal->transactions()->where('account_id', '!=', $account->id)->first(); + /** @var Transaction $accountTransaction */ + $accountTransaction = $journal->transactions()->where('account_id', $account->id)->first(); + + // if amount is negative: + if (1 === bccomp('0', $data['opening_balance'])) { + // account transaction loses money: + $accountTransaction->amount = app('steam')->negative($data['opening_balance']); + $accountTransaction->transaction_currency_id = $data['currency_id']; + + // OB account transaction gains money + $obTransaction->amount = app('steam')->positive($data['opening_balance']); + $obTransaction->transaction_currency_id = $data['currency_id']; + } + if (-1 === bccomp('0', $data['opening_balance'])) { + // account gains money: + $accountTransaction->amount = app('steam')->positive($data['opening_balance']); + $accountTransaction->transaction_currency_id = $data['currency_id']; + + // OB account loses money: + $obTransaction->amount = app('steam')->negative($data['opening_balance']); + $obTransaction->transaction_currency_id = $data['currency_id']; + } + // save both + $accountTransaction->save(); + $obTransaction->save(); + $journal->save(); + $obGroup->refresh(); + + return $obGroup; } /** @@ -288,123 +407,4 @@ trait AccountServiceTrait return $group; } - - /** - * Delete TransactionGroup with opening balance in it. - * - * @param Account $account - */ - protected function deleteOBGroup(Account $account): void - { - Log::debug(sprintf('deleteOB() for account #%d', $account->id)); - $openingBalanceGroup = $this->getOBGroup($account); - - // opening balance data? update it! - if (null !== $openingBalanceGroup) { - Log::debug('Opening balance journal found, delete journal.'); - /** @var TransactionGroupDestroyService $service */ - $service = app(TransactionGroupDestroyService::class); - $service->destroy($openingBalanceGroup); - } - } - - /** - * @param int $currencyId - * @param string $currencyCode - * - * @return TransactionCurrency - */ - protected function getCurrency(int $currencyId, string $currencyCode): TransactionCurrency - { - // find currency, or use default currency instead. - /** @var TransactionCurrencyFactory $factory */ - $factory = app(TransactionCurrencyFactory::class); - /** @var TransactionCurrency $currency */ - $currency = $factory->find($currencyId, $currencyCode); - - if (null === $currency) { - // use default currency: - $currency = app('amount')->getDefaultCurrencyByUser($this->user); - } - $currency->enabled = true; - $currency->save(); - - return $currency; - } - - /** - * Returns the opening balance group, or NULL if it does not exist. - * - * @param Account $account - * - * @return TransactionGroup|null - */ - protected function getOBGroup(Account $account): ?TransactionGroup - { - return $this->accountRepository->getOpeningBalanceGroup($account); - } - - /** - * Update or create the opening balance group. Assumes valid data in $data. - * - * Returns null if this fails. - * - * @param Account $account - * @param array $data - * - * @return TransactionGroup|null - */ - protected function updateOBGroup(Account $account, array $data): ?TransactionGroup - { - $obGroup = $this->getOBGroup($account); - if (null === $obGroup) { - return $this->createOBGroup($account, $data); - } - - // $data['currency_id'] is empty so creating a new journal may break. - if (!array_key_exists('currency_id', $data)) { - $currency = $this->accountRepository->getAccountCurrency($account); - if (null === $currency) { - $currency = app('default')->getDefaultCurrencyByUser($account->user); - } - $data['currency_id'] = $currency->id; - } - - /** @var TransactionJournal $journal */ - $journal = $obGroup->transactionJournals()->first(); - $journal->date = $data['opening_balance_date'] ?? $journal->date; - $journal->transaction_currency_id = $data['currency_id']; - - /** @var Transaction $obTransaction */ - $obTransaction = $journal->transactions()->where('account_id', '!=', $account->id)->first(); - /** @var Transaction $accountTransaction */ - $accountTransaction = $journal->transactions()->where('account_id', $account->id)->first(); - - // if amount is negative: - if (1 === bccomp('0', $data['opening_balance'])) { - // account transaction loses money: - $accountTransaction->amount = app('steam')->negative($data['opening_balance']); - $accountTransaction->transaction_currency_id = $data['currency_id']; - - // OB account transaction gains money - $obTransaction->amount = app('steam')->positive($data['opening_balance']); - $obTransaction->transaction_currency_id = $data['currency_id']; - } - if (-1 === bccomp('0', $data['opening_balance'])) { - // account gains money: - $accountTransaction->amount = app('steam')->positive($data['opening_balance']); - $accountTransaction->transaction_currency_id = $data['currency_id']; - - // OB account loses money: - $obTransaction->amount = app('steam')->negative($data['opening_balance']); - $obTransaction->transaction_currency_id = $data['currency_id']; - } - // save both - $accountTransaction->save(); - $obTransaction->save(); - $journal->save(); - $obGroup->refresh(); - - return $obGroup; - } } diff --git a/app/Services/Internal/Support/BillServiceTrait.php b/app/Services/Internal/Support/BillServiceTrait.php index b5b32ecbca..652fe9117d 100644 --- a/app/Services/Internal/Support/BillServiceTrait.php +++ b/app/Services/Internal/Support/BillServiceTrait.php @@ -32,6 +32,7 @@ use Log; /** * Trait BillServiceTrait + * * @codeCoverageIgnore */ trait BillServiceTrait diff --git a/app/Services/Internal/Support/JournalServiceTrait.php b/app/Services/Internal/Support/JournalServiceTrait.php index 7269164502..c7387435bc 100644 --- a/app/Services/Internal/Support/JournalServiceTrait.php +++ b/app/Services/Internal/Support/JournalServiceTrait.php @@ -49,35 +49,6 @@ trait JournalServiceTrait private CategoryRepositoryInterface $categoryRepository; private TagFactory $tagFactory; - - /** - * @param string|null $amount - * - * @return string - * @codeCoverageIgnore - */ - protected function getForeignAmount(?string $amount): ?string - { - if (null === $amount) { - Log::debug('No foreign amount info in array. Return NULL'); - - return null; - } - if ('' === $amount) { - Log::debug('Foreign amount is empty string, return NULL.'); - - return null; - } - if (0 === bccomp('0', $amount)) { - Log::debug('Foreign amount is 0.0, return NULL.'); - - return null; - } - Log::debug(sprintf('Foreign amount is %s', $amount)); - - return $amount; - } - /** * @param string $transactionType * @param string $direction @@ -113,6 +84,165 @@ trait JournalServiceTrait return $this->getCashAccount($result, $data, $expectedTypes[$transactionType]); } + /** + * @param array $data + * @param array $types + * + * @return Account|null + */ + private function findAccountById(array $data, array $types): ?Account + { + $search = null; + // first attempt, find by ID. + if (null !== $data['id']) { + $search = $this->accountRepository->findNull($data['id']); + if (null !== $search && in_array($search->accountType->type, $types, true)) { + Log::debug( + sprintf('Found "account_id" object: #%d, "%s" of type %s', $search->id, $search->name, $search->accountType->type) + ); + } + } + + return $search; + } + + /** + * @param Account|null $account + * @param array $data + * @param array $types + * + * @return Account|null + */ + private function findAccountByName(?Account $account, array $data, array $types): ?Account + { + // second attempt, find by name. + if (null === $account && null !== $data['name']) { + Log::debug('Found nothing by account ID.'); + // find by preferred type. + $source = $this->accountRepository->findByName($data['name'], [$types[0]]); + // or any expected type. + $source = $source ?? $this->accountRepository->findByName($data['name'], $types); + + if (null !== $source) { + Log::debug(sprintf('Found "account_name" object: #%d, %s', $source->id, $source->name)); + + $account = $source; + } + } + + return $account; + } + + /** + * @param Account|null $account + * @param array $data + * @param array $types + * + * @return Account|null + */ + private function findAccountByIban(?Account $account, array $data, array $types): ?Account + { + // third attempt, find by IBAN + if (null === $account && null !== $data['iban']) { + Log::debug(sprintf('Found nothing by account iban "%s".', $data['iban'])); + // find by preferred type. + $source = $this->accountRepository->findByIbanNull($data['iban'], [$types[0]]); + // or any expected type. + $source = $source ?? $this->accountRepository->findByIbanNull($data['iban'], $types); + + if (null !== $source) { + Log::debug(sprintf('Found "account_iban" object: #%d, %s', $source->id, $source->name)); + + $account = $source; + } + } + + return $account; + } + + /** + * @param Account|null $account + * @param array $data + * @param string $preferredType + * + * @return Account + * @throws FireflyException + */ + private function createAccount(?Account $account, array $data, string $preferredType): Account + { + Log::debug('Now in createAccount()', $data); + // return new account. + if (null !== $account) { + Log::debug( + sprintf( + 'Was also given %s account #%d ("%s") so will simply return that.', + $account->accountType->type, $account->id, $account->name + + ) + ); + } + if (null === $account) { + + // final attempt, create it. + if (AccountType::ASSET === $preferredType) { + throw new FireflyException('TransactionFactory: Cannot create asset account with these values', $data); + } + // fix name of account if only IBAN is given: + if ('' === (string)$data['name'] && '' !== (string)$data['iban']) { + Log::debug(sprintf('Account name is now IBAN ("%s")', $data['iban'])); + $data['name'] = $data['iban']; + } + + $data['name'] = $data['name'] ?? '(no name)'; + + $account = $this->accountRepository->store( + [ + 'account_type_id' => null, + 'account_type' => $preferredType, + 'name' => $data['name'], + 'virtual_balance' => null, + 'active' => true, + 'iban' => $data['iban'], + 'currency_id' => $data['currency_id'] ?? null, + 'order' => $this->accountRepository->maxOrder($preferredType), + ] + ); + // store BIC + if (null !== $data['bic']) { + /** @var AccountMetaFactory $metaFactory */ + $metaFactory = app(AccountMetaFactory::class); + $metaFactory->create(['account_id' => $account->id, 'name' => 'BIC', 'data' => $data['bic']]); + } + // store account number + if (null !== $data['number']) { + /** @var AccountMetaFactory $metaFactory */ + $metaFactory = app(AccountMetaFactory::class); + $metaFactory->create(['account_id' => $account->id, 'name' => 'account_number', 'data' => $data['bic']]); + } + + } + + return $account; + } + + /** + * @param Account|null $account + * @param array $data + * @param array $types + * + * @return Account|null + */ + private function getCashAccount(?Account $account, array $data, array $types): ?Account + { + // return cash account. + if (null === $account && null === $data['name'] + && in_array(AccountType::CASH, $types, true)) { + $account = $this->accountRepository->getCashAccount(); + } + + return $account; + } + /** * @param string $amount * @@ -132,6 +262,34 @@ trait JournalServiceTrait return $amount; } + /** + * @param string|null $amount + * + * @return string + * @codeCoverageIgnore + */ + protected function getForeignAmount(?string $amount): ?string + { + if (null === $amount) { + Log::debug('No foreign amount info in array. Return NULL'); + + return null; + } + if ('' === $amount) { + Log::debug('Foreign amount is empty string, return NULL.'); + + return null; + } + if (0 === bccomp('0', $amount)) { + Log::debug('Foreign amount is 0.0, return NULL.'); + + return null; + } + Log::debug(sprintf('Foreign amount is %s', $amount)); + + return $amount; + } + /** * @param TransactionJournal $journal * @param NullArrayObject $data @@ -242,163 +400,4 @@ trait JournalServiceTrait $journal->tags()->sync($set); Log::debug('Done!'); } - - /** - * @param array $data - * @param array $types - * - * @return Account|null - */ - private function findAccountById(array $data, array $types): ?Account - { - $search = null; - // first attempt, find by ID. - if (null !== $data['id']) { - $search = $this->accountRepository->findNull($data['id']); - if (null !== $search && in_array($search->accountType->type, $types, true)) { - Log::debug( - sprintf('Found "account_id" object: #%d, "%s" of type %s', $search->id, $search->name, $search->accountType->type) - ); - } - } - - return $search; - } - - /** - * @param Account|null $account - * @param array $data - * @param array $types - * - * @return Account|null - */ - private function findAccountByName(?Account $account, array $data, array $types): ?Account - { - // second attempt, find by name. - if (null === $account && null !== $data['name']) { - Log::debug('Found nothing by account ID.'); - // find by preferred type. - $source = $this->accountRepository->findByName($data['name'], [$types[0]]); - // or any expected type. - $source = $source ?? $this->accountRepository->findByName($data['name'], $types); - - if (null !== $source) { - Log::debug(sprintf('Found "account_name" object: #%d, %s', $source->id, $source->name)); - - $account = $source; - } - } - - return $account; - } - - /** - * @param Account|null $account - * @param array $data - * @param array $types - * - * @return Account|null - */ - private function findAccountByIban(?Account $account, array $data, array $types): ?Account - { - // third attempt, find by IBAN - if (null === $account && null !== $data['iban']) { - Log::debug(sprintf('Found nothing by account iban "%s".', $data['iban'])); - // find by preferred type. - $source = $this->accountRepository->findByIbanNull($data['iban'], [$types[0]]); - // or any expected type. - $source = $source ?? $this->accountRepository->findByIbanNull($data['iban'], $types); - - if (null !== $source) { - Log::debug(sprintf('Found "account_iban" object: #%d, %s', $source->id, $source->name)); - - $account = $source; - } - } - - return $account; - } - - /** - * @param Account|null $account - * @param array $data - * @param array $types - * - * @return Account|null - */ - private function getCashAccount(?Account $account, array $data, array $types): ?Account - { - // return cash account. - if (null === $account && null === $data['name'] - && in_array(AccountType::CASH, $types, true)) { - $account = $this->accountRepository->getCashAccount(); - } - - return $account; - } - - /** - * @param Account|null $account - * @param array $data - * @param string $preferredType - * - * @return Account - * @throws FireflyException - */ - private function createAccount(?Account $account, array $data, string $preferredType): Account - { - Log::debug('Now in createAccount()', $data); - // return new account. - if (null !== $account) { - Log::debug( - sprintf( - 'Was also given %s account #%d ("%s") so will simply return that.', - $account->accountType->type, $account->id, $account->name - - ) - ); - } - if (null === $account) { - - // final attempt, create it. - if (AccountType::ASSET === $preferredType) { - throw new FireflyException('TransactionFactory: Cannot create asset account with these values', $data); - } - // fix name of account if only IBAN is given: - if ('' === (string)$data['name'] && '' !== (string)$data['iban']) { - Log::debug(sprintf('Account name is now IBAN ("%s")', $data['iban'])); - $data['name'] = $data['iban']; - } - - $data['name'] = $data['name'] ?? '(no name)'; - - $account = $this->accountRepository->store( - [ - 'account_type_id' => null, - 'account_type' => $preferredType, - 'name' => $data['name'], - 'virtual_balance' => null, - 'active' => true, - 'iban' => $data['iban'], - 'currency_id' => $data['currency_id'] ?? null, - 'order' => $this->accountRepository->maxOrder($preferredType), - ] - ); - // store BIC - if (null !== $data['bic']) { - /** @var AccountMetaFactory $metaFactory */ - $metaFactory = app(AccountMetaFactory::class); - $metaFactory->create(['account_id' => $account->id, 'name' => 'BIC', 'data' => $data['bic']]); - } - // store account number - if (null !== $data['number']) { - /** @var AccountMetaFactory $metaFactory */ - $metaFactory = app(AccountMetaFactory::class); - $metaFactory->create(['account_id' => $account->id, 'name' => 'account_number', 'data' => $data['bic']]); - } - - } - - return $account; - } } diff --git a/app/Services/Internal/Support/RecurringTransactionTrait.php b/app/Services/Internal/Support/RecurringTransactionTrait.php index 41b03e5407..1699ed945d 100644 --- a/app/Services/Internal/Support/RecurringTransactionTrait.php +++ b/app/Services/Internal/Support/RecurringTransactionTrait.php @@ -51,29 +51,7 @@ trait RecurringTransactionTrait { /** * @param Recurrence $recurrence - * @param array $repetitions - */ - protected function createRepetitions(Recurrence $recurrence, array $repetitions): void - { - /** @var array $array */ - foreach ($repetitions as $array) { - RecurrenceRepetition::create( - [ - 'recurrence_id' => $recurrence->id, - 'repetition_type' => $array['type'], - 'repetition_moment' => $array['moment'] ?? '', - 'repetition_skip' => $array['skip'] ?? 0, - 'weekend' => $array['weekend'] ?? 1, - ] - ); - - } - } - - - /** - * @param Recurrence $recurrence - * @param string $note + * @param string $note * * @return bool */ @@ -102,6 +80,27 @@ trait RecurringTransactionTrait return true; } + /** + * @param Recurrence $recurrence + * @param array $repetitions + */ + protected function createRepetitions(Recurrence $recurrence, array $repetitions): void + { + /** @var array $array */ + foreach ($repetitions as $array) { + RecurrenceRepetition::create( + [ + 'recurrence_id' => $recurrence->id, + 'repetition_type' => $array['type'], + 'repetition_moment' => $array['moment'] ?? '', + 'repetition_skip' => $array['skip'] ?? 0, + 'weekend' => $array['weekend'] ?? 1, + ] + ); + + } + } + /** * Store transactions of a recurring transactions. It's complex but readable. * @@ -138,7 +137,7 @@ trait RecurringTransactionTrait if (!$validator->validateDestination($destination->id, null, null)) { throw new FireflyException(sprintf('Destination invalid: %s', $validator->destError)); // @codeCoverageIgnore } - if(array_key_exists('foreign_amount', $array) && '' === (string)$array['foreign_amount']) { + if (array_key_exists('foreign_amount', $array) && '' === (string)$array['foreign_amount']) { unset($array['foreign_amount']); } // TODO typeOverrule: the account validator may have another opinion on the transaction type. @@ -156,20 +155,11 @@ trait RecurringTransactionTrait ); $transaction->save(); - $budget = null; if (array_key_exists('budget_id', $array)) { - /** @var BudgetFactory $budgetFactory */ - $budgetFactory = app(BudgetFactory::class); - $budgetFactory->setUser($recurrence->user); - $budget = $budgetFactory->find($array['budget_id'], null); + $this->setBudget($transaction, (int)$array['budget_id']); } - - $category = null; if (array_key_exists('category_id', $array)) { - /** @var CategoryFactory $categoryFactory */ - $categoryFactory = app(CategoryFactory::class); - $categoryFactory->setUser($recurrence->user); - $category = $categoryFactory->findOrCreate($array['category_id'], null); + $this->setCategory($transaction, (int)$array['category_id']); } // same for piggy bank @@ -177,57 +167,10 @@ trait RecurringTransactionTrait $this->updatePiggyBank($transaction, (int)$array['piggy_bank_id']); } - if(array_key_exists('tags', $array)) { + if (array_key_exists('tags', $array)) { $this->updateTags($transaction, $array['tags']); } - // create recurrence transaction meta: - if (null !== $budget) { - RecurrenceTransactionMeta::create( - [ - 'rt_id' => $transaction->id, - 'name' => 'budget_id', - 'value' => $budget->id, - ] - ); - } - if (null !== $category) { - RecurrenceTransactionMeta::create( - [ - 'rt_id' => $transaction->id, - 'name' => 'category_name', - 'value' => $category->name, - ] - ); - } - } - } - - /** - * @param Recurrence $recurrence - * - * @codeCoverageIgnore - */ - protected function deleteRepetitions(Recurrence $recurrence): void - { - $recurrence->recurrenceRepetitions()->delete(); - } - - /** - * @param Recurrence $recurrence - * - * @codeCoverageIgnore - */ - protected function deleteTransactions(Recurrence $recurrence): void - { - /** @var RecurrenceTransaction $transaction */ - foreach ($recurrence->recurrenceTransactions as $transaction) { - $transaction->recurrenceTransactionMeta()->delete(); - try { - $transaction->delete(); - } catch (Exception $e) { - Log::debug($e->getMessage()); - } } } @@ -283,6 +226,52 @@ trait RecurringTransactionTrait return $result ?? $repository->getCashAccount(); } + /** + * @param RecurrenceTransaction $transaction + * @param int $budgetId + */ + private function setBudget(RecurrenceTransaction $transaction, int $budgetId): void + { + $budgetFactory = app(BudgetFactory::class); + $budgetFactory->setUser($transaction->recurrence->user); + $budget = $budgetFactory->find($budgetId, null); + if (null === $budget) { + return; + } + + $meta = $transaction->recurrenceTransactionMeta()->where('name', 'budget_id')->first(); + if (null === $meta) { + $meta = new RecurrenceTransactionMeta; + $meta->rt_id = $transaction->id; + $meta->name = 'budget_id'; + } + $meta->value = $budget->id; + $meta->save(); + } + + /** + * @param RecurrenceTransaction $transaction + * @param int $categoryId + */ + private function setCategory(RecurrenceTransaction $transaction, int $categoryId): void + { + $categoryFactory = app(CategoryFactory::class); + $categoryFactory->setUser($transaction->recurrence->user); + $category = $categoryFactory->findOrCreate($categoryId, null); + if (null === $category) { + return; + } + + $meta = $transaction->recurrenceTransactionMeta()->where('name', 'category_id')->first(); + if (null === $meta) { + $meta = new RecurrenceTransactionMeta; + $meta->rt_id = $transaction->id; + $meta->name = 'category_id'; + } + $meta->value = $category->id; + $meta->save(); + } + /** * @param RecurrenceTransaction $transaction * @param int $piggyId @@ -328,4 +317,32 @@ trait RecurringTransactionTrait $transaction->recurrenceTransactionMeta()->where('name', 'tags')->delete(); } } + + /** + * @param Recurrence $recurrence + * + * @codeCoverageIgnore + */ + protected function deleteRepetitions(Recurrence $recurrence): void + { + $recurrence->recurrenceRepetitions()->delete(); + } + + /** + * @param Recurrence $recurrence + * + * @codeCoverageIgnore + */ + protected function deleteTransactions(Recurrence $recurrence): void + { + /** @var RecurrenceTransaction $transaction */ + foreach ($recurrence->recurrenceTransactions as $transaction) { + $transaction->recurrenceTransactionMeta()->delete(); + try { + $transaction->delete(); + } catch (Exception $e) { + Log::debug($e->getMessage()); + } + } + } } diff --git a/app/Services/Internal/Update/BillUpdateService.php b/app/Services/Internal/Update/BillUpdateService.php index 1cad40408f..5749cfae57 100644 --- a/app/Services/Internal/Update/BillUpdateService.php +++ b/app/Services/Internal/Update/BillUpdateService.php @@ -56,7 +56,8 @@ class BillUpdateService if (array_key_exists('currency_id', $data) || array_key_exists('currency_code', $data)) { $factory = app(TransactionCurrencyFactory::class); - $currency = $factory->find((int) ($data['currency_id'] ?? null), $data['currency_code'] ?? null) ?? app('amount')->getDefaultCurrencyByUser($bill->user); + $currency = $factory->find((int)($data['currency_id'] ?? null), $data['currency_code'] ?? null) ?? + app('amount')->getDefaultCurrencyByUser($bill->user); // enable the currency if it isn't. $currency->enabled = true; diff --git a/app/Services/Internal/Update/CategoryUpdateService.php b/app/Services/Internal/Update/CategoryUpdateService.php index 819db8b38d..4d51a254cd 100644 --- a/app/Services/Internal/Update/CategoryUpdateService.php +++ b/app/Services/Internal/Update/CategoryUpdateService.php @@ -67,8 +67,8 @@ class CategoryUpdateService */ public function update(Category $category, array $data): Category { - $oldName = $category->name; - if(array_key_exists('name', $data)) { + $oldName = $category->name; + if (array_key_exists('name', $data)) { $category->name = $data['name']; $category->save(); // update triggers and actions diff --git a/app/Services/Internal/Update/CurrencyUpdateService.php b/app/Services/Internal/Update/CurrencyUpdateService.php index b1d99f0e05..f84a1b78f2 100644 --- a/app/Services/Internal/Update/CurrencyUpdateService.php +++ b/app/Services/Internal/Update/CurrencyUpdateService.php @@ -24,7 +24,6 @@ declare(strict_types=1); namespace FireflyIII\Services\Internal\Update; use FireflyIII\Models\TransactionCurrency; -use Log; /** * Class CurrencyUpdateService diff --git a/app/Services/Internal/Update/RecurrenceUpdateService.php b/app/Services/Internal/Update/RecurrenceUpdateService.php index f4bacda0a6..c3d04b8bd7 100644 --- a/app/Services/Internal/Update/RecurrenceUpdateService.php +++ b/app/Services/Internal/Update/RecurrenceUpdateService.php @@ -114,63 +114,6 @@ class RecurrenceUpdateService return $recurrence; } - /** - * TODO this method is way too complex. - * - * @param Recurrence $recurrence - * @param array $transactions - * - * @throws FireflyException - */ - private function updateTransactions(Recurrence $recurrence, array $transactions): void - { - $originalCount = $recurrence->recurrenceTransactions()->count(); - if (0 === count($transactions)) { - // wont drop transactions, rather avoid. - return; - } - // user added or removed repetitions, delete all and recreate: - if ($originalCount !== count($transactions)) { - Log::debug('Del + recreate'); - $this->deleteTransactions($recurrence); - $this->createTransactions($recurrence, $transactions); - - return; - } - // loop all and try to match them: - if ($originalCount === count($transactions)) { - Log::debug('Loop and find'); - foreach ($transactions as $current) { - $match = $this->matchTransaction($recurrence, $current); - if (null === $match) { - throw new FireflyException('Cannot match recurring transaction to existing transaction. Not sure what to do. Break.'); - } - // TODO find currency - // TODO find foreign currency - - // update fields - $fields = [ - 'source_id' => 'source_id', - 'destination_id' => 'destination_id', - 'amount' => 'amount', - 'foreign_amount' => 'foreign_amount', - 'description' => 'description', - ]; - foreach ($fields as $field => $column) { - if (array_key_exists($field, $current)) { - $match->$column = $current[$field]; - $match->save(); - } - } - // update meta data - // budget_id - // category_id - // tags - // piggy_bank_id - } - } - } - /** * @param Recurrence $recurrence * @param string $text @@ -272,6 +215,71 @@ class RecurrenceUpdateService return $query->first(); } + /** + * TODO this method is way too complex. + * + * @param Recurrence $recurrence + * @param array $transactions + * + * @throws FireflyException + */ + private function updateTransactions(Recurrence $recurrence, array $transactions): void + { + $originalCount = $recurrence->recurrenceTransactions()->count(); + if (0 === count($transactions)) { + // wont drop transactions, rather avoid. + return; + } + // user added or removed repetitions, delete all and recreate: + if ($originalCount !== count($transactions)) { + Log::debug('Del + recreate'); + $this->deleteTransactions($recurrence); + $this->createTransactions($recurrence, $transactions); + + return; + } + // loop all and try to match them: + if ($originalCount === count($transactions)) { + Log::debug('Loop and find'); + foreach ($transactions as $current) { + $match = $this->matchTransaction($recurrence, $current); + if (null === $match) { + throw new FireflyException('Cannot match recurring transaction to existing transaction. Not sure what to do. Break.'); + } + // TODO find currency + // TODO find foreign currency + + // update fields + $fields = [ + 'source_id' => 'source_id', + 'destination_id' => 'destination_id', + 'amount' => 'amount', + 'foreign_amount' => 'foreign_amount', + 'description' => 'description', + ]; + foreach ($fields as $field => $column) { + if (array_key_exists($field, $current)) { + $match->$column = $current[$field]; + $match->save(); + } + } + // update meta data + if (array_key_exists('budget_id', $current)) { + $this->setBudget($match, (int)$current['budget_id']); + } + if (array_key_exists('category_id', $current)) { + $this->setCategory($match, (int)$current['category_id']); + } + if (array_key_exists('tags', $current)) { + $this->updateTags($match, $current['tags']); + } + if (array_key_exists('piggy_bank_id', $current)) { + $this->updatePiggyBank($match, (int)$current['piggy_bank_id']); + } + } + } + } + /** * @param array $data *