From 05ee8dc44258e7c9e6dcb6e77afedeb92f3329a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Falc=C3=B3n?= Date: Sat, 30 May 2026 12:27:59 +0200 Subject: [PATCH] feat(categorize): show debtor and creditor names (#454) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## What Show the debtor and creditor names (when present) on the categorization page (`/transactions/categorize`). ## Changes - `TransactionController@categorize`: select `creditor_name` and `debtor_name` — they were never sent to the frontend. - `categorizer-card.tsx`: render Creditor/Debtor rows below the account when present, using the same i18n labels as the transaction columns. - `TransactionTest`: assert both names are exposed on the categorize page. ## Testing - `php artisan test --filter="debtor and creditor"` — passes. - pint, format, lint clean. --- .../Controllers/TransactionController.php | 2 +- .../transactions/categorizer-card.tsx | 31 +++++++++++++++++++ tests/Feature/TransactionTest.php | 23 ++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/TransactionController.php b/app/Http/Controllers/TransactionController.php index b7e30b63..2e8bd530 100644 --- a/app/Http/Controllers/TransactionController.php +++ b/app/Http/Controllers/TransactionController.php @@ -145,7 +145,7 @@ class TransactionController extends Controller ->with(['account.bank:id,name,logo', 'labels:id,name,color']) ->orderBy('transaction_date', 'desc') ->orderBy('id', 'desc') - ->get(['id', 'account_id', 'category_id', 'description', 'description_iv', 'transaction_date', 'amount', 'currency_code', 'notes', 'notes_iv']); + ->get(['id', 'account_id', 'category_id', 'description', 'description_iv', 'transaction_date', 'amount', 'currency_code', 'notes', 'notes_iv', 'creditor_name', 'debtor_name']); return Inertia::render('transactions/categorize', [ 'categories' => $categories, diff --git a/resources/js/components/transactions/categorizer-card.tsx b/resources/js/components/transactions/categorizer-card.tsx index 57d058e2..5efaf131 100644 --- a/resources/js/components/transactions/categorizer-card.tsx +++ b/resources/js/components/transactions/categorizer-card.tsx @@ -7,6 +7,7 @@ import { cn } from '@/lib/utils'; import { type Category, getCategoryColorClasses } from '@/types/category'; import { type DecryptedTransaction } from '@/types/transaction'; import { formatDateLong } from '@/utils/date'; +import { __ } from '@/utils/i18n'; import { CheckCircle2 } from 'lucide-react'; interface CategorizerCardProps { @@ -92,6 +93,36 @@ export function CategorizerCard({ /> )} + + {(transaction.creditor_name || + transaction.debtor_name) && ( +
+ {transaction.creditor_name && ( +
+
+ {__('Creditor')} +
+
+ { + transaction.creditor_name + } +
+
+ )} + {transaction.debtor_name && ( +
+
+ {__('Debtor')} +
+
+ { + transaction.debtor_name + } +
+
+ )} +
+ )} diff --git a/tests/Feature/TransactionTest.php b/tests/Feature/TransactionTest.php index 7015ccc4..bab81284 100644 --- a/tests/Feature/TransactionTest.php +++ b/tests/Feature/TransactionTest.php @@ -720,6 +720,29 @@ test('categorize page only returns uncategorized transactions', function () { ); }); +test('categorize page exposes debtor and creditor names', function () { + $user = User::factory()->onboarded()->create(); + $account = Account::factory()->create(['user_id' => $user->id]); + + $transaction = Transaction::factory()->create([ + 'user_id' => $user->id, + 'account_id' => $account->id, + 'category_id' => null, + 'creditor_name' => 'Acme Corp', + 'debtor_name' => 'Jane Doe', + ]); + + $response = actingAs($user)->get(route('transactions.categorize')); + + $response->assertSuccessful(); + $response->assertInertia(fn ($page) => $page + ->component('transactions/categorize') + ->where('transactions.0.id', $transaction->id) + ->where('transactions.0.creditor_name', 'Acme Corp') + ->where('transactions.0.debtor_name', 'Jane Doe') + ); +}); + test('categorize page does not return transactions from deleted accounts', function () { $user = User::factory()->onboarded()->create();