Add performance optimizations and database indexes
Database Indexes (migrations 006-009): - Add case-insensitive indexes for auth lookups (email, username) - Add composite indexes for task kanban queries - Add indexes for notification, document, and completion queries - Add unique index for active share codes - Remove redundant idx_share_code_active and idx_notification_user_sent Repository Optimizations: - Add FindResidenceIDsByUser() lightweight method (IDs only, no preloads) - Optimize GetResidenceUsers() with single UNION query (was 2 queries) - Optimize kanban completion preloads to minimal columns (id, task_id, completed_at) Service Optimizations: - Remove Category/Priority/Frequency preloads from task queries - Remove summary calculations from CRUD responses (client calculates) - Use lightweight FindResidenceIDsByUser() instead of full FindByUser() These changes reduce database load and response times for common operations. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -318,7 +318,7 @@ func TestKanbanBoard_CancelledTasksGoToCancelledColumn(t *testing.T) {
|
||||
task := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Cancelled Task")
|
||||
repo.Cancel(task.ID)
|
||||
|
||||
board, err := repo.GetKanbanData(residence.ID, 30)
|
||||
board, err := repo.GetKanbanData(residence.ID, 30, time.Now().UTC())
|
||||
require.NoError(t, err)
|
||||
|
||||
// Find cancelled column
|
||||
@@ -358,7 +358,7 @@ func TestKanbanBoard_CompletedTasksGoToCompletedColumn(t *testing.T) {
|
||||
err := repo.CreateCompletion(completion)
|
||||
require.NoError(t, err)
|
||||
|
||||
board, err := repo.GetKanbanData(residence.ID, 30)
|
||||
board, err := repo.GetKanbanData(residence.ID, 30, time.Now().UTC())
|
||||
require.NoError(t, err)
|
||||
|
||||
// Find completed column
|
||||
@@ -397,7 +397,7 @@ func TestKanbanBoard_InProgressTasksGoToInProgressColumn(t *testing.T) {
|
||||
err := db.Create(task).Error
|
||||
require.NoError(t, err)
|
||||
|
||||
board, err := repo.GetKanbanData(residence.ID, 30)
|
||||
board, err := repo.GetKanbanData(residence.ID, 30, time.Now().UTC())
|
||||
require.NoError(t, err)
|
||||
|
||||
// Find in_progress column
|
||||
@@ -437,7 +437,7 @@ func TestKanbanBoard_OverdueTasksGoToOverdueColumn(t *testing.T) {
|
||||
err := db.Create(task).Error
|
||||
require.NoError(t, err)
|
||||
|
||||
board, err := repo.GetKanbanData(residence.ID, 30)
|
||||
board, err := repo.GetKanbanData(residence.ID, 30, time.Now().UTC())
|
||||
require.NoError(t, err)
|
||||
|
||||
// Find overdue column
|
||||
@@ -477,7 +477,7 @@ func TestKanbanBoard_DueSoonTasksGoToDueSoonColumn(t *testing.T) {
|
||||
err := db.Create(task).Error
|
||||
require.NoError(t, err)
|
||||
|
||||
board, err := repo.GetKanbanData(residence.ID, 30)
|
||||
board, err := repo.GetKanbanData(residence.ID, 30, time.Now().UTC())
|
||||
require.NoError(t, err)
|
||||
|
||||
// Find due_soon column
|
||||
@@ -517,7 +517,7 @@ func TestKanbanBoard_UpcomingTasksGoToUpcomingColumn(t *testing.T) {
|
||||
err := db.Create(task).Error
|
||||
require.NoError(t, err)
|
||||
|
||||
board, err := repo.GetKanbanData(residence.ID, 30)
|
||||
board, err := repo.GetKanbanData(residence.ID, 30, time.Now().UTC())
|
||||
require.NoError(t, err)
|
||||
|
||||
// Find upcoming column
|
||||
@@ -549,7 +549,7 @@ func TestKanbanBoard_TasksWithNoDueDateGoToUpcomingColumn(t *testing.T) {
|
||||
// Create a task with no due date
|
||||
task := testutil.CreateTestTask(t, db, residence.ID, user.ID, "No Due Date Task")
|
||||
|
||||
board, err := repo.GetKanbanData(residence.ID, 30)
|
||||
board, err := repo.GetKanbanData(residence.ID, 30, time.Now().UTC())
|
||||
require.NoError(t, err)
|
||||
|
||||
// Find upcoming column
|
||||
@@ -579,7 +579,7 @@ func TestKanbanBoard_ArchivedTasksAreExcluded(t *testing.T) {
|
||||
archivedTask := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Archived Task")
|
||||
repo.Archive(archivedTask.ID)
|
||||
|
||||
board, err := repo.GetKanbanData(residence.ID, 30)
|
||||
board, err := repo.GetKanbanData(residence.ID, 30, time.Now().UTC())
|
||||
require.NoError(t, err)
|
||||
|
||||
// Count total tasks across all columns
|
||||
@@ -613,7 +613,7 @@ func TestKanbanBoard_CategoryPriority_CancelledTakesPrecedence(t *testing.T) {
|
||||
err := db.Create(task).Error
|
||||
require.NoError(t, err)
|
||||
|
||||
board, err := repo.GetKanbanData(residence.ID, 30)
|
||||
board, err := repo.GetKanbanData(residence.ID, 30, time.Now().UTC())
|
||||
require.NoError(t, err)
|
||||
|
||||
// Find cancelled column
|
||||
@@ -661,7 +661,7 @@ func TestKanbanBoard_CategoryPriority_CompletedTakesPrecedenceOverInProgress(t *
|
||||
err = repo.CreateCompletion(completion)
|
||||
require.NoError(t, err)
|
||||
|
||||
board, err := repo.GetKanbanData(residence.ID, 30)
|
||||
board, err := repo.GetKanbanData(residence.ID, 30, time.Now().UTC())
|
||||
require.NoError(t, err)
|
||||
|
||||
// Find columns
|
||||
@@ -700,7 +700,7 @@ func TestKanbanBoard_DaysThresholdAffectsCategorization(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// With 30-day threshold, should be in "due_soon"
|
||||
board30, err := repo.GetKanbanData(residence.ID, 30)
|
||||
board30, err := repo.GetKanbanData(residence.ID, 30, time.Now().UTC())
|
||||
require.NoError(t, err)
|
||||
|
||||
var dueSoon30, upcoming30 *models.KanbanColumn
|
||||
@@ -716,7 +716,7 @@ func TestKanbanBoard_DaysThresholdAffectsCategorization(t *testing.T) {
|
||||
assert.Equal(t, 0, upcoming30.Count, "With 30-day threshold, task should NOT be in upcoming")
|
||||
|
||||
// With 5-day threshold, should be in "upcoming"
|
||||
board5, err := repo.GetKanbanData(residence.ID, 5)
|
||||
board5, err := repo.GetKanbanData(residence.ID, 5, time.Now().UTC())
|
||||
require.NoError(t, err)
|
||||
|
||||
var dueSoon5, upcoming5 *models.KanbanColumn
|
||||
@@ -740,7 +740,7 @@ func TestKanbanBoard_ColumnMetadata(t *testing.T) {
|
||||
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password")
|
||||
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
|
||||
|
||||
board, err := repo.GetKanbanData(residence.ID, 30)
|
||||
board, err := repo.GetKanbanData(residence.ID, 30, time.Now().UTC())
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify all 6 columns exist with correct metadata
|
||||
@@ -793,7 +793,7 @@ func TestKanbanBoard_MultipleResidences(t *testing.T) {
|
||||
cancelledTask := testutil.CreateTestTask(t, db, residence1.ID, user.ID, "Cancelled in House 1")
|
||||
repo.Cancel(cancelledTask.ID)
|
||||
|
||||
board, err := repo.GetKanbanDataForMultipleResidences([]uint{residence1.ID, residence2.ID}, 30)
|
||||
board, err := repo.GetKanbanDataForMultipleResidences([]uint{residence1.ID, residence2.ID}, 30, time.Now().UTC())
|
||||
require.NoError(t, err)
|
||||
|
||||
// Count total tasks
|
||||
|
||||
Reference in New Issue
Block a user