LinkDesk/backend/schemas/custom_task_status.py

158 lines
5.5 KiB
Python

from pydantic import BaseModel, Field, validator
from typing import List, Optional
import re
class CustomTaskStatus(BaseModel):
"""Schema for a custom task status"""
id: str = Field(..., description="Unique identifier for the status")
name: str = Field(..., min_length=1, max_length=50, description="Display name")
color: str = Field(..., pattern=r'^#[0-9A-Fa-f]{6}$', description="Hex color code")
order: int = Field(..., ge=0, description="Display order")
is_default: bool = Field(default=False, description="Whether this is the default status")
class Config:
from_attributes = True
class CustomTaskStatusCreate(BaseModel):
"""Schema for creating a new custom task status"""
name: str = Field(..., min_length=1, max_length=50, description="Status name")
color: Optional[str] = Field(None, description="Hex color code (e.g., #FF5733)")
@validator('name')
def validate_name(cls, v):
"""Validate and normalize status name"""
# Trim whitespace
v = v.strip()
if not v:
raise ValueError('Status name cannot be empty')
if len(v) > 50:
raise ValueError('Status name cannot exceed 50 characters')
return v
@validator('color')
def validate_color(cls, v):
"""Validate color format if provided"""
if v is None:
return v
# Trim whitespace
v = v.strip()
# Check hex color format
if not re.match(r'^#[0-9A-Fa-f]{6}$', v):
raise ValueError('Color must be a valid hex code (e.g., #FF5733)')
return v.upper() # Normalize to uppercase
class CustomTaskStatusUpdate(BaseModel):
"""Schema for updating a custom task status"""
name: Optional[str] = Field(None, min_length=1, max_length=50, description="Status name")
color: Optional[str] = Field(None, description="Hex color code (e.g., #FF5733)")
is_default: Optional[bool] = Field(None, description="Set as default status")
@validator('name')
def validate_name(cls, v):
"""Validate and normalize status name"""
if v is None:
return v
# Trim whitespace
v = v.strip()
if not v:
raise ValueError('Status name cannot be empty')
if len(v) > 50:
raise ValueError('Status name cannot exceed 50 characters')
return v
@validator('color')
def validate_color(cls, v):
"""Validate color format if provided"""
if v is None:
return v
# Trim whitespace
v = v.strip()
# Check hex color format
if not re.match(r'^#[0-9A-Fa-f]{6}$', v):
raise ValueError('Color must be a valid hex code (e.g., #FF5733)')
return v.upper() # Normalize to uppercase
class CustomTaskStatusReorder(BaseModel):
"""Schema for reordering statuses"""
status_ids: List[str] = Field(..., min_items=1, description="Ordered list of status IDs")
@validator('status_ids')
def validate_status_ids(cls, v):
"""Validate status IDs list"""
if not v:
raise ValueError('Status IDs list cannot be empty')
# Check for duplicates
if len(v) != len(set(v)):
raise ValueError('Status IDs list contains duplicates')
return v
class CustomTaskStatusDelete(BaseModel):
"""Schema for deleting a status with optional reassignment"""
reassign_to_status_id: Optional[str] = Field(
None,
description="Status ID to reassign tasks to (required if status is in use)"
)
class SystemTaskStatus(BaseModel):
"""Schema for system (built-in) task statuses"""
id: str = Field(..., description="System status identifier")
name: str = Field(..., description="Display name")
color: str = Field(..., description="Hex color code")
is_system: bool = Field(default=True, description="Indicates this is a system status")
class Config:
from_attributes = True
class AllTaskStatusesResponse(BaseModel):
"""Schema for response containing all task statuses (system + custom)"""
statuses: List[CustomTaskStatus] = Field(
default_factory=list,
description="Custom task statuses defined for the project"
)
system_statuses: List[SystemTaskStatus] = Field(
default_factory=list,
description="Built-in system task statuses"
)
default_status_id: str = Field(
...,
description="ID of the default status for new tasks"
)
class Config:
from_attributes = True
class TaskStatusInUseError(BaseModel):
"""Schema for error when trying to delete a status that is in use"""
error: str = Field(..., description="Error message")
status_id: str = Field(..., description="ID of the status that cannot be deleted")
status_name: str = Field(..., description="Name of the status that cannot be deleted")
task_count: int = Field(..., ge=0, description="Number of tasks using this status")
task_ids: List[int] = Field(
default_factory=list,
description="IDs of tasks using this status"
)
class Config:
from_attributes = True
class CustomTaskStatusResponse(BaseModel):
"""Schema for successful custom task status operation response"""
message: str = Field(..., description="Success message")
status: Optional[CustomTaskStatus] = Field(None, description="The created or updated status")
all_statuses: Optional[AllTaskStatusesResponse] = Field(
None,
description="All statuses after the operation"
)
class Config:
from_attributes = True