"""Repository for Insight Feedback database operations.""" from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select, and_, desc from typing import Optional, List from uuid import UUID from decimal import Decimal from app.models.insight_feedback import InsightFeedback from app.schemas.feedback import InsightFeedbackCreate class FeedbackRepository: """Repository for Insight Feedback operations.""" def __init__(self, session: AsyncSession): self.session = session async def create(self, feedback_data: InsightFeedbackCreate) -> InsightFeedback: """Create feedback for an insight.""" # Calculate variance if both values provided variance = None if (feedback_data.expected_impact_value is not None and feedback_data.actual_impact_value is not None and feedback_data.expected_impact_value != 0): variance = ( (feedback_data.actual_impact_value - feedback_data.expected_impact_value) / feedback_data.expected_impact_value * 100 ) feedback = InsightFeedback( **feedback_data.model_dump(exclude={'variance_percentage'}), variance_percentage=variance ) self.session.add(feedback) await self.session.flush() await self.session.refresh(feedback) return feedback async def get_by_id(self, feedback_id: UUID) -> Optional[InsightFeedback]: """Get feedback by ID.""" query = select(InsightFeedback).where(InsightFeedback.id == feedback_id) result = await self.session.execute(query) return result.scalar_one_or_none() async def get_by_insight(self, insight_id: UUID) -> List[InsightFeedback]: """Get all feedback for an insight.""" query = select(InsightFeedback).where( InsightFeedback.insight_id == insight_id ).order_by(desc(InsightFeedback.created_at)) result = await self.session.execute(query) return list(result.scalars().all()) async def get_success_rate(self, insight_type: Optional[str] = None) -> float: """Calculate success rate for insights.""" query = select(InsightFeedback) result = await self.session.execute(query) feedbacks = result.scalars().all() if not feedbacks: return 0.0 successful = sum(1 for f in feedbacks if f.success) return (successful / len(feedbacks)) * 100 async def get_average_impact_variance(self) -> Decimal: """Calculate average variance between expected and actual impact.""" query = select(InsightFeedback).where( InsightFeedback.variance_percentage.isnot(None) ) result = await self.session.execute(query) feedbacks = result.scalars().all() if not feedbacks: return Decimal('0.0') avg_variance = sum(f.variance_percentage for f in feedbacks) / len(feedbacks) return Decimal(str(round(float(avg_variance), 2)))