From be0758ce8a4f45a2766f9eaa88dbf61300f2c9ba Mon Sep 17 00:00:00 2001 From: James Cole Date: Fri, 24 Nov 2017 21:51:07 +0100 Subject: [PATCH] Update reconciliation code for #1011 and #736 --- .../Account/ReconcileController.php | 120 +++++++ .../Transaction/SingleController.php | 4 + .../Controllers/TransactionController.php | 4 + .../Requests/ReconciliationFormRequest.php | 68 ++++ .../Account/AccountRepository.php | 97 +++++- .../Account/AccountRepositoryInterface.php | 9 + .../Journal/JournalRepository.php | 18 + .../Journal/JournalRepositoryInterface.php | 7 + public/js/ff/accounts/edit-reconciliation.js | 52 +++ resources/lang/en_US/firefly.php | 2 + resources/views/accounts/reconcile/edit.twig | 115 +++++++ resources/views/accounts/reconcile/show.twig | 107 ++++++ resources/views/transactions/show.twig | 308 +++++++++--------- routes/web.php | 5 + 14 files changed, 756 insertions(+), 160 deletions(-) create mode 100644 app/Http/Requests/ReconciliationFormRequest.php create mode 100644 public/js/ff/accounts/edit-reconciliation.js create mode 100644 resources/views/accounts/reconcile/edit.twig create mode 100644 resources/views/accounts/reconcile/show.twig diff --git a/app/Http/Controllers/Account/ReconcileController.php b/app/Http/Controllers/Account/ReconcileController.php index f77f2996c0..518785380f 100644 --- a/app/Http/Controllers/Account/ReconcileController.php +++ b/app/Http/Controllers/Account/ReconcileController.php @@ -26,9 +26,12 @@ use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Helpers\Collector\JournalCollectorInterface; use FireflyIII\Http\Controllers\Controller; +use FireflyIII\Http\Requests\ReconciliationFormRequest; use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; use FireflyIII\Models\Transaction; +use FireflyIII\Models\TransactionJournal; +use FireflyIII\Models\TransactionType; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; @@ -63,6 +66,45 @@ class ReconcileController extends Controller ); } + /** + * @param TransactionJournal $journal + * + * @return $this|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector + */ + public function edit(TransactionJournal $journal) + { + if ($journal->transactionType->type !== TransactionType::RECONCILIATION) { + return redirect(route('transactions.edit', [$journal->id])); + } + // view related code + $subTitle = trans('breadcrumbs.edit_journal', ['description' => $journal->description]); + + // journal related code + $pTransaction = $journal->positiveTransaction(); + $preFilled = [ + 'date' => $journal->dateAsString(), + 'category' => $journal->categoryAsString(), + 'tags' => join(',', $journal->tags->pluck('tag')->toArray()), + 'amount' => $pTransaction->amount, + ]; + + Session::flash('preFilled', $preFilled); + Session::flash('gaEventCategory', 'transactions'); + Session::flash('gaEventAction', 'edit-reconciliation'); + + // put previous url in session if not redirect from store (not "return_to_edit"). + if (true !== session('reconcile.edit.fromUpdate')) { + $this->rememberPreviousUri('reconcile.edit.uri'); + } + Session::forget('reconcile.edit.fromUpdate'); + + return view( + 'accounts.reconcile.edit', + compact('journal', 'optionalFields', 'assetAccounts', 'what', 'budgetList', 'subTitle') + )->with('data', $preFilled); + + } + /** * @param Request $request * @param Account $account @@ -197,6 +239,23 @@ class ReconcileController extends Controller ); } + /** + * @param TransactionJournal $journal + */ + public function show(JournalRepositoryInterface $repository, TransactionJournal $journal) + { + if ($journal->transactionType->type !== TransactionType::RECONCILIATION) { + return redirect(route('transactions.show', [$journal->id])); + } + $subTitle = trans('firefly.reconciliation') . ' "' . $journal->description . '"'; + + // get main transaction: + $transaction = $repository->getAssetTransaction($journal); + + + return view('accounts.reconcile.show', compact('journal', 'subTitle', 'transaction')); + } + /** * @param Account $account * @param Carbon $start @@ -289,4 +348,65 @@ class ReconcileController extends Controller return Response::json(['html' => $html, 'startBalance' => $startBalance, 'endBalance' => $endBalance]); } + + /** + * @param ReconciliationFormRequest $request + * @param AccountRepositoryInterface $repository + * @param TransactionJournal $journal + * + * @return $this|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector + */ + public function update(ReconciliationFormRequest $request, AccountRepositoryInterface $repository, TransactionJournal $journal) + { + if ($journal->transactionType->type !== TransactionType::RECONCILIATION) { + return redirect(route('transactions.show', [$journal->id])); + } + if (bccomp('0', $request->get('amount')) === 0) { + Session::flash('error', trans('firefly.amount_cannot_be_zero')); + + return redirect(route('accounts.reconcile.edit', [$journal->id]))->withInput(); + } + // update journal using account repository. Keep it consistent. + $data = $request->getJournalData(); + $repository->updateReconciliation($journal, $data); + + // @codeCoverageIgnoreStart + if (1 === intval($request->get('return_to_edit'))) { + Session::put('reconcile.edit.fromUpdate', true); + + return redirect(route('accounts.reconcile.edit', [$journal->id]))->withInput(['return_to_edit' => 1]); + } + // @codeCoverageIgnoreEnd + + // redirect to previous URL. + return redirect($this->getPreviousUri('reconcile.edit.uri')); + + } + + + /** + * @param Account $account + * + * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector + * + * @throws FireflyException + */ + private function redirectToOriginalAccount(Account $account) + { + /** @var Transaction $transaction */ + $transaction = $account->transactions()->first(); + if (null === $transaction) { + throw new FireflyException('Expected a transaction. This account has none. BEEP, error.'); + } + + $journal = $transaction->transactionJournal; + /** @var Transaction $opposingTransaction */ + $opposingTransaction = $journal->transactions()->where('transactions.id', '!=', $transaction->id)->first(); + + if (null === $opposingTransaction) { + throw new FireflyException('Expected an opposing transaction. This account has none. BEEP, error.'); // @codeCoverageIgnore + } + + return redirect(route('accounts.show', [$opposingTransaction->account_id])); + } } diff --git a/app/Http/Controllers/Transaction/SingleController.php b/app/Http/Controllers/Transaction/SingleController.php index a1c459916c..2fcf6e56d1 100644 --- a/app/Http/Controllers/Transaction/SingleController.php +++ b/app/Http/Controllers/Transaction/SingleController.php @@ -257,6 +257,10 @@ class SingleController extends Controller $assetAccounts = $this->groupedAccountList(); $budgetList = ExpandedForm::makeSelectListWithEmpty($this->budgets->getBudgets()); + if ($journal->transactionType->type === TransactionType::RECONCILIATION) { + return redirect(route('accounts.reconcile.edit', [$journal->id])); + } + // view related code $subTitle = trans('breadcrumbs.edit_journal', ['description' => $journal->description]); diff --git a/app/Http/Controllers/TransactionController.php b/app/Http/Controllers/TransactionController.php index 47eb0e690e..0f48c39b0a 100644 --- a/app/Http/Controllers/TransactionController.php +++ b/app/Http/Controllers/TransactionController.php @@ -28,6 +28,7 @@ use FireflyIII\Helpers\Collector\JournalCollectorInterface; use FireflyIII\Helpers\Filter\InternalTransferFilter; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionJournal; +use FireflyIII\Models\TransactionType; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Repositories\Journal\JournalTaskerInterface; use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface; @@ -179,6 +180,9 @@ class TransactionController extends Controller if ($this->isOpeningBalance($journal)) { return $this->redirectToAccount($journal); } + if ($journal->transactionType->type === TransactionType::RECONCILIATION) { + return redirect(route('accounts.reconcile.show', [$journal->id])); + } $linkTypes = $linkTypeRepository->get(); $links = $linkTypeRepository->getLinks($journal); $events = $tasker->getPiggyBankEvents($journal); diff --git a/app/Http/Requests/ReconciliationFormRequest.php b/app/Http/Requests/ReconciliationFormRequest.php new file mode 100644 index 0000000000..1f6f2c6238 --- /dev/null +++ b/app/Http/Requests/ReconciliationFormRequest.php @@ -0,0 +1,68 @@ +. + */ +declare(strict_types=1); + +namespace FireflyIII\Http\Requests; + +/** + * Class ReconciliationFormRequest. + */ +class ReconciliationFormRequest extends Request +{ + /** + * @return bool + */ + public function authorize() + { + // Only allow logged in users + return auth()->check(); + } + + /** + * Returns and validates the data required to update a reconciliation. + * + * @return array + */ + public function getJournalData() + { + $data = [ + 'tags' => explode(',', $this->string('tags')), + 'amount' => $this->string('amount'), + 'category' => $this->string('category'), + ]; + + return $data; + } + + /** + * @return array + */ + public function rules() + { + $rules = [ + 'amount' => 'numeric|required', + 'category' => 'between:1,255|nullable', + ]; + + return $rules; + } + +} diff --git a/app/Repositories/Account/AccountRepository.php b/app/Repositories/Account/AccountRepository.php index a3641779a8..cb4b8f87fc 100644 --- a/app/Repositories/Account/AccountRepository.php +++ b/app/Repositories/Account/AccountRepository.php @@ -28,9 +28,12 @@ use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Account; use FireflyIII\Models\AccountMeta; use FireflyIII\Models\AccountType; +use FireflyIII\Models\Category; +use FireflyIII\Models\Tag; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionType; +use FireflyIII\Repositories\Tag\TagRepositoryInterface; use FireflyIII\User; use Log; use Validator; @@ -40,10 +43,11 @@ use Validator; */ class AccountRepository implements AccountRepositoryInterface { - use FindAccountsTrait; /** @var User */ private $user; + + use FindAccountsTrait; /** @var array */ private $validFields = ['accountRole', 'ccMonthlyPaymentDate', 'ccType', 'accountNumber', 'currency_id', 'BIC']; @@ -195,6 +199,43 @@ class AccountRepository implements AccountRepositoryInterface return $account; } + /** + * @param TransactionJournal $journal + * @param array $data + * + * @return TransactionJournal + */ + public function updateReconciliation(TransactionJournal $journal, array $data): TransactionJournal + { + // update journal + // update actual journal: + $data['amount'] = strval($data['amount']); + + // unlink all categories, recreate them: + $journal->categories()->detach(); + + $this->storeCategoryWithJournal($journal, strval($data['category'])); + + // update amounts + /** @var Transaction $transaction */ + foreach ($journal->transactions as $transaction) { + $transaction->amount = bcmul($data['amount'], '-1'); + if ($transaction->account->accountType->type === AccountType::ASSET) { + $transaction->amount = $data['amount']; + } + $transaction->save(); + } + + $journal->save(); + + // update tags: + if (isset($data['tags']) && is_array($data['tags'])) { + $this->updateTags($journal, $data['tags']); + } + + return $journal; + } + /** * @param Account $account */ @@ -279,6 +320,18 @@ class AccountRepository implements AccountRepositoryInterface return $newAccount; } + /** + * @param TransactionJournal $journal + * @param string $category + */ + protected function storeCategoryWithJournal(TransactionJournal $journal, string $category) + { + if (strlen($category) > 0) { + $category = Category::firstOrCreateEncrypted(['name' => $category, 'user_id' => $journal->user_id]); + $journal->categories()->save($category); + } + } + /** * At this point strlen of amount > 0. * @@ -494,6 +547,48 @@ class AccountRepository implements AccountRepositoryInterface return true; } + /** + * @param TransactionJournal $journal + * @param array $array + * + * @return bool + */ + protected function updateTags(TransactionJournal $journal, array $array): bool + { + // create tag repository + /** @var TagRepositoryInterface $tagRepository */ + $tagRepository = app(TagRepositoryInterface::class); + + // find or create all tags: + $tags = []; + $ids = []; + foreach ($array as $name) { + if (strlen(trim($name)) > 0) { + $tag = Tag::firstOrCreateEncrypted(['tag' => $name, 'user_id' => $journal->user_id]); + $tags[] = $tag; + $ids[] = $tag->id; + } + } + + // delete all tags connected to journal not in this array: + if (count($ids) > 0) { + DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal->id)->whereNotIn('tag_id', $ids)->delete(); + } + // if count is zero, delete them all: + if (0 === count($ids)) { + DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal->id)->delete(); + } + + // connect each tag to journal (if not yet connected): + /** @var Tag $tag */ + foreach ($tags as $tag) { + Log::debug(sprintf('Will try to connect tag #%d to journal #%d.', $tag->id, $journal->id)); + $tagRepository->connect($journal, $tag); + } + + return true; + } + /** * @param array $data * diff --git a/app/Repositories/Account/AccountRepositoryInterface.php b/app/Repositories/Account/AccountRepositoryInterface.php index c2d90a2225..c05fb8243f 100644 --- a/app/Repositories/Account/AccountRepositoryInterface.php +++ b/app/Repositories/Account/AccountRepositoryInterface.php @@ -33,6 +33,7 @@ use Illuminate\Support\Collection; */ interface AccountRepositoryInterface { + /** * Moved here from account CRUD. * @@ -164,4 +165,12 @@ interface AccountRepositoryInterface * @return Account */ public function update(Account $account, array $data): Account; + + /** + * @param TransactionJournal $journal + * @param array $data + * + * @return TransactionJournal + */ + public function updateReconciliation(TransactionJournal $journal, array $data): TransactionJournal; } diff --git a/app/Repositories/Journal/JournalRepository.php b/app/Repositories/Journal/JournalRepository.php index 3a87a8f602..9ede11c83a 100644 --- a/app/Repositories/Journal/JournalRepository.php +++ b/app/Repositories/Journal/JournalRepository.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Repositories\Journal; use FireflyIII\Models\Account; +use FireflyIII\Models\AccountType; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionType; @@ -169,6 +170,23 @@ class JournalRepository implements JournalRepositoryInterface return $entry; } + /** + * @param TransactionJournal $journal + * + * @return Transaction|null + */ + public function getAssetTransaction(TransactionJournal $journal): ?Transaction + { + /** @var Transaction $transaction */ + foreach ($journal->transactions as $transaction) { + if ($transaction->account->accountType->type === AccountType::ASSET) { + return $transaction; + } + } + + return null; + } + /** * @return Collection */ diff --git a/app/Repositories/Journal/JournalRepositoryInterface.php b/app/Repositories/Journal/JournalRepositoryInterface.php index 2afb7a2785..47075de9df 100644 --- a/app/Repositories/Journal/JournalRepositoryInterface.php +++ b/app/Repositories/Journal/JournalRepositoryInterface.php @@ -91,6 +91,13 @@ interface JournalRepositoryInterface */ public function first(): TransactionJournal; + /** + * @param TransactionJournal $journal + * + * @return Transaction|null + */ + public function getAssetTransaction(TransactionJournal $journal): ?Transaction; + /** * @return Collection */ diff --git a/public/js/ff/accounts/edit-reconciliation.js b/public/js/ff/accounts/edit-reconciliation.js new file mode 100644 index 0000000000..cbcbcd7e42 --- /dev/null +++ b/public/js/ff/accounts/edit-reconciliation.js @@ -0,0 +1,52 @@ +/* + * edit-reconciliation.js + * Copyright (c) 2017 thegrumpydictator@gmail.com + * + * This file is part of Firefly III. + * + * Firefly III is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Firefly III is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Firefly III. If not, see . + */ + +/** global: what, Modernizr, selectsForeignCurrency, convertForeignToNative, validateCurrencyForTransfer, convertSourceToDestination, journalData, journal, accountInfo, exchangeRateInstructions, currencyInfo */ + +$(document).ready(function () { + "use strict"; + setAutocompletes(); + +}); + +/** + * Set the auto-complete JSON things. + */ +function setAutocompletes() { + + $.getJSON('json/categories').done(function (data) { + $('input[name="category"]').typeahead({source: data}); + }); + + $.getJSON('json/tags').done(function (data) { + var opt = { + typeahead: { + source: data, + afterSelect: function () { + this.$element.val(""); + } + } + }; + $('input[name="tags"]').tagsinput( + opt + ); + }); +} + diff --git a/resources/lang/en_US/firefly.php b/resources/lang/en_US/firefly.php index cdd2dd0e6c..3ef62e90a1 100644 --- a/resources/lang/en_US/firefly.php +++ b/resources/lang/en_US/firefly.php @@ -621,6 +621,8 @@ return [ 'cash_accounts' => 'Cash accounts', 'Cash account' => 'Cash account', 'reconcile_account' => 'Reconcile account ":account"', + 'update_reconciliation' => 'Update reconciliation', + 'amount_cannot_be_zero' => 'The amount cannot be zero', 'end_of_reconcile_period' => 'End of reconcile period: :period', 'start_of_reconcile_period' => 'Start of reconcile period: :period', 'start_balance' => 'Start balance', diff --git a/resources/views/accounts/reconcile/edit.twig b/resources/views/accounts/reconcile/edit.twig new file mode 100644 index 0000000000..dff6c8c6dc --- /dev/null +++ b/resources/views/accounts/reconcile/edit.twig @@ -0,0 +1,115 @@ +{% extends "./layout/default" %} + +{% block breadcrumbs %} + {{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, journal) }} +{% endblock %} + +{% block content %} +
+ + + + + {% if errors.all|length > 0 %} +
+
+

