refactor: update milestone/task status enums to new state machine values
Milestone: open/freeze/undergoing/completed/closed (was open/pending/deferred/progressing/closed) Task: open/pending/undergoing/completed/closed (was open/pending/progressing/closed) - Add MilestoneStatusEnum to schemas with typed validation - Add started_at field to Milestone model - Update all router/CLI references from progressing->undergoing - Add completed status handling in task transition logic
This commit is contained in:
@@ -111,8 +111,8 @@ def create_milestone_task(project_id: int, milestone_id: int, task_data: schemas
|
||||
if not milestone:
|
||||
raise HTTPException(status_code=404, detail="Milestone not found")
|
||||
|
||||
if milestone.status and hasattr(milestone.status, 'value') and milestone.status.value == "progressing":
|
||||
raise HTTPException(status_code=400, detail="Cannot add items to a milestone that is in_progress")
|
||||
if milestone.status and hasattr(milestone.status, 'value') and milestone.status.value == "undergoing":
|
||||
raise HTTPException(status_code=400, detail="Cannot add items to a milestone that is undergoing")
|
||||
|
||||
# Generate task_code
|
||||
milestone_code = milestone.milestone_code or f"m{milestone.id}"
|
||||
|
||||
@@ -425,8 +425,8 @@ def create_milestone_task(project_code: str, milestone_id: int, task_data: dict,
|
||||
if not ms:
|
||||
raise HTTPException(status_code=404, detail="Milestone not found")
|
||||
|
||||
if ms.status and hasattr(ms.status, "value") and ms.status.value == "progressing":
|
||||
raise HTTPException(status_code=400, detail="Cannot add items to a milestone that is in_progress")
|
||||
if ms.status and hasattr(ms.status, "value") and ms.status.value == "undergoing":
|
||||
raise HTTPException(status_code=400, detail="Cannot add items to a milestone that is undergoing")
|
||||
|
||||
milestone_code = ms.milestone_code or f"m{ms.id}"
|
||||
max_task = db.query(Task).filter(Task.milestone_id == ms.id).order_by(Task.id.desc()).first()
|
||||
@@ -504,8 +504,8 @@ def create_support(project_code: str, milestone_id: int, support_data: dict, db:
|
||||
if not ms:
|
||||
raise HTTPException(status_code=404, detail="Milestone not found")
|
||||
|
||||
if ms.status and hasattr(ms.status, "value") and ms.status.value == "progressing":
|
||||
raise HTTPException(status_code=400, detail="Cannot add items to a milestone that is in_progress")
|
||||
if ms.status and hasattr(ms.status, "value") and ms.status.value == "undergoing":
|
||||
raise HTTPException(status_code=400, detail="Cannot add items to a milestone that is undergoing")
|
||||
|
||||
milestone_code = ms.milestone_code or f"m{ms.id}"
|
||||
max_support = db.query(Support).filter(Support.milestone_id == milestone_id).order_by(Support.id.desc()).first()
|
||||
@@ -563,8 +563,8 @@ def create_meeting(project_code: str, milestone_id: int, meeting_data: dict, db:
|
||||
if not ms:
|
||||
raise HTTPException(status_code=404, detail="Milestone not found")
|
||||
|
||||
if ms.status and hasattr(ms.status, "value") and ms.status.value == "progressing":
|
||||
raise HTTPException(status_code=400, detail="Cannot add items to a milestone that is in_progress")
|
||||
if ms.status and hasattr(ms.status, "value") and ms.status.value == "undergoing":
|
||||
raise HTTPException(status_code=400, detail="Cannot add items to a milestone that is undergoing")
|
||||
|
||||
milestone_code = ms.milestone_code or f"m{ms.id}"
|
||||
max_meeting = db.query(Meeting).filter(Meeting.milestone_id == milestone_id).order_by(Meeting.id.desc()).first()
|
||||
|
||||
@@ -167,9 +167,9 @@ def update_task(task_id: int, task_update: schemas.TaskUpdate, db: Session = Dep
|
||||
update_data = task_update.model_dump(exclude_unset=True)
|
||||
if "status" in update_data:
|
||||
new_status = update_data["status"]
|
||||
if new_status == "progressing" and not task.started_on:
|
||||
if new_status == "undergoing" and not task.started_on:
|
||||
task.started_on = datetime.utcnow()
|
||||
if new_status == "closed" and not task.finished_on:
|
||||
if new_status in ("closed", "completed") and not task.finished_on:
|
||||
task.finished_on = datetime.utcnow()
|
||||
|
||||
for field, value in update_data.items():
|
||||
@@ -202,9 +202,9 @@ def transition_task(task_id: int, new_status: str, bg: BackgroundTasks, db: Sess
|
||||
if not task:
|
||||
raise HTTPException(status_code=404, detail="Task not found")
|
||||
old_status = task.status.value if hasattr(task.status, 'value') else task.status
|
||||
if new_status == "progressing" and not task.started_on:
|
||||
if new_status == "undergoing" and not task.started_on:
|
||||
task.started_on = datetime.utcnow()
|
||||
if new_status == "closed" and not task.finished_on:
|
||||
if new_status in ("closed", "completed") and not task.finished_on:
|
||||
task.finished_on = datetime.utcnow()
|
||||
task.status = new_status
|
||||
db.commit()
|
||||
|
||||
@@ -6,9 +6,9 @@ import enum
|
||||
|
||||
class MilestoneStatus(str, enum.Enum):
|
||||
OPEN = "open"
|
||||
PENDING = "pending"
|
||||
DEFERRED = "deferred"
|
||||
PROGRESSING = "progressing"
|
||||
FREEZE = "freeze"
|
||||
UNDERGOING = "undergoing"
|
||||
COMPLETED = "completed"
|
||||
CLOSED = "closed"
|
||||
|
||||
class Milestone(Base):
|
||||
@@ -25,6 +25,7 @@ class Milestone(Base):
|
||||
depend_on_tasks = Column(Text, nullable=True)
|
||||
project_id = Column(Integer, ForeignKey("projects.id"), nullable=False)
|
||||
created_by_id = Column(Integer, ForeignKey("users.id"), nullable=True)
|
||||
started_at = Column(DateTime(timezone=True), nullable=True)
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
|
||||
|
||||
|
||||
@@ -21,7 +21,8 @@ class TaskType(str, enum.Enum):
|
||||
class TaskStatus(str, enum.Enum):
|
||||
OPEN = "open"
|
||||
PENDING = "pending"
|
||||
PROGRESSING = "progressing"
|
||||
UNDERGOING = "undergoing"
|
||||
COMPLETED = "completed"
|
||||
CLOSED = "closed"
|
||||
|
||||
|
||||
|
||||
@@ -7,7 +7,8 @@ import enum
|
||||
class TaskStatus(str, enum.Enum):
|
||||
OPEN = "open"
|
||||
PENDING = "pending"
|
||||
PROGRESSING = "progressing"
|
||||
UNDERGOING = "undergoing"
|
||||
COMPLETED = "completed"
|
||||
CLOSED = "closed"
|
||||
|
||||
class TaskPriority(str, enum.Enum):
|
||||
|
||||
@@ -18,7 +18,8 @@ class TaskTypeEnum(str, Enum):
|
||||
class TaskStatusEnum(str, Enum):
|
||||
OPEN = "open"
|
||||
PENDING = "pending"
|
||||
PROGRESSING = "progressing"
|
||||
UNDERGOING = "undergoing"
|
||||
COMPLETED = "completed"
|
||||
CLOSED = "closed"
|
||||
|
||||
|
||||
@@ -193,11 +194,19 @@ class ProjectMemberResponse(BaseModel):
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class MilestoneStatusEnum(str, Enum):
|
||||
OPEN = "open"
|
||||
FREEZE = "freeze"
|
||||
UNDERGOING = "undergoing"
|
||||
COMPLETED = "completed"
|
||||
CLOSED = "closed"
|
||||
|
||||
|
||||
# Milestone schemas
|
||||
class MilestoneBase(BaseModel):
|
||||
title: str
|
||||
description: Optional[str] = None
|
||||
status: Optional[str] = "open"
|
||||
status: Optional[MilestoneStatusEnum] = MilestoneStatusEnum.OPEN
|
||||
due_date: Optional[datetime] = None
|
||||
planned_release_date: Optional[datetime] = None
|
||||
depend_on_milestones: Optional[List[str]] = None
|
||||
@@ -212,7 +221,7 @@ class MilestoneCreate(MilestoneBase):
|
||||
class MilestoneUpdate(BaseModel):
|
||||
title: Optional[str] = None
|
||||
description: Optional[str] = None
|
||||
status: Optional[str] = None
|
||||
status: Optional[MilestoneStatusEnum] = None
|
||||
due_date: Optional[datetime] = None
|
||||
planned_release_date: Optional[datetime] = None
|
||||
depend_on_milestones: Optional[List[str]] = None
|
||||
@@ -223,6 +232,7 @@ class MilestoneResponse(MilestoneBase):
|
||||
id: int
|
||||
project_id: int
|
||||
created_by_id: Optional[int] = None
|
||||
started_at: Optional[datetime] = None
|
||||
created_at: datetime
|
||||
updated_at: Optional[datetime] = None
|
||||
|
||||
|
||||
Reference in New Issue
Block a user