## Summary
Adds a **Notifications** section to the account settings page
(`/settings/account`, between Profile information and Update password)
where users can opt out of the daily "new transactions synced" email.
- New per-user preference `notify_on_bank_transactions_synced` on
`user_settings` (defaults to `true`, opt-out).
- `SendDailyBankTransactionsSyncedEmailJob` skips users who disabled it.
- Single generic `PATCH /settings/notifications` endpoint updates any
notification type via a key→column allowlist in
`NotificationPreferenceController::PREFERENCES`. Future notifications
only need a new entry there — no new route/controller.
- Email footer now links back to the settings section so users can
manage preferences.
## Testing
- `tests/Feature/Settings/NotificationPreferenceTest.php` — update,
unknown-key rejection, invalid value, auth, create-when-missing,
default-true, inertia prop.
- `tests/Feature/OpenBanking/SyncBankingConnectionJobTest.php` — email
not sent when disabled.
## Summary
- Adds **real estate** as a new account type (`real_estate`) for
tracking property assets within the existing Accounts page
- Properties store metadata (type, address, purchase price/date, area,
notes) in a dedicated `real_estate_details` table with a one-to-one
relationship to accounts
- Properties can be **linked to a loan account** (mortgage) to
implicitly calculate equity — property value counts as asset (+), linked
loan counts as liability (-)
- Market value is tracked as the account balance and uses "market value"
terminology throughout the UI
## What's included
### Backend
- `PropertyType` enum (Residential, Commercial, Land, Vacation, Other)
- `RealEstateDetail` model, factory, migration, policy
- `StoreRealEstateDetailRequest` and `UpdateRealEstateDetailRequest`
form requests
- `RealEstateDetailController` with `update()` for editing property
details
- Extended `Settings\AccountController@store` to create
`RealEstateDetail` when type is `real_estate`
- Extended `AccountController@show` to load real estate detail, linked
loan with bank info, and available loan accounts
- Extended `AccountController@index` SQL ordering to include
`real_estate`
- Conditional validation rules in `StoreAccountRequest` for real estate
fields
### Frontend
- New `real_estate` type in `account.ts` with `PropertyType`,
`AreaUnit`, `RealEstateDetail` interface, and helper functions
- Conditional real estate fields in `account-form.tsx` (property type,
address, purchase price, purchase date, area, linked loan, notes)
- `PropertyDetailsCard` component in `Accounts/Show.tsx` with view and
inline edit modes
- "Update market value" terminology in balance update buttons for real
estate accounts
- `real_estate` added to account type ordering and groups on the Index
page
- Wayfinder routes regenerated
### Tests
- 22 feature tests covering creation, validation, show page, index
ordering, updating details, IDOR protection, model relationships, and
soft delete behavior
- Unit test updates for `AccountType` enum (`reducesNetWorth`,
`isNonTransactional`)
### Translations
- 32 new Spanish translation strings for all real estate UI
## Design decisions
- Real estate accounts are **non-transactional** (like
investment/retirement) — balance-only tracking for now. Future iteration
will link transactions directly for rental income/expense tracking
- **Single loan per property** via direct FK from
`real_estate_details.linked_loan_account_id`
- No encryption on address/notes fields (opted out per discussion)
- No separate sidebar page — real estate is a grouped section within the
existing Accounts page
## 🚪 Why?
### Problem
PHPStan was running with a baseline of 56 suppressed errors, meaning
static analysis was not enforcing type safety across a significant
portion of the codebase. These errors were real type mismatches,
redundant null-safety operators, and incorrect PHPDoc annotations that
could mask bugs and make the code harder to reason about.
## 🔑 What?
### Changes
- Add `@property` PHPDoc annotations to `Account`, `BankingConnection`,
`ExchangeRate`, and `Transaction` models so Enum casts and typed columns
are visible to PHPStan
- Add `instanceof User` guards in `ScheduleDripEmailsListener`,
`SyncUserToResendListener`, and `FortifyServiceProvider` to properly
narrow `Authenticatable` to `App\Models\User`
- Remove redundant `?? false` and unnecessary nullsafe `?->value` in
`HandleInertiaRequests`
- Fix `SyncBankingConnectionJob`: use `->name` instead of `?->name` on
an always-loaded `bank` relation
- Remove `is_countable()` guard in `BalanceLookup` (parameter is always
`Collection|array`, both countable)
- Remove `?? []` / `?? default` fallbacks on fully-typed array keys
across `BalanceSyncService`, `BinanceBalanceSyncService`,
`BinanceClient`, `BitpandaBalanceSyncService`, `BitpandaClient`,
`IndexaCapitalClient`, `IndexaCapitalBalanceSyncService`, and
`AuthorizationController`
- Fix `BinanceClient::publicClient()` `retry()` call: use `when:` named
argument and `\Throwable` type hint to match `PendingRequest::retry()`
signature
- Update `IndexaCapitalClient::getPerformance()` `@return` to include
`portfolios` and `net_amounts` keys; simplify sync service to remove
dead null checks
- Replace nullsafe chain with ternary in `BudgetPeriodService`
- Replace `match` statement in `SetupMainUser` with `if/else` to
eliminate always-true comparison
- Clear `phpstan-baseline.neon` entirely (was 56 suppressed errors, now
0)
## ✅ Verification
### Tests
- Existing tests pass: PHPStan level 5 reports 0 errors with empty
baseline
## Summary
- Add a new **Chart color scheme** dropdown in Settings > Appearance
allowing users to choose between 4 color palettes: **Colorful** (new
default), **Neutral** (previous zinc grayscale), **Blue**, and **Pink**
- Persist the setting in a new `user_settings` table with instant
client-side feedback via localStorage + cookie
- All charts across dashboard, categories, budgets, and cashflow update
instantly when switching schemes
- Reduced colorful palette intensity (shifted from 500/600 to 300/400
range) for lower contrast