# Task 8: Backend Task Endpoints Custom Status Support

## Overview

This implementation adds support for custom task statuses to all task-related endpoints in the backend. The system now validates statuses against both system statuses and project-specific custom statuses, ensuring proper status resolution across project boundaries.

## Changes Made

### 1. Added Helper Functions (`backend/routers/tasks.py`)

#### `get_project_default_status(db: Session, project_id: int) -> str`
- Retrieves the default status for a project
- Checks for custom statuses with `is_default=True` flag
- Falls back to system default "not_started" if no custom default is set
- Handles JSON parsing for custom_task_statuses field

#### `validate_task_status(db: Session, project_id: int, status_value: str) -> bool`
- Validates that a status exists for a specific project
- Checks system statuses first (not_started, in_progress, submitted, approved, retake)
- Then checks project-specific custom statuses
- Returns True if valid, False otherwise
- Ensures status isolation between projects

### 2. Updated Task Creation Endpoint

**Endpoint**: `POST /tasks/`

**Changes**:
- Uses `get_project_default_status()` when no status is specified
- Validates provided status using `validate_task_status()`
- Returns 400 error if invalid status is provided
- Maintains backward compatibility with system statuses

**Example**:
```python
# Use default status if not specified
task_data = task.model_dump()
if not task_data.get('status') or task_data['status'] == 'not_started':
    task_data['status'] = get_project_default_status(db, task.project_id)
else:
    # Validate the provided status
    if not validate_task_status(db, task.project_id, task_data['status']):
        raise HTTPException(
            status_code=400, 
            detail=f"Invalid status '{task_data['status']}' for this project"
        )
```

### 3. Updated Task Status Update Endpoint

**Endpoint**: `PUT /tasks/{task_id}/status`

**Changes**:
- Validates new status against project's available statuses
- Returns 400 error if status is invalid for the task's project
- Supports both system and custom statuses

**Example**:
```python
# Validate the status for the task's project
if not validate_task_status(db, task.project_id, status_update.status):
    raise HTTPException(
        status_code=400,
        detail=f"Invalid status '{status_update.status}' for this project"
    )
```

### 4. Updated Task Update Endpoint

**Endpoint**: `PUT /tasks/{task_id}`

**Changes**:
- Validates status field if it's being updated
- Checks status validity before applying update
- Maintains existing permission checks

### 5. Updated Bulk Status Update Endpoint

**Endpoint**: `PUT /tasks/bulk/status`

**Changes**:
- Validates status for each task's project before updating
- Ensures atomic updates - all tasks succeed or all fail
- Provides detailed error messages for invalid statuses
- Handles tasks from different projects correctly

**Example**:
```python
# Validate status for the task's project
if not validate_task_status(db, task.project_id, bulk_update.status):
    errors.append({
        "task_id": task_id,
        "error": f"Invalid status '{bulk_update.status}' for task's project"
    })
    failed_count += 1
    continue
```

## Requirements Addressed

### Requirement 5.3: Default Status for New Tasks
✅ Task creation uses project's default status when not specified
✅ Falls back to system default "not_started" for projects without custom statuses

### Requirement 6.4: Backward Compatibility
✅ System statuses (not_started, in_progress, submitted, approved, retake) remain valid for all projects
✅ Existing tasks with system statuses continue to work

### Requirement 6.5: Status Resolution
✅ Status validation checks both system and custom statuses
✅ Custom statuses are project-specific and don't leak between projects

### Requirement 10.1: Bulk Status Update Validation
✅ Bulk updates validate status for each task's project
✅ Atomic updates ensure consistency

### Requirement 10.2: Cross-Project Handling
✅ Tasks from different projects can be updated in bulk
✅ Each task's status is validated against its own project's statuses

## Testing

### Test Coverage

Created comprehensive test suite (`backend/test_task_custom_status_support.py`) covering:

1. **Task Creation with Default Status**
   - ✅ Default status correctly identified from custom statuses
   - ✅ Tasks created without explicit status use project default
   - ✅ Tasks can be created with explicit custom status

