120 lines
4.0 KiB
Python
120 lines
4.0 KiB
Python
from sqlalchemy import Column, Integer, String, Float, Boolean, DateTime, Text, ARRAY, ForeignKey
|
|
from sqlalchemy.dialects.postgresql import UUID, JSONB
|
|
from sqlalchemy.sql import func
|
|
import uuid
|
|
|
|
try:
|
|
from backend.database import Base
|
|
except ImportError: # pragma: no cover - compatibility for direct module runs
|
|
from database import Base
|
|
|
|
|
|
class User(Base):
|
|
"""User model for authentication."""
|
|
__tablename__ = "users"
|
|
|
|
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
username = Column(String(100), unique=True, nullable=False)
|
|
email = Column(String(255), unique=True, nullable=False)
|
|
hashed_password = Column(String(255), nullable=False)
|
|
full_name = Column(String(255))
|
|
role = Column(String(20), nullable=False, default="operator")
|
|
is_active = Column(Boolean, default=True)
|
|
created_at = Column(DateTime, server_default=func.now())
|
|
last_login = Column(DateTime)
|
|
|
|
|
|
class Case(Base):
|
|
"""Unified case model - combines search case and result."""
|
|
__tablename__ = "cases"
|
|
|
|
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
created_at = Column(DateTime, server_default=func.now())
|
|
status = Column(String(20), default="active")
|
|
|
|
child_name = Column(String(255))
|
|
age_years = Column(Integer, nullable=False)
|
|
gender = Column(String(1))
|
|
height_build = Column(Text)
|
|
clothes_upper = Column(Text)
|
|
clothes_lower = Column(Text)
|
|
shoes = Column(Text)
|
|
clothes_description = Column(Text)
|
|
special_marks = Column(Text)
|
|
phone_status = Column(String(20))
|
|
|
|
has_diagnosis = Column(Boolean, default=False)
|
|
diagnosis_type = Column(ARRAY(String))
|
|
fitness_level = Column(String(20))
|
|
has_transport = Column(String(20), default="none")
|
|
cant_swim = Column(Boolean, default=False)
|
|
|
|
psychotype = Column(String(50))
|
|
psychotype_answers = Column(JSONB)
|
|
|
|
loss_reason = Column(String(100))
|
|
loss_time = Column(DateTime)
|
|
elapsed_hours = Column(Float)
|
|
last_seen_direction = Column(String(10))
|
|
last_seen_reliability = Column(String(20))
|
|
last_seen_description = Column(Text)
|
|
behavior_description = Column(Text)
|
|
familiar_places = Column(Text)
|
|
lost_before = Column(String(20))
|
|
|
|
season = Column(String(20))
|
|
temperature_c = Column(Float)
|
|
precipitation = Column(String(20))
|
|
visibility = Column(String(20))
|
|
wind = Column(String(20))
|
|
terrain = Column(ARRAY(String))
|
|
|
|
tnp_lat = Column(Float)
|
|
tnp_lon = Column(Float)
|
|
tnp_address = Column(Text)
|
|
|
|
teams_count = Column(Integer)
|
|
team_size = Column(Integer)
|
|
has_dog = Column(Boolean, default=False)
|
|
extra_resources = Column(ARRAY(String))
|
|
|
|
found_alive = Column(Boolean)
|
|
found_distance_km = Column(Float)
|
|
found_direction = Column(String(10))
|
|
found_location_type = Column(String(50))
|
|
found_lat = Column(Float)
|
|
found_lon = Column(Float)
|
|
search_duration_hours = Column(Float)
|
|
who_found = Column(String(50))
|
|
|
|
confidence_avg = Column(Float)
|
|
raw_text = Column(Text)
|
|
analysis_log = Column(JSONB)
|
|
|
|
|
|
class AnalysisLog(Base):
|
|
"""Analysis log for audit and debugging."""
|
|
__tablename__ = "analysis_log"
|
|
|
|
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
case_id = Column(UUID(as_uuid=True), ForeignKey("cases.id", ondelete="CASCADE"), nullable=False)
|
|
user_id = Column(UUID(as_uuid=True), ForeignKey("users.id", ondelete="SET NULL"))
|
|
analysis_type = Column(String(50), nullable=False)
|
|
input_data = Column(JSONB)
|
|
output_data = Column(JSONB)
|
|
execution_time = Column(Float)
|
|
status = Column(String(20), default="success")
|
|
error_message = Column(Text)
|
|
created_at = Column(DateTime, server_default=func.now())
|
|
|
|
|
|
class RawDocument(Base):
|
|
"""Raw document storage for parsed reports."""
|
|
__tablename__ = "raw_documents"
|
|
|
|
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
filename = Column(String(255), nullable=False)
|
|
raw_text = Column(Text)
|
|
extracted_json = Column(JSONB)
|
|
created_at = Column(DateTime, server_default=func.now())
|