whisper-money/tests
Víctor Falcón 0f8eca50d0
fix: stop double-dispatching transaction listeners (N+1 insert into jobs) (#620)
## What & why

Fixes the Sentry N+1 **PHP-LARAVEL-3V** — `N+1 insert into jobs` on
`POST /transactions`.

### Root cause
Laravel's **event discovery is on by default** (the base
`EventServiceProvider` sets `$shouldDiscoverEvents = true`, and this app
has no subclass to turn it off), so every listener in `app/Listeners` is
already wired to its event by its `handle()` type-hint.
`AppServiceProvider::boot()` was **also** registering six of them with
`Event::listen(...)`, so each ended up registered **twice** — every
queued listener published its job twice per event.

Concretely, creating a transaction dispatched
`AssignTransactionToBudget` and `CategorizeTransactionWithAi` twice each
→ repeated `insert into jobs` in one request. (The same bug made
`PostStripeEventToDiscord` post to Discord twice per webhook,
`ApplyAutomationRules` run twice, etc.)

## Changes
1. **`AppServiceProvider`** — drop the redundant explicit
`Event::listen` calls and rely on discovery, which already wires every
listener exactly once (`ScheduleDripEmailsListener` and
`SyncUserToResendListener` were discovery-only already). Verified with
`php artisan event:list`: each event now has a single listener, and the
synchronous `ApplyAutomationRules` still runs first on
`TransactionCreated`.
2. **`CategorizeTransactionWithAi`** — add `shouldQueue()` so the job
isn't even published when it would immediately no-op (already
categorized by a rule, encrypted, or user not AI-eligible — the default,
since AI is opt-in). The same guard still runs in `handle()` because
state can change while the job waits.

Together these remove the second `insert into jobs` on transaction
creation for the common (non-AI) path.

## Tests
- New `tests/Feature/Ai/CategorizeTransactionWithAiListenerTest.php`:
the AI job is queued **once** for an eligible uncategorized transaction,
and **not at all** when the user has no AI consent or the transaction is
already categorized.
- Full suite: **1828 passing**. The one failure (`DashboardTest` → 409)
is **pre-existing on `main`** (Inertia asset-version mismatch from a
local build manifest) and reproduces with these changes reverted —
unrelated to this PR.

Fixes PHP-LARAVEL-3V
2026-07-02 13:26:45 +00:00
..
.pest Speed up PR CI browser path (#365) 2026-05-07 20:40:13 +01:00
Browser feat(onboarding): auto-enable AI for connected banks, ask the rest (#618) 2026-07-01 07:26:52 +00:00
Feature fix: stop double-dispatching transaction listeners (N+1 insert into jobs) (#620) 2026-07-02 13:26:45 +00:00
Performance feat(transactions): make new-transaction marker cross-device (#611) 2026-06-29 19:11:37 +02:00
Support test(open-banking): e2e coverage for Enable Banking connection flows (#509) 2026-06-09 11:58:50 +02:00
Unit feat(banking): let Wise credentials be updated (#588) 2026-06-23 09:54:31 +00:00
Pest.php refactor(banking): scalable per-provider sync via a syncer factory (#545) 2026-06-16 16:25:29 +02:00
TestCase.php Remove encryption from browser tests and demo user (#129) 2026-02-17 11:45:27 +01:00
bootstrap.php chore: upgrade Laravel 12 to 13 (#242) 2026-03-25 12:56:33 +00:00