diff --git a/app/Rules/Actions/SetDestinationAccount.php b/app/Rules/Actions/SetDestinationAccount.php new file mode 100644 index 0000000000..4f6b4d28d5 --- /dev/null +++ b/app/Rules/Actions/SetDestinationAccount.php @@ -0,0 +1,141 @@ +action = $action; + } + + /** + * @param TransactionJournal $journal + * + * @return bool + */ + public function act(TransactionJournal $journal): bool + { + $this->journal = $journal; + $this->repository = app(AccountRepositoryInterface::class, [$journal->user]); + $count = $journal->transactions()->count(); + if ($count > 2) { + Log::error(sprintf('Cannot change destination account of journal #%d because it is a split journal.', $journal->id)); + + return true; + } + + // journal type: + $type = $journal->transactionType->type; + + // if this is a deposit or a transfer, the destination account must be an asset account or a default account, and it MUST exist: + if (($type === TransactionType::DEPOSIT || $type === TransactionType::TRANSFER) && !$this->findAssetAccount()) { + Log::error( + sprintf( + 'Cannot change destination account of journal #%d because no asset account with name "%s" exists.', + $journal->id, $this->action->action_value + ) + ); + + return true; + } + + // if this is a withdrawal, the new destination account must be a expense account and may be created: + if ($type === TransactionType::WITHDRAWAL) { + $this->findExpenseAccount(); + } + + Log::debug(sprintf('New destination account is #%d ("%s").', $this->newDestinationAccount->id, $this->newDestinationAccount->name)); + + // update destination transaction with new destination account: + // get destination transaction: + $transaction = $journal->transactions()->where('amount', '>', 0)->first(); + $transaction->account_id = $this->newDestinationAccount->id; + $transaction->save(); + Log::debug(sprintf('Updated transaction #%d and gave it new account ID.', $transaction->id)); + + return true; + } + + /** + * @return bool + */ + private function findAssetAccount(): bool + { + $account = $this->repository->findByName($this->action->action_value, [AccountType::DEFAULT, AccountType::ASSET]); + + if (is_null($account->id)) { + Log::debug(sprintf('There is NO asset account called "%s".', $this->action->action_value)); + + return false; + } + Log::debug(sprintf('There exists an asset account called "%s". ID is #%d', $this->action->action_value, $account->id)); + $this->newDestinationAccount = $account; + + return true; + } + + /** + * + */ + private function findExpenseAccount() + { + $account = $this->repository->findByName($this->action->action_value, [AccountType::REVENUE]); + if (is_null($account->id)) { + // create new revenue account with this name: + $data = [ + 'name' => $this->action->action_value, + 'accountType' => 'expense', + 'virtualBalance' => 0, + 'active' => true, + 'iban' => null, + ]; + $account = $this->repository->store($data); + } + Log::debug(sprintf('Found or created expense account #%d ("%s")', $account->id, $account->name)); + $this->newDestinationAccount = $account; + } +} diff --git a/config/firefly.php b/config/firefly.php index f93f5fe6f5..9d5113793b 100644 --- a/config/firefly.php +++ b/config/firefly.php @@ -185,8 +185,8 @@ return [ 'append_description' => 'FireflyIII\Rules\Actions\AppendDescription', 'prepend_description' => 'FireflyIII\Rules\Actions\PrependDescription', - 'set_source_account' => 'FireflyIII\Rules\Actions\SetSourceAccount', - //'set_destination_account' => 'FireflyIII\Rules\Actions\SetDestinationAccount', + 'set_source_account' => 'FireflyIII\Rules\Actions\SetSourceAccount', + 'set_destination_account' => 'FireflyIII\Rules\Actions\SetDestinationAccount', ], 'rule-actions-text' => [ 'set_category', diff --git a/resources/lang/en_US/firefly.php b/resources/lang/en_US/firefly.php index a2a639d8e5..cd3074e301 100644 --- a/resources/lang/en_US/firefly.php +++ b/resources/lang/en_US/firefly.php @@ -241,6 +241,7 @@ return [ 'rule_action_set_source_account_choice' => 'Set source account to...', 'rule_action_set_source_account' => 'Set source account to :action_value', 'rule_action_set_destination_account_choice' => 'Set destination account to...', + 'rule_action_set_destination_account' => 'Set destination account to :action_value', // tags 'store_new_tag' => 'Store new tag', 'update_tag' => 'Update tag',