From bcb4a7415887f0dca374f500f4cfd4ac37e28db6 Mon Sep 17 00:00:00 2001 From: Catherine Renelle <32781029+catrenelle@users.noreply.github.com> Date: Mon, 9 Feb 2026 00:34:52 -0500 Subject: [PATCH] Fix Dashboard top categories query translation error EF Core cannot translate GroupBy with a navigation property (Category.Name) joined via nullable FK into SQL. Split into two queries: group by CategoryId server-side, then look up category names in a separate query. Co-Authored-By: Claude Opus 4.6 --- src/Purrse.Api/Services/DashboardService.cs | 22 +++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/Purrse.Api/Services/DashboardService.cs b/src/Purrse.Api/Services/DashboardService.cs index 80e10eb..07e8d0a 100644 --- a/src/Purrse.Api/Services/DashboardService.cs +++ b/src/Purrse.Api/Services/DashboardService.cs @@ -51,18 +51,24 @@ public class DashboardService : IDashboardService var changePercent = lastMonthSpending == 0 ? 0 : ((thisMonthSpending - lastMonthSpending) / lastMonthSpending) * 100; - var topCategories = await _db.Transactions - .Include(t => t.Category) + var spendingByCategory = await _db.Transactions .Where(t => t.Account.UserId == userId && t.Date >= startOfMonth && t.Amount < 0 && !t.IsVoid && t.CategoryId.HasValue) - .GroupBy(t => new { t.CategoryId, CategoryName = t.Category!.Name }) - .Select(g => new CategorySpending(g.Key.CategoryName, -g.Sum(t => t.Amount), 0, null)) - .OrderByDescending(c => c.Amount) + .GroupBy(t => t.CategoryId) + .Select(g => new { CategoryId = g.Key, Total = -g.Sum(t => t.Amount) }) + .OrderByDescending(x => x.Total) .Take(5) .ToListAsync(); - var totalSpending = topCategories.Sum(c => c.Amount); - topCategories = topCategories.Select(c => new CategorySpending(c.CategoryName, c.Amount, - totalSpending > 0 ? (c.Amount / totalSpending) * 100 : 0, null)).ToList(); + var categoryNames = await _db.Categories + .Where(c => spendingByCategory.Select(x => x.CategoryId).Contains(c.Id)) + .ToDictionaryAsync(c => c.Id, c => c.Name); + + var totalSpending = spendingByCategory.Sum(x => x.Total); + var topCategories = spendingByCategory.Select(x => new CategorySpending( + categoryNames.GetValueOrDefault(x.CategoryId!.Value, "Unknown"), + x.Total, + totalSpending > 0 ? (x.Total / totalSpending) * 100 : 0, + null)).ToList(); var spendingSummary = new SpendingSummary(thisMonthSpending, lastMonthSpending, changePercent, topCategories);