LinkDesk/backend/docs/task-5-requirements-checkli...

6.1 KiB

Task 5 Requirements Checklist

Task: Backend: Implement PUT endpoint for updating custom status

Requirements Coverage

Requirement 2.1: Support updating name

Implementation:

# Validate name uniqueness if name is being changed
if status_update.name is not None and status_update.name != status_to_update.get('name'):
    # Check against other custom statuses
    existing_names = [
        s.get('name', '').lower() 
        for i, s in enumerate(custom_statuses_data) 
        if isinstance(s, dict) and i != status_index
    ]
    
    # Check against system statuses
    system_names = [s['name'].lower() for s in SYSTEM_TASK_STATUSES]
    
    if status_update.name.lower() in existing_names:
        raise HTTPException(status_code=409, ...)
    
    if status_update.name.lower() in system_names:
        raise HTTPException(status_code=409, ...)
    
    # Update name
    status_to_update['name'] = status_update.name

Verified:

  • Name can be updated
  • Name validation works
  • Uniqueness check implemented
  • Returns updated status

Requirement 2.2: Support updating color

Implementation:

# Update color if provided
if status_update.color is not None:
    status_to_update['color'] = status_update.color

Verified:

  • Color can be updated
  • Color format validated by schema (hex codes)
  • Color updates independently of other fields
  • Returns updated status

Requirement 2.3: Support updating is_default flag

Implementation:

# Handle is_default flag
if status_update.is_default is not None:
    if status_update.is_default:
        # If setting as default, unset other default statuses
        for status_data in custom_statuses_data:
            if isinstance(status_data, dict):
                status_data['is_default'] = False
        
        # Set this status as default
        status_to_update['is_default'] = True
    else:
        # Just unset this status as default
        status_to_update['is_default'] = False

Verified:

  • is_default flag can be updated
  • Can set status as default
  • Can unset status as default
  • Returns updated status

Requirement 5.2: If setting as default, unset other default statuses

Implementation:

if status_update.is_default:
    # If setting as default, unset other default statuses
    for status_data in custom_statuses_data:
        if isinstance(status_data, dict):
            status_data['is_default'] = False
    
    # Set this status as default
    status_to_update['is_default'] = True

Verified:

  • When setting a status as default, all other defaults are unset
  • Only one default status exists at a time
  • Default status ID is correctly returned in response
  • Previous default is properly unset

Additional Requirement: Validate name uniqueness if name is changed

Implementation:

# Validate name uniqueness if name is being changed
if status_update.name is not None and status_update.name != status_to_update.get('name'):
    # Check against other custom statuses
    existing_names = [...]
    
    # Check against system statuses
    system_names = [...]
    
    if status_update.name.lower() in existing_names:
        raise HTTPException(status_code=409, ...)
    
    if status_update.name.lower() in system_names:
        raise HTTPException(status_code=409, ...)

Verified:

  • Name uniqueness validated within project
  • Checks against other custom statuses
  • Checks against system status names
  • Returns 409 Conflict on duplicate

Additional Requirement: Use flag_modified for JSON column updates

Implementation:

# Update the status in the list
custom_statuses_data[status_index] = status_to_update
db_project.custom_task_statuses = custom_statuses_data

# Use flag_modified for JSON column updates
flag_modified(db_project, 'custom_task_statuses')

try:
    db.commit()
    db.refresh(db_project)
except Exception as e:
    db.rollback()
    raise HTTPException(...)

Verified:

  • flag_modified is used
  • Changes persist to database
  • JSON column updates work correctly
  • Rollback on error

Endpoint Details

Route: PUT /projects/{project_id}/task-statuses/{status_id}

Authorization: Requires coordinator or admin role

Request Body:

{
    "name": "string (optional)",
    "color": "string (optional)",
    "is_default": "boolean (optional)"
}

Response: CustomTaskStatusResponse

{
    "message": "string",
    "status": { ... },
    "all_statuses": { ... }
}

Error Codes:

  • 404: Project or status not found
  • 409: Name conflict (duplicate or system status)
  • 403: Insufficient permissions
  • 422: Invalid request body

Test Coverage

Manual Tests Created:

  • test_update_status_manual.py - Comprehensive manual test script
  • Tests all requirements
  • Tests error conditions
  • Tests edge cases

Documentation Created:

  • custom-task-status-update-endpoint.md - Complete API documentation
  • task-5-implementation-summary.md - Implementation summary
  • task-5-requirements-checklist.md - This checklist

Code Quality

Validation:

  • No syntax errors
  • No linting errors
  • Follows existing code patterns
  • Proper error handling
  • Comprehensive validation
  • Clear error messages

Best Practices:

  • Uses dependency injection
  • Proper authorization checks
  • Transaction management (commit/rollback)
  • Input validation via Pydantic schemas
  • Consistent response format
  • Proper HTTP status codes

Summary

All requirements implemented and verified

The PUT endpoint for updating custom task statuses has been successfully implemented with:

  • Full support for updating name, color, and is_default flag
  • Comprehensive validation (uniqueness, format, conflicts)
  • Proper default status management (only one default at a time)
  • Correct JSON column updates using flag_modified
  • Complete error handling and authorization
  • Comprehensive documentation and test scripts

Task Status: COMPLETED