diff --git a/app/Http/Controllers/Account/DeleteController.php b/app/Http/Controllers/Account/DeleteController.php index c997c4814e..16f870f7bf 100644 --- a/app/Http/Controllers/Account/DeleteController.php +++ b/app/Http/Controllers/Account/DeleteController.php @@ -27,6 +27,7 @@ namespace FireflyIII\Http\Controllers\Account; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\Account; use FireflyIII\Repositories\Account\AccountRepositoryInterface; +use FireflyIII\Support\Http\Controllers\UserNavigation; use Illuminate\Http\Request; /** @@ -34,6 +35,8 @@ use Illuminate\Http\Request; */ class DeleteController extends Controller { + use UserNavigation; + /** @var AccountRepositoryInterface The account repository */ private $repository; @@ -67,6 +70,10 @@ class DeleteController extends Controller */ public function delete(Account $account) { + if (!$this->isEditableAccount($account)) { + return $this->redirectAccountToAccount($account); // @codeCoverageIgnore + } + $typeName = config(sprintf('firefly.shortNamesByFullName.%s', $account->accountType->type)); $subTitle = (string)trans(sprintf('firefly.delete_%s_account', $typeName), ['name' => $account->name]); $accountList = app('expandedform')->makeSelectListWithEmpty($this->repository->getAccountsByType([$account->accountType->type])); @@ -89,6 +96,10 @@ class DeleteController extends Controller */ public function destroy(Request $request, Account $account) { + if (!$this->isEditableAccount($account)) { + return $this->redirectAccountToAccount($account); // @codeCoverageIgnore + } + $type = $account->accountType->type; $typeName = config(sprintf('firefly.shortNamesByFullName.%s', $type)); $name = $account->name; diff --git a/app/Http/Controllers/Account/EditController.php b/app/Http/Controllers/Account/EditController.php index 117f515dca..923d95e786 100644 --- a/app/Http/Controllers/Account/EditController.php +++ b/app/Http/Controllers/Account/EditController.php @@ -30,6 +30,7 @@ use FireflyIII\Models\Account; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Support\Http\Controllers\ModelInformation; +use FireflyIII\Support\Http\Controllers\UserNavigation; use Illuminate\Http\Request; /** @@ -38,7 +39,7 @@ use Illuminate\Http\Request; */ class EditController extends Controller { - use ModelInformation; + use ModelInformation, UserNavigation; /** @var CurrencyRepositoryInterface The currency repository */ private $currencyRepos; /** @var AccountRepositoryInterface The account repository */ @@ -79,6 +80,10 @@ class EditController extends Controller */ public function edit(Request $request, Account $account, AccountRepositoryInterface $repository) { + if (!$this->isEditableAccount($account)) { + return $this->redirectAccountToAccount($account); // @codeCoverageIgnore + } + $objectType = config('firefly.shortNamesByFullName')[$account->accountType->type]; $subTitle = (string)trans(sprintf('firefly.edit_%s_account', $objectType), ['name' => $account->name]); $subTitleIcon = config(sprintf('firefly.subIconsByIdentifier.%s', $objectType)); @@ -144,6 +149,10 @@ class EditController extends Controller */ public function update(AccountFormRequest $request, Account $account) { + if (!$this->isEditableAccount($account)) { + return $this->redirectAccountToAccount($account); // @codeCoverageIgnore + } + $data = $request->getAccountData(); $this->repository->update($account, $data); diff --git a/app/Http/Controllers/Account/ReconcileController.php b/app/Http/Controllers/Account/ReconcileController.php index 0b4fd5d40d..0c7398762a 100644 --- a/app/Http/Controllers/Account/ReconcileController.php +++ b/app/Http/Controllers/Account/ReconcileController.php @@ -86,6 +86,10 @@ class ReconcileController extends Controller */ public function reconcile(Account $account, Carbon $start = null, Carbon $end = null) { + if (!$this->isEditableAccount($account)) { + return $this->redirectAccountToAccount($account); // @codeCoverageIgnore + } + if (AccountType::ASSET !== $account->accountType->type) { // @codeCoverageIgnoreStart session()->flash('error', (string)trans('firefly.must_be_asset_account')); @@ -146,6 +150,10 @@ class ReconcileController extends Controller */ public function submit(ReconciliationStoreRequest $request, Account $account, Carbon $start, Carbon $end) { + if (!$this->isEditableAccount($account)) { + return $this->redirectAccountToAccount($account); // @codeCoverageIgnore + } + Log::debug('In ReconcileController::submit()'); $data = $request->getAll(); @@ -178,6 +186,10 @@ class ReconcileController extends Controller */ private function createReconciliation(Account $account, Carbon $start, Carbon $end, string $difference): string { + if (!$this->isEditableAccount($account)) { + return $this->redirectAccountToAccount($account); // @codeCoverageIgnore + } + $reconciliation = $this->accountRepos->getReconciliation($account); $currency = $this->accountRepos->getAccountCurrency($account) ?? app('amount')->getDefaultCurrency(); $source = $reconciliation; diff --git a/app/Http/Controllers/Account/ShowController.php b/app/Http/Controllers/Account/ShowController.php index 840ba8ff7a..0f6fd1cf8a 100644 --- a/app/Http/Controllers/Account/ShowController.php +++ b/app/Http/Controllers/Account/ShowController.php @@ -28,7 +28,6 @@ use Exception; use FireflyIII\Helpers\Collector\GroupCollectorInterface; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\Account; -use FireflyIII\Models\AccountType; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Support\Http\Controllers\PeriodOverview; @@ -87,8 +86,8 @@ class ShowController extends Controller */ public function show(Request $request, Account $account, Carbon $start = null, Carbon $end = null) { - if (in_array($account->accountType->type, [AccountType::INITIAL_BALANCE, AccountType::RECONCILIATION], true)) { - return $this->redirectToOriginalAccount($account); // @codeCoverageIgnore + if (!$this->isEditableAccount($account)) { + return $this->redirectAccountToAccount($account); // @codeCoverageIgnore } /** @var Carbon $start */ @@ -145,9 +144,10 @@ class ShowController extends Controller */ public function showAll(Request $request, Account $account) { - if (AccountType::INITIAL_BALANCE === $account->accountType->type) { - return $this->redirectToOriginalAccount($account); // @codeCoverageIgnore + if (!$this->isEditableAccount($account)) { + return $this->redirectAccountToAccount($account); // @codeCoverageIgnore } + $isLiability = $this->repository->isLiability($account); $objectType = config(sprintf('firefly.shortNamesByFullName.%s', $account->accountType->type)); $end = new Carbon; diff --git a/app/Http/Controllers/Transaction/ConvertController.php b/app/Http/Controllers/Transaction/ConvertController.php index 1d488e1767..b6faa17a7a 100644 --- a/app/Http/Controllers/Transaction/ConvertController.php +++ b/app/Http/Controllers/Transaction/ConvertController.php @@ -35,6 +35,7 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Services\Internal\Update\JournalUpdateService; use FireflyIII\Support\Http\Controllers\ModelInformation; +use FireflyIII\Support\Http\Controllers\UserNavigation; use FireflyIII\Transformers\TransactionGroupTransformer; use FireflyIII\Validation\AccountValidator; use Illuminate\Http\Request; @@ -49,7 +50,7 @@ use View; */ class ConvertController extends Controller { - use ModelInformation; + use ModelInformation, UserNavigation; /** @var JournalRepositoryInterface Journals and transactions overview */ private $repository; @@ -87,16 +88,16 @@ class ConvertController extends Controller */ public function index(TransactionType $destinationType, TransactionGroup $group) { + if (!$this->isEditableGroup($group)) { + return $this->redirectGroupToAccount($group); // @codeCoverageIgnore + } + /** @var TransactionGroupTransformer $transformer */ $transformer = app(TransactionGroupTransformer::class); /** @var TransactionJournal $first */ $first = $group->transactionJournals()->first(); $sourceType = $first->transactionType; - // return to account. - if (!in_array($sourceType->type, [TransactionType::WITHDRAWAL, TransactionType::TRANSFER, TransactionType::DEPOSIT], true)) { - return $this->redirectToAccount($first); // @codeCoverageIgnore - } $groupTitle = $group->title ?? $first->description; $groupArray = $transformer->transformObject($group); @@ -144,6 +145,10 @@ class ConvertController extends Controller */ public function postIndex(Request $request, TransactionType $destinationType, TransactionGroup $group) { + if (!$this->isEditableGroup($group)) { + return $this->redirectGroupToAccount($group); // @codeCoverageIgnore + } + /** @var TransactionJournal $journal */ foreach ($group->transactionJournals as $journal) { // catch FF exception. diff --git a/app/Http/Controllers/Transaction/DeleteController.php b/app/Http/Controllers/Transaction/DeleteController.php index 4a926364ef..a606421734 100644 --- a/app/Http/Controllers/Transaction/DeleteController.php +++ b/app/Http/Controllers/Transaction/DeleteController.php @@ -26,6 +26,7 @@ use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\TransactionGroup; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface; +use FireflyIII\Support\Http\Controllers\UserNavigation; use Illuminate\Http\RedirectResponse; use Log; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; @@ -36,6 +37,7 @@ use URL; */ class DeleteController extends Controller { + use UserNavigation; /** @var TransactionGroupRepositoryInterface */ private $repository; @@ -69,6 +71,10 @@ class DeleteController extends Controller */ public function delete(TransactionGroup $group) { + if (!$this->isEditableGroup($group)) { + return $this->redirectGroupToAccount($group); // @codeCoverageIgnore + } + Log::debug(sprintf('Start of delete view for group #%d', $group->id)); $journal = $group->transactionJournals->first(); @@ -94,6 +100,10 @@ class DeleteController extends Controller */ public function destroy(TransactionGroup $group): RedirectResponse { + if (!$this->isEditableGroup($group)) { + return $this->redirectGroupToAccount($group); // @codeCoverageIgnore + } + $journal = $group->transactionJournals->first(); if (null === $journal) { throw new NotFoundHttpException; diff --git a/app/Http/Controllers/Transaction/EditController.php b/app/Http/Controllers/Transaction/EditController.php index a31c35409e..f877939270 100644 --- a/app/Http/Controllers/Transaction/EditController.php +++ b/app/Http/Controllers/Transaction/EditController.php @@ -25,13 +25,14 @@ namespace FireflyIII\Http\Controllers\Transaction; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\TransactionGroup; use FireflyIII\Repositories\Account\AccountRepositoryInterface; +use FireflyIII\Support\Http\Controllers\UserNavigation; /** * Class EditController */ class EditController extends Controller { - + use UserNavigation; /** * EditController constructor. * @codeCoverageIgnore @@ -66,6 +67,10 @@ class EditController extends Controller */ public function edit(TransactionGroup $transactionGroup) { + if (!$this->isEditableGroup($transactionGroup)) { + return $this->redirectGroupToAccount($transactionGroup); // @codeCoverageIgnore + } + /** @var AccountRepositoryInterface $repository */ $repository = app(AccountRepositoryInterface::class); $allowedOpposingTypes = config('firefly.allowed_opposing_types'); diff --git a/app/Support/Http/Controllers/UserNavigation.php b/app/Support/Http/Controllers/UserNavigation.php index b23e90fc1f..4575083844 100644 --- a/app/Support/Http/Controllers/UserNavigation.php +++ b/app/Support/Http/Controllers/UserNavigation.php @@ -26,8 +26,9 @@ namespace FireflyIII\Support\Http\Controllers; use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; use FireflyIII\Models\Transaction; +use FireflyIII\Models\TransactionGroup; use FireflyIII\Models\TransactionJournal; -use Illuminate\Http\RedirectResponse; +use FireflyIII\Models\TransactionType; use Illuminate\Support\ViewErrorBag; use Log; @@ -37,6 +38,108 @@ use Log; */ trait UserNavigation { + + //if (!$this->isEditableAccount($account)) { + // return $this->redirectAccountToAccount($account); // @codeCoverageIgnore + // } + + /** + * Will return false if you cant edit this account type. + * + * @param Account $account + * + * @return bool + */ + protected function isEditableAccount(Account $account): bool + { + $editable = [AccountType::EXPENSE, AccountType::REVENUE, AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE]; + $type = $account->accountType->type; + + return in_array($type, $editable, true); + } + + /** + * @param TransactionGroup $group + * + * @return bool + */ + protected function isEditableGroup(TransactionGroup $group): bool + { + /** @var TransactionJournal $journal */ + $journal = $group->transactionJournals()->first(); + if (null === $journal) { + return false; + } + $type = $journal->transactionType->type; + $editable = [TransactionType::WITHDRAWAL, TransactionType::TRANSFER, TransactionType::DEPOSIT]; + + return in_array($type, $editable, true); + } + + /** + * @param TransactionGroup $group + * + * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector + */ + protected function redirectGroupToAccount(TransactionGroup $group) + { + /** @var TransactionJournal $journal */ + $journal = $group->transactionJournals()->first(); + if (null === $journal) { + Log::error(sprintf('No journals in group #%d', $group->id)); + + return redirect(route('index')); + } + // prefer redirect to everything but expense and revenue: + $transactions = $journal->transactions; + $ignore = [AccountType::REVENUE, AccountType::EXPENSE, AccountType::RECONCILIATION, AccountType::INITIAL_BALANCE]; + /** @var Transaction $transaction */ + foreach ($transactions as $transaction) { + $type = $transaction->account->accountType->type; + if (!in_array($type, $ignore)) { + return redirect(route('accounts.show', [$transaction->account_id])); + } + } + + return redirect(route('index')); + } + + /** + * @param Account $account + * + * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector + */ + protected function redirectAccountToAccount(Account $account) + { + $type = $account->accountType->type; + if (AccountType::RECONCILIATION === $type || AccountType::INITIAL_BALANCE === $type) { + // reconciliation must be stored somewhere in this account's transactions. + + /** @var Transaction $transaction */ + $transaction = $account->transactions()->first(); + if (null === $transaction) { + Log::error(sprintf('Account #%d has no transactions. Dont know where it belongs.', $account->id)); + session()->flash('error', trans('firefly.cant_find_redirect_account')); + + return redirect(route('index')); + } + $journal = $transaction->transactionJournal; + /** @var Transaction $other */ + $other = $journal->transactions()->where('id', '!=', $transaction->id)->first(); + if (null === $other) { + Log::error(sprintf('Account #%d has no valid journals. Dont know where it belongs.', $account->id)); + session()->flash('error', trans('firefly.cant_find_redirect_account')); + + return redirect(route('index')); + } + + return redirect(route('accounts.show', [$other->account_id])); + } + + return redirect(route('index')); + } + + /** * Functionality:. * @@ -59,94 +162,72 @@ trait UserNavigation Log::debug(sprintf('URI is now %s (uri contains jscript)', $uri)); } - // "forbidden" words for specific identifiers: - // if these are in the previous URI, don't refer back there. - // $array = [ - // 'accounts.delete.uri' => '/accounts/show/', - // 'transactions.delete.uri' => '/transactions/show/', - // 'attachments.delete.uri' => '/attachments/show/', - // 'bills.delete.uri' => '/bills/show/', - // 'budgets.delete.uri' => '/budgets/show/', - // 'categories.delete.uri' => '/categories/show/', - // 'currencies.delete.uri' => '/currencies/show/', - // 'piggy-banks.delete.uri' => '/piggy-banks/show/', - // 'tags.delete.uri' => '/tags/show/', - // 'rules.delete.uri' => '/rules/edit/', - // 'transactions.mass-delete.uri' => '/transactions/show/', - // ]; - //$forbidden = $array[$identifier] ?? '/show/'; - //Log::debug(sprintf('The forbidden word for %s is "%s"', $identifier, $forbidden)); - - - // if ( - // !(false === strpos($identifier, 'delete')) - // && !(false === strpos($uri, $forbidden))) { - // $uri = $this->redirectUri; - // //Log::debug(sprintf('URI is now %s (identifier contains "delete")', $uri)); - // } - - - // more debug notes: - //Log::debug(sprintf('strpos($identifier, "delete"): %s', var_export(strpos($identifier, 'delete'), true))); - //Log::debug(sprintf('strpos($uri, $forbidden): %s', var_export(strpos($uri, $forbidden), true))); Log::debug(sprintf('Return direct link %s', $uri)); return $uri; } - - /** - * Redirect to asset account that transaction belongs to. - * - * @param TransactionJournal $journal - * - * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector - * @codeCoverageIgnore - */ - protected function redirectToAccount(TransactionJournal $journal) - { - $valid = [AccountType::DEFAULT, AccountType::ASSET]; - $transactions = $journal->transactions; - /** @var Transaction $transaction */ - foreach ($transactions as $transaction) { - $account = $transaction->account; - if (in_array($account->accountType->type, $valid, true)) { - return redirect(route('accounts.show', [$account->id])); - } - } - // @codeCoverageIgnoreStart - session()->flash('error', (string)trans('firefly.cannot_redirect_to_account')); - - return redirect(route('index')); - // @codeCoverageIgnoreEnd - } - - /** - * @param Account $account - * - * @return RedirectResponse|\Illuminate\Routing\Redirector - * @codeCoverageIgnore - */ - protected function redirectToOriginalAccount(Account $account) - { - /** @var Transaction $transaction */ - $transaction = $account->transactions()->first(); - if (null === $transaction) { - app('session')->flash('error', trans('firefly.account_missing_transaction', ['name' => e($account->name), 'id' => $account->id])); - Log::error(sprintf('Expected a transaction. Account #%d has none. BEEP, error.', $account->id)); - - return redirect(route('index')); - } - - $journal = $transaction->transactionJournal; - /** @var Transaction $opposingTransaction */ - $opposingTransaction = $journal->transactions()->where('transactions.id', '!=', $transaction->id)->first(); - - if (null === $opposingTransaction) { - app('session')->flash('error', trans('firefly.account_missing_transaction', ['name' => e($account->name), 'id' => $account->id])); - Log::error(sprintf('Expected an opposing transaction. Account #%d has none. BEEP, error.', $account->id)); - } - - return redirect(route('accounts.show', [$opposingTransaction->account_id])); - } + // + // /** + // * Redirect to asset account that transaction belongs to. + // * + // * @param TransactionGroup $group + // * + // * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector + // * @codeCoverageIgnore + // */ + // protected function redirectToAccount(TransactionGroup $group) + // { + // $journals = $group->transactionJournals; + // $first = $journals->first(); + // + // if (null === $first) { + // return redirect(route('index')); + // } + // + // + // $valid = [AccountType::DEFAULT, AccountType::ASSET]; + // $transactions = $journal->transactions; + // /** @var Transaction $transaction */ + // foreach ($transactions as $transaction) { + // $account = $transaction->account; + // if (in_array($account->accountType->type, $valid, true)) { + // return redirect(route('accounts.show', [$account->id])); + // } + // } + // // @codeCoverageIgnoreStart + // session()->flash('error', (string)trans('firefly.cannot_redirect_to_account')); + // + // return redirect(route('index')); + // // @codeCoverageIgnoreEnd + // } + // + // /** + // * @param Account $account + // * + // * @return RedirectResponse|\Illuminate\Routing\Redirector + // * @codeCoverageIgnore + // */ + // protected function redirectToOriginalAccount(Account $account) + // { + // /** @var Transaction $transaction */ + // $transaction = $account->transactions()->first(); + // if (null === $transaction) { + // app('session')->flash('error', trans('firefly.account_missing_transaction', ['name' => e($account->name), 'id' => $account->id])); + // Log::error(sprintf('Expected a transaction. Account #%d has none. BEEP, error.', $account->id)); + // + // return redirect(route('index')); + // } + // + // $journal = $transaction->transactionJournal; + // /** @var Transaction $opposingTransaction */ + // $opposingTransaction = $journal->transactions()->where('transactions.id', '!=', $transaction->id)->first(); + // + // if (null === $opposingTransaction) { + // app('session')->flash('error', trans('firefly.account_missing_transaction', ['name' => e($account->name), 'id' => $account->id])); + // Log::error(sprintf('Expected an opposing transaction. Account #%d has none. BEEP, error.', $account->id)); + // } + // + // return redirect(route('accounts.show', [$opposingTransaction->account_id])); + // } /** * @param string $identifier diff --git a/resources/lang/en_US/firefly.php b/resources/lang/en_US/firefly.php index c23138e724..cc627a797e 100644 --- a/resources/lang/en_US/firefly.php +++ b/resources/lang/en_US/firefly.php @@ -756,32 +756,33 @@ return [ 'start_of_reconcile_period' => 'Start of reconcile period: :period', 'start_balance' => 'Start balance', 'end_balance' => 'End balance', - 'update_balance_dates_instruction' => 'Match the amounts and dates above to your bank statement, and press "Start reconciling"', - 'select_transactions_instruction' => 'Select the transactions that appear on your bank statement.', - 'select_range_and_balance' => 'First verify the date-range and balances. Then press "Start reconciling"', - 'date_change_instruction' => 'If you change the date range now, any progress will be lost.', - 'update_selection' => 'Update selection', - 'store_reconcile' => 'Store reconciliation', - 'reconciliation_transaction' => 'Reconciliation transaction', - 'Reconciliation' => 'Reconciliation', - 'reconciliation' => 'Reconciliation', - 'reconcile_options' => 'Reconciliation options', - 'reconcile_range' => 'Reconciliation range', - 'start_reconcile' => 'Start reconciling', - 'cash_account_type' => 'Cash', - 'cash' => 'cash', - 'account_type' => 'Account type', - 'save_transactions_by_moving' => 'Save these transaction(s) by moving them to another account:', - 'stored_new_account' => 'New account ":name" stored!', - 'updated_account' => 'Updated account ":name"', - 'credit_card_options' => 'Credit card options', - 'no_transactions_account' => 'There are no transactions (in this period) for asset account ":name".', - 'no_transactions_period' => 'There are no transactions (in this period).', - 'no_data_for_chart' => 'There is not enough information (yet) to generate this chart.', - 'select_at_least_one_account' => 'Please select at least one asset account', - 'select_at_least_one_category' => 'Please select at least one category', - 'select_at_least_one_budget' => 'Please select at least one budget', - 'select_at_least_one_tag' => 'Please select at least one tag', + 'update_balance_dates_instruction' => 'Match the amounts and dates above to your bank statement, and press "Start reconciling"', + 'select_transactions_instruction' => 'Select the transactions that appear on your bank statement.', + 'select_range_and_balance' => 'First verify the date-range and balances. Then press "Start reconciling"', + 'date_change_instruction' => 'If you change the date range now, any progress will be lost.', + 'update_selection' => 'Update selection', + 'store_reconcile' => 'Store reconciliation', + 'reconciliation_transaction' => 'Reconciliation transaction', + 'Reconciliation' => 'Reconciliation', + 'reconciliation' => 'Reconciliation', + 'reconcile_options' => 'Reconciliation options', + 'reconcile_range' => 'Reconciliation range', + 'start_reconcile' => 'Start reconciling', + 'cash_account_type' => 'Cash', + 'cash' => 'cash', + 'cant_find_redirect_account' => 'Firefly III tried to redirect you but couldn\'t. Sorry about that. Back to the index.', + 'account_type' => 'Account type', + 'save_transactions_by_moving' => 'Save these transaction(s) by moving them to another account:', + 'stored_new_account' => 'New account ":name" stored!', + 'updated_account' => 'Updated account ":name"', + 'credit_card_options' => 'Credit card options', + 'no_transactions_account' => 'There are no transactions (in this period) for asset account ":name".', + 'no_transactions_period' => 'There are no transactions (in this period).', + 'no_data_for_chart' => 'There is not enough information (yet) to generate this chart.', + 'select_at_least_one_account' => 'Please select at least one asset account', + 'select_at_least_one_category' => 'Please select at least one category', + 'select_at_least_one_budget' => 'Please select at least one budget', + 'select_at_least_one_tag' => 'Please select at least one tag', 'select_at_least_one_expense' => 'Please select at least one combination of expense/revenue accounts. If you have none (the list is empty) this report is not available.', 'account_default_currency' => 'This will be the default currency associated with this account.', 'reconcile_has_more' => 'Your Firefly III ledger has more money in it than your bank claims you should have. There are several options. Please choose what to do. Then, press "Confirm reconciliation".', diff --git a/resources/views/v1/transactions/show.twig b/resources/views/v1/transactions/show.twig index 3b0e75c589..4a17bb36e7 100644 --- a/resources/views/v1/transactions/show.twig +++ b/resources/views/v1/transactions/show.twig @@ -176,7 +176,7 @@ title="{{ journal.source_iban|default(journal.source_name) }}">{{ journal.source_name }} → {% if type == 'Withdrawal' or type == 'Deposit' %} {{ formatAmountBySymbol(journal.amount*-1, journal.currency_symbol, journal.currency_decimal_places) }} - {% elseif type == 'Transfer' %} + {% elseif type == 'Transfer' or type == 'Opening balance' %} {{ formatAmountBySymbol(journal.amount, journal.currency_symbol, journal.currency_decimal_places, false) }} @@ -193,7 +193,6 @@ {% endif %} {% endif %} - → {{ journal.destination_name }}