From 3c5c14ff5aef17995ecad9424ffc451580bc1f17 Mon Sep 17 00:00:00 2001 From: James Cole Date: Thu, 4 Jul 2019 17:31:47 +0200 Subject: [PATCH] Refactored the bulk edit controller. --- app/Helpers/Collector/GroupCollector.php | 51 +++++--- .../Collector/GroupCollectorInterface.php | 7 + .../Json/AutoCompleteController.php | 1 - .../Transaction/BulkController.php | 95 +++++++++----- .../Journal/JournalRepository.php | 31 ++++- app/Support/Binder/SimpleJournalList.php | 91 +++++-------- public/v1/js/ff/common/autocomplete.js | 16 +-- public/v1/js/ff/list/groups.js | 120 ++++++++++++++++++ .../v1/js/ff/transactions/mass/edit-bulk.js | 18 +++ resources/lang/en_US/firefly.php | 7 +- resources/views/v1/javascript/variables.twig | 8 +- resources/views/v1/list/groups.twig | 46 +++++-- .../v1/reports/partials/journals-audit.twig | 6 +- .../views/v1/transactions/bulk/edit.twig | 79 +++++++++--- resources/views/v1/transactions/index.twig | 8 +- routes/breadcrumbs.php | 18 +-- 16 files changed, 432 insertions(+), 170 deletions(-) create mode 100644 public/v1/js/ff/list/groups.js diff --git a/app/Helpers/Collector/GroupCollector.php b/app/Helpers/Collector/GroupCollector.php index 596385404a..931daa3742 100644 --- a/app/Helpers/Collector/GroupCollector.php +++ b/app/Helpers/Collector/GroupCollector.php @@ -409,7 +409,7 @@ class GroupCollector implements GroupCollectorInterface */ public function setTag(Tag $tag): GroupCollectorInterface { - $this->joinTagTables(); + $this->withTagInformation(); $this->query->where('tag_transaction_journal.tag_id', $tag->id); return $this; @@ -537,7 +537,7 @@ class GroupCollector implements GroupCollectorInterface */ public function setTags(Collection $tags): GroupCollectorInterface { - $this->joinTagTables(); + $this->withTagInformation(); $this->query->whereIn('tag_transaction_journal.tag_id', $tags->pluck('id')->toArray()); return $this; @@ -619,9 +619,11 @@ class GroupCollector implements GroupCollectorInterface $return = []; /** @var array $group */ foreach ($selection as $group) { + $count = count($group['transactions']); foreach ($group['transactions'] as $journalId => $journal) { - $journal['group_title'] = $group['title']; - $return[$journalId] = $journal; + $journal['group_title'] = $group['title']; + $journal['journals_in_group'] = $count; + $return[$journalId] = $journal; } } @@ -776,6 +778,24 @@ class GroupCollector implements GroupCollectorInterface return $this; } + /** + * @return GroupCollectorInterface + */ + public function withTagInformation(): GroupCollectorInterface + { + $this->fields[] = 'tags.id as tag_id'; + $this->fields[] = 'tags.tag as tag_name'; + $this->fields[] = 'tags.date as tag_date'; + $this->fields[] = 'tags.description as tag_description'; + $this->fields[] = 'tags.latitude as tag_latitude'; + $this->fields[] = 'tags.longitude as tag_longitude'; + $this->fields[] = 'tags.zoomLevel as tag_zoom_level'; + + $this->joinTagTables(); + + return $this; + } + /** * @param Collection $collection * @@ -789,16 +809,18 @@ class GroupCollector implements GroupCollectorInterface $groupId = $augmentedGroup->transaction_group_id; if (!isset($groups[$groupId])) { // make new array + $parsedGroup = $this->parseAugmentedGroup($augmentedGroup); $groupArray = [ - 'id' => $augmentedGroup->transaction_group_id, - 'user_id' => $augmentedGroup->user_id, - 'title' => $augmentedGroup->transaction_group_title, - 'count' => 1, - 'sums' => [], - 'transactions' => [], + 'id' => $augmentedGroup->transaction_group_id, + 'user_id' => $augmentedGroup->user_id, + 'title' => $augmentedGroup->transaction_group_title, + 'transaction_type' => $parsedGroup['transaction_type_type'], + 'count' => 1, + 'sums' => [], + 'transactions' => [], ]; $journalId = (int)$augmentedGroup->transaction_journal_id; - $groupArray['transactions'][$journalId] = $this->parseAugmentedGroup($augmentedGroup); + $groupArray['transactions'][$journalId] = $parsedGroup; $groups[$groupId] = $groupArray; continue; } @@ -948,13 +970,6 @@ class GroupCollector implements GroupCollectorInterface $this->hasJoinedTagTables = true; $this->query->leftJoin('tag_transaction_journal', 'tag_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id'); $this->query->leftJoin('tags', 'tag_transaction_journal.tag_id', '=', 'tags.id'); - $this->fields[] = 'tags.id as tag_id'; - $this->fields[] = 'tags.tag as tag_name'; - $this->fields[] = 'tags.date as tag_date'; - $this->fields[] = 'tags.description as tag_description'; - $this->fields[] = 'tags.latitude as tag_latitude'; - $this->fields[] = 'tags.longitude as tag_longitude'; - $this->fields[] = 'tags.zoomLevel as tag_zoom_level'; } } diff --git a/app/Helpers/Collector/GroupCollectorInterface.php b/app/Helpers/Collector/GroupCollectorInterface.php index e9e358f73f..2880576c3c 100644 --- a/app/Helpers/Collector/GroupCollectorInterface.php +++ b/app/Helpers/Collector/GroupCollectorInterface.php @@ -53,6 +53,13 @@ interface GroupCollectorInterface */ public function getSum(): string; + /** + * Add tag info. + * + * @return GroupCollectorInterface + */ + public function withTagInformation(): GroupCollectorInterface; + /** * Return the groups. * diff --git a/app/Http/Controllers/Json/AutoCompleteController.php b/app/Http/Controllers/Json/AutoCompleteController.php index 10fbc664e4..2cd13713ee 100644 --- a/app/Http/Controllers/Json/AutoCompleteController.php +++ b/app/Http/Controllers/Json/AutoCompleteController.php @@ -244,7 +244,6 @@ class AutoCompleteController extends Controller $array[$index]['name'] = $item['tag']; } - return response()->json($array); } diff --git a/app/Http/Controllers/Transaction/BulkController.php b/app/Http/Controllers/Transaction/BulkController.php index a19012351d..bc57f8fe2b 100644 --- a/app/Http/Controllers/Transaction/BulkController.php +++ b/app/Http/Controllers/Transaction/BulkController.php @@ -43,6 +43,7 @@ class BulkController extends Controller /** * BulkController constructor. + * @codeCoverageIgnore */ public function __construct() { @@ -66,7 +67,7 @@ class BulkController extends Controller * * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ - public function edit(Collection $journals) + public function edit(array $journals) { $subTitle = (string)trans('firefly.mass_bulk_journals'); @@ -74,12 +75,6 @@ class BulkController extends Controller /** @var BudgetRepositoryInterface $repository */ $repository = app(BudgetRepositoryInterface::class); $budgetList = app('expandedform')->makeSelectListWithEmpty($repository->getActiveBudgets()); - // collect some useful meta data for the mass edit: - $journals->each( - function (TransactionJournal $journal) { - $journal->transaction_count = $journal->transactions()->count(); - } - ); return view('transactions.bulk.edit', compact('journals', 'subTitle', 'budgetList')); } @@ -104,38 +99,72 @@ class BulkController extends Controller $count = 0; foreach ($journalIds as $journalId) { - $journal = $this->repository->findNull((int)$journalId); - if (null === $journal) { - continue; - } - - $count++; - Log::debug(sprintf('Found journal #%d', $journal->id)); - - // update category if not told to ignore - if (false === $ignoreCategory) { - Log::debug(sprintf('Set category to %s', $request->string('category'))); - - $this->repository->updateCategory($journal, $request->string('category')); - } - - // update budget if not told to ignore (and is withdrawal) - if (false === $ignoreBudget) { - Log::debug(sprintf('Set budget to %d', $request->integer('budget_id'))); - $this->repository->updateBudget($journal, $request->integer('budget_id')); - } - - // update tags: - if (false === $ignoreTags) { - Log::debug(sprintf('Set tags to %s', $request->string('budget_id'))); - $this->repository->updateTags($journal, ['tags' => explode(',', $request->string('tags'))]); + $journalId = (int)$journalId; + $journal = $this->repository->findNull($journalId); + if (null !== $journal) { + $resultA = $this->updateJournalBudget($journal, $ignoreBudget, $request->integer('budget_id')); + $resultB = $this->updateJournalTags($journal, $ignoreTags, explode(',', $request->string('tags'))); + $resultC = $this->updateJournalCategory($journal, $ignoreCategory, $request->string('category')); + if ($resultA || $resultB || $resultC) { + $count++; + } } } - app('preferences')->mark(); $request->session()->flash('success', (string)trans('firefly.mass_edited_transactions_success', ['amount' => $count])); // redirect to previous URL: return redirect($this->getPreviousUri('transactions.bulk-edit.uri')); } + + /** + * @param TransactionJournal $journal + * @param bool $ignoreUpdate + * @param array $tags + * @return bool + */ + public function updateJournalTags(TransactionJournal $journal, bool $ignoreUpdate, array $tags): bool + { + if (true === $ignoreUpdate) { + return false; + } + Log::debug(sprintf('Set tags to %s', implode(',', $tags))); + $this->repository->updateTags($journal, $tags); + + return true; + } + + /** + * @param TransactionJournal $journal + * @param bool $ignoreUpdate + * @param string $category + * @return bool + */ + private function updateJournalCategory(TransactionJournal $journal, bool $ignoreUpdate, string $category): bool + { + if (true === $ignoreUpdate) { + return false; + } + Log::debug(sprintf('Set budget to %s', $category)); + $this->repository->updateCategory($journal, $category); + + return true; + } + + /** + * @param TransactionJournal $journal + * @param bool $ignoreUpdate + * @param int $budgetId + * @return bool + */ + private function updateJournalBudget(TransactionJournal $journal, bool $ignoreUpdate, int $budgetId): bool + { + if (true === $ignoreUpdate) { + return false; + } + Log::debug(sprintf('Set budget to %d', $budgetId)); + $this->repository->updateBudget($journal, $budgetId); + + return true; + } } diff --git a/app/Repositories/Journal/JournalRepository.php b/app/Repositories/Journal/JournalRepository.php index 6b1d3a30be..dd1752dc9b 100644 --- a/app/Repositories/Journal/JournalRepository.php +++ b/app/Repositories/Journal/JournalRepository.php @@ -778,7 +778,16 @@ class JournalRepository implements JournalRepositoryInterface /** @var JournalUpdateService $service */ $service = app(JournalUpdateService::class); - return $service->updateBudget($journal, $budgetId); + $service->setTransactionJournal($journal); + $service->setData( + [ + 'budget_id' => $budgetId, + ] + ); + $service->update(); + $journal->refresh(); + + return $journal; } /** @@ -793,8 +802,16 @@ class JournalRepository implements JournalRepositoryInterface { /** @var JournalUpdateService $service */ $service = app(JournalUpdateService::class); + $service->setTransactionJournal($journal); + $service->setData( + [ + 'category_name' => $category, + ] + ); + $service->update(); + $journal->refresh(); - return $service->updateCategory($journal, $category); + return $journal; } /** @@ -809,10 +826,16 @@ class JournalRepository implements JournalRepositoryInterface { /** @var JournalUpdateService $service */ $service = app(JournalUpdateService::class); - $service->connectTags($journal, $tags); + $service->setTransactionJournal($journal); + $service->setData( + [ + 'tags' => $tags, + ] + ); + $service->update(); + $journal->refresh(); return $journal; - } /** diff --git a/app/Support/Binder/SimpleJournalList.php b/app/Support/Binder/SimpleJournalList.php index d5a9ddc12e..a07702a523 100644 --- a/app/Support/Binder/SimpleJournalList.php +++ b/app/Support/Binder/SimpleJournalList.php @@ -23,11 +23,9 @@ declare(strict_types=1); namespace FireflyIII\Support\Binder; -use FireflyIII\Models\TransactionJournal; +use FireflyIII\Helpers\Collector\GroupCollectorInterface; use FireflyIII\Models\TransactionType; -use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use Illuminate\Routing\Route; -use Illuminate\Support\Collection; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** @@ -35,73 +33,46 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; */ class SimpleJournalList implements BinderInterface { + /** * @param string $value - * @param Route $route + * @param Route $route * * @return mixed - * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) - * @SuppressWarnings(PHPMD.NPathComplexity) + * @throws NotFoundHttpException */ - public static function routeBinder(string $value, Route $route): Collection + public static function routeBinder(string $value, Route $route): array { if (auth()->check()) { - $list = array_unique(array_map('\intval', explode(',', $value))); - if (0 === count($list)) { - throw new NotFoundHttpException; // @codeCoverageIgnore + $list = self::parseList($value); + + // get the journals by using the collector. + /** @var GroupCollectorInterface $collector */ + $collector = app(GroupCollectorInterface::class); + $collector->setTypes([TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::TRANSFER]); + $collector->withCategoryInformation()->withBudgetInformation()->withTagInformation(); + $collector->setJournalIds($list); + $result = $collector->getExtractedJournals(); + if (0 === count($result)) { + throw new NotFoundHttpException; } - // prep some vars - $messages = []; - $final = new Collection; - /** @var JournalRepositoryInterface $repository */ - $repository = app(JournalRepositoryInterface::class); - - // get all journals: - /** @var \Illuminate\Support\Collection $collection */ - $collection = auth()->user()->transactionJournals() - ->whereIn('transaction_journals.id', $list) - ->where('transaction_journals.completed', 1) - ->get(['transaction_journals.*']); - - // filter the list! Yay! - /** @var TransactionJournal $journal */ - foreach ($collection as $journal) { - $sources = $repository->getJournalSourceAccounts($journal); - $destinations = $repository->getJournalDestinationAccounts($journal); - if ($sources->count() > 1) { - $messages[] = (string)trans('firefly.cannot_edit_multiple_source', ['description' => $journal->description, 'id' => $journal->id]); - continue; - } - - if ($destinations->count() > 1) { - $messages[] = (string)trans('firefly.cannot_edit_multiple_dest', ['description' => $journal->description, 'id' => $journal->id]); - continue; - } - if (TransactionType::OPENING_BALANCE === $repository->getTransactionType($journal)) { - $messages[] = (string)trans('firefly.cannot_edit_opening_balance'); - continue; - } - - // cannot edit reconciled transactions / journals: - if ($repository->isJournalReconciled($journal)) { - $messages[] = (string)trans('firefly.cannot_edit_reconciled', ['description' => $journal->description, 'id' => $journal->id]); - continue; - } - - $final->push($journal); - } - - if ($final->count() > 0) { - if (count($messages) > 0) { - session()->flash('info', $messages); - } - - return $final; - } + return $result; } throw new NotFoundHttpException; } + + /** + * @param string $value + * @return array + */ + protected static function parseList(string $value): array + { + $list = array_unique(array_map('\intval', explode(',', $value))); + if (0 === count($list)) { + throw new NotFoundHttpException; // @codeCoverageIgnore + } + + return $list; + } } diff --git a/public/v1/js/ff/common/autocomplete.js b/public/v1/js/ff/common/autocomplete.js index 5d8b15a796..ada9f5c524 100644 --- a/public/v1/js/ff/common/autocomplete.js +++ b/public/v1/js/ff/common/autocomplete.js @@ -29,8 +29,8 @@ function initTagsAC() { prefetch: { url: 'json/tags?uid=' + uid, filter: function (list) { - return $.map(list, function (tagTag) { - return {name: tagTag}; + return $.map(list, function (item) { + return {name: item.name}; }); } }, @@ -38,8 +38,8 @@ function initTagsAC() { url: 'json/tags?search=%QUERY&uid=' + uid, wildcard: '%QUERY', filter: function (list) { - return $.map(list, function (name) { - return {name: name}; + return $.map(list, function (item) { + return {name: item.name}; }); } } @@ -145,8 +145,8 @@ function initCategoryAC() { prefetch: { url: 'json/categories?uid=' + uid, filter: function (list) { - return $.map(list, function (name) { - return {name: name}; + return $.map(list, function (object) { + return {name: object.name}; }); } }, @@ -154,8 +154,8 @@ function initCategoryAC() { url: 'json/categories?search=%QUERY&uid=' + uid, wildcard: '%QUERY', filter: function (list) { - return $.map(list, function (name) { - return {name: name}; + return $.map(list, function (object) { + return {name: object.name}; }); } } diff --git a/public/v1/js/ff/list/groups.js b/public/v1/js/ff/list/groups.js new file mode 100644 index 0000000000..805cbb4cf5 --- /dev/null +++ b/public/v1/js/ff/list/groups.js @@ -0,0 +1,120 @@ +/* + * groups.js + * Copyright (c) 2019 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 . + */ + +var count = 0; + +$(document).ready(function () { + // top button to select all / deselect all: + $('input[name="select-all"]').change(function () { + if (this.checked) { + checkAll(); + countChecked(); + updateActionButtons(); + } else { + uncheckAll(); + countChecked(); + updateActionButtons(); + } + }); + + // click the mass edit button: + $('.mass-edit').click(goToMassEdit); + // click the bulk edit button: + $('.bulk-edit').click(goToBulkEdit); + // click the delete button: + $('.mass-delete').click(goToMassDelete); + + // click checkbox: + $('.mass-select').unbind('change').change(function () { + countChecked(); + updateActionButtons(); + }); + + +}); + +/** + * + * @returns {boolean} + */ +function goToMassEdit() { + console.log(mass_edit_url + '/' + getCheckboxes()); + window.location.href = mass_edit_url + '/' + getCheckboxes(); + return false; +} + +function goToBulkEdit() { + console.log(bulk_edit_url + '/' + getCheckboxes()); + window.location.href = bulk_edit_url + '/' + getCheckboxes(); + return false; +} + +function goToMassDelete() { + console.log(mass_delete_url + '/' + getCheckboxes()); + window.location.href = mass_delete_url + '/' + getCheckboxes(); + return false; +} + +/** + * + * @returns {Array} + */ +function getCheckboxes() { + "use strict"; + var list = []; + $.each($('.mass-select'), function (i, v) { + var checkbox = $(v); + if (checkbox.prop('checked')) { + // add to list. + list.push(checkbox.val()); + } + }); + return list; +} + + + + +function countChecked() { + count = $('.mass-select:checked').length; +} + +function checkAll() { + $('.mass-select').prop('checked', true); +} + +function uncheckAll() { + $('.mass-select').prop('checked', false); +} + +function updateActionButtons() { + if (0 !== count) { + $('.action-menu').show(); + + // also update labels: + $('.mass-edit span').text(edit_selected_txt + ' (' + count + ')'); + $('.bulk-edit span').text(edit_bulk_selected_txt + ' (' + count + ')'); + $('.mass-delete span').text(delete_selected_txt + ' (' + count + ')'); + + } + if (0 === count) { + $('.action-menu').hide(); + } +} \ No newline at end of file diff --git a/public/v1/js/ff/transactions/mass/edit-bulk.js b/public/v1/js/ff/transactions/mass/edit-bulk.js index bcff97c14a..b7aa58b044 100644 --- a/public/v1/js/ff/transactions/mass/edit-bulk.js +++ b/public/v1/js/ff/transactions/mass/edit-bulk.js @@ -24,4 +24,22 @@ $(document).ready(function () { "use strict"; initTagsAC(); initCategoryAC(); + + // on change, remove the checkbox. + $('input[name="category"]').change(function () { + $('input[name="ignore_category"]').attr('checked', false); + }); + + $('select[name="budget_id"]').change(function () { + + $('input[name="ignore_budget"]').attr('checked', false); + }); + + $('input[name="tags"]').on('itemAdded', function(event) { + $('input[name="ignore_tags"]').attr('checked', false); + + }); + + + }); \ No newline at end of file diff --git a/resources/lang/en_US/firefly.php b/resources/lang/en_US/firefly.php index 06ffab34e4..4f90a01816 100644 --- a/resources/lang/en_US/firefly.php +++ b/resources/lang/en_US/firefly.php @@ -839,12 +839,15 @@ return [ 'mass_delete_journals' => 'Delete a number of transactions', 'mass_edit_journals' => 'Edit a number of transactions', 'mass_bulk_journals' => 'Bulk edit a number of transactions', - 'mass_bulk_journals_explain' => 'If you do not want to change your transactions one-by-one using the mass-edit function, you can update them in one go. Simply select the preferred category, tag(s) or budget in the fields below, and all the transactions in the table will be updated.', + 'mass_bulk_journals_explain' => 'This form allows you to change properties if the transactions listed below in one sweeping update. All the transactions in the table will be updated when you change the parameters you see here.', + 'part_of_split' => 'This transaction is part of a split transaction. If you have not selected all the splits, you may end up with changing only half the transaction.', 'bulk_set_new_values' => 'Use the inputs below to set new values. If you leave them empty, they will be made empty for all. Also, note that only withdrawals will be given a budget.', 'no_bulk_category' => 'Don\'t update category', 'no_bulk_budget' => 'Don\'t update budget', 'no_bulk_tags' => 'Don\'t update tag(s)', - 'bulk_edit' => 'Bulk edit', + 'mass_edit' => 'Edit selected individually', + 'bulk_edit' => 'Edit selected in bulk', + 'mass_delete' => 'Delete selected', 'cannot_edit_other_fields' => 'You cannot mass-edit other fields than the ones here, because there is no room to show them. Please follow the link and edit them by one-by-one, if you need to edit these fields.', 'no_budget' => '(no budget)', 'no_budget_squared' => '(no budget)', diff --git a/resources/views/v1/javascript/variables.twig b/resources/views/v1/javascript/variables.twig index 803eb3a4f2..5af0c92803 100644 --- a/resources/views/v1/javascript/variables.twig +++ b/resources/views/v1/javascript/variables.twig @@ -50,9 +50,13 @@ var helpPageTitle = "{{ trans('firefly.help_for_this_page')|escape('js') }}"; var noHelpForPage = "{{ trans('firefly.no_help_could_be_found')|escape('js') }}"; var noHelpForPageTitle = "{{ trans('firefly.no_help_title')|escape('js') }}"; -var edit_selected_txt = "{{ trans('firefly.edit')|escape('js') }}"; +var edit_selected_txt = "{{ trans('firefly.mass_edit')|escape('js') }}"; var edit_bulk_selected_txt = "{{ trans('firefly.bulk_edit')|escape('js') }}"; -var delete_selected_txt = "{{ trans('firefly.delete')|escape('js') }}"; +var delete_selected_txt = "{{ trans('firefly.mass_delete')|escape('js') }}"; + +var mass_edit_url = '{{ route('transactions.mass.edit', ['']) }}'; +var bulk_edit_url = '{{ route('transactions.bulk.edit', ['']) }}'; +var mass_delete_url = '{{ route('transactions.mass.delete', ['']) }}'; // for demo: var nextLabel = "{{ trans('firefly.intro_next_label')|escape('js') }}"; diff --git a/resources/views/v1/list/groups.twig b/resources/views/v1/list/groups.twig index 1a44199aa5..513bf79c2a 100644 --- a/resources/views/v1/list/groups.twig +++ b/resources/views/v1/list/groups.twig @@ -8,7 +8,7 @@ TODO: hide and show columns {{ groups.render|raw }}
- +
@@ -23,8 +23,16 @@ TODO: hide and show columns - {% for sum in group.sums %} - {{ formatAmountBySymbol(sum.amount, sum.currency_symbol, sum.currency_symbol_decimal_places) }}{% if loop.index != group.sums|length %},{% endif %} + {% for sum in group.sums %} + {% if group.transaction_type == 'Deposit' %} + {{ formatAmountBySymbol(sum.amount*-1, sum.currency_symbol, sum.currency_symbol_decimal_places) }}{% if loop.index != group.sums|length %},{% endif %} + {% elseif group.transaction_type == 'Transfer' %} + + {{ formatAmountBySymbol(sum.amount*-1, sum.currency_symbol, sum.currency_symbol_decimal_places, false) }}{% if loop.index != group.sums|length %},{% endif %}X + + {% else %} + {{ formatAmountBySymbol(sum.amount, sum.currency_symbol, sum.currency_symbol_decimal_places) }}{% if loop.index != group.sums|length %},{% endif %} + {% endif %} {% endfor %}   @@ -75,9 +83,23 @@ TODO: hide and show columns {{ transaction.description }} - {{ formatAmountBySymbol(transaction.amount, transaction.currency_symbol, transaction.currency_symbol_decimal_places) }} - {% if null != transaction.foreign_amount %} - ({{ formatAmountBySymbol(transaction.foreign_amount, transaction.foreign_currency_symbol, transaction.foreign_currency_symbol_decimal_places) }}) + {% if transaction.transaction_type_type == 'Deposit' %} + {{ formatAmountBySymbol(transaction.amount*-1, transaction.currency_symbol, transaction.currency_symbol_decimal_places) }} + {% if null != transaction.foreign_amount %} + ({{ formatAmountBySymbol(transaction.foreign_amount*-1, transaction.foreign_currency_symbol, transaction.foreign_currency_symbol_decimal_places) }}) + {% endif %} + {% elseif transaction.transaction_type_type == 'Transfer' %} + + {{ formatAmountBySymbol(transaction.amount*-1, transaction.currency_symbol, transaction.currency_symbol_decimal_places, false) }} + {% if null != transaction.foreign_amount %} + ({{ formatAmountBySymbol(transaction.foreign_amount*-1, transaction.foreign_currency_symbol, transaction.foreign_currency_symbol_decimal_places, false) }}) + {% endif %} + + {% else %} + {{ formatAmountBySymbol(transaction.amount, transaction.currency_symbol, transaction.currency_symbol_decimal_places) }} + {% if null != transaction.foreign_amount %} + ({{ formatAmountBySymbol(transaction.foreign_amount, transaction.foreign_currency_symbol, transaction.foreign_currency_symbol_decimal_places) }}) + {% endif %} {% endif %} @@ -106,7 +128,7 @@ TODO: hide and show columns
-
@@ -119,16 +141,14 @@ TODO: hide and show columns
- diff --git a/resources/views/v1/reports/partials/journals-audit.twig b/resources/views/v1/reports/partials/journals-audit.twig index f800753e16..1eb246fcd8 100644 --- a/resources/views/v1/reports/partials/journals-audit.twig +++ b/resources/views/v1/reports/partials/journals-audit.twig @@ -89,13 +89,13 @@ {{ journal.destination_account_name }} - TODO BUDGET + {# TODO BUDGET #} - TODO CATEGORY + {# TODO CATEGORY#} - TODO BILL + {#TODO BILL#} diff --git a/resources/views/v1/transactions/bulk/edit.twig b/resources/views/v1/transactions/bulk/edit.twig index fd4adf8a87..e5e9bfb2e6 100644 --- a/resources/views/v1/transactions/bulk/edit.twig +++ b/resources/views/v1/transactions/bulk/edit.twig @@ -7,16 +7,19 @@ {% block content %}
+

{{ 'mass_bulk_journals'|_ }}

+

{{ 'mass_bulk_journals_explain'|_ }}

+
@@ -28,28 +31,63 @@ + {% for journal in journals %} - {% if journal.transaction_count == 2 %} - + - + - - + + + - {% endif %} {% endfor %}
{{ trans('list.category') }} {{ trans('list.budget') }} {{ trans('list.tags') }} 
- + {{ journal.description }}{{ journal|journalTotalAmount }} + {% if journal.transaction_type_type == 'Deposit' %} + {{ formatAmountBySymbol(journal.amount*-1, journal.currency_symbol, journal.currency_symbol_decimal_places) }} + {% if null != journal.foreign_amount %} + ({{ formatAmountBySymbol(journal.foreign_amount*-1, journal.foreign_currency_symbol, journal.foreign_currency_symbol_decimal_places) }}) + {% endif %} + {% elseif journal.transaction_type_type == 'Transfer' %} + + {{ formatAmountBySymbol(journal.amount*-1, journal.currency_symbol, journal.currency_symbol_decimal_places, false) }} + {% if null != journal.foreign_amount %} + ({{ formatAmountBySymbol(journal.foreign_amount*-1, journal.foreign_currency_symbol, journal.foreign_currency_symbol_decimal_places, false) }}) + {% endif %} + + {% else %} + {{ formatAmountBySymbol(journal.amount, journal.currency_symbol, journal.currency_symbol_decimal_places) }} + {% if null != journal.foreign_amount %} + ({{ formatAmountBySymbol(journal.foreign_amount, journal.foreign_currency_symbol, journal.foreign_currency_symbol_decimal_places) }}) + {% endif %} + {% endif %} + + + {{ journal.date.formatLocalized(monthAndDayFormat) }}{{ journalCategories(journal)|raw }}{{ journalBudgets(journal)|raw }} + {% if journal.category_id != null %} + {{ journal.category_name }} + {% endif %} + + {% if journal.budget_id != null %} + {{ journal.budget_name }} + {% endif %} + {% for tag in journal.tags %} - - {{ tag.tag }} + + + {{ tag.name }} + {% endfor %} + {% if journal.journals_in_group > 1 %} + + {% endif %} +
@@ -107,21 +145,30 @@
- +
-
- + + +
+
+
+ {% endblock %} {% block scripts %} diff --git a/resources/views/v1/transactions/index.twig b/resources/views/v1/transactions/index.twig index 9ce51a3103..472fb8eb87 100644 --- a/resources/views/v1/transactions/index.twig +++ b/resources/views/v1/transactions/index.twig @@ -66,5 +66,11 @@ {% endblock %} {% block scripts %} - + {# old list script #} + {# #} + + {% endblock %} diff --git a/routes/breadcrumbs.php b/routes/breadcrumbs.php index 1797c9818e..b5d4a1c926 100644 --- a/routes/breadcrumbs.php +++ b/routes/breadcrumbs.php @@ -43,6 +43,7 @@ use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournalLink; use FireflyIII\Models\TransactionType; use FireflyIII\User; +use Illuminate\Support\Arr; use Illuminate\Support\Collection; if (!function_exists('limitStringLength')) { @@ -302,7 +303,8 @@ try { $breadcrumbs->push( trans('firefly.delete_attachment', ['name' => limitStringLength($attachment->filename)]), route('attachments.edit', [$attachment]) ); - } else { + } + else { throw new FireflyException('Cannot make breadcrumb for attachment connected to object of type ' . get_class($object)); } } @@ -1120,19 +1122,17 @@ try { // BULK EDIT Breadcrumbs::register( 'transactions.bulk.edit', - function (BreadcrumbsGenerator $breadcrumbs, Collection $journals): void { - if ($journals->count() > 0) { - $journalIds = $journals->pluck('id')->toArray(); - $what = strtolower($journals->first()->transactionType->type); - $breadcrumbs->parent('transactions.index', $what); - $breadcrumbs->push(trans('firefly.mass_bulk_journals'), route('transactions.bulk.edit', $journalIds)); + static function (BreadcrumbsGenerator $breadcrumbs, array $journals): void { + if (count($journals) > 0) { + $ids = Arr::pluck($journals, 'transaction_journal_id'); + $first = reset($journals); + $breadcrumbs->parent('transactions.index', strtolower($first['transaction_type_type'])); + $breadcrumbs->push(trans('firefly.mass_bulk_journals'), route('transactions.bulk.edit', $ids)); return; } $breadcrumbs->parent('index'); - - return; } );