{{ 'errors'|_ }}

+
    + {% for err in errors.all %} +
  • {{ err }}
  • + {% endfor %} +
+
+
+ {% endif %} + + +
+
+
+
+

{{ 'mandatoryFields'|_ }}

+
+
+ {# ALWAYS AVAILABLE #} + {{ ExpandedForm.staticText('description',journal.description) }} + + {# ALWAYS SHOW AMOUNT #} + {{ ExpandedForm.nonSelectableAmount('amount',data.amount, {'currency' : data.currency}) }} + + {# ALWAYS SHOW DATE #} + {{ ExpandedForm.staticText('date',journal.date.formatLocalized(monthAndDayFormat)) }} +
+
+ +
+
+
+
+

{{ 'optionalFields'|_ }}

+
+
+ + {{ ExpandedForm.text('category',data['category']) }} + + + {{ ExpandedForm.text('tags') }} +
+
+ + + {% if optionalFields.attachments %} +
+
+

{{ 'optional_field_attachments'|_ }}

+
+
+ {% if optionalFields.attachments %} + + {{ ExpandedForm.file('attachments[]', {'multiple': 'multiple','helpText': trans('firefly.upload_max_file_size', {'size': uploadSize|filesize}) }) }} + {% endif %} +
+
+ {% endif %} + + +
+
+

{{ 'options'|_ }}

+
+
+ {{ ExpandedForm.optionsList('update','transaction') }} +
+ +
+
+
+ +
+ + +{% endblock %} +{% block scripts %} + + + + + + + + + +{% endblock %} +{% block styles %} + + + +{% endblock %} diff --git a/resources/views/accounts/reconcile/show.twig b/resources/views/accounts/reconcile/show.twig new file mode 100644 index 0000000000..0dab366f46 --- /dev/null +++ b/resources/views/accounts/reconcile/show.twig @@ -0,0 +1,107 @@ +{% extends "./layout/default" %} + +{% block breadcrumbs %} + {{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, journal) }} +{% endblock %} + +{% block content %} +
+
+
+
+

