whisper-money/tests/Feature/Settings
Víctor Falcón 1bd2d80b14
fix(budgets): keep per-transaction email notifications opt-in (#735)
Budget email notifications shipped opt-in, then #733 turned all three on
by default. The per-transaction notice is the wrong one to force on: it
emails on **every single transaction** assigned to a budget, and a
catch-all budget matches all of them. This puts it back to opt-in and
leaves the limit alerts (close to limit, over limit) on by default.

## Why a second migration instead of editing the first one

`2026_07_24_100000_enable_budget_notifications_by_default` **has already
run in production** (batch 76). Laravel never re-runs an applied
migration, so editing it in place would have been inert: 382 budgets and
174 settings rows would keep the flag on, and the `user_settings` column
default would stay `true`.

That default matters beyond new signups: every settings controller
writes its own column through `setting()->updateOrCreate(...)`, so a
user who merely changed their chart colour scheme would get a settings
row with `budget_notify_on_new_transaction = 1` filled in by MySQL —
silently opted in, with the checkbox rendering as checked.

So the original migration is restored to its merged form and a new one
resets the flag: column default back to `false`, plus a one-off reset of
existing `user_settings` and `budgets` rows. It uses the query builder,
so `updated_at` is untouched — same as the force-enable did. 381 of the
382 affected budgets had not been touched by their owner since the
deploy, so the reset undoes a force-enable rather than a user's choice.

## Changes

- New migration resetting
`user_settings.budget_notify_on_new_transaction` (default + rows) and
`budgets.notify_on_new_transaction`.
- `BudgetController::store` and
`NotificationPreferenceController::index` fall back to `false` for the
per-transaction flag when a user has no settings row.
- `UserSettingFactory` matches the new default.

Users who want the per-transaction notice can still turn it on per
budget, or as their default for new budgets, in Settings →
Notifications.

## QA

Ran the migration against a real database and checked the end state:
`budget_notify_on_new_transaction` default `0` with all 151 settings
rows and 333 budgets reset, both limit flags default `1` and left on.

Then drove real transactions through the listener and queue on a live
budget (limit €300) and read the resulting mail off Mailhog:

| Event | Spent / limit | Email |
| --- | --- | --- |
| New transaction, default settings | €50 / €300 | none |
| Reaches 90% | €270 / €300 | «Presupuesto de Ocio» está cerca de su
límite |
| Exceeds the limit | €320 / €300 | «Presupuesto de Ocio» ha superado su
límite |
| New transaction, after opting in | €10 / €5000 | Nueva transacción en
«Presupuesto de Ocio» |

Assignment still happens in every case — only the email is suppressed.
265 tests green across the Budget/Setting/Notification suites, including
new assertions that the rendered defaults have the per-transaction flag
off and that a settings row created without the budget columns does not
opt the user in.
2026-07-25 12:36:13 +02:00
..
AccountPageTest.php Reorganize setting items 2025-11-07 18:23:08 +00:00
AccountTest.php feat(currencies): add Colombian and Dominican peso (#471) 2026-06-01 18:14:16 +02:00
BankTest.php refactor(api): standardize serialization via model $hidden (#492) 2026-06-05 13:57:34 +02:00
BudgetNotificationPreferenceTest.php fix(budgets): keep per-transaction email notifications opt-in (#735) 2026-07-25 12:36:13 +02:00
BudgetSettingsRedirectTest.php fix(settings): restore budgets settings redirect (#228) 2026-03-16 13:04:08 +01:00
CategoryTest.php refactor: remove HIDE_AUTH_BUTTONS launch gate and waitlist apparatus (#717) 2026-07-22 08:51:48 +02:00
CategoryTreeTest.php feat: parent/child category tree (#474) 2026-06-03 19:30:12 +02:00
ChartColorSchemeTest.php refactor: remove HIDE_AUTH_BUTTONS launch gate and waitlist apparatus (#717) 2026-07-22 08:51:48 +02:00
DeleteAccountPageTest.php fix(account): block deletion while subscription or trial is active (#531) 2026-06-14 20:46:44 +02:00
McpTokenTest.php feat(mcp): add write tools (Phase 2) (#690) 2026-07-17 15:25:03 +00:00
NetWorthChartLoanPreferenceTest.php refactor: remove HIDE_AUTH_BUTTONS launch gate and waitlist apparatus (#717) 2026-07-22 08:51:48 +02:00
NetWorthChartRealEstatePreferenceTest.php refactor: remove HIDE_AUTH_BUTTONS launch gate and waitlist apparatus (#717) 2026-07-22 08:51:48 +02:00
NotificationPreferenceTest.php feat(budgets): add per-budget email notifications (#731) 2026-07-24 12:52:03 +02:00
PasswordUpdateTest.php E2E Encryption 2025-11-07 14:21:25 +00:00
ProfileUpdateTest.php fix(account): block deletion while subscription or trial is active (#531) 2026-06-14 20:46:44 +02:00
TimezoneTest.php refactor: remove HIDE_AUTH_BUTTONS launch gate and waitlist apparatus (#717) 2026-07-22 08:51:48 +02:00
TwoFactorAuthenticationTest.php E2E Encryption 2025-11-07 14:21:25 +00:00