FA3-Datafetch/backend/app/models.py
2026-01-13 14:49:36 +08:00

148 lines
5.3 KiB
Python

"""
SQLAlchemy Models for FA3 Refactored Architecture
新架构的数据库 ORM 模型
"""
from sqlalchemy import Column, Integer, String, Text, TIMESTAMP, Boolean, JSON, ForeignKey, Float
from sqlalchemy.orm import declarative_base, relationship
from sqlalchemy.sql import func
# ... (existing code)
Base = declarative_base()
class Company(Base):
"""公司元数据表"""
__tablename__ = 'companies'
id = Column(Integer, primary_key=True)
market = Column(String(10), nullable=False)
symbol = Column(String(50), nullable=False)
company_name = Column(String(255), nullable=False)
created_at = Column(TIMESTAMP, server_default=func.now())
updated_at = Column(TIMESTAMP, server_default=func.now(), onupdate=func.now())
# 关系
data_updates = relationship("DataUpdate", back_populates="company", cascade="all, delete-orphan")
ai_analyses = relationship("AIAnalysis", back_populates="company", cascade="all, delete-orphan")
data_source_availability = relationship("DataSourceAvailability", back_populates="company", cascade="all, delete-orphan")
def __repr__(self):
return f"<Company(id={self.id}, market={self.market}, symbol={self.symbol}, name={self.company_name})>"
class DataUpdate(Base):
"""数据更新记录表"""
__tablename__ = 'data_updates'
id = Column(Integer, primary_key=True)
company_id = Column(Integer, ForeignKey('companies.id', ondelete='CASCADE'), nullable=False)
data_source = Column(String(50), nullable=False)
update_type = Column(String(50), nullable=False)
status = Column(String(20), nullable=False)
started_at = Column(TIMESTAMP, server_default=func.now())
completed_at = Column(TIMESTAMP, nullable=True)
error_message = Column(Text, nullable=True)
# 数据覆盖范围
data_start_date = Column(String(8), nullable=True)
data_end_date = Column(String(8), nullable=True)
# 元数据 (JSONB)
fetched_tables = Column(JSON, nullable=True)
row_counts = Column(JSON, nullable=True)
# 进度跟踪
progress_message = Column(String(255), nullable=True)
progress_percentage = Column(Integer, default=0)
# 关系
company = relationship("Company", back_populates="data_updates")
def __repr__(self):
return f"<DataUpdate(id={self.id}, company_id={self.company_id}, source={self.data_source}, status={self.status})>"
class AIAnalysis(Base):
"""AI 分析报告表"""
__tablename__ = 'ai_analyses'
id = Column(Integer, primary_key=True)
company_id = Column(Integer, ForeignKey('companies.id', ondelete='CASCADE'), nullable=False)
data_source = Column(String(50), nullable=False)
ai_model = Column(String(100), nullable=False)
status = Column(String(20), nullable=False)
# 分析内容 (Markdown 格式)
company_profile = Column(Text, nullable=True)
fundamental_analysis = Column(Text, nullable=True)
insider_analysis = Column(Text, nullable=True)
bullish_analysis = Column(Text, nullable=True)
bearish_analysis = Column(Text, nullable=True)
# Token 使用情况
total_tokens = Column(Integer, default=0)
tokens_by_section = Column(JSON, nullable=True)
created_at = Column(TIMESTAMP, server_default=func.now())
completed_at = Column(TIMESTAMP, nullable=True)
error_message = Column(Text, nullable=True)
# 关系
company = relationship("Company", back_populates="ai_analyses")
def __repr__(self):
return f"<AIAnalysis(id={self.id}, company_id={self.company_id}, source={self.data_source}, status={self.status})>"
class DataSourceAvailability(Base):
"""数据源可用性表"""
__tablename__ = 'data_source_availability'
company_id = Column(Integer, ForeignKey('companies.id', ondelete='CASCADE'), primary_key=True)
data_source = Column(String(50), primary_key=True)
has_data = Column(Boolean, default=False)
last_update = Column(TIMESTAMP, nullable=True)
row_count = Column(Integer, default=0)
# 关系
company = relationship("Company", back_populates="data_source_availability")
def __repr__(self):
return f"<DataSourceAvailability(company_id={self.company_id}, source={self.data_source}, has_data={self.has_data})>"
class Setting(Base):
"""系统配置表"""
__tablename__ = 'settings'
key = Column(String(100), primary_key=True)
value = Column(Text, nullable=False)
updated_at = Column(TIMESTAMP, server_default=func.now(), onupdate=func.now())
def __repr__(self):
return f"<Setting(key={self.key}, value={self.value[:50]})>"
class LLMUsageLog(Base):
"""LLM 调用日志表"""
__tablename__ = 'llm_usage_logs'
id = Column(Integer, primary_key=True)
timestamp = Column(TIMESTAMP, server_default=func.now())
model = Column(String(50), nullable=False)
prompt = Column(Text, nullable=False)
response = Column(Text, nullable=True)
response_time = Column(Float, nullable=True) # Seconds
used_google_search = Column(Boolean, default=False)
session_id = Column(String, nullable=True)
# Token Usage
prompt_tokens = Column(Integer, default=0)
completion_tokens = Column(Integer, default=0)
total_tokens = Column(Integer, default=0)
def __repr__(self):
return f"<LLMUsageLog(id={self.id}, model={self.model}, tokens={self.total_tokens})>"