Replace status_id with in_progress boolean field
- Remove task_statuses lookup table and StatusID foreign key - Add InProgress boolean field to Task model - Add database migration (005_replace_status_with_in_progress) - Update all handlers, services, and repositories - Update admin frontend to display in_progress as checkbox/boolean - Remove Task Statuses tab from admin lookups page - Update tests to use InProgress instead of StatusID - Task categorization now uses InProgress for kanban column assignment 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -41,9 +41,9 @@ func TestTaskService_CreateTask(t *testing.T) {
|
||||
|
||||
resp, err := service.CreateTask(req, user.ID)
|
||||
require.NoError(t, err)
|
||||
assert.NotZero(t, resp.ID)
|
||||
assert.Equal(t, "Fix leaky faucet", resp.Title)
|
||||
assert.Equal(t, "Kitchen faucet is dripping", resp.Description)
|
||||
assert.NotZero(t, resp.Data.ID)
|
||||
assert.Equal(t, "Fix leaky faucet", resp.Data.Title)
|
||||
assert.Equal(t, "Kitchen faucet is dripping", resp.Data.Description)
|
||||
}
|
||||
|
||||
func TestTaskService_CreateTask_WithOptionalFields(t *testing.T) {
|
||||
@@ -76,10 +76,10 @@ func TestTaskService_CreateTask_WithOptionalFields(t *testing.T) {
|
||||
|
||||
resp, err := service.CreateTask(req, user.ID)
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, resp.Category)
|
||||
assert.NotNil(t, resp.Priority)
|
||||
assert.NotNil(t, resp.DueDate)
|
||||
assert.NotNil(t, resp.EstimatedCost)
|
||||
assert.NotNil(t, resp.Data.Category)
|
||||
assert.NotNil(t, resp.Data.Priority)
|
||||
assert.NotNil(t, resp.Data.DueDate)
|
||||
assert.NotNil(t, resp.Data.EstimatedCost)
|
||||
}
|
||||
|
||||
func TestTaskService_CreateTask_AccessDenied(t *testing.T) {
|
||||
@@ -180,8 +180,8 @@ func TestTaskService_UpdateTask(t *testing.T) {
|
||||
|
||||
resp, err := service.UpdateTask(task.ID, user.ID, req)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "Updated Title", resp.Title)
|
||||
assert.Equal(t, "Updated description", resp.Description)
|
||||
assert.Equal(t, "Updated Title", resp.Data.Title)
|
||||
assert.Equal(t, "Updated description", resp.Data.Description)
|
||||
}
|
||||
|
||||
func TestTaskService_DeleteTask(t *testing.T) {
|
||||
@@ -195,7 +195,7 @@ func TestTaskService_DeleteTask(t *testing.T) {
|
||||
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
|
||||
task := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Test Task")
|
||||
|
||||
err := service.DeleteTask(task.ID, user.ID)
|
||||
_, err := service.DeleteTask(task.ID, user.ID)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = service.GetTask(task.ID, user.ID)
|
||||
@@ -215,7 +215,7 @@ func TestTaskService_CancelTask(t *testing.T) {
|
||||
|
||||
resp, err := service.CancelTask(task.ID, user.ID)
|
||||
require.NoError(t, err)
|
||||
assert.True(t, resp.IsCancelled)
|
||||
assert.True(t, resp.Data.IsCancelled)
|
||||
}
|
||||
|
||||
func TestTaskService_CancelTask_AlreadyCancelled(t *testing.T) {
|
||||
@@ -248,7 +248,7 @@ func TestTaskService_UncancelTask(t *testing.T) {
|
||||
service.CancelTask(task.ID, user.ID)
|
||||
resp, err := service.UncancelTask(task.ID, user.ID)
|
||||
require.NoError(t, err)
|
||||
assert.False(t, resp.IsCancelled)
|
||||
assert.False(t, resp.Data.IsCancelled)
|
||||
}
|
||||
|
||||
func TestTaskService_ArchiveTask(t *testing.T) {
|
||||
@@ -264,7 +264,7 @@ func TestTaskService_ArchiveTask(t *testing.T) {
|
||||
|
||||
resp, err := service.ArchiveTask(task.ID, user.ID)
|
||||
require.NoError(t, err)
|
||||
assert.True(t, resp.IsArchived)
|
||||
assert.True(t, resp.Data.IsArchived)
|
||||
}
|
||||
|
||||
func TestTaskService_UnarchiveTask(t *testing.T) {
|
||||
@@ -281,7 +281,7 @@ func TestTaskService_UnarchiveTask(t *testing.T) {
|
||||
service.ArchiveTask(task.ID, user.ID)
|
||||
resp, err := service.UnarchiveTask(task.ID, user.ID)
|
||||
require.NoError(t, err)
|
||||
assert.False(t, resp.IsArchived)
|
||||
assert.False(t, resp.Data.IsArchived)
|
||||
}
|
||||
|
||||
func TestTaskService_MarkInProgress(t *testing.T) {
|
||||
@@ -297,8 +297,7 @@ func TestTaskService_MarkInProgress(t *testing.T) {
|
||||
|
||||
resp, err := service.MarkInProgress(task.ID, user.ID)
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, resp.Status)
|
||||
assert.Equal(t, "In Progress", resp.Status.Name)
|
||||
assert.True(t, resp.Data.InProgress)
|
||||
}
|
||||
|
||||
func TestTaskService_CreateCompletion(t *testing.T) {
|
||||
@@ -319,12 +318,12 @@ func TestTaskService_CreateCompletion(t *testing.T) {
|
||||
|
||||
resp, err := service.CreateCompletion(req, user.ID)
|
||||
require.NoError(t, err)
|
||||
assert.NotZero(t, resp.ID)
|
||||
assert.Equal(t, task.ID, resp.TaskID)
|
||||
assert.Equal(t, "Completed successfully", resp.Notes)
|
||||
assert.NotZero(t, resp.Data.ID)
|
||||
assert.Equal(t, task.ID, resp.Data.TaskID)
|
||||
assert.Equal(t, "Completed successfully", resp.Data.Notes)
|
||||
}
|
||||
|
||||
func TestTaskService_CreateCompletion_RecurringTask_ResetsStatusToPending(t *testing.T) {
|
||||
func TestTaskService_CreateCompletion_RecurringTask_ResetsInProgress(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
testutil.SeedLookupData(t, db)
|
||||
taskRepo := repositories.NewTaskRepository(db)
|
||||
@@ -334,20 +333,16 @@ func TestTaskService_CreateCompletion_RecurringTask_ResetsStatusToPending(t *tes
|
||||
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password")
|
||||
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
|
||||
|
||||
// Get the "In Progress" status (ID=2) and a recurring frequency
|
||||
var inProgressStatus models.TaskStatus
|
||||
db.Where("name = ?", "In Progress").First(&inProgressStatus)
|
||||
|
||||
var monthlyFrequency models.TaskFrequency
|
||||
db.Where("name = ?", "Monthly").First(&monthlyFrequency)
|
||||
|
||||
// Create a recurring task with "In Progress" status
|
||||
// Create a recurring task that is in progress
|
||||
dueDate := time.Now().AddDate(0, 0, 7) // Due in 7 days
|
||||
task := &models.Task{
|
||||
ResidenceID: residence.ID,
|
||||
CreatedByID: user.ID,
|
||||
Title: "Recurring Task",
|
||||
StatusID: &inProgressStatus.ID,
|
||||
InProgress: true,
|
||||
FrequencyID: &monthlyFrequency.ID,
|
||||
DueDate: &dueDate,
|
||||
NextDueDate: &dueDate,
|
||||
@@ -365,24 +360,21 @@ func TestTaskService_CreateCompletion_RecurringTask_ResetsStatusToPending(t *tes
|
||||
|
||||
resp, err := service.CreateCompletion(req, user.ID)
|
||||
require.NoError(t, err)
|
||||
assert.NotZero(t, resp.ID)
|
||||
assert.NotZero(t, resp.Data.ID)
|
||||
|
||||
// Verify the task in the response has status reset to "Pending" (ID=1)
|
||||
require.NotNil(t, resp.Task, "Response should include the updated task")
|
||||
require.NotNil(t, resp.Task.StatusID, "Task should have a status ID")
|
||||
assert.Equal(t, uint(1), *resp.Task.StatusID, "Recurring task status should be reset to Pending (ID=1) after completion")
|
||||
// Verify the task in the response has InProgress reset to false
|
||||
require.NotNil(t, resp.Data.Task, "Response should include the updated task")
|
||||
assert.False(t, resp.Data.Task.InProgress, "Recurring task InProgress should be reset to false after completion")
|
||||
|
||||
// Verify NextDueDate was updated (should be ~30 days from now for monthly)
|
||||
require.NotNil(t, resp.Task.NextDueDate, "Recurring task should have NextDueDate set")
|
||||
require.NotNil(t, resp.Data.Task.NextDueDate, "Recurring task should have NextDueDate set")
|
||||
expectedNextDue := time.Now().AddDate(0, 0, 30) // Monthly = 30 days
|
||||
assert.WithinDuration(t, expectedNextDue, *resp.Task.NextDueDate, 24*time.Hour, "NextDueDate should be approximately 30 days from now")
|
||||
assert.WithinDuration(t, expectedNextDue, *resp.Data.Task.NextDueDate, 24*time.Hour, "NextDueDate should be approximately 30 days from now")
|
||||
|
||||
// Also verify by reloading from database directly
|
||||
var reloadedTask models.Task
|
||||
db.Preload("Status").First(&reloadedTask, task.ID)
|
||||
require.NotNil(t, reloadedTask.StatusID)
|
||||
assert.Equal(t, uint(1), *reloadedTask.StatusID, "Database should show Pending status")
|
||||
assert.Equal(t, "Pending", reloadedTask.Status.Name)
|
||||
db.First(&reloadedTask, task.ID)
|
||||
assert.False(t, reloadedTask.InProgress, "Database should show InProgress=false")
|
||||
}
|
||||
|
||||
func TestTaskService_GetCompletion(t *testing.T) {
|
||||
@@ -428,7 +420,7 @@ func TestTaskService_DeleteCompletion(t *testing.T) {
|
||||
}
|
||||
db.Create(completion)
|
||||
|
||||
err := service.DeleteCompletion(completion.ID, user.ID)
|
||||
_, err := service.DeleteCompletion(completion.ID, user.ID)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = service.GetCompletion(completion.ID, user.ID)
|
||||
@@ -470,18 +462,6 @@ func TestTaskService_GetPriorities(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestTaskService_GetStatuses(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
testutil.SeedLookupData(t, db)
|
||||
taskRepo := repositories.NewTaskRepository(db)
|
||||
residenceRepo := repositories.NewResidenceRepository(db)
|
||||
service := NewTaskService(taskRepo, residenceRepo)
|
||||
|
||||
statuses, err := service.GetStatuses()
|
||||
require.NoError(t, err)
|
||||
assert.Greater(t, len(statuses), 0)
|
||||
}
|
||||
|
||||
func TestTaskService_GetFrequencies(t *testing.T) {
|
||||
db := testutil.SetupTestDB(t)
|
||||
testutil.SeedLookupData(t, db)
|
||||
|
||||
Reference in New Issue
Block a user