Skip to content

Fix category deletion and stale group tally after expense changes - #19

Merged
LouisBenjamin merged 1 commit into
mainfrom
fix/category-delete-and-expense-tally
Sep 2, 2026
Merged

Fix category deletion and stale group tally after expense changes#19
LouisBenjamin merged 1 commit into
mainfrom
fix/category-delete-and-expense-tally

Conversation

@LouisBenjamin

Copy link
Copy Markdown
Owner

Two bugs, reported together

1. Categories couldn't be deleted

CategoriesRepository.deleteCategory ran a plain delete from categories where id = ?. That has two failure modes, both of which look like "delete does nothing":

  • Silent zero-row delete when RLS hides the target — a global default (group_id is null), or a category owned by another group. PostgREST returns 204, no error, the list refetches, the row is still there.
  • Foreign-key violation anywhere the 0012 on delete set null cascade isn't in effect (an environment still on <= 0011) — expenses / recurring_expenses / merchant_rules still point at the row.

Fix: new delete_category(id) SECURITY DEFINER RPC (supabase/migrations/0013_delete_category_rpc.sql), mirroring delete_expense / update_expense / update_group_photo. It:

  • authorizes the caller as a member of the category's group,
  • raises a real error for "not found" / "default category" / "not authorized",
  • nulls out every expenses / recurring_expenses / merchant_rules reference explicitly, so it works regardless of the FK action,
  • deletes the row.

deleteCategory now calls the RPC.

2. Deleting an expense didn't fix the tally

The "you owe / you're owed" line on each groups-list card comes from groupSummariesProvider (the my_group_summaries view). Every expense mutation site — add, edit, delete, import — and the settle-up flow invalidated expensesProvider and balancesProvider but not groupSummariesProvider, which nothing else refreshes. Navigation is context.push, so GroupsListScreen stays mounted underneath and reuses its cached value: the tally stayed stale until a manual pull-to-refresh.

Fix: invalidateGroupMoney(ref, groupId) in groups_provider.dart invalidates all three, and replaces the ad-hoc pairs at every expense / settlement mutation point (group_detail_screen.dart, balances_tab.dart).

Testing

  • flutter analyze clean, flutter test — 180 existing + 1 new pass.
  • New test/features/groups/group_money_invalidation_test.dart asserts invalidateGroupMoney refetches the groups-list summary, not just the in-group providers.
  • delete_category RPC still needs supabase db push (or running 0013 in the SQL editor) against your project.

🤖 Generated with Claude Code

Two bugs reported together:

1. Categories couldn't be deleted. `CategoriesRepository.deleteCategory`
   ran a plain `delete from categories`, which removes zero rows — with no
   error — whenever RLS hides the target (a global default, or another
   group's row), and fails on a foreign-key violation anywhere the 0012
   `on delete set null` cascade isn't in place. Route it through a new
   `delete_category(id)` SECURITY DEFINER RPC (migration 0013) that
   authorizes the caller, raises a real error for the default / wrong-group
   cases, and detaches every expense/recurring/tag reference before
   deleting — the same pattern as `delete_expense`.

2. Deleting (or adding/editing/importing) an expense didn't update the
   "you owe / you're owed" tally on the groups list. The mutation sites
   invalidated `expensesProvider` and `balancesProvider` but not
   `groupSummariesProvider`, a separate view nothing else refreshes, so
   the list stayed stale until a manual pull-to-refresh. Add
   `invalidateGroupMoney(ref, groupId)` and use it at every expense /
   settlement mutation point.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EzXWJsUFffSSJAKGaRqUT4
@LouisBenjamin
LouisBenjamin merged commit 9b00f27 into main Sep 2, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant