191 lines
7.0 KiB
Python
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})>" |