102 lines
3.6 KiB
Python
102 lines
3.6 KiB
Python
"""
|
|
Commitment models for the Virtual Board Member AI System.
|
|
"""
|
|
|
|
from datetime import datetime
|
|
from typing import Optional
|
|
from sqlalchemy import Column, String, DateTime, Boolean, Text, Integer, ForeignKey, Date
|
|
from sqlalchemy.dialects.postgresql import UUID, JSONB
|
|
from sqlalchemy.orm import relationship
|
|
import uuid
|
|
import enum
|
|
|
|
from app.core.database import Base
|
|
|
|
|
|
class CommitmentStatus(str, enum.Enum):
|
|
"""Commitment status enumeration."""
|
|
PENDING = "pending"
|
|
IN_PROGRESS = "in_progress"
|
|
COMPLETED = "completed"
|
|
OVERDUE = "overdue"
|
|
CANCELLED = "cancelled"
|
|
DEFERRED = "deferred"
|
|
|
|
|
|
class CommitmentPriority(str, enum.Enum):
|
|
"""Commitment priority levels."""
|
|
LOW = "low"
|
|
MEDIUM = "medium"
|
|
HIGH = "high"
|
|
CRITICAL = "critical"
|
|
|
|
|
|
class Commitment(Base):
|
|
"""Commitment model for tracking board and executive commitments."""
|
|
|
|
__tablename__ = "commitments"
|
|
|
|
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
|
|
# Commitment details
|
|
title = Column(String(500), nullable=False, index=True)
|
|
description = Column(Text, nullable=True)
|
|
commitment_text = Column(Text, nullable=False) # Original text from document
|
|
|
|
# Status and priority
|
|
status = Column(String(50), default=CommitmentStatus.PENDING, nullable=False)
|
|
priority = Column(String(20), default=CommitmentPriority.MEDIUM, nullable=False)
|
|
|
|
# Dates
|
|
due_date = Column(Date, nullable=True)
|
|
completion_date = Column(Date, nullable=True)
|
|
|
|
# Assignment
|
|
assigned_to = Column(UUID(as_uuid=True), ForeignKey("users.id"), nullable=True)
|
|
assigned_by = Column(UUID(as_uuid=True), ForeignKey("users.id"), nullable=True)
|
|
|
|
# Source information
|
|
document_id = Column(UUID(as_uuid=True), ForeignKey("documents.id"), nullable=False)
|
|
document_page = Column(Integer, nullable=True) # Page number in document
|
|
document_section = Column(String(200), nullable=True) # Section/context
|
|
|
|
# AI extraction metadata
|
|
confidence_score = Column(Integer, nullable=True) # 0-100 confidence in extraction
|
|
extraction_method = Column(String(50), nullable=True) # LLM, rule-based, etc.
|
|
extraction_metadata = Column(JSONB, nullable=True) # Additional extraction info
|
|
|
|
# Progress tracking
|
|
progress_notes = Column(Text, nullable=True)
|
|
progress_percentage = Column(Integer, default=0) # 0-100
|
|
|
|
# Notifications
|
|
reminder_enabled = Column(Boolean, default=True)
|
|
reminder_frequency = Column(String(50), default="weekly") # daily, weekly, monthly
|
|
|
|
# Timestamps
|
|
created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
|
|
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
|
|
|
|
# Relationships
|
|
document = relationship("Document", back_populates="commitments")
|
|
assigned_user = relationship("User", foreign_keys=[assigned_to])
|
|
assigned_by_user = relationship("User", foreign_keys=[assigned_by])
|
|
|
|
def __repr__(self):
|
|
return f"<Commitment(id={self.id}, title='{self.title}', status='{self.status}')>"
|
|
|
|
@property
|
|
def is_overdue(self) -> bool:
|
|
"""Check if commitment is overdue."""
|
|
if self.due_date and self.status not in [CommitmentStatus.COMPLETED, CommitmentStatus.CANCELLED]:
|
|
return datetime.now().date() > self.due_date
|
|
return False
|
|
|
|
@property
|
|
def days_until_due(self) -> Optional[int]:
|
|
"""Get days until due date."""
|
|
if self.due_date:
|
|
delta = self.due_date - datetime.now().date()
|
|
return delta.days
|
|
return None
|