diff --git a/app/__pycache__/main.cpython-312.pyc b/app/__pycache__/main.cpython-312.pyc index a03bc92..ef94b29 100644 Binary files a/app/__pycache__/main.cpython-312.pyc and b/app/__pycache__/main.cpython-312.pyc differ diff --git a/app/db/__pycache__/db.cpython-312.pyc b/app/db/__pycache__/db.cpython-312.pyc index c852d80..f367c0d 100644 Binary files a/app/db/__pycache__/db.cpython-312.pyc and b/app/db/__pycache__/db.cpython-312.pyc differ diff --git a/app/db/__pycache__/models.cpython-312.pyc b/app/db/__pycache__/models.cpython-312.pyc index bccb5bd..5bcb5ac 100644 Binary files a/app/db/__pycache__/models.cpython-312.pyc and b/app/db/__pycache__/models.cpython-312.pyc differ diff --git a/app/db/models.py b/app/db/models.py index a3e0774..983533b 100644 --- a/app/db/models.py +++ b/app/db/models.py @@ -311,3 +311,24 @@ class ProjectTable(Base, TimestampMixin): companies = relationship( "CompanyTable", secondary=project_company_association, back_populates="projects" ) + + +class InvestorInsightCache(Base, TimestampMixin): + __tablename__ = "investor_insight_cache" + + id = Column(Integer, primary_key=True, index=True) + investor_id = Column( + Integer, ForeignKey("investors.id"), nullable=False, unique=True + ) + + # Cached insights + investment_pattern_analysis = Column(Text, nullable=False) + market_position = Column(Text, nullable=False) + + # Cache management + last_refreshed = Column( + DateTime(timezone=True), server_default=func.now(), nullable=False + ) + + # Relationship to investor + investor = relationship("InvestorTable") diff --git a/app/routers/insight_route.py b/app/routers/insight_route.py index 632bde2..4967c32 100644 --- a/app/routers/insight_route.py +++ b/app/routers/insight_route.py @@ -1,7 +1,8 @@ +from datetime import datetime, timedelta from typing import Optional from db.db import get_db -from db.models import InvestorTable, ProjectTable +from db.models import InvestorInsightCache, InvestorTable, ProjectTable from fastapi import APIRouter, Depends, HTTPException from schemas.insight_schema import InsightResponse from services.compatibility_score import ( @@ -39,19 +40,60 @@ async def get_insights( status_code=404, detail=f"Investor with id {investor_id} not found" ) - # Initialize the query processor for insights - query_processor = QueryProcessor() - - # Get investment pattern analysis and market position using web search - insights = await query_processor.get_investor_insights( - investor_name=investor.name, - investor_website=investor.website, - investor_description=investor.description, - investor_headquarters=investor.headquarters, - investment_thesis=investor.investment_thesis, - portfolio_highlights=investor.portfolio_highlights, + # Check if we have cached insights + cached_insights = ( + db.query(InvestorInsightCache) + .filter(InvestorInsightCache.investor_id == investor_id) + .first() ) + # Determine if cache needs refresh (older than 1 month) + needs_refresh = True + if cached_insights: + # Calculate if cache is older than 1 month + cache_age = ( + datetime.now(cached_insights.last_refreshed.tzinfo) + - cached_insights.last_refreshed + ) + needs_refresh = cache_age > timedelta(days=30) + + # Fetch new insights if needed + if needs_refresh: + # Initialize the query processor for insights + query_processor = QueryProcessor() + + # Get investment pattern analysis and market position using web search + insights = await query_processor.get_investor_insights( + investor_name=investor.name, + investor_website=investor.website, + investor_description=investor.description, + investor_headquarters=investor.headquarters, + investment_thesis=investor.investment_thesis, + portfolio_highlights=investor.portfolio_highlights, + ) + + # Update or create cache entry + if cached_insights: + # Update existing cache + cached_insights.investment_pattern_analysis = insights[ + "investment_pattern_analysis" + ] + cached_insights.market_position = insights["market_position"] + cached_insights.last_refreshed = datetime.now( + cached_insights.last_refreshed.tzinfo + ) + else: + # Create new cache entry + cached_insights = InvestorInsightCache( + investor_id=investor_id, + investment_pattern_analysis=insights["investment_pattern_analysis"], + market_position=insights["market_position"], + ) + db.add(cached_insights) + + db.commit() + db.refresh(cached_insights) + # Calculate compatibility score if project_id is provided compatibility_score = None if project_id: @@ -74,7 +116,7 @@ async def get_insights( compatibility_score = "Select a project to see compatibility analysis" return InsightResponse( - investment_pattern_analysis=insights["investment_pattern_analysis"], - market_position=insights["market_position"], + investment_pattern_analysis=cached_insights.investment_pattern_analysis, + market_position=cached_insights.market_position, compatibility_score=compatibility_score, ) diff --git a/app/services/__pycache__/querying.cpython-312.pyc b/app/services/__pycache__/querying.cpython-312.pyc index d5a560a..39750b2 100644 Binary files a/app/services/__pycache__/querying.cpython-312.pyc and b/app/services/__pycache__/querying.cpython-312.pyc differ diff --git a/app/services/report_gen.py b/app/services/report_gen.py index a3945bb..1e0c2a5 100644 --- a/app/services/report_gen.py +++ b/app/services/report_gen.py @@ -34,7 +34,6 @@ class ReportGenerator: # Render HTML from template template = self.env.get_template("report.html") html_content = template.render(**context) - # Convert HTML to PDF using Playwright pdf_bytes = await self._html_to_pdf(html_content) @@ -104,7 +103,11 @@ class ReportGenerator: project_valuation = project_data.get("valuation", 0) check_lower = investor_data.get("check_size_lower") or 0 check_upper = investor_data.get("check_size_upper") or float("inf") - if check_lower and check_upper and check_lower <= project_valuation <= check_upper: + if ( + check_lower + and check_upper + and check_lower <= project_valuation <= check_upper + ): score += weights["check_size"] # Thesis alignment (simplified) @@ -153,10 +156,12 @@ class ReportGenerator: # Geography criterion investor_geo = investor_data.get("geographic_focus") or "N/A" project_geo = project_data.get("location") or "N/A" - + # Safe comparison handling None values if investor_geo == "N/A" or project_geo == "N/A": - geo_match = "N/A" if investor_geo == "N/A" and project_geo == "N/A" else "Mismatch" + geo_match = ( + "N/A" if investor_geo == "N/A" and project_geo == "N/A" else "Mismatch" + ) else: investor_geo_lower = investor_geo.lower() project_geo_lower = project_geo.lower() diff --git a/app/templates/report.html b/app/templates/report.html index f394aa8..44d02ff 100644 --- a/app/templates/report.html +++ b/app/templates/report.html @@ -7,23 +7,43 @@ -
- -Investor Profile
-