Files
bakery-ia/services/ai_insights/app/models/ai_insight.py
2025-11-05 13:34:56 +01:00

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})>"