148 lines
5.3 KiB
Python
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})>"
|