# Shot Task Creation Endpoint

## Overview

Added a new backend endpoint to create tasks for shots, enabling AJAX-based task status editing in the frontend shot table.

## Endpoint Details

### POST /shots/{shot_id}/tasks

**Purpose**: Create a new task for a specific shot

**Location**: `backend/routers/shots.py` (after `get_shot` endpoint)

**Authentication**: Requires coordinator or admin role

**Parameters**:
- `shot_id` (path): The ID of the shot
- `task_type` (query): The type of task to create (e.g., "layout", "animation")

**Request Example**:
```
POST /shots/1/tasks?task_type=layout
Authorization: Bearer {token}
```

**Response** (201 Created):
```json
{
  "task_type": "layout",
  "status": "not_started",
  "task_id": 123,
  "assigned_user_id": null
}
```

**Response** (200 OK - if task already exists):
```json
{
  "task_type": "layout",
  "status": "in_progress",
  "task_id": 123,
  "assigned_user_id": 5
}
```

## Implementation

```python
@router.post("/{shot_id}/tasks", response_model=TaskStatusInfo, status_code=status.HTTP_201_CREATED)
async def create_shot_task(
    shot_id: int,
    task_type: str,
    db: Session = Depends(get_db),
    current_user: User = Depends(require_coordinator_or_admin)
):
    """Create a new task for a shot"""
    shot = db.query(Shot).filter(Shot.id == shot_id).first()
    
    if not shot:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Shot not found"
        )
    
    # Check episode access
    episode = check_episode_access(shot.episode_id, current_user, db)
    
    # Check if task already exists
    existing_task = db.query(Task).filter(
        Task.shot_id == shot_id,
        Task.task_type == task_type
    ).first()
    
    if existing_task:
        # Return existing task info instead of error (idempotent)
        return TaskStatusInfo(
            task_type=existing_task.task_type,
            status=existing_task.status,
            task_id=existing_task.id,
            assigned_user_id=existing_task.assigned_user_id
        )
    
    # Create the task
    task_name = f"{shot.name} - {task_type.title()}"
    db_task = Task(
        project_id=episode.project_id,
        shot_id=shot.id,
        task_type=task_type,
        name=task_name,
        description=f"{task_type.title()} task for {shot.name}",
        status=TaskStatus.NOT_STARTED
    )
    
    db.add(db_task)
    db.commit()
    db.refresh(db_task)
    
    return TaskStatusInfo(
        task_type=db_task.task_type,
        status=db_task.status,
        task_id=db_task.id,
        assigned_user_id=db_task.assigned_user_id
    )
```

## Key Features

### 1. Idempotent Operation
- If task already exists, returns existing task info
- No error thrown for duplicate creation attempts
- Simplifies frontend logic (no need to check existence first)

### 2. Permission Validation
- Requires coordinator or admin role
- Uses `require_coordinator_or_admin` dependency
- Artists cannot create tasks directly

### 3. Access Control
- Validates shot exists
- Checks episode access via `check_episode_access`
- Ensures user has permission to access the project

### 4. Automatic Task Naming
- Format: `{shot_name} - {task_type}`
- Example: "SH010 - Layout"
- Consistent with asset task naming

### 5. Default Values
- Status: `NOT_STARTED`
- Description: Auto-generated
- Project ID: Inherited from episode
- No assignee initially

## Error Responses

### 404 Not Found
```json
{
  "detail": "Shot not found"
}
```

### 403 Forbidden
```json
{
  "detail": "Insufficient permissions"
}
```

Or:
```json
{
  "detail": "Access denied to this project"
}
```

## Comparison with Asset Endpoint

The shot task creation endpoint mirrors the asset version:

| Feature | Asset Endpoint | Shot Endpoint |
|---------|---------------|---------------|
| Path | `/assets/{asset_id}/tasks` | `/shots/{shot_id}/tasks` |
| Permission | Coordinator/Admin | Coordinator/Admin |
| Idempotent | ✅ Yes | ✅ Yes |
| Access Check | `check_project_access` | `check_episode_access` |
| Task Naming | `{asset.name} - {type}` | `{shot.name} - {type}` |
| Project ID | From asset | From episode |

## Frontend Integration

This endpoint is called by:
- `frontend/src/services/task.ts` - `createShotTask()` method
- `frontend/src/components/shot/EditableTaskStatus.vue` - When changing status for non-existent task

**Usage Flow**:
1. User changes task status in shot table
2. Frontend checks if task exists (via `taskId` prop)
3. If no task exists, calls `createShotTask(shotId, taskType)`
4. Backend creates task and returns task ID
5. Frontend then calls `updateTaskStatus(taskId, newStatus)`
6. Status is updated and table refreshes

## Testing

Test file created: `backend/test_shot_task_creation.py`

**Manual Testing**:
1. Navigate to project shots tab
2. Switch to table view
3. Click on a task status cell for a shot without that task
4. Select a status
5. Verify:
   - Task is created
   - Status is set
   - No errors in console
   - Table updates correctly

## Related Files

- `backend/routers/shots.py` - Endpoint implementation
- `backend/routers/assets.py` - Reference implementation for assets
- `backend/schemas/shot.py` - TaskStatusInfo schema
- `backend/models/task.py` - Task model
- `frontend/src/services/task.ts` - Frontend service calling this endpoint
- `frontend/src/components/shot/EditableTaskStatus.vue` - Component using this endpoint

## Future Enhancements

Potential improvements:

1. **Bulk Task Creation**: Create multiple tasks at once
2. **Custom Defaults**: Allow project-specific default task settings
3. **Template Support**: Use task templates for consistent setup
4. **Validation**: Validate task_type against allowed types
5. **Webhooks**: Trigger notifications when tasks are created
6. **Audit Log**: Track who created which tasks and when

## Conclusion

The shot task creation endpoint successfully enables AJAX-based task status editing in the shot table, providing a seamless user experience without page refreshes. The implementation follows the same pattern as the asset endpoint, ensuring consistency across the application.
