diff --git a/app/Http/Controllers/Transaction/MassController.php b/app/Http/Controllers/Transaction/MassController.php
index 2bb0a44d27..aea0bf9d9d 100644
--- a/app/Http/Controllers/Transaction/MassController.php
+++ b/app/Http/Controllers/Transaction/MassController.php
@@ -26,6 +26,7 @@ use Carbon\Carbon;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Http\Requests\MassDeleteJournalRequest;
use FireflyIII\Http\Requests\MassEditJournalRequest;
+use FireflyIII\Http\Requests\MassEditBulkJournalRequest;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
@@ -131,7 +132,7 @@ class MassController extends Controller
// skip transactions that have multiple destinations, multiple sources or are an opening balance.
$filtered = new Collection;
$messages = [];
- // @var TransactionJournal
+ /** @var TransactionJournal $journal */
foreach ($journals as $journal) {
$sources = $journal->sourceAccountList();
$destinations = $journal->destinationAccountList();
@@ -200,6 +201,70 @@ class MassController extends Controller
return view('transactions.mass.edit', compact('journals', 'subTitle', 'accounts', 'budgets'));
}
+ /**
+ * @param Collection $journals
+ *
+ * @return View
+ */
+ public function editBulk(Collection $journals)
+ {
+ $subTitle = trans('firefly.mass_edit_bulk_journals');
+
+ // skip transactions that have multiple destinations, multiple sources or are an opening balance.
+ $filtered = new Collection;
+ $messages = [];
+ /** @var TransactionJournal $journal */
+ foreach ($journals as $journal) {
+ $sources = $journal->sourceAccountList();
+ $destinations = $journal->destinationAccountList();
+ if ($sources->count() > 1) {
+ $messages[] = trans('firefly.cannot_edit_multiple_source', ['description' => $journal->description, 'id' => $journal->id]);
+ continue;
+ }
+
+ if ($destinations->count() > 1) {
+ $messages[] = trans('firefly.cannot_edit_multiple_dest', ['description' => $journal->description, 'id' => $journal->id]);
+ continue;
+ }
+ if (TransactionType::OPENING_BALANCE === $journal->transactionType->type) {
+ $messages[] = trans('firefly.cannot_edit_opening_balance');
+ continue;
+ }
+
+ // cannot edit reconciled transactions / journals:
+ if ($journal->transactions->first()->reconciled) {
+ $messages[] = trans('firefly.cannot_edit_reconciled', ['description' => $journal->description, 'id' => $journal->id]);
+ continue;
+ }
+
+ $filtered->push($journal);
+ }
+
+ if (count($messages) > 0) {
+ Session::flash('info', $messages);
+ }
+
+ // put previous url in session
+ $this->rememberPreviousUri('transactions.mass-edit-bulk.uri');
+ Session::flash('gaEventCategory', 'transactions');
+ Session::flash('gaEventAction', 'mass-edit-bulk');
+
+ // collect some useful meta data for the mass edit:
+ $filtered->each(
+ function (TransactionJournal $journal) {
+ $journal->transaction_count = $journal->transactions()->count();
+ }
+ );
+
+ if (0 === $filtered->count()) {
+ Session::flash('error', trans('firefly.no_edit_multiple_left'));
+ }
+
+ $journals = $filtered;
+
+ return view('transactions.mass.edit-bulk', compact('journals', 'subTitle'));
+ }
+
/**
* @param MassEditJournalRequest $request
* @param JournalRepositoryInterface $repository
@@ -264,4 +329,24 @@ class MassController extends Controller
// redirect to previous URL:
return redirect($this->getPreviousUri('transactions.mass-edit.uri'));
}
+
+ /**
+ * @param MassEditBulkJournalRequest $request
+ * @param JournalRepositoryInterface $repository
+ *
+ * @return mixed
+ */
+ public function updateBulk(MassEditBulkJournalRequest $request, JournalRepositoryInterface $repository)
+ {
+ $journalIds = $request->get('journals');
+ $count = 0;
+ if (is_array($journalIds)) {
+ $repository->updateBulk($journalIds, $request->get('category'), $request->get('tags'));
+ }
+ Preferences::mark();
+ Session::flash('success', trans('firefly.mass_edited_transactions_success', ['amount' => $count]));
+
+ // redirect to previous URL:
+ return redirect($this->getPreviousUri('transactions.mass-edit-bulk.uri'));
+ }
}
diff --git a/app/Http/Requests/MassEditBulkJournalRequest.php b/app/Http/Requests/MassEditBulkJournalRequest.php
new file mode 100644
index 0000000000..c3024e6729
--- /dev/null
+++ b/app/Http/Requests/MassEditBulkJournalRequest.php
@@ -0,0 +1,48 @@
+.
+ */
+declare(strict_types=1);
+
+namespace FireflyIII\Http\Requests;
+
+/**
+ * Class MassEditBulkJournalRequest.
+ */
+class MassEditBulkJournalRequest extends Request
+{
+ /**
+ * @return bool
+ */
+ public function authorize()
+ {
+ // Only allow logged in users
+ return auth()->check();
+ }
+
+ /**
+ * @return array
+ */
+ public function rules()
+ {
+ // fixed
+
+ return [];
+ }
+}
diff --git a/app/Repositories/Journal/JournalRepository.php b/app/Repositories/Journal/JournalRepository.php
index c71afd2e20..43b66715fd 100644
--- a/app/Repositories/Journal/JournalRepository.php
+++ b/app/Repositories/Journal/JournalRepository.php
@@ -24,7 +24,9 @@ namespace FireflyIII\Repositories\Journal;
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;
@@ -432,6 +434,47 @@ class JournalRepository implements JournalRepositoryInterface
return $journal;
}
+ /**
+ * @param array $journals
+ * @param var $category
+ * @param var $tags
+ *
+ * @return int
+ */
+ public function updateBulk(array $journals, $category, $tags): int
+ {
+ $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();
+ }
+ }
+
+ // 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 $count;
+ }
+
/**
* Same as above but for transaction journal with multiple transactions.
*
diff --git a/app/Repositories/Journal/JournalRepositoryInterface.php b/app/Repositories/Journal/JournalRepositoryInterface.php
index a136ed1784..a895e03833 100644
--- a/app/Repositories/Journal/JournalRepositoryInterface.php
+++ b/app/Repositories/Journal/JournalRepositoryInterface.php
@@ -161,6 +161,15 @@ interface JournalRepositoryInterface
*/
public function update(TransactionJournal $journal, array $data): TransactionJournal;
+ /**
+ * @param array $journals
+ * @param var $category
+ * @param var $tags
+ *
+ * @return int
+ */
+ public function updateBulk(array $journals, $category, $tags): int;
+
/**
* @param TransactionJournal $journal
* @param array $data
diff --git a/public/js/ff/transactions/list.js b/public/js/ff/transactions/list.js
index 1a9b5d1230..4f013541ba 100644
--- a/public/js/ff/transactions/list.js
+++ b/public/js/ff/transactions/list.js
@@ -18,7 +18,7 @@
* along with Firefly III. If not, see
{{ trans('list.description') }} | diff --git a/routes/web.php b/routes/web.php index e368b4fc71..03c1c4caeb 100755 --- a/routes/web.php +++ b/routes/web.php @@ -784,8 +784,10 @@ Route::group( Route::group( ['middleware' => 'user-full-auth', 'namespace' => 'Transaction', 'prefix' => 'transactions/mass', 'as' => 'transactions.mass.'], function () { Route::get('edit/{journalList}', ['uses' => 'MassController@edit', 'as' => 'edit']); + Route::get('edit/bulk/{journalList}', ['uses' => 'MassController@editBulk', 'as' => 'edit-bulk']); Route::get('delete/{journalList}', ['uses' => 'MassController@delete', 'as' => 'delete']); Route::post('update', ['uses' => 'MassController@update', 'as' => 'update']); + Route::post('update/bulk', ['uses' => 'MassController@updateBulk', 'as' => 'update-bulk']); Route::post('destroy', ['uses' => 'MassController@destroy', 'as' => 'destroy']); } );
---|