130 lines
3.7 KiB
Python
130 lines
3.7 KiB
Python
"""AI Insight database model."""
|
|
|
|
from sqlalchemy import Column, String, Integer, Boolean, DECIMAL, TIMESTAMP, Text, Index, CheckConstraint
|
|
from sqlalchemy.dialects.postgresql import UUID, JSONB
|
|
from sqlalchemy.sql import func
|
|
import uuid
|
|
|
|
from app.core.database import Base
|
|
|
|
|
|
class AIInsight(Base):
|
|
"""AI Insight model for storing intelligent recommendations and predictions."""
|
|
|
|
__tablename__ = "ai_insights"
|
|
|
|
# Primary Key
|
|
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
|
|
# Tenant Information
|
|
tenant_id = Column(UUID(as_uuid=True), nullable=False, index=True)
|
|
|
|
# Classification
|
|
type = Column(
|
|
String(50),
|
|
nullable=False,
|
|
index=True,
|
|
comment="optimization, alert, prediction, recommendation, insight, anomaly"
|
|
)
|
|
priority = Column(
|
|
String(20),
|
|
nullable=False,
|
|
index=True,
|
|
comment="low, medium, high, critical"
|
|
)
|
|
category = Column(
|
|
String(50),
|
|
nullable=False,
|
|
index=True,
|
|
comment="forecasting, inventory, production, procurement, customer, cost, quality, efficiency, demand, maintenance, energy, scheduling"
|
|
)
|
|
|
|
# Content
|
|
title = Column(String(255), nullable=False)
|
|
description = Column(Text, nullable=False)
|
|
|
|
# Impact Information
|
|
impact_type = Column(
|
|
String(50),
|
|
comment="cost_savings, revenue_increase, waste_reduction, efficiency_gain, quality_improvement, risk_mitigation"
|
|
)
|
|
impact_value = Column(DECIMAL(10, 2), comment="Numeric impact value")
|
|
impact_unit = Column(
|
|
String(20),
|
|
comment="euros, percentage, hours, units, euros/month, euros/year"
|
|
)
|
|
|
|
# Confidence and Metrics
|
|
confidence = Column(
|
|
Integer,
|
|
CheckConstraint('confidence >= 0 AND confidence <= 100'),
|
|
nullable=False,
|
|
index=True,
|
|
comment="Confidence score 0-100"
|
|
)
|
|
metrics_json = Column(
|
|
JSONB,
|
|
comment="Dynamic metrics specific to insight type"
|
|
)
|
|
|
|
# Actionability
|
|
actionable = Column(
|
|
Boolean,
|
|
default=True,
|
|
nullable=False,
|
|
index=True,
|
|
comment="Whether this insight can be acted upon"
|
|
)
|
|
recommendation_actions = Column(
|
|
JSONB,
|
|
comment="List of possible actions: [{label, action, endpoint}]"
|
|
)
|
|
|
|
# Status
|
|
status = Column(
|
|
String(20),
|
|
default='new',
|
|
nullable=False,
|
|
index=True,
|
|
comment="new, acknowledged, in_progress, applied, dismissed, expired"
|
|
)
|
|
|
|
# Source Information
|
|
source_service = Column(
|
|
String(50),
|
|
comment="Service that generated this insight"
|
|
)
|
|
source_data_id = Column(
|
|
String(100),
|
|
comment="Reference to source data (e.g., forecast_id, model_id)"
|
|
)
|
|
|
|
# Timestamps
|
|
created_at = Column(
|
|
TIMESTAMP(timezone=True),
|
|
server_default=func.now(),
|
|
nullable=False,
|
|
index=True
|
|
)
|
|
updated_at = Column(
|
|
TIMESTAMP(timezone=True),
|
|
server_default=func.now(),
|
|
onupdate=func.now(),
|
|
nullable=False
|
|
)
|
|
applied_at = Column(TIMESTAMP(timezone=True), comment="When insight was applied")
|
|
expired_at = Column(
|
|
TIMESTAMP(timezone=True),
|
|
comment="When insight expires (auto-calculated based on TTL)"
|
|
)
|
|
|
|
# Composite Indexes
|
|
__table_args__ = (
|
|
Index('idx_tenant_status_category', 'tenant_id', 'status', 'category'),
|
|
Index('idx_tenant_created_confidence', 'tenant_id', 'created_at', 'confidence'),
|
|
Index('idx_actionable_status', 'actionable', 'status'),
|
|
)
|
|
|
|
def __repr__(self):
|
|
return f"<AIInsight(id={self.id}, type={self.type}, title={self.title[:30]}, confidence={self.confidence})>"
|