90 lines
3.2 KiB
Python
90 lines
3.2 KiB
Python
from sqlalchemy import Column, Integer, String, Float, Boolean, DateTime, Text, ARRAY
|
||
from sqlalchemy.dialects.postgresql import UUID, JSONB
|
||
from sqlalchemy.sql import func
|
||
import uuid
|
||
from database import Base
|
||
|
||
|
||
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') # active/closed/archived
|
||
|
||
# Ребёнок
|
||
child_name = Column(String(255))
|
||
age_years = Column(Integer, nullable=False)
|
||
gender = Column(String(1)) # М / Ж
|
||
clothes_description = Column(Text)
|
||
special_marks = Column(Text)
|
||
phone_status = Column(String(20)) # answers/silent/none
|
||
|
||
# Здоровье
|
||
has_diagnosis = Column(Boolean, default=False)
|
||
diagnosis_type = Column(ARRAY(String)) # РАС, эпилепсия, СДВГ, ЗПР...
|
||
fitness_level = Column(String(20)) # low/medium/high
|
||
has_transport = Column(String(20), default='none') # none/bike/scooter/other
|
||
cant_swim = Column(Boolean, default=False)
|
||
|
||
# Психотип
|
||
psychotype = Column(String(50)) # dominant/harmonic/anxious/...
|
||
psychotype_answers = Column(JSONB) # сырые ответы на 4 вопроса
|
||
|
||
# Обстоятельства
|
||
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)) # exact/approx/unknown
|
||
last_seen_description = Column(Text)
|
||
behavior_description = Column(Text)
|
||
familiar_places = Column(Text)
|
||
lost_before = Column(String(20)) # yes/no/unknown
|
||
|
||
# Среда
|
||
season = Column(String(20))
|
||
temperature_c = Column(Float)
|
||
precipitation = Column(String(20))
|
||
visibility = Column(String(20))
|
||
wind = Column(String(20))
|
||
terrain = Column(ARRAY(String))
|
||
|
||
# GPS
|
||
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)) # drone/helicopter/boat/thermal
|
||
|
||
# Исход (заполняется после завершения)
|
||
found_alive = Column(Boolean)
|
||
found_distance_km = Column(Float)
|
||
found_direction = Column(String(10))
|
||
found_location_type = Column(String(50)) # forest/road/building/water/field
|
||
found_lat = Column(Float)
|
||
found_lon = Column(Float)
|
||
search_duration_hours = Column(Float)
|
||
who_found = Column(String(50)) # mchs/mvd/volunteers/self
|
||
|
||
# Мета
|
||
confidence_avg = Column(Float)
|
||
raw_text = Column(Text)
|
||
analysis_log = Column(JSONB)
|
||
|
||
|
||
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())
|