Remove remaining status_id references after in_progress migration

- Remove Preload("Status") from worker handler and repositories
- Update seeds to use in_progress boolean instead of status_id
- Remove task_taskstatus table creation from lookup seeds
- Update documentation to reflect in_progress boolean pattern

Fixes notification worker error:
"Status: unsupported relations for schema Task"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Trey t
2025-12-08 22:43:53 -06:00
parent c5b0225422
commit 12eac24632
8 changed files with 89 additions and 111 deletions

View File

@@ -82,14 +82,14 @@ if task.NextDueDate == nil && len(task.Completions) > 0 {
**Handler**: `InProgressHandler` **Handler**: `InProgressHandler`
**Condition**: `task.Status != nil && task.Status.Name == "In Progress"` **Condition**: `task.InProgress == true`
**Result**: `in_progress_tasks` **Result**: `in_progress_tasks`
Tasks with the "In Progress" status are grouped together regardless of their due date. This allows users to see what's actively being worked on. Tasks marked as "In Progress" are grouped together regardless of their due date. This allows users to see what's actively being worked on.
```go ```go
if task.Status != nil && task.Status.Name == "In Progress" { if task.InProgress {
return "in_progress_tasks" return "in_progress_tasks"
} }
``` ```
@@ -188,15 +188,14 @@ return "upcoming_tasks"
This is by design - "In Progress" indicates active work, so the task should be visible there. However, this means: This is by design - "In Progress" indicates active work, so the task should be visible there. However, this means:
1. If a recurring task is marked "In Progress" and then completed 1. If a recurring task is marked "In Progress" and then completed
2. The status MUST be reset to "Pending" after completion 2. The `in_progress` flag MUST be reset to `false` after completion
3. Otherwise, the task stays in "In Progress" instead of moving to "Upcoming" 3. Otherwise, the task stays in "In Progress" instead of moving to "Upcoming"
This is handled automatically in `TaskService.CreateCompletion()`: This is handled automatically in `TaskService.CreateCompletion()`:
```go ```go
if isRecurringTask { if isRecurringTask {
pendingStatusID := uint(1) task.InProgress = false
task.StatusID = &pendingStatusID
} }
``` ```
@@ -246,8 +245,8 @@ Each column has associated metadata for UI rendering:
import "github.com/treytartt/casera-api/internal/task/categorization" import "github.com/treytartt/casera-api/internal/task/categorization"
task := &models.Task{ task := &models.Task{
DueDate: time.Now().AddDate(0, 0, 15), // 15 days from now DueDate: time.Now().AddDate(0, 0, 15), // 15 days from now
Status: &models.TaskStatus{Name: "Pending"}, InProgress: false,
} }
column := categorization.DetermineKanbanColumn(task, 30) column := categorization.DetermineKanbanColumn(task, 30)
@@ -291,14 +290,14 @@ Key test scenarios:
1. **Check `IsCancelled`**: Cancelled takes highest priority 1. **Check `IsCancelled`**: Cancelled takes highest priority
2. **Check `NextDueDate`**: For recurring tasks, this determines placement 2. **Check `NextDueDate`**: For recurring tasks, this determines placement
3. **Check `Status`**: "In Progress" overrides date-based categorization 3. **Check `InProgress`**: `true` overrides date-based categorization
4. **Check `Completions`**: Empty + nil NextDueDate = upcoming, not completed 4. **Check `Completions`**: Empty + nil NextDueDate = upcoming, not completed
### Recurring task not moving to Upcoming after completion? ### Recurring task not moving to Upcoming after completion?
Verify that `CreateCompletion` is: Verify that `CreateCompletion` is:
1. Setting `NextDueDate` correctly 1. Setting `NextDueDate` correctly
2. Resetting `StatusID` to Pending (1) 2. Resetting `InProgress` to `false`
### Task showing overdue but due date looks correct? ### Task showing overdue but due date looks correct?

View File

@@ -103,12 +103,12 @@ if len(task.Completions) > 0 {
### 3. In Progress ### 3. In Progress
```go ```go
if task.Status != nil && task.Status.Name == "In Progress" { if task.InProgress {
inProgress = append(inProgress, task) inProgress = append(inProgress, task)
continue continue
} }
``` ```
- **Condition**: Task's status name is exactly `"In Progress"` - **Condition**: Task's `in_progress` boolean is `true`
- **Button Types**: `edit`, `complete`, `cancel` - **Button Types**: `edit`, `complete`, `cancel`
- **Rationale**: In-progress tasks can be edited, marked complete, or cancelled if work is abandoned - **Rationale**: In-progress tasks can be edited, marked complete, or cancelled if work is abandoned

View File

@@ -29,7 +29,7 @@ predicates.IsCompleted(task) // NextDueDate == nil && len(Completions) > 0
predicates.IsActive(task) // !IsCancelled && !IsArchived predicates.IsActive(task) // !IsCancelled && !IsArchived
predicates.IsCancelled(task) // IsCancelled == true predicates.IsCancelled(task) // IsCancelled == true
predicates.IsArchived(task) // IsArchived == true predicates.IsArchived(task) // IsArchived == true
predicates.IsInProgress(task) // Status.Name == "In Progress" predicates.IsInProgress(task) // InProgress == true
// Date calculations // Date calculations
predicates.EffectiveDate(task) // NextDueDate ?? DueDate predicates.EffectiveDate(task) // NextDueDate ?? DueDate
@@ -105,7 +105,7 @@ These rules are defined in `predicates/predicates.go` and enforced everywhere:
|---------|------------|----------------| |---------|------------|----------------|
| **Completed** | `NextDueDate == nil && len(Completions) > 0` | `next_due_date IS NULL AND EXISTS (SELECT 1 FROM task_taskcompletion WHERE task_id = ?)` | | **Completed** | `NextDueDate == nil && len(Completions) > 0` | `next_due_date IS NULL AND EXISTS (SELECT 1 FROM task_taskcompletion WHERE task_id = ?)` |
| **Active** | `!IsCancelled && !IsArchived` | `is_cancelled = false AND is_archived = false` | | **Active** | `!IsCancelled && !IsArchived` | `is_cancelled = false AND is_archived = false` |
| **In Progress** | `Status.Name == "In Progress"` | `JOIN task_taskstatus WHERE name = 'In Progress'` | | **In Progress** | `InProgress == true` | `in_progress = true` |
| **Effective Date** | `NextDueDate ?? DueDate` | `COALESCE(next_due_date, due_date)` | | **Effective Date** | `NextDueDate ?? DueDate` | `COALESCE(next_due_date, due_date)` |
| **Overdue** | `Active && !Completed && EffectiveDate < now` | Active + NotCompleted + `COALESCE(...) < ?` | | **Overdue** | `Active && !Completed && EffectiveDate < now` | Active + NotCompleted + `COALESCE(...) < ?` |
| **Due Soon** | `Active && !Completed && now <= EffectiveDate < threshold` | Active + NotCompleted + `COALESCE(...) >= ? AND COALESCE(...) < ?` | | **Due Soon** | `Active && !Completed && now <= EffectiveDate < threshold` | Active + NotCompleted + `COALESCE(...) >= ? AND COALESCE(...) < ?` |
@@ -117,7 +117,7 @@ When categorizing a task, the chain evaluates in this priority order:
1. **Cancelled** (highest) - `IsCancelled == true` 1. **Cancelled** (highest) - `IsCancelled == true`
2. **Completed** - `NextDueDate == nil && len(Completions) > 0` 2. **Completed** - `NextDueDate == nil && len(Completions) > 0`
3. **In Progress** - `Status.Name == "In Progress"` 3. **In Progress** - `InProgress == true`
4. **Overdue** - `EffectiveDate < now` 4. **Overdue** - `EffectiveDate < now`
5. **Due Soon** - `now <= EffectiveDate < threshold` 5. **Due Soon** - `now <= EffectiveDate < threshold`
6. **Upcoming** (lowest/default) - Everything else 6. **Upcoming** (lowest/default) - Everything else
@@ -139,7 +139,7 @@ db.Model(&models.Task{}).
```go ```go
// Load tasks with preloads // Load tasks with preloads
var tasks []models.Task var tasks []models.Task
db.Preload("Status").Preload("Completions"). db.Preload("Completions").
Scopes(task.ScopeForResidence(residenceID)). Scopes(task.ScopeForResidence(residenceID)).
Find(&tasks) Find(&tasks)
@@ -329,18 +329,14 @@ db.Preload("Completions").Find(&tasks)
predicates.IsCompleted(task) // Correct result predicates.IsCompleted(task) // Correct result
``` ```
### Forgetting to Preload Status ### In Progress Boolean Field
The `IsInProgress` predicate checks `task.Status.Name == "In Progress"`. Without preloading: The `IsInProgress` predicate now uses a simple boolean field instead of a Status relation:
```go ```go
// BAD: Status not loaded // IsInProgress uses the in_progress boolean field directly
db.Find(&tasks) // No preloading required for this check
predicates.IsInProgress(task) // Nil pointer or always false predicates.IsInProgress(task) // Checks task.InProgress boolean
// GOOD: Preload status
db.Preload("Status").Find(&tasks)
predicates.IsInProgress(task) // Correct result
``` ```
## Quick Reference Import ## Quick Reference Import

View File

@@ -105,7 +105,6 @@ func (r *ContractorRepository) GetTasksForContractor(contractorID uint) ([]model
var tasks []models.Task var tasks []models.Task
err := r.db.Preload("Category"). err := r.db.Preload("Category").
Preload("Priority"). Preload("Priority").
Preload("Status").
Where("contractor_id = ?", contractorID). Where("contractor_id = ?", contractorID).
Order("due_date ASC NULLS LAST"). Order("due_date ASC NULLS LAST").
Find(&tasks).Error Find(&tasks).Error

View File

@@ -316,7 +316,6 @@ func (r *ResidenceRepository) GetTasksForReport(residenceID uint) ([]models.Task
err := r.db. err := r.db.
Preload("Category"). Preload("Category").
Preload("Priority"). Preload("Priority").
Preload("Status").
Preload("Completions"). Preload("Completions").
Preload("Completions.Images"). Preload("Completions.Images").
Preload("Completions.CompletedBy"). Preload("Completions.CompletedBy").

View File

@@ -117,7 +117,7 @@ func (h *Handler) HandleTaskReminder(ctx context.Context, task *asynq.Task) erro
// A task is "completed" when NextDueDate == nil AND has at least one completion. // A task is "completed" when NextDueDate == nil AND has at least one completion.
// See internal/task/scopes.ScopeNotCompleted for the SQL equivalent. // See internal/task/scopes.ScopeNotCompleted for the SQL equivalent.
var dueSoonTasks []models.Task var dueSoonTasks []models.Task
err = h.db.Preload("Status").Preload("Completions").Preload("Residence"). err = h.db.Preload("Completions").Preload("Residence").
Where("(due_date >= ? AND due_date < ?) OR (next_due_date >= ? AND next_due_date < ?)", Where("(due_date >= ? AND due_date < ?) OR (next_due_date >= ? AND next_due_date < ?)",
today, dayAfterTomorrow, today, dayAfterTomorrow). today, dayAfterTomorrow, today, dayAfterTomorrow).
Where("is_cancelled = false"). Where("is_cancelled = false").
@@ -220,7 +220,7 @@ func (h *Handler) HandleOverdueReminder(ctx context.Context, task *asynq.Task) e
// A task is "completed" when NextDueDate == nil AND has at least one completion. // A task is "completed" when NextDueDate == nil AND has at least one completion.
// See internal/task/scopes.ScopeNotCompleted for the SQL equivalent. // See internal/task/scopes.ScopeNotCompleted for the SQL equivalent.
var overdueTasks []models.Task var overdueTasks []models.Task
err = h.db.Preload("Status").Preload("Completions").Preload("Residence"). err = h.db.Preload("Completions").Preload("Residence").
Where("due_date < ? OR next_due_date < ?", today, today). Where("due_date < ? OR next_due_date < ?", today, today).
Where("is_cancelled = false"). Where("is_cancelled = false").
Where("is_archived = false"). Where("is_archived = false").

View File

@@ -53,20 +53,7 @@ ON CONFLICT (id) DO UPDATE SET
display_order = EXCLUDED.display_order, display_order = EXCLUDED.display_order,
updated_at = NOW(); updated_at = NOW();
-- Task Statuses (has: name, description, color, display_order - NO is_terminal) -- NOTE: task_taskstatus table removed - replaced with in_progress boolean field on task_task
INSERT INTO task_taskstatus (id, created_at, updated_at, name, description, color, display_order)
VALUES
(1, NOW(), NOW(), 'Pending', 'Task has not been started', '#95a5a6', 1),
(2, NOW(), NOW(), 'In Progress', 'Task is currently being worked on', '#3498db', 2),
(3, NOW(), NOW(), 'Completed', 'Task has been completed', '#27ae60', 3),
(4, NOW(), NOW(), 'Cancelled', 'Task has been cancelled', '#e74c3c', 4),
(5, NOW(), NOW(), 'On Hold', 'Task is on hold', '#f39c12', 5)
ON CONFLICT (id) DO UPDATE SET
name = EXCLUDED.name,
description = EXCLUDED.description,
color = EXCLUDED.color,
display_order = EXCLUDED.display_order,
updated_at = NOW();
-- Task Frequencies (has: name, days, display_order) -- Task Frequencies (has: name, days, display_order)
INSERT INTO task_taskfrequency (id, created_at, updated_at, name, days, display_order) INSERT INTO task_taskfrequency (id, created_at, updated_at, name, days, display_order)
@@ -162,7 +149,6 @@ ON CONFLICT (id) DO UPDATE SET
SELECT setval('residence_residencetype_id_seq', (SELECT COALESCE(MAX(id), 0) + 1 FROM residence_residencetype), false); SELECT setval('residence_residencetype_id_seq', (SELECT COALESCE(MAX(id), 0) + 1 FROM residence_residencetype), false);
SELECT setval('task_taskcategory_id_seq', (SELECT COALESCE(MAX(id), 0) + 1 FROM task_taskcategory), false); SELECT setval('task_taskcategory_id_seq', (SELECT COALESCE(MAX(id), 0) + 1 FROM task_taskcategory), false);
SELECT setval('task_taskpriority_id_seq', (SELECT COALESCE(MAX(id), 0) + 1 FROM task_taskpriority), false); SELECT setval('task_taskpriority_id_seq', (SELECT COALESCE(MAX(id), 0) + 1 FROM task_taskpriority), false);
SELECT setval('task_taskstatus_id_seq', (SELECT COALESCE(MAX(id), 0) + 1 FROM task_taskstatus), false);
SELECT setval('task_taskfrequency_id_seq', (SELECT COALESCE(MAX(id), 0) + 1 FROM task_taskfrequency), false); SELECT setval('task_taskfrequency_id_seq', (SELECT COALESCE(MAX(id), 0) + 1 FROM task_taskfrequency), false);
SELECT setval('task_contractorspecialty_id_seq', (SELECT COALESCE(MAX(id), 0) + 1 FROM task_contractorspecialty), false); SELECT setval('task_contractorspecialty_id_seq', (SELECT COALESCE(MAX(id), 0) + 1 FROM task_contractorspecialty), false);
SELECT setval('subscription_tierlimits_id_seq', (SELECT COALESCE(MAX(id), 0) + 1 FROM subscription_tierlimits), false); SELECT setval('subscription_tierlimits_id_seq', (SELECT COALESCE(MAX(id), 0) + 1 FROM subscription_tierlimits), false);

View File

@@ -185,131 +185,130 @@ VALUES
ON CONFLICT DO NOTHING; ON CONFLICT DO NOTHING;
-- ===================================================== -- =====================================================
-- TASKS (comprehensive coverage of all categories, priorities, statuses, frequencies) -- TASKS (comprehensive coverage of all categories, priorities, frequencies)
-- Categories: 1=Plumbing, 2=Electrical, 3=HVAC, 4=Appliances, 5=Outdoor/Landscaping, 6=Structural, 7=Safety, 8=Cleaning, 9=Pest Control, 10=Other -- Categories: 1=Plumbing, 2=Electrical, 3=HVAC, 4=Appliances, 5=Outdoor/Landscaping, 6=Structural, 7=Safety, 8=Cleaning, 9=Pest Control, 10=Other
-- Priorities: 1=Low, 2=Medium, 3=High, 4=Urgent -- Priorities: 1=Low, 2=Medium, 3=High, 4=Urgent
-- Statuses: 1=Pending, 2=In Progress, 3=Completed, 4=On Hold, 5=Cancelled -- in_progress: true = actively being worked on, false = not in progress
-- Frequencies: 1=Once, 2=Daily, 3=Weekly, 4=Bi-Weekly, 5=Monthly, 6=Quarterly, 7=Semi-Annual, 8=Annual -- Frequencies: 1=Once, 2=Daily, 3=Weekly, 4=Bi-Weekly, 5=Monthly, 6=Quarterly, 7=Semi-Annual, 8=Annual
-- ===================================================== -- =====================================================
-- IMPORTANT: For recurring tasks (frequency > 1) that have completions, we must set: -- IMPORTANT: For recurring tasks (frequency > 1) that have completions, we must set:
-- - status_id = 1 (Pending) - so they appear in date-based columns, not "Completed"
-- - next_due_date = completion_date + frequency_days -- - next_due_date = completion_date + frequency_days
-- Only one-time tasks (frequency_id = 1) with completions should have status_id = 3 and next_due_date = NULL -- Completion is determined by: next_due_date IS NULL AND has at least one completion record
INSERT INTO task_task (id, created_at, updated_at, residence_id, created_by_id, assigned_to_id, title, description, category_id, priority_id, status_id, frequency_id, due_date, next_due_date, estimated_cost, contractor_id, is_cancelled, is_archived) INSERT INTO task_task (id, created_at, updated_at, residence_id, created_by_id, assigned_to_id, title, description, category_id, priority_id, in_progress, frequency_id, due_date, next_due_date, estimated_cost, contractor_id, is_cancelled, is_archived)
VALUES VALUES
-- ===== RESIDENCE 1 (John's Main Home) - 15 tasks ===== -- ===== RESIDENCE 1 (John's Main Home) - 15 tasks =====
-- Plumbing tasks -- Plumbing tasks
(1, NOW() - INTERVAL '30 days', NOW(), 1, 2, 2, 'Fix leaky kitchen faucet', 'Kitchen faucet has been dripping for a week. Washer may need replacement.', 1, 2, 1, 1, CURRENT_DATE + INTERVAL '7 days', NULL, 150.00, 1, false, false), (1, NOW() - INTERVAL '30 days', NOW(), 1, 2, 2, 'Fix leaky kitchen faucet', 'Kitchen faucet has been dripping for a week. Washer may need replacement.', 1, 2, false, 1, CURRENT_DATE + INTERVAL '7 days', NULL, 150.00, 1, false, false),
(2, NOW() - INTERVAL '60 days', NOW(), 1, 2, 3, 'Unclog bathroom drain', 'Master bathroom sink draining slowly. Tried Drano with no success.', 1, 3, 3, 1, CURRENT_DATE - INTERVAL '45 days', NULL, 85.00, 1, false, false), (2, NOW() - INTERVAL '60 days', NOW(), 1, 2, 3, 'Unclog bathroom drain', 'Master bathroom sink draining slowly. Tried Drano with no success.', 1, 3, false, 1, CURRENT_DATE - INTERVAL '45 days', NULL, 85.00, 1, false, false),
(3, NOW() - INTERVAL '15 days', NOW(), 1, 2, NULL, 'Water heater inspection', 'Annual inspection and flush of water heater tank', 1, 1, 1, 8, CURRENT_DATE + INTERVAL '30 days', NULL, 175.00, 1, false, false), (3, NOW() - INTERVAL '15 days', NOW(), 1, 2, NULL, 'Water heater inspection', 'Annual inspection and flush of water heater tank', 1, 1, false, 8, CURRENT_DATE + INTERVAL '30 days', NULL, 175.00, 1, false, false),
-- Electrical tasks -- Electrical tasks
(4, NOW() - INTERVAL '20 days', NOW(), 1, 2, 2, 'Install ceiling fan', 'Replace light fixture in master bedroom with ceiling fan', 2, 2, 2, 1, CURRENT_DATE + INTERVAL '14 days', NULL, 350.00, 2, false, false), (4, NOW() - INTERVAL '20 days', NOW(), 1, 2, 2, 'Install ceiling fan', 'Replace light fixture in master bedroom with ceiling fan', 2, 2, true, 1, CURRENT_DATE + INTERVAL '14 days', NULL, 350.00, 2, false, false),
-- Task 5: Annual recurring, completed 60 days ago -> next_due_date = completion + 365 days = ~305 days from now -- Task 5: Annual recurring, completed 60 days ago -> next_due_date = completion + 365 days = ~305 days from now
(5, NOW() - INTERVAL '90 days', NOW(), 1, 2, NULL, 'Replace smoke detector batteries', 'Replace batteries in all 6 smoke detectors', 7, 3, 1, 8, CURRENT_DATE - INTERVAL '60 days', CURRENT_DATE + INTERVAL '305 days', 30.00, NULL, false, false), (5, NOW() - INTERVAL '90 days', NOW(), 1, 2, NULL, 'Replace smoke detector batteries', 'Replace batteries in all 6 smoke detectors', 7, 3, false, 8, CURRENT_DATE - INTERVAL '60 days', CURRENT_DATE + INTERVAL '305 days', 30.00, NULL, false, false),
(6, NOW() - INTERVAL '5 days', NOW(), 1, 2, NULL, 'Fix flickering lights', 'Living room lights flicker occasionally. May need new switch.', 2, 2, 1, 1, CURRENT_DATE + INTERVAL '10 days', NULL, 125.00, 2, false, false), (6, NOW() - INTERVAL '5 days', NOW(), 1, 2, NULL, 'Fix flickering lights', 'Living room lights flicker occasionally. May need new switch.', 2, 2, false, 1, CURRENT_DATE + INTERVAL '10 days', NULL, 125.00, 2, false, false),
-- HVAC tasks -- HVAC tasks
-- Task 7: Monthly recurring, completed 15 days ago -> next_due_date = completion + 30 days = ~15 days from now -- Task 7: Monthly recurring, completed 15 days ago -> next_due_date = completion + 30 days = ~15 days from now
(7, NOW() - INTERVAL '45 days', NOW(), 1, 2, 2, 'Replace HVAC filters', 'Monthly filter replacement for central air system', 3, 2, 1, 5, CURRENT_DATE - INTERVAL '15 days', CURRENT_DATE + INTERVAL '15 days', 45.00, 3, false, false), (7, NOW() - INTERVAL '45 days', NOW(), 1, 2, 2, 'Replace HVAC filters', 'Monthly filter replacement for central air system', 3, 2, false, 5, CURRENT_DATE - INTERVAL '15 days', CURRENT_DATE + INTERVAL '15 days', 45.00, 3, false, false),
(8, NOW() - INTERVAL '10 days', NOW(), 1, 2, NULL, 'Schedule AC tune-up', 'Pre-summer AC maintenance and coolant check', 3, 2, 1, 8, CURRENT_DATE + INTERVAL '60 days', NULL, 200.00, 3, false, false), (8, NOW() - INTERVAL '10 days', NOW(), 1, 2, NULL, 'Schedule AC tune-up', 'Pre-summer AC maintenance and coolant check', 3, 2, false, 8, CURRENT_DATE + INTERVAL '60 days', NULL, 200.00, 3, false, false),
-- Outdoor/Landscaping tasks -- Outdoor/Landscaping tasks
-- Task 9: Weekly recurring, completed 2 days ago -> next_due_date = completion + 7 days = ~5 days from now -- Task 9: Weekly recurring, completed 2 days ago -> next_due_date = completion + 7 days = ~5 days from now
(9, NOW() - INTERVAL '7 days', NOW(), 1, 2, 3, 'Mow lawn', 'Weekly lawn mowing and edging', 5, 1, 1, 3, CURRENT_DATE - INTERVAL '2 days', CURRENT_DATE + INTERVAL '5 days', 50.00, 5, false, false), (9, NOW() - INTERVAL '7 days', NOW(), 1, 2, 3, 'Mow lawn', 'Weekly lawn mowing and edging', 5, 1, false, 3, CURRENT_DATE - INTERVAL '2 days', CURRENT_DATE + INTERVAL '5 days', 50.00, 5, false, false),
(10, NOW() - INTERVAL '25 days', NOW(), 1, 2, NULL, 'Trim hedges', 'Trim front and back yard hedges', 5, 1, 1, 6, CURRENT_DATE + INTERVAL '20 days', NULL, 150.00, 5, false, false), (10, NOW() - INTERVAL '25 days', NOW(), 1, 2, NULL, 'Trim hedges', 'Trim front and back yard hedges', 5, 1, false, 6, CURRENT_DATE + INTERVAL '20 days', NULL, 150.00, 5, false, false),
-- Task 11: Semi-annual recurring, completed 70 days ago -> next_due_date = completion + 180 days = ~110 days from now -- Task 11: Semi-annual recurring, completed 70 days ago -> next_due_date = completion + 180 days = ~110 days from now
(11, NOW() - INTERVAL '100 days', NOW(), 1, 2, 5, 'Clean gutters', 'Remove leaves and debris from all gutters', 5, 2, 1, 7, CURRENT_DATE - INTERVAL '70 days', CURRENT_DATE + INTERVAL '110 days', 175.00, NULL, false, false), (11, NOW() - INTERVAL '100 days', NOW(), 1, 2, 5, 'Clean gutters', 'Remove leaves and debris from all gutters', 5, 2, false, 7, CURRENT_DATE - INTERVAL '70 days', CURRENT_DATE + INTERVAL '110 days', 175.00, NULL, false, false),
(12, NOW() - INTERVAL '3 days', NOW(), 1, 2, NULL, 'Fertilize lawn', 'Apply spring fertilizer treatment', 5, 1, 1, 6, CURRENT_DATE + INTERVAL '5 days', NULL, 75.00, 5, false, false), (12, NOW() - INTERVAL '3 days', NOW(), 1, 2, NULL, 'Fertilize lawn', 'Apply spring fertilizer treatment', 5, 1, false, 6, CURRENT_DATE + INTERVAL '5 days', NULL, 75.00, 5, false, false),
-- Safety tasks -- Safety tasks
-- Task 13: Annual recurring, completed 150 days ago -> next_due_date = completion + 365 days = ~215 days from now -- Task 13: Annual recurring, completed 150 days ago -> next_due_date = completion + 365 days = ~215 days from now
(13, NOW() - INTERVAL '180 days', NOW(), 1, 2, 2, 'Test fire extinguishers', 'Annual inspection of all fire extinguishers', 7, 3, 1, 8, CURRENT_DATE - INTERVAL '150 days', CURRENT_DATE + INTERVAL '215 days', 0.00, NULL, false, false), (13, NOW() - INTERVAL '180 days', NOW(), 1, 2, 2, 'Test fire extinguishers', 'Annual inspection of all fire extinguishers', 7, 3, false, 8, CURRENT_DATE - INTERVAL '150 days', CURRENT_DATE + INTERVAL '215 days', 0.00, NULL, false, false),
-- Cleaning tasks -- Cleaning tasks
-- Task 14: Annual recurring, completed 25 days ago -> next_due_date = completion + 365 days = ~340 days from now -- Task 14: Annual recurring, completed 25 days ago -> next_due_date = completion + 365 days = ~340 days from now
(14, NOW() - INTERVAL '40 days', NOW(), 1, 2, 3, 'Deep clean carpets', 'Professional carpet cleaning for all rooms', 8, 1, 1, 8, CURRENT_DATE - INTERVAL '25 days', CURRENT_DATE + INTERVAL '340 days', 350.00, NULL, false, false), (14, NOW() - INTERVAL '40 days', NOW(), 1, 2, 3, 'Deep clean carpets', 'Professional carpet cleaning for all rooms', 8, 1, false, 8, CURRENT_DATE - INTERVAL '25 days', CURRENT_DATE + INTERVAL '340 days', 350.00, NULL, false, false),
-- On hold task -- On hold task
(15, NOW() - INTERVAL '50 days', NOW(), 1, 2, NULL, 'Paint exterior', 'Repaint exterior trim and shutters', 6, 2, 4, 1, CURRENT_DATE + INTERVAL '90 days', NULL, 2500.00, NULL, false, false), (15, NOW() - INTERVAL '50 days', NOW(), 1, 2, NULL, 'Paint exterior', 'Repaint exterior trim and shutters', 6, 2, false, 1, CURRENT_DATE + INTERVAL '90 days', NULL, 2500.00, NULL, false, false),
-- ===== RESIDENCE 2 (Beach House) - 8 tasks ===== -- ===== RESIDENCE 2 (Beach House) - 8 tasks =====
-- Task 16: Weekly recurring, completed 6 days ago -> next_due_date = completion + 7 days = ~1 day from now -- Task 16: Weekly recurring, completed 6 days ago -> next_due_date = completion + 7 days = ~1 day from now
(16, NOW() - INTERVAL '20 days', NOW(), 2, 2, 2, 'Check pool chemicals', 'Weekly pool water testing and chemical balance', 10, 2, 1, 3, CURRENT_DATE - INTERVAL '6 days', CURRENT_DATE + INTERVAL '1 day', 50.00, NULL, false, false), (16, NOW() - INTERVAL '20 days', NOW(), 2, 2, 2, 'Check pool chemicals', 'Weekly pool water testing and chemical balance', 10, 2, false, 3, CURRENT_DATE - INTERVAL '6 days', CURRENT_DATE + INTERVAL '1 day', 50.00, NULL, false, false),
(17, NOW() - INTERVAL '15 days', NOW(), 2, 2, NULL, 'Hurricane shutter inspection', 'Annual inspection before hurricane season', 7, 3, 1, 8, CURRENT_DATE + INTERVAL '45 days', NULL, 300.00, 7, false, false), (17, NOW() - INTERVAL '15 days', NOW(), 2, 2, NULL, 'Hurricane shutter inspection', 'Annual inspection before hurricane season', 7, 3, false, 8, CURRENT_DATE + INTERVAL '45 days', NULL, 300.00, 7, false, false),
(18, NOW() - INTERVAL '30 days', NOW(), 2, 2, NULL, 'AC filter change', 'Replace AC filters - salt air requires more frequent changes', 3, 2, 1, 5, CURRENT_DATE + INTERVAL '5 days', NULL, 60.00, NULL, false, false), (18, NOW() - INTERVAL '30 days', NOW(), 2, 2, NULL, 'AC filter change', 'Replace AC filters - salt air requires more frequent changes', 3, 2, false, 5, CURRENT_DATE + INTERVAL '5 days', NULL, 60.00, NULL, false, false),
(19, NOW() - INTERVAL '60 days', NOW(), 2, 2, 2, 'Fix outdoor shower', 'Outdoor shower has low pressure', 1, 2, 3, 1, CURRENT_DATE - INTERVAL '40 days', NULL, 200.00, 6, false, false), (19, NOW() - INTERVAL '60 days', NOW(), 2, 2, 2, 'Fix outdoor shower', 'Outdoor shower has low pressure', 1, 2, false, 1, CURRENT_DATE - INTERVAL '40 days', NULL, 200.00, 6, false, false),
(20, NOW() - INTERVAL '5 days', NOW(), 2, 2, NULL, 'Pressure wash deck', 'Clean salt buildup from deck and railings', 8, 1, 1, 6, CURRENT_DATE + INTERVAL '30 days', NULL, 250.00, NULL, false, false), (20, NOW() - INTERVAL '5 days', NOW(), 2, 2, NULL, 'Pressure wash deck', 'Clean salt buildup from deck and railings', 8, 1, false, 6, CURRENT_DATE + INTERVAL '30 days', NULL, 250.00, NULL, false, false),
-- Task 21: Quarterly recurring, completed 60 days ago -> next_due_date = completion + 90 days = ~30 days from now -- Task 21: Quarterly recurring, completed 60 days ago -> next_due_date = completion + 90 days = ~30 days from now
(21, NOW() - INTERVAL '90 days', NOW(), 2, 2, NULL, 'Pest control treatment', 'Quarterly pest control for beach property', 9, 2, 1, 6, CURRENT_DATE - INTERVAL '60 days', CURRENT_DATE + INTERVAL '30 days', 150.00, NULL, false, false), (21, NOW() - INTERVAL '90 days', NOW(), 2, 2, NULL, 'Pest control treatment', 'Quarterly pest control for beach property', 9, 2, false, 6, CURRENT_DATE - INTERVAL '60 days', CURRENT_DATE + INTERVAL '30 days', 150.00, NULL, false, false),
(22, NOW() - INTERVAL '10 days', NOW(), 2, 2, NULL, 'Replace patio furniture', 'Sun-damaged furniture needs replacement', 10, 1, 4, 1, CURRENT_DATE + INTERVAL '60 days', NULL, 1200.00, NULL, false, false), (22, NOW() - INTERVAL '10 days', NOW(), 2, 2, NULL, 'Replace patio furniture', 'Sun-damaged furniture needs replacement', 10, 1, false, 1, CURRENT_DATE + INTERVAL '60 days', NULL, 1200.00, NULL, false, false),
(23, NOW() - INTERVAL '180 days', NOW(), 2, 2, 2, 'Install security cameras', 'Add 4 outdoor security cameras', 7, 2, 3, 1, CURRENT_DATE - INTERVAL '150 days', NULL, 800.00, NULL, false, false), (23, NOW() - INTERVAL '180 days', NOW(), 2, 2, 2, 'Install security cameras', 'Add 4 outdoor security cameras', 7, 2, false, 1, CURRENT_DATE - INTERVAL '150 days', NULL, 800.00, NULL, false, false),
-- ===== RESIDENCE 3 (Investment Duplex) - 5 tasks ===== -- ===== RESIDENCE 3 (Investment Duplex) - 5 tasks =====
(24, NOW() - INTERVAL '25 days', NOW(), 3, 2, NULL, 'Unit A - Repair drywall', 'Patch and paint drywall damage from tenant', 6, 2, 1, 1, CURRENT_DATE + INTERVAL '14 days', NULL, 400.00, NULL, false, false), (24, NOW() - INTERVAL '25 days', NOW(), 3, 2, NULL, 'Unit A - Repair drywall', 'Patch and paint drywall damage from tenant', 6, 2, false, 1, CURRENT_DATE + INTERVAL '14 days', NULL, 400.00, NULL, false, false),
(25, NOW() - INTERVAL '10 days', NOW(), 3, 2, NULL, 'Unit B - Replace dishwasher', 'Dishwasher not draining properly', 4, 3, 2, 1, CURRENT_DATE + INTERVAL '3 days', NULL, 650.00, NULL, false, false), (25, NOW() - INTERVAL '10 days', NOW(), 3, 2, NULL, 'Unit B - Replace dishwasher', 'Dishwasher not draining properly', 4, 3, true, 1, CURRENT_DATE + INTERVAL '3 days', NULL, 650.00, NULL, false, false),
-- Task 26: Annual recurring, completed 30 days ago -> next_due_date = completion + 365 days = ~335 days from now -- Task 26: Annual recurring, completed 30 days ago -> next_due_date = completion + 365 days = ~335 days from now
(26, NOW() - INTERVAL '45 days', NOW(), 3, 2, 2, 'Annual fire inspection', 'Required annual fire safety inspection', 7, 3, 1, 8, CURRENT_DATE - INTERVAL '30 days', CURRENT_DATE + INTERVAL '335 days', 150.00, NULL, false, false), (26, NOW() - INTERVAL '45 days', NOW(), 3, 2, 2, 'Annual fire inspection', 'Required annual fire safety inspection', 7, 3, false, 8, CURRENT_DATE - INTERVAL '30 days', CURRENT_DATE + INTERVAL '335 days', 150.00, NULL, false, false),
(27, NOW() - INTERVAL '5 days', NOW(), 3, 2, NULL, 'Replace hallway carpet', 'Common area carpet showing wear', 6, 1, 1, 1, CURRENT_DATE + INTERVAL '45 days', NULL, 1500.00, NULL, false, false), (27, NOW() - INTERVAL '5 days', NOW(), 3, 2, NULL, 'Replace hallway carpet', 'Common area carpet showing wear', 6, 1, false, 1, CURRENT_DATE + INTERVAL '45 days', NULL, 1500.00, NULL, false, false),
-- Task 28: Annual recurring, archived, completed 170 days ago -> next_due_date = completion + 365 days = ~195 days from now -- Task 28: Annual recurring, archived, completed 170 days ago -> next_due_date = completion + 365 days = ~195 days from now
(28, NOW() - INTERVAL '200 days', NOW(), 3, 2, NULL, 'Roof inspection', 'Annual roof inspection', 6, 2, 1, 8, CURRENT_DATE - INTERVAL '170 days', CURRENT_DATE + INTERVAL '195 days', 250.00, NULL, false, true), (28, NOW() - INTERVAL '200 days', NOW(), 3, 2, NULL, 'Roof inspection', 'Annual roof inspection', 6, 2, false, 8, CURRENT_DATE - INTERVAL '170 days', CURRENT_DATE + INTERVAL '195 days', 250.00, NULL, false, true),
-- ===== RESIDENCE 4 (Jane's Downtown Loft) - 7 tasks ===== -- ===== RESIDENCE 4 (Jane's Downtown Loft) - 7 tasks =====
(29, NOW() - INTERVAL '15 days', NOW(), 4, 3, 3, 'Fix garbage disposal', 'Disposal is jammed and making noise', 4, 3, 2, 1, CURRENT_DATE + INTERVAL '2 days', NULL, 150.00, 8, false, false), (29, NOW() - INTERVAL '15 days', NOW(), 4, 3, 3, 'Fix garbage disposal', 'Disposal is jammed and making noise', 4, 3, true, 1, CURRENT_DATE + INTERVAL '2 days', NULL, 150.00, 8, false, false),
(30, NOW() - INTERVAL '30 days', NOW(), 4, 3, NULL, 'Clean dryer vent', 'Annual dryer vent cleaning for fire safety', 7, 3, 1, 8, CURRENT_DATE + INTERVAL '30 days', NULL, 125.00, NULL, false, false), (30, NOW() - INTERVAL '30 days', NOW(), 4, 3, NULL, 'Clean dryer vent', 'Annual dryer vent cleaning for fire safety', 7, 3, false, 8, CURRENT_DATE + INTERVAL '30 days', NULL, 125.00, NULL, false, false),
(31, NOW() - INTERVAL '60 days', NOW(), 4, 3, 3, 'Touch up paint', 'Touch up scuff marks on walls', 6, 1, 3, 1, CURRENT_DATE - INTERVAL '45 days', NULL, 0.00, NULL, false, false), (31, NOW() - INTERVAL '60 days', NOW(), 4, 3, 3, 'Touch up paint', 'Touch up scuff marks on walls', 6, 1, false, 1, CURRENT_DATE - INTERVAL '45 days', NULL, 0.00, NULL, false, false),
(32, NOW() - INTERVAL '7 days', NOW(), 4, 3, NULL, 'Replace refrigerator water filter', 'Bi-annual filter replacement', 4, 1, 1, 7, CURRENT_DATE + INTERVAL '14 days', NULL, 50.00, 9, false, false), (32, NOW() - INTERVAL '7 days', NOW(), 4, 3, NULL, 'Replace refrigerator water filter', 'Bi-annual filter replacement', 4, 1, false, 7, CURRENT_DATE + INTERVAL '14 days', NULL, 50.00, 9, false, false),
-- Task 33: Annual recurring, completed 60 days ago -> next_due_date = completion + 365 days = ~305 days from now -- Task 33: Annual recurring, completed 60 days ago -> next_due_date = completion + 365 days = ~305 days from now
(33, NOW() - INTERVAL '90 days', NOW(), 4, 3, NULL, 'Deep clean oven', 'Professional oven cleaning', 8, 1, 1, 8, CURRENT_DATE - INTERVAL '60 days', CURRENT_DATE + INTERVAL '305 days', 100.00, NULL, false, false), (33, NOW() - INTERVAL '90 days', NOW(), 4, 3, NULL, 'Deep clean oven', 'Professional oven cleaning', 8, 1, false, 8, CURRENT_DATE - INTERVAL '60 days', CURRENT_DATE + INTERVAL '305 days', 100.00, NULL, false, false),
(34, NOW() - INTERVAL '120 days', NOW(), 4, 3, 3, 'Install smart thermostat', 'Replace old thermostat with Nest', 3, 2, 3, 1, CURRENT_DATE - INTERVAL '100 days', NULL, 250.00, NULL, false, false), (34, NOW() - INTERVAL '120 days', NOW(), 4, 3, 3, 'Install smart thermostat', 'Replace old thermostat with Nest', 3, 2, false, 1, CURRENT_DATE - INTERVAL '100 days', NULL, 250.00, NULL, false, false),
(35, NOW() - INTERVAL '3 days', NOW(), 4, 3, NULL, 'Repair window blinds', 'Bedroom blinds cord is broken', 10, 1, 1, 1, CURRENT_DATE + INTERVAL '21 days', NULL, 75.00, NULL, false, false), (35, NOW() - INTERVAL '3 days', NOW(), 4, 3, NULL, 'Repair window blinds', 'Bedroom blinds cord is broken', 10, 1, false, 1, CURRENT_DATE + INTERVAL '21 days', NULL, 75.00, NULL, false, false),
-- ===== RESIDENCE 5 (Bob's Mountain Condo) - 6 tasks ===== -- ===== RESIDENCE 5 (Bob's Mountain Condo) - 6 tasks =====
-- Task 36: Annual recurring, completed 10 days ago -> next_due_date = completion + 365 days = ~355 days from now -- Task 36: Annual recurring, completed 10 days ago -> next_due_date = completion + 365 days = ~355 days from now
(36, NOW() - INTERVAL '20 days', NOW(), 5, 4, 4, 'Winterize pipes', 'Prepare plumbing for winter freeze', 1, 3, 1, 8, CURRENT_DATE - INTERVAL '10 days', CURRENT_DATE + INTERVAL '355 days', 200.00, NULL, false, false), (36, NOW() - INTERVAL '20 days', NOW(), 5, 4, 4, 'Winterize pipes', 'Prepare plumbing for winter freeze', 1, 3, false, 8, CURRENT_DATE - INTERVAL '10 days', CURRENT_DATE + INTERVAL '355 days', 200.00, NULL, false, false),
-- Task 37: One-time (frequency=1), completed -> stays completed with no next_due_date -- Task 37: One-time (frequency=1), completed -> stays completed with no next_due_date
(37, NOW() - INTERVAL '40 days', NOW(), 5, 4, NULL, 'Check roof for snow damage', 'Inspect after heavy snowfall', 6, 3, 3, 1, CURRENT_DATE - INTERVAL '35 days', NULL, 0.00, 10, false, false), (37, NOW() - INTERVAL '40 days', NOW(), 5, 4, NULL, 'Check roof for snow damage', 'Inspect after heavy snowfall', 6, 3, false, 1, CURRENT_DATE - INTERVAL '35 days', NULL, 0.00, 10, false, false),
(38, NOW() - INTERVAL '10 days', NOW(), 5, 4, 12, 'Tune ski equipment storage', 'Organize ski room and check equipment', 10, 1, 2, 8, CURRENT_DATE + INTERVAL '7 days', NULL, 0.00, NULL, false, false), (38, NOW() - INTERVAL '10 days', NOW(), 5, 4, 12, 'Tune ski equipment storage', 'Organize ski room and check equipment', 10, 1, true, 8, CURRENT_DATE + INTERVAL '7 days', NULL, 0.00, NULL, false, false),
(39, NOW() - INTERVAL '5 days', NOW(), 5, 4, NULL, 'Replace entry door weatherstrip', 'Cold air leaking around front door', 6, 2, 1, 1, CURRENT_DATE + INTERVAL '10 days', NULL, 100.00, NULL, false, false), (39, NOW() - INTERVAL '5 days', NOW(), 5, 4, NULL, 'Replace entry door weatherstrip', 'Cold air leaking around front door', 6, 2, false, 1, CURRENT_DATE + INTERVAL '10 days', NULL, 100.00, NULL, false, false),
-- Task 40: Annual recurring, completed 60 days ago -> next_due_date = completion + 365 days = ~305 days from now -- Task 40: Annual recurring, completed 60 days ago -> next_due_date = completion + 365 days = ~305 days from now
(40, NOW() - INTERVAL '90 days', NOW(), 5, 4, 4, 'HOA deck staining', 'Required deck maintenance per HOA', 5, 2, 1, 8, CURRENT_DATE - INTERVAL '60 days', CURRENT_DATE + INTERVAL '305 days', 500.00, NULL, false, false), (40, NOW() - INTERVAL '90 days', NOW(), 5, 4, 4, 'HOA deck staining', 'Required deck maintenance per HOA', 5, 2, false, 8, CURRENT_DATE - INTERVAL '60 days', CURRENT_DATE + INTERVAL '305 days', 500.00, NULL, false, false),
-- Task 41: Annual recurring, completed 150 days ago -> next_due_date = completion + 365 days = ~215 days from now -- Task 41: Annual recurring, completed 150 days ago -> next_due_date = completion + 365 days = ~215 days from now
(41, NOW() - INTERVAL '180 days', NOW(), 5, 4, NULL, 'Fireplace inspection', 'Annual chimney and fireplace check', 7, 3, 1, 8, CURRENT_DATE - INTERVAL '150 days', CURRENT_DATE + INTERVAL '215 days', 175.00, NULL, false, false), (41, NOW() - INTERVAL '180 days', NOW(), 5, 4, NULL, 'Fireplace inspection', 'Annual chimney and fireplace check', 7, 3, false, 8, CURRENT_DATE - INTERVAL '150 days', CURRENT_DATE + INTERVAL '215 days', 175.00, NULL, false, false),
-- ===== RESIDENCE 8 (Alice's Craftsman) - 6 tasks ===== -- ===== RESIDENCE 8 (Alice's Craftsman) - 6 tasks =====
(42, NOW() - INTERVAL '25 days', NOW(), 8, 5, 5, 'Refinish hardwood floors', 'Sand and refinish original hardwood in living room', 6, 2, 2, 1, CURRENT_DATE + INTERVAL '30 days', NULL, 2000.00, 13, false, false), (42, NOW() - INTERVAL '25 days', NOW(), 8, 5, 5, 'Refinish hardwood floors', 'Sand and refinish original hardwood in living room', 6, 2, true, 1, CURRENT_DATE + INTERVAL '30 days', NULL, 2000.00, 13, false, false),
(43, NOW() - INTERVAL '50 days', NOW(), 8, 5, 9, 'Repair original windows', 'Restore and weatherproof historic windows', 6, 2, 3, 1, CURRENT_DATE - INTERVAL '20 days', NULL, 1500.00, 13, false, false), (43, NOW() - INTERVAL '50 days', NOW(), 8, 5, 9, 'Repair original windows', 'Restore and weatherproof historic windows', 6, 2, false, 1, CURRENT_DATE - INTERVAL '20 days', NULL, 1500.00, 13, false, false),
(44, NOW() - INTERVAL '15 days', NOW(), 8, 5, NULL, 'Update knob and tube wiring', 'Replace section of old wiring in attic', 2, 4, 1, 1, CURRENT_DATE + INTERVAL '14 days', NULL, 3000.00, NULL, false, false), (44, NOW() - INTERVAL '15 days', NOW(), 8, 5, NULL, 'Update knob and tube wiring', 'Replace section of old wiring in attic', 2, 4, false, 1, CURRENT_DATE + INTERVAL '14 days', NULL, 3000.00, NULL, false, false),
-- Task 45: Weekly recurring, completed 7 days ago -> next_due_date = completion + 7 days = today (due soon) -- Task 45: Weekly recurring, completed 7 days ago -> next_due_date = completion + 7 days = today (due soon)
(45, NOW() - INTERVAL '30 days', NOW(), 8, 5, 5, 'Garden maintenance', 'Weekly garden care and weeding', 5, 1, 1, 3, CURRENT_DATE - INTERVAL '7 days', CURRENT_DATE, 75.00, NULL, false, false), (45, NOW() - INTERVAL '30 days', NOW(), 8, 5, 5, 'Garden maintenance', 'Weekly garden care and weeding', 5, 1, false, 3, CURRENT_DATE - INTERVAL '7 days', CURRENT_DATE, 75.00, NULL, false, false),
(46, NOW() - INTERVAL '7 days', NOW(), 8, 5, NULL, 'Fix porch swing', 'Chains need tightening and wood needs oiling', 10, 1, 1, 1, CURRENT_DATE + INTERVAL '21 days', NULL, 50.00, 13, false, false), (46, NOW() - INTERVAL '7 days', NOW(), 8, 5, NULL, 'Fix porch swing', 'Chains need tightening and wood needs oiling', 10, 1, false, 1, CURRENT_DATE + INTERVAL '21 days', NULL, 50.00, 13, false, false),
-- Task 47: Semi-annual recurring, completed 30 days ago -> next_due_date = completion + 180 days = ~150 days from now -- Task 47: Semi-annual recurring, completed 30 days ago -> next_due_date = completion + 180 days = ~150 days from now
(47, NOW() - INTERVAL '60 days', NOW(), 8, 5, 5, 'Clean rain gutters', 'Clear leaves from craftsman-style gutters', 5, 2, 1, 7, CURRENT_DATE - INTERVAL '30 days', CURRENT_DATE + INTERVAL '150 days', 200.00, NULL, false, false), (47, NOW() - INTERVAL '60 days', NOW(), 8, 5, 5, 'Clean rain gutters', 'Clear leaves from craftsman-style gutters', 5, 2, false, 7, CURRENT_DATE - INTERVAL '30 days', CURRENT_DATE + INTERVAL '150 days', 200.00, NULL, false, false),
-- ===== RESIDENCE 11 (Edward's Fixer Upper) - 5 tasks ===== -- ===== RESIDENCE 11 (Edward's Fixer Upper) - 5 tasks =====
(48, NOW() - INTERVAL '14 days', NOW(), 11, 8, 8, 'Demo bathroom tile', 'Remove old tile in master bathroom', 6, 3, 2, 1, CURRENT_DATE + INTERVAL '7 days', NULL, 500.00, 15, false, false), (48, NOW() - INTERVAL '14 days', NOW(), 11, 8, 8, 'Demo bathroom tile', 'Remove old tile in master bathroom', 6, 3, true, 1, CURRENT_DATE + INTERVAL '7 days', NULL, 500.00, 15, false, false),
(49, NOW() - INTERVAL '10 days', NOW(), 11, 8, NULL, 'Install new cabinets', 'Kitchen cabinet installation', 6, 3, 1, 1, CURRENT_DATE + INTERVAL '21 days', NULL, 5000.00, 16, false, false), (49, NOW() - INTERVAL '10 days', NOW(), 11, 8, NULL, 'Install new cabinets', 'Kitchen cabinet installation', 6, 3, false, 1, CURRENT_DATE + INTERVAL '21 days', NULL, 5000.00, 16, false, false),
(50, NOW() - INTERVAL '7 days', NOW(), 11, 8, 8, 'Run new electrical', 'Additional outlets for kitchen', 2, 3, 2, 1, CURRENT_DATE + INTERVAL '14 days', NULL, 1200.00, NULL, false, false), (50, NOW() - INTERVAL '7 days', NOW(), 11, 8, 8, 'Run new electrical', 'Additional outlets for kitchen', 2, 3, true, 1, CURRENT_DATE + INTERVAL '14 days', NULL, 1200.00, NULL, false, false),
(51, NOW() - INTERVAL '3 days', NOW(), 11, 8, NULL, 'Plumbing rough-in', 'Rough plumbing for bathroom remodel', 1, 3, 1, 1, CURRENT_DATE + INTERVAL '10 days', NULL, 2500.00, NULL, false, false), (51, NOW() - INTERVAL '3 days', NOW(), 11, 8, NULL, 'Plumbing rough-in', 'Rough plumbing for bathroom remodel', 1, 3, false, 1, CURRENT_DATE + INTERVAL '10 days', NULL, 2500.00, NULL, false, false),
(52, NOW() - INTERVAL '1 day', NOW(), 11, 8, 8, 'Order new appliances', 'Select and order kitchen appliances', 4, 2, 2, 1, CURRENT_DATE + INTERVAL '5 days', NULL, 4000.00, NULL, false, false), (52, NOW() - INTERVAL '1 day', NOW(), 11, 8, 8, 'Order new appliances', 'Select and order kitchen appliances', 4, 2, true, 1, CURRENT_DATE + INTERVAL '5 days', NULL, 4000.00, NULL, false, false),
-- ===== RESIDENCE 12 (Fiona's Studio) - 4 tasks ===== -- ===== RESIDENCE 12 (Fiona's Studio) - 4 tasks =====
(53, NOW() - INTERVAL '7 days', NOW(), 12, 9, 9, 'Setup smart lights', 'Install Philips Hue throughout studio', 2, 1, 3, 1, CURRENT_DATE - INTERVAL '3 days', NULL, 400.00, 17, false, false), (53, NOW() - INTERVAL '7 days', NOW(), 12, 9, 9, 'Setup smart lights', 'Install Philips Hue throughout studio', 2, 1, false, 1, CURRENT_DATE - INTERVAL '3 days', NULL, 400.00, 17, false, false),
(54, NOW() - INTERVAL '5 days', NOW(), 12, 9, NULL, 'Mount TV on wall', 'Install TV mount and hide cables', 2, 1, 1, 1, CURRENT_DATE + INTERVAL '10 days', NULL, 200.00, 17, false, false), (54, NOW() - INTERVAL '5 days', NOW(), 12, 9, NULL, 'Mount TV on wall', 'Install TV mount and hide cables', 2, 1, false, 1, CURRENT_DATE + INTERVAL '10 days', NULL, 200.00, 17, false, false),
(55, NOW() - INTERVAL '3 days', NOW(), 12, 9, 9, 'Organize closet', 'Install closet organization system', 10, 1, 2, 1, CURRENT_DATE + INTERVAL '7 days', NULL, 300.00, NULL, false, false), (55, NOW() - INTERVAL '3 days', NOW(), 12, 9, 9, 'Organize closet', 'Install closet organization system', 10, 1, true, 1, CURRENT_DATE + INTERVAL '7 days', NULL, 300.00, NULL, false, false),
(56, NOW() - INTERVAL '1 day', NOW(), 12, 9, NULL, 'Replace faucet aerator', 'Low water pressure in bathroom sink', 1, 1, 1, 1, CURRENT_DATE + INTERVAL '14 days', NULL, 15.00, NULL, false, false), (56, NOW() - INTERVAL '1 day', NOW(), 12, 9, NULL, 'Replace faucet aerator', 'Low water pressure in bathroom sink', 1, 1, false, 1, CURRENT_DATE + INTERVAL '14 days', NULL, 15.00, NULL, false, false),
-- ===== RESIDENCE 13 (George's Townhome) - 5 tasks ===== -- ===== RESIDENCE 13 (George's Townhome) - 5 tasks =====
-- Task 57: Quarterly recurring, completed 15 days ago -> next_due_date = completion + 90 days = ~75 days from now -- Task 57: Quarterly recurring, completed 15 days ago -> next_due_date = completion + 90 days = ~75 days from now
(57, NOW() - INTERVAL '30 days', NOW(), 13, 12, 12, 'Service pool equipment', 'Quarterly pool pump and filter service', 10, 2, 1, 6, CURRENT_DATE - INTERVAL '15 days', CURRENT_DATE + INTERVAL '75 days', 175.00, 19, false, false), (57, NOW() - INTERVAL '30 days', NOW(), 13, 12, 12, 'Service pool equipment', 'Quarterly pool pump and filter service', 10, 2, false, 6, CURRENT_DATE - INTERVAL '15 days', CURRENT_DATE + INTERVAL '75 days', 175.00, 19, false, false),
(58, NOW() - INTERVAL '20 days', NOW(), 13, 12, NULL, 'HVAC maintenance', 'Pre-summer AC tune-up', 3, 2, 1, 8, CURRENT_DATE + INTERVAL '30 days', NULL, 200.00, 18, false, false), (58, NOW() - INTERVAL '20 days', NOW(), 13, 12, NULL, 'HVAC maintenance', 'Pre-summer AC tune-up', 3, 2, false, 8, CURRENT_DATE + INTERVAL '30 days', NULL, 200.00, 18, false, false),
(59, NOW() - INTERVAL '10 days', NOW(), 13, 12, 12, 'Trim desert landscaping', 'Prune cacti and desert plants', 5, 1, 2, 6, CURRENT_DATE + INTERVAL '5 days', NULL, 100.00, NULL, false, false), (59, NOW() - INTERVAL '10 days', NOW(), 13, 12, 12, 'Trim desert landscaping', 'Prune cacti and desert plants', 5, 1, true, 6, CURRENT_DATE + INTERVAL '5 days', NULL, 100.00, NULL, false, false),
-- Task 60: Monthly recurring, completed 30 days ago -> next_due_date = completion + 30 days = today (due soon) -- Task 60: Monthly recurring, completed 30 days ago -> next_due_date = completion + 30 days = today (due soon)
(60, NOW() - INTERVAL '45 days', NOW(), 13, 12, 12, 'Check irrigation system', 'Test all drip irrigation zones', 5, 2, 1, 5, CURRENT_DATE - INTERVAL '30 days', CURRENT_DATE, 50.00, NULL, false, false), (60, NOW() - INTERVAL '45 days', NOW(), 13, 12, 12, 'Check irrigation system', 'Test all drip irrigation zones', 5, 2, false, 5, CURRENT_DATE - INTERVAL '30 days', CURRENT_DATE, 50.00, NULL, false, false),
(61, NOW() - INTERVAL '5 days', NOW(), 13, 12, NULL, 'Replace garage door opener', 'Old opener failing', 4, 2, 1, 1, CURRENT_DATE + INTERVAL '14 days', NULL, 400.00, NULL, false, false), (61, NOW() - INTERVAL '5 days', NOW(), 13, 12, NULL, 'Replace garage door opener', 'Old opener failing', 4, 2, false, 1, CURRENT_DATE + INTERVAL '14 days', NULL, 400.00, NULL, false, false),
-- Cancelled task -- Cancelled task
(62, NOW() - INTERVAL '60 days', NOW(), 1, 2, NULL, 'Build treehouse', 'Cancelled - tree not suitable', 6, 1, 5, 1, CURRENT_DATE - INTERVAL '30 days', NULL, 2000.00, NULL, true, false) (62, NOW() - INTERVAL '60 days', NOW(), 1, 2, NULL, 'Build treehouse', 'Cancelled - tree not suitable', 6, 1, false, 1, CURRENT_DATE - INTERVAL '30 days', NULL, 2000.00, NULL, true, false)
ON CONFLICT (id) DO UPDATE SET title = EXCLUDED.title, updated_at = NOW(); ON CONFLICT (id) DO UPDATE SET title = EXCLUDED.title, updated_at = NOW();
-- ===================================================== -- =====================================================