opencode/backend/app/models.py

96 lines
4.0 KiB
Python
Raw Normal View History

# app/models.py
from sqlalchemy import Column, Integer, String, Float, DateTime, Text, ForeignKey, JSON, Boolean
from sqlalchemy.orm import relationship
from datetime import datetime
from app.database import Base
class Project(Base):
"""Проект — один загруженный PDF."""
__tablename__ = "projects"
id = Column(Integer, primary_key=True, index=True)
name = Column(String, index=True)
pdf_filename = Column(String, nullable=False)
status = Column(String, default="uploaded") # uploaded / processing / completed / error
created_at = Column(DateTime, default=datetime.utcnow)
completed_at = Column(DateTime, nullable=True)
error_message = Column(Text, nullable=True)
# Пути к файлам
output_folder = Column(String, nullable=True)
pages = relationship("Page", back_populates="project", cascade="all, delete-orphan")
issues = relationship("Issue", back_populates="project", cascade="all, delete-orphan")
class Page(Base):
"""Страница PDF."""
__tablename__ = "pages"
id = Column(Integer, primary_key=True, index=True)
project_id = Column(Integer, ForeignKey("projects.id"))
page_number = Column(Integer, nullable=False)
png_path = Column(String, nullable=True)
dzi_path = Column(String, nullable=True)
ocr_data = Column(JSON, nullable=True) # full_ocr_results для этой страницы
vlm_description = Column(Text, nullable=True)
width = Column(Integer, nullable=True)
height = Column(Integer, nullable=True)
project = relationship("Project", back_populates="pages")
issues = relationship("Issue", back_populates="page")
class Issue(Base):
"""Замечание QC — одна проблема на чертеже."""
__tablename__ = "issues"
id = Column(Integer, primary_key=True, index=True)
project_id = Column(Integer, ForeignKey("projects.id"))
page_id = Column(Integer, ForeignKey("pages.id"))
issue_type = Column(String, nullable=False) # DIMENSION_OVERLAP, LOW_CONFIDENCE, etc.
severity = Column(String, nullable=False) # error / warning / info
message = Column(Text, nullable=False)
# Координаты bbox на PNG (в пикселях)
bbox_x1 = Column(Float, nullable=True)
bbox_y1 = Column(Float, nullable=True)
bbox_x2 = Column(Float, nullable=True)
bbox_y2 = Column(Float, nullable=True)
# Дополнительные данные
dimension_text = Column(String, nullable=True) # Текст размера (если применимо)
confidence = Column(Float, nullable=True) # OCR confidence
extra_data = Column(JSON, nullable=True) # Всё остальное
source = Column(String, nullable=True) # "rules" или "vlm"
created_at = Column(DateTime, default=datetime.utcnow)
project = relationship("Project", back_populates="issues")
page = relationship("Page", back_populates="issues")
feedback = relationship("Feedback", back_populates="issue", uselist=False)
class Feedback(Base):
"""Feedback проектировщика — правда ли это замечание."""
__tablename__ = "feedback"
id = Column(Integer, primary_key=True, index=True)
issue_id = Column(Integer, ForeignKey("issues.id"), unique=True)
# True = реальная проблема, False = ложное срабатывание, None = не размечено
is_true_positive = Column(Boolean, nullable=True)
# Почему (опционально)
comment = Column(Text, nullable=True)
# Что сделал проектировщик
action_taken = Column(String, nullable=True) # fixed / ignored / not_sure
created_at = Column(DateTime, default=datetime.utcnow)
user_id = Column(String, nullable=True) # Для многопользовательского режима
issue = relationship("Issue", back_populates="feedback")