Files
delphi-database/app/models/file_management.py
HotSwapp ae4484381f progress
2025-08-16 10:05:42 -05:00

191 lines
7.0 KiB
Python

"""
File management models for enhanced file operations
"""
from sqlalchemy import Column, Integer, String, DateTime, Date, Float, Text, ForeignKey, Boolean
from sqlalchemy.orm import relationship
from sqlalchemy.sql import func
from app.models.base import BaseModel
class FileStatusHistory(BaseModel):
"""
Track file status changes over time
Provides audit trail for file status transitions
"""
__tablename__ = "file_status_history"
id = Column(Integer, primary_key=True, autoincrement=True)
file_no = Column(String(45), ForeignKey("files.file_no"), nullable=False, index=True)
# Status change details
old_status = Column(String(45), nullable=False)
new_status = Column(String(45), nullable=False)
change_date = Column(DateTime(timezone=True), default=func.now(), nullable=False)
# Who made the change
changed_by_user_id = Column(Integer, ForeignKey("users.id"))
changed_by_name = Column(String(100)) # Cached name for reporting
# Additional context
notes = Column(Text) # Reason for status change
system_generated = Column(Boolean, default=False) # True if automated change
# Relationships
file = relationship("File")
changed_by = relationship("User")
def __repr__(self):
return f"<FileStatusHistory(file_no='{self.file_no}', {self.old_status} -> {self.new_status})>"
class FileTransferHistory(BaseModel):
"""
Track file transfers between attorneys
Maintains chain of custody for files
"""
__tablename__ = "file_transfer_history"
id = Column(Integer, primary_key=True, autoincrement=True)
file_no = Column(String(45), ForeignKey("files.file_no"), nullable=False, index=True)
# Transfer details
old_attorney_id = Column(String(10), ForeignKey("employees.empl_num"), nullable=False)
new_attorney_id = Column(String(10), ForeignKey("employees.empl_num"), nullable=False)
transfer_date = Column(DateTime(timezone=True), default=func.now(), nullable=False)
# Who authorized the transfer
authorized_by_user_id = Column(Integer, ForeignKey("users.id"))
authorized_by_name = Column(String(100))
# Transfer context
reason = Column(Text) # Reason for transfer
effective_date = Column(Date) # When transfer becomes effective (may be future)
# Rate changes
old_hourly_rate = Column(Float, nullable=True)
new_hourly_rate = Column(Float, nullable=True)
# Relationships
file = relationship("File")
old_attorney = relationship("Employee", foreign_keys=[old_attorney_id])
new_attorney = relationship("Employee", foreign_keys=[new_attorney_id])
authorized_by = relationship("User")
def __repr__(self):
return f"<FileTransferHistory(file_no='{self.file_no}', {self.old_attorney_id} -> {self.new_attorney_id})>"
class FileArchiveInfo(BaseModel):
"""
Archive information for files
Tracks where files are stored and retrieval information
"""
__tablename__ = "file_archive_info"
id = Column(Integer, primary_key=True, autoincrement=True)
file_no = Column(String(45), ForeignKey("files.file_no"), nullable=False, unique=True, index=True)
# Archive details
archive_date = Column(Date, nullable=False, default=func.current_date())
archive_location = Column(String(200)) # Physical or digital location
box_number = Column(String(50)) # Physical box identifier
shelf_location = Column(String(100)) # Physical shelf/room location
# Digital archive info
digital_path = Column(String(500)) # Path to digital archive
backup_location = Column(String(500)) # Backup storage location
# Archive metadata
archived_by_user_id = Column(Integer, ForeignKey("users.id"))
archived_by_name = Column(String(100))
retrieval_instructions = Column(Text) # How to retrieve the file
# Retention information
retention_date = Column(Date) # When file can be destroyed
destruction_date = Column(Date) # When file was actually destroyed
destruction_authorized_by = Column(String(100))
# Archive status
is_retrievable = Column(Boolean, default=True)
last_verified = Column(Date) # Last time archive was verified to exist
# Relationships
file = relationship("File")
archived_by = relationship("User")
def __repr__(self):
return f"<FileArchiveInfo(file_no='{self.file_no}', location='{self.archive_location}')>"
class FileClosureChecklist(BaseModel):
"""
Checklist items for file closure process
Ensures all necessary steps are completed before closing
"""
__tablename__ = "file_closure_checklist"
id = Column(Integer, primary_key=True, autoincrement=True)
file_no = Column(String(45), ForeignKey("files.file_no"), nullable=False, index=True)
# Checklist item details
item_name = Column(String(200), nullable=False)
item_description = Column(Text)
is_required = Column(Boolean, default=True) # Must be completed to close file
# Completion tracking
is_completed = Column(Boolean, default=False)
completed_date = Column(DateTime(timezone=True))
completed_by_user_id = Column(Integer, ForeignKey("users.id"))
completed_by_name = Column(String(100))
# Additional info
notes = Column(Text) # Notes about completion
sort_order = Column(Integer, default=0) # Display order
# Relationships
file = relationship("File")
completed_by = relationship("User")
def __repr__(self):
status = "" if self.is_completed else ""
return f"<FileClosureChecklist({status} {self.item_name} - {self.file_no})>"
class FileAlert(BaseModel):
"""
Alerts and reminders for files
Automated notifications for important dates and events
"""
__tablename__ = "file_alerts"
id = Column(Integer, primary_key=True, autoincrement=True)
file_no = Column(String(45), ForeignKey("files.file_no"), nullable=False, index=True)
# Alert details
alert_type = Column(String(50), nullable=False) # deadline, follow_up, billing, etc.
title = Column(String(200), nullable=False)
message = Column(Text, nullable=False)
# Timing
alert_date = Column(Date, nullable=False) # When alert should trigger
created_date = Column(Date, default=func.current_date())
# Status
is_active = Column(Boolean, default=True)
is_acknowledged = Column(Boolean, default=False)
acknowledged_by_user_id = Column(Integer, ForeignKey("users.id"))
acknowledged_at = Column(DateTime(timezone=True))
# Notification settings
notify_attorney = Column(Boolean, default=True)
notify_admin = Column(Boolean, default=False)
notification_days_advance = Column(Integer, default=7) # Days before alert_date
# Relationships
file = relationship("File")
acknowledged_by = relationship("User")
def __repr__(self):
status = "🔔" if self.is_active and not self.is_acknowledged else ""
return f"<FileAlert({status} {self.alert_type} - {self.file_no} on {self.alert_date})>"