Repository navigation
Fix account self-deletion FK violation for users with recorded payments - #122
Merged
Merged
Conversation
Account deletion is full deletion (ToS §9), but invoice_payments' invoice_id/accounting_invoice_id foreign keys are deliberately RESTRICT (protecting payment history from invoice force-deletes), so the users -> invoices cascade threw an FK violation for any user with recorded payments. - User deleting hook removes the user's invoice_payments rows (both source and accounting references, trashed invoices included) before the cascade runs; reattribution is same-user scoped, so other users' records are never touched. RESTRICT FKs stay in place. - ProfileController@destroy wraps the delete in a transaction so the hook and cascade succeed or roll back together. - Migration purges sessions rows already orphaned by past deletions and adds a cascading sessions.user_id foreign key so future account deletions drop the user's session rows at the DB level. - ProfileTest covers deletion with detected/reattributed/trashed-invoice payments plus session rows, and that other users' records survive. Fixes #121 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BBzTGeMigvwBHobeTwbVoa
n8bar
added a commit
that referenced
this pull request
Jul 3, 2026
…grated) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BBzTGeMigvwBHobeTwbVoa
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Deleting an account from
/profileruns the DB cascade users → invoices, butinvoice_payments.invoice_idandinvoice_payments.accounting_invoice_idare deliberatelyRESTRICT(they block invoice force-deletes that would drop payment history). Any user with a recorded payment therefore hit an FK constraint violation and could not delete their account. Separately,sessions.user_idhad no foreign key, so database-driver session rows outlived their user as orphans.What this does
Account deletion is full deletion per ToS §9: profile, wallet configuration, invoices, and payment/accounting records are all removed, and shared invoice links stop working.
Userdeleting hook (app/Models/User.php): before the users → invoices cascade runs, deletes everyinvoice_paymentsrow referencing the user's invoices viainvoice_idoraccounting_invoice_id, soft-deleted invoices included, and forgets the user's dashboard snapshot cache. Payment reattribution is scoped to a single user's invoices, so this never removes rows tied to another user's records. TheRESTRICTFKs remain in place — invoice force-deletes stay guarded.ProfileController@destroy: wraps the delete in a DB transaction so the hook's deletes and the user-row cascade succeed or roll back together.2026_07_03_120000_purge_orphaned_sessions_and_add_sessions_user_foreign_key.php): one-time purge ofsessionsrows whoseuser_idpoints at a no-longer-existing user, then adds a cascadingsessions.user_id→users.idforeign key so future account deletions remove the user's session rows at the DB level. Guest sessions keep a nulluser_idand are unaffected.Tests
tests/Feature/ProfileTest.phpadds:test_user_with_invoices_and_recorded_payments_can_delete_their_account— user with detected, reattributed, and trashed-invoice payments plus a persisted session row deletes their account; asserts user, invoices, clients, payment rows, and session rows are all gone. (Failed with the issue's FK violation before the fix.)test_account_deletion_leaves_other_users_records_untouched— a second user's invoices, payments, and sessions survive the first user's deletion.Full suite: 375 passed (1801 assertions).
Fixes #121
🤖 Generated with Claude Code
https://claude.ai/code/session_01BBzTGeMigvwBHobeTwbVoa