117 lines
3.7 KiB
Python
117 lines
3.7 KiB
Python
"""Task service: CRUD + assignment + status management."""
|
|
from sqlalchemy.orm import Session
|
|
from typing import List, Optional
|
|
from datetime import datetime
|
|
from app.models.task import Task
|
|
from app.schemas.task import TaskCreate, TaskUpdate, TaskAssign
|
|
|
|
|
|
class TaskService:
|
|
@staticmethod
|
|
def list_tasks(
|
|
db: Session,
|
|
tenant_id: int,
|
|
project_id: Optional[int] = None,
|
|
status: Optional[str] = None,
|
|
assignee_id: Optional[int] = None,
|
|
skip: int = 0,
|
|
limit: int = 100,
|
|
) -> List[Task]:
|
|
q = db.query(Task).filter(Task.tenant_id == tenant_id)
|
|
if project_id:
|
|
q = q.filter(Task.project_id == project_id)
|
|
if status:
|
|
q = q.filter(Task.status == status)
|
|
if assignee_id:
|
|
q = q.filter(Task.assignee_id == assignee_id)
|
|
return q.order_by(Task.created_at.desc()).offset(skip).limit(limit).all()
|
|
|
|
@staticmethod
|
|
def get_task(db: Session, tenant_id: int, task_id: int) -> Optional[Task]:
|
|
return (
|
|
db.query(Task)
|
|
.filter(Task.id == task_id, Task.tenant_id == tenant_id)
|
|
.first()
|
|
)
|
|
|
|
@staticmethod
|
|
def create_task(
|
|
db: Session, tenant_id: int, project_id: int, req: TaskCreate
|
|
) -> Task:
|
|
task = Task(
|
|
tenant_id=tenant_id,
|
|
project_id=project_id,
|
|
title=req.title,
|
|
description=req.description,
|
|
status="pending",
|
|
priority=req.priority,
|
|
task_type=req.task_type,
|
|
input_data=req.input_data,
|
|
requires_review=req.requires_review,
|
|
assignee_id=req.assignee_id,
|
|
worker_id=req.worker_id,
|
|
due_date=req.due_date,
|
|
depends_on=req.depends_on,
|
|
)
|
|
db.add(task)
|
|
db.commit()
|
|
db.refresh(task)
|
|
return task
|
|
|
|
@staticmethod
|
|
def update_task(
|
|
db: Session, tenant_id: int, task_id: int, req: TaskUpdate
|
|
) -> Task:
|
|
task = TaskService.get_task(db, tenant_id, task_id)
|
|
if not task:
|
|
raise ValueError(f"Task #{task_id} not found")
|
|
for field, value in req.model_dump(exclude_unset=True).items():
|
|
setattr(task, field, value)
|
|
db.commit()
|
|
db.refresh(task)
|
|
return task
|
|
|
|
@staticmethod
|
|
def delete_task(db: Session, tenant_id: int, task_id: int) -> bool:
|
|
task = TaskService.get_task(db, tenant_id, task_id)
|
|
if not task:
|
|
return False
|
|
db.delete(task)
|
|
db.commit()
|
|
return True
|
|
|
|
@staticmethod
|
|
def assign_task(
|
|
db: Session, tenant_id: int, task_id: int, req: TaskAssign
|
|
) -> Task:
|
|
task = TaskService.get_task(db, tenant_id, task_id)
|
|
if not task:
|
|
raise ValueError(f"Task #{task_id} not found")
|
|
if req.assignee_id is not None:
|
|
task.assignee_id = req.assignee_id
|
|
if req.worker_id is not None:
|
|
task.worker_id = req.worker_id
|
|
if task.status == "pending":
|
|
task.status = "assigned"
|
|
db.commit()
|
|
db.refresh(task)
|
|
return task
|
|
|
|
@staticmethod
|
|
def mark_status(
|
|
db: Session, tenant_id: int, task_id: int, status: str, output: str = ""
|
|
) -> Task:
|
|
task = TaskService.get_task(db, tenant_id, task_id)
|
|
if not task:
|
|
raise ValueError(f"Task #{task_id} not found")
|
|
task.status = status
|
|
if output:
|
|
task.output_data = output
|
|
if status == "in_progress":
|
|
task.started_at = datetime.utcnow()
|
|
elif status in ("done", "review", "rejected", "cancelled"):
|
|
task.completed_at = datetime.utcnow()
|
|
db.commit()
|
|
db.refresh(task)
|
|
return task
|