c09710f4e5
Departments are now a customizable per-project list (standard + custom), matching the existing custom task type/status pattern, instead of a fixed 7-value enum. They're usable directly on tasks (new field, independent of assignee) and continue to drive team member department roles.
252 lines
6.5 KiB
Python
252 lines
6.5 KiB
Python
from pydantic import BaseModel, Field
|
|
from typing import Optional, List
|
|
from datetime import date, datetime
|
|
from enum import Enum
|
|
|
|
from models.task import TaskType, TaskStatus, ReviewDecision, AttachmentType, NoteType
|
|
|
|
|
|
class TaskBase(BaseModel):
|
|
name: str = Field(..., min_length=1, max_length=255)
|
|
description: Optional[str] = None
|
|
task_type: str # Changed from TaskType enum to str to support custom task types
|
|
start_date: Optional[date] = None
|
|
deadline: Optional[date] = None
|
|
status: str = "not_started" # Changed from TaskStatus enum to str to support custom statuses
|
|
department: Optional[str] = None # Standard or project-custom department, independent of assignee
|
|
|
|
|
|
class TaskCreate(TaskBase):
|
|
project_id: int
|
|
episode_id: Optional[int] = None
|
|
shot_id: Optional[int] = None
|
|
asset_id: Optional[int] = None
|
|
assigned_user_id: Optional[int] = None
|
|
|
|
|
|
class TaskUpdate(BaseModel):
|
|
name: Optional[str] = Field(None, min_length=1, max_length=255)
|
|
description: Optional[str] = None
|
|
task_type: Optional[str] = None # Changed from TaskType enum to str to support custom task types
|
|
start_date: Optional[date] = None
|
|
deadline: Optional[date] = None
|
|
status: Optional[str] = None # Changed from TaskStatus enum to str to support custom statuses
|
|
department: Optional[str] = None # Standard or project-custom department, independent of assignee
|
|
assigned_user_id: Optional[int] = None
|
|
|
|
|
|
class TaskStatusUpdate(BaseModel):
|
|
status: str # Changed from TaskStatus enum to str to support custom statuses
|
|
|
|
|
|
class TaskAssignment(BaseModel):
|
|
assigned_user_id: int
|
|
|
|
|
|
class TaskResponse(TaskBase):
|
|
id: int
|
|
project_id: int
|
|
episode_id: Optional[int] = None
|
|
shot_id: Optional[int] = None
|
|
asset_id: Optional[int] = None
|
|
assigned_user_id: Optional[int] = None
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
|
|
# Related entity names for display
|
|
project_name: Optional[str] = None
|
|
episode_name: Optional[str] = None
|
|
shot_name: Optional[str] = None
|
|
asset_name: Optional[str] = None
|
|
assigned_user_name: Optional[str] = None
|
|
assigned_user_email: Optional[str] = None
|
|
assigned_user_avatar_url: Optional[str] = None
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class TaskListResponse(BaseModel):
|
|
id: int
|
|
name: str
|
|
task_type: str # Changed from TaskType enum to str to support custom task types
|
|
status: str # Changed from TaskStatus enum to str to support custom statuses
|
|
department: Optional[str] = None # Standard or project-custom department, independent of assignee
|
|
start_date: Optional[date] = None
|
|
deadline: Optional[date] = None
|
|
project_id: int
|
|
project_name: str
|
|
episode_id: Optional[int] = None
|
|
episode_name: Optional[str] = None
|
|
shot_id: Optional[int] = None
|
|
shot_name: Optional[str] = None
|
|
asset_id: Optional[int] = None
|
|
asset_name: Optional[str] = None
|
|
assigned_user_id: Optional[int] = None
|
|
assigned_user_name: Optional[str] = None
|
|
assigned_user_avatar_url: Optional[str] = None
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# Production Notes schemas
|
|
class ProductionNoteBase(BaseModel):
|
|
content: str = Field(..., min_length=1)
|
|
parent_note_id: Optional[int] = None
|
|
|
|
|
|
class ProductionNoteCreate(ProductionNoteBase):
|
|
note_type: NoteType = NoteType.INTERNAL
|
|
|
|
|
|
class ProductionNoteUpdate(BaseModel):
|
|
content: str = Field(..., min_length=1)
|
|
|
|
|
|
class ProductionNoteResponse(ProductionNoteBase):
|
|
id: int
|
|
task_id: int
|
|
user_id: int
|
|
note_type: NoteType
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
|
|
# User information
|
|
user_first_name: str
|
|
user_last_name: str
|
|
user_email: str
|
|
user_avatar_url: Optional[str] = None
|
|
|
|
# Child notes for threading
|
|
child_notes: Optional[List['ProductionNoteResponse']] = None
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# Task Attachment schemas
|
|
class TaskAttachmentBase(BaseModel):
|
|
file_name: str
|
|
attachment_type: AttachmentType = AttachmentType.REFERENCE
|
|
description: Optional[str] = None
|
|
|
|
|
|
class TaskAttachmentCreate(TaskAttachmentBase):
|
|
pass
|
|
|
|
|
|
class TaskAttachmentResponse(TaskAttachmentBase):
|
|
id: int
|
|
task_id: int
|
|
user_id: int
|
|
file_path: str
|
|
file_type: str
|
|
file_size: int
|
|
uploaded_at: datetime
|
|
|
|
# User information
|
|
user_first_name: str
|
|
user_last_name: str
|
|
|
|
# File serving URLs (computed properties)
|
|
download_url: Optional[str] = None
|
|
thumbnail_url: Optional[str] = None
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# Submission schemas
|
|
class SubmissionBase(BaseModel):
|
|
notes: Optional[str] = None
|
|
|
|
|
|
class SubmissionCreate(SubmissionBase):
|
|
pass
|
|
|
|
|
|
class SubmissionUpdate(BaseModel):
|
|
notes: Optional[str] = None
|
|
|
|
|
|
class SubmissionResponse(SubmissionBase):
|
|
id: int
|
|
task_id: int
|
|
user_id: int
|
|
file_path: str
|
|
file_name: str
|
|
version_number: int
|
|
submitted_at: datetime
|
|
|
|
# User information
|
|
user_first_name: str
|
|
user_last_name: str
|
|
|
|
# Latest review if any
|
|
latest_review: Optional['ReviewResponse'] = None
|
|
|
|
# File serving URLs (computed properties)
|
|
download_url: Optional[str] = None
|
|
thumbnail_url: Optional[str] = None
|
|
stream_url: Optional[str] = None
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class SubmissionDateInfo(BaseModel):
|
|
"""Minimal per-task submission date, for lightweight bulk lookups (e.g. Gantt markers)."""
|
|
task_id: int
|
|
submitted_at: datetime
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# Review schemas
|
|
class ReviewBase(BaseModel):
|
|
decision: ReviewDecision
|
|
feedback: Optional[str] = None
|
|
|
|
|
|
class ReviewCreate(ReviewBase):
|
|
pass
|
|
|
|
|
|
class ReviewResponse(ReviewBase):
|
|
id: int
|
|
submission_id: int
|
|
reviewer_id: int
|
|
reviewed_at: datetime
|
|
|
|
# Reviewer information
|
|
reviewer_first_name: str
|
|
reviewer_last_name: str
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# Bulk action schemas
|
|
class BulkStatusUpdate(BaseModel):
|
|
task_ids: List[int] = Field(..., min_length=1)
|
|
status: str # Changed from TaskStatus enum to str to support custom statuses
|
|
|
|
|
|
class BulkAssignment(BaseModel):
|
|
task_ids: List[int] = Field(..., min_length=1)
|
|
assigned_user_id: int
|
|
|
|
|
|
class BulkActionResult(BaseModel):
|
|
success_count: int
|
|
failed_count: int
|
|
errors: Optional[List[dict]] = None
|
|
|
|
|
|
# Update forward references
|
|
ProductionNoteResponse.model_rebuild()
|
|
SubmissionResponse.model_rebuild() |