Files
HarborForge.Backend/app/models/task.py
zhi c84884fe64 BE-PR-008: add Proposal Accept tracking fields (source_proposal_id, source_essential_id)
- Add source_proposal_id and source_essential_id FK columns to Task model
- Populate tracking fields during Proposal Accept task generation
- Add generated_tasks relationship on Proposal model for reverse lookup
- Expose source_proposal_id/source_essential_id in TaskResponse schema
- Add GeneratedTaskBrief schema and include generated_tasks in ProposalDetailResponse
- Proposal detail endpoint now returns generated story tasks with status
2026-03-30 10:46:20 +00:00

73 lines
3.0 KiB
Python

from sqlalchemy import Column, Integer, String, Text, DateTime, ForeignKey, Enum, Time
from sqlalchemy.orm import relationship
from sqlalchemy.sql import func
from app.core.config import Base
import enum
class TaskStatus(str, enum.Enum):
OPEN = "open"
PENDING = "pending"
UNDERGOING = "undergoing"
COMPLETED = "completed"
CLOSED = "closed"
class TaskPriority(str, enum.Enum):
LOW = "low"
MEDIUM = "medium"
HIGH = "high"
CRITICAL = "critical"
class Task(Base):
__tablename__ = "tasks"
id = Column(Integer, primary_key=True, index=True)
title = Column(String(255), nullable=False)
description = Column(Text, nullable=True)
status = Column(Enum(TaskStatus, values_callable=lambda x: [e.value for e in x]), default=TaskStatus.OPEN)
priority = Column(Enum(TaskPriority, values_callable=lambda x: [e.value for e in x]), default=TaskPriority.MEDIUM)
task_code = Column(String(64), nullable=True, unique=True, index=True)
# Task type/subtype (replaces old issue_type/issue_subtype)
task_type = Column(String(32), default="issue") # P7.1: default changed from 'task' to 'issue'
task_subtype = Column(String(64), nullable=True)
project_id = Column(Integer, ForeignKey("projects.id"), nullable=False)
milestone_id = Column(Integer, ForeignKey("milestones.id"), nullable=False)
reporter_id = Column(Integer, ForeignKey("users.id"), nullable=False)
assignee_id = Column(Integer, ForeignKey("users.id"), nullable=True)
created_by_id = Column(Integer, ForeignKey("users.id"), nullable=True)
# Proposal Accept tracking (BE-PR-008)
# When a task is generated from Proposal Accept, these record the source.
source_proposal_id = Column(
Integer, ForeignKey("proposes.id"), nullable=True,
comment="Proposal that generated this task via accept (NULL if manually created)",
)
source_essential_id = Column(
Integer, ForeignKey("essentials.id"), nullable=True,
comment="Essential that generated this task via accept (NULL if manually created)",
)
# Tags (comma-separated)
tags = Column(String(500), nullable=True)
# Dependencies
depend_on = Column(Text, nullable=True)
related_tasks = Column(Text, nullable=True)
# Effort tracking
estimated_effort = Column(Integer, nullable=True)
estimated_working_time = Column(Time, nullable=True)
started_on = Column(DateTime(timezone=True), nullable=True)
finished_on = Column(DateTime(timezone=True), nullable=True)
# Resolution specific fields (for task_type="resolution")
resolution_summary = Column(Text, nullable=True)
positions = Column(Text, nullable=True)
pending_matters = Column(Text, nullable=True)
created_at = Column(DateTime(timezone=True), server_default=func.now())
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
comments = relationship("Comment", foreign_keys="Comment.task_id", cascade="all, delete-orphan")