{{ 'transaction_journal_information'|_ }}

+ + + +
+
+ + + + + + + + + + + {# total amount #} + + + + + + + + + +
{{ trans('list.type') }}{{ journal.transactiontype.type|_ }}
{{ trans('list.description') }}{{ journal.description }}
{{ 'total_amount'|_ }} + {{ formatAmountByAccount(transaction.account, transaction.amount) }} + +
{{ trans('list.date') }}{{ journal.date.formatLocalized(monthAndDayFormat) }}
+
+ +
+
+
+ +
+
+

{{ 'transaction_journal_meta'|_ }}

+
+
+ + + + + + + {% if journal.tags|length > 0 %} + + + + + {% endif %} + +
{{ 'categories'|_ }}{{ journalCategories(journal)|raw }}
{{ 'tags'|_ }} + {% for tag in journal.tags %} + +

+ {% if tag.tagMode == 'nothing' %} + + {% endif %} + {% if tag.tagMode == 'balancingAct' %} + + {% endif %} + {% if tag.tagMode == 'advancePayment' %} + + {% endif %} + {{ tag.tag }} +

+ {% endfor %} +
+
+
+
+
+ +{% endblock %} +{% block scripts %} +{% endblock %} diff --git a/resources/views/transactions/show.twig b/resources/views/transactions/show.twig index 4e869f350d..48b3145e10 100644 --- a/resources/views/transactions/show.twig +++ b/resources/views/transactions/show.twig @@ -19,47 +19,45 @@
  • {{ 'edit'|_ }}
  • {{ 'delete'|_ }}
  • {# convert to withdrawal #} - {% if journal.transactionType.type != 'Reconciliation' %} - {% if journal.transactionType.type != "Withdrawal" %} -
  • - - {{ ('convert_'~journal.transactionType.type~'_to_withdrawal')|_ }} - -
  • - {% endif %} - {# convert to deposit #} - {% if journal.transactionType.type != "Deposit" %} -
  • - - {{ ('convert_'~journal.transactionType.type~'_to_deposit')|_ }} - -
  • - {% endif %} - {# convert to transfer#} - {% if journal.transactionType.type != "Transfer" %} -
  • - - {{ ('convert_'~journal.transactionType.type~'_to_transfer')|_ }} - -
  • - {% endif %} - {# other options #} + {% if journal.transactionType.type != "Withdrawal" %}
  • - - {{ ('clone_'~journal.transactionType.type|lower)|_ }} - -
  • -
  • - - {{ ('split_this_'~what)|_ }} - -
  • -
  • - {{ 'link_transaction'|_ }} + + {{ ('convert_'~journal.transactionType.type~'_to_withdrawal')|_ }}
  • {% endif %} + {# convert to deposit #} + {% if journal.transactionType.type != "Deposit" %} +
  • + + {{ ('convert_'~journal.transactionType.type~'_to_deposit')|_ }} + +
  • + {% endif %} + {# convert to transfer#} + {% if journal.transactionType.type != "Transfer" %} +
  • + + {{ ('convert_'~journal.transactionType.type~'_to_transfer')|_ }} + +
  • + {% endif %} + {# other options #} +
  • + + {{ ('clone_'~journal.transactionType.type|lower)|_ }} + +
  • +
  • + + {{ ('split_this_'~what)|_ }} + +
  • +
  • + {{ 'link_transaction'|_ }} + +
  • @@ -76,19 +74,17 @@ {{ trans('list.description') }} {{ journal.description }} - {% if journal.transactionType.type != 'Reconciliation' %} - - - {{ 'source_accounts'|_ }} - {{ sourceAccount(journal)|raw }} - + + + {{ 'source_accounts'|_ }} + {{ sourceAccount(journal)|raw }} + - - - {{ 'destination_accounts'|_ }} - {{ destinationAccount(journal)|raw }} - - {% endif %} + + + {{ 'destination_accounts'|_ }} + {{ destinationAccount(journal)|raw }} + {{ 'total_amount'|_ }} @@ -113,55 +109,53 @@
    {{ 'edit'|_ }} - {% if journal.transactionType.type != 'Reconciliation' %} - - {{ 'delete'|_ }}
    @@ -194,12 +188,10 @@ {{ 'categories'|_ }} {{ journalCategories(journal)|raw }} - {% if journal.transactionType.type != 'Reconciliation' %} - - {{ 'budgets'|_ }} - {{ journalBudgets(journal)|raw }} - - {% endif %} + + {{ 'budgets'|_ }} + {{ journalBudgets(journal)|raw }} + {% if journal.hasMeta('interest_date') %} @@ -373,75 +365,73 @@ {% endif %}
    - {% if journal.transactionType.type != 'Reconciliation' %} -
    -
    -
    -
    -

    {{ 'transactions'|_ }}

    -
    - - - - - - - - - - - - - - - {% for transaction in transactions %} - - - - - - - - - - - {% endfor %} - -
    {{ trans('list.source_account') }}{{ trans('list.destination_account') }}{{ trans('list.amount') }}
    - {% if transaction.source_account_type == 'Cash account' %} - ({{ 'cash'|_ }}) - {% else %} - {{ transaction.source_account_name }} - {% endif %} - - - {% if transaction.destination_account_type == 'Cash account' %} - ({{ 'cash'|_ }}) - {% else %} - {{ transaction.destination_account_name }} - {% endif %} - - - {{ transaction|transactionArrayAmount }} -
    +
    +
    +
    +
    +

    {{ 'transactions'|_ }}

    + + + + + + + + + + + + + + + {% for transaction in transactions %} + + + + + + + + + + + {% endfor %} + +
    {{ trans('list.source_account') }}{{ trans('list.destination_account') }}{{ trans('list.amount') }}
    + {% if transaction.source_account_type == 'Cash account' %} + ({{ 'cash'|_ }}) + {% else %} + {{ transaction.source_account_name }} + {% endif %} + + + {% if transaction.destination_account_type == 'Cash account' %} + ({{ 'cash'|_ }}) + {% else %} + {{ transaction.destination_account_name }} + {% endif %} + + + {{ transaction|transactionArrayAmount }} +
    - {% endif %} +
    {# link journal modal:#}