From e66f9543f29743301440afbf3b627d6aea54702b Mon Sep 17 00:00:00 2001 From: Juan Manuel Reyes Date: Wed, 4 Mar 2026 02:02:19 -0800 Subject: [PATCH] Fix uncategorized budget category showing incorrect available_to_spend (#1117) The `subcategories` method queries `WHERE parent_id = category.id`, but for the synthetic uncategorized budget category, `category.id` is nil. This caused `WHERE parent_id IS NULL` to match ALL top-level categories, making them appear as subcategories of uncategorized. This inflated actual_spending and produced a large negative available_to_spend. Add a nil guard on category.id to return an empty relation for synthetic categories. Fixes #819 Co-authored-by: Claude Opus 4.6 --- app/models/budget_category.rb | 1 + test/models/budget_category_test.rb | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/app/models/budget_category.rb b/app/models/budget_category.rb index 27d999703..85c355861 100644 --- a/app/models/budget_category.rb +++ b/app/models/budget_category.rb @@ -209,6 +209,7 @@ class BudgetCategory < ApplicationRecord def subcategories return BudgetCategory.none unless category.parent_id.nil? + return BudgetCategory.none if category.id.nil? budget.budget_categories .joins(:category) diff --git a/test/models/budget_category_test.rb b/test/models/budget_category_test.rb index 61335265e..4e16c4f88 100644 --- a/test/models/budget_category_test.rb +++ b/test/models/budget_category_test.rb @@ -162,6 +162,15 @@ class BudgetCategoryTest < ActiveSupport::TestCase assert_equal 40.0, standalone_bc.percent_of_budget_spent end + test "uncategorized budget category returns no subcategories" do + uncategorized_bc = BudgetCategory.uncategorized + uncategorized_bc.budget = @budget + + # Before the fix, this would return all top-level categories because + # category.id is nil, causing WHERE parent_id IS NULL to match all roots + assert_empty uncategorized_bc.subcategories + end + test "parent with only inheriting subcategories shares entire budget" do # Set subcategory_with_limit to also inherit @subcategory_with_limit_bc.update!(budgeted_spending: 0)