from sqlalchemy import Column, Integer, String, Boolean, DateTime, ForeignKey, Text from sqlalchemy.sql import func from app.db.session import Base class Task(Base): __tablename__ = "tasks" id = Column(Integer, primary_key=True, index=True) title = Column(String, index=True, nullable=False) description = Column(Text, nullable=True) priority = Column(Integer, default=0) # e.g. 1=High, 2=Medium, 3=Low position = Column(Integer, default=0) # order within priority status = Column(String, default="open") # open, in_progress, review, completed, dismissed origin = Column(String, nullable=True) # e.g. "gmail", "nextcloud_todo:Personal", "manual" source_id = Column(String, nullable=True, index=True) # CalDAV UID or IMAP Message-ID source_url = Column(String, nullable=True) # Link to original item (email, task board, etc.) created_at = Column(DateTime(timezone=True), server_default=func.now()) due_date = Column(DateTime(timezone=True), nullable=True) hidden_until = Column(DateTime(timezone=True), nullable=True) agent_ready = Column(Boolean, default=False) # Flag: orchestrator can pick this up labels = Column(String, nullable=True) # Comma-separated labels for filtering last_synced_at = Column(DateTime(timezone=True), nullable=True) # When last synced with remote has_conflict = Column(Boolean, default=False) # True if conflict detected conflict_data = Column(Text, nullable=True) # JSON: remote version of conflicting fields class Event(Base): __tablename__ = "events" id = Column(Integer, primary_key=True, index=True) title = Column(String, index=True, nullable=False) start_time = Column(DateTime(timezone=True), nullable=False) end_time = Column(DateTime(timezone=True), nullable=False) source = Column(String, nullable=False) # e.g. "google", "nextcloud" is_conflict = Column(Boolean, default=False) created_at = Column(DateTime(timezone=True), server_default=func.now()) class Suggestion(Base): __tablename__ = "suggestions" id = Column(Integer, primary_key=True, index=True) content = Column(String, nullable=False) explanation = Column(Text, nullable=True) type = Column(String, nullable=False) # e.g. "schedule_task", "resolve_conflict" status = Column(String, default="pending") # pending, accepted, rejected created_at = Column(DateTime(timezone=True), server_default=func.now()) class UserSession(Base): __tablename__ = "user_sessions" id = Column(Integer, primary_key=True, index=True) session_id = Column(String, unique=True, index=True, nullable=False) username = Column(String, nullable=False) expires_at = Column(DateTime, nullable=False) created_at = Column(DateTime(timezone=True), server_default=func.now()) class ProjectTask(Base): __tablename__ = "project_tasks" id = Column(Integer, primary_key=True, index=True) title = Column(String, nullable=False) description = Column(Text, nullable=True) repo = Column(String, nullable=True) # e.g. "OrgMyLife", "AI-Orchestrator" status = Column(String, default="backlog") # backlog, ready, in_progress, blocked, review, done priority = Column(Integer, default=3) created_at = Column(DateTime(timezone=True), server_default=func.now()) updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now()) class CallItem(Base): __tablename__ = "call_items" id = Column(Integer, primary_key=True, index=True) person = Column(String(200), nullable=False) reason = Column(String(500), nullable=False) phone_number = Column(String(30), nullable=True) original_task_id = Column(Integer, ForeignKey("tasks.id"), nullable=True) priority = Column(Integer, default=3) # 1=Very High, 2=High, 3=Medium, 4=Low status = Column(String, default="pending") # "pending" or "done" created_at = Column(DateTime(timezone=True), server_default=func.now())