arrow_back Back to Course |

Personal finance with Laravel and Filament

Lesson 7 / 7
Lesson 7

Software Improvements and Conclusion

We have built a fully functional Personal Finance application with Laravel and Filament. We have accounts, transactions, budgets, and a dashboard. However, as “The Passionate Architect” would say, functionality is just the baseline. Truly great software is robust, secure, and delightful to use.

In this final lesson, we are going to pay down some technical debt, improve the user experience, and add those final touches that make an app feel “finished”.

1. Safety First: Manual Data Scoping

Throughout our development, you might have noticed a repetitive pattern. Every time we query Transaction, BankAccount, or Budget, we have to append ->where('user_id', auth()->id()).

This isn’t just annoying; it’s dangerous. If we forget this line in just one place, we could expose one user’s financial data to another. That is a critical security failure.

The Solution: Global Scopes

Laravel offers an elegant solution called Global Scopes. These allow us to add a constraint to all queries for a given model properly.

We can create a UserScope that automatically applies the where('user_id', auth()->id()) clause. To make this even cleaner, we can wrap the applying of this scope into a Trait (e.g., BelongsToAuthenticatedUser) and use it on all our user-owned models.

Now, our models secure themselves by default.

View the commit

2. Keeping Balances in Sync

Right now, if you create a transaction, the balance on the BankAccount model stays the same. You’d have to manually calculate it, which leads to desynchronized data.

We need the system to react to changes. When a transaction is created, we subtract (or add) the amount. When it’s deleted, we reverse it. When it’s updated, we handle the difference.

Enter Observers

We can generate an Observer to handle these model events:

bash
php artisan make:observer TransactionObserver --model=Transaction

In the observer, we handle the created, updated, and deleted methods to adjust the bank account balance automatically. This ensures our data remains consistent without cluttering our controllers or Filalment resources with logic.

View the commit

3. Better UX: Inline Creation

Imagine you are adding a transaction and realize you forgot to create the “Groceries” category. In a standard app, you’d have to leave the page, go to Categories, create it, come back, and restart your transaction. Frustrating.

Filament solves this with createOptionForm(). By adding this to our Select fields for Category, Budget, and BankAccount, users can create a new item within a modal without leaving the transaction flow.

Crucially, since these are new records, we must ensure they are assigned to the current user automatically behind the scenes.

View the commit

4. Making it Personal: Currency & Locale

Up until now, we’ve hardcoded ‘EUR’. But what if our user is in the US? or Japan?

We shouldn’t hardcode these preferences. Let’s move them to the database.

  1. Add currency and locale columns to the users table via a migration.
  2. Update the User model.
  3. Create a Profile page in Filament to let users manage these settings.

Now, every number in the app can be formatted according to the user’s actual preference.

Profile Settings Page

View the commit

Future Improvements

Our application is solid, but software is never “done”. Here are some challenges for you to tackle next:

  • Multi-currency Support: Handle exchange rates between accounts.
  • Recurring Transactions: Implement subscriptions or scheduled payments.
  • CSV Import/Export: Allow users to upload their bank statements.
  • Budget Alerts: Send email notifications when a budget is nearing its limit.
  • Shared Accounts: Allow partners to manage a single bank account together (Family features).
  • Performance: Install Laravel Debugbar to check for N+1 query problems.

Conclusion

Congratulations! You have built a secure, feature-rich Personal Finance application using the Laravel and Filament.

You’ve learned about Resources, Widgets, Relations, Observers, Global Scopes, and Custom Pages. You have a portfolio-ready project that solves a real problem.

View the final project documentation

Happy coding!

quiz

Knowledge Check

1. What is the primary benefit of using a Global Scope like `UserScope` in this application?

2. Which Filament method allows users to create a related record (like a Category) directly from a Select field?

3. Why do we use an Observer for the Transaction model in this lesson?