From 7784f0d4fb535cffab5cacc8c5919c81fc4d8ca3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Falc=C3=B3n?= Date: Wed, 3 Jun 2026 17:59:24 +0200 Subject: [PATCH] refactor(banks): add Bank::availableForUser scope (#480) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## What The "public banks + user's own banks" query was repeated in **5 controllers** (Transaction ×2, Settings/Bank, Budget, Cashflow, Onboarding). New `Bank::availableForUser($user)` scope; all 5 sites use it. Bonus: the Onboarding variant had no `where()` grouping around `whereNull/orWhere` — harmless today (no other constraints) but a latent precedence bug. The scope always groups. ## Stats - **-31 / +24 lines**, 5 call sites → 1 definition ## Checks - `php artisan test --filter="Bank|Transaction|Budget|Cashflow|Onboarding"` — 612 passed (2707 assertions), 1 skipped - `vendor/bin/pint --dirty` — pass Part of duplication-removal series (#475–#479). --- app/Http/Controllers/BudgetController.php | 5 +---- app/Http/Controllers/CashflowController.php | 5 +---- app/Http/Controllers/OnboardingController.php | 3 +-- app/Http/Controllers/Settings/BankController.php | 6 +----- app/Http/Controllers/TransactionController.php | 10 ++-------- app/Models/Bank.php | 15 +++++++++++++++ 6 files changed, 21 insertions(+), 23 deletions(-) diff --git a/app/Http/Controllers/BudgetController.php b/app/Http/Controllers/BudgetController.php index 8587192b..6d358b79 100644 --- a/app/Http/Controllers/BudgetController.php +++ b/app/Http/Controllers/BudgetController.php @@ -95,10 +95,7 @@ class BudgetController extends Controller ->get(['id', 'name', 'name_iv', 'encrypted', 'bank_id', 'type', 'currency_code']); $banks = Bank::query() - ->where(function ($q) use ($user) { - $q->whereNull('user_id') - ->orWhere('user_id', $user->id); - }) + ->availableForUser($user) ->orderBy('name') ->get(['id', 'name', 'logo']); diff --git a/app/Http/Controllers/CashflowController.php b/app/Http/Controllers/CashflowController.php index 5dee091b..50036a51 100644 --- a/app/Http/Controllers/CashflowController.php +++ b/app/Http/Controllers/CashflowController.php @@ -27,10 +27,7 @@ class CashflowController extends Controller ->get(['id', 'name', 'name_iv', 'encrypted', 'bank_id', 'type', 'currency_code']); $banks = Bank::query() - ->where(function ($q) use ($user) { - $q->whereNull('user_id') - ->orWhere('user_id', $user->id); - }) + ->availableForUser($user) ->orderBy('name') ->get(['id', 'name', 'logo']); diff --git a/app/Http/Controllers/OnboardingController.php b/app/Http/Controllers/OnboardingController.php index 0374c197..3dac4e27 100644 --- a/app/Http/Controllers/OnboardingController.php +++ b/app/Http/Controllers/OnboardingController.php @@ -19,8 +19,7 @@ class OnboardingController extends Controller $user = $request->user(); $banks = Bank::query() - ->whereNull('user_id') - ->orWhere('user_id', $user->id) + ->availableForUser($user) ->orderBy('name') ->get(['id', 'name', 'logo']); diff --git a/app/Http/Controllers/Settings/BankController.php b/app/Http/Controllers/Settings/BankController.php index 8fb7ec09..aa48803b 100644 --- a/app/Http/Controllers/Settings/BankController.php +++ b/app/Http/Controllers/Settings/BankController.php @@ -14,11 +14,7 @@ class BankController extends Controller { public function index(Request $request): JsonResponse { - $query = Bank::query() - ->where(function (Builder $q) { - $q->whereNull('user_id') - ->orWhere('user_id', auth()->id()); - }); + $query = Bank::query()->availableForUser($request->user()); $search = trim((string) $request->input('search', '')); diff --git a/app/Http/Controllers/TransactionController.php b/app/Http/Controllers/TransactionController.php index 2e8bd530..6f9e3fa5 100644 --- a/app/Http/Controllers/TransactionController.php +++ b/app/Http/Controllers/TransactionController.php @@ -82,10 +82,7 @@ class TransactionController extends Controller ->get(['id', 'name', 'name_iv', 'encrypted', 'bank_id', 'type', 'currency_code']); $banks = Bank::query() - ->where(function ($q) use ($user) { - $q->whereNull('user_id') - ->orWhere('user_id', $user->id); - }) + ->availableForUser($user) ->orderBy('name') ->get(['id', 'name', 'logo']); @@ -127,10 +124,7 @@ class TransactionController extends Controller ->get(['id', 'name', 'name_iv', 'encrypted', 'bank_id', 'type', 'currency_code']); $banks = Bank::query() - ->where(function ($q) use ($user) { - $q->whereNull('user_id') - ->orWhere('user_id', $user->id); - }) + ->availableForUser($user) ->orderBy('name') ->get(['id', 'name', 'logo']); diff --git a/app/Models/Bank.php b/app/Models/Bank.php index dd865726..19dcf822 100644 --- a/app/Models/Bank.php +++ b/app/Models/Bank.php @@ -3,6 +3,7 @@ namespace App\Models; use Database\Factories\BankFactory; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Concerns\HasUuids; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; @@ -21,6 +22,20 @@ class Bank extends Model 'user_id', ]; + /** + * Scope to banks visible to the given user: public banks plus their own. + * + * @param Builder $query + * @return Builder + */ + public function scopeAvailableForUser(Builder $query, User $user): Builder + { + return $query->where(function (Builder $q) use ($user) { + $q->whereNull('user_id') + ->orWhere('user_id', $user->id); + }); + } + /** @return BelongsTo */ public function user(): BelongsTo {