diff --git a/app/Http/Controllers/Transaction/BulkController.php b/app/Http/Controllers/Transaction/BulkController.php index 9df614045c..2dfecca07b 100644 --- a/app/Http/Controllers/Transaction/BulkController.php +++ b/app/Http/Controllers/Transaction/BulkController.php @@ -26,12 +26,14 @@ namespace FireflyIII\Http\Controllers\Transaction; use ExpandedForm; use FireflyIII\Http\Controllers\Controller; -use FireflyIII\Http\Requests\MassEditBulkJournalRequest; +use FireflyIII\Http\Requests\BulkEditJournalRequest; use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionType; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; +use Illuminate\Http\Request; use Illuminate\Support\Collection; +use Log; use Preferences; use Session; use View; @@ -65,7 +67,7 @@ class BulkController extends Controller * * @return View */ - public function edit(Collection $journals) + public function edit(Request $request, Collection $journals) { $subTitle = trans('firefly.mass_bulk_journals'); @@ -101,11 +103,11 @@ class BulkController extends Controller } if (count($messages) > 0) { - Session::flash('info', $messages); + $request->session()->flash('info', $messages); } // put previous url in session - $this->rememberPreviousUri('transactions.mass-edit-bulk.uri'); + $this->rememberPreviousUri('transactions.bulk-edit.uri'); // get list of budgets: /** @var BudgetRepositoryInterface $repository */ @@ -119,33 +121,58 @@ class BulkController extends Controller ); if (0 === $filtered->count()) { - Session::flash('error', trans('firefly.no_edit_multiple_left')); + $request->session()->flash('error', trans('firefly.no_edit_multiple_left')); } $journals = $filtered; - return view('transactions.bulk.edit', compact('journals', 'subTitle','budgetList')); + return view('transactions.bulk.edit', compact('journals', 'subTitle', 'budgetList')); } /** - * @param MassEditBulkJournalRequest $request + * @param BulkEditJournalRequest $request * @param JournalRepositoryInterface $repository * * @return mixed */ - public function updateBulk(MassEditBulkJournalRequest $request, JournalRepositoryInterface $repository) + public function update(BulkEditJournalRequest $request, JournalRepositoryInterface $repository) { - $journalIds = $request->get('journals'); - $count = 0; + $journalIds = $request->get('journals'); + $ignoreCategory = intval($request->get('ignore_category')) === 1; + $ignoreBudget = intval($request->get('ignore_budget')) === 1; + $ignoreTags = intval($request->get('ignore_tags')) === 1; + $count = 0; if (is_array($journalIds)) { - $count = $repository->updateBulk($journalIds, $request->get('category'), $request->get('tags')); + foreach ($journalIds as $journalId) { + $journal = $repository->find(intval($journalId)); + if (!is_null($journal)) { + $count++; + Log::debug(sprintf('Found journal #%d', $journal->id)); + // update category if not told to ignore + if ($ignoreCategory === false) { + Log::debug(sprintf('Set category to %s', $request->string('category'))); + $repository->updateCategory($journal, $request->string('category')); + } + // update budget if not told to ignore (and is withdrawal) + if ($ignoreBudget === false) { + Log::debug(sprintf('Set budget to %d', $request->integer('budget_id'))); + $repository->updateBudget($journal, $request->integer('budget_id')); + } + if ($ignoreTags === false) { + Log::debug(sprintf('Set tags to %s', $request->string('budget_id'))); + $repository->updateTags($journal, explode(',', $request->string('tags'))); + } + // update tags if not told to ignore (and is withdrawal) + } + } } + Preferences::mark(); - Session::flash('success', trans('firefly.mass_edited_transactions_success', ['amount' => $count])); + $request->session()->flash('success', trans('firefly.mass_edited_transactions_success', ['amount' => $count])); // redirect to previous URL: - return redirect($this->getPreviousUri('transactions.mass-edit-bulk.uri')); + return redirect($this->getPreviousUri('transactions.bulk-edit.uri')); } } \ No newline at end of file diff --git a/app/Http/Controllers/Transaction/MassController.php b/app/Http/Controllers/Transaction/MassController.php index 734bbe1397..f19e12df7b 100644 --- a/app/Http/Controllers/Transaction/MassController.php +++ b/app/Http/Controllers/Transaction/MassController.php @@ -214,7 +214,7 @@ class MassController extends Controller if (is_array($journalIds)) { foreach ($journalIds as $journalId) { $journal = $repository->find(intval($journalId)); - if ($journal) { + if (!is_null($journal)) { // get optional fields: $what = strtolower($journal->transactionTypeStr()); $sourceAccountId = $request->get('source_account_id')[$journal->id] ?? 0; diff --git a/app/Http/Requests/MassEditBulkJournalRequest.php b/app/Http/Requests/BulkEditJournalRequest.php similarity index 85% rename from app/Http/Requests/MassEditBulkJournalRequest.php rename to app/Http/Requests/BulkEditJournalRequest.php index c3024e6729..4aefd85029 100644 --- a/app/Http/Requests/MassEditBulkJournalRequest.php +++ b/app/Http/Requests/BulkEditJournalRequest.php @@ -1,6 +1,6 @@ 'required|belongsToUser:transaction_journals,id', + ]; } } diff --git a/app/Http/Requests/Request.php b/app/Http/Requests/Request.php index 92916f77f4..dca2d3f774 100644 --- a/app/Http/Requests/Request.php +++ b/app/Http/Requests/Request.php @@ -143,7 +143,7 @@ class Request extends FormRequest * * @return int */ - protected function integer(string $field): int + public function integer(string $field): int { return intval($this->get($field)); } diff --git a/app/Repositories/Journal/JournalRepository.php b/app/Repositories/Journal/JournalRepository.php index 43b66715fd..7bf6bb78cd 100644 --- a/app/Repositories/Journal/JournalRepository.php +++ b/app/Repositories/Journal/JournalRepository.php @@ -22,14 +22,15 @@ declare(strict_types=1); namespace FireflyIII\Repositories\Journal; +use DB; use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; -use FireflyIII\Models\Category; use FireflyIII\Models\Note; 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 Illuminate\Support\Collection; use Illuminate\Support\MessageBag; @@ -435,44 +436,40 @@ class JournalRepository implements JournalRepositoryInterface } /** - * @param array $journals - * @param var $category - * @param var $tags + * @param TransactionJournal $journal + * @param int $budgetId * - * @return int + * @return TransactionJournal */ - public function updateBulk(array $journals, $category, $tags): int + public function updateBudget(TransactionJournal $journal, int $budgetId): TransactionJournal { - $count = 0; - foreach ($journals as $journalId) { - $journal = $this->find(intval($journalId)); - if ($journal) { - // update category: - if (isset($category)) { - $categoryToReplace = Category::firstOrCreateEncrypted(['name' => strval($category), 'user_id' => $journal->user->id]); - $journal->categories()->sync([$categoryToReplace->id]); - /** @var Transaction $transaction */ - foreach ($journal->transactions()->getResults() as $transaction) { - $transaction->categories()->sync([$categoryToReplace->id]); - $transaction->touch(); - } - } + if ($budgetId === 0) { + $journal->budgets()->detach(); + $journal->save(); - // update tags: - if (isset($tags)) { - $tagsToReplace = []; - foreach (explode(',', strval($tags)) as $tag) { - array_push($tagsToReplace, Tag::firstOrCreateEncrypted(['tag' => $tag, 'user_id' => $journal->user->id])->id); - } - $journal->tags()->sync($tagsToReplace); - } - - $journal->touch(); - ++$count; - } + return $journal; } + $this->storeBudgetWithJournal($journal, $budgetId); - return $count; + return $journal; + } + + /** + * @param TransactionJournal $journal + * @param string $category + * + * @return TransactionJournal + */ + public function updateCategory(TransactionJournal $journal, string $category): TransactionJournal + { + Log::debug(sprintf('In updateCategory("%s")', $category)); + $journal->categories()->detach(); + if (strlen($category) === 0) { + return $journal; + } + $this->storeCategoryWithJournal($journal, $category); + + return $journal; } /** @@ -535,4 +532,48 @@ class JournalRepository implements JournalRepositoryInterface return $journal; } + + /** + * Update tags. + * + * @param TransactionJournal $journal + * @param array $array + * + * @return bool + */ + public 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; + } } diff --git a/app/Repositories/Journal/JournalRepositoryInterface.php b/app/Repositories/Journal/JournalRepositoryInterface.php index 1e765722c0..5a99125173 100644 --- a/app/Repositories/Journal/JournalRepositoryInterface.php +++ b/app/Repositories/Journal/JournalRepositoryInterface.php @@ -161,13 +161,20 @@ interface JournalRepositoryInterface public function update(TransactionJournal $journal, array $data): TransactionJournal; /** - * @param array $journals - * @param var $category - * @param var $tags + * @param TransactionJournal $journal + * @param int $budgetId * - * @return int + * @return TransactionJournal */ - public function updateBulk(array $journals, $category, $tags): int; + public function updateBudget(TransactionJournal $journal, int $budgetId): TransactionJournal; + + /** + * @param TransactionJournal $journal + * @param string $category + * + * @return TransactionJournal + */ + public function updateCategory(TransactionJournal $journal, string $category): TransactionJournal; /** * @param TransactionJournal $journal @@ -176,4 +183,12 @@ interface JournalRepositoryInterface * @return TransactionJournal */ public function updateSplitJournal(TransactionJournal $journal, array $data): TransactionJournal; + + /** + * @param TransactionJournal $journal + * @param array $tags + * + * @return bool + */ + public function updateTags(TransactionJournal $journal, array $tags): bool; } diff --git a/app/Repositories/Journal/SupportJournalsTrait.php b/app/Repositories/Journal/SupportJournalsTrait.php index 6584e18a80..fd856d9b56 100644 --- a/app/Repositories/Journal/SupportJournalsTrait.php +++ b/app/Repositories/Journal/SupportJournalsTrait.php @@ -100,6 +100,7 @@ trait SupportJournalsTrait $budget = Budget::find($budgetId); $journal->budgets()->save($budget); } + $journal->touch(); } /** @@ -112,6 +113,7 @@ trait SupportJournalsTrait $category = Category::firstOrCreateEncrypted(['name' => $category, 'user_id' => $journal->user_id]); $journal->categories()->save($category); } + $journal->touch(); } /** diff --git a/app/Repositories/Journal/UpdateJournalsTrait.php b/app/Repositories/Journal/UpdateJournalsTrait.php index e56b62d73a..eb16eaeda3 100644 --- a/app/Repositories/Journal/UpdateJournalsTrait.php +++ b/app/Repositories/Journal/UpdateJournalsTrait.php @@ -37,6 +37,7 @@ use Log; */ trait UpdateJournalsTrait { + /** * When the user edits a split journal, each line is missing crucial data:. * @@ -121,47 +122,5 @@ trait UpdateJournalsTrait $transaction->save(); } - /** - * Update tags. - * - * @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; - } } diff --git a/resources/lang/en_US/firefly.php b/resources/lang/en_US/firefly.php index 9f09d2d2b8..559caacafc 100644 --- a/resources/lang/en_US/firefly.php +++ b/resources/lang/en_US/firefly.php @@ -730,7 +730,10 @@ return [ '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.', - '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.', + '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', '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' => 'none', diff --git a/resources/views/transactions/bulk/edit.twig b/resources/views/transactions/bulk/edit.twig index 1e8ece9167..5c7c3d0cc8 100644 --- a/resources/views/transactions/bulk/edit.twig +++ b/resources/views/transactions/bulk/edit.twig @@ -5,14 +5,8 @@ {% endblock %} {% block content %} -