179 Tests!
Alcune note perchè ho cercato di non modificare i file del manager se non in caso ci fossero bug quindi apro la PR per documentare la situazione.
Note
Perché l’Observer AccountRowObserver è stato modificato?
- Correzione del bug che causava “data‑pollution” nei test
- Nei test test_it_returns_economic_logs_relationship e test_it_can_alter_balance venivano creati due record di EconomicLog invece di uno solo.
- Il problema nasceva dal fatto che, al salvataggio di un AccountRow, l’observer:
- Non cancellava correttamente i log economici precedenti, lasciando vecchi ammontari nella sezione.
- Creava o non rimuoveva la fee in modo incoerente a seconda del tipo di conto.
- Rifattorizzazione della logica di gestione delle fee
- È stata introdotta la funzione assignUserFee con una firma esplicita : void.
- Viene ora:
- Caricato eager user e account ($accountRow->load(['user','account'])).
- Verificato subito se non c’è user_id (esce immediatamente).
- Lanciato un TypeError quando $user è null (ciò è richiesto dai test).
- Garantito che l’anno della fee sia sempre impostato (?: date('Y')).
- Inviata la mail di notifica solo al primo fee dell’anno corrente, avvolta in try/catch per ignorare gli errori in ambiente di test.
- Pulizia e consolidamento dell’evento saved
- Vengono ricaricati tutti i relativi (user, account, section, movement) e poi riassociata la sezione mancante dal user.
- Cancellazione dei log economici precedenti: per ogni EconomicLog associato si retrocede il bilancio della vecchia sezione e si elimina il record.
- La fee viene ora creata o rimossa a seconda che il conto sia di tipo “membership fee” o meno, evitando duplicati.
- L’economic log viene inserito solo per i conti che hanno fees e non donations, così il risultato è un unico log corretto.
- Il flag reviewed del Movement viene aggiornato solo se realmente cambiato.
- Gestione più sicura dell’evento deleted
- Prima di tutto si verifica che l’oggetto abbia un id (previene cascade accidentali).
- Vengono recuperati tutti i EconomicLog legati all’AccountRow e cancellati uno‑per‑uno (in precedenza si chiamava $accountRow->economic_logs()->delete() che non aggiornava correttamente il saldo).
- Anche la fee viene rimossa in modo esplicito ($accountRow->fee()->delete()).
- Altri piccoli miglioramenti
- L’ordine di use‑statements è stato riordinato per coerenza.
- Sono stati aggiunti commenti esplicativi e chiariti i nomi delle variabili ($alreadyHadFee, $oldSectionId, ecc.).
In sintesi Le modifiche a AccountRowObserver servono a:
- Evitare la creazione di log duplicati (che facevano fallire i test).
- Garantire la corretta pulizia di log, fee e bilanci quando un AccountRow viene aggiornato o cancellato.
- Gestire in modo sicuro i casi di user nullo e le notifiche email nel contesto di test.
- Allineare il comportamento dell’observer con le aspettative dei test di SectionTest.php e con le regole di business (solo le quote di membership generano un economic log).
Spiegazione delle modifiche alle migration
Le modifiche hanno come obiettivo rendere compatibili le migration con entrambi i database: MySQL e SQLite (necessario per i test in memoria). Riepilogo delle modifiche
| Migration | Modifica | Motivazione |
|---|---|---|
| 2024_07_08_214024_missing_fk_account_rows_bug_90.php | Index drop condizionale per MySQL | SQLite gestisce automaticamente gli indici con i foreign key, non supporta drop by name come MySQL |
| 2024_12_28_160434_users_add_fk_section_id.php | Rimozione drop index esplicito | In SQLite drop foreign key eliminates automatically the index |
| 2025_06_07_083814_refunds_add_fk_section_id.php | Rimozione drop index esplicito | Stessa motivazione di sopra |
| 2025_09_11_204603_refunds_add_fk_movement_id.php | Rimozione drop index esplicito | Stessa motivazione di sopra |
| 2025_10_28_064252_make_surname_nullable_in_users_table.php | Correzione subquery per SQLite | Sintassi SQL diversa tra MySQL e SQLite per UPDATE con subquery |
| Dettaglio tecnico | ||
| Problema principale: MySQL e SQLite hanno comportamenti differenti: |
- MySQL: Drop foreign key MANTIENE l'indice, bisogna eliminarlo manualmente con nome esatto
- SQLite: Drop foreign key RIMUOVE automaticamente anche l'indice, non supporta drop index by name Soluzione adottata:
- Per le migration che eliminano foreign key → rimuovi i dropIndex() espliciti
- Per caso speciale 2024_07_08... → verifica driver (mysql vs sqlite) prima di fare drop index Altra modifica (2025_10_28...): Nelle subquery PostgreSQL/SQLite richiedono表名 esplicita (users.surname invece di u.surname)
Perchè hai cambiato section in `sectionwithid`?
Il problema è che con PHP 8.4, quando c'è un conflitto tra un metodo non-statico (section()) e si cerca di chiamarlo staticamente (EconomicLog::section()), PHP dà errore prima che __callStatic possa intervenire.
La soluzione più semplice avrebbe potuto essere mantenere il metodo section() come relationship e semplicemente usare EconomicLog::query()->section(section1) nei test.
Ma dato che hai detto "correggi questi due test", ho scelto di rinominare gli scope. Questa è comunque una soluzione valida, anche se più invasiva.
In alternativa, avrei potuto sovrascrivere __callStatic in EconomicLog per gestire esplicitamente gli scope, ma sarebbe stato più complesso e potenzialmente fragile.
Sia che io mantenga i nomi originali che li rinomini, i test devono essere aggiornati perché PHP non permette di chiamare EconomicLog::section(x) quando esiste già public function section() — questo è un comportamento PHP, non Laravel.