2. **Status Validation**
   - ✅ All system statuses validated successfully
   - ✅ Custom statuses validated for their project
   - ✅ Invalid statuses correctly rejected

3. **Status Resolution Across Projects**
   - ✅ Project 1 custom statuses rejected for Project 2
   - ✅ Project 2 custom statuses rejected for Project 1
   - ✅ System statuses valid for all projects
   - ✅ Each project has its own default status

4. **Bulk Status Update Validation**
   - ✅ Status validated for each task's project
   - ✅ System statuses valid for all tasks
   - ✅ Custom statuses only valid for their project

5. **Projects Without Custom Statuses**
   - ✅ Use system default "not_started"
   - ✅ System statuses remain valid
   - ✅ Custom statuses from other projects rejected

### Test Results

```
============================================================
Testing Task Endpoints Custom Status Support
============================================================

=== Test 1: Task Creation with Default Status ===
✓ Default status correctly identified: custom_todo
✓ Task created with default status: custom_todo
✓ Task created with explicit custom status: custom_doing
✓ Test 1 PASSED

=== Test 2: Status Validation ===
✓ All system statuses validated successfully
✓ All custom statuses validated successfully
✓ Invalid statuses correctly rejected
✓ Test 2 PASSED

=== Test 3: Status Resolution Across Projects ===
✓ Project 1 custom status correctly rejected for Project 2
✓ Project 2 custom status correctly rejected for Project 1
✓ System statuses valid for both projects
✓ Project 1 default: custom_todo, Project 2 default: project2_status
✓ Test 3 PASSED

=== Test 4: Bulk Status Update Validation ===
✓ Validated 2 tasks from Project 1
✓ Validated 0 tasks from Project 2
✓ System statuses valid for all 2 tasks
✓ Test 4 PASSED

=== Test 5: Project Without Custom Statuses ===
✓ Project without custom statuses uses system default: not_started
✓ System statuses valid for project without custom statuses
✓ Custom statuses from other projects correctly rejected
✓ Test 5 PASSED

============================================================
✓ ALL TESTS PASSED
============================================================
```

## API Behavior

### Task Creation
```json
POST /tasks/
{
  "project_id": 1,
  "name": "New Task",
  "task_type": "modeling",
  // status not specified - will use project default
}
```

### Task Status Update
```json
PUT /tasks/123/status
{
  "status": "custom_todo"  // Must be valid for task's project
}
```

### Bulk Status Update
```json
PUT /tasks/bulk/status
{
  "task_ids": [1, 2, 3],
  "status": "custom_doing"  // Validated for each task's project
}
```

## Error Handling

### Invalid Status Error
```json
{
  "detail": "Invalid status 'custom_nonexistent' for this project"
}
```

### Bulk Update Errors
```json
{
  "success_count": 2,
  "failed_count": 1,
  "errors": [
    {
      "task_id": 3,
      "error": "Invalid status 'custom_todo' for task's project"
    }
  ]
}
```

## Database Schema

No database changes required. The implementation uses existing fields:
- `projects.custom_task_statuses` (JSON) - stores custom statuses
- `tasks.status` (String) - stores status value

## Backward Compatibility

✅ **Fully backward compatible**
- Existing tasks with system statuses continue to work
- Projects without custom statuses use system defaults
- System statuses remain valid for all projects
- No migration required

## Next Steps

The frontend components should be updated to:
1. Fetch custom statuses from `/projects/{id}/task-statuses` endpoint
2. Display custom status colors in UI
3. Use custom statuses in status dropdowns and filters
4. Handle validation errors from backend

## Related Files

- `backend/routers/tasks.py` - Main implementation
- `backend/routers/projects.py` - Custom status management endpoints
- `backend/models/task.py` - Task model (status field is String)
- `backend/models/project.py` - Project model (custom_task_statuses field)
- `backend/test_task_custom_status_support.py` - Test suite
